@sphoro/bugcatch-web-sdk 0.13.1 → 0.14.1
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 +48 -78
- package/dist/bugcatch.es.js +1752 -1685
- package/dist/bugcatch.es.js.map +1 -1
- package/dist/bugcatch.umd.js +154 -110
- package/dist/bugcatch.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/drafts.js +32 -0
- package/src/index.d.ts +114 -75
- package/src/index.js +147 -164
- package/src/references.js +172 -0
- package/src/updates.js +45 -74
- package/src/widget.js +320 -105
- package/src/voice.js +0 -372
package/README.md
CHANGED
|
@@ -60,9 +60,8 @@ doing gets attached to the report.
|
|
|
60
60
|
| `updates` | `true` | Tell the reporter, live, when a bug they filed moves. Connects only once this browser has filed something. |
|
|
61
61
|
| `updateToast` | `true` | Show the built-in notification. It stays until the reporter marks it read — a reload included. Set `false` to render your own. |
|
|
62
62
|
| `onUpdate` | — | `{ id, bugId, title, kind, summary, at }` on every update, whether or not the built-in notification is shown. |
|
|
63
|
-
| `voice` | `true` | Offer a
|
|
64
|
-
| `onCallState` | — | `('connecting' \| '
|
|
65
|
-
| `onCallTranscript` | — | `{ bugId, role, text, final }` for each line, as it is recognised. |
|
|
63
|
+
| `voice` | `true` | Offer a call to the team when a report is picked up, where the workspace has calling configured. Nothing is dialled and no microphone is asked for until the reporter presses the button — see [Talking a report through](#talking-a-report-through). |
|
|
64
|
+
| `onCallState` | — | `('ringing' \| 'connecting' \| 'connected' \| 'missed' \| 'ended' \| 'failed', { bugId })` as a call moves. |
|
|
66
65
|
|
|
67
66
|
## Screenshots, recordings and files
|
|
68
67
|
|
|
@@ -127,19 +126,19 @@ await BugCatch.matchKnownIssues(q, { signal }); // the ones matching what they
|
|
|
127
126
|
await BugCatch.meToo(bugId, { email }); // join a report instead of filing a second
|
|
128
127
|
|
|
129
128
|
await BugCatch.canCallNow(); // may this visitor call instead of typing?
|
|
130
|
-
await BugCatch.startCall(); // file a report and
|
|
129
|
+
await BugCatch.startCall(); // file a report and ring the team about it
|
|
131
130
|
await BugCatch.canCall(bugId); // may this report be talked through?
|
|
132
|
-
await BugCatch.startCall(bugId); //
|
|
133
|
-
await BugCatch.canCallTeam(bugId); //
|
|
134
|
-
await BugCatch.startLiveCall(bugId); //
|
|
131
|
+
await BugCatch.startCall(bugId); // ring the team about an existing report
|
|
132
|
+
await BugCatch.canCallTeam(bugId); // the same question, under the widget's name
|
|
133
|
+
await BugCatch.startLiveCall(bugId); // the same call, under its older name
|
|
135
134
|
BugCatch.on('incoming-call', fn); // the team ringing *them* — the SDK draws the card
|
|
136
|
-
BugCatch.endCall(); // hang up
|
|
135
|
+
BugCatch.endCall(); // hang up
|
|
137
136
|
```
|
|
138
137
|
|
|
139
138
|
### Telling BugCatch who is reporting
|
|
140
139
|
|
|
141
140
|
```js
|
|
142
|
-
BugCatch.identify({ id: 'u_42', email: 'alex@
|
|
141
|
+
BugCatch.identify({ id: 'u_42', email: 'alex@example.com', name: 'Alex' });
|
|
143
142
|
|
|
144
143
|
// On sign-out
|
|
145
144
|
BugCatch.identify(null);
|
|
@@ -195,8 +194,8 @@ The built-in widget draws all of this itself. With `widget: false` you drive it:
|
|
|
195
194
|
```js
|
|
196
195
|
const { mode, signedIn } = await BugCatch.loginState();
|
|
197
196
|
if (mode !== 'off' && !signedIn) {
|
|
198
|
-
await BugCatch.signIn('alex@
|
|
199
|
-
await BugCatch.confirmSignIn('alex@
|
|
197
|
+
await BugCatch.signIn('alex@example.com'); // a code goes out
|
|
198
|
+
await BugCatch.confirmSignIn('alex@example.com', code); // whatever they typed back
|
|
200
199
|
}
|
|
201
200
|
```
|
|
202
201
|
|
|
@@ -217,7 +216,7 @@ happens:
|
|
|
217
216
|
|
|
218
217
|
```js
|
|
219
218
|
BugCatch.init({ apiKey, projectId });
|
|
220
|
-
BugCatch.identify({ email: 'alex@
|
|
219
|
+
BugCatch.identify({ email: 'alex@example.com', name: 'Alex' });
|
|
221
220
|
// Alex reports a bug. Later, someone marks it resolved —
|
|
222
221
|
// Alex sees "Your report has been fixed" without leaving your app.
|
|
223
222
|
```
|
|
@@ -506,104 +505,76 @@ a description: the question it answers is "is this the thing I came here about".
|
|
|
506
505
|
|
|
507
506
|
## Talking a report through
|
|
508
507
|
|
|
509
|
-
Where the workspace has sphoro.voice configured, a reporter can talk
|
|
510
|
-
|
|
508
|
+
Where the workspace has sphoro.voice configured, a reporter can talk to the team
|
|
509
|
+
instead of typing. There are two ways in.
|
|
511
510
|
|
|
512
|
-
**Instead of the form.** A **Talk to
|
|
513
|
-
Pressing it files the report
|
|
514
|
-
environment the SDK is already holding — and
|
|
515
|
-
|
|
511
|
+
**Instead of the form.** A **Talk to the team** button appears next to *Send
|
|
512
|
+
report*. Pressing it asks for the microphone, files the report — carrying the
|
|
513
|
+
console, network and environment the SDK is already holding — and rings the team
|
|
514
|
+
about it. The report is written before the phones ring, so a call nobody answers
|
|
516
515
|
still leaves the context behind, and it opens unassigned: whoever takes it in
|
|
517
|
-
the dashboard owns it.
|
|
518
|
-
thing the reporter actually says.
|
|
516
|
+
the dashboard owns it.
|
|
519
517
|
|
|
520
518
|
**After somebody picks it up.** When a report is assigned, its reporter is
|
|
521
|
-
offered a call about it
|
|
522
|
-
and what it learns lands in the report's thread.
|
|
519
|
+
offered a call about it, and the open report's composer grows a phone button.
|
|
523
520
|
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
521
|
+
The other end is a colleague, not software. The audio travels directly between
|
|
522
|
+
the two browsers over WebRTC and never reaches BugCatch or sphoro.voice, so
|
|
523
|
+
there is no transcript — the report's thread gets a note saying the call
|
|
524
|
+
happened, who took it and how long it lasted. It goes both ways: the team can
|
|
525
|
+
ring back, which is the section after this one.
|
|
527
526
|
|
|
528
527
|
```js
|
|
529
528
|
BugCatch.init({
|
|
530
529
|
apiBase: '…', apiKey: '…', projectId: '…',
|
|
531
|
-
onCallState: (state) => setStatus(state),
|
|
532
|
-
onCallTranscript: ({ role, text }) => appendLine(role, text),
|
|
530
|
+
onCallState: (state) => setStatus(state), // 'ringing' → 'connected' → 'ended'
|
|
533
531
|
});
|
|
534
532
|
```
|
|
535
533
|
|
|
536
|
-
Both affordances are built in: the **Talk to
|
|
537
|
-
with `updateToast` on, the default — a **Talk it through** button on the
|
|
538
|
-
card when a report is picked up (pressing it marks that update read:
|
|
539
|
-
notification is the clearest way there is of having seen it). To
|
|
534
|
+
Both affordances are built in: the **Talk to the team** button on the composer,
|
|
535
|
+
and — with `updateToast` on, the default — a **Talk it through** button on the
|
|
536
|
+
update card when a report is picked up (pressing it marks that update read:
|
|
537
|
+
acting on a notification is the clearest way there is of having seen it). To
|
|
538
|
+
render your own instead:
|
|
540
539
|
|
|
541
540
|
```js
|
|
542
|
-
// Instead of the form: files a report and
|
|
541
|
+
// Instead of the form: files a report and rings the team about it.
|
|
543
542
|
if (await BugCatch.canCallNow()) {
|
|
544
|
-
const call = await BugCatch.startCall();
|
|
543
|
+
const call = await BugCatch.startCall(); // resolves once it is *ringing*
|
|
545
544
|
call.bugId; // what it was filed as
|
|
545
|
+
call.setMuted(true);
|
|
546
|
+
call.hangUp();
|
|
546
547
|
}
|
|
547
548
|
|
|
548
549
|
// About a report already filed.
|
|
549
550
|
if (await BugCatch.canCall(bugId)) {
|
|
550
551
|
await BugCatch.startCall(bugId);
|
|
551
552
|
}
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
`startCall()` with no id rejects with `.filed` set when the report was written
|
|
555
|
-
but no call could be placed — the report still exists, and telling the reporter
|
|
556
|
-
otherwise would have them file it twice.
|
|
557
|
-
|
|
558
|
-
Three things are worth being explicit about, because they are what people ask:
|
|
559
|
-
|
|
560
|
-
- **Nobody from the team is on the line.** The agent is software, it says so,
|
|
561
|
-
and the team reads the transcript afterwards. Nothing rings anywhere. (Unless
|
|
562
|
-
it is a *live* call — see below, which is the other feature entirely.)
|
|
563
|
-
- **The microphone is asked for on the press, never before.** An offer that
|
|
564
|
-
raised a permission prompt on arrival would be a page listening to somebody
|
|
565
|
-
who walked away from it.
|
|
566
|
-
- **One call at a time**, and `destroy()` ends it. Two microphones on one page
|
|
567
|
-
transcribe each other.
|
|
568
|
-
|
|
569
|
-
### Calling a person instead
|
|
570
553
|
|
|
571
|
-
|
|
572
|
-
rings the team, and whoever is free picks it up. It goes both ways — the team
|
|
573
|
-
can ring back, which is the section after this one.
|
|
574
|
-
|
|
575
|
-
```js
|
|
576
|
-
if (await BugCatch.canCallTeam(bugId)) {
|
|
577
|
-
const call = await BugCatch.startLiveCall(bugId); // resolves once it is *ringing*
|
|
578
|
-
call.setMuted(true);
|
|
579
|
-
call.hangUp();
|
|
580
|
-
}
|
|
581
|
-
|
|
582
|
-
BugCatch.on('call', ({ live, state }) => {
|
|
583
|
-
if (!live) return;
|
|
554
|
+
BugCatch.on('call', ({ state }) => {
|
|
584
555
|
// 'ringing' → 'connecting' → 'connected' → 'ended'
|
|
585
556
|
// or 'ringing' → 'missed', when nobody picked up in about twenty seconds.
|
|
586
557
|
});
|
|
587
558
|
```
|
|
588
559
|
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
560
|
+
`startCall()` with no id rejects with `.filed` set when the report was written
|
|
561
|
+
but nobody could be rung — the report still exists, and telling the reporter
|
|
562
|
+
otherwise would have them file it twice. `startLiveCall()` is the same call
|
|
563
|
+
under its older name, from when this was one of two kinds.
|
|
592
564
|
|
|
593
|
-
|
|
565
|
+
Four things are worth being explicit about, because they are what people ask:
|
|
594
566
|
|
|
595
567
|
- **It is a real person, and it is not recorded.** The audio goes directly
|
|
596
|
-
between the two browsers
|
|
597
|
-
|
|
598
|
-
saying the call happened, who took it and how long it lasted.
|
|
568
|
+
between the two browsers, so there is no transcript for the team to read
|
|
569
|
+
instead of answering. The thread gets a note saying the call happened.
|
|
599
570
|
- **It can go unanswered.** It rings everybody who can see the report for about
|
|
600
571
|
twenty seconds; if nobody is free, the state is `missed` and the reporter is
|
|
601
572
|
pointed back at the chat.
|
|
602
|
-
- **
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
- **One
|
|
606
|
-
|
|
573
|
+
- **The microphone is asked for on the press, never before.** An offer that
|
|
574
|
+
raised a permission prompt on arrival would be a page listening to somebody
|
|
575
|
+
who walked away from it.
|
|
576
|
+
- **One call at a time**, and `destroy()` ends it. Two microphones on one page
|
|
577
|
+
talk over each other.
|
|
607
578
|
|
|
608
579
|
### Being called
|
|
609
580
|
|
|
@@ -679,8 +650,7 @@ deployment without sphoro.voice and any workspace that has not switched calling
|
|
|
679
650
|
on, which is most of them. `canCallNow` additionally needs `identify()` to have
|
|
680
651
|
supplied an email: a call with nobody to attribute has no way to tell the
|
|
681
652
|
reporter what happened next. Set `voice: false` to opt out entirely; the code is
|
|
682
|
-
still in the bundle
|
|
683
|
-
does not ship), but nothing runs.
|
|
653
|
+
still in the bundle, but nothing runs.
|
|
684
654
|
|
|
685
655
|
## What is captured
|
|
686
656
|
|