@mhosaic/feedback 0.35.0 → 0.37.0
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/dist/{chunk-557ACRBU.mjs → chunk-BQDUJOWL.mjs} +3 -2
- package/dist/{chunk-557ACRBU.mjs.map → chunk-BQDUJOWL.mjs.map} +1 -1
- package/dist/{chunk-A2TMODNI.mjs → chunk-C3ILJCVI.mjs} +256 -98
- package/dist/chunk-C3ILJCVI.mjs.map +1 -0
- package/dist/embed.min.js +53 -11
- package/dist/embed.min.js.map +1 -1
- package/dist/error-tracking.d.ts +1 -1
- package/dist/{index-Dp0nfVYj.d.ts → index-BRmQGB1a.d.ts} +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.mjs +1 -1
- package/dist/loader/react.d.ts +1 -1
- package/dist/loader/react.mjs +1 -1
- package/dist/loader.d.ts +1 -1
- package/dist/loader.min.js +1 -1
- package/dist/loader.min.js.map +1 -1
- package/dist/loader.mjs +1 -1
- package/dist/react.d.ts +2 -2
- package/dist/react.mjs +1 -1
- package/dist/replay.d.ts +1 -1
- package/dist/telemetry.d.ts +1 -1
- package/dist/{types-Cg1v8AbB.d.ts → types-C04JGBPo.d.ts} +10 -0
- package/dist/vue.d.ts +2 -2
- package/dist/vue.mjs +1 -1
- package/dist/webvitals.d.ts +1 -1
- package/dist/widget.min.js +54 -12
- package/dist/widget.min.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-A2TMODNI.mjs.map +0 -1
|
@@ -20,9 +20,7 @@ function assertSafeEndpoint(endpoint) {
|
|
|
20
20
|
try {
|
|
21
21
|
parsed = new URL(endpoint);
|
|
22
22
|
} catch {
|
|
23
|
-
throw new Error(
|
|
24
|
-
`[mhosaic-feedback] \`endpoint\` is not a valid URL: ${endpoint}`
|
|
25
|
-
);
|
|
23
|
+
throw new Error(`[mhosaic-feedback] \`endpoint\` is not a valid URL: ${endpoint}`);
|
|
26
24
|
}
|
|
27
25
|
if (parsed.protocol === "https:") return;
|
|
28
26
|
if (parsed.protocol === "http:" && (parsed.hostname === "localhost" || parsed.hostname === "127.0.0.1" || parsed.hostname === "[::1]")) {
|
|
@@ -91,6 +89,7 @@ function createApiClient(options) {
|
|
|
91
89
|
form.append("screenshot", blob, i === 0 ? "screenshot.png" : `screenshot-${i + 1}.png`);
|
|
92
90
|
});
|
|
93
91
|
if (payload.synthetic) form.append("synthetic", "true");
|
|
92
|
+
if (payload.meta) form.append("meta", "true");
|
|
94
93
|
if (payload.user?.id) {
|
|
95
94
|
form.append("user", JSON.stringify(payload.user));
|
|
96
95
|
}
|
|
@@ -172,29 +171,26 @@ function createApiClient(options) {
|
|
|
172
171
|
return "healthy";
|
|
173
172
|
}
|
|
174
173
|
async function listChangelog(externalId) {
|
|
175
|
-
const response = await fetcher(
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
);
|
|
174
|
+
const response = await fetcher(`${endpoint}/api/feedback/v1/reports/widget/changelog/`, {
|
|
175
|
+
method: "GET",
|
|
176
|
+
headers: widgetHeaders(externalId)
|
|
177
|
+
});
|
|
179
178
|
if (response.status === 404) return [];
|
|
180
179
|
return readJsonArray(response, "listChangelog");
|
|
181
180
|
}
|
|
182
181
|
async function getReport(reportId, externalId, opts) {
|
|
183
|
-
const response = await fetcher(
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
...opts?.signal ? { signal: opts.signal } : {}
|
|
189
|
-
}
|
|
190
|
-
);
|
|
182
|
+
const response = await fetcher(`${endpoint}/api/feedback/v1/reports/widget/${reportId}/`, {
|
|
183
|
+
method: "GET",
|
|
184
|
+
headers: widgetHeaders(externalId),
|
|
185
|
+
...opts?.signal ? { signal: opts.signal } : {}
|
|
186
|
+
});
|
|
191
187
|
return readJsonObject(response, "getReport");
|
|
192
188
|
}
|
|
193
189
|
async function getReportBySeq(seq, externalId) {
|
|
194
|
-
const response = await fetcher(
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
);
|
|
190
|
+
const response = await fetcher(`${endpoint}/api/feedback/v1/reports/widget/by-seq/${seq}/`, {
|
|
191
|
+
method: "GET",
|
|
192
|
+
headers: widgetHeaders(externalId)
|
|
193
|
+
});
|
|
198
194
|
return readJsonObject(response, "getReportBySeq");
|
|
199
195
|
}
|
|
200
196
|
async function addComment(reportId, externalId, body, clientNonce, attachments) {
|
|
@@ -203,9 +199,7 @@ function createApiClient(options) {
|
|
|
203
199
|
const form = new FormData();
|
|
204
200
|
form.append("body", body);
|
|
205
201
|
if (clientNonce !== void 0) form.append("client_nonce", clientNonce);
|
|
206
|
-
attachments.forEach(
|
|
207
|
-
(blob, i) => form.append("attachment", blob, `attachment-${i + 1}.png`)
|
|
208
|
-
);
|
|
202
|
+
attachments.forEach((blob, i) => form.append("attachment", blob, `attachment-${i + 1}.png`));
|
|
209
203
|
init = { method: "POST", headers: widgetHeaders(externalId), body: form };
|
|
210
204
|
} else {
|
|
211
205
|
init = {
|
|
@@ -231,17 +225,14 @@ function createApiClient(options) {
|
|
|
231
225
|
return response.json();
|
|
232
226
|
}
|
|
233
227
|
async function editDescription(reportId, externalId, description) {
|
|
234
|
-
const response = await fetcher(
|
|
235
|
-
|
|
236
|
-
{
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
body: JSON.stringify({ description })
|
|
243
|
-
}
|
|
244
|
-
);
|
|
228
|
+
const response = await fetcher(`${endpoint}/api/feedback/v1/reports/widget/${reportId}/`, {
|
|
229
|
+
method: "PATCH",
|
|
230
|
+
headers: {
|
|
231
|
+
...widgetHeaders(externalId),
|
|
232
|
+
"Content-Type": "application/json"
|
|
233
|
+
},
|
|
234
|
+
body: JSON.stringify({ description })
|
|
235
|
+
});
|
|
245
236
|
if (!response.ok) {
|
|
246
237
|
const text = await response.text().catch(() => "");
|
|
247
238
|
throw new Error(`editDescription failed: ${response.status} ${text}`);
|
|
@@ -249,17 +240,14 @@ function createApiClient(options) {
|
|
|
249
240
|
return response.json();
|
|
250
241
|
}
|
|
251
242
|
async function closeAsResolved(reportId, externalId) {
|
|
252
|
-
const response = await fetcher(
|
|
253
|
-
|
|
254
|
-
{
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
body: JSON.stringify({ status: "closed" })
|
|
261
|
-
}
|
|
262
|
-
);
|
|
243
|
+
const response = await fetcher(`${endpoint}/api/feedback/v1/reports/widget/${reportId}/`, {
|
|
244
|
+
method: "PATCH",
|
|
245
|
+
headers: {
|
|
246
|
+
...widgetHeaders(externalId),
|
|
247
|
+
"Content-Type": "application/json"
|
|
248
|
+
},
|
|
249
|
+
body: JSON.stringify({ status: "closed" })
|
|
250
|
+
});
|
|
263
251
|
if (!response.ok) {
|
|
264
252
|
const text = await response.text().catch(() => "");
|
|
265
253
|
throw new Error(`closeAsResolved failed: ${response.status} ${text}`);
|
|
@@ -267,17 +255,14 @@ function createApiClient(options) {
|
|
|
267
255
|
return response.json();
|
|
268
256
|
}
|
|
269
257
|
async function reopenUnresolved(reportId, externalId) {
|
|
270
|
-
const response = await fetcher(
|
|
271
|
-
|
|
272
|
-
{
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
body: JSON.stringify({ status: "in_progress" })
|
|
279
|
-
}
|
|
280
|
-
);
|
|
258
|
+
const response = await fetcher(`${endpoint}/api/feedback/v1/reports/widget/${reportId}/`, {
|
|
259
|
+
method: "PATCH",
|
|
260
|
+
headers: {
|
|
261
|
+
...widgetHeaders(externalId),
|
|
262
|
+
"Content-Type": "application/json"
|
|
263
|
+
},
|
|
264
|
+
body: JSON.stringify({ status: "in_progress" })
|
|
265
|
+
});
|
|
281
266
|
if (!response.ok) {
|
|
282
267
|
const text = await response.text().catch(() => "");
|
|
283
268
|
throw new Error(`reopenUnresolved failed: ${response.status} ${text}`);
|
|
@@ -331,20 +316,17 @@ function createApiClient(options) {
|
|
|
331
316
|
return readJsonObject(response, "fetchBoardKpis");
|
|
332
317
|
}
|
|
333
318
|
async function checkVisibility(externalId, email) {
|
|
334
|
-
const response = await fetcher(
|
|
335
|
-
|
|
336
|
-
{
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
})
|
|
346
|
-
}
|
|
347
|
-
);
|
|
319
|
+
const response = await fetcher(`${endpoint}/api/feedback/v1/widget/visibility/`, {
|
|
320
|
+
method: "POST",
|
|
321
|
+
headers: {
|
|
322
|
+
...widgetHeaders(externalId),
|
|
323
|
+
"Content-Type": "application/json"
|
|
324
|
+
},
|
|
325
|
+
body: JSON.stringify({
|
|
326
|
+
external_id: externalId,
|
|
327
|
+
...email ? { email } : {}
|
|
328
|
+
})
|
|
329
|
+
});
|
|
348
330
|
if (!response.ok) {
|
|
349
331
|
throw new Error(`checkVisibility failed: ${response.status}`);
|
|
350
332
|
}
|
|
@@ -677,6 +659,9 @@ var DEFAULT_STRINGS = {
|
|
|
677
659
|
"form.cancel": "Cancel",
|
|
678
660
|
"form.close": "Close",
|
|
679
661
|
"form.submitting": "Sending\u2026",
|
|
662
|
+
"form.meta.action": "Report a problem with this feedback tool",
|
|
663
|
+
"form.meta.badge": "\u2192 goes to the feedback-tool team",
|
|
664
|
+
"form.meta.cancel": "Back to normal feedback",
|
|
680
665
|
"form.success": "Thanks \u2014 your feedback was sent.",
|
|
681
666
|
"form.success.seq": "Thanks \u2014 report #{seq} was sent. \u2713",
|
|
682
667
|
"form.discard.title": "Unsaved changes",
|
|
@@ -850,6 +835,10 @@ var DEFAULT_STRINGS = {
|
|
|
850
835
|
"detail.tech.errors": "Runtime errors",
|
|
851
836
|
"detail.tech.console": "Console (last 20)",
|
|
852
837
|
"detail.tech.network": "Network (last 15)",
|
|
838
|
+
"detail.verified.badge": "Agent-verified",
|
|
839
|
+
"detail.verified.title": "Proof of fix",
|
|
840
|
+
"detail.verified.functional": "Functional check",
|
|
841
|
+
"detail.verified.ui": "UI check",
|
|
853
842
|
"status.new": "New",
|
|
854
843
|
"status.in_progress": "In progress",
|
|
855
844
|
"status.awaiting_validation": "Awaiting your validation",
|
|
@@ -877,6 +866,9 @@ var FRENCH_STRINGS = {
|
|
|
877
866
|
"form.cancel": "Annuler",
|
|
878
867
|
"form.close": "Fermer",
|
|
879
868
|
"form.submitting": "Envoi\u2026",
|
|
869
|
+
"form.meta.action": "Signaler un probl\xE8me avec l'outil de feedback",
|
|
870
|
+
"form.meta.badge": "\u2192 envoy\xE9 \xE0 l'\xE9quipe de l'outil de feedback",
|
|
871
|
+
"form.meta.cancel": "Revenir au commentaire normal",
|
|
880
872
|
"form.success": "Merci \u2014 votre commentaire a \xE9t\xE9 envoy\xE9.",
|
|
881
873
|
"form.success.seq": "Merci \u2014 rapport n\xB0{seq} envoy\xE9. \u2713",
|
|
882
874
|
"form.discard.title": "Modifications non enregistr\xE9es",
|
|
@@ -1050,6 +1042,10 @@ var FRENCH_STRINGS = {
|
|
|
1050
1042
|
"detail.tech.errors": "Erreurs d\u2019ex\xE9cution",
|
|
1051
1043
|
"detail.tech.console": "Console (20 derniers)",
|
|
1052
1044
|
"detail.tech.network": "R\xE9seau (15 derniers)",
|
|
1045
|
+
"detail.verified.badge": "V\xE9rifi\xE9 par l\u2019agent",
|
|
1046
|
+
"detail.verified.title": "Preuve de correction",
|
|
1047
|
+
"detail.verified.functional": "Fonctionnel v\xE9rifi\xE9",
|
|
1048
|
+
"detail.verified.ui": "Interface v\xE9rifi\xE9e",
|
|
1053
1049
|
"status.new": "Nouveau",
|
|
1054
1050
|
"status.in_progress": "En cours",
|
|
1055
1051
|
"status.awaiting_validation": "En attente de validation",
|
|
@@ -1310,6 +1306,26 @@ var ALLOWED_IMAGE_TYPES = [
|
|
|
1310
1306
|
];
|
|
1311
1307
|
var MAX_SCREENSHOT_BYTES = 10 * 1024 * 1024;
|
|
1312
1308
|
var MAX_SCREENSHOTS = 5;
|
|
1309
|
+
var ALLOWED_ATTACHMENT_TYPES = [
|
|
1310
|
+
...ALLOWED_IMAGE_TYPES,
|
|
1311
|
+
"application/pdf",
|
|
1312
|
+
"text/plain",
|
|
1313
|
+
"text/csv",
|
|
1314
|
+
"application/json",
|
|
1315
|
+
""
|
|
1316
|
+
];
|
|
1317
|
+
var ATTACHMENT_ACCEPT = "image/png,image/jpeg,image/webp,application/pdf,text/plain,.log,.txt,.csv,.json";
|
|
1318
|
+
function validateAttachmentFile(file) {
|
|
1319
|
+
if (!ALLOWED_ATTACHMENT_TYPES.includes(
|
|
1320
|
+
file.type
|
|
1321
|
+
)) {
|
|
1322
|
+
return { kind: "type" };
|
|
1323
|
+
}
|
|
1324
|
+
if (file.size > MAX_SCREENSHOT_BYTES) {
|
|
1325
|
+
return { kind: "size", maxMb: MAX_SCREENSHOT_BYTES / (1024 * 1024) };
|
|
1326
|
+
}
|
|
1327
|
+
return null;
|
|
1328
|
+
}
|
|
1313
1329
|
function validateScreenshotFile(file) {
|
|
1314
1330
|
if (!ALLOWED_IMAGE_TYPES.includes(
|
|
1315
1331
|
file.type
|
|
@@ -1396,7 +1412,7 @@ function ReportDetailView({
|
|
|
1396
1412
|
const remaining = MAX_SCREENSHOTS - composeShots.length;
|
|
1397
1413
|
const batch = files.slice(0, Math.max(0, remaining));
|
|
1398
1414
|
for (const file of batch) {
|
|
1399
|
-
const err =
|
|
1415
|
+
const err = validateAttachmentFile(file);
|
|
1400
1416
|
if (err) {
|
|
1401
1417
|
setAttachError(
|
|
1402
1418
|
err.kind === "type" ? strings["form.screenshot.error_type"] : strings["form.screenshot.error_size"].replace("{max}", String(err.maxMb))
|
|
@@ -1621,7 +1637,10 @@ function ReportDetailView({
|
|
|
1621
1637
|
"\u2190 ",
|
|
1622
1638
|
strings["detail.back"]
|
|
1623
1639
|
] }),
|
|
1624
|
-
/* @__PURE__ */
|
|
1640
|
+
/* @__PURE__ */ jsxs3("span", { class: "report-detail-header-pills", children: [
|
|
1641
|
+
/* @__PURE__ */ jsx3("span", { class: `pill pill-status pill-status--${detail.status}`, children: strings[`status.${detail.status}`] ?? detail.status }),
|
|
1642
|
+
detail.verification && /* @__PURE__ */ jsx3("span", { class: "pill pill-verified", children: strings["detail.verified.badge"] })
|
|
1643
|
+
] })
|
|
1625
1644
|
] }),
|
|
1626
1645
|
variant === "board" && /* @__PURE__ */ jsxs3("div", { class: "report-detail-header report-detail-header--board", children: [
|
|
1627
1646
|
/* @__PURE__ */ jsxs3(
|
|
@@ -1637,7 +1656,10 @@ function ReportDetailView({
|
|
|
1637
1656
|
]
|
|
1638
1657
|
}
|
|
1639
1658
|
),
|
|
1640
|
-
/* @__PURE__ */
|
|
1659
|
+
/* @__PURE__ */ jsxs3("span", { class: "report-detail-header-pills", children: [
|
|
1660
|
+
/* @__PURE__ */ jsx3("span", { class: `pill pill-status pill-status--${detail.status}`, children: strings[`status.${detail.status}`] ?? detail.status }),
|
|
1661
|
+
detail.verification && /* @__PURE__ */ jsx3("span", { class: "pill pill-verified", children: strings["detail.verified.badge"] })
|
|
1662
|
+
] })
|
|
1641
1663
|
] }),
|
|
1642
1664
|
/* @__PURE__ */ jsxs3("div", { class: "report-detail-body", children: [
|
|
1643
1665
|
/* @__PURE__ */ jsx3(ContextBlock, { detail, strings }),
|
|
@@ -1711,6 +1733,15 @@ function ReportDetailView({
|
|
|
1711
1733
|
}
|
|
1712
1734
|
) : /* @__PURE__ */ jsx3("div", { class: "report-detail-screenshot", children: /* @__PURE__ */ jsx3("img", { src: url, alt: "", loading: "lazy", onError: () => unpinUrl(pinKey) }) });
|
|
1713
1735
|
}),
|
|
1736
|
+
detail.verification && /* @__PURE__ */ jsx3(
|
|
1737
|
+
VerificationPanel,
|
|
1738
|
+
{
|
|
1739
|
+
verification: detail.verification,
|
|
1740
|
+
strings,
|
|
1741
|
+
pinUrl,
|
|
1742
|
+
unpinUrl
|
|
1743
|
+
}
|
|
1744
|
+
),
|
|
1714
1745
|
/* @__PURE__ */ jsx3("h3", { class: "report-detail-section", children: strings["detail.thread"] }),
|
|
1715
1746
|
detail.comments.length === 0 ? /* @__PURE__ */ jsx3("p", { class: "report-detail-empty", children: strings["detail.no_replies"] }) : /* @__PURE__ */ jsx3("ul", { class: "report-comments", children: detail.comments.map((c) => /* @__PURE__ */ jsx3("li", { children: /* @__PURE__ */ jsx3(
|
|
1716
1747
|
CommentBubble,
|
|
@@ -1753,7 +1784,7 @@ function ReportDetailView({
|
|
|
1753
1784
|
{
|
|
1754
1785
|
ref: fileInputRef,
|
|
1755
1786
|
type: "file",
|
|
1756
|
-
accept:
|
|
1787
|
+
accept: ATTACHMENT_ACCEPT,
|
|
1757
1788
|
multiple: true,
|
|
1758
1789
|
class: "compose-attach-input",
|
|
1759
1790
|
onChange: handleAttachChange,
|
|
@@ -1879,6 +1910,68 @@ function TechnicalContextDrawer({ ctx, strings }) {
|
|
|
1879
1910
|
] })
|
|
1880
1911
|
] });
|
|
1881
1912
|
}
|
|
1913
|
+
function VerificationPanel({
|
|
1914
|
+
verification,
|
|
1915
|
+
strings,
|
|
1916
|
+
pinUrl,
|
|
1917
|
+
unpinUrl
|
|
1918
|
+
}) {
|
|
1919
|
+
return /* @__PURE__ */ jsxs3("details", { class: "report-detail-verification", children: [
|
|
1920
|
+
/* @__PURE__ */ jsx3("summary", { children: strings["detail.verified.title"] }),
|
|
1921
|
+
/* @__PURE__ */ jsxs3("div", { class: "verification-body", children: [
|
|
1922
|
+
/* @__PURE__ */ jsx3("p", { class: "verification-evidence", children: verification.evidence }),
|
|
1923
|
+
/* @__PURE__ */ jsxs3("div", { class: "verification-meta", children: [
|
|
1924
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1925
|
+
verification.functional_ok ? "\u2713" : "\u2717",
|
|
1926
|
+
" ",
|
|
1927
|
+
strings["detail.verified.functional"]
|
|
1928
|
+
] }),
|
|
1929
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1930
|
+
verification.ui_ok ? "\u2713" : "\u2717",
|
|
1931
|
+
" ",
|
|
1932
|
+
strings["detail.verified.ui"]
|
|
1933
|
+
] }),
|
|
1934
|
+
/* @__PURE__ */ jsxs3("span", { children: [
|
|
1935
|
+
verification.environment,
|
|
1936
|
+
verification.app_version ? ` \xB7 ${verification.app_version}` : ""
|
|
1937
|
+
] })
|
|
1938
|
+
] }),
|
|
1939
|
+
verification.screenshots.length > 0 && /* @__PURE__ */ jsx3("div", { class: "verification-shots", children: verification.screenshots.map((s, i) => {
|
|
1940
|
+
const pinKey = `verif:${i}`;
|
|
1941
|
+
const url = pinUrl(pinKey, s.url);
|
|
1942
|
+
if (!url) return null;
|
|
1943
|
+
const safeHref = safeExternalHref(url);
|
|
1944
|
+
return safeHref ? /* @__PURE__ */ jsx3(
|
|
1945
|
+
"a",
|
|
1946
|
+
{
|
|
1947
|
+
class: "report-detail-screenshot",
|
|
1948
|
+
href: safeHref,
|
|
1949
|
+
target: "_blank",
|
|
1950
|
+
rel: "noopener noreferrer",
|
|
1951
|
+
children: /* @__PURE__ */ jsx3(
|
|
1952
|
+
"img",
|
|
1953
|
+
{
|
|
1954
|
+
src: url,
|
|
1955
|
+
alt: s.caption ?? "",
|
|
1956
|
+
loading: "lazy",
|
|
1957
|
+
onError: () => unpinUrl(pinKey)
|
|
1958
|
+
}
|
|
1959
|
+
)
|
|
1960
|
+
},
|
|
1961
|
+
i
|
|
1962
|
+
) : /* @__PURE__ */ jsx3("div", { class: "report-detail-screenshot", children: /* @__PURE__ */ jsx3(
|
|
1963
|
+
"img",
|
|
1964
|
+
{
|
|
1965
|
+
src: url,
|
|
1966
|
+
alt: s.caption ?? "",
|
|
1967
|
+
loading: "lazy",
|
|
1968
|
+
onError: () => unpinUrl(pinKey)
|
|
1969
|
+
}
|
|
1970
|
+
) }, i);
|
|
1971
|
+
}) })
|
|
1972
|
+
] })
|
|
1973
|
+
] });
|
|
1974
|
+
}
|
|
1882
1975
|
function DeviceSection({
|
|
1883
1976
|
device,
|
|
1884
1977
|
strings
|
|
@@ -3301,8 +3394,10 @@ function Form({
|
|
|
3301
3394
|
status,
|
|
3302
3395
|
errorMessage,
|
|
3303
3396
|
submittedSeq,
|
|
3304
|
-
onDirtyChange
|
|
3397
|
+
onDirtyChange,
|
|
3398
|
+
metaFeedbackEnabled
|
|
3305
3399
|
}) {
|
|
3400
|
+
const [metaMode, setMetaMode] = useState6(false);
|
|
3306
3401
|
const [description, setDescription] = useState6("");
|
|
3307
3402
|
const [feedbackType, setFeedbackType] = useState6("bug");
|
|
3308
3403
|
const [severity, setSeverity] = useState6("medium");
|
|
@@ -3422,10 +3517,14 @@ function Form({
|
|
|
3422
3517
|
values.screenshots = shots.map((s) => s.blob);
|
|
3423
3518
|
values.capture_method = "manual";
|
|
3424
3519
|
}
|
|
3520
|
+
if (metaMode) {
|
|
3521
|
+
values.meta = true;
|
|
3522
|
+
}
|
|
3425
3523
|
onSubmit(values);
|
|
3426
3524
|
};
|
|
3427
3525
|
return /* @__PURE__ */ jsxs9("form", { onSubmit: handleSubmit, onPaste: handlePaste, children: [
|
|
3428
3526
|
/* @__PURE__ */ jsx9("h2", { children: strings["form.title"] }),
|
|
3527
|
+
metaMode && /* @__PURE__ */ jsx9("div", { class: "meta-badge", children: strings["form.meta.badge"] }),
|
|
3429
3528
|
/* @__PURE__ */ jsxs9("div", { class: "field", children: [
|
|
3430
3529
|
/* @__PURE__ */ jsx9("label", { for: "mfb-desc", children: strings["form.description.label"] }),
|
|
3431
3530
|
/* @__PURE__ */ jsx9(
|
|
@@ -3592,6 +3691,16 @@ function Form({
|
|
|
3592
3691
|
/* @__PURE__ */ jsx9("button", { type: "button", class: "btn", onClick: onCancel, disabled: submitting, children: strings["form.cancel"] }),
|
|
3593
3692
|
/* @__PURE__ */ jsx9("button", { type: "submit", class: "btn btn--primary", disabled: submitting, children: submitLabel })
|
|
3594
3693
|
] }),
|
|
3694
|
+
metaFeedbackEnabled && /* @__PURE__ */ jsx9(
|
|
3695
|
+
"button",
|
|
3696
|
+
{
|
|
3697
|
+
type: "button",
|
|
3698
|
+
class: "meta-toggle",
|
|
3699
|
+
onClick: () => setMetaMode(!metaMode),
|
|
3700
|
+
disabled: submitting,
|
|
3701
|
+
children: metaMode ? strings["form.meta.cancel"] : strings["form.meta.action"]
|
|
3702
|
+
}
|
|
3703
|
+
),
|
|
3595
3704
|
annotatingIndex !== null && shots[annotatingIndex] && /* @__PURE__ */ jsx9(
|
|
3596
3705
|
Annotator,
|
|
3597
3706
|
{
|
|
@@ -4455,6 +4564,12 @@ var WIDGET_STYLES = `
|
|
|
4455
4564
|
/* REQ-A7: quiet transparency line under the form. */
|
|
4456
4565
|
.capture-notice { color: var(--mfb-muted, #6b7280); font-size: 11px; line-height: 1.4; margin-top: 6px; }
|
|
4457
4566
|
|
|
4567
|
+
/* Meta-feedback: footer escape hatch + active-mode badge. Deliberately as
|
|
4568
|
+
quiet as the capture notice \u2014 never competes with the host's own flow. */
|
|
4569
|
+
.meta-toggle { background: none; border: none; padding: 0; margin-top: 10px; color: var(--mfb-muted, #6b7280); font-size: 11px; text-decoration: underline; cursor: pointer; align-self: flex-start; }
|
|
4570
|
+
.meta-toggle:hover { color: var(--mfb-text, #111827); }
|
|
4571
|
+
.meta-badge { display: inline-block; margin: 2px 0 6px; padding: 2px 8px; border-radius: 999px; background: var(--mfb-accent-soft, #eef2ff); color: var(--mfb-accent, #4f46e5); font-size: 11px; font-weight: 600; }
|
|
4572
|
+
|
|
4458
4573
|
/* #85: inline "#NN" report reference rendered as a link (a button for a11y). */
|
|
4459
4574
|
.seq-link {
|
|
4460
4575
|
display: inline;
|
|
@@ -4965,6 +5080,10 @@ var WIDGET_STYLES = `
|
|
|
4965
5080
|
.pill-status--awaiting_validation { background: #faf5ff; color: #6b21a8; border-color: #e9d5ff; }
|
|
4966
5081
|
.pill-status--closed { background: #ecfdf5; color: #065f46; border-color: #a7f3d0; }
|
|
4967
5082
|
.pill-status--rejected, .pill-status--wontfix, .pill-status--duplicate { background: #f3f4f6; color: #374151; border-color: #e5e7eb; }
|
|
5083
|
+
/* Agent-verified fix badge (Phase B) \u2014 emerald, same family as
|
|
5084
|
+
.pill-status--closed but its own modifier since it layers alongside
|
|
5085
|
+
the status pill rather than replacing it. */
|
|
5086
|
+
.pill-verified { background: #ecfdf5; color: #047857; border-color: #a7f3d0; }
|
|
4968
5087
|
.pill-type { background: var(--mfb-surface); color: var(--mfb-text-muted); border-color: var(--mfb-border); }
|
|
4969
5088
|
.pill-severity { background: var(--mfb-surface); color: var(--mfb-text-muted); border-color: var(--mfb-border); }
|
|
4970
5089
|
.pill-severity--blocker { background: #fef2f2; color: #991b1b; border-color: #fecaca; }
|
|
@@ -4979,6 +5098,7 @@ var WIDGET_STYLES = `
|
|
|
4979
5098
|
justify-content: space-between;
|
|
4980
5099
|
gap: 8px;
|
|
4981
5100
|
}
|
|
5101
|
+
.report-detail-header-pills { display: inline-flex; align-items: center; gap: 6px; }
|
|
4982
5102
|
.report-detail-body { display: flex; flex-direction: column; gap: 10px; }
|
|
4983
5103
|
.report-detail-description {
|
|
4984
5104
|
font-size: 14px;
|
|
@@ -5332,12 +5452,14 @@ button.report-detail-edit {
|
|
|
5332
5452
|
/* Transparency drawer \u2014 closed by default. The user can click open to
|
|
5333
5453
|
verify what their browser sent: device, errors, console tail, network
|
|
5334
5454
|
tail. Read-only; purely a trust-building gesture. */
|
|
5335
|
-
.report-detail-tech
|
|
5455
|
+
.report-detail-tech,
|
|
5456
|
+
.report-detail-verification {
|
|
5336
5457
|
border: 1px solid var(--mfb-border);
|
|
5337
5458
|
border-radius: var(--mfb-radius);
|
|
5338
5459
|
background: var(--mfb-surface);
|
|
5339
5460
|
}
|
|
5340
|
-
.report-detail-tech > summary
|
|
5461
|
+
.report-detail-tech > summary,
|
|
5462
|
+
.report-detail-verification > summary {
|
|
5341
5463
|
cursor: pointer;
|
|
5342
5464
|
padding: 8px 10px;
|
|
5343
5465
|
font-size: 11px;
|
|
@@ -5347,15 +5469,19 @@ button.report-detail-edit {
|
|
|
5347
5469
|
user-select: none;
|
|
5348
5470
|
list-style: none;
|
|
5349
5471
|
}
|
|
5350
|
-
.report-detail-tech > summary::-webkit-details-marker
|
|
5351
|
-
.report-detail-
|
|
5472
|
+
.report-detail-tech > summary::-webkit-details-marker,
|
|
5473
|
+
.report-detail-verification > summary::-webkit-details-marker { display: none; }
|
|
5474
|
+
.report-detail-tech > summary::before,
|
|
5475
|
+
.report-detail-verification > summary::before {
|
|
5352
5476
|
content: '\u25B8';
|
|
5353
5477
|
display: inline-block;
|
|
5354
5478
|
margin-right: 6px;
|
|
5355
5479
|
transition: transform 120ms;
|
|
5356
5480
|
}
|
|
5357
|
-
.report-detail-tech[open] > summary::before
|
|
5358
|
-
.
|
|
5481
|
+
.report-detail-tech[open] > summary::before,
|
|
5482
|
+
.report-detail-verification[open] > summary::before { transform: rotate(90deg); }
|
|
5483
|
+
.tech-body,
|
|
5484
|
+
.verification-body {
|
|
5359
5485
|
padding: 0 10px 10px 10px;
|
|
5360
5486
|
display: flex;
|
|
5361
5487
|
flex-direction: column;
|
|
@@ -5435,6 +5561,31 @@ button.report-detail-edit {
|
|
|
5435
5561
|
.tech-network-url { word-break: break-all; }
|
|
5436
5562
|
.tech-network-time { text-align: right; color: var(--mfb-text-muted); font-variant-numeric: tabular-nums; }
|
|
5437
5563
|
|
|
5564
|
+
/* Proof-of-fix drawer (Phase B) \u2014 shares the collapsible shell rules
|
|
5565
|
+
with .report-detail-tech above (grouped selectors): closed by
|
|
5566
|
+
default, rotating \u25B8 marker. Surfaces an agent's verification pass
|
|
5567
|
+
so the submitter can see the evidence behind the "V\xE9rifi\xE9 par
|
|
5568
|
+
l'agent" badge. */
|
|
5569
|
+
.verification-evidence {
|
|
5570
|
+
margin: 0;
|
|
5571
|
+
font-size: 12px;
|
|
5572
|
+
white-space: pre-wrap;
|
|
5573
|
+
}
|
|
5574
|
+
.verification-meta {
|
|
5575
|
+
display: flex;
|
|
5576
|
+
gap: 12px;
|
|
5577
|
+
flex-wrap: wrap;
|
|
5578
|
+
font-size: 11px;
|
|
5579
|
+
color: var(--mfb-text-muted);
|
|
5580
|
+
}
|
|
5581
|
+
.verification-shots {
|
|
5582
|
+
display: flex;
|
|
5583
|
+
gap: 8px;
|
|
5584
|
+
flex-wrap: wrap;
|
|
5585
|
+
}
|
|
5586
|
+
.verification-shots .report-detail-screenshot { width: 96px; flex: 0 0 auto; }
|
|
5587
|
+
.verification-shots .report-detail-screenshot img { max-height: 96px; }
|
|
5588
|
+
|
|
5438
5589
|
/* KPI strip \u2014 four pills above the My Reports list. Each is clickable
|
|
5439
5590
|
to filter the rows below. Borrowed from thePnr's FeedbackKPICards. */
|
|
5440
5591
|
.kpi-strip {
|
|
@@ -6202,8 +6353,7 @@ function mountWidget(options) {
|
|
|
6202
6353
|
});
|
|
6203
6354
|
}, 1200);
|
|
6204
6355
|
} catch (err) {
|
|
6205
|
-
if (typeof console !== "undefined")
|
|
6206
|
-
console.warn("[mhosaic] submit:", err);
|
|
6356
|
+
if (typeof console !== "undefined") console.warn("[mhosaic] submit:", err);
|
|
6207
6357
|
rerender({
|
|
6208
6358
|
...currentState,
|
|
6209
6359
|
status: "error",
|
|
@@ -6237,9 +6387,7 @@ function mountWidget(options) {
|
|
|
6237
6387
|
enabled: pageActivityEnabled
|
|
6238
6388
|
});
|
|
6239
6389
|
const fabLabel = pageSignal.open === 1 ? options.strings["page.badge.aria.one"] : pageSignal.open > 0 ? options.strings["page.badge.aria"].replace("{n}", String(pageSignal.open)) : options.strings["fab.label"];
|
|
6240
|
-
const [visibilityAllowed, setVisibilityAllowed] = useState10(
|
|
6241
|
-
!options.requiresVisibilityCheck
|
|
6242
|
-
);
|
|
6390
|
+
const [visibilityAllowed, setVisibilityAllowed] = useState10(!options.requiresVisibilityCheck);
|
|
6243
6391
|
useEffect10(() => {
|
|
6244
6392
|
if (!options.requiresVisibilityCheck) {
|
|
6245
6393
|
setVisibilityAllowed(true);
|
|
@@ -6443,6 +6591,9 @@ function mountWidget(options) {
|
|
|
6443
6591
|
},
|
|
6444
6592
|
onDirtyChange: (d) => {
|
|
6445
6593
|
formDirty = d;
|
|
6594
|
+
},
|
|
6595
|
+
...options.metaFeedbackEnabled !== void 0 && {
|
|
6596
|
+
metaFeedbackEnabled: options.metaFeedbackEnabled
|
|
6446
6597
|
}
|
|
6447
6598
|
}
|
|
6448
6599
|
)
|
|
@@ -6486,8 +6637,12 @@ function mountWidget(options) {
|
|
|
6486
6637
|
api: options.api,
|
|
6487
6638
|
externalId,
|
|
6488
6639
|
strings: options.strings,
|
|
6489
|
-
...options.getCurrentPage !== void 0 && {
|
|
6490
|
-
|
|
6640
|
+
...options.getCurrentPage !== void 0 && {
|
|
6641
|
+
getCurrentPage: options.getCurrentPage
|
|
6642
|
+
},
|
|
6643
|
+
...state.boardSelectId !== void 0 && {
|
|
6644
|
+
initialSelectedId: state.boardSelectId
|
|
6645
|
+
}
|
|
6491
6646
|
}
|
|
6492
6647
|
)
|
|
6493
6648
|
]
|
|
@@ -6502,9 +6657,7 @@ function mountWidget(options) {
|
|
|
6502
6657
|
if (!api || !externalId || !ref) return;
|
|
6503
6658
|
const seq = /^\d+$/.test(ref) ? parseInt(ref, 10) : null;
|
|
6504
6659
|
const resolve = seq !== null ? api.getReportBySeq(seq, externalId) : api.getReport(ref, externalId);
|
|
6505
|
-
void resolve.then(
|
|
6506
|
-
(r) => rerender({ ...currentState, open: true, tab: "mine", selectedReportId: r.id })
|
|
6507
|
-
).catch(() => {
|
|
6660
|
+
void resolve.then((r) => rerender({ ...currentState, open: true, tab: "mine", selectedReportId: r.id })).catch(() => {
|
|
6508
6661
|
});
|
|
6509
6662
|
}
|
|
6510
6663
|
if (options.deepLinkParam !== false) {
|
|
@@ -6543,10 +6696,7 @@ function defaultQaPosition() {
|
|
|
6543
6696
|
function createFeedback(config) {
|
|
6544
6697
|
const env = config.env ?? "prod";
|
|
6545
6698
|
const locale = config.locale ?? (typeof navigator !== "undefined" ? navigator.language : void 0);
|
|
6546
|
-
const strings = resolveStrings(
|
|
6547
|
-
config.translations ?? {},
|
|
6548
|
-
locale !== void 0 ? { locale } : {}
|
|
6549
|
-
);
|
|
6699
|
+
const strings = resolveStrings(config.translations ?? {}, locale !== void 0 ? { locale } : {});
|
|
6550
6700
|
const capture = installCapture({
|
|
6551
6701
|
...config.sanitizeUrl !== void 0 && { sanitizeUrl: config.sanitizeUrl }
|
|
6552
6702
|
});
|
|
@@ -6601,14 +6751,15 @@ function createFeedback(config) {
|
|
|
6601
6751
|
capture_method: captureMethod,
|
|
6602
6752
|
technical_context
|
|
6603
6753
|
};
|
|
6604
|
-
if ("0.
|
|
6605
|
-
payload.widget_version = "0.
|
|
6754
|
+
if ("0.37.0") {
|
|
6755
|
+
payload.widget_version = "0.37.0";
|
|
6606
6756
|
}
|
|
6607
6757
|
if (manualScreenshots?.length) {
|
|
6608
6758
|
payload.screenshots = manualScreenshots;
|
|
6609
6759
|
payload.screenshot = manualScreenshots[0];
|
|
6610
6760
|
}
|
|
6611
6761
|
if (values.synthetic) payload.synthetic = true;
|
|
6762
|
+
if (values.meta) payload.meta = true;
|
|
6612
6763
|
const pagePath = currentPagePath(config);
|
|
6613
6764
|
if (pagePath) payload.page_path = pagePath;
|
|
6614
6765
|
if (user?.id !== void 0 && user.id !== null && user.id !== "") {
|
|
@@ -6658,12 +6809,15 @@ function createFeedback(config) {
|
|
|
6658
6809
|
...config.openToCurrentPageFeedback !== void 0 && {
|
|
6659
6810
|
openToCurrentPageFeedback: config.openToCurrentPageFeedback
|
|
6660
6811
|
},
|
|
6812
|
+
...config.metaFeedbackEnabled !== void 0 && {
|
|
6813
|
+
metaFeedbackEnabled: config.metaFeedbackEnabled
|
|
6814
|
+
},
|
|
6661
6815
|
...config.showPageActivity !== void 0 && {
|
|
6662
6816
|
showPageActivity: config.showPageActivity
|
|
6663
6817
|
}
|
|
6664
6818
|
};
|
|
6665
6819
|
const handle = mountWidget(mountOptions);
|
|
6666
|
-
if (config.openToCurrentPageFeedback === void 0 && config.showFAB !== false) {
|
|
6820
|
+
if ((config.openToCurrentPageFeedback === void 0 || config.metaFeedbackEnabled === void 0) && config.showFAB !== false) {
|
|
6667
6821
|
const behaviorFetch = config.fetchImpl ?? globalThis.fetch;
|
|
6668
6822
|
void (async () => {
|
|
6669
6823
|
try {
|
|
@@ -6676,6 +6830,10 @@ function createFeedback(config) {
|
|
|
6676
6830
|
if (typeof v === "boolean" && mountOptions.openToCurrentPageFeedback === void 0) {
|
|
6677
6831
|
mountOptions.openToCurrentPageFeedback = v;
|
|
6678
6832
|
}
|
|
6833
|
+
const meta = m?.config?.behavior?.metaFeedbackEnabled;
|
|
6834
|
+
if (typeof meta === "boolean" && mountOptions.metaFeedbackEnabled === void 0) {
|
|
6835
|
+
mountOptions.metaFeedbackEnabled = meta;
|
|
6836
|
+
}
|
|
6679
6837
|
} catch {
|
|
6680
6838
|
}
|
|
6681
6839
|
})();
|
|
@@ -6746,4 +6904,4 @@ function createFeedback(config) {
|
|
|
6746
6904
|
export {
|
|
6747
6905
|
createFeedback
|
|
6748
6906
|
};
|
|
6749
|
-
//# sourceMappingURL=chunk-
|
|
6907
|
+
//# sourceMappingURL=chunk-C3ILJCVI.mjs.map
|