@sphoro/bugcatch-web-sdk 0.17.0 → 0.19.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.
Files changed (52) hide show
  1. package/README.md +104 -6
  2. package/dist/bugcatch-call.es.js +587 -0
  3. package/dist/bugcatch-call.es.js.map +1 -0
  4. package/dist/bugcatch-call.umd.js +2 -0
  5. package/dist/bugcatch-call.umd.js.map +1 -0
  6. package/dist/bugcatch-core.es.js +3292 -0
  7. package/dist/bugcatch-core.es.js.map +1 -0
  8. package/dist/bugcatch-panel.es.js +2531 -0
  9. package/dist/bugcatch-panel.es.js.map +1 -0
  10. package/dist/bugcatch-panel.umd.js +1311 -0
  11. package/dist/bugcatch-panel.umd.js.map +1 -0
  12. package/dist/bugcatch.es.js +2 -5625
  13. package/dist/bugcatch.es.js.map +1 -1
  14. package/dist/bugcatch.standalone.umd.js +1619 -0
  15. package/dist/bugcatch.standalone.umd.js.map +1 -0
  16. package/dist/bugcatch.umd.js +195 -1318
  17. package/dist/bugcatch.umd.js.map +1 -1
  18. package/package.json +6 -6
  19. package/src/accent.js +38 -0
  20. package/src/announcements.js +147 -0
  21. package/src/busy.js +18 -0
  22. package/src/call.js +7 -0
  23. package/src/capture.js +9 -0
  24. package/src/chunks.js +56 -0
  25. package/src/gesture.js +33 -0
  26. package/src/icons.js +18 -0
  27. package/src/identity.js +13 -8
  28. package/src/incoming-call.js +25 -45
  29. package/src/index.d.ts +93 -2
  30. package/src/index.js +164 -42
  31. package/src/lazy.js +23 -0
  32. package/src/notice.js +68 -0
  33. package/src/panel/call.js +242 -0
  34. package/src/panel/compose.js +416 -0
  35. package/src/panel/composer.js +235 -0
  36. package/src/panel/icons.js +36 -0
  37. package/src/panel/index.js +265 -0
  38. package/src/panel/known.js +130 -0
  39. package/src/panel/messages.js +176 -0
  40. package/src/panel/notices.js +34 -0
  41. package/src/panel/picks.js +65 -0
  42. package/src/panel/refs.js +321 -0
  43. package/src/panel/render.js +132 -0
  44. package/src/panel/signin.js +228 -0
  45. package/src/panel/styles.js +1016 -0
  46. package/src/panel/thread.js +494 -0
  47. package/src/session.js +8 -3
  48. package/src/umd/call.js +6 -0
  49. package/src/umd/lazy.js +98 -0
  50. package/src/umd/panel.js +6 -0
  51. package/src/updates.js +97 -34
  52. package/src/widget.js +385 -3376
