@drawbridge/components 0.1.7 → 0.1.9
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/bridge/form-subdomain-shop-modal.js +8 -0
- package/dist/bridge/form-subdomain-shop-modal.mjs +8 -0
- package/dist/bridge/template-modal.js +4 -3
- package/dist/bridge/template-modal.mjs +4 -3
- package/dist/bridge/template-subdomain.js +1 -1
- package/dist/bridge/template-subdomain.mjs +1 -1
- package/dist/dashboard/form-admin-organization.js +32 -0
- package/dist/dashboard/form-admin-organization.mjs +32 -0
- package/dist/dashboard/form-organization-workflow.js +128 -108
- package/dist/dashboard/form-organization-workflow.mjs +123 -108
- package/dist/dashboard/lib/navigation.js +22 -2
- package/dist/dashboard/lib/navigation.mjs +18 -1
- package/dist/dashboard/lib/sms.js +27 -0
- package/dist/dashboard/lib/sms.mjs +4 -0
- package/dist/dashboard/provider-ui.js +31 -6
- package/dist/dashboard/provider-ui.mjs +31 -6
- package/dist/dashboard/template-dashboard.js +9 -7
- package/dist/dashboard/template-dashboard.mjs +7 -6
- package/dist/dashboard/template-socket.js +3 -0
- package/dist/dashboard/template-socket.mjs +3 -0
- package/package.json +7 -2
- package/types/dashboard/form-organization-workflow.d.ts +31 -1
- package/types/dashboard/lib/navigation.d.ts +21 -0
- package/types/dashboard/lib/sms.d.ts +6 -0
- package/types/dashboard/template-dashboard.d.ts +2 -0
|
@@ -4,13 +4,14 @@ import Link from "./link.mjs";
|
|
|
4
4
|
import { Fragment, useCallback, useState } from "react";
|
|
5
5
|
import { request } from "@drawbridge/drawbridge-utils/fetch";
|
|
6
6
|
import { useForm, useWatch, Controller } from "../shared/lib/form.mjs";
|
|
7
|
-
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
|
7
|
+
import { useQueries, useQuery, useQueryClient } from "@tanstack/react-query";
|
|
8
8
|
import yup, { resolver } from "../shared/lib/yup.mjs";
|
|
9
9
|
import Form from "../shared/form.mjs";
|
|
10
10
|
import Fieldset from "../shared/fieldset.mjs";
|
|
11
11
|
import InputGroup from "../input-group.mjs";
|
|
12
12
|
import Error from "../shared/error.mjs";
|
|
13
13
|
import InputText from "../input-text.mjs";
|
|
14
|
+
import InputTextarea from "../input-textarea.mjs";
|
|
14
15
|
import InputUrl from "../shared/input-url.mjs";
|
|
15
16
|
import InputResource from "./input-resource.mjs";
|
|
16
17
|
import InputCombobox from "./input-combobox.mjs";
|
|
@@ -19,6 +20,7 @@ import { InputArrayButton, InputArrayControl, InputArraySortable } from "./input
|
|
|
19
20
|
import Badge from "../shared/badge.mjs";
|
|
20
21
|
import CardTask from "./card-task.mjs";
|
|
21
22
|
import { LoaderDynamic } from "../shared/loader.mjs";
|
|
23
|
+
import { smsNumberActive } from "./lib/sms.mjs";
|
|
22
24
|
import Trash from "../icons/trash.mjs";
|
|
23
25
|
import Button from "../shared/button.mjs";
|
|
24
26
|
const emailSteps = ["step.email.send", "step.email.digest"];
|
|
@@ -195,32 +197,45 @@ const WorkflowTitleField = ({ control, formState }) => /* @__PURE__ */ jsx(
|
|
|
195
197
|
}
|
|
196
198
|
);
|
|
197
199
|
const campaignFilterId = (campaign) => (campaign == null ? void 0 : campaign.id) || campaign || null;
|
|
200
|
+
const campaignFilterIds = (filters) => (Array.isArray(filters == null ? void 0 : filters.campaigns) ? filters.campaigns : [filters == null ? void 0 : filters.campaign]).map(campaignFilterId).filter(Boolean);
|
|
201
|
+
const filterRows = (ids, docs) => ids.map((id) => docs.find((doc) => (doc == null ? void 0 : doc.id) === id) || { id });
|
|
202
|
+
const filterSeed = (seeds, id) => (seeds || []).find((doc) => (doc == null ? void 0 : doc.id) === id);
|
|
203
|
+
const filterMissing = (error) => {
|
|
204
|
+
if ((error == null ? void 0 : error.status) === 404) return { result: null };
|
|
205
|
+
throw error;
|
|
206
|
+
};
|
|
198
207
|
const WorkflowFilterField = ({
|
|
199
208
|
collection,
|
|
200
209
|
control,
|
|
201
210
|
label,
|
|
202
211
|
message,
|
|
203
212
|
model,
|
|
213
|
+
multiple = false,
|
|
204
214
|
name,
|
|
205
215
|
organization,
|
|
206
|
-
resource
|
|
216
|
+
resource,
|
|
217
|
+
seeds
|
|
207
218
|
}) => {
|
|
208
219
|
const queryClient = useQueryClient();
|
|
209
|
-
const
|
|
220
|
+
const value = useWatch({
|
|
210
221
|
control,
|
|
211
222
|
name
|
|
212
223
|
});
|
|
213
|
-
const
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
+
const ids = multiple ? value || [] : [value].filter(Boolean);
|
|
225
|
+
const docs = useQueries({
|
|
226
|
+
queries: ids.map((id) => ({
|
|
227
|
+
queryKey: ["workflow-filter", model, organization, id],
|
|
228
|
+
queryFn: async () => {
|
|
229
|
+
const { result } = await request({
|
|
230
|
+
endpoint: "/organization/" + organization + "/" + resource + "/" + id
|
|
231
|
+
}).catch(filterMissing);
|
|
232
|
+
return result;
|
|
233
|
+
},
|
|
234
|
+
initialData: () => filterSeed(seeds, id),
|
|
235
|
+
staleTime: Infinity
|
|
236
|
+
}))
|
|
237
|
+
}).map((query) => query.data);
|
|
238
|
+
const seed = (doc) => (doc == null ? void 0 : doc.id) && queryClient.setQueryData(["workflow-filter", model, organization, doc.id], doc);
|
|
224
239
|
return /* @__PURE__ */ jsx(
|
|
225
240
|
Controller,
|
|
226
241
|
{
|
|
@@ -237,11 +252,15 @@ const WorkflowFilterField = ({
|
|
|
237
252
|
...{
|
|
238
253
|
endpoint: "/organization/" + organization + "/" + collection,
|
|
239
254
|
model,
|
|
240
|
-
|
|
241
|
-
|
|
255
|
+
multiple,
|
|
256
|
+
onChange: multiple ? (picked) => {
|
|
257
|
+
picked.forEach(seed);
|
|
258
|
+
onChange(picked.map((doc) => doc == null ? void 0 : doc.id).filter(Boolean));
|
|
259
|
+
} : (doc) => {
|
|
260
|
+
seed(doc);
|
|
242
261
|
onChange((doc == null ? void 0 : doc.id) || null);
|
|
243
262
|
},
|
|
244
|
-
value:
|
|
263
|
+
value: multiple ? filterRows(ids, docs) : docs[0] || null
|
|
245
264
|
}
|
|
246
265
|
}
|
|
247
266
|
),
|
|
@@ -328,7 +347,7 @@ const FormOrganizationWorkflow = ({
|
|
|
328
347
|
// Both blank, meaning every campaign and every segment. The
|
|
329
348
|
// create drawer asks for a trigger and a title only; narrowing
|
|
330
349
|
// is done on the workflow page afterwards.
|
|
331
|
-
|
|
350
|
+
campaigns: [],
|
|
332
351
|
segment: null
|
|
333
352
|
}
|
|
334
353
|
}
|
|
@@ -397,6 +416,48 @@ const FormOrganizationWorkflow = ({
|
|
|
397
416
|
}
|
|
398
417
|
);
|
|
399
418
|
};
|
|
419
|
+
const workflowSchema = yup.object({
|
|
420
|
+
title: yup.string().required().max(100).label("Title"),
|
|
421
|
+
triggerEvent: yup.string().label("Trigger").required("A trigger is required"),
|
|
422
|
+
steps: yup.array().of(
|
|
423
|
+
yup.object({
|
|
424
|
+
type: yup.string().label("Step").required("A step is required"),
|
|
425
|
+
url: yup.string().when("type", ([type], schema) => {
|
|
426
|
+
if (type === "step.webhook.send") {
|
|
427
|
+
return schema.url().required("URL is required").label("URL");
|
|
428
|
+
}
|
|
429
|
+
return schema;
|
|
430
|
+
}),
|
|
431
|
+
subject: yup.string().when("type", ([type], schema) => {
|
|
432
|
+
if (emailSteps.includes(type)) {
|
|
433
|
+
return schema.required("Subject is required").label("Subject");
|
|
434
|
+
}
|
|
435
|
+
return schema;
|
|
436
|
+
}),
|
|
437
|
+
message: yup.string().when("type", ([type], schema) => {
|
|
438
|
+
if (type === "step.sms.send") {
|
|
439
|
+
return schema.required("Message is required").max(1500).label("Message");
|
|
440
|
+
}
|
|
441
|
+
if (messageSteps.includes(type)) {
|
|
442
|
+
return schema.required("Message is required").label("Message");
|
|
443
|
+
}
|
|
444
|
+
return schema;
|
|
445
|
+
}),
|
|
446
|
+
// No minimum. The organization owner is always a recipient, so a
|
|
447
|
+
// step with no members chosen is complete — requiring one here
|
|
448
|
+
// made the step unsaveable for a solo merchant, who has no
|
|
449
|
+
// member documents to choose and cannot reach the members
|
|
450
|
+
// endpoint at all.
|
|
451
|
+
members: yup.array().label("Recipients"),
|
|
452
|
+
discount: yup.object().nullable().when("type", ([type], schema) => {
|
|
453
|
+
if (type === "step.commerce.code.issue") {
|
|
454
|
+
return schema.required("Discount is required").label("Discount");
|
|
455
|
+
}
|
|
456
|
+
return schema;
|
|
457
|
+
})
|
|
458
|
+
})
|
|
459
|
+
)
|
|
460
|
+
});
|
|
400
461
|
const FormOrganizationWorkflowEdit = ({
|
|
401
462
|
disabled,
|
|
402
463
|
onClose,
|
|
@@ -404,11 +465,13 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
404
465
|
onSuccess,
|
|
405
466
|
values
|
|
406
467
|
}) => {
|
|
407
|
-
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n;
|
|
468
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o;
|
|
408
469
|
const { catalog, catalogList, triggerOptions } = useWorkflowCatalog(values == null ? void 0 : values.organization, (_a = values == null ? void 0 : values.trigger) == null ? void 0 : _a.event);
|
|
409
470
|
const { items: memberItems, loading: membersLoading } = useOrganizationMembers(values == null ? void 0 : values.organization);
|
|
410
471
|
const queryClient = useQueryClient();
|
|
411
|
-
const
|
|
472
|
+
const organizationData = queryClient.getQueryData(["organization", values == null ? void 0 : values.organization]);
|
|
473
|
+
const ownerEmail = organizationData.owner.email;
|
|
474
|
+
const smsActive = smsNumberActive(organizationData);
|
|
412
475
|
const commerceConnectionId = ((_b = catalogList.flatMap((item) => item.steps || []).find(
|
|
413
476
|
(s) => s.value === "step.commerce.customer.insert" || s.value === "step.commerce.code.issue"
|
|
414
477
|
)) == null ? void 0 : _b.connectionId) || null;
|
|
@@ -436,55 +499,15 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
436
499
|
const { control, formState, getValues, handleSubmit, setValue } = useForm({
|
|
437
500
|
values: {
|
|
438
501
|
steps: defaultSteps,
|
|
439
|
-
|
|
502
|
+
filterCampaigns: campaignFilterIds((_g = values == null ? void 0 : values.trigger) == null ? void 0 : _g.filters),
|
|
440
503
|
// Stored and returned as a plain id — extend.workflow() $lookup-hydrates
|
|
441
504
|
// only the campaign — but read through the same reducer, so the field
|
|
442
505
|
// stays right if the segment is ever hydrated too.
|
|
443
|
-
filterSegment: campaignFilterId((
|
|
506
|
+
filterSegment: campaignFilterId((_i = (_h = values == null ? void 0 : values.trigger) == null ? void 0 : _h.filters) == null ? void 0 : _i.segment),
|
|
444
507
|
title: (values == null ? void 0 : values.title) || "",
|
|
445
|
-
triggerEvent: ((
|
|
508
|
+
triggerEvent: ((_j = values == null ? void 0 : values.trigger) == null ? void 0 : _j.event) || ""
|
|
446
509
|
},
|
|
447
|
-
resolver: resolver(
|
|
448
|
-
yup.object({
|
|
449
|
-
title: yup.string().required().max(100).label("Title"),
|
|
450
|
-
triggerEvent: yup.string().label("Trigger").required("A trigger is required"),
|
|
451
|
-
steps: yup.array().of(
|
|
452
|
-
yup.object({
|
|
453
|
-
type: yup.string().label("Step").required("A step is required"),
|
|
454
|
-
url: yup.string().when("type", ([type], schema) => {
|
|
455
|
-
if (type === "step.webhook.send") {
|
|
456
|
-
return schema.url().required("URL is required").label("URL");
|
|
457
|
-
}
|
|
458
|
-
return schema;
|
|
459
|
-
}),
|
|
460
|
-
subject: yup.string().when("type", ([type], schema) => {
|
|
461
|
-
if (messageSteps.includes(type)) {
|
|
462
|
-
return schema.required("Subject is required").label("Subject");
|
|
463
|
-
}
|
|
464
|
-
return schema;
|
|
465
|
-
}),
|
|
466
|
-
message: yup.string().when("type", ([type], schema) => {
|
|
467
|
-
if (messageSteps.includes(type)) {
|
|
468
|
-
return schema.required("Message is required").label("Message");
|
|
469
|
-
}
|
|
470
|
-
return schema;
|
|
471
|
-
}),
|
|
472
|
-
// No minimum. The organization owner is always a recipient, so a
|
|
473
|
-
// step with no members chosen is complete — requiring one here
|
|
474
|
-
// made the step unsaveable for a solo merchant, who has no
|
|
475
|
-
// member documents to choose and cannot reach the members
|
|
476
|
-
// endpoint at all.
|
|
477
|
-
members: yup.array().label("Recipients"),
|
|
478
|
-
discount: yup.object().nullable().when("type", ([type], schema) => {
|
|
479
|
-
if (type === "step.commerce.code.issue") {
|
|
480
|
-
return schema.required("Discount is required").label("Discount");
|
|
481
|
-
}
|
|
482
|
-
return schema;
|
|
483
|
-
})
|
|
484
|
-
})
|
|
485
|
-
)
|
|
486
|
-
})
|
|
487
|
-
)
|
|
510
|
+
resolver: resolver(workflowSchema)
|
|
488
511
|
});
|
|
489
512
|
const watchedTrigger = useWatch({
|
|
490
513
|
control,
|
|
@@ -494,7 +517,7 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
494
517
|
control,
|
|
495
518
|
name: "steps"
|
|
496
519
|
});
|
|
497
|
-
const issueIndex = ((
|
|
520
|
+
const issueIndex = ((_k = values == null ? void 0 : values.issue) == null ? void 0 : _k.step) ? (watchedSteps || []).findIndex((step) => (step == null ? void 0 : step.type) === values.issue.step) : -1;
|
|
498
521
|
const selectedTriggerEntry = catalogList.find((item) => item.trigger === watchedTrigger) || null;
|
|
499
522
|
const getAvailableVariables = (index) => {
|
|
500
523
|
return watchedSteps.slice(0, index).flatMap((watchedStep) => {
|
|
@@ -534,6 +557,22 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
534
557
|
href: "/organizations/" + (values == null ? void 0 : values.organization) + "/connections/" + step.slug,
|
|
535
558
|
onClick: onClose
|
|
536
559
|
}
|
|
560
|
+
} : {},
|
|
561
|
+
// The same link-shaped option, greyed: it cannot be picked, and
|
|
562
|
+
// clicking it opens Settings, where the number is bought.
|
|
563
|
+
...step.value === "step.sms.send" && !smsActive ? {
|
|
564
|
+
badge: {
|
|
565
|
+
text: "Settings"
|
|
566
|
+
},
|
|
567
|
+
className: "opacity-50",
|
|
568
|
+
disabled: false,
|
|
569
|
+
element: Link,
|
|
570
|
+
key: step == null ? void 0 : step.key,
|
|
571
|
+
props: {
|
|
572
|
+
"aria-disabled": true,
|
|
573
|
+
href: "/organizations/" + (values == null ? void 0 : values.organization) + "/settings",
|
|
574
|
+
onClick: onClose
|
|
575
|
+
}
|
|
537
576
|
} : {}
|
|
538
577
|
}))
|
|
539
578
|
];
|
|
@@ -580,7 +619,7 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
580
619
|
};
|
|
581
620
|
const onSubmit = async ({
|
|
582
621
|
steps,
|
|
583
|
-
|
|
622
|
+
filterCampaigns,
|
|
584
623
|
filterSegment,
|
|
585
624
|
title,
|
|
586
625
|
triggerEvent
|
|
@@ -590,10 +629,8 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
590
629
|
steps: steps.map(({ connectionId, discount, members, message, score, slug, subject, text, type, url }, index) => {
|
|
591
630
|
const settings = {};
|
|
592
631
|
if (type === "step.webhook.send") settings.url = url;
|
|
593
|
-
if (
|
|
594
|
-
|
|
595
|
-
settings.message = message;
|
|
596
|
-
}
|
|
632
|
+
if (emailSteps.includes(type)) settings.subject = subject;
|
|
633
|
+
if (messageSteps.includes(type)) settings.message = message;
|
|
597
634
|
if (emailSteps.includes(type)) {
|
|
598
635
|
if (score && score.subject === subject && score.message === message) settings.score = score;
|
|
599
636
|
else if (score) setValue("steps." + index + ".score", null);
|
|
@@ -616,7 +653,7 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
616
653
|
trigger: {
|
|
617
654
|
event: triggerEvent,
|
|
618
655
|
filters: {
|
|
619
|
-
|
|
656
|
+
campaigns: filterCampaigns || [],
|
|
620
657
|
segment: filterSegment || null
|
|
621
658
|
}
|
|
622
659
|
}
|
|
@@ -686,12 +723,14 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
686
723
|
...{
|
|
687
724
|
collection: "campaigns",
|
|
688
725
|
control,
|
|
689
|
-
label: "
|
|
690
|
-
message: "Only
|
|
726
|
+
label: "Campaigns",
|
|
727
|
+
message: "Only runs for leads from the campaigns you add. With none added, it runs for every campaign.",
|
|
691
728
|
model: "campaign",
|
|
692
|
-
|
|
729
|
+
multiple: true,
|
|
730
|
+
name: "filterCampaigns",
|
|
693
731
|
organization: values == null ? void 0 : values.organization,
|
|
694
|
-
resource: "campaign"
|
|
732
|
+
resource: "campaign",
|
|
733
|
+
seeds: (_m = (_l = values == null ? void 0 : values.trigger) == null ? void 0 : _l.filters) == null ? void 0 : _m.campaigns
|
|
695
734
|
}
|
|
696
735
|
}
|
|
697
736
|
),
|
|
@@ -714,7 +753,7 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
714
753
|
InputGroup,
|
|
715
754
|
{
|
|
716
755
|
...{
|
|
717
|
-
error: (
|
|
756
|
+
error: (_o = (_n = formState == null ? void 0 : formState.errors) == null ? void 0 : _n.steps) == null ? void 0 : _o.message,
|
|
718
757
|
input: /* @__PURE__ */ jsx(
|
|
719
758
|
InputArraySortable,
|
|
720
759
|
{
|
|
@@ -944,36 +983,6 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
944
983
|
}
|
|
945
984
|
}
|
|
946
985
|
),
|
|
947
|
-
step.type === "step.sms.send" && /* @__PURE__ */ jsx(
|
|
948
|
-
Controller,
|
|
949
|
-
{
|
|
950
|
-
...{
|
|
951
|
-
control,
|
|
952
|
-
name: `steps.${index}.subject`,
|
|
953
|
-
render: ({ field: { value, onChange } }) => {
|
|
954
|
-
var _a2, _b2, _c2, _d2;
|
|
955
|
-
return /* @__PURE__ */ jsx(
|
|
956
|
-
InputGroup,
|
|
957
|
-
{
|
|
958
|
-
...{
|
|
959
|
-
error: (_d2 = (_c2 = (_b2 = (_a2 = formState == null ? void 0 : formState.errors) == null ? void 0 : _a2.steps) == null ? void 0 : _b2[index]) == null ? void 0 : _c2.subject) == null ? void 0 : _d2.message,
|
|
960
|
-
input: /* @__PURE__ */ jsx(
|
|
961
|
-
InputText,
|
|
962
|
-
{
|
|
963
|
-
...{
|
|
964
|
-
onChange,
|
|
965
|
-
value: value || ""
|
|
966
|
-
}
|
|
967
|
-
}
|
|
968
|
-
),
|
|
969
|
-
label: "Subject"
|
|
970
|
-
}
|
|
971
|
-
}
|
|
972
|
-
);
|
|
973
|
-
}
|
|
974
|
-
}
|
|
975
|
-
}
|
|
976
|
-
),
|
|
977
986
|
step.type === "step.sms.send" && /* @__PURE__ */ jsx(
|
|
978
987
|
Controller,
|
|
979
988
|
{
|
|
@@ -988,10 +997,11 @@ const FormOrganizationWorkflowEdit = ({
|
|
|
988
997
|
...{
|
|
989
998
|
error: (_d2 = (_c2 = (_b2 = (_a2 = formState == null ? void 0 : formState.errors) == null ? void 0 : _a2.steps) == null ? void 0 : _b2[index]) == null ? void 0 : _c2.message) == null ? void 0 : _d2.message,
|
|
990
999
|
input: /* @__PURE__ */ jsx(
|
|
991
|
-
|
|
1000
|
+
InputTextarea,
|
|
992
1001
|
{
|
|
993
1002
|
...{
|
|
994
1003
|
onChange,
|
|
1004
|
+
rows: 3,
|
|
995
1005
|
value: value || ""
|
|
996
1006
|
}
|
|
997
1007
|
}
|
|
@@ -1105,5 +1115,10 @@ export {
|
|
|
1105
1115
|
FormOrganizationWorkflow,
|
|
1106
1116
|
FormOrganizationWorkflowEdit,
|
|
1107
1117
|
campaignFilterId,
|
|
1108
|
-
|
|
1118
|
+
campaignFilterIds,
|
|
1119
|
+
filterMissing,
|
|
1120
|
+
filterRows,
|
|
1121
|
+
filterSeed,
|
|
1122
|
+
stepRow,
|
|
1123
|
+
workflowSchema
|
|
1109
1124
|
};
|
|
@@ -17,7 +17,10 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
18
|
var navigation_exports = {};
|
|
19
19
|
__export(navigation_exports, {
|
|
20
|
-
|
|
20
|
+
expiredSessionHref: () => expiredSessionHref,
|
|
21
|
+
interceptHref: () => interceptHref,
|
|
22
|
+
retrySession: () => retrySession,
|
|
23
|
+
sessionRetryKey: () => sessionRetryKey
|
|
21
24
|
});
|
|
22
25
|
module.exports = __toCommonJS(navigation_exports);
|
|
23
26
|
const interceptHref = ({
|
|
@@ -40,7 +43,24 @@ const interceptHref = ({
|
|
|
40
43
|
if (url.pathname === location.pathname && url.search === location.search) return null;
|
|
41
44
|
return url.pathname + url.search + url.hash;
|
|
42
45
|
};
|
|
46
|
+
const expiredSessionHref = ({
|
|
47
|
+
csrf,
|
|
48
|
+
pathname = "/",
|
|
49
|
+
search = ""
|
|
50
|
+
}) => {
|
|
51
|
+
if (pathname === "/auth" || pathname.startsWith("/auth/")) return null;
|
|
52
|
+
const back = "/auth?redirectTo=" + encodeURIComponent(pathname + search);
|
|
53
|
+
return "/api/auth/signout?redirectTo=" + encodeURIComponent(back) + (csrf ? "&csrf=" + encodeURIComponent(csrf) : "");
|
|
54
|
+
};
|
|
55
|
+
const sessionRetryKey = "drawbridge.session.retry";
|
|
56
|
+
const retrySession = ({
|
|
57
|
+
now,
|
|
58
|
+
stamp
|
|
59
|
+
}) => !(Number(stamp) > now - 6e4);
|
|
43
60
|
// Annotate the CommonJS export names for ESM import in node:
|
|
44
61
|
0 && (module.exports = {
|
|
45
|
-
|
|
62
|
+
expiredSessionHref,
|
|
63
|
+
interceptHref,
|
|
64
|
+
retrySession,
|
|
65
|
+
sessionRetryKey
|
|
46
66
|
});
|
|
@@ -18,6 +18,23 @@ const interceptHref = ({
|
|
|
18
18
|
if (url.pathname === location.pathname && url.search === location.search) return null;
|
|
19
19
|
return url.pathname + url.search + url.hash;
|
|
20
20
|
};
|
|
21
|
+
const expiredSessionHref = ({
|
|
22
|
+
csrf,
|
|
23
|
+
pathname = "/",
|
|
24
|
+
search = ""
|
|
25
|
+
}) => {
|
|
26
|
+
if (pathname === "/auth" || pathname.startsWith("/auth/")) return null;
|
|
27
|
+
const back = "/auth?redirectTo=" + encodeURIComponent(pathname + search);
|
|
28
|
+
return "/api/auth/signout?redirectTo=" + encodeURIComponent(back) + (csrf ? "&csrf=" + encodeURIComponent(csrf) : "");
|
|
29
|
+
};
|
|
30
|
+
const sessionRetryKey = "drawbridge.session.retry";
|
|
31
|
+
const retrySession = ({
|
|
32
|
+
now,
|
|
33
|
+
stamp
|
|
34
|
+
}) => !(Number(stamp) > now - 6e4);
|
|
21
35
|
export {
|
|
22
|
-
|
|
36
|
+
expiredSessionHref,
|
|
37
|
+
interceptHref,
|
|
38
|
+
retrySession,
|
|
39
|
+
sessionRetryKey
|
|
23
40
|
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
4
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
5
|
+
var __export = (target, all) => {
|
|
6
|
+
for (var name in all)
|
|
7
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
8
|
+
};
|
|
9
|
+
var __copyProps = (to, from, except, desc) => {
|
|
10
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
11
|
+
for (let key of __getOwnPropNames(from))
|
|
12
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
13
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
14
|
+
}
|
|
15
|
+
return to;
|
|
16
|
+
};
|
|
17
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
|
+
var sms_exports = {};
|
|
19
|
+
__export(sms_exports, {
|
|
20
|
+
smsNumberActive: () => smsNumberActive
|
|
21
|
+
});
|
|
22
|
+
module.exports = __toCommonJS(sms_exports);
|
|
23
|
+
const smsNumberActive = (organization) => ((organization == null ? void 0 : organization.identityItems) || []).some((row) => (row == null ? void 0 : row.type) === "sms" && (row == null ? void 0 : row.status) === "verified");
|
|
24
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
25
|
+
0 && (module.exports = {
|
|
26
|
+
smsNumberActive
|
|
27
|
+
});
|
|
@@ -37,6 +37,7 @@ var import_react_query = require("@tanstack/react-query");
|
|
|
37
37
|
var import_fetch = require("@drawbridge/drawbridge-utils/fetch");
|
|
38
38
|
var import_socket = require("socket.io-client");
|
|
39
39
|
var import_template_not_found = __toESM(require("./template-not-found"));
|
|
40
|
+
var import_navigation = require("./lib/navigation");
|
|
40
41
|
var import_drawer = __toESM(require("./drawer"));
|
|
41
42
|
var import_guard_navigation = __toESM(require("./guard-navigation"));
|
|
42
43
|
var import_modal = __toESM(require("./modal"));
|
|
@@ -46,7 +47,7 @@ const ProviderUi = ({
|
|
|
46
47
|
children,
|
|
47
48
|
token
|
|
48
49
|
}) => {
|
|
49
|
-
var _a, _b, _c, _d;
|
|
50
|
+
var _a, _b, _c, _d, _e, _f;
|
|
50
51
|
const queryClient = (0, import_react_query.useQueryClient)();
|
|
51
52
|
const tokenRef = (0, import_react.useRef)(token);
|
|
52
53
|
(0, import_react.useEffect)(
|
|
@@ -171,7 +172,31 @@ const ProviderUi = ({
|
|
|
171
172
|
}
|
|
172
173
|
]
|
|
173
174
|
});
|
|
174
|
-
|
|
175
|
+
const expired = ((_a = account == null ? void 0 : account.error) == null ? void 0 : _a.status) === 401 && typeof window !== "undefined" ? (0, import_navigation.expiredSessionHref)({
|
|
176
|
+
csrf: (_b = document.cookie.match(/(?:^|;\s*)drawbridge\.csrf=([^;]+)/)) == null ? void 0 : _b[1],
|
|
177
|
+
pathname: window.location.pathname,
|
|
178
|
+
search: window.location.search
|
|
179
|
+
}) : null;
|
|
180
|
+
(0, import_react.useEffect)(
|
|
181
|
+
() => {
|
|
182
|
+
if (!expired) return;
|
|
183
|
+
const signOut = () => window.location.replace(expired);
|
|
184
|
+
try {
|
|
185
|
+
if (!(0, import_navigation.retrySession)({ now: Date.now(), stamp: window.sessionStorage.getItem(import_navigation.sessionRetryKey) })) return signOut();
|
|
186
|
+
window.sessionStorage.setItem(import_navigation.sessionRetryKey, String(Date.now()));
|
|
187
|
+
} catch {
|
|
188
|
+
return signOut();
|
|
189
|
+
}
|
|
190
|
+
fetch(
|
|
191
|
+
"/api/auth/refresh",
|
|
192
|
+
{
|
|
193
|
+
method: "POST"
|
|
194
|
+
}
|
|
195
|
+
).then((response) => response.ok ? window.location.reload() : signOut()).catch(signOut);
|
|
196
|
+
},
|
|
197
|
+
[expired]
|
|
198
|
+
);
|
|
199
|
+
if ((account == null ? void 0 : account.isLoading) || (app == null ? void 0 : app.isLoading) || expired) {
|
|
175
200
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_loader.LogoLoader, {});
|
|
176
201
|
}
|
|
177
202
|
;
|
|
@@ -182,7 +207,7 @@ const ProviderUi = ({
|
|
|
182
207
|
...{
|
|
183
208
|
button: false,
|
|
184
209
|
href: false,
|
|
185
|
-
message: (
|
|
210
|
+
message: (_c = app == null ? void 0 : app.error) == null ? void 0 : _c.message
|
|
186
211
|
}
|
|
187
212
|
}
|
|
188
213
|
);
|
|
@@ -195,7 +220,7 @@ const ProviderUi = ({
|
|
|
195
220
|
{
|
|
196
221
|
...{
|
|
197
222
|
button: false,
|
|
198
|
-
message: (
|
|
223
|
+
message: (_d = account == null ? void 0 : account.error) == null ? void 0 : _d.message
|
|
199
224
|
}
|
|
200
225
|
}
|
|
201
226
|
);
|
|
@@ -207,7 +232,7 @@ const ProviderUi = ({
|
|
|
207
232
|
...{
|
|
208
233
|
button: "Sign in",
|
|
209
234
|
href: "/auth",
|
|
210
|
-
message: (
|
|
235
|
+
message: (_e = account == null ? void 0 : account.error) == null ? void 0 : _e.message
|
|
211
236
|
}
|
|
212
237
|
}
|
|
213
238
|
);
|
|
@@ -227,7 +252,7 @@ const ProviderUi = ({
|
|
|
227
252
|
})
|
|
228
253
|
)
|
|
229
254
|
},
|
|
230
|
-
children: (
|
|
255
|
+
children: (_f = drawer == null ? void 0 : drawer.data) == null ? void 0 : _f.children
|
|
231
256
|
}
|
|
232
257
|
),
|
|
233
258
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
@@ -5,6 +5,7 @@ import { useQueries, useQueryClient } from "@tanstack/react-query";
|
|
|
5
5
|
import { isTransientError, request, setMemoryToken } from "@drawbridge/drawbridge-utils/fetch";
|
|
6
6
|
import { io } from "socket.io-client";
|
|
7
7
|
import TemplateNotFound from "./template-not-found.mjs";
|
|
8
|
+
import { expiredSessionHref, retrySession, sessionRetryKey } from "./lib/navigation.mjs";
|
|
8
9
|
import Drawer from "./drawer.mjs";
|
|
9
10
|
import GuardNavigation from "./guard-navigation.mjs";
|
|
10
11
|
import Modal from "./modal.mjs";
|
|
@@ -14,7 +15,7 @@ const ProviderUi = ({
|
|
|
14
15
|
children,
|
|
15
16
|
token
|
|
16
17
|
}) => {
|
|
17
|
-
var _a, _b, _c, _d;
|
|
18
|
+
var _a, _b, _c, _d, _e, _f;
|
|
18
19
|
const queryClient = useQueryClient();
|
|
19
20
|
const tokenRef = useRef(token);
|
|
20
21
|
useEffect(
|
|
@@ -139,7 +140,31 @@ const ProviderUi = ({
|
|
|
139
140
|
}
|
|
140
141
|
]
|
|
141
142
|
});
|
|
142
|
-
|
|
143
|
+
const expired = ((_a = account == null ? void 0 : account.error) == null ? void 0 : _a.status) === 401 && typeof window !== "undefined" ? expiredSessionHref({
|
|
144
|
+
csrf: (_b = document.cookie.match(/(?:^|;\s*)drawbridge\.csrf=([^;]+)/)) == null ? void 0 : _b[1],
|
|
145
|
+
pathname: window.location.pathname,
|
|
146
|
+
search: window.location.search
|
|
147
|
+
}) : null;
|
|
148
|
+
useEffect(
|
|
149
|
+
() => {
|
|
150
|
+
if (!expired) return;
|
|
151
|
+
const signOut = () => window.location.replace(expired);
|
|
152
|
+
try {
|
|
153
|
+
if (!retrySession({ now: Date.now(), stamp: window.sessionStorage.getItem(sessionRetryKey) })) return signOut();
|
|
154
|
+
window.sessionStorage.setItem(sessionRetryKey, String(Date.now()));
|
|
155
|
+
} catch {
|
|
156
|
+
return signOut();
|
|
157
|
+
}
|
|
158
|
+
fetch(
|
|
159
|
+
"/api/auth/refresh",
|
|
160
|
+
{
|
|
161
|
+
method: "POST"
|
|
162
|
+
}
|
|
163
|
+
).then((response) => response.ok ? window.location.reload() : signOut()).catch(signOut);
|
|
164
|
+
},
|
|
165
|
+
[expired]
|
|
166
|
+
);
|
|
167
|
+
if ((account == null ? void 0 : account.isLoading) || (app == null ? void 0 : app.isLoading) || expired) {
|
|
143
168
|
return /* @__PURE__ */ jsx(LogoLoader, {});
|
|
144
169
|
}
|
|
145
170
|
;
|
|
@@ -150,7 +175,7 @@ const ProviderUi = ({
|
|
|
150
175
|
...{
|
|
151
176
|
button: false,
|
|
152
177
|
href: false,
|
|
153
|
-
message: (
|
|
178
|
+
message: (_c = app == null ? void 0 : app.error) == null ? void 0 : _c.message
|
|
154
179
|
}
|
|
155
180
|
}
|
|
156
181
|
);
|
|
@@ -163,7 +188,7 @@ const ProviderUi = ({
|
|
|
163
188
|
{
|
|
164
189
|
...{
|
|
165
190
|
button: false,
|
|
166
|
-
message: (
|
|
191
|
+
message: (_d = account == null ? void 0 : account.error) == null ? void 0 : _d.message
|
|
167
192
|
}
|
|
168
193
|
}
|
|
169
194
|
);
|
|
@@ -175,7 +200,7 @@ const ProviderUi = ({
|
|
|
175
200
|
...{
|
|
176
201
|
button: "Sign in",
|
|
177
202
|
href: "/auth",
|
|
178
|
-
message: (
|
|
203
|
+
message: (_e = account == null ? void 0 : account.error) == null ? void 0 : _e.message
|
|
179
204
|
}
|
|
180
205
|
}
|
|
181
206
|
);
|
|
@@ -195,7 +220,7 @@ const ProviderUi = ({
|
|
|
195
220
|
})
|
|
196
221
|
)
|
|
197
222
|
},
|
|
198
|
-
children: (
|
|
223
|
+
children: (_f = drawer == null ? void 0 : drawer.data) == null ? void 0 : _f.children
|
|
199
224
|
}
|
|
200
225
|
),
|
|
201
226
|
/* @__PURE__ */ jsx(
|