@mhosaic/feedback 0.21.0 → 0.23.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-2I7RGRYD.mjs → chunk-NCNRU3SR.mjs} +99 -15
- package/dist/chunk-NCNRU3SR.mjs.map +1 -0
- package/dist/embed.min.js +43 -22
- package/dist/embed.min.js.map +1 -1
- package/dist/error-tracking.d.ts +1 -1
- package/dist/{index-CmHNkJsj.d.ts → index-DHNIgEcR.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.d.ts +1 -1
- package/dist/qa-meter.mjs +67 -25
- package/dist/qa-meter.mjs.map +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-CfSqqfkw.d.ts → types-CKwnZDsE.d.ts} +16 -0
- package/dist/webvitals.d.ts +1 -1
- package/dist/widget.min.js +44 -23
- package/dist/widget.min.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-2I7RGRYD.mjs.map +0 -1
|
@@ -58,6 +58,9 @@ function createApiClient(options) {
|
|
|
58
58
|
if (payload.widget_version) {
|
|
59
59
|
form.append("widget_version", payload.widget_version);
|
|
60
60
|
}
|
|
61
|
+
if (payload.page_path) {
|
|
62
|
+
form.append("page_path", payload.page_path);
|
|
63
|
+
}
|
|
61
64
|
const headers = {
|
|
62
65
|
Authorization: `Bearer ${options.apiKey}`
|
|
63
66
|
};
|
|
@@ -197,6 +200,7 @@ function createApiClient(options) {
|
|
|
197
200
|
if (filters.mine) params.set("mine", "1");
|
|
198
201
|
if (filters.ordering) params.set("ordering", filters.ordering);
|
|
199
202
|
if (filters.page && filters.page > 1) params.set("page", String(filters.page));
|
|
203
|
+
if (filters.pagePath) params.set("page_path", filters.pagePath);
|
|
200
204
|
const qs = params.toString();
|
|
201
205
|
return qs ? `?${qs}` : "";
|
|
202
206
|
}
|
|
@@ -323,7 +327,7 @@ function installConsolePatch(buffer) {
|
|
|
323
327
|
const original = console[level];
|
|
324
328
|
if (typeof original !== "function") continue;
|
|
325
329
|
originals[level] = original;
|
|
326
|
-
console[level] = function
|
|
330
|
+
console[level] = function patched2(...args) {
|
|
327
331
|
try {
|
|
328
332
|
const rawMessage = args.map(safeStringify).join(" ");
|
|
329
333
|
const message = scrubCredentials(rawMessage).slice(0, 2e3);
|
|
@@ -350,7 +354,7 @@ function installFetchPatch(buffer, sanitize) {
|
|
|
350
354
|
if (typeof window === "undefined" || typeof window.fetch !== "function") return () => {
|
|
351
355
|
};
|
|
352
356
|
const original = window.fetch.bind(window);
|
|
353
|
-
window.fetch = async function
|
|
357
|
+
window.fetch = async function patched2(input, init) {
|
|
354
358
|
const start = performance.now();
|
|
355
359
|
const url = typeof input === "string" ? input : input instanceof URL ? input.toString() : input.url;
|
|
356
360
|
const method = (init?.method || (input instanceof Request ? input.method : "GET")).toUpperCase();
|
|
@@ -630,6 +634,7 @@ var DEFAULT_STRINGS = {
|
|
|
630
634
|
"board.detail.status_history": "History",
|
|
631
635
|
"board.scope.project": "Project reports",
|
|
632
636
|
"board.scope.mine": "Your reports",
|
|
637
|
+
"board.scope.thisPage": "This page",
|
|
633
638
|
"board.back": "Back",
|
|
634
639
|
"changelog.empty.title": "Nothing resolved yet",
|
|
635
640
|
"changelog.empty.body": "Once a report you sent is fixed it will appear here, grouped by week.",
|
|
@@ -779,6 +784,7 @@ var FRENCH_STRINGS = {
|
|
|
779
784
|
"board.detail.status_history": "Historique",
|
|
780
785
|
"board.scope.project": "Rapports du projet",
|
|
781
786
|
"board.scope.mine": "Vos rapports",
|
|
787
|
+
"board.scope.thisPage": "Cette page",
|
|
782
788
|
"board.back": "Retour",
|
|
783
789
|
"changelog.empty.title": "Rien de r\xE9solu pour l\u2019instant",
|
|
784
790
|
"changelog.empty.body": "Quand un rapport que vous avez envoy\xE9 est corrig\xE9, il appara\xEEtra ici, regroup\xE9 par semaine.",
|
|
@@ -865,6 +871,36 @@ function resolveStrings(overrides, options = {}) {
|
|
|
865
871
|
import { h, render } from "preact";
|
|
866
872
|
import { useCallback, useEffect as useEffect8, useState as useState7 } from "preact/hooks";
|
|
867
873
|
|
|
874
|
+
// src/widget/currentPage.ts
|
|
875
|
+
function currentPagePath(opts) {
|
|
876
|
+
const override = opts.getCurrentPage?.();
|
|
877
|
+
if (override) return override;
|
|
878
|
+
return typeof window !== "undefined" ? window.location.pathname : "/";
|
|
879
|
+
}
|
|
880
|
+
var LOCATION_CHANGE = "mfb:locationchange";
|
|
881
|
+
var patched = false;
|
|
882
|
+
function patchHistory() {
|
|
883
|
+
if (patched || typeof history === "undefined") return;
|
|
884
|
+
patched = true;
|
|
885
|
+
for (const m of ["pushState", "replaceState"]) {
|
|
886
|
+
const orig = history[m];
|
|
887
|
+
history[m] = function(...args) {
|
|
888
|
+
const r = orig.apply(this, args);
|
|
889
|
+
window.dispatchEvent(new Event(LOCATION_CHANGE));
|
|
890
|
+
return r;
|
|
891
|
+
};
|
|
892
|
+
}
|
|
893
|
+
}
|
|
894
|
+
function onLocationChange(cb) {
|
|
895
|
+
patchHistory();
|
|
896
|
+
window.addEventListener("popstate", cb);
|
|
897
|
+
window.addEventListener(LOCATION_CHANGE, cb);
|
|
898
|
+
return () => {
|
|
899
|
+
window.removeEventListener("popstate", cb);
|
|
900
|
+
window.removeEventListener(LOCATION_CHANGE, cb);
|
|
901
|
+
};
|
|
902
|
+
}
|
|
903
|
+
|
|
868
904
|
// src/widget/BoardView.tsx
|
|
869
905
|
import { useEffect as useEffect2, useMemo, useState as useState2 } from "preact/hooks";
|
|
870
906
|
|
|
@@ -1335,8 +1371,9 @@ var STATUSES = [
|
|
|
1335
1371
|
];
|
|
1336
1372
|
var TYPES = ["bug", "feature", "question", "praise", "typo"];
|
|
1337
1373
|
var SEVERITIES = ["blocker", "high", "medium", "low"];
|
|
1338
|
-
function BoardView({ api, externalId, strings }) {
|
|
1374
|
+
function BoardView({ api, externalId, strings, getCurrentPage }) {
|
|
1339
1375
|
const [filters, setFilters] = useState2(() => loadBoardView(externalId));
|
|
1376
|
+
const [thisPage, setThisPage] = useState2(true);
|
|
1340
1377
|
useEffect2(() => {
|
|
1341
1378
|
saveBoardView(externalId, filters);
|
|
1342
1379
|
}, [externalId, filtersHash(filters)]);
|
|
@@ -1350,14 +1387,23 @@ function BoardView({ api, externalId, strings }) {
|
|
|
1350
1387
|
const activeFilterCount = useMemo(() => {
|
|
1351
1388
|
return (filters.status?.length ?? 0) + (filters.type?.length ?? 0) + (filters.severity?.length ?? 0) + (filters.q ? 1 : 0) + (filters.mine ? 1 : 0);
|
|
1352
1389
|
}, [filters]);
|
|
1390
|
+
useEffect2(() => {
|
|
1391
|
+
if (!thisPage) return;
|
|
1392
|
+
return onLocationChange(() => setReloadTick((t) => t + 1));
|
|
1393
|
+
}, [thisPage]);
|
|
1394
|
+
const fetchFilters = useMemo(
|
|
1395
|
+
() => thisPage ? { ...filters, pagePath: currentPagePath(getCurrentPage !== void 0 ? { getCurrentPage } : {}) } : filters,
|
|
1396
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
1397
|
+
[filtersHash(filters), thisPage, reloadTick]
|
|
1398
|
+
);
|
|
1353
1399
|
useEffect2(() => {
|
|
1354
1400
|
let cancelled = false;
|
|
1355
1401
|
let timer = null;
|
|
1356
1402
|
const tick = async () => {
|
|
1357
1403
|
try {
|
|
1358
1404
|
const [list, k] = await Promise.all([
|
|
1359
|
-
api.listBoard(externalId,
|
|
1360
|
-
api.fetchBoardKpis(externalId,
|
|
1405
|
+
api.listBoard(externalId, fetchFilters),
|
|
1406
|
+
api.fetchBoardKpis(externalId, fetchFilters)
|
|
1361
1407
|
]);
|
|
1362
1408
|
if (cancelled) return;
|
|
1363
1409
|
setPage(list);
|
|
@@ -1377,7 +1423,7 @@ function BoardView({ api, externalId, strings }) {
|
|
|
1377
1423
|
cancelled = true;
|
|
1378
1424
|
if (timer) clearTimeout(timer);
|
|
1379
1425
|
};
|
|
1380
|
-
}, [api, externalId,
|
|
1426
|
+
}, [api, externalId, JSON.stringify(fetchFilters)]);
|
|
1381
1427
|
const selectedRow = useMemo(() => {
|
|
1382
1428
|
if (!selectedId || !page) return null;
|
|
1383
1429
|
return page.results.find((r) => r.id === selectedId) ?? null;
|
|
@@ -1394,7 +1440,9 @@ function BoardView({ api, externalId, strings }) {
|
|
|
1394
1440
|
filters,
|
|
1395
1441
|
onChange: setFilters,
|
|
1396
1442
|
activeCount: activeFilterCount,
|
|
1397
|
-
strings
|
|
1443
|
+
strings,
|
|
1444
|
+
thisPage,
|
|
1445
|
+
onToggleThisPage: () => setThisPage((v) => !v)
|
|
1398
1446
|
}
|
|
1399
1447
|
),
|
|
1400
1448
|
/* @__PURE__ */ jsxs3("div", { class: "board-body", children: [
|
|
@@ -1502,7 +1550,9 @@ function BoardFilters({
|
|
|
1502
1550
|
filters,
|
|
1503
1551
|
onChange,
|
|
1504
1552
|
activeCount,
|
|
1505
|
-
strings
|
|
1553
|
+
strings,
|
|
1554
|
+
thisPage,
|
|
1555
|
+
onToggleThisPage
|
|
1506
1556
|
}) {
|
|
1507
1557
|
const setStatus = (value) => {
|
|
1508
1558
|
if (value === "") {
|
|
@@ -1614,6 +1664,19 @@ function BoardFilters({
|
|
|
1614
1664
|
),
|
|
1615
1665
|
/* @__PURE__ */ jsx3("span", { children: strings["board.filter.mine"] })
|
|
1616
1666
|
] }),
|
|
1667
|
+
/* @__PURE__ */ jsxs3(
|
|
1668
|
+
"button",
|
|
1669
|
+
{
|
|
1670
|
+
type: "button",
|
|
1671
|
+
class: `board-chip ${thisPage ? "board-chip--on" : ""}`,
|
|
1672
|
+
onClick: onToggleThisPage,
|
|
1673
|
+
children: [
|
|
1674
|
+
"\u{1F4CD} ",
|
|
1675
|
+
strings["board.scope.thisPage"],
|
|
1676
|
+
thisPage ? " \u2715" : ""
|
|
1677
|
+
]
|
|
1678
|
+
}
|
|
1679
|
+
),
|
|
1617
1680
|
activeCount > 0 && /* @__PURE__ */ jsxs3("button", { type: "button", class: "board-filter-clear", onClick: clear, children: [
|
|
1618
1681
|
/* @__PURE__ */ jsx3(CloseIcon, {}),
|
|
1619
1682
|
strings["board.filter.clear"]
|
|
@@ -4626,6 +4689,17 @@ function mountWidget(options) {
|
|
|
4626
4689
|
void _drop;
|
|
4627
4690
|
return rest;
|
|
4628
4691
|
}
|
|
4692
|
+
function openWidget(externalId) {
|
|
4693
|
+
rerender({ ...currentState, open: true, tab: "send" });
|
|
4694
|
+
if (options.openToCurrentPageFeedback && options.api && externalId) {
|
|
4695
|
+
options.api.fetchBoardKpis(externalId, { pagePath: currentPagePath(options) }).then((kpis) => {
|
|
4696
|
+
if (kpis.total > 0 && currentState.open && currentState.tab === "send") {
|
|
4697
|
+
rerender({ ...currentState, tab: "board" });
|
|
4698
|
+
}
|
|
4699
|
+
}).catch(() => {
|
|
4700
|
+
});
|
|
4701
|
+
}
|
|
4702
|
+
}
|
|
4629
4703
|
function Root({ state }) {
|
|
4630
4704
|
const handleSubmit = useCallback(async (values) => {
|
|
4631
4705
|
rerender({ ...currentState, status: "submitting" });
|
|
@@ -4685,7 +4759,7 @@ function mountWidget(options) {
|
|
|
4685
4759
|
Fab,
|
|
4686
4760
|
{
|
|
4687
4761
|
label: options.strings["fab.label"],
|
|
4688
|
-
onClick: () =>
|
|
4762
|
+
onClick: () => openWidget(externalId)
|
|
4689
4763
|
}
|
|
4690
4764
|
),
|
|
4691
4765
|
state.open && /* @__PURE__ */ jsxs12(
|
|
@@ -4786,7 +4860,8 @@ function mountWidget(options) {
|
|
|
4786
4860
|
{
|
|
4787
4861
|
api: options.api,
|
|
4788
4862
|
externalId,
|
|
4789
|
-
strings: options.strings
|
|
4863
|
+
strings: options.strings,
|
|
4864
|
+
...options.getCurrentPage !== void 0 && { getCurrentPage: options.getCurrentPage }
|
|
4790
4865
|
}
|
|
4791
4866
|
)
|
|
4792
4867
|
]
|
|
@@ -4797,7 +4872,7 @@ function mountWidget(options) {
|
|
|
4797
4872
|
rerender(currentState);
|
|
4798
4873
|
return {
|
|
4799
4874
|
open() {
|
|
4800
|
-
|
|
4875
|
+
openWidget(options.getExternalId?.());
|
|
4801
4876
|
},
|
|
4802
4877
|
close() {
|
|
4803
4878
|
rerender({ ...currentState, open: false, status: "idle" });
|
|
@@ -4880,11 +4955,13 @@ function createFeedback(config) {
|
|
|
4880
4955
|
capture_method: captureMethod,
|
|
4881
4956
|
technical_context
|
|
4882
4957
|
};
|
|
4883
|
-
if ("0.
|
|
4884
|
-
payload.widget_version = "0.
|
|
4958
|
+
if ("0.23.0") {
|
|
4959
|
+
payload.widget_version = "0.23.0";
|
|
4885
4960
|
}
|
|
4886
4961
|
if (manualScreenshot) payload.screenshot = manualScreenshot;
|
|
4887
4962
|
if (values.synthetic) payload.synthetic = true;
|
|
4963
|
+
const pagePath = currentPagePath(config);
|
|
4964
|
+
if (pagePath) payload.page_path = pagePath;
|
|
4888
4965
|
if (user?.id !== void 0 && user.id !== null && user.id !== "") {
|
|
4889
4966
|
payload.user = {
|
|
4890
4967
|
// The host can pass `id` as a string or number; the backend
|
|
@@ -4925,7 +5002,14 @@ function createFeedback(config) {
|
|
|
4925
5002
|
// Send the identified email alongside the id so an email-based allowlist
|
|
4926
5003
|
// can match (the backend matches external_id OR email). Read from `user`
|
|
4927
5004
|
// live so identity set after createFeedback() is reflected.
|
|
4928
|
-
checkVisibility: (externalId) => api.checkVisibility(externalId, user?.email)
|
|
5005
|
+
checkVisibility: (externalId) => api.checkVisibility(externalId, user?.email),
|
|
5006
|
+
// Thread the host's getCurrentPage override so the Board chip resolves
|
|
5007
|
+
// the page identically to what the submit side records (§ currentPage).
|
|
5008
|
+
...config.getCurrentPage !== void 0 && { getCurrentPage: config.getCurrentPage },
|
|
5009
|
+
// Opt-in: FAB opens to the page-scoped Board (default off → Send-first).
|
|
5010
|
+
...config.openToCurrentPageFeedback !== void 0 && {
|
|
5011
|
+
openToCurrentPageFeedback: config.openToCurrentPageFeedback
|
|
5012
|
+
}
|
|
4929
5013
|
});
|
|
4930
5014
|
let qaHandle;
|
|
4931
5015
|
let qaDisposed = false;
|
|
@@ -4992,4 +5076,4 @@ function createFeedback(config) {
|
|
|
4992
5076
|
export {
|
|
4993
5077
|
createFeedback
|
|
4994
5078
|
};
|
|
4995
|
-
//# sourceMappingURL=chunk-
|
|
5079
|
+
//# sourceMappingURL=chunk-NCNRU3SR.mjs.map
|