synapse-react-client 4.0.43 → 4.0.45

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 (159) hide show
  1. package/dist/SWC.index.d.ts +1 -1
  2. package/dist/SWC.index.js +2 -2
  3. package/dist/SWC.index.js.map +1 -1
  4. package/dist/components/AccessRequirementList/AccessRequirementList.d.ts +2 -1
  5. package/dist/components/AccessRequirementList/AccessRequirementList.d.ts.map +1 -1
  6. package/dist/components/AccessRequirementList/AccessRequirementList.js +126 -125
  7. package/dist/components/AccessRequirementList/AccessRequirementList.js.map +1 -1
  8. package/dist/components/AccessRequirementList/AccessRequirementListItem.d.ts +1 -1
  9. package/dist/components/AccessRequirementList/AccessRequirementListItem.d.ts.map +1 -1
  10. package/dist/components/AccessRequirementList/AccessRequirementListItem.js.map +1 -1
  11. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/EDucPreviewStep/EDucPreviewStep.d.ts.map +1 -1
  12. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/EDucPreviewStep/EDucPreviewStep.js +28 -16
  13. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/EDucPreviewStep/EDucPreviewStep.js.map +1 -1
  14. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManualUploadDucStep/ManualUploadDucStep.d.ts.map +1 -1
  15. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManualUploadDucStep/ManualUploadDucStep.js +99 -97
  16. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManualUploadDucStep/ManualUploadDucStep.js.map +1 -1
  17. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/requestFlowTypes.d.ts +1 -1
  18. package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/requestFlowTypes.d.ts.map +1 -1
  19. package/dist/components/AccessRequirementList/RequestDataStep.d.ts +1 -4
  20. package/dist/components/AccessRequirementList/RequestDataStep.d.ts.map +1 -1
  21. package/dist/components/AccessRequirementList/RequestDataStep.js +15 -18
  22. package/dist/components/AccessRequirementList/RequestDataStep.js.map +1 -1
  23. package/dist/components/CreateOrUpdateAccessRequirementWizard/CreateOrUpdateAccessRequirementWizard.d.ts.map +1 -1
  24. package/dist/components/CreateOrUpdateAccessRequirementWizard/CreateOrUpdateAccessRequirementWizard.js +52 -49
  25. package/dist/components/CreateOrUpdateAccessRequirementWizard/CreateOrUpdateAccessRequirementWizard.js.map +1 -1
  26. package/dist/components/DataGrid/DataGridWebSocket.d.ts +29 -1
  27. package/dist/components/DataGrid/DataGridWebSocket.d.ts.map +1 -1
  28. package/dist/components/DataGrid/DataGridWebSocket.js +48 -16
  29. package/dist/components/DataGrid/DataGridWebSocket.js.map +1 -1
  30. package/dist/components/DataGrid/components/GridLoadingState.d.ts +2 -2
  31. package/dist/components/DataGrid/components/GridLoadingState.d.ts.map +1 -1
  32. package/dist/components/DataGrid/components/GridLoadingState.js +2 -2
  33. package/dist/components/DataGrid/components/GridLoadingState.js.map +1 -1
  34. package/dist/components/DataGrid/useDataGridWebsocket.d.ts.map +1 -1
  35. package/dist/components/DataGrid/useDataGridWebsocket.js +2 -1
  36. package/dist/components/DataGrid/useDataGridWebsocket.js.map +1 -1
  37. package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.d.ts.map +1 -1
  38. package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.js +11 -10
  39. package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.js.map +1 -1
  40. package/dist/components/FormTemplateEditor/useSaveFormTemplate.d.ts.map +1 -1
  41. package/dist/components/FormTemplateEditor/useSaveFormTemplate.js.map +1 -1
  42. package/dist/components/FormTemplateReferenceField/FormTemplatePreviewDialog.d.ts +9 -0
  43. package/dist/components/FormTemplateReferenceField/FormTemplatePreviewDialog.d.ts.map +1 -0
  44. package/dist/components/FormTemplateReferenceField/FormTemplatePreviewDialog.js +45 -0
  45. package/dist/components/FormTemplateReferenceField/FormTemplatePreviewDialog.js.map +1 -0
  46. package/dist/components/FormTemplateReferenceField/FormTemplateReferenceField.d.ts +22 -0
  47. package/dist/components/FormTemplateReferenceField/FormTemplateReferenceField.d.ts.map +1 -0
  48. package/dist/components/FormTemplateReferenceField/FormTemplateReferenceField.js +139 -0
  49. package/dist/components/FormTemplateReferenceField/FormTemplateReferenceField.js.map +1 -0
  50. package/dist/components/Forum/ForumTable.d.ts +17 -5
  51. package/dist/components/Forum/ForumTable.d.ts.map +1 -1
  52. package/dist/components/Forum/ForumTable.js +94 -77
  53. package/dist/components/Forum/ForumTable.js.map +1 -1
  54. package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.d.ts.map +1 -1
  55. package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js +142 -108
  56. package/dist/components/SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js.map +1 -1
  57. package/dist/components/SetBasicAccessRequirementFields/AccessorRequirements.d.ts.map +1 -1
  58. package/dist/components/SetBasicAccessRequirementFields/AccessorRequirements.js +15 -15
  59. package/dist/components/SetBasicAccessRequirementFields/AccessorRequirements.js.map +1 -1
  60. package/dist/components/SetManagedAccessRequirementFields/DataUseCertificateFields.d.ts +10 -0
  61. package/dist/components/SetManagedAccessRequirementFields/DataUseCertificateFields.d.ts.map +1 -0
  62. package/dist/components/SetManagedAccessRequirementFields/DataUseCertificateFields.js +81 -0
  63. package/dist/components/SetManagedAccessRequirementFields/DataUseCertificateFields.js.map +1 -0
  64. package/dist/components/SetManagedAccessRequirementFields/ExpirationPeriodField.d.ts +9 -0
  65. package/dist/components/SetManagedAccessRequirementFields/ExpirationPeriodField.d.ts.map +1 -0
  66. package/dist/components/SetManagedAccessRequirementFields/ExpirationPeriodField.js +32 -0
  67. package/dist/components/SetManagedAccessRequirementFields/ExpirationPeriodField.js.map +1 -0
  68. package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.d.ts +0 -2
  69. package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.d.ts.map +1 -1
  70. package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.js +79 -154
  71. package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.js.map +1 -1
  72. package/dist/components/TanStackTable/TanStackTableUtils.d.ts.map +1 -1
  73. package/dist/components/TanStackTable/TanStackTableUtils.js +8 -5
  74. package/dist/components/TanStackTable/TanStackTableUtils.js.map +1 -1
  75. package/dist/components/dataaccess/SubmissionPage/DataAccessSubmissionFileHandleLink.d.ts +5 -0
  76. package/dist/components/dataaccess/SubmissionPage/DataAccessSubmissionFileHandleLink.d.ts.map +1 -0
  77. package/dist/components/dataaccess/SubmissionPage/DataAccessSubmissionFileHandleLink.js +20 -0
  78. package/dist/components/dataaccess/SubmissionPage/DataAccessSubmissionFileHandleLink.js.map +1 -0
  79. package/dist/components/dataaccess/SubmissionPage/SubmissionPage.d.ts.map +1 -1
  80. package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js +183 -188
  81. package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js.map +1 -1
  82. package/dist/components/dataaccess/SubmissionPage/SubmissionSchemaAnswers.d.ts +25 -0
  83. package/dist/components/dataaccess/SubmissionPage/SubmissionSchemaAnswers.d.ts.map +1 -0
  84. package/dist/components/dataaccess/SubmissionPage/SubmissionSchemaAnswers.js +125 -0
  85. package/dist/components/dataaccess/SubmissionPage/SubmissionSchemaAnswers.js.map +1 -0
  86. package/dist/components/dataaccess/UserAccessRequestHistory/InFlightEDucSignaturesTable.d.ts.map +1 -1
  87. package/dist/components/dataaccess/UserAccessRequestHistory/InFlightEDucSignaturesTable.js +4 -1
  88. package/dist/components/dataaccess/UserAccessRequestHistory/InFlightEDucSignaturesTable.js.map +1 -1
  89. package/dist/mocks/accessRequirement/mockJsonSchemaAccessRequirements.d.ts +5 -0
  90. package/dist/mocks/accessRequirement/mockJsonSchemaAccessRequirements.d.ts.map +1 -1
  91. package/dist/mocks/accessRequirement/mockJsonSchemaAccessRequirements.js +37 -26
  92. package/dist/mocks/accessRequirement/mockJsonSchemaAccessRequirements.js.map +1 -1
  93. package/dist/mocks/dataaccess/MockSubmission.d.ts +76 -0
  94. package/dist/mocks/dataaccess/MockSubmission.d.ts.map +1 -1
  95. package/dist/mocks/dataaccess/MockSubmission.js +108 -63
  96. package/dist/mocks/dataaccess/MockSubmission.js.map +1 -1
  97. package/dist/mocks/msw/handlers/discussionHandlers.d.ts.map +1 -1
  98. package/dist/mocks/msw/handlers/discussionHandlers.js +40 -33
  99. package/dist/mocks/msw/handlers/discussionHandlers.js.map +1 -1
  100. package/dist/style/components/_submission-page.scss +0 -4
  101. package/dist/style/main.css +1 -1
  102. package/dist/synapse-client/SynapseClient.d.ts +10 -0
  103. package/dist/synapse-client/SynapseClient.d.ts.map +1 -1
  104. package/dist/synapse-client/SynapseClient.js +486 -482
  105. package/dist/synapse-client/SynapseClient.js.map +1 -1
  106. package/dist/synapse-client/index.js +3 -3
  107. package/dist/synapse-queries/KeyFactory.d.ts +13 -1
  108. package/dist/synapse-queries/KeyFactory.d.ts.map +1 -1
  109. package/dist/synapse-queries/KeyFactory.js +11 -1
  110. package/dist/synapse-queries/KeyFactory.js.map +1 -1
  111. package/dist/synapse-queries/dataaccess/index.js +4 -4
  112. package/dist/synapse-queries/dataaccess/useAccessRequirements.d.ts.map +1 -1
  113. package/dist/synapse-queries/dataaccess/useAccessRequirements.js +4 -1
  114. package/dist/synapse-queries/dataaccess/useAccessRequirements.js.map +1 -1
  115. package/dist/synapse-queries/dataaccess/useEDuc.d.ts +19 -5
  116. package/dist/synapse-queries/dataaccess/useEDuc.d.ts.map +1 -1
  117. package/dist/synapse-queries/dataaccess/useEDuc.js +29 -21
  118. package/dist/synapse-queries/dataaccess/useEDuc.js.map +1 -1
  119. package/dist/synapse-queries/dataaccess/useFormTemplate.d.ts +12 -0
  120. package/dist/synapse-queries/dataaccess/useFormTemplate.d.ts.map +1 -1
  121. package/dist/synapse-queries/dataaccess/useFormTemplate.js +52 -30
  122. package/dist/synapse-queries/dataaccess/useFormTemplate.js.map +1 -1
  123. package/dist/synapse-queries/dataaccess/useGeneratedSubmissionForm.d.ts +37 -0
  124. package/dist/synapse-queries/dataaccess/useGeneratedSubmissionForm.d.ts.map +1 -0
  125. package/dist/synapse-queries/dataaccess/useGeneratedSubmissionForm.js +35 -0
  126. package/dist/synapse-queries/dataaccess/useGeneratedSubmissionForm.js.map +1 -0
  127. package/dist/synapse-queries/forum/useForum.d.ts +5 -1
  128. package/dist/synapse-queries/forum/useForum.d.ts.map +1 -1
  129. package/dist/synapse-queries/forum/useForum.js +23 -1
  130. package/dist/synapse-queries/forum/useForum.js.map +1 -1
  131. package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts +2 -0
  132. package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts.map +1 -1
  133. package/dist/synapse-queries/grid/useEstablishWebsocketConnection.js.map +1 -1
  134. package/dist/synapse-queries/index.js +185 -184
  135. package/dist/synapse-queries/jsonschema/useCreateJsonSchema.d.ts +5 -3
  136. package/dist/synapse-queries/jsonschema/useCreateJsonSchema.d.ts.map +1 -1
  137. package/dist/synapse-queries/jsonschema/useCreateJsonSchema.js +12 -15
  138. package/dist/synapse-queries/jsonschema/useCreateJsonSchema.js.map +1 -1
  139. package/dist/synapse-queries/termsOfService/useTermsOfService.d.ts.map +1 -1
  140. package/dist/synapse-queries/termsOfService/useTermsOfService.js +21 -19
  141. package/dist/synapse-queries/termsOfService/useTermsOfService.js.map +1 -1
  142. package/dist/tsconfig.build.tsbuildinfo +1 -1
  143. package/dist/utils/featureflag/FeatureFlags.d.ts.map +1 -1
  144. package/dist/utils/featureflag/FeatureFlags.js.map +1 -1
  145. package/dist/utils/functions/EntityTypeUtils.d.ts +2 -2
  146. package/dist/utils/functions/EntityTypeUtils.d.ts.map +1 -1
  147. package/dist/utils/functions/EntityTypeUtils.js +135 -135
  148. package/dist/utils/functions/EntityTypeUtils.js.map +1 -1
  149. package/dist/utils/functions/getEndpoint.d.ts +1 -0
  150. package/dist/utils/functions/getEndpoint.d.ts.map +1 -1
  151. package/dist/utils/functions/getEndpoint.js +3 -3
  152. package/dist/utils/functions/getEndpoint.js.map +1 -1
  153. package/dist/utils/types/RequestableAccessRequirement.d.ts +8 -0
  154. package/dist/utils/types/RequestableAccessRequirement.d.ts.map +1 -0
  155. package/dist/utils/types/RequestableAccessRequirement.js +9 -0
  156. package/dist/utils/types/RequestableAccessRequirement.js.map +1 -0
  157. package/package.json +3 -3
  158. package/dist/testutils/ReactQueryMockUtils.js +0 -676
  159. package/dist/testutils/ReactQueryMockUtils.js.map +0 -1
