@checkstack/integration-frontend 0.4.4 → 0.4.5
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/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,89 @@
|
|
|
1
1
|
# @checkstack/integration-frontend
|
|
2
2
|
|
|
3
|
+
## 0.4.5
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- f23f3c9: Retrofit the highest-traffic configuration list tables
|
|
8
|
+
(`HealthCheckList`, `SloConfigPage`, and the integration
|
|
9
|
+
`DeliveryLogsPage`) onto the `ResponsiveTable` + `MobileCardList`
|
|
10
|
+
primitives from `@checkstack/ui`. On `sm` and up each page still
|
|
11
|
+
renders the unchanged 5- to 7-column table; below that breakpoint a
|
|
12
|
+
sibling stacked-card layout surfaces the same data with the resource
|
|
13
|
+
name + status badge at the top, secondary columns in a muted line, and
|
|
14
|
+
the existing action buttons in a right-aligned footer. The
|
|
15
|
+
`HealthCheckListSkeleton` placeholder mirrors both branches so the page
|
|
16
|
+
no longer jumps when data resolves. No business logic, column order,
|
|
17
|
+
or query inputs changed.
|
|
18
|
+
- f23f3c9: Sweep every paginated `*-common` contract onto the canonical
|
|
19
|
+
`PaginationInput` / `PaginatedResult` from `@checkstack/common` and
|
|
20
|
+
remove the now-unused legacy exports.
|
|
21
|
+
|
|
22
|
+
**BREAKING CHANGE** - `@checkstack/common` drops the deprecated
|
|
23
|
+
`PaginationInputSchema`, `paginatedOutput`, and `PaginatedResponse`
|
|
24
|
+
symbols. Callers must consume `PaginationInput` (input) and
|
|
25
|
+
`PaginatedResult(itemSchema)` (output) instead. The canonical input is
|
|
26
|
+
`{ limit (1-100, default 20), offset (>= 0, default 0) }`; the
|
|
27
|
+
canonical output envelope is
|
|
28
|
+
`{ items, total, limit, offset }`.
|
|
29
|
+
|
|
30
|
+
**BREAKING CHANGE** - `@checkstack/notification-common` migrates
|
|
31
|
+
`getNotifications` off the legacy `PaginationInputSchema`
|
|
32
|
+
(`{ limit, offset, unreadOnly }` with output `{ notifications, total }`)
|
|
33
|
+
onto `ListNotificationsInputSchema =
|
|
34
|
+
PaginationInput.extend({ unreadOnly })` and
|
|
35
|
+
`PaginatedResult(NotificationSchema)`. The output key changes from
|
|
36
|
+
`notifications` to `items`, and `limit` / `offset` are now echoed on
|
|
37
|
+
the response. The `PaginationInput` type alias previously exported
|
|
38
|
+
from `notification-common` is removed - use `ListNotificationsInput`
|
|
39
|
+
or the canonical `PaginationInput` from `@checkstack/common`.
|
|
40
|
+
|
|
41
|
+
**BREAKING CHANGE** - `@checkstack/integration-common` migrates
|
|
42
|
+
`listSubscriptions` (inline `{ page, pageSize, ... }` -> output
|
|
43
|
+
`{ subscriptions, total }`) and `getDeliveryLogs` (via
|
|
44
|
+
`DeliveryLogQueryInputSchema` `{ subscriptionId?, eventType?, status?,
|
|
45
|
+
page, pageSize }` -> output `{ logs, total }`) onto the canonical
|
|
46
|
+
`PaginationInput.extend({...})` input and
|
|
47
|
+
`PaginatedResult(itemSchema)` output. External callers must switch
|
|
48
|
+
from `{ page, pageSize }` to `{ limit, offset }` and read response
|
|
49
|
+
items from `data.items` (no more `data.subscriptions` / `data.logs`).
|
|
50
|
+
|
|
51
|
+
The matching `*-backend` handlers were updated to consume the new
|
|
52
|
+
input shape (`offset` arithmetic in lieu of `(page - 1) * pageSize`)
|
|
53
|
+
and to echo `limit` / `offset` on the response. The `*-frontend` call
|
|
54
|
+
sites in `NotificationsPage`, `NotificationBell`, `IntegrationsPage`,
|
|
55
|
+
and `DeliveryLogsPage` were updated to send the new input shape and
|
|
56
|
+
read `data.items`.
|
|
57
|
+
|
|
58
|
+
- f23f3c9: Gate decorative motion and blur effects behind
|
|
59
|
+
`usePerformance().isLowPower` on a focused set of high-traffic plugin
|
|
60
|
+
pages (Dashboard, Dependency map, System node, Notification bell,
|
|
61
|
+
Announcement banner / cards, Anomaly field overrides editor, SLO
|
|
62
|
+
attribution chart, Catalog droppable group). Hover scales, backdrop
|
|
63
|
+
blurs, `animate-pulse`/`animate-ping` accents, and entry transitions
|
|
64
|
+
now drop to static states on low-power devices; functional UX
|
|
65
|
+
transitions (Drawer/Dialog open-close, colour transitions) are left
|
|
66
|
+
alone.
|
|
67
|
+
|
|
68
|
+
Standardise the post-mutation error-toast voice on plugin pages by
|
|
69
|
+
migrating multi-clause `toast.error(extractErrorMessage(error, "Failed
|
|
70
|
+
to X"))` call sites onto the `toastError(toast, "Failed to X", error)`
|
|
71
|
+
helper from `@checkstack/ui`. The helper applies the canonical
|
|
72
|
+
`"action: message"` prefix and 100-character truncation in one place,
|
|
73
|
+
and the now-orphaned `extractErrorMessage` imports are dropped from
|
|
74
|
+
the affected files. No business logic or component APIs changed.
|
|
75
|
+
|
|
76
|
+
- Updated dependencies [f23f3c9]
|
|
77
|
+
- Updated dependencies [f23f3c9]
|
|
78
|
+
- Updated dependencies [f23f3c9]
|
|
79
|
+
- Updated dependencies [f23f3c9]
|
|
80
|
+
- @checkstack/common@0.11.0
|
|
81
|
+
- @checkstack/frontend-api@0.5.2
|
|
82
|
+
- @checkstack/integration-common@0.5.0
|
|
83
|
+
- @checkstack/ui@1.10.0
|
|
84
|
+
- @checkstack/tips-frontend@0.2.5
|
|
85
|
+
- @checkstack/signal-frontend@0.1.4
|
|
86
|
+
|
|
3
87
|
## 0.4.4
|
|
4
88
|
|
|
5
89
|
### Patch Changes
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@checkstack/integration-frontend",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.5",
|
|
4
4
|
"license": "Elastic-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "src/index.tsx",
|
|
@@ -17,8 +17,8 @@
|
|
|
17
17
|
"@checkstack/frontend-api": "0.5.1",
|
|
18
18
|
"@checkstack/integration-common": "0.4.0",
|
|
19
19
|
"@checkstack/signal-frontend": "0.1.3",
|
|
20
|
-
"@checkstack/tips-frontend": "0.2.
|
|
21
|
-
"@checkstack/ui": "1.
|
|
20
|
+
"@checkstack/tips-frontend": "0.2.4",
|
|
21
|
+
"@checkstack/ui": "1.9.0",
|
|
22
22
|
"lucide-react": "^0.344.0",
|
|
23
23
|
"react": "^18.2.0",
|
|
24
24
|
"react-router-dom": "^6.22.0"
|
|
@@ -23,10 +23,11 @@ import {
|
|
|
23
23
|
SelectValue,
|
|
24
24
|
Label,
|
|
25
25
|
ConfirmationModal,
|
|
26
|
+
toastError,
|
|
26
27
|
type LucideIconName,
|
|
27
28
|
} from "@checkstack/ui";
|
|
28
29
|
import { usePluginClient } from "@checkstack/frontend-api";
|
|
29
|
-
import { resolveRoute
|
|
30
|
+
import { resolveRoute } from "@checkstack/common";
|
|
30
31
|
import {
|
|
31
32
|
IntegrationApi,
|
|
32
33
|
integrationRoutes,
|
|
@@ -128,7 +129,7 @@ export const SubscriptionDialog = ({
|
|
|
128
129
|
setSaving(false);
|
|
129
130
|
},
|
|
130
131
|
onError: (error) => {
|
|
131
|
-
toast
|
|
132
|
+
toastError(toast, "Failed to create subscription", error);
|
|
132
133
|
setSaving(false);
|
|
133
134
|
},
|
|
134
135
|
});
|
|
@@ -141,7 +142,7 @@ export const SubscriptionDialog = ({
|
|
|
141
142
|
setSaving(false);
|
|
142
143
|
},
|
|
143
144
|
onError: (error) => {
|
|
144
|
-
toast
|
|
145
|
+
toastError(toast, "Failed to update subscription", error);
|
|
145
146
|
setSaving(false);
|
|
146
147
|
},
|
|
147
148
|
});
|
|
@@ -153,7 +154,7 @@ export const SubscriptionDialog = ({
|
|
|
153
154
|
onOpenChange(false);
|
|
154
155
|
},
|
|
155
156
|
onError: (error) => {
|
|
156
|
-
toast
|
|
157
|
+
toastError(toast, "Failed to delete subscription", error);
|
|
157
158
|
},
|
|
158
159
|
});
|
|
159
160
|
|
|
@@ -24,6 +24,8 @@ import {
|
|
|
24
24
|
usePagination,
|
|
25
25
|
usePaginationSync,
|
|
26
26
|
BackLink,
|
|
27
|
+
ResponsiveTable,
|
|
28
|
+
MobileCardList,
|
|
27
29
|
} from "@checkstack/ui";
|
|
28
30
|
import { usePluginClient } from "@checkstack/frontend-api";
|
|
29
31
|
import { resolveRoute } from "@checkstack/common";
|
|
@@ -70,17 +72,16 @@ export const DeliveryLogsPage = () => {
|
|
|
70
72
|
const pagination = usePagination({ defaultLimit: 20 });
|
|
71
73
|
|
|
72
74
|
// Fetch data with useQuery
|
|
73
|
-
const page = Math.floor(pagination.offset / pagination.limit) + 1;
|
|
74
75
|
const { data, isLoading, refetch } =
|
|
75
76
|
integrationClient.getDeliveryLogs.useQuery({
|
|
76
|
-
|
|
77
|
-
|
|
77
|
+
limit: pagination.limit,
|
|
78
|
+
offset: pagination.offset,
|
|
78
79
|
});
|
|
79
80
|
|
|
80
81
|
// Sync total from response
|
|
81
82
|
usePaginationSync(pagination, data?.total);
|
|
82
83
|
|
|
83
|
-
const logs = data?.
|
|
84
|
+
const logs = data?.items ?? [];
|
|
84
85
|
|
|
85
86
|
// Retry mutation
|
|
86
87
|
const retryMutation = integrationClient.retryDelivery.useMutation({
|
|
@@ -132,81 +133,141 @@ export const DeliveryLogsPage = () => {
|
|
|
132
133
|
</div>
|
|
133
134
|
</Card>
|
|
134
135
|
) : (
|
|
135
|
-
|
|
136
|
-
<
|
|
137
|
-
<
|
|
138
|
-
<
|
|
139
|
-
<
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
<TableBody>
|
|
149
|
-
{logs.map((log: DeliveryLog) => {
|
|
150
|
-
const config = statusConfig[log.status];
|
|
151
|
-
return (
|
|
152
|
-
<TableRow key={log.id}>
|
|
153
|
-
<TableCell>
|
|
154
|
-
<Badge
|
|
155
|
-
variant={config.variant}
|
|
156
|
-
className="flex items-center gap-1 w-fit"
|
|
157
|
-
>
|
|
158
|
-
{config.icon}
|
|
159
|
-
{log.status}
|
|
160
|
-
</Badge>
|
|
161
|
-
</TableCell>
|
|
162
|
-
<TableCell>
|
|
163
|
-
<div className="font-medium">
|
|
164
|
-
{log.subscriptionName ?? "Unknown"}
|
|
165
|
-
</div>
|
|
166
|
-
</TableCell>
|
|
167
|
-
<TableCell>
|
|
168
|
-
<div className="text-sm font-mono">
|
|
169
|
-
{log.eventType}
|
|
170
|
-
</div>
|
|
171
|
-
</TableCell>
|
|
172
|
-
<TableCell>{log.attempts}</TableCell>
|
|
173
|
-
<TableCell>
|
|
174
|
-
<div className="text-sm text-muted-foreground">
|
|
175
|
-
{new Date(log.createdAt).toLocaleString()}
|
|
176
|
-
</div>
|
|
177
|
-
</TableCell>
|
|
178
|
-
<TableCell>
|
|
179
|
-
{log.errorMessage ? (
|
|
180
|
-
<div
|
|
181
|
-
className="text-sm text-destructive max-w-[200px] truncate"
|
|
182
|
-
title={log.errorMessage}
|
|
183
|
-
>
|
|
184
|
-
{log.errorMessage}
|
|
185
|
-
</div>
|
|
186
|
-
) : undefined}
|
|
187
|
-
</TableCell>
|
|
188
|
-
<TableCell>
|
|
189
|
-
{log.status === "failed" && (
|
|
190
|
-
<Button
|
|
191
|
-
variant="ghost"
|
|
192
|
-
size="sm"
|
|
193
|
-
onClick={() => handleRetry(log.id)}
|
|
194
|
-
disabled={retrying === log.id}
|
|
195
|
-
>
|
|
196
|
-
<RefreshCw
|
|
197
|
-
className={`h-4 w-4 mr-1 ${
|
|
198
|
-
retrying === log.id ? "animate-spin" : ""
|
|
199
|
-
}`}
|
|
200
|
-
/>
|
|
201
|
-
Retry
|
|
202
|
-
</Button>
|
|
203
|
-
)}
|
|
204
|
-
</TableCell>
|
|
136
|
+
<>
|
|
137
|
+
<ResponsiveTable>
|
|
138
|
+
<Card>
|
|
139
|
+
<Table>
|
|
140
|
+
<TableHeader>
|
|
141
|
+
<TableRow>
|
|
142
|
+
<TableHead>Status</TableHead>
|
|
143
|
+
<TableHead>Subscription</TableHead>
|
|
144
|
+
<TableHead>Event</TableHead>
|
|
145
|
+
<TableHead>Attempts</TableHead>
|
|
146
|
+
<TableHead>Created</TableHead>
|
|
147
|
+
<TableHead>Error</TableHead>
|
|
148
|
+
<TableHead></TableHead>
|
|
205
149
|
</TableRow>
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
150
|
+
</TableHeader>
|
|
151
|
+
<TableBody>
|
|
152
|
+
{logs.map((log: DeliveryLog) => {
|
|
153
|
+
const config = statusConfig[log.status];
|
|
154
|
+
return (
|
|
155
|
+
<TableRow key={log.id}>
|
|
156
|
+
<TableCell>
|
|
157
|
+
<Badge
|
|
158
|
+
variant={config.variant}
|
|
159
|
+
className="flex items-center gap-1 w-fit"
|
|
160
|
+
>
|
|
161
|
+
{config.icon}
|
|
162
|
+
{log.status}
|
|
163
|
+
</Badge>
|
|
164
|
+
</TableCell>
|
|
165
|
+
<TableCell>
|
|
166
|
+
<div className="font-medium">
|
|
167
|
+
{log.subscriptionName ?? "Unknown"}
|
|
168
|
+
</div>
|
|
169
|
+
</TableCell>
|
|
170
|
+
<TableCell>
|
|
171
|
+
<div className="text-sm font-mono">
|
|
172
|
+
{log.eventType}
|
|
173
|
+
</div>
|
|
174
|
+
</TableCell>
|
|
175
|
+
<TableCell>{log.attempts}</TableCell>
|
|
176
|
+
<TableCell>
|
|
177
|
+
<div className="text-sm text-muted-foreground">
|
|
178
|
+
{new Date(log.createdAt).toLocaleString()}
|
|
179
|
+
</div>
|
|
180
|
+
</TableCell>
|
|
181
|
+
<TableCell>
|
|
182
|
+
{log.errorMessage ? (
|
|
183
|
+
<div
|
|
184
|
+
className="text-sm text-destructive max-w-[200px] truncate"
|
|
185
|
+
title={log.errorMessage}
|
|
186
|
+
>
|
|
187
|
+
{log.errorMessage}
|
|
188
|
+
</div>
|
|
189
|
+
) : undefined}
|
|
190
|
+
</TableCell>
|
|
191
|
+
<TableCell>
|
|
192
|
+
{log.status === "failed" && (
|
|
193
|
+
<Button
|
|
194
|
+
variant="ghost"
|
|
195
|
+
size="sm"
|
|
196
|
+
onClick={() => handleRetry(log.id)}
|
|
197
|
+
disabled={retrying === log.id}
|
|
198
|
+
>
|
|
199
|
+
<RefreshCw
|
|
200
|
+
className={`h-4 w-4 mr-1 ${
|
|
201
|
+
retrying === log.id ? "animate-spin" : ""
|
|
202
|
+
}`}
|
|
203
|
+
/>
|
|
204
|
+
Retry
|
|
205
|
+
</Button>
|
|
206
|
+
)}
|
|
207
|
+
</TableCell>
|
|
208
|
+
</TableRow>
|
|
209
|
+
);
|
|
210
|
+
})}
|
|
211
|
+
</TableBody>
|
|
212
|
+
</Table>
|
|
213
|
+
</Card>
|
|
214
|
+
</ResponsiveTable>
|
|
215
|
+
|
|
216
|
+
<MobileCardList>
|
|
217
|
+
{logs.map((log: DeliveryLog) => {
|
|
218
|
+
const config = statusConfig[log.status];
|
|
219
|
+
return (
|
|
220
|
+
<Card key={log.id} className="p-3">
|
|
221
|
+
<div className="flex items-start justify-between gap-2">
|
|
222
|
+
<span className="font-medium truncate">
|
|
223
|
+
{log.subscriptionName ?? "Unknown"}
|
|
224
|
+
</span>
|
|
225
|
+
<Badge
|
|
226
|
+
variant={config.variant}
|
|
227
|
+
className="flex items-center gap-1 w-fit shrink-0"
|
|
228
|
+
>
|
|
229
|
+
{config.icon}
|
|
230
|
+
{log.status}
|
|
231
|
+
</Badge>
|
|
232
|
+
</div>
|
|
233
|
+
<div className="mt-1 text-xs text-muted-foreground font-mono break-all">
|
|
234
|
+
{log.eventType}
|
|
235
|
+
</div>
|
|
236
|
+
<div className="mt-1 text-xs text-muted-foreground">
|
|
237
|
+
{log.attempts} attempt
|
|
238
|
+
{log.attempts === 1 ? "" : "s"} ·{" "}
|
|
239
|
+
{new Date(log.createdAt).toLocaleString()}
|
|
240
|
+
</div>
|
|
241
|
+
{log.errorMessage && (
|
|
242
|
+
<div
|
|
243
|
+
className="mt-2 text-xs text-destructive line-clamp-2"
|
|
244
|
+
title={log.errorMessage}
|
|
245
|
+
>
|
|
246
|
+
{log.errorMessage}
|
|
247
|
+
</div>
|
|
248
|
+
)}
|
|
249
|
+
{log.status === "failed" && (
|
|
250
|
+
<div className="mt-3 flex justify-end">
|
|
251
|
+
<Button
|
|
252
|
+
variant="ghost"
|
|
253
|
+
size="sm"
|
|
254
|
+
onClick={() => handleRetry(log.id)}
|
|
255
|
+
disabled={retrying === log.id}
|
|
256
|
+
>
|
|
257
|
+
<RefreshCw
|
|
258
|
+
className={`h-4 w-4 mr-1 ${
|
|
259
|
+
retrying === log.id ? "animate-spin" : ""
|
|
260
|
+
}`}
|
|
261
|
+
/>
|
|
262
|
+
Retry
|
|
263
|
+
</Button>
|
|
264
|
+
</div>
|
|
265
|
+
)}
|
|
266
|
+
</Card>
|
|
267
|
+
);
|
|
268
|
+
})}
|
|
269
|
+
</MobileCardList>
|
|
270
|
+
|
|
210
271
|
{pagination.totalPages > 1 && (
|
|
211
272
|
<div className="p-4 border-t flex justify-center gap-2">
|
|
212
273
|
<Button
|
|
@@ -230,7 +291,7 @@ export const DeliveryLogsPage = () => {
|
|
|
230
291
|
</Button>
|
|
231
292
|
</div>
|
|
232
293
|
)}
|
|
233
|
-
|
|
294
|
+
</>
|
|
234
295
|
)}
|
|
235
296
|
</section>
|
|
236
297
|
</div>
|
|
@@ -51,7 +51,7 @@ export const IntegrationsPage = () => {
|
|
|
51
51
|
data: subscriptionsData,
|
|
52
52
|
isLoading: subsLoading,
|
|
53
53
|
refetch: refetchSubs,
|
|
54
|
-
} = client.listSubscriptions.useQuery({
|
|
54
|
+
} = client.listSubscriptions.useQuery({ limit: 100, offset: 0 });
|
|
55
55
|
|
|
56
56
|
const { data: providers = [], isLoading: providersLoading } =
|
|
57
57
|
client.listProviders.useQuery({});
|
|
@@ -74,7 +74,7 @@ export const IntegrationsPage = () => {
|
|
|
74
74
|
},
|
|
75
75
|
});
|
|
76
76
|
|
|
77
|
-
const subscriptions = subscriptionsData?.
|
|
77
|
+
const subscriptions = subscriptionsData?.items ?? [];
|
|
78
78
|
const loading = subsLoading || providersLoading || statsLoading;
|
|
79
79
|
|
|
80
80
|
// Handle ?action=create URL parameter (from command palette)
|
|
@@ -42,10 +42,11 @@ import {
|
|
|
42
42
|
useToast,
|
|
43
43
|
ConfirmationModal,
|
|
44
44
|
BackLink,
|
|
45
|
+
toastError,
|
|
45
46
|
type LucideIconName,
|
|
46
47
|
} from "@checkstack/ui";
|
|
47
48
|
import { usePluginClient } from "@checkstack/frontend-api";
|
|
48
|
-
import { resolveRoute
|
|
49
|
+
import { resolveRoute } from "@checkstack/common";
|
|
49
50
|
import {
|
|
50
51
|
IntegrationApi,
|
|
51
52
|
integrationRoutes,
|
|
@@ -108,7 +109,7 @@ export const ProviderConnectionsPage = () => {
|
|
|
108
109
|
setSaving(false);
|
|
109
110
|
},
|
|
110
111
|
onError: (error) => {
|
|
111
|
-
toast
|
|
112
|
+
toastError(toast, "Failed to create connection", error);
|
|
112
113
|
setSaving(false);
|
|
113
114
|
},
|
|
114
115
|
});
|
|
@@ -122,7 +123,7 @@ export const ProviderConnectionsPage = () => {
|
|
|
122
123
|
setSaving(false);
|
|
123
124
|
},
|
|
124
125
|
onError: (error) => {
|
|
125
|
-
toast
|
|
126
|
+
toastError(toast, "Failed to update connection", error);
|
|
126
127
|
setSaving(false);
|
|
127
128
|
},
|
|
128
129
|
});
|
|
@@ -135,7 +136,7 @@ export const ProviderConnectionsPage = () => {
|
|
|
135
136
|
toast.success("Connection deleted");
|
|
136
137
|
},
|
|
137
138
|
onError: (error) => {
|
|
138
|
-
toast
|
|
139
|
+
toastError(toast, "Failed to delete connection", error);
|
|
139
140
|
},
|
|
140
141
|
});
|
|
141
142
|
|
|
@@ -157,7 +158,7 @@ export const ProviderConnectionsPage = () => {
|
|
|
157
158
|
...prev,
|
|
158
159
|
[variables.connectionId]: { success: false, message: "Test failed" },
|
|
159
160
|
}));
|
|
160
|
-
toast
|
|
161
|
+
toastError(toast, "Connection test failed", error);
|
|
161
162
|
setTestingId(undefined);
|
|
162
163
|
},
|
|
163
164
|
});
|