@webority/support-react 0.13.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/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ Copyright (c) Webority Technologies. All rights reserved.
2
+
3
+ This software and its source code are proprietary and confidential to
4
+ Webority Technologies. Use is restricted to Webority products and teams under
5
+ internal license. Redistribution outside Webority Technologies is prohibited.
package/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # @webority/support-react
2
+
3
+ Customer support for a React portal: a ticket centre, a report-an-issue button that attaches a
4
+ screenshot of the page, and support contact details. It talks to the Webority Support API that
5
+ the product's backend hosts, and it is built on `@webority/ui-react` and `@webority/theme`, so it
6
+ looks like the rest of the portal with no extra CSS.
7
+
8
+ ## Install
9
+
10
+ ```bash
11
+ npm install @webority/support-react @webority/ui-react react-bootstrap bootstrap@5.3.3
12
+ ```
13
+
14
+ `@webority/ui-react`, `react`, `react-dom`, `react-bootstrap` and `bootstrap` are peer
15
+ dependencies: the portal already has them. Pin `@webority/support-react` to the same exact
16
+ version as `@webority/ui-react`. The screenshot uses `html-to-image`, which installs with the
17
+ package.
18
+
19
+ ## Set up the provider
20
+
21
+ Give the provider a client built on the portal's own HTTP instance. That instance already
22
+ carries the bearer token and refreshes it, so the support calls sign in the same way as every
23
+ other call. Attachments are fetched through it too, so private files never need a public URL.
24
+
25
+ ```jsx
26
+ import { createSupportClient, SupportProvider } from "@webority/support-react";
27
+ import { userClient } from "./services/api/clients";
28
+
29
+ const supportClient = createSupportClient(userClient, "/api/support");
30
+
31
+ export function App() {
32
+ return (
33
+ <SupportProvider client={supportClient}>
34
+ <Routes />
35
+ </SupportProvider>
36
+ );
37
+ }
38
+ ```
39
+
40
+ `createSupportClient(http, basePath = "/api/support")` accepts any axios-like instance with
41
+ `get(url, config)` and `post(url, data, config)` that resolve to `{ data }`. Every method
42
+ rejects with a `SupportApiError` carrying `code`, `status` and a `message` written for the
43
+ person, which the components show as-is.
44
+
45
+ | Method | Request |
46
+ |---|---|
47
+ | `getConfig()` | `GET {base}/config` |
48
+ | `listTickets()` | `GET {base}/tickets` |
49
+ | `getTicket(id)` | `GET {base}/tickets/{id}` |
50
+ | `createTicket({ category, subject, body, pageUrl, userAgent, appVersion, files, screenshots })` | `POST {base}/tickets`, multipart |
51
+ | `reply(id, { body, files, screenshots })` | `POST {base}/tickets/{id}/replies`, multipart |
52
+ | `reopen(id)` | `POST {base}/tickets/{id}/reopen` |
53
+ | `rate(id, { satisfaction, comment })` | `POST {base}/tickets/{id}/rating`, JSON |
54
+ | `fetchAttachment(id)` | `GET {base}/attachments/{id}`, returns a `Blob` |
55
+
56
+ ## Components
57
+
58
+ ### `<SupportCenter />`
59
+
60
+ The support page: the customer's tickets with status tabs and a search box, one ticket's
61
+ conversation, and a New ticket dialog.
62
+
63
+ ```jsx
64
+ <SupportCenter appVersion={import.meta.env.VITE_APP_VERSION} defaultCategory="Question" />
65
+ ```
66
+
67
+ | Prop | What it does |
68
+ |---|---|
69
+ | `initialTicketId` | Open this ticket first. |
70
+ | `defaultCategory` | Preselected in the New ticket form when the config lists it. |
71
+ | `appVersion` | Recorded on new tickets so support knows which build you were on. |
72
+
73
+ Support emails link to the support page with `?ticket=<id>`. The centre opens that ticket and
74
+ keeps the parameter in step as tickets open and close, so a refresh stays on the same ticket.
75
+ In a ticket the customer can reply with files (pasting an image into the message attaches it),
76
+ reopen a settled ticket, and say whether it solved their problem. Files are checked against the
77
+ config's type, size and count limits before anything uploads.
78
+
79
+ ### `<ReportIssue />`
80
+
81
+ A button that takes a screenshot of the current page, then opens a dialog to describe the
82
+ problem. The person can remove the screenshot and add more images by picking, dropping or
83
+ pasting them. The ticket records the page address, the browser and the product version.
84
+
85
+ ```jsx
86
+ <ReportIssue floating appVersion={version} getTicketHref={(id) => `/support?ticket=${id}`} />
87
+ ```
88
+
89
+ | Prop | What it does |
90
+ |---|---|
91
+ | `label` | Button text. Default "Report an issue". |
92
+ | `floating` | Pin the button to the bottom corner of the screen. |
93
+ | `defaultCategory` | Preselected when the config lists it. Default "Bug report". |
94
+ | `appVersion` | Recorded on the ticket. |
95
+ | `getTicketHref(id)` | Shows a View ticket link to the new ticket. |
96
+ | `onOpenTicket(ticket)` | Called by the View ticket button when there is no href. |
97
+ | `onCreated(ticket)` | Called once the ticket is raised. |
98
+
99
+ The screenshot is taken before the dialog opens, and the button itself is left out of it.
100
+ Anything else the page marks with `data-support-capture="exclude"` is left out too.
101
+
102
+ ### `<SupportContact />`
103
+
104
+ The support email with a copy button, the phone number as a call link, and the hours, from the
105
+ support config. A field the product has not set is left out, and nothing renders when none is.
106
+
107
+ ```jsx
108
+ <SupportContact />
109
+ ```
110
+
111
+ ## Hooks
112
+
113
+ `useSupportConfig()`, `useSupportTickets()` and `useSupportTicket(id)` return the data with
114
+ `loading`, `error` and `reload`. `useSupportTicket` also returns `reply`, `reopen` and `rate`,
115
+ each resolving to the updated ticket. `useSupportClient()` returns the client itself.
116
+
117
+ ## Display rules
118
+
119
+ Status text always comes from the API's `statusLabel`. Times show in the viewer's own time zone
120
+ with the zone named.