@@ -1,86 +1,89 @@
1
- import e from "../ConfirmationDialog/index.js";
2
- import { AccessRequirementAclEditor as t } from "../AccessRequirementAclEditor/AccessRequirementAclEditor.js";
3
- import n from "../SetBasicAccessRequirementFields/index.js";
4
- import r from "../SetManagedAccessRequirementFields/index.js";
5
- import { SetAccessRequirementCommonFields as i } from "../SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js";
1
+ import { useGetFeatureFlag as e } from "../../synapse-queries/featureflags/useGetFeatureFlag.js";
2
+ import t from "../ConfirmationDialog/index.js";
3
+ import { AccessRequirementAclEditor as n } from "../AccessRequirementAclEditor/AccessRequirementAclEditor.js";
4
+ import { FeatureFlagEnum as r } from "../../utils/featureflag/FeatureFlags.js";
5
+ import i from "../SetBasicAccessRequirementFields/index.js";
6
+ import a from "../SetManagedAccessRequirementFields/index.js";
7
+ import { SetAccessRequirementCommonFields as o } from "../SetAccessRequirementCommonFields/SetAccessRequirementCommonFields.js";
6
8
  import "../SetAccessRequirementCommonFields/index.js";
7
- import { getDialogTitle as a, isLastStep as o } from "./CreateOrUpdateAccessRequirementWizardUtils.js";
8
- import { useMemo as s, useRef as c, useState as l } from "react";
9
- import { jsx as u } from "react/jsx-runtime";
10
- import { MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE as d } from "@sage-bionetworks/synapse-types";
9
+ import { getDialogTitle as s, isLastStep as c } from "./CreateOrUpdateAccessRequirementWizardUtils.js";
10
+ import { useMemo as l, useRef as u, useState as d } from "react";
11
+ import { jsx as f } from "react/jsx-runtime";
12
+ import { JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE as p, MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE as m } from "@sage-bionetworks/synapse-types";
11
13
  //#region src/components/CreateOrUpdateAccessRequirementWizard/CreateOrUpdateAccessRequirementWizard.tsx
