@merittdev/horus-lens 0.0.1 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +129 -0
- package/dist/browser.cjs +1 -1
- package/dist/browser.cjs.map +1 -1
- package/dist/browser.js +2 -2
- package/dist/{chunk-DU7HNRF4.js → chunk-CTBY5XIN.js} +2 -2
- package/dist/{chunk-S6S3ZZQA.js → chunk-XRONR4GR.js} +2 -2
- package/dist/{chunk-S6S3ZZQA.js.map → chunk-XRONR4GR.js.map} +1 -1
- package/dist/dashboard.cjs +784 -434
- package/dist/dashboard.cjs.map +1 -1
- package/dist/dashboard.css +224 -1
- package/dist/dashboard.d.cts +85 -1
- package/dist/dashboard.d.ts +85 -1
- package/dist/dashboard.js +648 -301
- package/dist/dashboard.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/dist/lens.min.js +1 -1
- package/dist/lens.min.js.map +1 -1
- package/dist/react.cjs +6 -3
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +18 -6
- package/dist/react.d.ts +18 -6
- package/dist/react.js +6 -4
- package/dist/react.js.map +1 -1
- package/dist/server.cjs +109 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.cts +59 -0
- package/dist/server.d.ts +59 -0
- package/dist/server.js +82 -0
- package/dist/server.js.map +1 -0
- package/package.json +30 -4
- /package/dist/{chunk-DU7HNRF4.js.map → chunk-CTBY5XIN.js.map} +0 -0
package/dist/dashboard.js
CHANGED
|
@@ -3,7 +3,7 @@ import "./chunk-PZ5AY32C.js";
|
|
|
3
3
|
// ../dashboard/dist/index.js
|
|
4
4
|
import { createContext, useContext } from "react";
|
|
5
5
|
import { jsx } from "react/jsx-runtime";
|
|
6
|
-
import {
|
|
6
|
+
import { createContext as createContext2, useContext as useContext2, useEffect as useEffect7, useMemo, useRef as useRef4, useState as useState8 } from "react";
|
|
7
7
|
|
|
8
8
|
// ../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/dist/clsx.mjs
|
|
9
9
|
function r(e) {
|
|
@@ -22,23 +22,25 @@ function clsx() {
|
|
|
22
22
|
var clsx_default = clsx;
|
|
23
23
|
|
|
24
24
|
// ../dashboard/dist/index.js
|
|
25
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
26
|
-
import { jsx as jsx3
|
|
27
|
-
import {
|
|
25
|
+
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
26
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
27
|
+
import { useCallback, useEffect, useState } from "react";
|
|
28
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
29
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
28
30
|
import { useId, useRef as useRef3, useState as useState4 } from "react";
|
|
29
31
|
import { useCallback as useCallback2, useEffect as useEffect2, useRef, useState as useState2 } from "react";
|
|
30
32
|
import { useCallback as useCallback3, useEffect as useEffect3, useRef as useRef2, useState as useState3 } from "react";
|
|
31
|
-
import { jsx as
|
|
32
|
-
import { Fragment as Fragment2, jsx as
|
|
33
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
34
|
+
import { Fragment as Fragment2, jsx as jsx7, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
33
35
|
import { useEffect as useEffect5, useState as useState6 } from "react";
|
|
34
36
|
import { useEffect as useEffect4, useState as useState5 } from "react";
|
|
35
|
-
import { Fragment as Fragment3, jsx as
|
|
36
|
-
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
37
|
-
import { useEffect as useEffect6, useState as useState7 } from "react";
|
|
37
|
+
import { Fragment as Fragment3, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
38
38
|
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
39
|
+
import { useEffect as useEffect6, useState as useState7 } from "react";
|
|
39
40
|
import { Fragment as Fragment4, jsx as jsx10, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
40
|
-
import { useEffect as useEffect7, useState as useState8 } from "react";
|
|
41
41
|
import { Fragment as Fragment5, jsx as jsx11, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
42
|
+
import { useEffect as useEffect8, useState as useState9 } from "react";
|
|
43
|
+
import { Fragment as Fragment6, jsx as jsx12, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
42
44
|
var LensApiError = class extends Error {
|
|
43
45
|
constructor(status, code, message) {
|
|
44
46
|
super(message);
|
|
@@ -153,6 +155,11 @@ function createLensApi(config) {
|
|
|
153
155
|
if (res && Array.isArray(res.integrations)) return res.integrations;
|
|
154
156
|
return this.listIntegrations();
|
|
155
157
|
},
|
|
158
|
+
async getIntegrationOptions(provider) {
|
|
159
|
+
return request(
|
|
160
|
+
`/v1/integrations/${encodeURIComponent(provider)}/options`
|
|
161
|
+
);
|
|
162
|
+
},
|
|
156
163
|
async createProject(body) {
|
|
157
164
|
return request("/v1/projects", {
|
|
158
165
|
method: "POST",
|
|
@@ -200,61 +207,6 @@ function useLensApi() {
|
|
|
200
207
|
}
|
|
201
208
|
return api;
|
|
202
209
|
}
|
|
203
|
-
function relativeTime(iso, now = Date.now()) {
|
|
204
|
-
if (!iso) return "\u2014";
|
|
205
|
-
const then = new Date(iso).getTime();
|
|
206
|
-
if (Number.isNaN(then)) return "\u2014";
|
|
207
|
-
const diff = now - then;
|
|
208
|
-
const sec = Math.round(diff / 1e3);
|
|
209
|
-
if (sec < 5) return "just now";
|
|
210
|
-
if (sec < 60) return `${sec}s ago`;
|
|
211
|
-
const min = Math.round(sec / 60);
|
|
212
|
-
if (min < 60) return `${min}m ago`;
|
|
213
|
-
const hr = Math.round(min / 60);
|
|
214
|
-
if (hr < 24) return `${hr}h ago`;
|
|
215
|
-
const day = Math.round(hr / 24);
|
|
216
|
-
if (day < 7) return `${day}d ago`;
|
|
217
|
-
const wk = Math.round(day / 7);
|
|
218
|
-
if (wk < 5) return `${wk}w ago`;
|
|
219
|
-
const mo = Math.round(day / 30);
|
|
220
|
-
if (mo < 12) return `${mo}mo ago`;
|
|
221
|
-
const yr = Math.round(day / 365);
|
|
222
|
-
return `${yr}y ago`;
|
|
223
|
-
}
|
|
224
|
-
function formatTimestamp(iso) {
|
|
225
|
-
if (!iso) return "\u2014";
|
|
226
|
-
const d = new Date(iso);
|
|
227
|
-
if (Number.isNaN(d.getTime())) return "\u2014";
|
|
228
|
-
return d.toLocaleString();
|
|
229
|
-
}
|
|
230
|
-
function truncate(value, max = 80) {
|
|
231
|
-
if (value.length <= max) return value;
|
|
232
|
-
return `${value.slice(0, max - 1).trimEnd()}\u2026`;
|
|
233
|
-
}
|
|
234
|
-
function urlPath(raw) {
|
|
235
|
-
if (!raw) return "\u2014";
|
|
236
|
-
try {
|
|
237
|
-
const u = new URL(raw);
|
|
238
|
-
return `${u.pathname}${u.search}` || "/";
|
|
239
|
-
} catch {
|
|
240
|
-
return raw;
|
|
241
|
-
}
|
|
242
|
-
}
|
|
243
|
-
function formatDuration(ms) {
|
|
244
|
-
if (ms == null) return "\u2014";
|
|
245
|
-
if (ms < 1e3) return `${Math.round(ms)}ms`;
|
|
246
|
-
return `${(ms / 1e3).toFixed(2)}s`;
|
|
247
|
-
}
|
|
248
|
-
var LABELS = {
|
|
249
|
-
initiated: "Initiated",
|
|
250
|
-
submitted: "Submitted",
|
|
251
|
-
triaged: "Triaged",
|
|
252
|
-
linked: "Linked",
|
|
253
|
-
resolved: "Resolved"
|
|
254
|
-
};
|
|
255
|
-
function StatusBadge({ status }) {
|
|
256
|
-
return /* @__PURE__ */ jsx2("span", { className: clsx_default("lens-db__badge", `lens-db__badge--${status}`), children: LABELS[status] });
|
|
257
|
-
}
|
|
258
210
|
function base({ size = 16, ...rest }) {
|
|
259
211
|
return {
|
|
260
212
|
width: size,
|
|
@@ -271,55 +223,77 @@ function base({ size = 16, ...rest }) {
|
|
|
271
223
|
};
|
|
272
224
|
}
|
|
273
225
|
function IconPlay(props) {
|
|
274
|
-
return /* @__PURE__ */
|
|
226
|
+
return /* @__PURE__ */ jsx2("svg", { ...base(props), children: /* @__PURE__ */ jsx2("path", { d: "M8 5.5v13l11-6.5-11-6.5Z", fill: "currentColor", stroke: "none" }) });
|
|
275
227
|
}
|
|
276
228
|
function IconPause(props) {
|
|
277
229
|
return /* @__PURE__ */ jsxs("svg", { ...base(props), children: [
|
|
278
|
-
/* @__PURE__ */
|
|
279
|
-
/* @__PURE__ */
|
|
230
|
+
/* @__PURE__ */ jsx2("rect", { x: "7", y: "5", width: "3.5", height: "14", rx: "1", fill: "currentColor", stroke: "none" }),
|
|
231
|
+
/* @__PURE__ */ jsx2("rect", { x: "13.5", y: "5", width: "3.5", height: "14", rx: "1", fill: "currentColor", stroke: "none" })
|
|
280
232
|
] });
|
|
281
233
|
}
|
|
282
234
|
function IconClose(props) {
|
|
283
|
-
return /* @__PURE__ */
|
|
235
|
+
return /* @__PURE__ */ jsx2("svg", { ...base(props), children: /* @__PURE__ */ jsx2("path", { d: "M18 6 6 18M6 6l12 12" }) });
|
|
284
236
|
}
|
|
285
237
|
function IconChevronLeft(props) {
|
|
286
|
-
return /* @__PURE__ */
|
|
238
|
+
return /* @__PURE__ */ jsx2("svg", { ...base(props), children: /* @__PURE__ */ jsx2("path", { d: "M15 6l-6 6 6 6" }) });
|
|
287
239
|
}
|
|
288
240
|
function IconChevronRight(props) {
|
|
289
|
-
return /* @__PURE__ */
|
|
241
|
+
return /* @__PURE__ */ jsx2("svg", { ...base(props), children: /* @__PURE__ */ jsx2("path", { d: "M9 6l6 6-6 6" }) });
|
|
290
242
|
}
|
|
291
243
|
function IconExternal(props) {
|
|
292
244
|
return /* @__PURE__ */ jsxs("svg", { ...base(props), children: [
|
|
293
|
-
/* @__PURE__ */
|
|
294
|
-
/* @__PURE__ */
|
|
245
|
+
/* @__PURE__ */ jsx2("path", { d: "M14 5h5v5M19 5l-8 8" }),
|
|
246
|
+
/* @__PURE__ */ jsx2("path", { d: "M18 13.5V18a1.5 1.5 0 0 1-1.5 1.5H6A1.5 1.5 0 0 1 4.5 18V7.5A1.5 1.5 0 0 1 6 6h4.5" })
|
|
295
247
|
] });
|
|
296
248
|
}
|
|
297
249
|
function IconCopy(props) {
|
|
298
250
|
return /* @__PURE__ */ jsxs("svg", { ...base(props), children: [
|
|
299
|
-
/* @__PURE__ */
|
|
300
|
-
/* @__PURE__ */
|
|
251
|
+
/* @__PURE__ */ jsx2("rect", { x: "9", y: "9", width: "11", height: "11", rx: "2" }),
|
|
252
|
+
/* @__PURE__ */ jsx2("path", { d: "M5 15V6a1 1 0 0 1 1-1h9" })
|
|
301
253
|
] });
|
|
302
254
|
}
|
|
303
255
|
function IconCheck(props) {
|
|
304
|
-
return /* @__PURE__ */
|
|
256
|
+
return /* @__PURE__ */ jsx2("svg", { ...base(props), children: /* @__PURE__ */ jsx2("path", { d: "M20 6 9 17l-5-5" }) });
|
|
305
257
|
}
|
|
306
258
|
function IconCheckCircle(props) {
|
|
307
259
|
return /* @__PURE__ */ jsxs("svg", { ...base(props), children: [
|
|
308
|
-
/* @__PURE__ */
|
|
309
|
-
/* @__PURE__ */
|
|
260
|
+
/* @__PURE__ */ jsx2("circle", { cx: "12", cy: "12", r: "9" }),
|
|
261
|
+
/* @__PURE__ */ jsx2("path", { d: "m8.5 12 2.5 2.5 4.5-5" })
|
|
310
262
|
] });
|
|
311
263
|
}
|
|
312
264
|
function IconAlertTriangle(props) {
|
|
313
265
|
return /* @__PURE__ */ jsxs("svg", { ...base(props), children: [
|
|
314
|
-
/* @__PURE__ */
|
|
315
|
-
/* @__PURE__ */
|
|
316
|
-
/* @__PURE__ */
|
|
266
|
+
/* @__PURE__ */ jsx2("path", { d: "M12 4.5 21 19.5H3L12 4.5Z" }),
|
|
267
|
+
/* @__PURE__ */ jsx2("path", { d: "M12 10v4.5" }),
|
|
268
|
+
/* @__PURE__ */ jsx2("path", { d: "M12 17.25h.01" })
|
|
317
269
|
] });
|
|
318
270
|
}
|
|
319
271
|
function IconInbox(props) {
|
|
320
272
|
return /* @__PURE__ */ jsxs("svg", { ...base(props), children: [
|
|
321
|
-
/* @__PURE__ */
|
|
322
|
-
/* @__PURE__ */
|
|
273
|
+
/* @__PURE__ */ jsx2("path", { d: "M4 13h4l1.5 2.5h5L16 13h4" }),
|
|
274
|
+
/* @__PURE__ */ jsx2("path", { d: "M6.5 5h11l3 8v4.5A1.5 1.5 0 0 1 19 19H5a1.5 1.5 0 0 1-1.5-1.5V13l3-8Z" })
|
|
275
|
+
] });
|
|
276
|
+
}
|
|
277
|
+
function IconBug(props) {
|
|
278
|
+
return /* @__PURE__ */ jsxs("svg", { ...base(props), children: [
|
|
279
|
+
/* @__PURE__ */ jsx2("rect", { x: "8", y: "7", width: "8", height: "12", rx: "4" }),
|
|
280
|
+
/* @__PURE__ */ jsx2("path", { d: "M9 5a3 3 0 0 1 6 0" }),
|
|
281
|
+
/* @__PURE__ */ jsx2("path", { d: "M12 8.5v10" }),
|
|
282
|
+
/* @__PURE__ */ jsx2("path", { d: "M8 11H4.5M8 15H4M8 8 5.5 6M16 11h3.5M16 15h4M16 8l2.5-2" })
|
|
283
|
+
] });
|
|
284
|
+
}
|
|
285
|
+
function IconPlug(props) {
|
|
286
|
+
return /* @__PURE__ */ jsxs("svg", { ...base(props), children: [
|
|
287
|
+
/* @__PURE__ */ jsx2("path", { d: "M9 3v5M15 3v5" }),
|
|
288
|
+
/* @__PURE__ */ jsx2("path", { d: "M6.5 8h11v1.5a5.5 5.5 0 0 1-11 0V8Z" }),
|
|
289
|
+
/* @__PURE__ */ jsx2("path", { d: "M12 15v6" })
|
|
290
|
+
] });
|
|
291
|
+
}
|
|
292
|
+
function IconRocket(props) {
|
|
293
|
+
return /* @__PURE__ */ jsxs("svg", { ...base(props), children: [
|
|
294
|
+
/* @__PURE__ */ jsx2("path", { d: "M12 3c2.6 1.7 4 4.6 4 7.5l-1.8 2.5H9.8L8 10.5C8 7.6 9.4 4.7 12 3Z" }),
|
|
295
|
+
/* @__PURE__ */ jsx2("circle", { cx: "12", cy: "9", r: "1.4" }),
|
|
296
|
+
/* @__PURE__ */ jsx2("path", { d: "M9.8 13l-2 2.2.2 3 2.4-1.4M14.2 13l2 2.2-.2 3-2.4-1.4" })
|
|
323
297
|
] });
|
|
324
298
|
}
|
|
325
299
|
function brand({ size = 16, ...rest }) {
|
|
@@ -334,13 +308,114 @@ function brand({ size = 16, ...rest }) {
|
|
|
334
308
|
};
|
|
335
309
|
}
|
|
336
310
|
function IconGitHub(props) {
|
|
337
|
-
return /* @__PURE__ */
|
|
311
|
+
return /* @__PURE__ */ jsx2("svg", { ...brand(props), children: /* @__PURE__ */ jsx2("path", { d: "M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12" }) });
|
|
338
312
|
}
|
|
339
313
|
function IconLinear(props) {
|
|
340
|
-
return /* @__PURE__ */
|
|
314
|
+
return /* @__PURE__ */ jsx2("svg", { ...brand(props), children: /* @__PURE__ */ jsx2("path", { d: "M2.886 4.18A11.982 11.982 0 0 1 11.99 0C18.624 0 24 5.376 24 12.009c0 3.64-1.62 6.903-4.18 9.105L2.887 4.18ZM1.817 5.626l16.556 16.556c-.524.33-1.075.62-1.65.866L.951 7.277c.247-.575.537-1.126.866-1.65ZM.322 9.163l14.515 14.515c-.71.172-1.443.282-2.195.322L0 11.358a12 12 0 0 1 .322-2.195Zm-.17 4.862 9.823 9.824a12.02 12.02 0 0 1-9.824-9.824Z" }) });
|
|
341
315
|
}
|
|
342
316
|
function IconJira(props) {
|
|
343
|
-
return /* @__PURE__ */
|
|
317
|
+
return /* @__PURE__ */ jsx2("svg", { ...brand(props), children: /* @__PURE__ */ jsx2("path", { d: "M11.571 11.513H0a5.218 5.218 0 0 0 5.232 5.215h2.13v2.057A5.215 5.215 0 0 0 12.575 24V12.518a1.005 1.005 0 0 0-1.005-1.005zm5.723-5.756H5.736a5.215 5.215 0 0 0 5.215 5.214h2.129v2.058a5.218 5.218 0 0 0 5.215 5.214V6.758a1.001 1.001 0 0 0-1.001-1.001zM23.013 0H11.455a5.215 5.215 0 0 0 5.215 5.215h2.129v2.057A5.215 5.215 0 0 0 24 12.483V1.005A1.001 1.001 0 0 0 23.013 0Z" }) });
|
|
318
|
+
}
|
|
319
|
+
var MARKUP_RULES = [
|
|
320
|
+
{ cls: "com", re: /<!--[\s\S]*?-->|\/\*[\s\S]*?\*\/|\/\/[^\n]*/y },
|
|
321
|
+
{ cls: "str", re: /"(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'|`(?:[^`\\]|\\.)*`/y },
|
|
322
|
+
{ cls: "tag", re: /<\/?[a-zA-Z][\w.-]*|\/>|>/y },
|
|
323
|
+
{
|
|
324
|
+
cls: "kw",
|
|
325
|
+
re: /\b(?:import|from|export|function|return|const|let|var|async|await|new|window|default)\b/y
|
|
326
|
+
},
|
|
327
|
+
{ cls: "attr", re: /\b[a-zA-Z_][\w-]*(?==)/y },
|
|
328
|
+
{ cls: "num", re: /\b\d+(?:\.\d+)?\b/y }
|
|
329
|
+
];
|
|
330
|
+
var ENV_RULES = [
|
|
331
|
+
{ cls: "com", re: /#[^\n]*/y },
|
|
332
|
+
{ cls: "attr", re: /^[A-Z][A-Z0-9_]*(?==)/my },
|
|
333
|
+
{ cls: "str", re: /(?<==)[^\n]+/y }
|
|
334
|
+
];
|
|
335
|
+
function highlightCode(code, lang) {
|
|
336
|
+
const rules = lang === "env" ? ENV_RULES : MARKUP_RULES;
|
|
337
|
+
const out = [];
|
|
338
|
+
let pos = 0;
|
|
339
|
+
let plainStart = 0;
|
|
340
|
+
let key = 0;
|
|
341
|
+
const flushPlain = (until) => {
|
|
342
|
+
if (until > plainStart) out.push(code.slice(plainStart, until));
|
|
343
|
+
};
|
|
344
|
+
while (pos < code.length) {
|
|
345
|
+
let matched = false;
|
|
346
|
+
for (const rule of rules) {
|
|
347
|
+
rule.re.lastIndex = pos;
|
|
348
|
+
const m = rule.re.exec(code);
|
|
349
|
+
if (m && m[0].length > 0) {
|
|
350
|
+
flushPlain(pos);
|
|
351
|
+
out.push(
|
|
352
|
+
/* @__PURE__ */ jsx3("span", { className: `lens-db__tok-${rule.cls}`, children: m[0] }, key++)
|
|
353
|
+
);
|
|
354
|
+
pos += m[0].length;
|
|
355
|
+
plainStart = pos;
|
|
356
|
+
matched = true;
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
if (!matched) pos += 1;
|
|
361
|
+
}
|
|
362
|
+
flushPlain(code.length);
|
|
363
|
+
return out;
|
|
364
|
+
}
|
|
365
|
+
function relativeTime(iso, now = Date.now()) {
|
|
366
|
+
if (!iso) return "\u2014";
|
|
367
|
+
const then = new Date(iso).getTime();
|
|
368
|
+
if (Number.isNaN(then)) return "\u2014";
|
|
369
|
+
const diff = now - then;
|
|
370
|
+
const sec = Math.round(diff / 1e3);
|
|
371
|
+
if (sec < 5) return "just now";
|
|
372
|
+
if (sec < 60) return `${sec}s ago`;
|
|
373
|
+
const min = Math.round(sec / 60);
|
|
374
|
+
if (min < 60) return `${min}m ago`;
|
|
375
|
+
const hr = Math.round(min / 60);
|
|
376
|
+
if (hr < 24) return `${hr}h ago`;
|
|
377
|
+
const day = Math.round(hr / 24);
|
|
378
|
+
if (day < 7) return `${day}d ago`;
|
|
379
|
+
const wk = Math.round(day / 7);
|
|
380
|
+
if (wk < 5) return `${wk}w ago`;
|
|
381
|
+
const mo = Math.round(day / 30);
|
|
382
|
+
if (mo < 12) return `${mo}mo ago`;
|
|
383
|
+
const yr = Math.round(day / 365);
|
|
384
|
+
return `${yr}y ago`;
|
|
385
|
+
}
|
|
386
|
+
function formatTimestamp(iso) {
|
|
387
|
+
if (!iso) return "\u2014";
|
|
388
|
+
const d = new Date(iso);
|
|
389
|
+
if (Number.isNaN(d.getTime())) return "\u2014";
|
|
390
|
+
return d.toLocaleString();
|
|
391
|
+
}
|
|
392
|
+
function truncate(value, max = 80) {
|
|
393
|
+
if (value.length <= max) return value;
|
|
394
|
+
return `${value.slice(0, max - 1).trimEnd()}\u2026`;
|
|
395
|
+
}
|
|
396
|
+
function urlPath(raw) {
|
|
397
|
+
if (!raw) return "\u2014";
|
|
398
|
+
try {
|
|
399
|
+
const u = new URL(raw);
|
|
400
|
+
return `${u.pathname}${u.search}` || "/";
|
|
401
|
+
} catch {
|
|
402
|
+
return raw;
|
|
403
|
+
}
|
|
404
|
+
}
|
|
405
|
+
function formatDuration(ms) {
|
|
406
|
+
if (ms == null) return "\u2014";
|
|
407
|
+
if (ms < 1e3) return `${Math.round(ms)}ms`;
|
|
408
|
+
return `${(ms / 1e3).toFixed(2)}s`;
|
|
409
|
+
}
|
|
410
|
+
var LABELS = {
|
|
411
|
+
initiated: "Initiated",
|
|
412
|
+
submitted: "Submitted",
|
|
413
|
+
triaged: "Triaged",
|
|
414
|
+
linked: "Linked",
|
|
415
|
+
resolved: "Resolved"
|
|
416
|
+
};
|
|
417
|
+
function StatusBadge({ status }) {
|
|
418
|
+
return /* @__PURE__ */ jsx4("span", { className: clsx_default("lens-db__badge", `lens-db__badge--${status}`), children: LABELS[status] });
|
|
344
419
|
}
|
|
345
420
|
var SEARCH_DEBOUNCE_MS = 350;
|
|
346
421
|
function ReportsTable(props) {
|
|
@@ -403,7 +478,7 @@ function ReportsTable(props) {
|
|
|
403
478
|
const contextText = isOnlyPage ? `Showing ${reports.length}` : `${reports.length} on this page`;
|
|
404
479
|
return /* @__PURE__ */ jsxs2("div", { className: clsx_default("lens-db", "lens-db__table-wrap", className), children: [
|
|
405
480
|
/* @__PURE__ */ jsxs2("div", { className: "lens-db__table-toolbar", children: [
|
|
406
|
-
/* @__PURE__ */
|
|
481
|
+
/* @__PURE__ */ jsx5(
|
|
407
482
|
"input",
|
|
408
483
|
{
|
|
409
484
|
type: "search",
|
|
@@ -420,23 +495,23 @@ function ReportsTable(props) {
|
|
|
420
495
|
}
|
|
421
496
|
}
|
|
422
497
|
),
|
|
423
|
-
!loading && !error && reports.length > 0 && /* @__PURE__ */
|
|
498
|
+
!loading && !error && reports.length > 0 && /* @__PURE__ */ jsx5("span", { className: "lens-db__table-context lens-db__muted", children: contextText })
|
|
424
499
|
] }),
|
|
425
500
|
/* @__PURE__ */ jsxs2("table", { className: "lens-db__table", children: [
|
|
426
|
-
/* @__PURE__ */
|
|
427
|
-
/* @__PURE__ */
|
|
428
|
-
/* @__PURE__ */
|
|
429
|
-
/* @__PURE__ */
|
|
430
|
-
/* @__PURE__ */
|
|
431
|
-
/* @__PURE__ */
|
|
432
|
-
/* @__PURE__ */
|
|
433
|
-
/* @__PURE__ */
|
|
501
|
+
/* @__PURE__ */ jsx5("thead", { children: /* @__PURE__ */ jsxs2("tr", { children: [
|
|
502
|
+
/* @__PURE__ */ jsx5("th", { children: "Created" }),
|
|
503
|
+
/* @__PURE__ */ jsx5("th", { children: "Comment" }),
|
|
504
|
+
/* @__PURE__ */ jsx5("th", { children: "Path" }),
|
|
505
|
+
/* @__PURE__ */ jsx5("th", { children: "Status" }),
|
|
506
|
+
/* @__PURE__ */ jsx5("th", { className: "lens-db__num", children: "Errors" }),
|
|
507
|
+
/* @__PURE__ */ jsx5("th", { className: "lens-db__center", children: "Replay" }),
|
|
508
|
+
/* @__PURE__ */ jsx5("th", { children: "Issue" })
|
|
434
509
|
] }) }),
|
|
435
|
-
/* @__PURE__ */
|
|
510
|
+
/* @__PURE__ */ jsx5("tbody", { children: loading ? /* @__PURE__ */ jsx5(SkeletonRows, { rows: 6 }) : error ? /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsxs2("td", { colSpan: 7, className: "lens-db__error", children: [
|
|
436
511
|
"Failed to load reports: ",
|
|
437
512
|
error.message,
|
|
438
513
|
" ",
|
|
439
|
-
/* @__PURE__ */
|
|
514
|
+
/* @__PURE__ */ jsx5(
|
|
440
515
|
"button",
|
|
441
516
|
{
|
|
442
517
|
type: "button",
|
|
@@ -445,20 +520,20 @@ function ReportsTable(props) {
|
|
|
445
520
|
children: "Retry"
|
|
446
521
|
}
|
|
447
522
|
)
|
|
448
|
-
] }) }) : reports.length === 0 ? /* @__PURE__ */
|
|
449
|
-
/* @__PURE__ */
|
|
523
|
+
] }) }) : reports.length === 0 ? /* @__PURE__ */ jsx5("tr", { children: /* @__PURE__ */ jsxs2("td", { colSpan: 7, className: "lens-db__empty", children: [
|
|
524
|
+
/* @__PURE__ */ jsx5("span", { className: "lens-db__empty-icon", children: /* @__PURE__ */ jsx5(IconInbox, { size: 32 }) }),
|
|
450
525
|
query ? /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
451
|
-
/* @__PURE__ */
|
|
526
|
+
/* @__PURE__ */ jsx5("div", { className: "lens-db__empty-title", children: "No matching reports" }),
|
|
452
527
|
/* @__PURE__ */ jsxs2("div", { className: "lens-db__empty-hint", children: [
|
|
453
528
|
"No reports match \u201C",
|
|
454
529
|
query,
|
|
455
530
|
"\u201D. Try a different search."
|
|
456
531
|
] })
|
|
457
532
|
] }) : /* @__PURE__ */ jsxs2(Fragment, { children: [
|
|
458
|
-
/* @__PURE__ */
|
|
533
|
+
/* @__PURE__ */ jsx5("div", { className: "lens-db__empty-title", children: "No reports yet" }),
|
|
459
534
|
/* @__PURE__ */ jsxs2("div", { className: "lens-db__empty-hint", children: [
|
|
460
535
|
"Visit your app with ",
|
|
461
|
-
/* @__PURE__ */
|
|
536
|
+
/* @__PURE__ */ jsx5("code", { children: "?lens=true" }),
|
|
462
537
|
" and submit one."
|
|
463
538
|
] })
|
|
464
539
|
] })
|
|
@@ -475,13 +550,13 @@ function ReportsTable(props) {
|
|
|
475
550
|
}
|
|
476
551
|
} : void 0,
|
|
477
552
|
children: [
|
|
478
|
-
/* @__PURE__ */
|
|
479
|
-
/* @__PURE__ */
|
|
480
|
-
/* @__PURE__ */
|
|
481
|
-
/* @__PURE__ */
|
|
482
|
-
/* @__PURE__ */
|
|
483
|
-
/* @__PURE__ */
|
|
484
|
-
/* @__PURE__ */
|
|
553
|
+
/* @__PURE__ */ jsx5("td", { className: "lens-db__muted lens-db__tnum", title: r2.createdAt, children: relativeTime(r2.createdAt) }),
|
|
554
|
+
/* @__PURE__ */ jsx5("td", { children: r2.comment ? /* @__PURE__ */ jsx5("span", { className: "lens-db__cell-comment", title: r2.comment, children: r2.comment }) : /* @__PURE__ */ jsx5("span", { className: "lens-db__muted", children: "\u2014" }) }),
|
|
555
|
+
/* @__PURE__ */ jsx5("td", { className: "lens-db__mono lens-db__muted", title: r2.url, children: urlPath(r2.url) }),
|
|
556
|
+
/* @__PURE__ */ jsx5("td", { children: /* @__PURE__ */ jsx5(StatusBadge, { status: r2.status }) }),
|
|
557
|
+
/* @__PURE__ */ jsx5("td", { className: "lens-db__num", children: r2.errorCount > 0 ? /* @__PURE__ */ jsx5("span", { className: "lens-db__badge lens-db__badge--danger", children: r2.errorCount }) : /* @__PURE__ */ jsx5("span", { className: "lens-db__muted", children: "0" }) }),
|
|
558
|
+
/* @__PURE__ */ jsx5("td", { className: "lens-db__center", children: r2.hasReplay ? /* @__PURE__ */ jsx5("span", { className: "lens-db__play", title: "Session replay captured", "aria-label": "Has replay", children: /* @__PURE__ */ jsx5(IconPlay, { size: 14 }) }) : /* @__PURE__ */ jsx5("span", { className: "lens-db__muted", "aria-label": "No replay", children: "\u2014" }) }),
|
|
559
|
+
/* @__PURE__ */ jsx5("td", { children: r2.externalIssue ? /* @__PURE__ */ jsx5(
|
|
485
560
|
"a",
|
|
486
561
|
{
|
|
487
562
|
className: "lens-db__link",
|
|
@@ -491,7 +566,7 @@ function ReportsTable(props) {
|
|
|
491
566
|
onClick: (e) => e.stopPropagation(),
|
|
492
567
|
children: r2.externalIssue.key
|
|
493
568
|
}
|
|
494
|
-
) : /* @__PURE__ */
|
|
569
|
+
) : /* @__PURE__ */ jsx5("span", { className: "lens-db__muted", children: "\u2014" }) })
|
|
495
570
|
]
|
|
496
571
|
},
|
|
497
572
|
r2.id
|
|
@@ -506,7 +581,7 @@ function ReportsTable(props) {
|
|
|
506
581
|
disabled: !canPrev || loading,
|
|
507
582
|
onClick: goPrev,
|
|
508
583
|
children: [
|
|
509
|
-
/* @__PURE__ */
|
|
584
|
+
/* @__PURE__ */ jsx5(IconChevronLeft, { size: 16 }),
|
|
510
585
|
"Prev"
|
|
511
586
|
]
|
|
512
587
|
}
|
|
@@ -520,7 +595,7 @@ function ReportsTable(props) {
|
|
|
520
595
|
onClick: goNext,
|
|
521
596
|
children: [
|
|
522
597
|
"Next",
|
|
523
|
-
/* @__PURE__ */
|
|
598
|
+
/* @__PURE__ */ jsx5(IconChevronRight, { size: 16 })
|
|
524
599
|
]
|
|
525
600
|
}
|
|
526
601
|
)
|
|
@@ -528,7 +603,7 @@ function ReportsTable(props) {
|
|
|
528
603
|
] });
|
|
529
604
|
}
|
|
530
605
|
function SkeletonRows({ rows }) {
|
|
531
|
-
return /* @__PURE__ */
|
|
606
|
+
return /* @__PURE__ */ jsx5(Fragment, { children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsx5("tr", { className: "lens-db__row lens-db__row--skeleton", "aria-hidden": true, children: Array.from({ length: 7 }).map((__, j) => /* @__PURE__ */ jsx5("td", { children: /* @__PURE__ */ jsx5("span", { className: "lens-db__skeleton" }) }, j)) }, i)) });
|
|
532
607
|
}
|
|
533
608
|
function useAsync(fn, deps) {
|
|
534
609
|
const [data, setData] = useState2(void 0);
|
|
@@ -773,17 +848,17 @@ function ReplayPlayer(props) {
|
|
|
773
848
|
}, [api, reportId, stopRaf]);
|
|
774
849
|
const pct = total > 0 ? Math.min(100, elapsed / total * 100) : 0;
|
|
775
850
|
return /* @__PURE__ */ jsxs3("div", { className: clsx_default("lens-db", "lens-db__replay", className), children: [
|
|
776
|
-
status === "loading" && /* @__PURE__ */
|
|
777
|
-
status === "empty" && /* @__PURE__ */
|
|
851
|
+
status === "loading" && /* @__PURE__ */ jsx6("div", { className: "lens-db__replay-state", children: "Loading replay\u2026" }),
|
|
852
|
+
status === "empty" && /* @__PURE__ */ jsx6("div", { className: "lens-db__replay-state lens-db__muted", children: "No replay captured." }),
|
|
778
853
|
status === "error" && /* @__PURE__ */ jsxs3("div", { className: "lens-db__replay-state lens-db__error", children: [
|
|
779
854
|
"No replay captured",
|
|
780
855
|
message ? ` \u2014 ${message}` : "",
|
|
781
856
|
"."
|
|
782
857
|
] }),
|
|
783
858
|
/* @__PURE__ */ jsxs3("div", { className: "lens-db__rp", "data-visible": status === "ready", children: [
|
|
784
|
-
/* @__PURE__ */
|
|
859
|
+
/* @__PURE__ */ jsx6("div", { ref: frameRef, className: "lens-db__rp-frame" }),
|
|
785
860
|
/* @__PURE__ */ jsxs3("div", { className: "lens-db__rp-bar", children: [
|
|
786
|
-
/* @__PURE__ */
|
|
861
|
+
/* @__PURE__ */ jsx6(
|
|
787
862
|
"button",
|
|
788
863
|
{
|
|
789
864
|
type: "button",
|
|
@@ -791,11 +866,11 @@ function ReplayPlayer(props) {
|
|
|
791
866
|
onClick: togglePlay,
|
|
792
867
|
"aria-label": playing ? "Pause replay" : "Play replay",
|
|
793
868
|
"aria-pressed": playing,
|
|
794
|
-
children: playing ? /* @__PURE__ */
|
|
869
|
+
children: playing ? /* @__PURE__ */ jsx6(IconPause, { size: 16 }) : /* @__PURE__ */ jsx6(IconPlay, { size: 16 })
|
|
795
870
|
}
|
|
796
871
|
),
|
|
797
|
-
/* @__PURE__ */
|
|
798
|
-
/* @__PURE__ */
|
|
872
|
+
/* @__PURE__ */ jsx6("span", { className: "lens-db__rp-time", children: formatTime(elapsed) }),
|
|
873
|
+
/* @__PURE__ */ jsx6(
|
|
799
874
|
"div",
|
|
800
875
|
{
|
|
801
876
|
ref: trackRef,
|
|
@@ -810,11 +885,11 @@ function ReplayPlayer(props) {
|
|
|
810
885
|
onPointerDown: onTrackPointerDown,
|
|
811
886
|
onPointerMove: onTrackPointerMove,
|
|
812
887
|
onKeyDown: onTrackKeyDown,
|
|
813
|
-
children: /* @__PURE__ */
|
|
888
|
+
children: /* @__PURE__ */ jsx6("div", { className: "lens-db__rp-fill", style: { width: `${pct}%` } })
|
|
814
889
|
}
|
|
815
890
|
),
|
|
816
|
-
/* @__PURE__ */
|
|
817
|
-
/* @__PURE__ */
|
|
891
|
+
/* @__PURE__ */ jsx6("span", { className: "lens-db__rp-time", children: formatTime(total) }),
|
|
892
|
+
/* @__PURE__ */ jsx6("div", { className: "lens-db__rp-speeds", role: "group", "aria-label": "Playback speed", children: SPEEDS.map((s) => /* @__PURE__ */ jsxs3(
|
|
818
893
|
"button",
|
|
819
894
|
{
|
|
820
895
|
type: "button",
|
|
@@ -828,7 +903,7 @@ function ReplayPlayer(props) {
|
|
|
828
903
|
},
|
|
829
904
|
s
|
|
830
905
|
)) }),
|
|
831
|
-
/* @__PURE__ */
|
|
906
|
+
/* @__PURE__ */ jsx6(
|
|
832
907
|
"button",
|
|
833
908
|
{
|
|
834
909
|
type: "button",
|
|
@@ -850,14 +925,14 @@ function ReportDetail(props) {
|
|
|
850
925
|
[reportId]
|
|
851
926
|
);
|
|
852
927
|
return /* @__PURE__ */ jsxs4("div", { className: clsx_default("lens-db", "lens-db__detail", className), children: [
|
|
853
|
-
loading && /* @__PURE__ */
|
|
928
|
+
loading && /* @__PURE__ */ jsx7("div", { className: "lens-db__detail-loading", children: "Loading report\u2026" }),
|
|
854
929
|
error && /* @__PURE__ */ jsxs4("div", { className: "lens-db__error", children: [
|
|
855
930
|
"Failed to load report: ",
|
|
856
931
|
error.message,
|
|
857
932
|
" ",
|
|
858
|
-
/* @__PURE__ */
|
|
933
|
+
/* @__PURE__ */ jsx7("button", { type: "button", className: "lens-db__link-btn", onClick: reload, children: "Retry" })
|
|
859
934
|
] }),
|
|
860
|
-
report && /* @__PURE__ */
|
|
935
|
+
report && /* @__PURE__ */ jsx7(ReportDetailBody, { report, onClose })
|
|
861
936
|
] });
|
|
862
937
|
}
|
|
863
938
|
function ReportDetailBody({ report, onClose }) {
|
|
@@ -902,8 +977,8 @@ function ReportDetailBody({ report, onClose }) {
|
|
|
902
977
|
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
903
978
|
/* @__PURE__ */ jsxs4("header", { className: "lens-db__detail-header", children: [
|
|
904
979
|
/* @__PURE__ */ jsxs4("div", { className: "lens-db__detail-header-main", children: [
|
|
905
|
-
/* @__PURE__ */
|
|
906
|
-
/* @__PURE__ */
|
|
980
|
+
/* @__PURE__ */ jsx7(StatusBadge, { status: report.status }),
|
|
981
|
+
/* @__PURE__ */ jsx7("span", { className: "lens-db__detail-time", title: formatTimestamp(report.createdAt), children: relativeTime(report.createdAt) }),
|
|
907
982
|
report.externalIssue && /* @__PURE__ */ jsxs4(
|
|
908
983
|
"a",
|
|
909
984
|
{
|
|
@@ -915,14 +990,14 @@ function ReportDetailBody({ report, onClose }) {
|
|
|
915
990
|
report.externalIssue.provider,
|
|
916
991
|
" \xB7 ",
|
|
917
992
|
report.externalIssue.key,
|
|
918
|
-
/* @__PURE__ */
|
|
993
|
+
/* @__PURE__ */ jsx7(IconExternal, { size: 13 })
|
|
919
994
|
]
|
|
920
995
|
}
|
|
921
996
|
)
|
|
922
997
|
] }),
|
|
923
|
-
onClose && /* @__PURE__ */
|
|
998
|
+
onClose && /* @__PURE__ */ jsx7("button", { type: "button", className: "lens-db__icon-btn", "aria-label": "Close", onClick: onClose, children: /* @__PURE__ */ jsx7(IconClose, {}) })
|
|
924
999
|
] }),
|
|
925
|
-
/* @__PURE__ */
|
|
1000
|
+
/* @__PURE__ */ jsx7("div", { className: "lens-db__tabs", role: "tablist", "aria-label": "Report sections", children: tabs.map((t, i) => {
|
|
926
1001
|
const active = t.id === tab;
|
|
927
1002
|
return /* @__PURE__ */ jsxs4(
|
|
928
1003
|
"button",
|
|
@@ -940,18 +1015,18 @@ function ReportDetailBody({ report, onClose }) {
|
|
|
940
1015
|
onClick: () => select(t.id),
|
|
941
1016
|
onKeyDown: (e) => onTabKeyDown(e, i),
|
|
942
1017
|
children: [
|
|
943
|
-
/* @__PURE__ */
|
|
944
|
-
t.count != null && t.count > 0 && /* @__PURE__ */
|
|
1018
|
+
/* @__PURE__ */ jsx7("span", { className: "lens-db__tab-label", children: t.label }),
|
|
1019
|
+
t.count != null && t.count > 0 && /* @__PURE__ */ jsx7("span", { className: "lens-db__tab-count", children: t.count })
|
|
945
1020
|
]
|
|
946
1021
|
},
|
|
947
1022
|
t.id
|
|
948
1023
|
);
|
|
949
1024
|
}) }),
|
|
950
1025
|
/* @__PURE__ */ jsxs4("div", { className: "lens-db__tabpanels", children: [
|
|
951
|
-
tab === "overview" && /* @__PURE__ */
|
|
952
|
-
tab === "logs" && /* @__PURE__ */
|
|
953
|
-
tab === "network" && /* @__PURE__ */
|
|
954
|
-
replayMounted && /* @__PURE__ */
|
|
1026
|
+
tab === "overview" && /* @__PURE__ */ jsx7("div", { role: "tabpanel", id: panelId("overview"), "aria-labelledby": tabId("overview"), tabIndex: 0, children: /* @__PURE__ */ jsx7(OverviewPanel, { report, meta }) }),
|
|
1027
|
+
tab === "logs" && /* @__PURE__ */ jsx7("div", { role: "tabpanel", id: panelId("logs"), "aria-labelledby": tabId("logs"), tabIndex: 0, children: /* @__PURE__ */ jsx7(LogsPanel, { errors: meta?.errors ?? [], consoleEntries: meta?.consoleTail ?? [] }) }),
|
|
1028
|
+
tab === "network" && /* @__PURE__ */ jsx7("div", { role: "tabpanel", id: panelId("network"), "aria-labelledby": tabId("network"), tabIndex: 0, children: /* @__PURE__ */ jsx7(NetworkPanel, { entries: meta?.networkTail ?? [] }) }),
|
|
1029
|
+
replayMounted && /* @__PURE__ */ jsx7(
|
|
955
1030
|
"div",
|
|
956
1031
|
{
|
|
957
1032
|
role: "tabpanel",
|
|
@@ -959,7 +1034,7 @@ function ReportDetailBody({ report, onClose }) {
|
|
|
959
1034
|
"aria-labelledby": tabId("replay"),
|
|
960
1035
|
tabIndex: 0,
|
|
961
1036
|
hidden: tab !== "replay",
|
|
962
|
-
children: /* @__PURE__ */
|
|
1037
|
+
children: /* @__PURE__ */ jsx7("div", { className: "lens-db__panel", children: /* @__PURE__ */ jsx7(ReplayPlayer, { reportId: report.id }) })
|
|
963
1038
|
}
|
|
964
1039
|
)
|
|
965
1040
|
] })
|
|
@@ -970,20 +1045,20 @@ function OverviewPanel({ report, meta }) {
|
|
|
970
1045
|
const attachments = report.assets.filter((a) => a.kind !== "screenshot");
|
|
971
1046
|
if (!meta) {
|
|
972
1047
|
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
973
|
-
hasScreenshot && /* @__PURE__ */
|
|
974
|
-
/* @__PURE__ */
|
|
1048
|
+
hasScreenshot && /* @__PURE__ */ jsx7(Section, { title: "Screenshot", children: /* @__PURE__ */ jsx7(Screenshot, { reportId: report.id }) }),
|
|
1049
|
+
/* @__PURE__ */ jsx7(Section, { title: "Report", children: /* @__PURE__ */ jsx7("p", { className: "lens-db__muted", children: "This report has no metadata yet (still initiating)." }) })
|
|
975
1050
|
] });
|
|
976
1051
|
}
|
|
977
1052
|
const hasTarget = Boolean(meta.target && (meta.target.domPath || meta.target.reactComponents?.length));
|
|
978
1053
|
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
979
|
-
meta.comment && /* @__PURE__ */
|
|
980
|
-
hasScreenshot && /* @__PURE__ */
|
|
981
|
-
/* @__PURE__ */
|
|
1054
|
+
meta.comment && /* @__PURE__ */ jsx7(Section, { title: "Comment", children: /* @__PURE__ */ jsx7("p", { className: "lens-db__comment", children: meta.comment }) }),
|
|
1055
|
+
hasScreenshot && /* @__PURE__ */ jsx7(Section, { title: "Screenshot", children: /* @__PURE__ */ jsx7(Screenshot, { reportId: report.id }) }),
|
|
1056
|
+
/* @__PURE__ */ jsx7(Section, { title: "Environment", children: /* @__PURE__ */ jsx7(EnvironmentGrid, { env: meta.env, app: meta.app }) }),
|
|
982
1057
|
hasTarget && meta.target && /* @__PURE__ */ jsxs4(Section, { title: "Target element", children: [
|
|
983
|
-
meta.target.domPath && /* @__PURE__ */
|
|
984
|
-
meta.target.reactComponents && meta.target.reactComponents.length > 0 && /* @__PURE__ */
|
|
1058
|
+
meta.target.domPath && /* @__PURE__ */ jsx7("code", { className: "lens-db__dompath", children: meta.target.domPath }),
|
|
1059
|
+
meta.target.reactComponents && meta.target.reactComponents.length > 0 && /* @__PURE__ */ jsx7("div", { className: "lens-db__chips", children: meta.target.reactComponents.map((c, i) => /* @__PURE__ */ jsx7("span", { className: "lens-db__chip", children: c }, `${c}-${i}`)) })
|
|
985
1060
|
] }),
|
|
986
|
-
attachments.length > 0 && /* @__PURE__ */
|
|
1061
|
+
attachments.length > 0 && /* @__PURE__ */ jsx7(Section, { title: "Attachments", children: /* @__PURE__ */ jsx7(Attachments, { reportId: report.id, assets: attachments }) })
|
|
987
1062
|
] });
|
|
988
1063
|
}
|
|
989
1064
|
function Screenshot({ reportId }) {
|
|
@@ -993,10 +1068,10 @@ function Screenshot({ reportId }) {
|
|
|
993
1068
|
[reportId]
|
|
994
1069
|
);
|
|
995
1070
|
if (loading) {
|
|
996
|
-
return /* @__PURE__ */
|
|
1071
|
+
return /* @__PURE__ */ jsx7("div", { className: "lens-db__shot lens-db__shot--loading", "aria-hidden": true });
|
|
997
1072
|
}
|
|
998
1073
|
if (error || !url) return null;
|
|
999
|
-
return /* @__PURE__ */
|
|
1074
|
+
return /* @__PURE__ */ jsx7(
|
|
1000
1075
|
"a",
|
|
1001
1076
|
{
|
|
1002
1077
|
className: "lens-db__shot",
|
|
@@ -1004,7 +1079,7 @@ function Screenshot({ reportId }) {
|
|
|
1004
1079
|
target: "_blank",
|
|
1005
1080
|
rel: "noreferrer",
|
|
1006
1081
|
title: "Open full screenshot in a new tab",
|
|
1007
|
-
children: /* @__PURE__ */
|
|
1082
|
+
children: /* @__PURE__ */ jsx7("img", { className: "lens-db__shot-img", src: url, alt: "Captured screenshot", loading: "lazy" })
|
|
1008
1083
|
}
|
|
1009
1084
|
);
|
|
1010
1085
|
}
|
|
@@ -1026,60 +1101,60 @@ function dedupeErrors(errors) {
|
|
|
1026
1101
|
function LogsPanel({ errors, consoleEntries }) {
|
|
1027
1102
|
const groups = dedupeErrors(errors);
|
|
1028
1103
|
return /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
1029
|
-
/* @__PURE__ */
|
|
1030
|
-
/* @__PURE__ */
|
|
1104
|
+
/* @__PURE__ */ jsx7(Section, { title: `Errors${errors.length ? ` (${groups.length})` : ""}`, children: groups.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "lens-db__muted", children: "Nothing captured." }) : /* @__PURE__ */ jsx7("div", { className: "lens-db__scroll", children: /* @__PURE__ */ jsx7("ul", { className: "lens-db__errlog", children: groups.map((g, i) => /* @__PURE__ */ jsx7(ErrorRow, { group: g }, i)) }) }) }),
|
|
1105
|
+
/* @__PURE__ */ jsx7(Section, { title: "Console", children: consoleEntries.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "lens-db__muted", children: "Nothing captured." }) : /* @__PURE__ */ jsx7("div", { className: "lens-db__scroll", children: /* @__PURE__ */ jsx7(ConsoleTail, { entries: consoleEntries }) }) })
|
|
1031
1106
|
] });
|
|
1032
1107
|
}
|
|
1033
1108
|
function ErrorRow({ group }) {
|
|
1034
1109
|
const { entry, count } = group;
|
|
1035
1110
|
const firstLine = entry.message.split("\n")[0] ?? entry.message;
|
|
1036
|
-
return /* @__PURE__ */
|
|
1111
|
+
return /* @__PURE__ */ jsx7("li", { className: "lens-db__errlog-item", children: /* @__PURE__ */ jsxs4("details", { className: "lens-db__errlog-details", children: [
|
|
1037
1112
|
/* @__PURE__ */ jsxs4("summary", { className: "lens-db__errlog-summary", children: [
|
|
1038
|
-
/* @__PURE__ */
|
|
1113
|
+
/* @__PURE__ */ jsx7("span", { className: "lens-db__errlog-msg", children: truncate(firstLine, 140) }),
|
|
1039
1114
|
count > 1 && /* @__PURE__ */ jsxs4("span", { className: "lens-db__count-badge", children: [
|
|
1040
1115
|
"\xD7",
|
|
1041
1116
|
count
|
|
1042
1117
|
] }),
|
|
1043
|
-
/* @__PURE__ */
|
|
1118
|
+
/* @__PURE__ */ jsx7("span", { className: "lens-db__errlog-source", children: entry.source })
|
|
1044
1119
|
] }),
|
|
1045
1120
|
/* @__PURE__ */ jsxs4("div", { className: "lens-db__errlog-body", children: [
|
|
1046
|
-
entry.message !== firstLine && /* @__PURE__ */
|
|
1047
|
-
entry.stack && /* @__PURE__ */
|
|
1121
|
+
entry.message !== firstLine && /* @__PURE__ */ jsx7("pre", { className: "lens-db__stack", children: entry.message }),
|
|
1122
|
+
entry.stack && /* @__PURE__ */ jsx7("pre", { className: "lens-db__stack", children: entry.stack })
|
|
1048
1123
|
] })
|
|
1049
1124
|
] }) });
|
|
1050
1125
|
}
|
|
1051
1126
|
function ConsoleTail({ entries }) {
|
|
1052
|
-
return /* @__PURE__ */
|
|
1053
|
-
/* @__PURE__ */
|
|
1054
|
-
/* @__PURE__ */
|
|
1127
|
+
return /* @__PURE__ */ jsx7("div", { className: "lens-db__console", children: entries.map((e, i) => /* @__PURE__ */ jsxs4("div", { className: clsx_default("lens-db__console-line", `lens-db__console-line--${e.level}`), children: [
|
|
1128
|
+
/* @__PURE__ */ jsx7("span", { className: "lens-db__console-level", children: e.level }),
|
|
1129
|
+
/* @__PURE__ */ jsx7("span", { className: "lens-db__console-args", children: e.args.join(" ") })
|
|
1055
1130
|
] }, i)) });
|
|
1056
1131
|
}
|
|
1057
1132
|
function NetworkPanel({ entries }) {
|
|
1058
|
-
return /* @__PURE__ */
|
|
1133
|
+
return /* @__PURE__ */ jsx7("div", { className: "lens-db__panel", children: entries.length === 0 ? /* @__PURE__ */ jsx7("p", { className: "lens-db__muted", children: "Nothing captured." }) : /* @__PURE__ */ jsx7(NetworkTail, { entries }) });
|
|
1059
1134
|
}
|
|
1060
1135
|
function NetworkTail({ entries }) {
|
|
1061
1136
|
return /* @__PURE__ */ jsxs4("table", { className: "lens-db__nettable", children: [
|
|
1062
|
-
/* @__PURE__ */
|
|
1063
|
-
/* @__PURE__ */
|
|
1064
|
-
/* @__PURE__ */
|
|
1065
|
-
/* @__PURE__ */
|
|
1066
|
-
/* @__PURE__ */
|
|
1137
|
+
/* @__PURE__ */ jsx7("thead", { children: /* @__PURE__ */ jsxs4("tr", { children: [
|
|
1138
|
+
/* @__PURE__ */ jsx7("th", { children: "Method" }),
|
|
1139
|
+
/* @__PURE__ */ jsx7("th", { children: "Path" }),
|
|
1140
|
+
/* @__PURE__ */ jsx7("th", { className: "lens-db__num", children: "Status" }),
|
|
1141
|
+
/* @__PURE__ */ jsx7("th", { className: "lens-db__num", children: "Duration" })
|
|
1067
1142
|
] }) }),
|
|
1068
|
-
/* @__PURE__ */
|
|
1143
|
+
/* @__PURE__ */ jsx7("tbody", { children: entries.map((e, i) => {
|
|
1069
1144
|
const bad = e.error != null || e.ok === false || e.status != null && (e.status < 200 || e.status >= 300);
|
|
1070
1145
|
return /* @__PURE__ */ jsxs4("tr", { className: clsx_default(bad && "lens-db__netrow--bad"), children: [
|
|
1071
|
-
/* @__PURE__ */
|
|
1072
|
-
/* @__PURE__ */
|
|
1073
|
-
/* @__PURE__ */
|
|
1074
|
-
/* @__PURE__ */
|
|
1146
|
+
/* @__PURE__ */ jsx7("td", { className: "lens-db__mono", children: e.method }),
|
|
1147
|
+
/* @__PURE__ */ jsx7("td", { className: "lens-db__mono lens-db__muted", title: e.url, children: urlPath(e.url) }),
|
|
1148
|
+
/* @__PURE__ */ jsx7("td", { className: "lens-db__num lens-db__mono lens-db__net-status", children: e.error ? "ERR" : e.status ?? "\u2014" }),
|
|
1149
|
+
/* @__PURE__ */ jsx7("td", { className: "lens-db__num lens-db__muted", children: formatDuration(e.durationMs) })
|
|
1075
1150
|
] }, i);
|
|
1076
1151
|
}) })
|
|
1077
1152
|
] });
|
|
1078
1153
|
}
|
|
1079
1154
|
function Section({ title, children }) {
|
|
1080
1155
|
return /* @__PURE__ */ jsxs4("section", { className: "lens-db__section", children: [
|
|
1081
|
-
/* @__PURE__ */
|
|
1082
|
-
/* @__PURE__ */
|
|
1156
|
+
/* @__PURE__ */ jsx7("h3", { className: "lens-db__section-title", children: title }),
|
|
1157
|
+
/* @__PURE__ */ jsx7("div", { className: "lens-db__section-body", children })
|
|
1083
1158
|
] });
|
|
1084
1159
|
}
|
|
1085
1160
|
function EnvironmentGrid({ env, app }) {
|
|
@@ -1095,9 +1170,9 @@ function EnvironmentGrid({ env, app }) {
|
|
|
1095
1170
|
["Git SHA", app?.gitSha]
|
|
1096
1171
|
];
|
|
1097
1172
|
const monoLabels = /* @__PURE__ */ new Set(["URL", "Route", "Release", "Git SHA"]);
|
|
1098
|
-
return /* @__PURE__ */
|
|
1099
|
-
/* @__PURE__ */
|
|
1100
|
-
/* @__PURE__ */
|
|
1173
|
+
return /* @__PURE__ */ jsx7("dl", { className: "lens-db__grid", children: rows.filter(([, v]) => v != null && v !== "").map(([label, value]) => /* @__PURE__ */ jsxs4("div", { className: "lens-db__grid-row", children: [
|
|
1174
|
+
/* @__PURE__ */ jsx7("dt", { className: "lens-db__grid-label", children: label }),
|
|
1175
|
+
/* @__PURE__ */ jsx7("dd", { className: clsx_default("lens-db__grid-value", monoLabels.has(label) && "lens-db__mono"), children: value })
|
|
1101
1176
|
] }, label)) });
|
|
1102
1177
|
}
|
|
1103
1178
|
function Attachments({ reportId, assets }) {
|
|
@@ -1117,12 +1192,12 @@ function Attachments({ reportId, assets }) {
|
|
|
1117
1192
|
}
|
|
1118
1193
|
}
|
|
1119
1194
|
return /* @__PURE__ */ jsxs4("div", { className: "lens-db__attachments", children: [
|
|
1120
|
-
err && /* @__PURE__ */
|
|
1121
|
-
/* @__PURE__ */
|
|
1122
|
-
/* @__PURE__ */
|
|
1123
|
-
/* @__PURE__ */
|
|
1124
|
-
a.byteSize != null && /* @__PURE__ */
|
|
1125
|
-
/* @__PURE__ */
|
|
1195
|
+
err && /* @__PURE__ */ jsx7("div", { className: "lens-db__error", children: err }),
|
|
1196
|
+
/* @__PURE__ */ jsx7("ul", { className: "lens-db__attachment-list", children: assets.map((a) => /* @__PURE__ */ jsxs4("li", { className: "lens-db__attachment", children: [
|
|
1197
|
+
/* @__PURE__ */ jsx7("span", { className: "lens-db__attachment-kind", children: a.kind }),
|
|
1198
|
+
/* @__PURE__ */ jsx7("span", { className: "lens-db__muted lens-db__attachment-type", children: a.contentType }),
|
|
1199
|
+
a.byteSize != null && /* @__PURE__ */ jsx7("span", { className: "lens-db__muted lens-db__attachment-size", children: formatBytes(a.byteSize) }),
|
|
1200
|
+
/* @__PURE__ */ jsx7(
|
|
1126
1201
|
"button",
|
|
1127
1202
|
{
|
|
1128
1203
|
type: "button",
|
|
@@ -1165,6 +1240,11 @@ var CONFIG_FIELD = {
|
|
|
1165
1240
|
placeholder: "First team (default)"
|
|
1166
1241
|
}
|
|
1167
1242
|
};
|
|
1243
|
+
var SELECT_PLACEHOLDER = {
|
|
1244
|
+
linear: "First team (default)",
|
|
1245
|
+
github: "Select a repository\u2026",
|
|
1246
|
+
jira: "Select a project\u2026"
|
|
1247
|
+
};
|
|
1168
1248
|
function IntegrationList(props) {
|
|
1169
1249
|
const {
|
|
1170
1250
|
integrations,
|
|
@@ -1181,6 +1261,7 @@ function IntegrationList(props) {
|
|
|
1181
1261
|
onDisconnect,
|
|
1182
1262
|
onCompleteDev,
|
|
1183
1263
|
onSaveConfig,
|
|
1264
|
+
loadOptions,
|
|
1184
1265
|
className
|
|
1185
1266
|
} = props;
|
|
1186
1267
|
useEffect4(() => {
|
|
@@ -1193,8 +1274,8 @@ function IntegrationList(props) {
|
|
|
1193
1274
|
const hasHeader = Boolean(title || description);
|
|
1194
1275
|
return /* @__PURE__ */ jsxs5("div", { className: clsx_default("lens-db__intlist", className), children: [
|
|
1195
1276
|
hasHeader && /* @__PURE__ */ jsxs5("div", { className: "lens-db__intlist-head", children: [
|
|
1196
|
-
title && /* @__PURE__ */
|
|
1197
|
-
description && /* @__PURE__ */
|
|
1277
|
+
title && /* @__PURE__ */ jsx8("div", { className: "lens-db__intlist-title", children: title }),
|
|
1278
|
+
description && /* @__PURE__ */ jsx8("div", { className: "lens-db__intlist-desc lens-db__muted", children: description })
|
|
1198
1279
|
] }),
|
|
1199
1280
|
flash && /* @__PURE__ */ jsxs5(
|
|
1200
1281
|
"div",
|
|
@@ -1205,16 +1286,16 @@ function IntegrationList(props) {
|
|
|
1205
1286
|
),
|
|
1206
1287
|
role: "status",
|
|
1207
1288
|
children: [
|
|
1208
|
-
flash.kind === "ok" ? /* @__PURE__ */
|
|
1209
|
-
/* @__PURE__ */
|
|
1289
|
+
flash.kind === "ok" ? /* @__PURE__ */ jsx8(IconCheckCircle, { size: 16 }) : /* @__PURE__ */ jsx8(IconAlertTriangle, { size: 16 }),
|
|
1290
|
+
/* @__PURE__ */ jsx8("span", { children: flash.message })
|
|
1210
1291
|
]
|
|
1211
1292
|
}
|
|
1212
1293
|
),
|
|
1213
|
-
loading ? /* @__PURE__ */
|
|
1214
|
-
/* @__PURE__ */
|
|
1294
|
+
loading ? /* @__PURE__ */ jsx8("div", { className: "lens-db__intlist-rows", "aria-busy": "true", children: PROVIDER_ORDER.map((p) => /* @__PURE__ */ jsxs5("div", { className: "lens-db__introw lens-db__introw--skeleton", children: [
|
|
1295
|
+
/* @__PURE__ */ jsx8("span", { className: "lens-db__skeleton lens-db__intmark-skeleton" }),
|
|
1215
1296
|
/* @__PURE__ */ jsxs5("span", { className: "lens-db__intbody", children: [
|
|
1216
|
-
/* @__PURE__ */
|
|
1217
|
-
/* @__PURE__ */
|
|
1297
|
+
/* @__PURE__ */ jsx8("span", { className: "lens-db__skeleton", style: { width: "35%" } }),
|
|
1298
|
+
/* @__PURE__ */ jsx8(
|
|
1218
1299
|
"span",
|
|
1219
1300
|
{
|
|
1220
1301
|
className: "lens-db__skeleton",
|
|
@@ -1227,9 +1308,9 @@ function IntegrationList(props) {
|
|
|
1227
1308
|
loadError,
|
|
1228
1309
|
onRetry && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1229
1310
|
" ",
|
|
1230
|
-
/* @__PURE__ */
|
|
1311
|
+
/* @__PURE__ */ jsx8("button", { type: "button", className: "lens-db__link-btn", onClick: onRetry, children: "Retry" })
|
|
1231
1312
|
] })
|
|
1232
|
-
] }) : /* @__PURE__ */
|
|
1313
|
+
] }) : /* @__PURE__ */ jsx8(
|
|
1233
1314
|
"div",
|
|
1234
1315
|
{
|
|
1235
1316
|
className: "lens-db__intlist-rows",
|
|
@@ -1250,11 +1331,11 @@ function IntegrationList(props) {
|
|
|
1250
1331
|
{
|
|
1251
1332
|
className: clsx_default("lens-db__introw", active && "lens-db__introw--active"),
|
|
1252
1333
|
children: [
|
|
1253
|
-
/* @__PURE__ */
|
|
1334
|
+
/* @__PURE__ */ jsx8("span", { className: "lens-db__intmark", "aria-hidden": true, children: /* @__PURE__ */ jsx8(Icon, { size: 20 }) }),
|
|
1254
1335
|
/* @__PURE__ */ jsxs5("span", { className: "lens-db__intbody", children: [
|
|
1255
|
-
/* @__PURE__ */
|
|
1336
|
+
/* @__PURE__ */ jsx8("span", { className: "lens-db__intname", children: meta.name }),
|
|
1256
1337
|
/* @__PURE__ */ jsxs5("span", { className: "lens-db__intstatus", children: [
|
|
1257
|
-
/* @__PURE__ */
|
|
1338
|
+
/* @__PURE__ */ jsx8(
|
|
1258
1339
|
"span",
|
|
1259
1340
|
{
|
|
1260
1341
|
className: clsx_default(
|
|
@@ -1264,7 +1345,7 @@ function IntegrationList(props) {
|
|
|
1264
1345
|
"aria-hidden": true
|
|
1265
1346
|
}
|
|
1266
1347
|
),
|
|
1267
|
-
/* @__PURE__ */
|
|
1348
|
+
/* @__PURE__ */ jsx8("span", { children: statusLine })
|
|
1268
1349
|
] })
|
|
1269
1350
|
] }),
|
|
1270
1351
|
/* @__PURE__ */ jsxs5("span", { className: "lens-db__introw-right", children: [
|
|
@@ -1282,14 +1363,14 @@ function IntegrationList(props) {
|
|
|
1282
1363
|
disabled: isBusy || active,
|
|
1283
1364
|
onClick: () => !active && onActivate(provider),
|
|
1284
1365
|
children: [
|
|
1285
|
-
/* @__PURE__ */
|
|
1366
|
+
/* @__PURE__ */ jsx8("span", { className: "lens-db__intradio-dot", children: active && /* @__PURE__ */ jsx8("span", { className: "lens-db__intradio-fill" }) }),
|
|
1286
1367
|
"Destination"
|
|
1287
1368
|
]
|
|
1288
1369
|
}
|
|
1289
1370
|
),
|
|
1290
1371
|
status === "pending" && /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
1291
|
-
/* @__PURE__ */
|
|
1292
|
-
/* @__PURE__ */
|
|
1372
|
+
/* @__PURE__ */ jsx8("span", { className: "lens-db__intwait", children: "waiting for authorization\u2026" }),
|
|
1373
|
+
/* @__PURE__ */ jsx8(
|
|
1293
1374
|
"button",
|
|
1294
1375
|
{
|
|
1295
1376
|
type: "button",
|
|
@@ -1300,7 +1381,7 @@ function IntegrationList(props) {
|
|
|
1300
1381
|
}
|
|
1301
1382
|
)
|
|
1302
1383
|
] }),
|
|
1303
|
-
status === "disconnected" && /* @__PURE__ */
|
|
1384
|
+
status === "disconnected" && /* @__PURE__ */ jsx8(
|
|
1304
1385
|
"button",
|
|
1305
1386
|
{
|
|
1306
1387
|
type: "button",
|
|
@@ -1310,7 +1391,7 @@ function IntegrationList(props) {
|
|
|
1310
1391
|
children: isBusy ? "Opening\u2026" : "Connect"
|
|
1311
1392
|
}
|
|
1312
1393
|
),
|
|
1313
|
-
status !== "disconnected" && /* @__PURE__ */
|
|
1394
|
+
status !== "disconnected" && /* @__PURE__ */ jsx8(
|
|
1314
1395
|
"button",
|
|
1315
1396
|
{
|
|
1316
1397
|
type: "button",
|
|
@@ -1322,14 +1403,15 @@ function IntegrationList(props) {
|
|
|
1322
1403
|
}
|
|
1323
1404
|
)
|
|
1324
1405
|
] }),
|
|
1325
|
-
isConnected && /* @__PURE__ */
|
|
1406
|
+
isConnected && /* @__PURE__ */ jsx8(
|
|
1326
1407
|
IntegrationConfigLine,
|
|
1327
1408
|
{
|
|
1328
1409
|
provider,
|
|
1329
1410
|
config: integration?.config ?? {},
|
|
1330
1411
|
active,
|
|
1331
1412
|
disabled: isBusy,
|
|
1332
|
-
onSave: (config) => onSaveConfig(provider, config)
|
|
1413
|
+
onSave: (config) => onSaveConfig(provider, config),
|
|
1414
|
+
loadOptions
|
|
1333
1415
|
}
|
|
1334
1416
|
)
|
|
1335
1417
|
]
|
|
@@ -1346,23 +1428,38 @@ function IntegrationConfigLine({
|
|
|
1346
1428
|
config,
|
|
1347
1429
|
active,
|
|
1348
1430
|
disabled,
|
|
1349
|
-
onSave
|
|
1431
|
+
onSave,
|
|
1432
|
+
loadOptions
|
|
1350
1433
|
}) {
|
|
1351
1434
|
const field = CONFIG_FIELD[provider];
|
|
1352
1435
|
const saved = config[field.key] ?? "";
|
|
1353
1436
|
const [value, setValue] = useState5(saved);
|
|
1354
1437
|
const [busy, setBusy] = useState5(false);
|
|
1355
1438
|
const [done, setDone] = useState5(false);
|
|
1439
|
+
const [options, setOptions] = useState5({ status: "idle" });
|
|
1356
1440
|
useEffect4(() => {
|
|
1357
1441
|
setValue(saved);
|
|
1358
1442
|
}, [saved]);
|
|
1443
|
+
useEffect4(() => {
|
|
1444
|
+
if (!loadOptions) return;
|
|
1445
|
+
let cancelled = false;
|
|
1446
|
+
setOptions({ status: "loading" });
|
|
1447
|
+
loadOptions(provider).then((res) => {
|
|
1448
|
+
if (!cancelled) setOptions({ status: "ready", options: res.options });
|
|
1449
|
+
}).catch(() => {
|
|
1450
|
+
if (!cancelled) setOptions({ status: "error" });
|
|
1451
|
+
});
|
|
1452
|
+
return () => {
|
|
1453
|
+
cancelled = true;
|
|
1454
|
+
};
|
|
1455
|
+
}, [loadOptions, provider]);
|
|
1359
1456
|
const dirty = value.trim() !== saved;
|
|
1360
|
-
async function
|
|
1361
|
-
if (busy
|
|
1457
|
+
async function commit(raw) {
|
|
1458
|
+
if (busy) return;
|
|
1362
1459
|
setBusy(true);
|
|
1363
1460
|
setDone(false);
|
|
1364
1461
|
const next = { ...config };
|
|
1365
|
-
next[field.key] =
|
|
1462
|
+
next[field.key] = raw.trim() || void 0;
|
|
1366
1463
|
try {
|
|
1367
1464
|
await onSave(next);
|
|
1368
1465
|
setDone(true);
|
|
@@ -1372,11 +1469,29 @@ function IntegrationConfigLine({
|
|
|
1372
1469
|
setBusy(false);
|
|
1373
1470
|
}
|
|
1374
1471
|
}
|
|
1472
|
+
const saveText = () => {
|
|
1473
|
+
if (dirty) void commit(value);
|
|
1474
|
+
};
|
|
1475
|
+
const onSelect = (next) => {
|
|
1476
|
+
setValue(next);
|
|
1477
|
+
void commit(next);
|
|
1478
|
+
};
|
|
1375
1479
|
const showHint = Boolean(field.requiredHint) && active && !saved;
|
|
1480
|
+
const useSelect = Boolean(loadOptions) && (options.status === "loading" || options.status === "ready");
|
|
1376
1481
|
return /* @__PURE__ */ jsxs5("div", { className: "lens-db__intconfig", children: [
|
|
1377
1482
|
/* @__PURE__ */ jsxs5("label", { className: "lens-db__intconfig-field", children: [
|
|
1378
|
-
/* @__PURE__ */
|
|
1379
|
-
/* @__PURE__ */
|
|
1483
|
+
/* @__PURE__ */ jsx8("span", { className: "lens-db__intconfig-label", children: field.label }),
|
|
1484
|
+
useSelect ? /* @__PURE__ */ jsx8(
|
|
1485
|
+
ConfigSelect,
|
|
1486
|
+
{
|
|
1487
|
+
provider,
|
|
1488
|
+
value,
|
|
1489
|
+
options: options.status === "ready" ? options.options : null,
|
|
1490
|
+
loading: options.status === "loading",
|
|
1491
|
+
disabled: disabled || busy,
|
|
1492
|
+
onChange: onSelect
|
|
1493
|
+
}
|
|
1494
|
+
) : /* @__PURE__ */ jsx8(
|
|
1380
1495
|
"input",
|
|
1381
1496
|
{
|
|
1382
1497
|
className: "lens-db__intconfig-input",
|
|
@@ -1391,25 +1506,55 @@ function IntegrationConfigLine({
|
|
|
1391
1506
|
onKeyDown: (e) => {
|
|
1392
1507
|
if (e.key === "Enter") {
|
|
1393
1508
|
e.preventDefault();
|
|
1394
|
-
|
|
1509
|
+
saveText();
|
|
1395
1510
|
}
|
|
1396
1511
|
}
|
|
1397
1512
|
}
|
|
1398
1513
|
)
|
|
1399
1514
|
] }),
|
|
1400
|
-
busy ? /* @__PURE__ */
|
|
1515
|
+
busy ? /* @__PURE__ */ jsx8("span", { className: "lens-db__intconfig-busy", "aria-live": "polite", "aria-label": "Saving", children: /* @__PURE__ */ jsx8("span", { className: "lens-db__spinner", "aria-hidden": true }) }) : done ? /* @__PURE__ */ jsx8("span", { className: "lens-db__intconfig-done", "aria-live": "polite", "aria-label": "Saved", children: /* @__PURE__ */ jsx8(IconCheck, { size: 14 }) }) : !useSelect && dirty ? /* @__PURE__ */ jsx8(
|
|
1401
1516
|
"button",
|
|
1402
1517
|
{
|
|
1403
1518
|
type: "button",
|
|
1404
1519
|
className: "lens-db__btn lens-db__btn--sm",
|
|
1405
1520
|
disabled,
|
|
1406
|
-
onClick:
|
|
1521
|
+
onClick: saveText,
|
|
1407
1522
|
children: "Save"
|
|
1408
1523
|
}
|
|
1409
1524
|
) : null,
|
|
1410
|
-
|
|
1525
|
+
!useSelect && options.status === "error" && loadOptions && /* @__PURE__ */ jsx8("span", { className: "lens-db__intconfig-note", children: "Couldn't load options \u2014 enter manually." }),
|
|
1526
|
+
showHint && /* @__PURE__ */ jsx8("span", { className: "lens-db__intconfig-hint", children: field.requiredHint })
|
|
1411
1527
|
] });
|
|
1412
1528
|
}
|
|
1529
|
+
function ConfigSelect({
|
|
1530
|
+
provider,
|
|
1531
|
+
value,
|
|
1532
|
+
options,
|
|
1533
|
+
loading,
|
|
1534
|
+
disabled,
|
|
1535
|
+
onChange
|
|
1536
|
+
}) {
|
|
1537
|
+
if (loading || !options) {
|
|
1538
|
+
return /* @__PURE__ */ jsx8("select", { className: "lens-db__intconfig-select", disabled: true, "aria-label": "Loading options", children: /* @__PURE__ */ jsx8("option", { children: "Loading\u2026" }) });
|
|
1539
|
+
}
|
|
1540
|
+
const placeholderDisabled = provider !== "linear";
|
|
1541
|
+
const known = new Set(options.map((o) => o.value));
|
|
1542
|
+
const orphan = value && !known.has(value) ? value : null;
|
|
1543
|
+
return /* @__PURE__ */ jsxs5(
|
|
1544
|
+
"select",
|
|
1545
|
+
{
|
|
1546
|
+
className: "lens-db__intconfig-select",
|
|
1547
|
+
value,
|
|
1548
|
+
disabled,
|
|
1549
|
+
onChange: (e) => onChange(e.target.value),
|
|
1550
|
+
children: [
|
|
1551
|
+
/* @__PURE__ */ jsx8("option", { value: "", disabled: placeholderDisabled, children: SELECT_PLACEHOLDER[provider] }),
|
|
1552
|
+
orphan && /* @__PURE__ */ jsx8("option", { value: orphan, children: orphan }),
|
|
1553
|
+
options.map((o) => /* @__PURE__ */ jsx8("option", { value: o.value, children: o.label }, o.value))
|
|
1554
|
+
]
|
|
1555
|
+
}
|
|
1556
|
+
);
|
|
1557
|
+
}
|
|
1413
1558
|
var PROVIDER_NAME = {
|
|
1414
1559
|
linear: "Linear",
|
|
1415
1560
|
jira: "Jira",
|
|
@@ -1493,7 +1638,7 @@ function IntegrationSettings(props) {
|
|
|
1493
1638
|
setBusy(null);
|
|
1494
1639
|
}
|
|
1495
1640
|
}
|
|
1496
|
-
return /* @__PURE__ */
|
|
1641
|
+
return /* @__PURE__ */ jsx9("div", { className: clsx_default("lens-db", props.className), children: /* @__PURE__ */ jsx9(
|
|
1497
1642
|
IntegrationList,
|
|
1498
1643
|
{
|
|
1499
1644
|
integrations,
|
|
@@ -1509,56 +1654,11 @@ function IntegrationSettings(props) {
|
|
|
1509
1654
|
onActivate: (p) => void activate(p),
|
|
1510
1655
|
onDisconnect: (p) => void disconnect(p),
|
|
1511
1656
|
onCompleteDev: (p) => void completeDev(p),
|
|
1512
|
-
onSaveConfig: saveConfig
|
|
1657
|
+
onSaveConfig: saveConfig,
|
|
1658
|
+
loadOptions: (p) => api.getIntegrationOptions(p)
|
|
1513
1659
|
}
|
|
1514
1660
|
) });
|
|
1515
1661
|
}
|
|
1516
|
-
var MARKUP_RULES = [
|
|
1517
|
-
{ cls: "com", re: /<!--[\s\S]*?-->|\/\*[\s\S]*?\*\/|\/\/[^\n]*/y },
|
|
1518
|
-
{ cls: "str", re: /"(?:[^"\\\n]|\\.)*"|'(?:[^'\\\n]|\\.)*'|`(?:[^`\\]|\\.)*`/y },
|
|
1519
|
-
{ cls: "tag", re: /<\/?[a-zA-Z][\w.-]*|\/>|>/y },
|
|
1520
|
-
{
|
|
1521
|
-
cls: "kw",
|
|
1522
|
-
re: /\b(?:import|from|export|function|return|const|let|var|async|await|new|window|default)\b/y
|
|
1523
|
-
},
|
|
1524
|
-
{ cls: "attr", re: /\b[a-zA-Z_][\w-]*(?==)/y },
|
|
1525
|
-
{ cls: "num", re: /\b\d+(?:\.\d+)?\b/y }
|
|
1526
|
-
];
|
|
1527
|
-
var ENV_RULES = [
|
|
1528
|
-
{ cls: "com", re: /#[^\n]*/y },
|
|
1529
|
-
{ cls: "attr", re: /^[A-Z][A-Z0-9_]*(?==)/my },
|
|
1530
|
-
{ cls: "str", re: /(?<==)[^\n]+/y }
|
|
1531
|
-
];
|
|
1532
|
-
function highlightCode(code, lang) {
|
|
1533
|
-
const rules = lang === "env" ? ENV_RULES : MARKUP_RULES;
|
|
1534
|
-
const out = [];
|
|
1535
|
-
let pos = 0;
|
|
1536
|
-
let plainStart = 0;
|
|
1537
|
-
let key = 0;
|
|
1538
|
-
const flushPlain = (until) => {
|
|
1539
|
-
if (until > plainStart) out.push(code.slice(plainStart, until));
|
|
1540
|
-
};
|
|
1541
|
-
while (pos < code.length) {
|
|
1542
|
-
let matched = false;
|
|
1543
|
-
for (const rule of rules) {
|
|
1544
|
-
rule.re.lastIndex = pos;
|
|
1545
|
-
const m = rule.re.exec(code);
|
|
1546
|
-
if (m && m[0].length > 0) {
|
|
1547
|
-
flushPlain(pos);
|
|
1548
|
-
out.push(
|
|
1549
|
-
/* @__PURE__ */ jsx9("span", { className: `lens-db__tok-${rule.cls}`, children: m[0] }, key++)
|
|
1550
|
-
);
|
|
1551
|
-
pos += m[0].length;
|
|
1552
|
-
plainStart = pos;
|
|
1553
|
-
matched = true;
|
|
1554
|
-
break;
|
|
1555
|
-
}
|
|
1556
|
-
}
|
|
1557
|
-
if (!matched) pos += 1;
|
|
1558
|
-
}
|
|
1559
|
-
flushPlain(code.length);
|
|
1560
|
-
return out;
|
|
1561
|
-
}
|
|
1562
1662
|
var STEPS = ["Project", "Destination", "Asset storage", "Install"];
|
|
1563
1663
|
var PROVIDER_NAME2 = {
|
|
1564
1664
|
linear: "Linear",
|
|
@@ -1924,7 +2024,8 @@ export function App() {
|
|
|
1924
2024
|
onActivate: (p) => void activate(p),
|
|
1925
2025
|
onDisconnect: (p) => void disconnect(p),
|
|
1926
2026
|
onCompleteDev: (p) => void completeDev(p),
|
|
1927
|
-
onSaveConfig: saveConfig
|
|
2027
|
+
onSaveConfig: saveConfig,
|
|
2028
|
+
loadOptions: (p) => api.getIntegrationOptions(p)
|
|
1928
2029
|
}
|
|
1929
2030
|
),
|
|
1930
2031
|
/* @__PURE__ */ jsx10("p", { className: "lens-db__hint", children: activeProvider ? `Issues will route to ${providerLabel2(activeProvider)}.` : "No destination selected yet \u2014 issues will queue until you pick one." })
|
|
@@ -2071,20 +2172,263 @@ export function App() {
|
|
|
2071
2172
|
] })
|
|
2072
2173
|
] });
|
|
2073
2174
|
}
|
|
2175
|
+
var HOSTED_LENS_API_URL = "https://api-lens.meritt.app";
|
|
2176
|
+
var LensConfigContext = createContext2(null);
|
|
2177
|
+
function LensProvider({
|
|
2178
|
+
config,
|
|
2179
|
+
children
|
|
2180
|
+
}) {
|
|
2181
|
+
return /* @__PURE__ */ jsx11(LensConfigContext.Provider, { value: config, children });
|
|
2182
|
+
}
|
|
2183
|
+
var TABS = [
|
|
2184
|
+
{ id: "reports", label: "Issue Reports", Icon: IconBug },
|
|
2185
|
+
{ id: "integrations", label: "Integrations", Icon: IconPlug },
|
|
2186
|
+
{ id: "setup", label: "Setup", Icon: IconRocket }
|
|
2187
|
+
];
|
|
2188
|
+
function readInitialParams() {
|
|
2189
|
+
if (typeof window === "undefined") return { report: null, project: null };
|
|
2190
|
+
const params = new URLSearchParams(window.location.search);
|
|
2191
|
+
return { report: params.get("report"), project: params.get("project") };
|
|
2192
|
+
}
|
|
2193
|
+
function syncReportParam(reportId) {
|
|
2194
|
+
if (typeof window === "undefined") return;
|
|
2195
|
+
try {
|
|
2196
|
+
const params = new URLSearchParams(window.location.search);
|
|
2197
|
+
if (reportId) params.set("report", reportId);
|
|
2198
|
+
else params.delete("report");
|
|
2199
|
+
const qs = params.toString();
|
|
2200
|
+
const url = window.location.pathname + (qs ? `?${qs}` : "") + window.location.hash;
|
|
2201
|
+
window.history.replaceState(window.history.state, "", url);
|
|
2202
|
+
} catch {
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
function CopyButton2({ value, label = "Copy" }) {
|
|
2206
|
+
const [copied, setCopied] = useState8(false);
|
|
2207
|
+
return /* @__PURE__ */ jsxs7(
|
|
2208
|
+
"button",
|
|
2209
|
+
{
|
|
2210
|
+
type: "button",
|
|
2211
|
+
className: clsx_default("lens-db__copy-btn", copied && "lens-db__copy-btn--done"),
|
|
2212
|
+
"aria-label": copied ? "Copied" : label,
|
|
2213
|
+
onClick: () => {
|
|
2214
|
+
void navigator.clipboard?.writeText(value).then(
|
|
2215
|
+
() => {
|
|
2216
|
+
setCopied(true);
|
|
2217
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
2218
|
+
},
|
|
2219
|
+
() => void 0
|
|
2220
|
+
);
|
|
2221
|
+
},
|
|
2222
|
+
children: [
|
|
2223
|
+
copied ? /* @__PURE__ */ jsx11(IconCheck, { size: 14 }) : /* @__PURE__ */ jsx11(IconCopy, { size: 14 }),
|
|
2224
|
+
copied ? "Copied" : label
|
|
2225
|
+
]
|
|
2226
|
+
}
|
|
2227
|
+
);
|
|
2228
|
+
}
|
|
2229
|
+
function LensAdmin(props) {
|
|
2230
|
+
const contextConfig = useContext2(LensConfigContext);
|
|
2231
|
+
const {
|
|
2232
|
+
config = contextConfig ?? void 0,
|
|
2233
|
+
baseUrl = "/api/lens",
|
|
2234
|
+
projectsUrl = "/api/lens-projects",
|
|
2235
|
+
projects: propProjects,
|
|
2236
|
+
defaultTab = "reports",
|
|
2237
|
+
theme,
|
|
2238
|
+
className
|
|
2239
|
+
} = props;
|
|
2240
|
+
const direct = !!config;
|
|
2241
|
+
const staticProjects = useMemo(
|
|
2242
|
+
() => config?.projects.map(({ name, accessId }) => ({ name, accessId })) ?? propProjects,
|
|
2243
|
+
[config, propProjects]
|
|
2244
|
+
);
|
|
2245
|
+
const wizardSecretRef = useRef4("");
|
|
2246
|
+
const activeProjectRef = useRef4(null);
|
|
2247
|
+
const configRef = useRef4(config);
|
|
2248
|
+
configRef.current = config;
|
|
2249
|
+
const api = useMemo(
|
|
2250
|
+
() => direct ? createLensApi({
|
|
2251
|
+
baseUrl: configRef.current?.apiUrl ?? HOSTED_LENS_API_URL,
|
|
2252
|
+
getToken: () => {
|
|
2253
|
+
const cfg = configRef.current;
|
|
2254
|
+
const active = cfg?.projects.find((p) => p.accessId === activeProjectRef.current);
|
|
2255
|
+
return wizardSecretRef.current || active?.secretKey || cfg?.adminToken || "";
|
|
2256
|
+
}
|
|
2257
|
+
}) : createLensApi({
|
|
2258
|
+
baseUrl,
|
|
2259
|
+
tokenHeader: "x-lens-token",
|
|
2260
|
+
getToken: () => wizardSecretRef.current,
|
|
2261
|
+
project: () => activeProjectRef.current
|
|
2262
|
+
}),
|
|
2263
|
+
[direct, baseUrl]
|
|
2264
|
+
);
|
|
2265
|
+
const [initialParams] = useState8(readInitialParams);
|
|
2266
|
+
const [projects, setProjects] = useState8(staticProjects ?? []);
|
|
2267
|
+
const [loadingProjects, setLoadingProjects] = useState8(!staticProjects);
|
|
2268
|
+
const [activeAccessId, setActiveAccessId] = useState8(null);
|
|
2269
|
+
const [firstReportId, setFirstReportId] = useState8(initialParams.report);
|
|
2270
|
+
useEffect7(() => {
|
|
2271
|
+
if (staticProjects) return;
|
|
2272
|
+
let active = true;
|
|
2273
|
+
setLoadingProjects(true);
|
|
2274
|
+
fetch(projectsUrl, { headers: { Accept: "application/json" } }).then((res) => res.ok ? res.json() : Promise.reject(new Error(String(res.status)))).then((body) => {
|
|
2275
|
+
if (!active) return;
|
|
2276
|
+
const list = body && typeof body === "object" && Array.isArray(body.projects) ? body.projects.filter(
|
|
2277
|
+
(p) => !!p && typeof p === "object" && typeof p.name === "string" && typeof p.accessId === "string"
|
|
2278
|
+
) : [];
|
|
2279
|
+
setProjects(list);
|
|
2280
|
+
setLoadingProjects(false);
|
|
2281
|
+
}).catch(() => {
|
|
2282
|
+
if (!active) return;
|
|
2283
|
+
setProjects([]);
|
|
2284
|
+
setLoadingProjects(false);
|
|
2285
|
+
});
|
|
2286
|
+
return () => {
|
|
2287
|
+
active = false;
|
|
2288
|
+
};
|
|
2289
|
+
}, [projectsUrl, staticProjects]);
|
|
2290
|
+
useEffect7(() => {
|
|
2291
|
+
const first = projects[0];
|
|
2292
|
+
if (!first) {
|
|
2293
|
+
setActiveAccessId(null);
|
|
2294
|
+
return;
|
|
2295
|
+
}
|
|
2296
|
+
setActiveAccessId((current) => {
|
|
2297
|
+
if (current && projects.some((p) => p.accessId === current)) return current;
|
|
2298
|
+
const fromUrl = initialParams.project && projects.find((p) => p.accessId === initialParams.project);
|
|
2299
|
+
return fromUrl ? fromUrl.accessId : first.accessId;
|
|
2300
|
+
});
|
|
2301
|
+
}, [projects, initialParams.project]);
|
|
2302
|
+
if (activeAccessId) activeProjectRef.current = activeAccessId;
|
|
2303
|
+
const provisioning = !loadingProjects && projects.length === 0;
|
|
2304
|
+
function switchProject(accessId) {
|
|
2305
|
+
setFirstReportId(null);
|
|
2306
|
+
setActiveAccessId(accessId);
|
|
2307
|
+
}
|
|
2308
|
+
return /* @__PURE__ */ jsx11("div", { className: clsx_default("lens-db", "lens-db__shell", className), children: /* @__PURE__ */ jsx11(LensDashboardProvider, { api, theme, children: loadingProjects ? /* @__PURE__ */ jsx11("div", { className: "lens-db__shell-loading", children: "Loading\u2026" }) : provisioning ? /* @__PURE__ */ jsx11(
|
|
2309
|
+
Provisioning,
|
|
2310
|
+
{
|
|
2311
|
+
onProjectCreated: (res) => {
|
|
2312
|
+
wizardSecretRef.current = res.accessSecret;
|
|
2313
|
+
activeProjectRef.current = res.accessId;
|
|
2314
|
+
}
|
|
2315
|
+
}
|
|
2316
|
+
) : /* @__PURE__ */ jsx11(
|
|
2317
|
+
DashboardSurface,
|
|
2318
|
+
{
|
|
2319
|
+
projects,
|
|
2320
|
+
activeAccessId,
|
|
2321
|
+
onSwitchProject: switchProject,
|
|
2322
|
+
defaultTab,
|
|
2323
|
+
initialReportId: firstReportId
|
|
2324
|
+
},
|
|
2325
|
+
activeAccessId ?? "none"
|
|
2326
|
+
) }) });
|
|
2327
|
+
}
|
|
2328
|
+
function Provisioning({
|
|
2329
|
+
onProjectCreated
|
|
2330
|
+
}) {
|
|
2331
|
+
const [minted, setMinted] = useState8(
|
|
2332
|
+
null
|
|
2333
|
+
);
|
|
2334
|
+
const envBlock = minted ? `LENS_PROJECTS=[${JSON.stringify({
|
|
2335
|
+
name: minted.name,
|
|
2336
|
+
accessId: minted.accessId,
|
|
2337
|
+
secretKey: minted.secretKey
|
|
2338
|
+
})}]` : "";
|
|
2339
|
+
return /* @__PURE__ */ jsxs7("div", { className: "lens-db__shell-provision", children: [
|
|
2340
|
+
/* @__PURE__ */ jsxs7("div", { className: "lens-db__shell-notice", children: [
|
|
2341
|
+
/* @__PURE__ */ jsx11("p", { className: "lens-db__shell-notice-title", children: "No Lens projects configured" }),
|
|
2342
|
+
/* @__PURE__ */ jsx11("p", { className: "lens-db__muted", children: "Create your first project below. The minted access secret is shown once \u2014 add it to your server environment to finish wiring up the proxy." })
|
|
2343
|
+
] }),
|
|
2344
|
+
/* @__PURE__ */ jsx11(
|
|
2345
|
+
OnboardingWizard,
|
|
2346
|
+
{
|
|
2347
|
+
onProjectCreated: (res) => {
|
|
2348
|
+
onProjectCreated(res);
|
|
2349
|
+
setMinted({
|
|
2350
|
+
name: res.project.name,
|
|
2351
|
+
accessId: res.accessId,
|
|
2352
|
+
secretKey: res.accessSecret
|
|
2353
|
+
});
|
|
2354
|
+
}
|
|
2355
|
+
}
|
|
2356
|
+
),
|
|
2357
|
+
minted && /* @__PURE__ */ jsxs7("div", { className: "lens-db__shell-env", children: [
|
|
2358
|
+
/* @__PURE__ */ jsx11("p", { className: "lens-db__label", children: "Add this to your server env and restart \u2014 the proxy reads it to route requests to the new project:" }),
|
|
2359
|
+
/* @__PURE__ */ jsxs7("div", { className: "lens-db__codeblock", children: [
|
|
2360
|
+
/* @__PURE__ */ jsx11("pre", { className: "lens-db__pre", children: highlightCode(envBlock, "env") }),
|
|
2361
|
+
/* @__PURE__ */ jsx11(CopyButton2, { value: envBlock, label: "Copy" })
|
|
2362
|
+
] })
|
|
2363
|
+
] })
|
|
2364
|
+
] });
|
|
2365
|
+
}
|
|
2366
|
+
function DashboardSurface({
|
|
2367
|
+
projects,
|
|
2368
|
+
activeAccessId,
|
|
2369
|
+
onSwitchProject,
|
|
2370
|
+
defaultTab,
|
|
2371
|
+
initialReportId
|
|
2372
|
+
}) {
|
|
2373
|
+
const [tab, setTab] = useState8(defaultTab);
|
|
2374
|
+
const [selected, setSelected] = useState8(initialReportId);
|
|
2375
|
+
useEffect7(() => {
|
|
2376
|
+
syncReportParam(selected);
|
|
2377
|
+
}, [selected]);
|
|
2378
|
+
const showSwitcher = projects.length > 1;
|
|
2379
|
+
return /* @__PURE__ */ jsxs7(Fragment5, { children: [
|
|
2380
|
+
/* @__PURE__ */ jsxs7("div", { className: "lens-db__shell-bar", children: [
|
|
2381
|
+
/* @__PURE__ */ jsx11("div", { className: "lens-db__shell-tabs", role: "tablist", "aria-label": "Lens sections", children: TABS.map(({ id, label, Icon }) => {
|
|
2382
|
+
const active = id === tab;
|
|
2383
|
+
return /* @__PURE__ */ jsxs7(
|
|
2384
|
+
"button",
|
|
2385
|
+
{
|
|
2386
|
+
type: "button",
|
|
2387
|
+
role: "tab",
|
|
2388
|
+
"aria-selected": active,
|
|
2389
|
+
className: clsx_default("lens-db__shell-tab", active && "lens-db__shell-tab--active"),
|
|
2390
|
+
onClick: () => setTab(id),
|
|
2391
|
+
children: [
|
|
2392
|
+
/* @__PURE__ */ jsx11(Icon, { size: 16 }),
|
|
2393
|
+
/* @__PURE__ */ jsx11("span", { className: "lens-db__shell-tab-label", children: label })
|
|
2394
|
+
]
|
|
2395
|
+
},
|
|
2396
|
+
id
|
|
2397
|
+
);
|
|
2398
|
+
}) }),
|
|
2399
|
+
showSwitcher && /* @__PURE__ */ jsx11("div", { className: "lens-db__shell-switcher", children: /* @__PURE__ */ jsx11(
|
|
2400
|
+
"select",
|
|
2401
|
+
{
|
|
2402
|
+
className: "lens-db__shell-select",
|
|
2403
|
+
"aria-label": "Switch project",
|
|
2404
|
+
value: activeAccessId ?? "",
|
|
2405
|
+
onChange: (e) => onSwitchProject(e.target.value),
|
|
2406
|
+
children: projects.map((p) => /* @__PURE__ */ jsx11("option", { value: p.accessId, children: p.name }, p.accessId))
|
|
2407
|
+
}
|
|
2408
|
+
) })
|
|
2409
|
+
] }),
|
|
2410
|
+
/* @__PURE__ */ jsxs7("div", { className: "lens-db__shell-content", children: [
|
|
2411
|
+
tab === "reports" && (selected ? /* @__PURE__ */ jsx11(ReportDetail, { reportId: selected, onClose: () => setSelected(null) }) : /* @__PURE__ */ jsx11(ReportsTable, { onSelect: setSelected })),
|
|
2412
|
+
tab === "integrations" && /* @__PURE__ */ jsx11(IntegrationSettings, {}),
|
|
2413
|
+
tab === "setup" && /* @__PURE__ */ jsx11(OnboardingWizard, { existingProject: true })
|
|
2414
|
+
] })
|
|
2415
|
+
] });
|
|
2416
|
+
}
|
|
2417
|
+
var LensDashboard = LensAdmin;
|
|
2074
2418
|
function parseOrigins2(raw) {
|
|
2075
2419
|
return raw.split("\n").map((line) => line.trim()).filter((line) => line.length > 0);
|
|
2076
2420
|
}
|
|
2077
2421
|
function ProjectSettings(props) {
|
|
2078
2422
|
const api = useLensApi();
|
|
2079
2423
|
const { data, error, loading, reload } = useAsync(() => api.getProject(), []);
|
|
2080
|
-
const [name, setName] =
|
|
2081
|
-
const [origins, setOrigins] =
|
|
2082
|
-
const [dashboardUrl, setDashboardUrl] =
|
|
2083
|
-
const [saving, setSaving] =
|
|
2084
|
-
const [saveError, setSaveError] =
|
|
2085
|
-
const [saved, setSaved] =
|
|
2086
|
-
const [copied, setCopied] =
|
|
2087
|
-
|
|
2424
|
+
const [name, setName] = useState9("");
|
|
2425
|
+
const [origins, setOrigins] = useState9("");
|
|
2426
|
+
const [dashboardUrl, setDashboardUrl] = useState9("");
|
|
2427
|
+
const [saving, setSaving] = useState9(false);
|
|
2428
|
+
const [saveError, setSaveError] = useState9(void 0);
|
|
2429
|
+
const [saved, setSaved] = useState9(false);
|
|
2430
|
+
const [copied, setCopied] = useState9(false);
|
|
2431
|
+
useEffect8(() => {
|
|
2088
2432
|
if (!data) return;
|
|
2089
2433
|
setName(data.name);
|
|
2090
2434
|
setOrigins(data.allowedOrigins.join("\n"));
|
|
@@ -2116,22 +2460,22 @@ function ProjectSettings(props) {
|
|
|
2116
2460
|
}
|
|
2117
2461
|
}
|
|
2118
2462
|
const accessId = data?.accessId ?? "";
|
|
2119
|
-
return /* @__PURE__ */
|
|
2120
|
-
/* @__PURE__ */
|
|
2121
|
-
/* @__PURE__ */
|
|
2122
|
-
/* @__PURE__ */
|
|
2463
|
+
return /* @__PURE__ */ jsxs8("div", { className: clsx_default("lens-db", "lens-db__panel", props.className), children: [
|
|
2464
|
+
/* @__PURE__ */ jsxs8("div", { children: [
|
|
2465
|
+
/* @__PURE__ */ jsx12("h3", { className: "lens-db__wizard-title", children: "Project settings" }),
|
|
2466
|
+
/* @__PURE__ */ jsx12("p", { className: "lens-db__muted", children: "Update the project name and the origins allowed to submit reports." })
|
|
2123
2467
|
] }),
|
|
2124
|
-
loading && !data && /* @__PURE__ */
|
|
2125
|
-
error && !data && /* @__PURE__ */
|
|
2468
|
+
loading && !data && /* @__PURE__ */ jsx12("p", { className: "lens-db__muted", children: "Loading project\u2026" }),
|
|
2469
|
+
error && !data && /* @__PURE__ */ jsxs8("div", { className: "lens-db__error", children: [
|
|
2126
2470
|
"Failed to load project: ",
|
|
2127
2471
|
error.message,
|
|
2128
2472
|
" ",
|
|
2129
|
-
/* @__PURE__ */
|
|
2473
|
+
/* @__PURE__ */ jsx12("button", { type: "button", className: "lens-db__link-btn", onClick: reload, children: "Retry" })
|
|
2130
2474
|
] }),
|
|
2131
|
-
data && /* @__PURE__ */
|
|
2132
|
-
/* @__PURE__ */
|
|
2133
|
-
/* @__PURE__ */
|
|
2134
|
-
/* @__PURE__ */
|
|
2475
|
+
data && /* @__PURE__ */ jsxs8(Fragment6, { children: [
|
|
2476
|
+
/* @__PURE__ */ jsxs8("label", { className: "lens-db__field", children: [
|
|
2477
|
+
/* @__PURE__ */ jsx12("span", { className: "lens-db__label", children: "Project name" }),
|
|
2478
|
+
/* @__PURE__ */ jsx12(
|
|
2135
2479
|
"input",
|
|
2136
2480
|
{
|
|
2137
2481
|
className: "lens-db__input",
|
|
@@ -2143,9 +2487,9 @@ function ProjectSettings(props) {
|
|
|
2143
2487
|
}
|
|
2144
2488
|
)
|
|
2145
2489
|
] }),
|
|
2146
|
-
/* @__PURE__ */
|
|
2147
|
-
/* @__PURE__ */
|
|
2148
|
-
/* @__PURE__ */
|
|
2490
|
+
/* @__PURE__ */ jsxs8("label", { className: "lens-db__field", children: [
|
|
2491
|
+
/* @__PURE__ */ jsx12("span", { className: "lens-db__label", children: "Allowed origins" }),
|
|
2492
|
+
/* @__PURE__ */ jsx12(
|
|
2149
2493
|
"textarea",
|
|
2150
2494
|
{
|
|
2151
2495
|
className: "lens-db__input lens-db__textarea",
|
|
@@ -2156,11 +2500,11 @@ function ProjectSettings(props) {
|
|
|
2156
2500
|
onChange: (e) => setOrigins(e.target.value)
|
|
2157
2501
|
}
|
|
2158
2502
|
),
|
|
2159
|
-
/* @__PURE__ */
|
|
2503
|
+
/* @__PURE__ */ jsx12("span", { className: "lens-db__hint", children: "One origin per line." })
|
|
2160
2504
|
] }),
|
|
2161
|
-
/* @__PURE__ */
|
|
2162
|
-
/* @__PURE__ */
|
|
2163
|
-
/* @__PURE__ */
|
|
2505
|
+
/* @__PURE__ */ jsxs8("label", { className: "lens-db__field", children: [
|
|
2506
|
+
/* @__PURE__ */ jsx12("span", { className: "lens-db__label", children: "Dashboard URL" }),
|
|
2507
|
+
/* @__PURE__ */ jsx12(
|
|
2164
2508
|
"input",
|
|
2165
2509
|
{
|
|
2166
2510
|
className: "lens-db__input",
|
|
@@ -2171,13 +2515,13 @@ function ProjectSettings(props) {
|
|
|
2171
2515
|
onChange: (e) => setDashboardUrl(e.target.value)
|
|
2172
2516
|
}
|
|
2173
2517
|
),
|
|
2174
|
-
/* @__PURE__ */
|
|
2518
|
+
/* @__PURE__ */ jsx12("span", { className: "lens-db__hint", children: "Issues link reports back to this page." })
|
|
2175
2519
|
] }),
|
|
2176
|
-
/* @__PURE__ */
|
|
2177
|
-
/* @__PURE__ */
|
|
2178
|
-
/* @__PURE__ */
|
|
2179
|
-
/* @__PURE__ */
|
|
2180
|
-
/* @__PURE__ */
|
|
2520
|
+
/* @__PURE__ */ jsxs8("div", { className: "lens-db__field", children: [
|
|
2521
|
+
/* @__PURE__ */ jsx12("span", { className: "lens-db__label", children: "Access ID" }),
|
|
2522
|
+
/* @__PURE__ */ jsxs8("div", { className: "lens-db__cred-row", children: [
|
|
2523
|
+
/* @__PURE__ */ jsx12("code", { className: "lens-db__code-inline", children: accessId }),
|
|
2524
|
+
/* @__PURE__ */ jsxs8(
|
|
2181
2525
|
"button",
|
|
2182
2526
|
{
|
|
2183
2527
|
type: "button",
|
|
@@ -2193,16 +2537,16 @@ function ProjectSettings(props) {
|
|
|
2193
2537
|
);
|
|
2194
2538
|
},
|
|
2195
2539
|
children: [
|
|
2196
|
-
copied ? /* @__PURE__ */
|
|
2540
|
+
copied ? /* @__PURE__ */ jsx12(IconCheck, { size: 14 }) : /* @__PURE__ */ jsx12(IconCopy, { size: 14 }),
|
|
2197
2541
|
copied ? "Copied" : "Copy"
|
|
2198
2542
|
]
|
|
2199
2543
|
}
|
|
2200
2544
|
)
|
|
2201
2545
|
] })
|
|
2202
2546
|
] }),
|
|
2203
|
-
saveError && /* @__PURE__ */
|
|
2204
|
-
/* @__PURE__ */
|
|
2205
|
-
/* @__PURE__ */
|
|
2547
|
+
saveError && /* @__PURE__ */ jsx12("div", { className: "lens-db__error", children: saveError }),
|
|
2548
|
+
/* @__PURE__ */ jsxs8("div", { className: "lens-db__panel-actions", children: [
|
|
2549
|
+
/* @__PURE__ */ jsx12(
|
|
2206
2550
|
"button",
|
|
2207
2551
|
{
|
|
2208
2552
|
type: "button",
|
|
@@ -2212,8 +2556,8 @@ function ProjectSettings(props) {
|
|
|
2212
2556
|
children: saving ? "Saving\u2026" : "Save"
|
|
2213
2557
|
}
|
|
2214
2558
|
),
|
|
2215
|
-
saved && /* @__PURE__ */
|
|
2216
|
-
/* @__PURE__ */
|
|
2559
|
+
saved && /* @__PURE__ */ jsxs8("span", { className: "lens-db__flash lens-db__flash--ok", children: [
|
|
2560
|
+
/* @__PURE__ */ jsx12(IconCheck, { size: 14 }),
|
|
2217
2561
|
"Saved"
|
|
2218
2562
|
] })
|
|
2219
2563
|
] })
|
|
@@ -2222,8 +2566,11 @@ function ProjectSettings(props) {
|
|
|
2222
2566
|
}
|
|
2223
2567
|
export {
|
|
2224
2568
|
IntegrationSettings,
|
|
2569
|
+
LensAdmin,
|
|
2225
2570
|
LensApiError,
|
|
2571
|
+
LensDashboard,
|
|
2226
2572
|
LensDashboardProvider,
|
|
2573
|
+
LensProvider,
|
|
2227
2574
|
OnboardingWizard,
|
|
2228
2575
|
ProjectSettings,
|
|
2229
2576
|
ReplayPlayer,
|