synapse-react-client 4.0.42 → 4.0.44
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SWC.index.js +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementList.d.ts +6 -20
- package/dist/components/AccessRequirementList/AccessRequirementList.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementList.js +165 -159
- package/dist/components/AccessRequirementList/AccessRequirementList.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementListItem.d.ts +3 -2
- package/dist/components/AccessRequirementList/AccessRequirementListItem.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementListItem.js +23 -22
- package/dist/components/AccessRequirementList/AccessRequirementListItem.js.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementListUtils.d.ts +4 -3
- package/dist/components/AccessRequirementList/AccessRequirementListUtils.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/AccessRequirementListUtils.js +6 -4
- package/dist/components/AccessRequirementList/AccessRequirementListUtils.js.map +1 -1
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/JsonSchemaRequestWizard.d.ts +22 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/JsonSchemaRequestWizard.d.ts.map +1 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/JsonSchemaRequestWizard.js +166 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/JsonSchemaRequestWizard.js.map +1 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/RequesterInformationFields.d.ts +18 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/RequesterInformationFields.d.ts.map +1 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/RequesterInformationFields.js +91 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/RequesterInformationFields.js.map +1 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/requesterInformation.d.ts +33 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/requesterInformation.d.ts.map +1 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/requesterInformation.js +49 -0
- package/dist/components/AccessRequirementList/JsonSchemaAccessRequirementRequestFlow/requesterInformation.js.map +1 -0
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/CancelRequestDataAccess.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/CancelRequestDataAccess.js +26 -42
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/CancelRequestDataAccess.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsFilesForm/DataAccessRequestAccessorsFilesForm.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsFilesForm/DataAccessRequestAccessorsFilesForm.js +140 -155
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsFilesForm/DataAccessRequestAccessorsFilesForm.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/EDucPreviewStep/EDucPreviewStep.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/EDucPreviewStep/EDucPreviewStep.js +43 -60
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/EDucPreviewStep/EDucPreviewStep.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManagedACTAccessRequirementFormWikiWrapper.d.ts +4 -5
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManagedACTAccessRequirementFormWikiWrapper.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManagedACTAccessRequirementFormWikiWrapper.js +5 -5
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManagedACTAccessRequirementFormWikiWrapper.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManualUploadDucStep/ManualUploadDucStep.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManualUploadDucStep/ManualUploadDucStep.js +88 -103
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManualUploadDucStep/ManualUploadDucStep.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/RequestDataAccessSuccess.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/RequestDataAccessSuccess.js +14 -30
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/RequestDataAccessSuccess.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/{ManagedACTAccessRequirementItem.d.ts → RequestableAccessRequirementItem.d.ts} +9 -8
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/RequestableAccessRequirementItem.d.ts.map +1 -0
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/{ManagedACTAccessRequirementItem.js → RequestableAccessRequirementItem.js} +16 -16
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/RequestableAccessRequirementItem.js.map +1 -0
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/{ManagedACTAccessRequirementItemView.d.ts → RequestableAccessRequirementItemView.d.ts} +5 -5
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/RequestableAccessRequirementItemView.d.ts.map +1 -0
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/{ManagedACTAccessRequirementItemView.js → RequestableAccessRequirementItemView.js} +3 -4
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/RequestableAccessRequirementItemView.js.map +1 -0
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ResearchProjectForm/ResearchProjectForm.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ResearchProjectForm/ResearchProjectForm.js +94 -110
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ResearchProjectForm/ResearchProjectForm.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ReviewDucStep/ReviewDucStep.d.ts +0 -2
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ReviewDucStep/ReviewDucStep.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ReviewDucStep/ReviewDucStep.js +35 -52
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ReviewDucStep/ReviewDucStep.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/SignatureStatusStep/SignatureStatusStep.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/SignatureStatusStep/SignatureStatusStep.js +79 -95
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/SignatureStatusStep/SignatureStatusStep.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/requestFlowTypes.d.ts +2 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/requestFlowTypes.d.ts.map +1 -1
- package/dist/components/AccessRequirementList/RequestDataStep.d.ts +34 -0
- package/dist/components/AccessRequirementList/RequestDataStep.d.ts.map +1 -0
- package/dist/components/AccessRequirementList/RequestDataStep.js +37 -0
- package/dist/components/AccessRequirementList/RequestDataStep.js.map +1 -0
- package/dist/components/AccessRequirementList/RequirementItem/UnmanagedACTAccessRequirementItem.d.ts +1 -1
- package/dist/components/AccessRequirementList/RequirementItem/UnmanagedACTAccessRequirementItem.js.map +1 -1
- package/dist/components/DataGrid/DataGridWebSocket.d.ts +29 -1
- package/dist/components/DataGrid/DataGridWebSocket.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGridWebSocket.js +48 -16
- package/dist/components/DataGrid/DataGridWebSocket.js.map +1 -1
- package/dist/components/DataGrid/components/GridLoadingState.d.ts +2 -2
- package/dist/components/DataGrid/components/GridLoadingState.d.ts.map +1 -1
- package/dist/components/DataGrid/components/GridLoadingState.js +2 -2
- package/dist/components/DataGrid/components/GridLoadingState.js.map +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.d.ts.map +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.js +2 -1
- package/dist/components/DataGrid/useDataGridWebsocket.js.map +1 -1
- package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.d.ts.map +1 -1
- package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.js +11 -10
- package/dist/components/EntityViewScopeEditor/EntityViewMaskEditor.js.map +1 -1
- package/dist/components/FormTemplateEditor/FormTemplatePreview.d.ts.map +1 -1
- package/dist/components/FormTemplateEditor/FormTemplatePreview.js +29 -30
- package/dist/components/FormTemplateEditor/FormTemplatePreview.js.map +1 -1
- package/dist/components/JsonSchemaForm/SchemaStepForm.d.ts +21 -0
- package/dist/components/JsonSchemaForm/SchemaStepForm.d.ts.map +1 -0
- package/dist/components/JsonSchemaForm/SchemaStepForm.js +29 -0
- package/dist/components/JsonSchemaForm/SchemaStepForm.js.map +1 -0
- package/dist/components/SetBasicAccessRequirementFields/GovernanceUtils.d.ts +2 -2
- package/dist/components/SetBasicAccessRequirementFields/GovernanceUtils.d.ts.map +1 -1
- package/dist/components/SetBasicAccessRequirementFields/GovernanceUtils.js +11 -10
- package/dist/components/SetBasicAccessRequirementFields/GovernanceUtils.js.map +1 -1
- package/dist/components/SetManagedAccessRequirementFields/DataUseCertificateFields.d.ts +10 -0
- package/dist/components/SetManagedAccessRequirementFields/DataUseCertificateFields.d.ts.map +1 -0
- package/dist/components/SetManagedAccessRequirementFields/DataUseCertificateFields.js +81 -0
- package/dist/components/SetManagedAccessRequirementFields/DataUseCertificateFields.js.map +1 -0
- package/dist/components/SetManagedAccessRequirementFields/ExpirationPeriodField.d.ts +9 -0
- package/dist/components/SetManagedAccessRequirementFields/ExpirationPeriodField.d.ts.map +1 -0
- package/dist/components/SetManagedAccessRequirementFields/ExpirationPeriodField.js +32 -0
- package/dist/components/SetManagedAccessRequirementFields/ExpirationPeriodField.js.map +1 -0
- package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.d.ts +0 -2
- package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.d.ts.map +1 -1
- package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.js +74 -151
- package/dist/components/SetManagedAccessRequirementFields/SetManagedAccessRequirementFields.js.map +1 -1
- package/dist/components/SynapseForm/SynapseForm.js +28 -28
- package/dist/components/TanStackTable/TanStackTableUtils.d.ts.map +1 -1
- package/dist/components/TanStackTable/TanStackTableUtils.js +8 -5
- package/dist/components/TanStackTable/TanStackTableUtils.js.map +1 -1
- package/dist/components/dataaccess/SubmissionPage/DataAccessSubmissionFileHandleLink.d.ts +5 -0
- package/dist/components/dataaccess/SubmissionPage/DataAccessSubmissionFileHandleLink.d.ts.map +1 -0
- package/dist/components/dataaccess/SubmissionPage/DataAccessSubmissionFileHandleLink.js +20 -0
- package/dist/components/dataaccess/SubmissionPage/DataAccessSubmissionFileHandleLink.js.map +1 -0
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.d.ts.map +1 -1
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js +183 -188
- package/dist/components/dataaccess/SubmissionPage/SubmissionPage.js.map +1 -1
- package/dist/components/dataaccess/SubmissionPage/SubmissionSchemaAnswers.d.ts +25 -0
- package/dist/components/dataaccess/SubmissionPage/SubmissionSchemaAnswers.d.ts.map +1 -0
- package/dist/components/dataaccess/SubmissionPage/SubmissionSchemaAnswers.js +125 -0
- package/dist/components/dataaccess/SubmissionPage/SubmissionSchemaAnswers.js.map +1 -0
- package/dist/components/dataaccess/UserAccessRequestHistory/InFlightEDucSignaturesTable.d.ts.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/InFlightEDucSignaturesTable.js +5 -4
- package/dist/components/dataaccess/UserAccessRequestHistory/InFlightEDucSignaturesTable.js.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryPlace.d.ts.map +1 -1
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryPlace.js +5 -4
- package/dist/components/dataaccess/UserAccessRequestHistory/UserAccessRequestHistoryPlace.js.map +1 -1
- package/dist/features/curator/dashboard/CuratorDashboardRouter.d.ts.map +1 -1
- package/dist/features/curator/dashboard/CuratorDashboardRouter.js +15 -15
- package/dist/features/curator/dashboard/CuratorDashboardRouter.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksPageRouter.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksPageRouter.js +15 -14
- package/dist/features/entity/metadata-task/components/MetadataTasksPageRouter.js.map +1 -1
- package/dist/mocks/accessRequirement/mockJsonSchemaAccessRequirements.d.ts +7 -0
- package/dist/mocks/accessRequirement/mockJsonSchemaAccessRequirements.d.ts.map +1 -1
- package/dist/mocks/accessRequirement/mockJsonSchemaAccessRequirements.js +30 -15
- package/dist/mocks/accessRequirement/mockJsonSchemaAccessRequirements.js.map +1 -1
- package/dist/mocks/dataaccess/MockDataAccessRequest.d.ts +3 -0
- package/dist/mocks/dataaccess/MockDataAccessRequest.d.ts.map +1 -1
- package/dist/mocks/dataaccess/MockDataAccessRequest.js +24 -12
- package/dist/mocks/dataaccess/MockDataAccessRequest.js.map +1 -1
- package/dist/mocks/dataaccess/MockSubmission.d.ts +76 -0
- package/dist/mocks/dataaccess/MockSubmission.d.ts.map +1 -1
- package/dist/mocks/dataaccess/MockSubmission.js +108 -63
- package/dist/mocks/dataaccess/MockSubmission.js.map +1 -1
- package/dist/mocks/msw/handlers/dataAccessRequestHandlers.d.ts.map +1 -1
- package/dist/mocks/msw/handlers/dataAccessRequestHandlers.js +42 -30
- package/dist/mocks/msw/handlers/dataAccessRequestHandlers.js.map +1 -1
- package/dist/style/components/_submission-page.scss +0 -4
- package/dist/style/main.css +1 -1
- package/dist/synapse-queries/dataaccess/useGeneratedRequestForm.d.ts +19 -0
- package/dist/synapse-queries/dataaccess/useGeneratedRequestForm.d.ts.map +1 -0
- package/dist/synapse-queries/dataaccess/useGeneratedRequestForm.js +26 -0
- package/dist/synapse-queries/dataaccess/useGeneratedRequestForm.js.map +1 -0
- package/dist/synapse-queries/dataaccess/useGeneratedSubmissionForm.d.ts +37 -0
- package/dist/synapse-queries/dataaccess/useGeneratedSubmissionForm.d.ts.map +1 -0
- package/dist/synapse-queries/dataaccess/useGeneratedSubmissionForm.js +35 -0
- package/dist/synapse-queries/dataaccess/useGeneratedSubmissionForm.js.map +1 -0
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts +2 -0
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.d.ts.map +1 -1
- package/dist/synapse-queries/grid/useEstablishWebsocketConnection.js.map +1 -1
- package/dist/synapse-queries/termsOfService/useTermsOfService.d.ts.map +1 -1
- package/dist/synapse-queries/termsOfService/useTermsOfService.js +21 -19
- package/dist/synapse-queries/termsOfService/useTermsOfService.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/functions/EntityTypeUtils.d.ts +2 -2
- package/dist/utils/functions/EntityTypeUtils.d.ts.map +1 -1
- package/dist/utils/functions/EntityTypeUtils.js +135 -135
- package/dist/utils/functions/EntityTypeUtils.js.map +1 -1
- package/dist/utils/hooks/useDetectSSOCode.d.ts.map +1 -1
- package/dist/utils/hooks/useDetectSSOCode.js +31 -26
- package/dist/utils/hooks/useDetectSSOCode.js.map +1 -1
- package/dist/utils/jsonschema/schemaData.d.ts +18 -0
- package/dist/utils/jsonschema/schemaData.d.ts.map +1 -0
- package/dist/utils/jsonschema/schemaData.js +26 -0
- package/dist/utils/jsonschema/schemaData.js.map +1 -0
- package/package.json +2 -2
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManagedACTAccessRequirementItem.d.ts.map +0 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManagedACTAccessRequirementItem.js.map +0 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManagedACTAccessRequirementItemView.d.ts.map +0 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/ManagedACTAccessRequirementItemView.js.map +0 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { AccessRequirement, JsonSchemaAccessRequirement, ManagedACTAccessRequirement } from '@sage-bionetworks/synapse-types';
|
|
2
|
+
/** The access requirement types that a user can request access to through the request wizard */
|
|
3
|
+
export type RequestableAccessRequirement = ManagedACTAccessRequirement | JsonSchemaAccessRequirement;
|
|
4
|
+
export declare function isRequestableAccessRequirement(accessRequirement: AccessRequirement): accessRequirement is RequestableAccessRequirement;
|
|
5
|
+
/**
|
|
6
|
+
* Represents a distinct screen in the wizard used to request access to a {@link RequestableAccessRequirement}
|
|
7
|
+
*/
|
|
8
|
+
export declare enum RequestDataStep {
|
|
9
|
+
SHOW_ALL_ARS = 0,
|
|
10
|
+
UPDATE_RESEARCH_PROJECT = 1,
|
|
11
|
+
UPDATE_ACCESSORS_AND_FILES = 2,
|
|
12
|
+
PROMPT_CANCEL = 3,
|
|
13
|
+
PROMPT_LOGIN = 4,
|
|
14
|
+
COMPLETE = 5,
|
|
15
|
+
REVIEW_DUC = 6,
|
|
16
|
+
EDUC_PREVIEW = 7,
|
|
17
|
+
MANUAL_UPLOAD_DUC = 8,
|
|
18
|
+
SIGNATURE_STATUS = 9,
|
|
19
|
+
/** The request wizard of a JsonSchemaAccessRequirement, which owns its own sequence of steps */
|
|
20
|
+
SCHEMA_DRIVEN_REQUEST = 10
|
|
21
|
+
}
|
|
22
|
+
/** The first step of the wizard in which a user requests access to the given access requirement */
|
|
23
|
+
export declare function getFirstRequestStep(accessRequirement: Pick<RequestableAccessRequirement, 'concreteType'>): RequestDataStep;
|
|
24
|
+
/**
|
|
25
|
+
* The step that follows `currentStep` in the request wizard of the given access requirement.
|
|
26
|
+
* @throws if `currentStep` is the last step of, or not a step of, the access requirement's request wizard
|
|
27
|
+
*/
|
|
28
|
+
export declare function getNextRequestStep(accessRequirement: Pick<RequestableAccessRequirement, 'concreteType'>, currentStep: RequestDataStep): RequestDataStep;
|
|
29
|
+
/**
|
|
30
|
+
* The step that precedes `currentStep` in the request wizard of the given access requirement.
|
|
31
|
+
* @throws if `currentStep` is the first step of, or not a step of, the access requirement's request wizard
|
|
32
|
+
*/
|
|
33
|
+
export declare function getPreviousRequestStep(accessRequirement: Pick<RequestableAccessRequirement, 'concreteType'>, currentStep: RequestDataStep): RequestDataStep;
|
|
34
|
+
//# sourceMappingURL=RequestDataStep.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequestDataStep.d.ts","sourceRoot":"","sources":["../../../src/components/AccessRequirementList/RequestDataStep.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,iBAAiB,EAEjB,2BAA2B,EAE3B,2BAA2B,EAC5B,MAAM,iCAAiC,CAAA;AAExC,gGAAgG;AAChG,MAAM,MAAM,4BAA4B,GACpC,2BAA2B,GAC3B,2BAA2B,CAAA;AAE/B,wBAAgB,8BAA8B,CAC5C,iBAAiB,EAAE,iBAAiB,GACnC,iBAAiB,IAAI,4BAA4B,CAOnD;AAED;;GAEG;AACH,oBAAY,eAAe;IACzB,YAAY,IAAA;IACZ,uBAAuB,IAAA;IACvB,0BAA0B,IAAA;IAC1B,aAAa,IAAA;IACb,YAAY,IAAA;IACZ,QAAQ,IAAA;IACR,UAAU,IAAA;IACV,YAAY,IAAA;IACZ,iBAAiB,IAAA;IACjB,gBAAgB,IAAA;IAChB,gGAAgG;IAChG,qBAAqB,KAAA;CACtB;AAyBD,mGAAmG;AACnG,wBAAgB,mBAAmB,CACjC,iBAAiB,EAAE,IAAI,CAAC,4BAA4B,EAAE,cAAc,CAAC,GACpE,eAAe,CAEjB;AAED;;;GAGG;AACH,wBAAgB,kBAAkB,CAChC,iBAAiB,EAAE,IAAI,CAAC,4BAA4B,EAAE,cAAc,CAAC,EACrE,WAAW,EAAE,eAAe,GAC3B,eAAe,CAEjB;AAED;;;GAGG;AACH,wBAAgB,sBAAsB,CACpC,iBAAiB,EAAE,IAAI,CAAC,4BAA4B,EAAE,cAAc,CAAC,EACrE,WAAW,EAAE,eAAe,GAC3B,eAAe,CAEjB"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE as e, MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE as t } from "@sage-bionetworks/synapse-types";
|
|
2
|
+
//#region src/components/AccessRequirementList/RequestDataStep.ts
|
|
3
|
+
function n(n) {
|
|
4
|
+
return n.concreteType === t || n.concreteType === e;
|
|
5
|
+
}
|
|
6
|
+
var r = /* @__PURE__ */ function(e) {
|
|
7
|
+
return e[e.SHOW_ALL_ARS = 0] = "SHOW_ALL_ARS", e[e.UPDATE_RESEARCH_PROJECT = 1] = "UPDATE_RESEARCH_PROJECT", e[e.UPDATE_ACCESSORS_AND_FILES = 2] = "UPDATE_ACCESSORS_AND_FILES", e[e.PROMPT_CANCEL = 3] = "PROMPT_CANCEL", e[e.PROMPT_LOGIN = 4] = "PROMPT_LOGIN", e[e.COMPLETE = 5] = "COMPLETE", e[e.REVIEW_DUC = 6] = "REVIEW_DUC", e[e.EDUC_PREVIEW = 7] = "EDUC_PREVIEW", e[e.MANUAL_UPLOAD_DUC = 8] = "MANUAL_UPLOAD_DUC", e[e.SIGNATURE_STATUS = 9] = "SIGNATURE_STATUS", e[e.SCHEMA_DRIVEN_REQUEST = 10] = "SCHEMA_DRIVEN_REQUEST", e;
|
|
8
|
+
}({}), i = [
|
|
9
|
+
6,
|
|
10
|
+
7,
|
|
11
|
+
8
|
|
12
|
+
], a = {
|
|
13
|
+
[t]: [
|
|
14
|
+
1,
|
|
15
|
+
2,
|
|
16
|
+
...i
|
|
17
|
+
],
|
|
18
|
+
[e]: [10, ...i]
|
|
19
|
+
};
|
|
20
|
+
function o(e) {
|
|
21
|
+
return a[e.concreteType][0];
|
|
22
|
+
}
|
|
23
|
+
function s(e, t) {
|
|
24
|
+
return l(e, t, 1);
|
|
25
|
+
}
|
|
26
|
+
function c(e, t) {
|
|
27
|
+
return l(e, t, -1);
|
|
28
|
+
}
|
|
29
|
+
function l(e, t, n) {
|
|
30
|
+
let i = a[e.concreteType], o = i.indexOf(t), s = o === -1 ? void 0 : i[o + n];
|
|
31
|
+
if (s === void 0) throw Error(`There is no ${n === 1 ? "next" : "previous"} step for ${r[t]} in the request wizard of ${e.concreteType}`);
|
|
32
|
+
return s;
|
|
33
|
+
}
|
|
34
|
+
//#endregion
|
|
35
|
+
export { r as RequestDataStep, o as getFirstRequestStep, s as getNextRequestStep, c as getPreviousRequestStep, n as isRequestableAccessRequirement };
|
|
36
|
+
|
|
37
|
+
//# sourceMappingURL=RequestDataStep.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RequestDataStep.js","names":[],"sources":["../../../src/components/AccessRequirementList/RequestDataStep.ts"],"sourcesContent":["import {\n AccessRequirement,\n JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n JsonSchemaAccessRequirement,\n MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE,\n ManagedACTAccessRequirement,\n} from '@sage-bionetworks/synapse-types'\n\n/** The access requirement types that a user can request access to through the request wizard */\nexport type RequestableAccessRequirement =\n | ManagedACTAccessRequirement\n | JsonSchemaAccessRequirement\n\nexport function isRequestableAccessRequirement(\n accessRequirement: AccessRequirement,\n): accessRequirement is RequestableAccessRequirement {\n return (\n accessRequirement.concreteType ===\n MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE ||\n accessRequirement.concreteType ===\n JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE\n )\n}\n\n/**\n * Represents a distinct screen in the wizard used to request access to a {@link RequestableAccessRequirement}\n */\nexport enum RequestDataStep {\n SHOW_ALL_ARS,\n UPDATE_RESEARCH_PROJECT,\n UPDATE_ACCESSORS_AND_FILES,\n PROMPT_CANCEL,\n PROMPT_LOGIN,\n COMPLETE,\n REVIEW_DUC,\n EDUC_PREVIEW,\n MANUAL_UPLOAD_DUC,\n SIGNATURE_STATUS,\n /** The request wizard of a JsonSchemaAccessRequirement, which owns its own sequence of steps */\n SCHEMA_DRIVEN_REQUEST,\n}\n\n// Only ARs with an eDUC template continue to these steps; others submit from the last step before them.\n// MANUAL_UPLOAD_DUC is the alternative to sending the eDUC for signature from EDUC_PREVIEW.\nconst EDUC_STEPS = [\n RequestDataStep.REVIEW_DUC,\n RequestDataStep.EDUC_PREVIEW,\n RequestDataStep.MANUAL_UPLOAD_DUC,\n] as const\n\nconst REQUEST_STEP_ORDER: Record<\n RequestableAccessRequirement['concreteType'],\n readonly RequestDataStep[]\n> = {\n [MANAGED_ACT_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE]: [\n RequestDataStep.UPDATE_RESEARCH_PROJECT,\n RequestDataStep.UPDATE_ACCESSORS_AND_FILES,\n ...EDUC_STEPS,\n ],\n [JSON_SCHEMA_ACCESS_REQUIREMENT_CONCRETE_TYPE_VALUE]: [\n RequestDataStep.SCHEMA_DRIVEN_REQUEST,\n ...EDUC_STEPS,\n ],\n}\n\n/** The first step of the wizard in which a user requests access to the given access requirement */\nexport function getFirstRequestStep(\n accessRequirement: Pick<RequestableAccessRequirement, 'concreteType'>,\n): RequestDataStep {\n return REQUEST_STEP_ORDER[accessRequirement.concreteType][0]\n}\n\n/**\n * The step that follows `currentStep` in the request wizard of the given access requirement.\n * @throws if `currentStep` is the last step of, or not a step of, the access requirement's request wizard\n */\nexport function getNextRequestStep(\n accessRequirement: Pick<RequestableAccessRequirement, 'concreteType'>,\n currentStep: RequestDataStep,\n): RequestDataStep {\n return getAdjacentRequestStep(accessRequirement, currentStep, 1)\n}\n\n/**\n * The step that precedes `currentStep` in the request wizard of the given access requirement.\n * @throws if `currentStep` is the first step of, or not a step of, the access requirement's request wizard\n */\nexport function getPreviousRequestStep(\n accessRequirement: Pick<RequestableAccessRequirement, 'concreteType'>,\n currentStep: RequestDataStep,\n): RequestDataStep {\n return getAdjacentRequestStep(accessRequirement, currentStep, -1)\n}\n\nfunction getAdjacentRequestStep(\n accessRequirement: Pick<RequestableAccessRequirement, 'concreteType'>,\n currentStep: RequestDataStep,\n offset: 1 | -1,\n): RequestDataStep {\n const stepOrder = REQUEST_STEP_ORDER[accessRequirement.concreteType]\n const currentIndex = stepOrder.indexOf(currentStep)\n const adjacentStep =\n currentIndex === -1 ? undefined : stepOrder[currentIndex + offset]\n if (adjacentStep === undefined) {\n throw new Error(\n `There is no ${offset === 1 ? 'next' : 'previous'} step for ${RequestDataStep[currentStep]} in the request wizard of ${accessRequirement.concreteType}`,\n )\n }\n return adjacentStep\n}\n"],"mappings":";;AAaA,SAAgB,EACd,GACmD;CACnD,OACE,EAAkB,iBAChB,KACF,EAAkB,iBAChB;AAEN;AAKA,IAAY,IAAL,yBAAA,GAAA;QACL,EAAA,EAAA,eAAA,KAAA,gBACA,EAAA,EAAA,0BAAA,KAAA,2BACA,EAAA,EAAA,6BAAA,KAAA,8BACA,EAAA,EAAA,gBAAA,KAAA,iBACA,EAAA,EAAA,eAAA,KAAA,gBACA,EAAA,EAAA,WAAA,KAAA,YACA,EAAA,EAAA,aAAA,KAAA,cACA,EAAA,EAAA,eAAA,KAAA,gBACA,EAAA,EAAA,oBAAA,KAAA,qBACA,EAAA,EAAA,mBAAA,KAAA,oBAEA,EAAA,EAAA,wBAAA,MAAA;AACF,EAAA,CAAA,CAAA,GAIM,IAAa;;;;AAInB,GAEM,IAGF;EACD,IAAqD;;;EAGpD,GAAG;CACL;EACC,IAAqD,CAAA,IAEpD,GAAG,CACL;AACF;AAGA,SAAgB,EACd,GACiB;CACjB,OAAO,EAAmB,EAAkB,cAAc;AAC5D;AAMA,SAAgB,EACd,GACA,GACiB;CACjB,OAAO,EAAuB,GAAmB,GAAa,CAAC;AACjE;AAMA,SAAgB,EACd,GACA,GACiB;CACjB,OAAO,EAAuB,GAAmB,GAAa,EAAE;AAClE;AAEA,SAAS,EACP,GACA,GACA,GACiB;CACjB,IAAM,IAAY,EAAmB,EAAkB,eACjD,IAAe,EAAU,QAAQ,CAAW,GAC5C,IACJ,MAAiB,KAAK,KAAA,IAAY,EAAU,IAAe;CAC7D,IAAI,MAAiB,KAAA,GACnB,MAAU,MACR,eAAe,MAAW,IAAI,SAAS,WAAW,YAAY,EAAgB,GAAa,4BAA4B,EAAkB,cAC3I;CAEF,OAAO;AACT"}
|
package/dist/components/AccessRequirementList/RequirementItem/UnmanagedACTAccessRequirementItem.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export type UnmanagedACTAccessRequirementItemProps = {
|
|
|
8
8
|
/**
|
|
9
9
|
* Renders a {@link RequirementItem} for the deprecated {@link ACTAccessRequirement}.
|
|
10
10
|
*
|
|
11
|
-
* For {@link ManagedACTAccessRequirement}s, see {@link
|
|
11
|
+
* For {@link ManagedACTAccessRequirement}s and {@link JsonSchemaAccessRequirement}s, see {@link RequestableAccessRequirementItem}
|
|
12
12
|
*
|
|
13
13
|
* For {@link SelfSignAccessRequirement} and {@link TermsOfUseAccessRequirement}, see {@link SelfSignAccessRequirementItem}
|
|
14
14
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UnmanagedACTAccessRequirementItem.js","names":[],"sources":["../../../../src/components/AccessRequirementList/RequirementItem/UnmanagedACTAccessRequirementItem.tsx"],"sourcesContent":["import {\n useGetAccessRequirementStatus,\n useGetAccessRequirementWikiPageKey,\n} from '@/synapse-queries'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport { PRODUCTION_ENDPOINT_CONFIG } from '@/utils/functions/getEndpoint'\nimport { Box, ButtonProps, Link, Typography } from '@mui/material'\nimport {\n ACTAccessRequirement,\n RestrictableObjectType,\n} from '@sage-bionetworks/synapse-types'\nimport { useState } from 'react'\nimport MarkdownSynapse from '../../Markdown/MarkdownSynapse'\nimport { RequirementItemStatus } from '../AccessApprovalCheckMark'\nimport RequirementItem from './RequirementItem'\n\nexport type UnmanagedACTAccessRequirementItemProps = {\n subjectId?: string\n subjectType?: RestrictableObjectType\n accessRequirement: ACTAccessRequirement\n onHide: () => void\n}\n\n/**\n * Renders a {@link RequirementItem} for the deprecated {@link ACTAccessRequirement}.\n *\n * For {@link ManagedACTAccessRequirement}s, see {@link
|
|
1
|
+
{"version":3,"file":"UnmanagedACTAccessRequirementItem.js","names":[],"sources":["../../../../src/components/AccessRequirementList/RequirementItem/UnmanagedACTAccessRequirementItem.tsx"],"sourcesContent":["import {\n useGetAccessRequirementStatus,\n useGetAccessRequirementWikiPageKey,\n} from '@/synapse-queries'\nimport { useSynapseContext } from '@/utils/context/SynapseContext'\nimport { PRODUCTION_ENDPOINT_CONFIG } from '@/utils/functions/getEndpoint'\nimport { Box, ButtonProps, Link, Typography } from '@mui/material'\nimport {\n ACTAccessRequirement,\n RestrictableObjectType,\n} from '@sage-bionetworks/synapse-types'\nimport { useState } from 'react'\nimport MarkdownSynapse from '../../Markdown/MarkdownSynapse'\nimport { RequirementItemStatus } from '../AccessApprovalCheckMark'\nimport RequirementItem from './RequirementItem'\n\nexport type UnmanagedACTAccessRequirementItemProps = {\n subjectId?: string\n subjectType?: RestrictableObjectType\n accessRequirement: ACTAccessRequirement\n onHide: () => void\n}\n\n/**\n * Renders a {@link RequirementItem} for the deprecated {@link ACTAccessRequirement}.\n *\n * For {@link ManagedACTAccessRequirement}s and {@link JsonSchemaAccessRequirement}s, see {@link RequestableAccessRequirementItem}\n *\n * For {@link SelfSignAccessRequirement} and {@link TermsOfUseAccessRequirement}, see {@link SelfSignAccessRequirementItem}\n */\nexport default function UnmanagedACTAccessRequirementItem(\n props: UnmanagedACTAccessRequirementItemProps,\n) {\n const { accessRequirement, subjectId, subjectType, onHide } = props\n const { isAuthenticated } = useSynapseContext()\n\n const { data: accessRequirementStatus, isLoading: isLoadingStatus } =\n useGetAccessRequirementStatus(String(accessRequirement.id))\n\n const { data: wikiPage } = useGetAccessRequirementWikiPageKey(\n accessRequirement.id.toString(),\n // ACT ARs may have the contact info embedded in the AR or may have an associated Wiki.\n )\n\n const isApproved = accessRequirementStatus?.isApproved\n\n const [showACTContactInfoInstructions, setShowACTContactInfoInstructions] =\n useState<boolean>(false)\n\n let acceptButtonText = ''\n if (\n typeof window !== 'undefined' &&\n (window.location.hostname === 'www.synapse.org' ||\n window.location.hostname === 'staging.synapse.org')\n ) {\n acceptButtonText = 'Request access'\n } else {\n acceptButtonText = 'Request access via Synapse.org'\n }\n\n const gotoSynapseAccessRequirementPage = () => {\n const subjectTypeFilter = subjectType ? `&TYPE=${subjectType}` : ''\n const subjectIdFilter = subjectId ? `&ID=${subjectId}` : ''\n window.open(\n `${PRODUCTION_ENDPOINT_CONFIG.PORTAL}AccessRequirement:AR_ID=${accessRequirement.id}${subjectTypeFilter}${subjectIdFilter}`,\n )\n }\n const onAcceptClicked = () => {\n gotoSynapseAccessRequirementPage()\n // PORTALS-1483: and close the dialog.\n if (onHide) {\n onHide()\n }\n }\n\n const actContactInfo = accessRequirement.actContactInfo\n\n let actions: ButtonProps[] | undefined = undefined\n\n if (isAuthenticated && !isApproved) {\n actions = [\n {\n variant: 'outlined',\n onClick: onAcceptClicked,\n children: acceptButtonText,\n },\n {\n variant: 'text',\n onClick: onHide,\n children: 'I do not accept',\n },\n ]\n }\n\n let renderedTerms = <></>\n if (actContactInfo) {\n renderedTerms = <MarkdownSynapse markdown={actContactInfo} />\n } else if (wikiPage) {\n renderedTerms = (\n <MarkdownSynapse\n wikiId={wikiPage?.wikiPageId}\n ownerId={wikiPage?.ownerObjectId}\n objectType={wikiPage?.ownerObjectType}\n />\n )\n }\n return (\n <RequirementItem\n data-testid={'UnmanagedACTAccessRequirementItem'}\n status={\n isLoadingStatus\n ? RequirementItemStatus.LOADING\n : isApproved\n ? RequirementItemStatus.COMPLETE\n : RequirementItemStatus.LOCKED\n }\n actions={actions}\n >\n {isApproved ? (\n <>\n <Typography variant={'body1'}>\n Your data access request has been approved.{' '}\n <Link\n role={'button'}\n onClick={() =>\n setShowACTContactInfoInstructions(\n !showACTContactInfoInstructions,\n )\n }\n >\n {showACTContactInfoInstructions\n ? 'Hide Instructions'\n : 'View Instructions'}\n </Link>\n </Typography>\n {showACTContactInfoInstructions && (\n <Box sx={{ my: 1 }}>{renderedTerms}</Box>\n )}\n </>\n ) : (\n renderedTerms\n )}\n </RequirementItem>\n )\n}\n"],"mappings":";;;;;;;;;;;AA8BA,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,sBAAmB,cAAW,gBAAa,cAAW,GACxD,EAAE,uBAAoB,EAAkB,GAExC,EAAE,MAAM,GAAyB,WAAW,MAChD,EAA8B,OAAO,EAAkB,EAAE,CAAC,GAEtD,EAAE,MAAM,MAAa,EACzB,EAAkB,GAAG,SAAS,CAEhC,GAEM,IAAa,GAAyB,YAEtC,CAAC,GAAgC,KACrC,EAAkB,EAAK,GAErB,IAAmB;CACvB,AAOE,IANA,OAAO,SAAW,QACjB,OAAO,SAAS,aAAa,qBAC5B,OAAO,SAAS,aAAa,yBAEZ,mBAEA;CAGrB,IAAM,UAAyC;EAC7C,IAAM,IAAoB,IAAc,SAAS,MAAgB,IAC3D,IAAkB,IAAY,OAAO,MAAc;EACzD,OAAO,KACL,GAAG,EAA2B,OAAO,0BAA0B,EAAkB,KAAK,IAAoB,GAC5G;CACF,GACM,UAAwB;EAG5B,AAFA,EAAiC,GAE7B,KACF,EAAO;CAEX,GAEM,IAAiB,EAAkB,gBAErC;CAEJ,AAAI,KAAmB,CAAC,MACtB,IAAU,CACR;EACE,SAAS;EACT,SAAS;EACT,UAAU;CACZ,GACA;EACE,SAAS;EACT,SAAS;EACT,UAAU;CACZ,CACF;CAGF,IAAI,IAAgB,kBAAA,GAAA,CAAI,CAAA;CAYxB,OAXI,IACF,IAAgB,kBAAC,GAAD,EAAiB,UAAU,EAAiB,CAAA,IACnD,MACT,IACE,kBAAC,GAAD;EACE,QAAQ,GAAU;EAClB,SAAS,GAAU;EACnB,YAAY,GAAU;CACvB,CAAA,IAIH,kBAAC,GAAD;EACE,eAAa;EACb,QACE,IACI,EAAsB,UACtB,IACE,EAAsB,WACtB,EAAsB;EAErB;YAER,IACC,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;GAAY,SAAS;aAArB;IAA8B;IACgB;IAC5C,kBAAC,GAAD;KACE,MAAM;KACN,eACE,EACE,CAAC,CACH;eAGD,IACG,sBACA;IACA,CAAA;GACI;MACX,KACC,kBAAC,GAAD;GAAK,IAAI,EAAE,IAAI,EAAE;aAAI;EAAmB,CAAA,CAE1C,EAAA,CAAA,IAEF;CAEa,CAAA;AAErB"}
|
|
@@ -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
|
|
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;
|
|
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:
|
|
36
|
-
this.messageCounter = new a(), this.replicaId = t, this.maxPayloadSizeBytes = m ?? h, this.socket =
|
|
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
|
-
|
|
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
|
-
|
|
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).
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
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 {
|
|
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: "
|
|
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
|
|
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;;;;;;
|
|
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: "
|
|
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
|
|
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: '
|
|
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;;;;
|
|
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) {
|