12
- function f(f) {
13
- let { open: p, onCancel: m, onComplete: h } = f, [g, _] = l("SET_AR_COMMON_FIELDS"), [v, y] = l(!1), [b, x] = l(f.accessRequirementId), S = c(null), C = c(null), w = c(null), T = c(null), E = !!f.accessRequirementId, D = s(() => {
14
- switch (g) {
15
- case "SET_AR_COMMON_FIELDS": return /* @__PURE__ */ u(i, {
16
- ref: S,
14
+ function h(h) {
15
+ let { open: g, onCancel: _, onComplete: v } = h, y = e(r.ACT_DASHBOARD_FORM_TEMPLATES), [b, x] = d("SET_AR_COMMON_FIELDS"), [S, C] = d(!1), [w, T] = d(h.accessRequirementId), E = u(null), D = u(null), O = u(null), k = u(null), A = !!h.accessRequirementId, j = l(() => {
16
+ switch (b) {
17
+ case "SET_AR_COMMON_FIELDS": return /* @__PURE__ */ f(o, {
18
+ ref: E,
17
19
  onSave: (e, t) => {
18
- x(e), _(t === d ? "SET_MANAGED_AR_FIELDS" : "SET_BASIC_AR_FIELDS"), y(!1);
20
+ T(e), x(t === m || y && t === p ? "SET_MANAGED_AR_FIELDS" : "SET_BASIC_AR_FIELDS"), C(!1);
19
21
  },
20
- onError: () => y(!1),
21
- subject: f.subject,
22
- accessRequirementId: f.accessRequirementId
22
+ onError: () => C(!1),
23
+ subject: h.subject,
24
+ accessRequirementId: h.accessRequirementId
23
25
  });
24
- case "SET_MANAGED_AR_FIELDS": return /* @__PURE__ */ u(r, {
25
- ref: C,
26
- accessRequirementId: b,
26
+ case "SET_MANAGED_AR_FIELDS": return /* @__PURE__ */ f(a, {
27
+ ref: D,
28
+ accessRequirementId: w,
27
29
  onSave: () => {
28
- _("SET_MANAGED_AR_ACL_PERMISSIONS"), y(!1);
30
+ x("SET_MANAGED_AR_ACL_PERMISSIONS"), C(!1);
29
31
  },
30
32
  onError: () => {
31
- y(!1);
33
+ C(!1);
32
34
  }
33
35
  });
34
- case "SET_MANAGED_AR_ACL_PERMISSIONS": return /* @__PURE__ */ u(t, {
35
- ref: w,
36
- accessRequirementId: b,
36
+ case "SET_MANAGED_AR_ACL_PERMISSIONS": return /* @__PURE__ */ f(n, {
37
+ ref: O,
38
+ accessRequirementId: w,
37
39
  onSaveComplete: (e) => {
38
- e && h(b), y(!1);
40
+ e && v(w), C(!1);
39
41
  }
40
42
  });
41
- case "SET_BASIC_AR_FIELDS": return /* @__PURE__ */ u(n, {
42
- ref: T,
43
- accessRequirementId: b,
43
+ case "SET_BASIC_AR_FIELDS": return /* @__PURE__ */ f(i, {
44
+ ref: k,
45
+ accessRequirementId: w,
44
46
  onSave: () => {
45
- h(b), y(!1);
47
+ v(w), C(!1);
46
48
  },
47
- onError: () => y(!1)
49
+ onError: () => C(!1)
48
50
  });
49
51
  }
50
52
  }, [
51
- g,
52
- f.subject,
53
- f.accessRequirementId,
54
53
  b,
55
- h
54
+ h.subject,
55
+ h.accessRequirementId,
56
+ w,
57
+ v,
58
+ y
56
59
  ]);
57
- return /* @__PURE__ */ u(e, {
58
- open: p,
59
- onCancel: m,
60
+ return /* @__PURE__ */ f(t, {
61
+ open: g,
62
+ onCancel: _,
60
63
  onConfirm: (e) => {
61
- switch (e.preventDefault(), y(!0), g) {
64
+ switch (e.preventDefault(), C(!0), b) {
62
65
  case "SET_AR_COMMON_FIELDS":
63
- S?.current?.save();
66
+ E?.current?.save();
64
67
  return;
65
68
  case "SET_MANAGED_AR_FIELDS":
66
- C?.current?.save();
69
+ D?.current?.save();
67
70
  return;
68
71
  case "SET_MANAGED_AR_ACL_PERMISSIONS":
69
- w?.current?.save();
72
+ O?.current?.save();
70
73
  return;
71
- case "SET_BASIC_AR_FIELDS": T?.current?.save();
74
+ case "SET_BASIC_AR_FIELDS": k?.current?.save();
72
75
  }
73
76
  },
74
77
  confirmButtonProps: {
75
- children: o(g) ? "Save" : "Save & Continue",
76
- disabled: v
78
+ children: c(b) ? "Save" : "Save & Continue",
79
+ disabled: S
77
80
  },
78
81
  maxWidth: "md",
79
- title: a(g, E),
80
- content: D
82
+ title: s(b, A),
83
+ content: j
81
84
  });
82
85
  }
83
86
  //#endregion
84
- export { f as CreateOrUpdateAccessRequirementWizard, f as default };
87
+ export { h as CreateOrUpdateAccessRequirementWizard, h as default };
85
88
 
86
89
  //# sourceMappingURL=CreateOrUpdateAccessRequirementWizard.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"CreateOrUpdateAccessRequirementWizard.js","names":[],"sources":["../../../src/components/CreateOrUpdateAccessRequirementWizard/CreateOrUpdateAccessRequirementWizard.tsx"],"sourcesContent":["import { MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE } from '@sage-bionetworks/synapse-types'\nimport { MouseEventHandler, useMemo, useRef, useState } from 'react'\nimport {\n AccessRequirementAclEditor,\n AccessRequirementAclEditorHandle,\n} from '../AccessRequirementAclEditor/AccessRequirementAclEditor'\nimport ConfirmationDialog from '../ConfirmationDialog'\nimport {\n SetAccessRequirementCommonFields,\n SetAccessRequirementCommonFieldsHandle,\n SetAccessRequirementCommonFieldsProps,\n} from '../SetAccessRequirementCommonFields'\nimport SetBasicAccessRequirementFields, {\n SetBasicAccessRequirementFieldsHandle,\n} from '../SetBasicAccessRequirementFields'\nimport SetManagedAccessRequirementFields, {\n SetManagedAccessRequirementFieldsHandle,\n} from '../SetManagedAccessRequirementFields'\nimport {\n CreateOrUpdateAccessRequirementWizardStep,\n getDialogTitle,\n isLastStep,\n} from './CreateOrUpdateAccessRequirementWizardUtils'\n\nexport type CreateOrUpdateAccessRequirementWizardProps = {\n open: boolean\n onCancel: () => void\n onComplete: (accessRequirementID?: string) => void // return the (possibly new) Access Requirement ID\n} & Pick<\n SetAccessRequirementCommonFieldsProps,\n 'subject' | 'accessRequirementId'\n>\n\nexport function CreateOrUpdateAccessRequirementWizard(\n props: CreateOrUpdateAccessRequirementWizardProps,\n) {\n const { open, onCancel, onComplete } = props\n\n const [step, setStep] = useState<CreateOrUpdateAccessRequirementWizardStep>(\n 'SET_AR_COMMON_FIELDS',\n )\n const [isLoading, setIsLoading] = useState<boolean>(false)\n const [accessRequirementId, setAccessRequirementId] = useState<\n string | undefined\n >(props.accessRequirementId)\n\n const setArCommonFieldsRef =\n useRef<SetAccessRequirementCommonFieldsHandle>(null)\n const setManagedArFieldsRef =\n useRef<SetManagedAccessRequirementFieldsHandle>(null)\n const editArAclRef = useRef<AccessRequirementAclEditorHandle>(null)\n const setBasicArFieldsRef =\n useRef<SetBasicAccessRequirementFieldsHandle>(null)\n\n const isEditing = Boolean(props['accessRequirementId'])\n\n const stepContent = useMemo(() => {\n switch (step) {\n case 'SET_AR_COMMON_FIELDS':\n return (\n <SetAccessRequirementCommonFields\n ref={setArCommonFieldsRef}\n onSave={(accessRequirementId, accessRequirementConcreteType) => {\n setAccessRequirementId(accessRequirementId)\n const nextStep: CreateOrUpdateAccessRequirementWizardStep =\n accessRequirementConcreteType ===\n MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE\n ? 'SET_MANAGED_AR_FIELDS'\n : 'SET_BASIC_AR_FIELDS'\n setStep(nextStep)\n setIsLoading(false)\n }}\n onError={() => setIsLoading(false)}\n subject={props.subject}\n accessRequirementId={props.accessRequirementId}\n />\n )\n case 'SET_MANAGED_AR_FIELDS':\n return (\n <SetManagedAccessRequirementFields\n ref={setManagedArFieldsRef}\n accessRequirementId={accessRequirementId!}\n onSave={() => {\n setStep('SET_MANAGED_AR_ACL_PERMISSIONS')\n setIsLoading(false)\n }}\n onError={() => {\n setIsLoading(false)\n }}\n />\n )\n case 'SET_MANAGED_AR_ACL_PERMISSIONS':\n return (\n <AccessRequirementAclEditor\n ref={editArAclRef}\n accessRequirementId={accessRequirementId!}\n onSaveComplete={saveSuccessful => {\n if (saveSuccessful) {\n onComplete(accessRequirementId)\n }\n setIsLoading(false)\n }}\n />\n )\n case 'SET_BASIC_AR_FIELDS':\n return (\n <SetBasicAccessRequirementFields\n ref={setBasicArFieldsRef}\n accessRequirementId={accessRequirementId!}\n onSave={() => {\n onComplete(accessRequirementId)\n setIsLoading(false)\n }}\n onError={() => setIsLoading(false)}\n />\n )\n }\n }, [\n step,\n props.subject,\n props.accessRequirementId,\n accessRequirementId,\n onComplete,\n ])\n\n const onClickPrimary: MouseEventHandler<HTMLButtonElement> = e => {\n // SWC-7055 - The default action may trigger `beforeunload` and erroneously warn the user about leaving the page.\n e.preventDefault()\n setIsLoading(true)\n switch (step) {\n case 'SET_AR_COMMON_FIELDS':\n setArCommonFieldsRef?.current?.save()\n return\n case 'SET_MANAGED_AR_FIELDS':\n setManagedArFieldsRef?.current?.save()\n return\n case 'SET_MANAGED_AR_ACL_PERMISSIONS':\n editArAclRef?.current?.save()\n return\n case 'SET_BASIC_AR_FIELDS':\n setBasicArFieldsRef?.current?.save()\n }\n }\n\n return (\n <ConfirmationDialog\n open={open}\n onCancel={onCancel}\n onConfirm={onClickPrimary}\n confirmButtonProps={{\n children: isLastStep(step) ? 'Save' : 'Save & Continue',\n disabled: isLoading,\n }}\n maxWidth={'md'}\n title={getDialogTitle(step, isEditing)}\n content={stepContent}\n />\n )\n}\n\nexport default CreateOrUpdateAccessRequirementWizard\n"],"mappings":";;;;;;;;;;;AAiCA,SAAgB,EACd,GACA;CACA,IAAM,EAAE,SAAM,aAAU,kBAAe,GAEjC,CAAC,GAAM,KAAW,EACtB,sBACF,GACM,CAAC,GAAW,KAAgB,EAAkB,EAAK,GACnD,CAAC,GAAqB,KAA0B,EAEpD,EAAM,mBAAmB,GAErB,IACJ,EAA+C,IAAI,GAC/C,IACJ,EAAgD,IAAI,GAChD,IAAe,EAAyC,IAAI,GAC5D,IACJ,EAA8C,IAAI,GAE9C,IAAY,EAAQ,EAAM,qBAE1B,IAAc,QAAc;EAChC,QAAQ,GAAR;GACE,KAAK,wBACH,OACE,kBAAC,GAAD;IACE,KAAK;IACL,SAAS,GAAqB,MAAkC;KAQ9D,AAPA,EAAuB,CAAmB,GAM1C,EAJE,MACA,IACI,0BACA,qBACU,GAChB,EAAa,EAAK;IACpB;IACA,eAAe,EAAa,EAAK;IACjC,SAAS,EAAM;IACf,qBAAqB,EAAM;GAC5B,CAAA;GAEL,KAAK,yBACH,OACE,kBAAC,GAAD;IACE,KAAK;IACgB;IACrB,cAAc;KAEZ,AADA,EAAQ,gCAAgC,GACxC,EAAa,EAAK;IACpB;IACA,eAAe;KACb,EAAa,EAAK;IACpB;GACD,CAAA;GAEL,KAAK,kCACH,OACE,kBAAC,GAAD;IACE,KAAK;IACgB;IACrB,iBAAgB,MAAkB;KAIhC,AAHI,KACF,EAAW,CAAmB,GAEhC,EAAa,EAAK;IACpB;GACD,CAAA;GAEL,KAAK,uBACH,OACE,kBAAC,GAAD;IACE,KAAK;IACgB;IACrB,cAAc;KAEZ,AADA,EAAW,CAAmB,GAC9B,EAAa,EAAK;IACpB;IACA,eAAe,EAAa,EAAK;GAClC,CAAA;EAEP;CACF,GAAG;EACD;EACA,EAAM;EACN,EAAM;EACN;EACA;CACF,CAAC;CAqBD,OACE,kBAAC,GAAD;EACQ;EACI;EACV,YAvByD,MAAK;GAIhE,QAFA,EAAE,eAAe,GACjB,EAAa,EAAI,GACT,GAAR;IACE,KAAK;KACH,GAAsB,SAAS,KAAK;KACpC;IACF,KAAK;KACH,GAAuB,SAAS,KAAK;KACrC;IACF,KAAK;KACH,GAAc,SAAS,KAAK;KAC5B;IACF,KAAK,uBACH,GAAqB,SAAS,KAAK;GACvC;EACF;EAOI,oBAAoB;GAClB,UAAU,EAAW,CAAI,IAAI,SAAS;GACtC,UAAU;EACZ;EACA,UAAU;EACV,OAAO,EAAe,GAAM,CAAS;EACrC,SAAS;CACV,CAAA;AAEL"}
1
+ {"version":3,"file":"CreateOrUpdateAccessRequirementWizard.js","names":[],"sources":["../../../src/components/CreateOrUpdateAccessRequirementWizard/CreateOrUpdateAccessRequirementWizard.tsx"],"sourcesContent":["import { useGetFeatureFlag } from '@/synapse-queries/featureflags/useGetFeatureFlag'\nimport { FeatureFlagEnum } from '@/utils/featureflag/FeatureFlags'\nimport {\n JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n} from '@sage-bionetworks/synapse-types'\nimport { MouseEventHandler, useMemo, useRef, useState } from 'react'\nimport {\n AccessRequirementAclEditor,\n AccessRequirementAclEditorHandle,\n} from '../AccessRequirementAclEditor/AccessRequirementAclEditor'\nimport ConfirmationDialog from '../ConfirmationDialog'\nimport {\n SetAccessRequirementCommonFields,\n SetAccessRequirementCommonFieldsHandle,\n SetAccessRequirementCommonFieldsProps,\n} from '../SetAccessRequirementCommonFields'\nimport SetBasicAccessRequirementFields, {\n SetBasicAccessRequirementFieldsHandle,\n} from '../SetBasicAccessRequirementFields'\nimport SetManagedAccessRequirementFields, {\n SetManagedAccessRequirementFieldsHandle,\n} from '../SetManagedAccessRequirementFields'\nimport {\n CreateOrUpdateAccessRequirementWizardStep,\n getDialogTitle,\n isLastStep,\n} from './CreateOrUpdateAccessRequirementWizardUtils'\n\nexport type CreateOrUpdateAccessRequirementWizardProps = {\n open: boolean\n onCancel: () => void\n onComplete: (accessRequirementID?: string) => void // return the (possibly new) Access Requirement ID\n} & Pick<\n SetAccessRequirementCommonFieldsProps,\n 'subject' | 'accessRequirementId'\n>\n\nexport function CreateOrUpdateAccessRequirementWizard(\n props: CreateOrUpdateAccessRequirementWizardProps,\n) {\n const { open, onCancel, onComplete } = props\n const isSchemaDrivenEnabled = useGetFeatureFlag(\n FeatureFlagEnum.ACT_DASHBOARD_FORM_TEMPLATES,\n )\n\n const [step, setStep] = useState<CreateOrUpdateAccessRequirementWizardStep>(\n 'SET_AR_COMMON_FIELDS',\n )\n const [isLoading, setIsLoading] = useState<boolean>(false)\n const [accessRequirementId, setAccessRequirementId] = useState<\n string | undefined\n >(props.accessRequirementId)\n\n const setArCommonFieldsRef =\n useRef<SetAccessRequirementCommonFieldsHandle>(null)\n const setManagedArFieldsRef =\n useRef<SetManagedAccessRequirementFieldsHandle>(null)\n const editArAclRef = useRef<AccessRequirementAclEditorHandle>(null)\n const setBasicArFieldsRef =\n useRef<SetBasicAccessRequirementFieldsHandle>(null)\n\n const isEditing = Boolean(props['accessRequirementId'])\n\n const stepContent = useMemo(() => {\n switch (step) {\n case 'SET_AR_COMMON_FIELDS':\n return (\n <SetAccessRequirementCommonFields\n ref={setArCommonFieldsRef}\n onSave={(accessRequirementId, accessRequirementConcreteType) => {\n setAccessRequirementId(accessRequirementId)\n const isReviewedInSynapse =\n accessRequirementConcreteType ===\n MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE ||\n (isSchemaDrivenEnabled &&\n accessRequirementConcreteType ===\n JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE)\n const nextStep: CreateOrUpdateAccessRequirementWizardStep =\n isReviewedInSynapse\n ? 'SET_MANAGED_AR_FIELDS'\n : 'SET_BASIC_AR_FIELDS'\n setStep(nextStep)\n setIsLoading(false)\n }}\n onError={() => setIsLoading(false)}\n subject={props.subject}\n accessRequirementId={props.accessRequirementId}\n />\n )\n case 'SET_MANAGED_AR_FIELDS':\n return (\n <SetManagedAccessRequirementFields\n ref={setManagedArFieldsRef}\n accessRequirementId={accessRequirementId!}\n onSave={() => {\n setStep('SET_MANAGED_AR_ACL_PERMISSIONS')\n setIsLoading(false)\n }}\n onError={() => {\n setIsLoading(false)\n }}\n />\n )\n case 'SET_MANAGED_AR_ACL_PERMISSIONS':\n return (\n <AccessRequirementAclEditor\n ref={editArAclRef}\n accessRequirementId={accessRequirementId!}\n onSaveComplete={saveSuccessful => {\n if (saveSuccessful) {\n onComplete(accessRequirementId)\n }\n setIsLoading(false)\n }}\n />\n )\n case 'SET_BASIC_AR_FIELDS':\n return (\n <SetBasicAccessRequirementFields\n ref={setBasicArFieldsRef}\n accessRequirementId={accessRequirementId!}\n onSave={() => {\n onComplete(accessRequirementId)\n setIsLoading(false)\n }}\n onError={() => setIsLoading(false)}\n />\n )\n }\n }, [\n step,\n props.subject,\n props.accessRequirementId,\n accessRequirementId,\n onComplete,\n isSchemaDrivenEnabled,\n ])\n\n const onClickPrimary: MouseEventHandler<HTMLButtonElement> = e => {\n // SWC-7055 - The default action may trigger `beforeunload` and erroneously warn the user about leaving the page.\n e.preventDefault()\n setIsLoading(true)\n switch (step) {\n case 'SET_AR_COMMON_FIELDS':\n setArCommonFieldsRef?.current?.save()\n return\n case 'SET_MANAGED_AR_FIELDS':\n setManagedArFieldsRef?.current?.save()\n return\n case 'SET_MANAGED_AR_ACL_PERMISSIONS':\n editArAclRef?.current?.save()\n return\n case 'SET_BASIC_AR_FIELDS':\n setBasicArFieldsRef?.current?.save()\n }\n }\n\n return (\n <ConfirmationDialog\n open={open}\n onCancel={onCancel}\n onConfirm={onClickPrimary}\n confirmButtonProps={{\n children: isLastStep(step) ? 'Save' : 'Save & Continue',\n disabled: isLoading,\n }}\n maxWidth={'md'}\n title={getDialogTitle(step, isEditing)}\n content={stepContent}\n />\n )\n}\n\nexport default CreateOrUpdateAccessRequirementWizard\n"],"mappings":";;;;;;;;;;;;;AAsCA,SAAgB,EACd,GACA;CACA,IAAM,EAAE,SAAM,aAAU,kBAAe,GACjC,IAAwB,EAC5B,EAAgB,4BAClB,GAEM,CAAC,GAAM,KAAW,EACtB,sBACF,GACM,CAAC,GAAW,KAAgB,EAAkB,EAAK,GACnD,CAAC,GAAqB,KAA0B,EAEpD,EAAM,mBAAmB,GAErB,IACJ,EAA+C,IAAI,GAC/C,IACJ,EAAgD,IAAI,GAChD,IAAe,EAAyC,IAAI,GAC5D,IACJ,EAA8C,IAAI,GAE9C,IAAY,EAAQ,EAAM,qBAE1B,IAAc,QAAc;EAChC,QAAQ,GAAR;GACE,KAAK,wBACH,OACE,kBAAC,GAAD;IACE,KAAK;IACL,SAAS,GAAqB,MAAkC;KAa9D,AAZA,EAAuB,CAAmB,GAW1C,EATE,MACE,KACD,KACC,MACE,IAGA,0BACA,qBACU,GAChB,EAAa,EAAK;IACpB;IACA,eAAe,EAAa,EAAK;IACjC,SAAS,EAAM;IACf,qBAAqB,EAAM;GAC5B,CAAA;GAEL,KAAK,yBACH,OACE,kBAAC,GAAD;IACE,KAAK;IACgB;IACrB,cAAc;KAEZ,AADA,EAAQ,gCAAgC,GACxC,EAAa,EAAK;IACpB;IACA,eAAe;KACb,EAAa,EAAK;IACpB;GACD,CAAA;GAEL,KAAK,kCACH,OACE,kBAAC,GAAD;IACE,KAAK;IACgB;IACrB,iBAAgB,MAAkB;KAIhC,AAHI,KACF,EAAW,CAAmB,GAEhC,EAAa,EAAK;IACpB;GACD,CAAA;GAEL,KAAK,uBACH,OACE,kBAAC,GAAD;IACE,KAAK;IACgB;IACrB,cAAc;KAEZ,AADA,EAAW,CAAmB,GAC9B,EAAa,EAAK;IACpB;IACA,eAAe,EAAa,EAAK;GAClC,CAAA;EAEP;CACF,GAAG;EACD;EACA,EAAM;EACN,EAAM;EACN;EACA;EACA;CACF,CAAC;CAqBD,OACE,kBAAC,GAAD;EACQ;EACI;EACV,YAvByD,MAAK;GAIhE,QAFA,EAAE,eAAe,GACjB,EAAa,EAAI,GACT,GAAR;IACE,KAAK;KACH,GAAsB,SAAS,KAAK;KACpC;IACF,KAAK;KACH,GAAuB,SAAS,KAAK;KACrC;IACF,KAAK;KACH,GAAc,SAAS,KAAK;KAC5B;IACF,KAAK,uBACH,GAAqB,SAAS,KAAK;GACvC;EACF;EAOI,oBAAoB;GAClB,UAAU,EAAW,CAAI,IAAI,SAAS;GACtC,UAAU;EACZ;EACA,UAAU;EACV,OAAO,EAAe,GAAM,CAAS;EACrC,SAAS;CACV,CAAA;AAEL"}
@@ -1,4 +1,5 @@
1
1
  import { GridModel } from '@/components/DataGrid/DataGridTypes';
2
+ import { CompactCodecPatch } from 'json-joy/lib/json-crdt-patch/codec/compact';
2
3
  type DataGridWebSocketConstructorArgs = {
3
4
  replicaId: number;
4
5
  url: string;
@@ -14,6 +15,9 @@ type DataGridWebSocketConstructorArgs = {
14
15
  socket?: WebSocket;
15
16
  model?: GridModel | null;
16
17
  patchThrottleMs?: number;
18
+ /** Patches the previous connection never saw acknowledged, resent in order ahead of new ones */
19
+ pendingPatches?: CompactCodecPatch[];
20
+ patchAckTimeoutMs?: number;
17
21
  };
18
22
  export declare class DataGridWebSocket {
19
23
  private socket;
@@ -24,6 +28,12 @@ export declare class DataGridWebSocket {
24
28
  private maxPayloadSizeBytes;
25
29
  private throttledSendPatch;
26
30
  private snapshotDecoder;
31
+ private unacknowledgedPatches;
32
+ private inFlightPatchRequestId;
33
+ private patchAckTimeoutMs;
34
+ private patchAckTimer;
35
+ private isClosing;
36
+ private isSyncExchangeOpen;
27
37
  private onModelCreate;
28
38
  private onGridReady;
29
39
  private onStatusChange;
@@ -34,7 +44,17 @@ export declare class DataGridWebSocket {
34
44
  private onError;
35
45
  constructor(args: DataGridWebSocketConstructorArgs);
36
46
  private attachSocketHandlers;
47
+ /**
48
+ * Closes the connection once every unacknowledged patch has been acknowledged, so edits made
49
+ * just before leaving are not lost. The owner has moved on, so no further callbacks fire.
50
+ */
37
51
  disconnect(): void;
52
+ private closeSocket;
53
+ /**
54
+ * @returns the patches the server has not acknowledged, oldest first. A replacement connection
55
+ * created with these as `pendingPatches` resends them in order.
56
+ */
57
+ getPendingPatches(): CompactCodecPatch[];
38
58
  /**
39
59
  * Flushes the local model clock and sends the resulting patch (or a clock-sync
40
60
  * message) to the server so that both sides converge.
@@ -45,13 +65,21 @@ export declare class DataGridWebSocket {
45
65
  private handlePatchPayload;
46
66
  private handleSnapshotPayload;
47
67
  private handleResponseComplete;
68
+ private handlePatchAcknowledged;
48
69
  private handleNotification;
49
70
  private sendMessage;
50
71
  sendPatch(): void;
51
72
  /**
52
- * @returns true if one or more patches were sent
73
+ * @returns true if the model had local changes, which are now queued to be sent
53
74
  */
54
75
  private sendPatchImmediate;
76
+ private sendNextPatch;
77
+ private stopWaitingForPatchAck;
78
+ /**
79
+ * Resending on the same connection could reorder patches, so the connection is dropped and
80
+ * the owner reconnects with getPendingPatches(). The server ignores patches it already stored.
81
+ */
82
+ private handlePatchAckTimeout;
55
83
  private sendSyncMessage;
56
84
  private fetchAndDecodeSnapshot;
57
85
  }
@@ -1 +1 @@
1
- {"version":3,"file":"DataGridWebSocket.d.ts","sourceRoot":"","sources":["../../../src/components/DataGrid/DataGridWebSocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAyC/D,KAAK,gCAAgC,GAAG;IACtC,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACvE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAA;IAC1C,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC/B,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAA;IAClC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAA;AAQD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,mBAAmB,CAAQ;IACnC,OAAO,CAAC,kBAAkB,CAA2B;IACrD,OAAO,CAAC,eAAe,CAAwB;IAE/C,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,cAAc,CAAqD;IAC3E,OAAO,CAAC,kBAAkB,CAAY;IACtC,OAAO,CAAC,qBAAqB,CAAY;IACzC,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,OAAO,CAA0B;gBAE7B,IAAI,EAAE,gCAAgC;IA+ClD,OAAO,CAAC,oBAAoB;IAwBrB,UAAU;IAWjB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,kBAAkB;YAiBZ,qBAAqB;IAYnC,OAAO,CAAC,sBAAsB;IAS9B,OAAO,CAAC,kBAAkB;IAmD1B,OAAO,CAAC,WAAW;IAWZ,SAAS;IAIhB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA0B1B,OAAO,CAAC,eAAe;YAUT,sBAAsB;CAYrC"}
1
+ {"version":3,"file":"DataGridWebSocket.d.ts","sourceRoot":"","sources":["../../../src/components/DataGrid/DataGridWebSocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAU/D,OAAO,EACL,iBAAiB,EAElB,MAAM,4CAA4C,CAAA;AA4BnD,KAAK,gCAAgC,GAAG;IACtC,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACvE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAA;IAC1C,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC/B,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAA;IAClC,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,SAAS,CAAC,EAAE,MAAM,IAAI,CAAA;IACtB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAA;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,gGAAgG;IAChG,cAAc,CAAC,EAAE,iBAAiB,EAAE,CAAA;IACpC,iBAAiB,CAAC,EAAE,MAAM,CAAA;CAC3B,CAAA;AAUD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,mBAAmB,CAAQ;IACnC,OAAO,CAAC,kBAAkB,CAA2B;IACrD,OAAO,CAAC,eAAe,CAAwB;IAG/C,OAAO,CAAC,qBAAqB,CAAqB;IAClD,OAAO,CAAC,sBAAsB,CAAsB;IACpD,OAAO,CAAC,iBAAiB,CAAQ;IACjC,OAAO,CAAC,aAAa,CAAsB;IAE3C,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,kBAAkB,CAAQ;IAElC,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,cAAc,CAAqD;IAC3E,OAAO,CAAC,kBAAkB,CAAY;IACtC,OAAO,CAAC,qBAAqB,CAAY;IACzC,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,SAAS,CAAY;IAC7B,OAAO,CAAC,OAAO,CAA0B;gBAE7B,IAAI,EAAE,gCAAgC;IAmDlD,OAAO,CAAC,oBAAoB;IA2B5B;;;OAGG;IACI,UAAU;IAwBjB,OAAO,CAAC,WAAW;IAKnB;;;OAGG;IACI,iBAAiB,IAAI,iBAAiB,EAAE;IAI/C;;;OAGG;IACH,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,aAAa;IAkBrB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,kBAAkB;YAiBZ,qBAAqB;IAYnC,OAAO,CAAC,sBAAsB;IAc9B,OAAO,CAAC,uBAAuB;IAc/B,OAAO,CAAC,kBAAkB;IAqD1B,OAAO,CAAC,WAAW;IAWZ,SAAS;IAIhB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IAoB1B,OAAO,CAAC,aAAa;IAmBrB,OAAO,CAAC,sBAAsB;IAQ9B;;;OAGG;IACH,OAAO,CAAC,qBAAqB;IAe7B,OAAO,CAAC,eAAe;YAWT,sBAAsB;CAYrC"}
@@ -14,7 +14,7 @@ import f from "lodash-es/throttle";
14
14
  import { Decoder as p } from "json-joy/lib/json-crdt/codec/indexed/binary/Decoder";
15
15
  import { decode as m } from "cbor2";
16
16
  //#region src/components/DataGrid/DataGridWebSocket.ts
17
- var h = 30 * 1024, g = 250, _ = class {
17
+ var h = 30 * 1024, g = 250, _ = 15 * 1e3, v = class {
18
18
  socket;
19
19
  model = null;
20
20
  messageCounter;
@@ -23,6 +23,12 @@ var h = 30 * 1024, g = 250, _ = class {
23
23
  maxPayloadSizeBytes;
24
24
  throttledSendPatch;
25
25
  snapshotDecoder = new p();
26
+ unacknowledgedPatches;
27
+ inFlightPatchRequestId = null;
28
+ patchAckTimeoutMs;
29
+ patchAckTimer = null;
30
+ isClosing = !1;
31
+ isSyncExchangeOpen = !1;
26
32
  onModelCreate;
27
33
  onGridReady;
28
34
  onStatusChange;
@@ -32,8 +38,8 @@ var h = 30 * 1024, g = 250, _ = class {
32
38
  onSyncEnd;
33
39
  onError;
34
40
  constructor(e) {
35
- let { replicaId: t, url: n, onGridReady: r, onStatusChange: i, onModelCreate: o, onReplicaConnected: s, onReplicaDisconnected: l, onSyncStart: u, onSyncEnd: d, onError: p, maxPayloadSizeBytes: m, socket: _, model: v, patchThrottleMs: y } = e;
36
- this.messageCounter = new a(), this.replicaId = t, this.maxPayloadSizeBytes = m ?? h, this.socket = _ ?? new WebSocket(n), this.onModelCreate = o ?? c, this.onGridReady = r ?? c, this.onStatusChange = i ?? c, this.onReplicaConnected = s ?? c, this.onReplicaDisconnected = l ?? c, this.onSyncStart = u ?? c, this.onSyncEnd = d ?? c, this.onError = p ?? c, v && (this.model = v), this.attachSocketHandlers(), this.throttledSendPatch = f(() => this.sendPatchImmediate(), y ?? g, {
41
+ let { replicaId: t, url: n, onGridReady: r, onStatusChange: i, onModelCreate: o, onReplicaConnected: s, onReplicaDisconnected: l, onSyncStart: u, onSyncEnd: d, onError: p, maxPayloadSizeBytes: m, socket: v, model: y, patchThrottleMs: b, pendingPatches: x, patchAckTimeoutMs: S } = e;
42
+ this.messageCounter = new a(), this.replicaId = t, this.maxPayloadSizeBytes = m ?? h, this.socket = v ?? new WebSocket(n), this.unacknowledgedPatches = [...x ?? []], this.patchAckTimeoutMs = S ?? _, this.onModelCreate = o ?? c, this.onGridReady = r ?? c, this.onStatusChange = i ?? c, this.onReplicaConnected = s ?? c, this.onReplicaDisconnected = l ?? c, this.onSyncStart = u ?? c, this.onSyncEnd = d ?? c, this.onError = p ?? c, y && (this.model = y), this.attachSocketHandlers(), this.throttledSendPatch = f(() => this.sendPatchImmediate(), b ?? g, {
37
43
  leading: !1,
38
44
  trailing: !0
39
45
  });
@@ -44,13 +50,23 @@ var h = 30 * 1024, g = 250, _ = class {
44
50
  }, this.socket.onmessage = (e) => {
45
51
  typeof e.data == "string" ? this.handleMessage(e.data) : console.error("Received non-string message data:", e.data);
46
52
  }, this.socket.onclose = () => {
47
- console.debug("Disconnected from the WebSocket server"), this.onStatusChange(!1, this);
53
+ console.debug("Disconnected from the WebSocket server"), this.stopWaitingForPatchAck(), this.throttledSendPatch.cancel(), this.onStatusChange(!1, this);
48
54
  }, this.socket.onerror = (e) => {
49
55
  console.error("WebSocket error:", e);
50
56
  };
51
57
  }
52
58
  disconnect() {
53
- this.throttledSendPatch.flush(), this.throttledSendPatch.cancel(), this.socket.readyState === WebSocket.OPEN ? (this.socket.close(), console.debug("WebSocket connection closed")) : console.warn("WebSocket is not open. No action taken.");
59
+ if (this.socket.readyState !== WebSocket.OPEN) {
60
+ this.throttledSendPatch.cancel(), console.warn("WebSocket is not open. No action taken.");
61
+ return;
62
+ }
63
+ this.throttledSendPatch.flush(), this.throttledSendPatch.cancel(), this.isClosing = !0, this.onModelCreate = c, this.onGridReady = c, this.onStatusChange = c, this.onReplicaConnected = c, this.onReplicaDisconnected = c, this.onSyncStart = c, this.onSyncEnd = c, this.onError = c, this.unacknowledgedPatches.length === 0 && this.closeSocket();
64
+ }
65
+ closeSocket() {
66
+ this.socket.close(), console.debug("WebSocket connection closed");
67
+ }
68
+ getPendingPatches() {
69
+ return [...this.unacknowledgedPatches];
54
70
  }
55
71
  sendClockSync() {
56
72
  if (!this.model) {
@@ -64,7 +80,7 @@ var h = 30 * 1024, g = 250, _ = class {
64
80
  }
65
81
  handleMessage(r) {
66
82
  let a = i.fromJson(JSON.parse(r));
67
- a instanceof t ? this.handleResponse(a) : a instanceof n ? this.handleResponseComplete() : a instanceof e ? this.handleNotification(a) : console.warn("Unexpected WebSocket message format:", a);
83
+ this.isClosing && !(a instanceof n) || (a instanceof t ? this.handleResponse(a) : a instanceof n ? this.handleResponseComplete(a) : a instanceof e ? this.handleNotification(a) : console.warn("Unexpected WebSocket message format:", a));
68
84
  }
69
85
  handleResponse(e) {
70
86
  let t = e.getPayload();
@@ -100,8 +116,15 @@ var h = 30 * 1024, g = 250, _ = class {
100
116
  console.error("Failed to fetch or decode snapshot", e);
101
117
  }
102
118
  }
103
- handleResponseComplete() {
104
- this.onGridReady(), this.onSyncEnd(), console.debug("Clocks synchronized with server. Incrementing sequence number.");
119
+ handleResponseComplete(e) {
120
+ if (e.getSubscriptionId() === this.inFlightPatchRequestId) {
121
+ this.handlePatchAcknowledged();
122
+ return;
123
+ }
124
+ this.isSyncExchangeOpen = !1, this.onGridReady(), this.onSyncEnd(), console.debug("Clocks synchronized with server. Incrementing sequence number.");
125
+ }
126
+ handlePatchAcknowledged() {
127
+ this.unacknowledgedPatches.shift(), this.stopWaitingForPatchAck(), this.unacknowledgedPatches.length > 0 ? this.sendNextPatch() : this.isClosing ? this.closeSocket() : this.isSyncExchangeOpen && this.model && this.sendSyncMessage(this.verboseEncoder.encode(this.model).time);
105
128
  }
106
129
  handleNotification(e) {
107
130
  let t = e.getMethodName();
@@ -110,7 +133,7 @@ var h = 30 * 1024, g = 250, _ = class {
110
133
  console.debug("Received ping from server");
111
134
  break;
112
135
  case "connected":
113
- console.debug("Server ready to receive patches"), this.sendSyncMessage(this.model ? this.verboseEncoder.encode(this.model).time : void 0);
136
+ console.debug("Server ready to receive patches"), this.sendSyncMessage(this.model ? this.verboseEncoder.encode(this.model).time : void 0), this.sendNextPatch();
114
137
  break;
115
138
  case "error":
116
139
  console.warn("Error from server:", e.getPayload()), this.onError(e.getPayload());
@@ -145,15 +168,24 @@ var h = 30 * 1024, g = 250, _ = class {
145
168
  sendPatchImmediate() {
146
169
  if (!this.model) return console.warn("Model is not initialized. Cannot send patch."), !1;
147
170
  let e = this.model.api.flush(), t = e.ops.length > 0;
148
- return t && o(e, this.maxPayloadSizeBytes).forEach((e) => {
149
- console.debug("Sending patch to server:", e);
150
- let t = new r(this.messageCounter.getNext(), "patch", e);
151
- this.sendMessage(t);
152
- }), t;
171
+ return t && (this.unacknowledgedPatches.push(...o(e, this.maxPayloadSizeBytes)), this.sendNextPatch()), t;
172
+ }
173
+ sendNextPatch() {
174
+ let e = this.unacknowledgedPatches[0];
175
+ if (e === void 0 || this.inFlightPatchRequestId !== null || this.socket.readyState !== WebSocket.OPEN) return;
176
+ console.debug("Sending patch to server:", e);
177
+ let t = this.messageCounter.getNext();
178
+ this.inFlightPatchRequestId = t, this.patchAckTimer = window.setTimeout(() => this.handlePatchAckTimeout(), this.patchAckTimeoutMs), this.sendMessage(new r(t, "patch", e));
179
+ }
180
+ stopWaitingForPatchAck() {
181
+ this.patchAckTimer !== null && (window.clearTimeout(this.patchAckTimer), this.patchAckTimer = null), this.inFlightPatchRequestId = null;
182
+ }
183
+ handlePatchAckTimeout() {
184
+ console.warn("Timed out waiting for a patch acknowledgement. Dropping the connection so unacknowledged patches are resent."), this.socket.onopen = null, this.socket.onmessage = null, this.socket.onclose = null, this.socket.onerror = null, this.throttledSendPatch.cancel(), this.stopWaitingForPatchAck(), this.socket.close(), this.onStatusChange(!1, this);
153
185
  }
154
186
  sendSyncMessage(e) {
155
187
  let t = new r(this.messageCounter.getNext(), "synchronize-clock", e ?? []);
156
- this.onSyncStart(), this.sendMessage(t);
188
+ this.isSyncExchangeOpen = !0, this.onSyncStart(), this.sendMessage(t);
157
189
  }
158
190
  async fetchAndDecodeSnapshot(e) {
159
191
  let t = await (await (await s(e)).blob()).arrayBuffer(), n = m(new Uint8Array(t));
@@ -161,6 +193,6 @@ var h = 30 * 1024, g = 250, _ = class {
161
193
  }
162
194
  };
163
195
  //#endregion
164
- export { _ as DataGridWebSocket };
196
+ export { v as DataGridWebSocket };
165
197
 
166
198
  //# sourceMappingURL=DataGridWebSocket.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DataGridWebSocket.js","names":["GridModel","JsonRx","JsonRxMessage","JsonRxNotification","JsonRxRequestComplete","JsonRxResponse","JsonRxResponseComplete","MessageCounter","splitPatch","Model","CompactCodecPatch","decode","Encoder","VerboseEncoder","JsonCrdtVerboseLogicalTimestamp","noop","throttle","DebouncedFunc","Decoder","SnapshotDecoder","decodeCbor","IndexedFields","fetchWithExponentialTimeout","SynapseGridWebSocketMessagePayloadType","PATCH","SNAPSHOT","PATCHES","SynapseGridWebSocketMessagePayload","type","body","DataGridWebSocketConstructorArgs","replicaId","url","onGridReady","onStatusChange","isOpen","instance","DataGridWebSocket","onModelCreate","model","onReplicaConnected","onReplicaDisconnected","onSyncStart","onSyncEnd","onError","error","maxPayloadSizeBytes","socket","WebSocket","patchThrottleMs","DEFAULT_MAX_PAYLOAD_SIZE_BYTES","DEFAULT_PATCH_THROTTLE_MS","messageCounter","verboseEncoder","throttledSendPatch","snapshotDecoder","_this","constructor","args","attachSocketHandlers","sendPatchImmediate","leading","trailing","onopen","console","debug","onmessage","event","MessageEvent","data","handleMessage","onclose","onerror","Event","disconnect","flush","cancel","readyState","OPEN","close","warn","sendClockSync","patchesWereSent","verbModel","encode","sendSyncMessage","time","rawMessage","message","fromJson","JSON","parse","handleResponse","handleResponseComplete","handleNotification","payload","getPayload","handlePatchPayload","handleSnapshotPayload","encodedPatch","patches","map","fromPatches","fork","applyBatch","err","snapshotUrl","decodedModel","fetchAndDecodeSnapshot","methodName","getMethodName","undefined","sendMessage","send","stringify","getJson","sendPatch","patch","api","hasOperationsToDispatch","ops","length","forEach","compactEncodedPatch","msg","getNext","clock","Promise","response","blob","buffer","arrayBuffer","decodedFromCbor","Uint8Array"],"sources":["../../../src/components/DataGrid/DataGridWebSocket.ts"],"sourcesContent":["import { GridModel } from '@/components/DataGrid/DataGridTypes'\nimport JsonRx from '@/components/DataGrid/utils/json-rx/JsonRx'\nimport JsonRxMessage from '@/components/DataGrid/utils/json-rx/JsonRxMessage'\nimport JsonRxNotification from '@/components/DataGrid/utils/json-rx/JsonRxNotification'\nimport JsonRxRequestComplete from '@/components/DataGrid/utils/json-rx/JsonRxRequestComplete'\nimport JsonRxResponse from '@/components/DataGrid/utils/json-rx/JsonRxResponse'\nimport JsonRxResponseComplete from '@/components/DataGrid/utils/json-rx/JsonRxResponseComplete'\nimport MessageCounter from '@/components/DataGrid/utils/MessageCounter'\nimport { splitPatch } from '@/components/DataGrid/utils/splitPatch'\nimport { Model } from 'json-joy/lib/json-crdt'\nimport {\n CompactCodecPatch,\n decode,\n} from 'json-joy/lib/json-crdt-patch/codec/compact'\nimport { Encoder as VerboseEncoder } from 'json-joy/lib/json-crdt/codec/structural/verbose/Encoder'\nimport { JsonCrdtVerboseLogicalTimestamp } from 'json-joy/lib/json-crdt/codec/structural/verbose/types'\nimport noop from 'lodash-es/noop'\nimport throttle from 'lodash-es/throttle'\nimport { type DebouncedFunc } from 'lodash-es'\nimport { Decoder as SnapshotDecoder } from 'json-joy/lib/json-crdt/codec/indexed/binary/Decoder'\nimport { decode as decodeCbor } from 'cbor2'\nimport type { IndexedFields } from 'json-joy/lib/json-crdt/codec/indexed/binary'\nimport { fetchWithExponentialTimeout } from '@sage-bionetworks/synapse-client'\n\nenum SynapseGridWebSocketMessagePayloadType {\n PATCH = 'patch',\n SNAPSHOT = 'snapshot',\n PATCHES = 'patches',\n}\n\ntype SynapseGridWebSocketMessagePayload =\n | {\n type: SynapseGridWebSocketMessagePayloadType.PATCH\n body: CompactCodecPatch\n }\n | {\n type: SynapseGridWebSocketMessagePayloadType.PATCHES\n body: CompactCodecPatch[]\n }\n | { type: SynapseGridWebSocketMessagePayloadType.SNAPSHOT; body: string }\n\ntype DataGridWebSocketConstructorArgs = {\n replicaId: number\n url: string\n onGridReady?: () => void\n onStatusChange?: (isOpen: boolean, instance: DataGridWebSocket) => void\n onModelCreate?: (model: GridModel) => void\n onReplicaConnected?: () => void\n onReplicaDisconnected?: () => void\n onSyncStart?: () => void\n onSyncEnd?: () => void\n onError?: (error: unknown) => void\n maxPayloadSizeBytes?: number\n socket?: WebSocket\n model?: GridModel | null\n patchThrottleMs?: number\n}\n\n// API Gateway WebSocket payload size limit is 32 KB per message\n// There is some overhead we aren't computing in our utility, namely the size of the patch header and the communication protocol itself\n// So add some buffer\nconst DEFAULT_MAX_PAYLOAD_SIZE_BYTES = 30 * 1024 // 30 KB\nconst DEFAULT_PATCH_THROTTLE_MS = 250\n\nexport class DataGridWebSocket {\n private socket: WebSocket\n private model: GridModel | null = null\n private messageCounter: MessageCounter\n private replicaId: number\n private verboseEncoder = new VerboseEncoder()\n private maxPayloadSizeBytes: number\n private throttledSendPatch: DebouncedFunc<() => void>\n private snapshotDecoder = new SnapshotDecoder()\n\n private onModelCreate: (model: GridModel) => void\n private onGridReady: () => void\n private onStatusChange: (isOpen: boolean, _this: DataGridWebSocket) => void\n private onReplicaConnected: () => void\n private onReplicaDisconnected: () => void\n private onSyncStart: () => void\n private onSyncEnd: () => void\n private onError: (error: unknown) => void\n\n constructor(args: DataGridWebSocketConstructorArgs) {\n const {\n replicaId,\n url,\n onGridReady,\n onStatusChange,\n onModelCreate,\n onReplicaConnected,\n onReplicaDisconnected,\n onSyncStart,\n onSyncEnd,\n onError,\n maxPayloadSizeBytes,\n socket,\n model,\n patchThrottleMs,\n } = args\n this.messageCounter = new MessageCounter()\n this.replicaId = replicaId\n this.maxPayloadSizeBytes =\n maxPayloadSizeBytes ?? DEFAULT_MAX_PAYLOAD_SIZE_BYTES\n this.socket = socket ?? new WebSocket(url)\n\n // Assign callbacks, falling back to no-ops\n this.onModelCreate = onModelCreate ?? noop\n this.onGridReady = onGridReady ?? noop\n this.onStatusChange = onStatusChange ?? noop\n this.onReplicaConnected = onReplicaConnected ?? noop\n this.onReplicaDisconnected = onReplicaDisconnected ?? noop\n this.onSyncStart = onSyncStart ?? noop\n this.onSyncEnd = onSyncEnd ?? noop\n this.onError = onError ?? noop\n\n // Restore existing model if provided\n if (model) {\n this.model = model\n }\n\n this.attachSocketHandlers()\n\n this.throttledSendPatch = throttle(\n () => this.sendPatchImmediate(),\n patchThrottleMs ?? DEFAULT_PATCH_THROTTLE_MS,\n { leading: false, trailing: true },\n )\n }\n\n private attachSocketHandlers() {\n this.socket.onopen = () => {\n console.debug('Connected to the WebSocket server')\n this.onStatusChange(true, this)\n }\n\n this.socket.onmessage = (event: MessageEvent) => {\n if (typeof event.data === 'string') {\n this.handleMessage(event.data)\n } else {\n console.error('Received non-string message data:', event.data)\n }\n }\n\n this.socket.onclose = () => {\n console.debug('Disconnected from the WebSocket server')\n this.onStatusChange(false, this)\n }\n\n this.socket.onerror = (error: Event) => {\n console.error('WebSocket error:', error)\n }\n }\n\n public disconnect() {\n this.throttledSendPatch.flush()\n this.throttledSendPatch.cancel()\n if (this.socket.readyState === WebSocket.OPEN) {\n this.socket.close()\n console.debug('WebSocket connection closed')\n } else {\n console.warn('WebSocket is not open. No action taken.')\n }\n }\n\n /**\n * Flushes the local model clock and sends the resulting patch (or a clock-sync\n * message) to the server so that both sides converge.\n */\n private sendClockSync() {\n if (!this.model) {\n console.error('Model is not initialized. Cannot sync model.')\n return\n }\n\n const patchesWereSent = this.sendPatchImmediate()\n if (!patchesWereSent) {\n // We've flushed all of our changes, so now we can receive changes from the server\n const verbModel = this.verboseEncoder.encode(this.model)\n this.sendSyncMessage(verbModel.time)\n }\n }\n\n private handleMessage(rawMessage: string) {\n const message = JsonRx.fromJson(JSON.parse(rawMessage))\n if (message instanceof JsonRxResponse) {\n this.handleResponse(\n message as JsonRxResponse<SynapseGridWebSocketMessagePayload>,\n )\n } else if (message instanceof JsonRxResponseComplete) {\n this.handleResponseComplete()\n } else if (message instanceof JsonRxNotification) {\n this.handleNotification(message)\n } else {\n console.warn('Unexpected WebSocket message format:', message)\n }\n }\n\n private handleResponse(\n message: JsonRxResponse<SynapseGridWebSocketMessagePayload>,\n ) {\n const payload = message.getPayload()\n\n switch (payload.type) {\n case SynapseGridWebSocketMessagePayloadType.PATCH:\n this.handlePatchPayload([payload.body])\n break\n\n case SynapseGridWebSocketMessagePayloadType.PATCHES:\n void this.handlePatchPayload(payload.body)\n break\n\n case SynapseGridWebSocketMessagePayloadType.SNAPSHOT:\n void this.handleSnapshotPayload(payload.body)\n break\n\n default:\n console.warn('Unknown payload type:', payload)\n break\n }\n }\n\n private handlePatchPayload(encodedPatch: CompactCodecPatch[]) {\n try {\n const patches = encodedPatch.map(decode)\n if (!this.model) {\n this.model = Model.fromPatches(patches).fork(\n this.replicaId,\n ) as unknown as GridModel\n this.onModelCreate(this.model)\n } else {\n this.model.applyBatch(patches)\n }\n this.sendClockSync()\n } catch (err) {\n console.error('Failed to apply patches or send clock:', err)\n }\n }\n\n private async handleSnapshotPayload(snapshotUrl: string) {\n console.debug('Received snapshot URL from server:', snapshotUrl)\n try {\n const decodedModel = await this.fetchAndDecodeSnapshot(snapshotUrl)\n this.model = decodedModel.fork(this.replicaId) as unknown as GridModel\n this.onModelCreate(this.model)\n this.sendClockSync()\n } catch (err) {\n console.error('Failed to fetch or decode snapshot', err)\n }\n }\n\n private handleResponseComplete() {\n // Clocks are in sync, no further action needed\n this.onGridReady()\n this.onSyncEnd()\n console.debug(\n 'Clocks synchronized with server. Incrementing sequence number.',\n )\n }\n\n private handleNotification(message: JsonRxNotification) {\n const methodName = message.getMethodName()\n console.debug('Notification received from server:', methodName)\n\n switch (methodName) {\n case 'ping':\n console.debug('Received ping from server')\n break\n\n case 'connected':\n console.debug('Server ready to receive patches')\n this.sendSyncMessage(\n this.model ? this.verboseEncoder.encode(this.model).time : undefined,\n )\n break\n\n case 'error':\n console.warn('Error from server:', message.getPayload())\n this.onError(message.getPayload())\n break\n\n case 'new-patch':\n if (!this.model) {\n console.warn(\n \"Model is not initialized. Cannot handle 'new-patch' message.\",\n )\n break\n }\n {\n const verbModel = this.verboseEncoder.encode(this.model)\n console.debug('New patch received, syncing data:', verbModel.time)\n this.sendSyncMessage(verbModel.time)\n }\n break\n\n case 'replica-connected':\n console.debug('A replica connected to the grid session')\n this.onReplicaConnected()\n break\n\n case 'replica-disconnected':\n console.debug('A replica disconnected from the grid session')\n this.onReplicaDisconnected()\n break\n\n default:\n console.warn('Unknown notification method:', methodName)\n break\n }\n }\n\n private sendMessage(message: JsonRxMessage) {\n if (this.socket.readyState === WebSocket.OPEN) {\n this.socket.send(JSON.stringify(message.getJson()))\n } else {\n console.error(\n 'WebSocket is not open. Unable to send message. Current state:',\n this.socket.readyState,\n )\n }\n }\n\n public sendPatch() {\n this.throttledSendPatch()\n }\n\n /**\n * @returns true if one or more patches were sent\n */\n private sendPatchImmediate(): boolean {\n if (!this.model) {\n console.warn('Model is not initialized. Cannot send patch.')\n return false\n }\n\n const patch = this.model.api.flush()\n const hasOperationsToDispatch = patch.ops.length > 0\n\n if (hasOperationsToDispatch) {\n // Split the patch if it exceeds the maximum size we can send in a single frame\n const patches = splitPatch(patch, this.maxPayloadSizeBytes)\n patches.forEach(compactEncodedPatch => {\n console.debug('Sending patch to server:', compactEncodedPatch)\n const msg = new JsonRxRequestComplete(\n this.messageCounter.getNext(),\n 'patch',\n compactEncodedPatch,\n )\n this.sendMessage(msg)\n })\n }\n\n return hasOperationsToDispatch\n }\n\n private sendSyncMessage(clock?: number | JsonCrdtVerboseLogicalTimestamp[]) {\n const message = new JsonRxRequestComplete(\n this.messageCounter.getNext(),\n 'synchronize-clock',\n clock ?? [],\n )\n this.onSyncStart()\n this.sendMessage(message)\n }\n\n private async fetchAndDecodeSnapshot(\n snapshotUrl: string,\n ): Promise<GridModel> {\n const response = await fetchWithExponentialTimeout(snapshotUrl)\n const blob = await response.blob()\n const buffer = await blob.arrayBuffer()\n const decodedFromCbor = decodeCbor(new Uint8Array(buffer))\n const decodedModel = this.snapshotDecoder.decode(\n decodedFromCbor as IndexedFields,\n ) as unknown as GridModel\n return decodedModel\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"DataGridWebSocket.js","names":["GridModel","JsonRx","JsonRxMessage","JsonRxNotification","JsonRxRequestComplete","JsonRxResponse","JsonRxResponseComplete","MessageCounter","splitPatch","Model","CompactCodecPatch","decode","Encoder","VerboseEncoder","JsonCrdtVerboseLogicalTimestamp","noop","throttle","DebouncedFunc","Decoder","SnapshotDecoder","decodeCbor","IndexedFields","fetchWithExponentialTimeout","SynapseGridWebSocketMessagePayloadType","PATCH","SNAPSHOT","PATCHES","SynapseGridWebSocketMessagePayload","type","body","DataGridWebSocketConstructorArgs","replicaId","url","onGridReady","onStatusChange","isOpen","instance","DataGridWebSocket","onModelCreate","model","onReplicaConnected","onReplicaDisconnected","onSyncStart","onSyncEnd","onError","error","maxPayloadSizeBytes","socket","WebSocket","patchThrottleMs","pendingPatches","patchAckTimeoutMs","DEFAULT_MAX_PAYLOAD_SIZE_BYTES","DEFAULT_PATCH_THROTTLE_MS","DEFAULT_PATCH_ACK_TIMEOUT_MS","messageCounter","verboseEncoder","throttledSendPatch","snapshotDecoder","unacknowledgedPatches","inFlightPatchRequestId","patchAckTimer","isClosing","isSyncExchangeOpen","_this","constructor","args","attachSocketHandlers","sendPatchImmediate","leading","trailing","onopen","console","debug","onmessage","event","MessageEvent","data","handleMessage","onclose","stopWaitingForPatchAck","cancel","onerror","Event","disconnect","readyState","OPEN","warn","flush","length","closeSocket","close","getPendingPatches","sendClockSync","patchesWereSent","verbModel","encode","sendSyncMessage","time","rawMessage","message","fromJson","JSON","parse","handleResponse","handleResponseComplete","handleNotification","payload","getPayload","handlePatchPayload","handleSnapshotPayload","encodedPatch","patches","map","fromPatches","fork","applyBatch","err","snapshotUrl","decodedModel","fetchAndDecodeSnapshot","getSubscriptionId","handlePatchAcknowledged","shift","sendNextPatch","methodName","getMethodName","undefined","sendMessage","send","stringify","getJson","sendPatch","patch","api","hasOperationsToDispatch","ops","push","nextPatch","requestId","getNext","window","setTimeout","handlePatchAckTimeout","clearTimeout","clock","Promise","response","blob","buffer","arrayBuffer","decodedFromCbor","Uint8Array"],"sources":["../../../src/components/DataGrid/DataGridWebSocket.ts"],"sourcesContent":["import { GridModel } from '@/components/DataGrid/DataGridTypes'\nimport JsonRx from '@/components/DataGrid/utils/json-rx/JsonRx'\nimport JsonRxMessage from '@/components/DataGrid/utils/json-rx/JsonRxMessage'\nimport JsonRxNotification from '@/components/DataGrid/utils/json-rx/JsonRxNotification'\nimport JsonRxRequestComplete from '@/components/DataGrid/utils/json-rx/JsonRxRequestComplete'\nimport JsonRxResponse from '@/components/DataGrid/utils/json-rx/JsonRxResponse'\nimport JsonRxResponseComplete from '@/components/DataGrid/utils/json-rx/JsonRxResponseComplete'\nimport MessageCounter from '@/components/DataGrid/utils/MessageCounter'\nimport { splitPatch } from '@/components/DataGrid/utils/splitPatch'\nimport { Model } from 'json-joy/lib/json-crdt'\nimport {\n CompactCodecPatch,\n decode,\n} from 'json-joy/lib/json-crdt-patch/codec/compact'\nimport { Encoder as VerboseEncoder } from 'json-joy/lib/json-crdt/codec/structural/verbose/Encoder'\nimport { JsonCrdtVerboseLogicalTimestamp } from 'json-joy/lib/json-crdt/codec/structural/verbose/types'\nimport noop from 'lodash-es/noop'\nimport throttle from 'lodash-es/throttle'\nimport { type DebouncedFunc } from 'lodash-es'\nimport { Decoder as SnapshotDecoder } from 'json-joy/lib/json-crdt/codec/indexed/binary/Decoder'\nimport { decode as decodeCbor } from 'cbor2'\nimport type { IndexedFields } from 'json-joy/lib/json-crdt/codec/indexed/binary'\nimport { fetchWithExponentialTimeout } from '@sage-bionetworks/synapse-client'\n\nenum SynapseGridWebSocketMessagePayloadType {\n PATCH = 'patch',\n SNAPSHOT = 'snapshot',\n PATCHES = 'patches',\n}\n\ntype SynapseGridWebSocketMessagePayload =\n | {\n type: SynapseGridWebSocketMessagePayloadType.PATCH\n body: CompactCodecPatch\n }\n | {\n type: SynapseGridWebSocketMessagePayloadType.PATCHES\n body: CompactCodecPatch[]\n }\n | { type: SynapseGridWebSocketMessagePayloadType.SNAPSHOT; body: string }\n\ntype DataGridWebSocketConstructorArgs = {\n replicaId: number\n url: string\n onGridReady?: () => void\n onStatusChange?: (isOpen: boolean, instance: DataGridWebSocket) => void\n onModelCreate?: (model: GridModel) => void\n onReplicaConnected?: () => void\n onReplicaDisconnected?: () => void\n onSyncStart?: () => void\n onSyncEnd?: () => void\n onError?: (error: unknown) => void\n maxPayloadSizeBytes?: number\n socket?: WebSocket\n model?: GridModel | null\n patchThrottleMs?: number\n /** Patches the previous connection never saw acknowledged, resent in order ahead of new ones */\n pendingPatches?: CompactCodecPatch[]\n patchAckTimeoutMs?: number\n}\n\n// API Gateway WebSocket payload size limit is 32 KB per message\n// There is some overhead we aren't computing in our utility, namely the size of the patch header and the communication protocol itself\n// So add some buffer\nconst DEFAULT_MAX_PAYLOAD_SIZE_BYTES = 30 * 1024 // 30 KB\nconst DEFAULT_PATCH_THROTTLE_MS = 250\n// A patch is acknowledged only after the server has stored it, so a missing acknowledgement means the connection is unusable\nconst DEFAULT_PATCH_ACK_TIMEOUT_MS = 15 * 1000\n\nexport class DataGridWebSocket {\n private socket: WebSocket\n private model: GridModel | null = null\n private messageCounter: MessageCounter\n private replicaId: number\n private verboseEncoder = new VerboseEncoder()\n private maxPayloadSizeBytes: number\n private throttledSendPatch: DebouncedFunc<() => void>\n private snapshotDecoder = new SnapshotDecoder()\n // Oldest first. The server must receive patches in order, so only the head is ever on the wire\n // (identified by inFlightPatchRequestId); the rest wait for its acknowledgement.\n private unacknowledgedPatches: CompactCodecPatch[]\n private inFlightPatchRequestId: number | null = null\n private patchAckTimeoutMs: number\n private patchAckTimer: number | null = null\n // Set once disconnect() has been requested: the socket closes when the last patch is acknowledged\n private isClosing = false\n private isSyncExchangeOpen = false\n\n private onModelCreate: (model: GridModel) => void\n private onGridReady: () => void\n private onStatusChange: (isOpen: boolean, _this: DataGridWebSocket) => void\n private onReplicaConnected: () => void\n private onReplicaDisconnected: () => void\n private onSyncStart: () => void\n private onSyncEnd: () => void\n private onError: (error: unknown) => void\n\n constructor(args: DataGridWebSocketConstructorArgs) {\n const {\n replicaId,\n url,\n onGridReady,\n onStatusChange,\n onModelCreate,\n onReplicaConnected,\n onReplicaDisconnected,\n onSyncStart,\n onSyncEnd,\n onError,\n maxPayloadSizeBytes,\n socket,\n model,\n patchThrottleMs,\n pendingPatches,\n patchAckTimeoutMs,\n } = args\n this.messageCounter = new MessageCounter()\n this.replicaId = replicaId\n this.maxPayloadSizeBytes =\n maxPayloadSizeBytes ?? DEFAULT_MAX_PAYLOAD_SIZE_BYTES\n this.socket = socket ?? new WebSocket(url)\n this.unacknowledgedPatches = [...(pendingPatches ?? [])]\n this.patchAckTimeoutMs = patchAckTimeoutMs ?? DEFAULT_PATCH_ACK_TIMEOUT_MS\n\n // Assign callbacks, falling back to no-ops\n this.onModelCreate = onModelCreate ?? noop\n this.onGridReady = onGridReady ?? noop\n this.onStatusChange = onStatusChange ?? noop\n this.onReplicaConnected = onReplicaConnected ?? noop\n this.onReplicaDisconnected = onReplicaDisconnected ?? noop\n this.onSyncStart = onSyncStart ?? noop\n this.onSyncEnd = onSyncEnd ?? noop\n this.onError = onError ?? noop\n\n // Restore existing model if provided\n if (model) {\n this.model = model\n }\n\n this.attachSocketHandlers()\n\n this.throttledSendPatch = throttle(\n () => this.sendPatchImmediate(),\n patchThrottleMs ?? DEFAULT_PATCH_THROTTLE_MS,\n { leading: false, trailing: true },\n )\n }\n\n private attachSocketHandlers() {\n this.socket.onopen = () => {\n console.debug('Connected to the WebSocket server')\n this.onStatusChange(true, this)\n }\n\n this.socket.onmessage = (event: MessageEvent) => {\n if (typeof event.data === 'string') {\n this.handleMessage(event.data)\n } else {\n console.error('Received non-string message data:', event.data)\n }\n }\n\n this.socket.onclose = () => {\n console.debug('Disconnected from the WebSocket server')\n this.stopWaitingForPatchAck()\n // Edits not yet flushed stay in the model for the replacement connection to send\n this.throttledSendPatch.cancel()\n this.onStatusChange(false, this)\n }\n\n this.socket.onerror = (error: Event) => {\n console.error('WebSocket error:', error)\n }\n }\n\n /**\n * Closes the connection once every unacknowledged patch has been acknowledged, so edits made\n * just before leaving are not lost. The owner has moved on, so no further callbacks fire.\n */\n public disconnect() {\n if (this.socket.readyState !== WebSocket.OPEN) {\n // Edits that were never flushed stay in the model for the next connection to send\n this.throttledSendPatch.cancel()\n console.warn('WebSocket is not open. No action taken.')\n return\n }\n\n this.throttledSendPatch.flush()\n this.throttledSendPatch.cancel()\n this.isClosing = true\n this.onModelCreate = noop\n this.onGridReady = noop\n this.onStatusChange = noop\n this.onReplicaConnected = noop\n this.onReplicaDisconnected = noop\n this.onSyncStart = noop\n this.onSyncEnd = noop\n this.onError = noop\n if (this.unacknowledgedPatches.length === 0) {\n this.closeSocket()\n }\n }\n\n private closeSocket() {\n this.socket.close()\n console.debug('WebSocket connection closed')\n }\n\n /**\n * @returns the patches the server has not acknowledged, oldest first. A replacement connection\n * created with these as `pendingPatches` resends them in order.\n */\n public getPendingPatches(): CompactCodecPatch[] {\n return [...this.unacknowledgedPatches]\n }\n\n /**\n * Flushes the local model clock and sends the resulting patch (or a clock-sync\n * message) to the server so that both sides converge.\n */\n private sendClockSync() {\n if (!this.model) {\n console.error('Model is not initialized. Cannot sync model.')\n return\n }\n\n const patchesWereSent = this.sendPatchImmediate()\n if (!patchesWereSent) {\n // We've flushed all of our changes, so now we can receive changes from the server\n const verbModel = this.verboseEncoder.encode(this.model)\n this.sendSyncMessage(verbModel.time)\n }\n }\n\n private handleMessage(rawMessage: string) {\n const message = JsonRx.fromJson(JSON.parse(rawMessage))\n if (this.isClosing && !(message instanceof JsonRxResponseComplete)) {\n return\n }\n if (message instanceof JsonRxResponse) {\n this.handleResponse(\n message as JsonRxResponse<SynapseGridWebSocketMessagePayload>,\n )\n } else if (message instanceof JsonRxResponseComplete) {\n this.handleResponseComplete(message)\n } else if (message instanceof JsonRxNotification) {\n this.handleNotification(message)\n } else {\n console.warn('Unexpected WebSocket message format:', message)\n }\n }\n\n private handleResponse(\n message: JsonRxResponse<SynapseGridWebSocketMessagePayload>,\n ) {\n const payload = message.getPayload()\n\n switch (payload.type) {\n case SynapseGridWebSocketMessagePayloadType.PATCH:\n this.handlePatchPayload([payload.body])\n break\n\n case SynapseGridWebSocketMessagePayloadType.PATCHES:\n void this.handlePatchPayload(payload.body)\n break\n\n case SynapseGridWebSocketMessagePayloadType.SNAPSHOT:\n void this.handleSnapshotPayload(payload.body)\n break\n\n default:\n console.warn('Unknown payload type:', payload)\n break\n }\n }\n\n private handlePatchPayload(encodedPatch: CompactCodecPatch[]) {\n try {\n const patches = encodedPatch.map(decode)\n if (!this.model) {\n this.model = Model.fromPatches(patches).fork(\n this.replicaId,\n ) as unknown as GridModel\n this.onModelCreate(this.model)\n } else {\n this.model.applyBatch(patches)\n }\n this.sendClockSync()\n } catch (err) {\n console.error('Failed to apply patches or send clock:', err)\n }\n }\n\n private async handleSnapshotPayload(snapshotUrl: string) {\n console.debug('Received snapshot URL from server:', snapshotUrl)\n try {\n const decodedModel = await this.fetchAndDecodeSnapshot(snapshotUrl)\n this.model = decodedModel.fork(this.replicaId) as unknown as GridModel\n this.onModelCreate(this.model)\n this.sendClockSync()\n } catch (err) {\n console.error('Failed to fetch or decode snapshot', err)\n }\n }\n\n private handleResponseComplete(message: JsonRxResponseComplete) {\n if (message.getSubscriptionId() === this.inFlightPatchRequestId) {\n this.handlePatchAcknowledged()\n return\n }\n this.isSyncExchangeOpen = false\n // Clocks are in sync, no further action needed\n this.onGridReady()\n this.onSyncEnd()\n console.debug(\n 'Clocks synchronized with server. Incrementing sequence number.',\n )\n }\n\n private handlePatchAcknowledged() {\n this.unacknowledgedPatches.shift()\n this.stopWaitingForPatchAck()\n if (this.unacknowledgedPatches.length > 0) {\n this.sendNextPatch()\n } else if (this.isClosing) {\n this.closeSocket()\n } else if (this.isSyncExchangeOpen && this.model) {\n // The sync was answered with local patches instead of a clock. Now that they are stored,\n // confirm the clock so the server can complete the exchange.\n this.sendSyncMessage(this.verboseEncoder.encode(this.model).time)\n }\n }\n\n private handleNotification(message: JsonRxNotification) {\n const methodName = message.getMethodName()\n console.debug('Notification received from server:', methodName)\n\n switch (methodName) {\n case 'ping':\n console.debug('Received ping from server')\n break\n\n case 'connected':\n console.debug('Server ready to receive patches')\n this.sendSyncMessage(\n this.model ? this.verboseEncoder.encode(this.model).time : undefined,\n )\n // Resend patches an earlier connection never saw acknowledged\n this.sendNextPatch()\n break\n\n case 'error':\n console.warn('Error from server:', message.getPayload())\n this.onError(message.getPayload())\n break\n\n case 'new-patch':\n if (!this.model) {\n console.warn(\n \"Model is not initialized. Cannot handle 'new-patch' message.\",\n )\n break\n }\n {\n const verbModel = this.verboseEncoder.encode(this.model)\n console.debug('New patch received, syncing data:', verbModel.time)\n this.sendSyncMessage(verbModel.time)\n }\n break\n\n case 'replica-connected':\n console.debug('A replica connected to the grid session')\n this.onReplicaConnected()\n break\n\n case 'replica-disconnected':\n console.debug('A replica disconnected from the grid session')\n this.onReplicaDisconnected()\n break\n\n default:\n console.warn('Unknown notification method:', methodName)\n break\n }\n }\n\n private sendMessage(message: JsonRxMessage) {\n if (this.socket.readyState === WebSocket.OPEN) {\n this.socket.send(JSON.stringify(message.getJson()))\n } else {\n console.error(\n 'WebSocket is not open. Unable to send message. Current state:',\n this.socket.readyState,\n )\n }\n }\n\n public sendPatch() {\n this.throttledSendPatch()\n }\n\n /**\n * @returns true if the model had local changes, which are now queued to be sent\n */\n private sendPatchImmediate(): boolean {\n if (!this.model) {\n console.warn('Model is not initialized. Cannot send patch.')\n return false\n }\n\n const patch = this.model.api.flush()\n const hasOperationsToDispatch = patch.ops.length > 0\n\n if (hasOperationsToDispatch) {\n // Split the patch if it exceeds the maximum size we can send in a single frame\n this.unacknowledgedPatches.push(\n ...splitPatch(patch, this.maxPayloadSizeBytes),\n )\n this.sendNextPatch()\n }\n\n return hasOperationsToDispatch\n }\n\n private sendNextPatch() {\n const nextPatch = this.unacknowledgedPatches[0]\n if (\n nextPatch === undefined ||\n this.inFlightPatchRequestId !== null ||\n this.socket.readyState !== WebSocket.OPEN\n ) {\n return\n }\n console.debug('Sending patch to server:', nextPatch)\n const requestId = this.messageCounter.getNext()\n this.inFlightPatchRequestId = requestId\n this.patchAckTimer = window.setTimeout(\n () => this.handlePatchAckTimeout(),\n this.patchAckTimeoutMs,\n )\n this.sendMessage(new JsonRxRequestComplete(requestId, 'patch', nextPatch))\n }\n\n private stopWaitingForPatchAck() {\n if (this.patchAckTimer !== null) {\n window.clearTimeout(this.patchAckTimer)\n this.patchAckTimer = null\n }\n this.inFlightPatchRequestId = null\n }\n\n /**\n * Resending on the same connection could reorder patches, so the connection is dropped and\n * the owner reconnects with getPendingPatches(). The server ignores patches it already stored.\n */\n private handlePatchAckTimeout() {\n console.warn(\n 'Timed out waiting for a patch acknowledgement. Dropping the connection so unacknowledged patches are resent.',\n )\n // Detach handlers so late events from the abandoned socket can't interleave with its replacement\n this.socket.onopen = null\n this.socket.onmessage = null\n this.socket.onclose = null\n this.socket.onerror = null\n this.throttledSendPatch.cancel()\n this.stopWaitingForPatchAck()\n this.socket.close()\n this.onStatusChange(false, this)\n }\n\n private sendSyncMessage(clock?: number | JsonCrdtVerboseLogicalTimestamp[]) {\n const message = new JsonRxRequestComplete(\n this.messageCounter.getNext(),\n 'synchronize-clock',\n clock ?? [],\n )\n this.isSyncExchangeOpen = true\n this.onSyncStart()\n this.sendMessage(message)\n }\n\n private async fetchAndDecodeSnapshot(\n snapshotUrl: string,\n ): Promise<GridModel> {\n const response = await fetchWithExponentialTimeout(snapshotUrl)\n const blob = await response.blob()\n const buffer = await blob.arrayBuffer()\n const decodedFromCbor = decodeCbor(new Uint8Array(buffer))\n const decodedModel = this.snapshotDecoder.decode(\n decodedFromCbor as IndexedFields,\n ) as unknown as GridModel\n return decodedModel\n }\n}\n"],"mappings":"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"}
@@ -4,11 +4,11 @@ export type GridLoadingStateProps = {
4
4
  isConnected: boolean;
5
5
  };
6
6
  export declare const GRID_LOADING_MESSAGES: {
7
- readonly heading: "Setting up grid";
7
+ readonly heading: "Preparing your grid";
8
8
  readonly awaitingReplica: "Setting up real-time sync…";
9
9
  readonly awaitingPresignedUrl: "Establishing secure connection…";
10
10
  readonly awaitingConnection: "Connecting to server…";
11
- readonly awaitingData: "Loading table data…";
11
+ readonly awaitingData: "Loading metadata and validation results. Large datasets may take up to 5 minutes to load. Please keep this page open.";
12
12
  };
13
13
  /**
14
14
  * Describes how far along the grid is in establishing its first connection.
@@ -1 +1 @@
1
- {"version":3,"file":"GridLoadingState.d.ts","sourceRoot":"","sources":["../../../../src/components/DataGrid/components/GridLoadingState.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,EAAE,OAAO,CAAA;IACrB,eAAe,EAAE,OAAO,CAAA;IACxB,WAAW,EAAE,OAAO,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,qBAAqB;;;;;;CAMxB,CAAA;AAEV;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,YAAY,EACZ,eAAe,EACf,WAAW,GACZ,EAAE,qBAAqB,GAAG,MAAM,CAWhC;AAED;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,2CAepE"}
1
+ {"version":3,"file":"GridLoadingState.d.ts","sourceRoot":"","sources":["../../../../src/components/DataGrid/components/GridLoadingState.tsx"],"names":[],"mappings":"AAIA,MAAM,MAAM,qBAAqB,GAAG;IAClC,YAAY,EAAE,OAAO,CAAA;IACrB,eAAe,EAAE,OAAO,CAAA;IACxB,WAAW,EAAE,OAAO,CAAA;CACrB,CAAA;AAED,eAAO,MAAM,qBAAqB;;;;;;CAOxB,CAAA;AAEV;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,YAAY,EACZ,eAAe,EACf,WAAW,GACZ,EAAE,qBAAqB,GAAG,MAAM,CAWhC;AAED;;;;GAIG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,2CAepE"}
@@ -5,11 +5,11 @@ import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
5
  import { c as o } from "react/compiler-runtime";
6
6
  //#region src/components/DataGrid/components/GridLoadingState.tsx
7
7
  var s = {
8
- heading: "Setting up grid",
8
+ heading: "Preparing your grid",
9
9
  awaitingReplica: "Setting up real-time sync…",
10
10
  awaitingPresignedUrl: "Establishing secure connection…",
11
11
  awaitingConnection: "Connecting to server…",
12
- awaitingData: "Loading table data…"
12
+ awaitingData: "Loading metadata and validation results. Large datasets may take up to 5 minutes to load. Please keep this page open."
13
13
  };
14
14
  function c({ hasReplicaId: e, hasPresignedUrl: t, isConnected: n }) {
15
15
  return e ? t ? n ? s.awaitingData : s.awaitingConnection : s.awaitingPresignedUrl : s.awaitingReplica;
@@ -1 +1 @@
1
- {"version":3,"file":"GridLoadingState.js","names":["SkeletonTable","Stack","Typography","SynapseSpinner","GridLoadingStateProps","hasReplicaId","hasPresignedUrl","isConnected","GRID_LOADING_MESSAGES","heading","awaitingReplica","awaitingPresignedUrl","awaitingConnection","awaitingData","const","getGridLoadingMessage","GridLoadingState","props","$","_c","t0","t1","Symbol","for","mb","t2","t3","t4","t5","t6"],"sources":["../../../../src/components/DataGrid/components/GridLoadingState.tsx"],"sourcesContent":["import { SkeletonTable } from '@/components/Skeleton/SkeletonTable'\nimport { Stack, Typography } from '@mui/material'\nimport { SynapseSpinner } from '../../LoadingScreen/LoadingScreen'\n\nexport type GridLoadingStateProps = {\n hasReplicaId: boolean\n hasPresignedUrl: boolean\n isConnected: boolean\n}\n\nexport const GRID_LOADING_MESSAGES = {\n heading: 'Setting up grid',\n awaitingReplica: 'Setting up real-time sync…',\n awaitingPresignedUrl: 'Establishing secure connection…',\n awaitingConnection: 'Connecting to server…',\n awaitingData: 'Loading table data…',\n} as const\n\n/**\n * Describes how far along the grid is in establishing its first connection.\n */\nexport function getGridLoadingMessage({\n hasReplicaId,\n hasPresignedUrl,\n isConnected,\n}: GridLoadingStateProps): string {\n if (!hasReplicaId) {\n return GRID_LOADING_MESSAGES.awaitingReplica\n }\n if (!hasPresignedUrl) {\n return GRID_LOADING_MESSAGES.awaitingPresignedUrl\n }\n if (!isConnected) {\n return GRID_LOADING_MESSAGES.awaitingConnection\n }\n return GRID_LOADING_MESSAGES.awaitingData\n}\n\n/**\n * Placeholder shown in place of the grid until its first connection has finished\n * loading data. Rendering this instead of the grid keeps users from editing cells\n * or watching rows stream in while the initial data is still being replayed.\n */\nexport default function GridLoadingState(props: GridLoadingStateProps) {\n return (\n <Stack spacing={1} aria-busy=\"true\" sx={{ mb: 1.25 }}>\n <Typography variant=\"sectionTitle\" component=\"h2\">\n {GRID_LOADING_MESSAGES.heading}\n </Typography>\n <Stack direction=\"row\" spacing={1} role=\"status\" alignItems=\"center\">\n <SynapseSpinner size={16} margin=\"0\" />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {getGridLoadingMessage(props)}\n </Typography>\n </Stack>\n <SkeletonTable aria-hidden numRows={4} numCols={1} />\n </Stack>\n )\n}\n"],"mappings":";;;;;;AAUA,IAAaQ,IAAwB;CACnCC,SAAS;CACTC,iBAAiB;CACjBC,sBAAsB;CACtBC,oBAAoB;CACpBC,cAAc;AAChB;AAKA,SAAgBE,EAAsB,EACpCV,iBACAC,oBACAC,kBACgC;CAUhC,OATKF,IAGAC,IAGAC,IAGEC,EAAsBK,eAFpBL,EAAsBI,qBAHtBJ,EAAsBG,uBAHtBH,EAAsBE;AASjC;AAOA,SAAeM,EAAAC,GAAA;CAAA,IAAAC,IAAAC,EAAA,EAAA,GAAAC,GAAAC;CAAA,AAAAH,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KAE6BH,IAAA,EAAAI,IAAM,KAAK,GACjDH,IAAA,kBAAC,GAAD;EAAoB,SAAA;EAAyB,WAAA;YAC1Cb,EAAqBC;CADb,CAAA,GAEES,EAAA,KAAAE,GAAAF,EAAA,KAAAG,MAAAD,IAAAF,EAAA,IAAAG,IAAAH,EAAA;CAAA,IAAAO;CAAA,AAAAP,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KAEXE,IAAA,kBAAC,GAAD;EAAsB,MAAA;EAAW,QAAA;CAAG,CAAA,GAAGP,EAAA,KAAAO,KAAAA,IAAAP,EAAA;CAAA,IAAAQ;CAAA,AAAAR,EAAA,OAAAD,IAERS,IAAAR,EAAA,MAA5BQ,IAAAX,EAAsBE,CAAK,GAACC,EAAA,KAAAD,GAAAC,EAAA,KAAAQ;CAAA,IAAAC;CAAA,AAAAT,EAAA,OAAAQ,IAEzBC,IAAAT,EAAA,MALRS,IAAA,kBAAC,GAAD;EAAiB,WAAA;EAAe,SAAA;EAAQ,MAAA;EAAoB,YAAA;YAA5D,CACEF,GACA,kBAAC,GAAD;GAAoB,SAAA;GAAgB,OAAA;aACjCC;EADQ,CAAA,CAFP;KAKER,EAAA,KAAAQ,GAAAR,EAAA,KAAAS;CAAA,IAAAC;CAAA,AAAAV,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KACRK,IAAA,kBAAC,GAAD;EAAe,eAAA;EAAqB,SAAA;EAAY,SAAA;CAAC,CAAA,GAAIV,EAAA,KAAAU,KAAAA,IAAAV,EAAA;CAAA,IAAAW;CAC/C,OAD+CX,EAAA,OAAAS,IAC/CE,IAAAX,EAAA,MAXRW,IAAA,kBAAC,GAAD;EAAgB,SAAA;EAAa,aAAA;EAAW,IAAAT;YAAxC;GACEC;GAGAM;GAMAC;EAVI;KAWEV,EAAA,KAAAS,GAAAT,EAAA,KAAAW,IAXRA;AAWQ"}
1
+ {"version":3,"file":"GridLoadingState.js","names":["SkeletonTable","Stack","Typography","SynapseSpinner","GridLoadingStateProps","hasReplicaId","hasPresignedUrl","isConnected","GRID_LOADING_MESSAGES","heading","awaitingReplica","awaitingPresignedUrl","awaitingConnection","awaitingData","const","getGridLoadingMessage","GridLoadingState","props","$","_c","t0","t1","Symbol","for","mb","t2","t3","t4","t5","t6"],"sources":["../../../../src/components/DataGrid/components/GridLoadingState.tsx"],"sourcesContent":["import { SkeletonTable } from '@/components/Skeleton/SkeletonTable'\nimport { Stack, Typography } from '@mui/material'\nimport { SynapseSpinner } from '../../LoadingScreen/LoadingScreen'\n\nexport type GridLoadingStateProps = {\n hasReplicaId: boolean\n hasPresignedUrl: boolean\n isConnected: boolean\n}\n\nexport const GRID_LOADING_MESSAGES = {\n heading: 'Preparing your grid',\n awaitingReplica: 'Setting up real-time sync…',\n awaitingPresignedUrl: 'Establishing secure connection…',\n awaitingConnection: 'Connecting to server…',\n awaitingData:\n 'Loading metadata and validation results. Large datasets may take up to 5 minutes to load. Please keep this page open.',\n} as const\n\n/**\n * Describes how far along the grid is in establishing its first connection.\n */\nexport function getGridLoadingMessage({\n hasReplicaId,\n hasPresignedUrl,\n isConnected,\n}: GridLoadingStateProps): string {\n if (!hasReplicaId) {\n return GRID_LOADING_MESSAGES.awaitingReplica\n }\n if (!hasPresignedUrl) {\n return GRID_LOADING_MESSAGES.awaitingPresignedUrl\n }\n if (!isConnected) {\n return GRID_LOADING_MESSAGES.awaitingConnection\n }\n return GRID_LOADING_MESSAGES.awaitingData\n}\n\n/**\n * Placeholder shown in place of the grid until its first connection has finished\n * loading data. Rendering this instead of the grid keeps users from editing cells\n * or watching rows stream in while the initial data is still being replayed.\n */\nexport default function GridLoadingState(props: GridLoadingStateProps) {\n return (\n <Stack spacing={1} aria-busy=\"true\" sx={{ mb: 1.25 }}>\n <Typography variant=\"sectionTitle\" component=\"h2\">\n {GRID_LOADING_MESSAGES.heading}\n </Typography>\n <Stack direction=\"row\" spacing={1} role=\"status\" alignItems=\"center\">\n <SynapseSpinner size={16} margin=\"0\" />\n <Typography variant=\"caption\" color=\"text.secondary\">\n {getGridLoadingMessage(props)}\n </Typography>\n </Stack>\n <SkeletonTable aria-hidden numRows={4} numCols={1} />\n </Stack>\n )\n}\n"],"mappings":";;;;;;AAUA,IAAaQ,IAAwB;CACnCC,SAAS;CACTC,iBAAiB;CACjBC,sBAAsB;CACtBC,oBAAoB;CACpBC,cACE;AACJ;AAKA,SAAgBE,EAAsB,EACpCV,iBACAC,oBACAC,kBACgC;CAUhC,OATKF,IAGAC,IAGAC,IAGEC,EAAsBK,eAFpBL,EAAsBI,qBAHtBJ,EAAsBG,uBAHtBH,EAAsBE;AASjC;AAOA,SAAeM,EAAAC,GAAA;CAAA,IAAAC,IAAAC,EAAA,EAAA,GAAAC,GAAAC;CAAA,AAAAH,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KAE6BH,IAAA,EAAAI,IAAM,KAAK,GACjDH,IAAA,kBAAC,GAAD;EAAoB,SAAA;EAAyB,WAAA;YAC1Cb,EAAqBC;CADb,CAAA,GAEES,EAAA,KAAAE,GAAAF,EAAA,KAAAG,MAAAD,IAAAF,EAAA,IAAAG,IAAAH,EAAA;CAAA,IAAAO;CAAA,AAAAP,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KAEXE,IAAA,kBAAC,GAAD;EAAsB,MAAA;EAAW,QAAA;CAAG,CAAA,GAAGP,EAAA,KAAAO,KAAAA,IAAAP,EAAA;CAAA,IAAAQ;CAAA,AAAAR,EAAA,OAAAD,IAERS,IAAAR,EAAA,MAA5BQ,IAAAX,EAAsBE,CAAK,GAACC,EAAA,KAAAD,GAAAC,EAAA,KAAAQ;CAAA,IAAAC;CAAA,AAAAT,EAAA,OAAAQ,IAEzBC,IAAAT,EAAA,MALRS,IAAA,kBAAC,GAAD;EAAiB,WAAA;EAAe,SAAA;EAAQ,MAAA;EAAoB,YAAA;YAA5D,CACEF,GACA,kBAAC,GAAD;GAAoB,SAAA;GAAgB,OAAA;aACjCC;EADQ,CAAA,CAFP;KAKER,EAAA,KAAAQ,GAAAR,EAAA,KAAAS;CAAA,IAAAC;CAAA,AAAAV,EAAA,OAAAI,OAAAC,IAAA,2BAAA,KACRK,IAAA,kBAAC,GAAD;EAAe,eAAA;EAAqB,SAAA;EAAY,SAAA;CAAC,CAAA,GAAIV,EAAA,KAAAU,KAAAA,IAAAV,EAAA;CAAA,IAAAW;CAC/C,OAD+CX,EAAA,OAAAS,IAC/CE,IAAAX,EAAA,MAXRW,IAAA,kBAAC,GAAD;EAAgB,SAAA;EAAa,aAAA;EAAW,IAAAT;YAAxC;GACEC;GAGAM;GAMAC;EAVI;KAWEV,EAAA,KAAAS,GAAAT,EAAA,KAAAW,IAXRA;AAWQ"}
@@ -1 +1 @@
1
- {"version":3,"file":"useDataGridWebsocket.d.ts","sourceRoot":"","sources":["../../../src/components/DataGrid/useDataGridWebsocket.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,iBAAiB,EAClB,MAAM,qCAAqC,CAAA;AAI5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAKvD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;IACvB;;;;;OAKG;IACH,uBAAuB,EAAE,OAAO,CAAA;IAChC;;;;;OAKG;IACH,uBAAuB,EAAE,OAAO,CAAA;IAChC;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,OAAO,CAAA;IACpB,YAAY,EAAE,OAAO,CAAA;IACrB,gBAAgB,EAAE;QAChB,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,EAAE,MAAM,CAAA;KAClB,GAAG,IAAI,CAAA;IACR,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAC3C,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,eAAe,EAAE,OAAO,CAAA;IACxB,cAAc,EAAE,OAAO,CAAA;CACxB;AAGD,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,mBAAmB,CAAA;IACzB,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;CACrE,GACD;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,uBAAuB,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,SAAS,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAA;AAGjD,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,eAAe,GACtB,cAAc,CAyGhB;AAED,eAAO,MAAM,qBAAqB,EAAE,cAYnC,CAAA;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,cAAc,EACrB,aAAa,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,GAClD,OAAO,CAOT;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,2BAA2B;IAC1C,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC/B,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAA;CACnC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAyD1D,MAAM,aAAa,MAAM;;;;EAuIxC"}
1
+ {"version":3,"file":"useDataGridWebsocket.d.ts","sourceRoot":"","sources":["../../../src/components/DataGrid/useDataGridWebsocket.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,iBAAiB,EAClB,MAAM,qCAAqC,CAAA;AAI5C,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AAKvD,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,SAAS,GAAG,IAAI,CAAA;IACvB;;;;;OAKG;IACH,uBAAuB,EAAE,OAAO,CAAA;IAChC;;;;;OAKG;IACH,uBAAuB,EAAE,OAAO,CAAA;IAChC;;;;OAIG;IACH,SAAS,EAAE,OAAO,CAAA;IAClB,WAAW,EAAE,OAAO,CAAA;IACpB,YAAY,EAAE,OAAO,CAAA;IACrB,gBAAgB,EAAE;QAChB,SAAS,EAAE,MAAM,CAAA;QACjB,SAAS,EAAE,MAAM,CAAA;KAClB,GAAG,IAAI,CAAA;IACR,iBAAiB,EAAE,iBAAiB,GAAG,IAAI,CAAA;IAC3C,mBAAmB,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,eAAe,EAAE,OAAO,CAAA;IACxB,cAAc,EAAE,OAAO,CAAA;CACxB;AAGD,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,mBAAmB,CAAA;IACzB,OAAO,EAAE;QAAE,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAA;CACrE,GACD;IAAE,IAAI,EAAE,wBAAwB,CAAC;IAAC,OAAO,EAAE,iBAAiB,CAAA;CAAE,GAC9D;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,mBAAmB,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,uBAAuB,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE,GACxB;IAAE,IAAI,EAAE,YAAY,CAAA;CAAE,GACtB;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,OAAO,EAAE,SAAS,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE,CAAA;AAGjD,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,cAAc,EACrB,MAAM,EAAE,eAAe,GACtB,cAAc,CAyGhB;AAED,eAAO,MAAM,qBAAqB,EAAE,cAYnC,CAAA;AAmBD;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAChC,KAAK,EAAE,cAAc,EACrB,aAAa,EAAE,iBAAiB,GAAG,IAAI,GAAG,SAAS,GAClD,OAAO,CAOT;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,2BAA2B;IAC1C,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC/B,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAA;CACnC;AAED,wBAAgB,oBAAoB,CAAC,OAAO,CAAC,EAAE,2BAA2B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;yBAyD1D,MAAM,aAAa,MAAM;;;;EA2IxC"}
@@ -144,7 +144,8 @@ function p(d) {
144
144
  sessionId: e.sessionId,
145
145
  websocketOptions: {
146
146
  ...E,
147
- model: p.model
147
+ model: p.model,
148
+ pendingPatches: p.model ? p.websocketInstance?.getPendingPatches() : void 0
148
149
  }
149
150
  }).then((e) => {
150
151
  if (g.current !== t) {