package/README.md CHANGED
@@ -55,7 +55,7 @@ BugCatch.init({
55
55
  ```html
56
56
  <!-- Pin the version. Without one the CDN serves whatever is latest, so a
57
57
  future release changes behaviour on a site nobody redeployed. -->
58
- <script src="https://unpkg.com/@sphoro/bugcatch-web-sdk@0.17.0/dist/bugcatch.umd.js"></script>
58
+ <script src="https://unpkg.com/@sphoro/bugcatch-web-sdk@0.19.0/dist/bugcatch.umd.js"></script>
59
59
  <script>
60
60
  BugCatch.init({ apiBase: '…', apiKey: 'bc_live_…', projectId: '…' });
61
61
  </script>
@@ -65,6 +65,21 @@ A floating **Report a bug** button appears, and whatever the page was doing is
65
65
  attached to each report. Types ship with the package (`src/index.d.ts`), so
66
66
  editors autocomplete every option and method below.
67
67
 
68
+ The script is the launcher and the capture, and nothing more. The report panel
69
+ and the call code are separate files in `dist/` — `bugcatch-panel.umd.js` and
70
+ `bugcatch-call.umd.js` — fetched from the folder the script was loaded from the
71
+ first time they are needed: the panel once the page has settled (or when the
72
+ button is pressed, if that comes first), the call code when a call is offered.
73
+ From a bundler, the same two parts are `import()`ed and your bundler splits them.
74
+
75
+ - **Content-Security-Policy:** allow the host in `script-src`, not the one file.
76
+ A `nonce` on the script tag is carried over to the parts it loads.
77
+ - **Hosting it yourself:** copy every `dist/bugcatch*.umd.js` into one folder
78
+ and load `bugcatch.umd.js` from it. If the script cannot know its own address
79
+ — pasted inline, or concatenated into one of your files — point it at the
80
+ folder with `init({ chunkBase: '/vendor/bugcatch/' })`, or serve
81
+ `dist/bugcatch.standalone.umd.js`, which is all of it in one file.
82
+
68
83
  Call `init()` once, as early as you can — console and network capture start at
69
84
  `init()`, so anything before it is not recorded. `identify()` and `setContext()`
70
85
  may be called before or after it.
@@ -357,8 +372,8 @@ On top of that:
357
372
  | `onError` | — | See [Events](#events). |
358
373
  | `widget` | `true` | Floating launcher and panel. `false` to drive everything from your own UI. |
359
374
  | `widgetPosition` | `'bottom-right'` | `bottom-left`, `top-right`, `top-left`. |
360
- | `theme` | `'auto'` | `auto` follows the system; `light` / `dark` pin it. A visitor's own choice in the widget wins on later visits. |
361
- | `accent` | `'#4F46E5'` | Any CSS colour. |
375
+ | `theme` | `'auto'` | `auto` follows the system; `light` / `dark` pin it. Visitors can change it from the panel's header, and their choice wins on later visits. |
376
+ | `accent` | `null` | Any CSS colour, for the launcher, buttons and the assistant's orb. Text on it is white or near-black, whichever reads. `null` is ink: black on light, white on dark. |
362
377
  | `captureConsole` / `captureNetwork` / `captureErrors` | `true` | Each capture can be switched off. |
363
378
  | `consoleLimit` / `networkLimit` | `100` / `50` | Entries retained. |
364
379
  | `attachments` | `true` | Offer screenshot, recording and file attach. |
@@ -366,12 +381,14 @@ On top of that:
366
381
  | `drafts` | `true` | Recover an unfinished report on this device for seven days. |
367
382
  | `agentIssues` | `true` | Show the one-tap questions the assistant answers by itself. Draws nothing until the project turns the agent on. |
368
383
  | `knownIssues` | `true` | Show what this project already knows is broken, with "me too". Draws nothing until the project turns it on. |
384
+ | `announcements` | `true` | Show what your team publishes under Settings → Project → Widget announcements, in the panel and beside the button. Draws nothing until one is published. `false` to show them your own way with `announcements()`. |
369
385
  | `beforeSend` | — | Mutate the payload, or return `false` to cancel. |
370
386
  | `updates` | `true` | Tell the reporter live when a report they filed moves. |
371
387
  | `updateToast` | `true` | Show the built-in notification; `false` to render your own from `'update'` / `'unread'`. |
372
388
  | `onUpdate` | — | Called on every update. |
373
389
  | `voice` | `true` | Offer calls where the workspace has calling configured. `false` switches calls off in both directions. |
374
390
  | `onCallState` / `onIncomingCall` | — | See [Talking a report through](#talking-a-report-through). |
391
+ | `chunkBase` | the script's own folder | Script tag only: where the panel and call code are fetched from. Set it when the bundle is inlined or its `dist/` files are served elsewhere. |
375
392
 
376
393
  An option the SDK does not know is reported in the console with a suggestion
377
394
  (`unknown option "projectID" — did you mean "projectId"?`).
@@ -397,6 +414,8 @@ BugCatch.off(event, handler);
397
414
  await BugCatch.myReports(); // everything filed from this browser
398
415
  await BugCatch.myReport(bugId); // one report, with timeline and assistant phase
399
416
  await BugCatch.replyToReport(bugId, { body, attachments });
417
+ await BugCatch.verifyFix(bugId, { result, resolvedAt, note }); // 'CONFIRMED' | 'STILL_HAPPENING'
418
+ await BugCatch.rate(bugId, { score, comment }); // 1–5, once it is settled
400
419
  BugCatch.unreadUpdates(); BugCatch.markUpdateRead(id); BugCatch.markReportRead(bugId); BugCatch.markUpdatesRead();
401
420
  BugCatch.hasReports(); BugCatch.forgetReports();
402
421
 
@@ -406,6 +425,7 @@ await BugCatch.referenceFields(); // the identifier question this projec
406
425
  await BugCatch.agentIssues(); // one-tap questions the assistant answers and closes
407
426
 
408
427
  await BugCatch.knownIssues(); await BugCatch.matchKnownIssues(q, { signal }); await BugCatch.meToo(bugId);
428
+ await BugCatch.announcements(); BugCatch.dismissAnnouncement(a); // what your team is telling visitors
409
429
 
410
430
  await BugCatch.canCallNow(); await BugCatch.startCall(bugId?); BugCatch.endCall();
411
431
 
@@ -433,6 +453,7 @@ Turn on `debug: true` first: the console then shows what `init()` received, ever
433
453
  | `identify()` "did nothing" | It was called with a non-object (ignored with a warning), or an identifier was an object/array/too long. See the console. |
434
454
  | Reports are not attributed / no resolution email / no live updates / no Call button | `identify()` has no `email`. |
435
455
  | The panel will not open with `open()` | `widget: false` — there is no built-in panel; use `report()`. |
456
+ | *The report form didn't load* above the launcher | `bugcatch-panel.umd.js` could not be fetched from beside `bugcatch.umd.js` — the console names the address. Serve `dist/` together, allow it in `script-src`, or set `chunkBase`. |
436
457
  | Nothing is captured from before a certain point | Capture starts at `init()`. Call it as early as possible. |
437
458
 
438
459
  ## Reference
@@ -697,6 +718,37 @@ attachments stay images and video, because they are typed `SCREENSHOT` or
697
718
  `report.canReply` says whether this reader can write back; the widget hides its
698
719
  composer when it is false rather than offering a box that would fail on send.
699
720
 
721
+ ### Asking how it went
722
+
723
+ Once a report is resolved or closed, the widget asks the reporter **How did we
724
+ do?** under it: five stars, one tap to send, and a box for a note after the
725
+ tap rather than before — a form that asks for a sentence first is a form people
726
+ close. Their list of reports says **Rate it** against the settled ones still
727
+ waiting for a rating, and shows the score on the ones that have one.
728
+
729
+ The same rating is asked for on the reporter's own page and in the email that
730
+ tells them it was fixed, so whichever they answer is the one that counts.
731
+ Rating again replaces the earlier score. Whether a project asks at all is
732
+ **Project Settings → Resolutions → Ask the reporter to rate it**, on by default.
733
+
734
+ To drive it from your own UI:
735
+
736
+ ```js
737
+ const report = await BugCatch.myReport(id);
738
+
739
+ if (report.ratingAsked) {
740
+ // report.rating is null until they rate, then
741
+ // { score: 4, comment: 'Quick, thanks', ratedAt, via: 'widget', current: true }
742
+ await BugCatch.rate(id, { score: 4, comment: 'Quick, thanks' });
743
+ }
744
+ ```
745
+
746
+ `ratingAsked` is true only for a settled report on a project that asks; `rate()`
747
+ rejects otherwise. `rating.current` is false when the report was reopened and
748
+ fixed again after the rating was given — the rating stands, but it was about an
749
+ earlier fix. In `myReports()`, each row carries `rating` (the score, or null)
750
+ and `ratingAsked`.
751
+
700
752
  ### Reporting from your own UI
701
753
 
702
754
  ```js
@@ -815,6 +867,41 @@ this on, which is the default — draw nothing rather than an empty heading. Wha
815
867
  comes back is a title, a state and a count, and never a severity, an assignee or
816
868
  a description: the question it answers is "is this the thing I came here about".
817
869
 
870
+ ### Telling visitors something
871
+
872
+ Your team can put a notice in the widget from the dashboard, and change it or
873
+ take it down there, without redeploying your site: **Settings → Project → Widget
874
+ announcements**. "UPI payments are delayed today — we're on it, no need to
875
+ report it" is the reason it exists: said where people come to report, before
876
+ they type it out.
877
+
878
+ Each one picks where it appears:
879
+
880
+ - **In the widget**: at the top of the report panel, when somebody opens it.
881
+ - **Next to the button, too**: also as a small card beside the launcher on
882
+ every page, for people who came to do something else. Always closable.
883
+
884
+ A tone (info, success, warning, critical) picks the colour and the icon; info
885
+ wears your `accent`. A link is optional — a path like `/status` is a page on
886
+ your site, a full `https://` address opens a tab. Each runs between two days,
887
+ inclusive, on the visitor's own calendar, and the last day is required.
888
+ Closing one is remembered in that browser until somebody presses **Show it
889
+ again**; editing the wording does not reopen it.
890
+
891
+ A browser asks at most every five minutes, so a change reaches visitors within
892
+ that, and a project with nothing published costs one small request per browser
893
+ per five minutes.
894
+
895
+ ```js
896
+ // widget: false, or announcements: false — draw them your own way
897
+ const notices = await BugCatch.announcements();
898
+ // [{ id, title, body, tone, ctaLabel, ctaHref, placement, dismissible, ... }]
899
+ BugCatch.dismissAnnouncement(notices[0]);
900
+ ```
901
+
902
+ `announcements()` is already narrowed to the visitor's day and to what this
903
+ browser has not closed, and resolves to an empty list on every failure.
904
+
818
905
  ### Talking a report through
819
906
 
820
907
  Where the workspace has sphoro.voice configured, a reporter can talk to the team
@@ -961,8 +1048,8 @@ call, and if both are open, the first to answer gets it.
961
1048
  deployment without sphoro.voice and any workspace that has not switched calling
962
1049
  on, which is most of them. `canCallNow` additionally needs `identify()` to have
963
1050
  supplied an email: a call with nobody to attribute has no way to tell the
964
- reporter what happened next. Set `voice: false` to opt out entirely; the code is
965
- still in the bundle, but nothing runs.
1051
+ reporter what happened next. Set `voice: false` to opt out entirely; the call
1052
+ code is then never fetched, and nothing runs.
966
1053
 
967
1054
  ### Notes
968
1055
 
@@ -980,5 +1067,16 @@ still in the bundle, but nothing runs.
980
1067
 
981
1068
  ```bash
982
1069
  npm install
983
- npm run build # dist/bugcatch.es.js + dist/bugcatch.umd.js
1070
+ npm run build # every file below, into dist/ (scripts/build.mjs; the builds are in vite.config.js)
1071
+ npm run dev # the same, rebuilt on change
984
1072
  ```
1073
+
1074
+ | File | For |
1075
+ |---|---|
1076
+ | `bugcatch.es.js` (+ `bugcatch-core.es.js`, `bugcatch-panel.es.js`, `bugcatch-call.es.js`) | Bundlers. The panel and call code are `import()`ed, so they split off. |
1077
+ | `bugcatch.umd.js` | A `<script>` tag; `window.BugCatch`. Fetches the two below from beside itself. |
1078
+ | `bugcatch-panel.umd.js`, `bugcatch-call.umd.js` | Those parts, as scripts that register themselves with it. |
1079
+ | `bugcatch.standalone.umd.js` | All of it in one file, for a page that cannot load a second one. |
1080
+
1081
+ The build fails if the main script ends up containing either part, or if a part
1082
+ carries its own copy of something whose state belongs to the main script.