synapse-react-client 4.0.5 → 4.0.7
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.d.ts +2 -0
- package/dist/SWC.index.d.ts.map +1 -1
- package/dist/SWC.index.js +47 -41
- package/dist/SWC.index.js.map +1 -1
- package/dist/assets/DefaultColorfulPortalCardBackground.svg +50 -12
- package/dist/assets/DefaultColorfulPortalCardBackground.svg.js +4 -4
- package/dist/assets/DefaultColorfulPortalCardBackground.svg.js.map +1 -1
- package/dist/components/CardDeck/TableQueryCardDeck.js +3 -4
- package/dist/components/CardDeck/TableQueryCardDeck.js.map +1 -1
- package/dist/components/ChangePassword/useChangePasswordFormState.js +2 -3
- package/dist/components/ChangePassword/useChangePasswordFormState.js.map +1 -1
- package/dist/components/ColoredBulletListItem/ColoredBulletListItem.css +1 -0
- package/dist/components/ColoredBulletListItem/ColoredBulletListItem.d.ts +8 -0
- package/dist/components/ColoredBulletListItem/ColoredBulletListItem.d.ts.map +1 -0
- package/dist/components/ColoredBulletListItem/ColoredBulletListItem.js +21 -0
- package/dist/components/ColoredBulletListItem/ColoredBulletListItem.js.map +1 -0
- package/dist/components/ColoredBulletListItem/ColoredBulletListItem.module.scss +32 -0
- package/dist/components/ColoredBulletListItem/ColoredBulletListItem.module.scss.js +14 -0
- package/dist/components/ColoredBulletListItem/ColoredBulletListItem.module.scss.js.map +1 -0
- package/dist/components/ColoredBulletListItem/index.d.ts +5 -0
- package/dist/components/ColoredBulletListItem/index.d.ts.map +1 -0
- package/dist/components/ColoredBulletListItem/index.js +6 -0
- package/dist/components/ColoredBulletListItem/index.js.map +1 -0
- package/dist/components/CreateOrUpdateAccessRequirementWizard/CreateOrUpdateAccessRequirementWizard.js +3 -4
- package/dist/components/CreateOrUpdateAccessRequirementWizard/CreateOrUpdateAccessRequirementWizard.js.map +1 -1
- package/dist/components/CreateProjectModal/CreateProjectModal.d.ts +2 -1
- package/dist/components/CreateProjectModal/CreateProjectModal.d.ts.map +1 -1
- package/dist/components/CreateProjectModal/CreateProjectModal.js +122 -43
- package/dist/components/CreateProjectModal/CreateProjectModal.js.map +1 -1
- package/dist/components/CreateProjectModal/ProjectVisibilityRadioGroup.d.ts +7 -0
- package/dist/components/CreateProjectModal/ProjectVisibilityRadioGroup.d.ts.map +1 -0
- package/dist/components/CreateProjectModal/ProjectVisibilityRadioGroup.js +132 -0
- package/dist/components/CreateProjectModal/ProjectVisibilityRadioGroup.js.map +1 -0
- package/dist/components/DataGrid/DataGrid.d.ts +2 -0
- package/dist/components/DataGrid/DataGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGrid.js +69 -67
- package/dist/components/DataGrid/DataGrid.js.map +1 -1
- package/dist/components/DataGrid/DataGridWebSocket.d.ts +4 -0
- package/dist/components/DataGrid/DataGridWebSocket.d.ts.map +1 -1
- package/dist/components/DataGrid/DataGridWebSocket.js +47 -37
- package/dist/components/DataGrid/DataGridWebSocket.js.map +1 -1
- package/dist/components/DataGrid/MergeGridWithSourceTableButton.js +2 -3
- package/dist/components/DataGrid/MergeGridWithSourceTableButton.js.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.d.ts.map +1 -1
- package/dist/components/DataGrid/SynapseGrid.js +209 -162
- package/dist/components/DataGrid/SynapseGrid.js.map +1 -1
- package/dist/components/DataGrid/components/UploadCsvToGridDialog.js +2 -3
- package/dist/components/DataGrid/components/UploadCsvToGridDialog.js.map +1 -1
- package/dist/components/DataGrid/hooks/useRemoteSelections.d.ts +16 -0
- package/dist/components/DataGrid/hooks/useRemoteSelections.d.ts.map +1 -0
- package/dist/components/DataGrid/hooks/useRemoteSelections.js +30 -0
- package/dist/components/DataGrid/hooks/useRemoteSelections.js.map +1 -0
- package/dist/components/DataGrid/useDataGridWebsocket.d.ts +6 -1
- package/dist/components/DataGrid/useDataGridWebsocket.d.ts.map +1 -1
- package/dist/components/DataGrid/useDataGridWebsocket.js +78 -69
- package/dist/components/DataGrid/useDataGridWebsocket.js.map +1 -1
- package/dist/components/DataGrid/utils/getCellClassName.d.ts +3 -0
- package/dist/components/DataGrid/utils/getCellClassName.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/getCellClassName.js +21 -12
- package/dist/components/DataGrid/utils/getCellClassName.js.map +1 -1
- package/dist/components/DataGrid/utils/replicaSelectionToGridSelection.d.ts +15 -0
- package/dist/components/DataGrid/utils/replicaSelectionToGridSelection.d.ts.map +1 -0
- package/dist/components/DataGrid/utils/replicaSelectionToGridSelection.js +43 -0
- package/dist/components/DataGrid/utils/replicaSelectionToGridSelection.js.map +1 -0
- package/dist/components/DialogBase.d.ts +3 -1
- package/dist/components/DialogBase.d.ts.map +1 -1
- package/dist/components/DialogBase.js +75 -56
- package/dist/components/DialogBase.js.map +1 -1
- package/dist/components/Ecosystem/EcosystemSkeleton.js +2 -3
- package/dist/components/Ecosystem/EcosystemSkeleton.js.map +1 -1
- package/dist/components/FeaturedDataTabs/FacetPlotsCard.js +2 -3
- package/dist/components/FeaturedDataTabs/FacetPlotsCard.js.map +1 -1
- package/dist/components/FeaturedDataTabs/FeaturedDataTabs.js +2 -3
- package/dist/components/FeaturedDataTabs/FeaturedDataTabs.js.map +1 -1
- package/dist/components/GenericCard/GenericCard.js +3 -4
- package/dist/components/GenericCard/GenericCard.js.map +1 -1
- package/dist/components/HeaderCard.js +2 -3
- package/dist/components/HeaderCard.js.map +1 -1
- package/dist/components/IconSvg/IconSvg.d.ts +1 -1
- package/dist/components/IconSvg/IconSvg.d.ts.map +1 -1
- package/dist/components/IconSvg/IconSvg.js +168 -165
- package/dist/components/IconSvg/IconSvg.js.map +1 -1
- package/dist/components/StorybookComponentWrapper.js +3 -4
- package/dist/components/StorybookComponentWrapper.js.map +1 -1
- package/dist/components/SynapseForm/SynapseFormSubmissionGrid.d.ts +1 -0
- package/dist/components/SynapseForm/SynapseFormSubmissionGrid.d.ts.map +1 -1
- package/dist/components/SynapseForm/SynapseFormSubmissionGrid.js +23 -16
- package/dist/components/SynapseForm/SynapseFormSubmissionGrid.js.map +1 -1
- package/dist/components/SynapseTable/SynapseTable.d.ts +6 -1
- package/dist/components/SynapseTable/SynapseTable.d.ts.map +1 -1
- package/dist/components/SynapseTable/SynapseTable.js +123 -93
- package/dist/components/SynapseTable/SynapseTable.js.map +1 -1
- package/dist/components/TextField/TextField.css +1 -0
- package/dist/components/TextField/TextField.d.ts +2 -1
- package/dist/components/TextField/TextField.d.ts.map +1 -1
- package/dist/components/TextField/TextField.js +42 -28
- package/dist/components/TextField/TextField.js.map +1 -1
- package/dist/components/TextField/TextField.module.scss +25 -0
- package/dist/components/TextField/TextField.module.scss.js +14 -0
- package/dist/components/TextField/TextField.module.scss.js.map +1 -0
- package/dist/components/download_list/AddToDownloadListConfirmationAlert/AddToDownloadListConfirmationAlert.js +2 -3
- package/dist/components/download_list/AddToDownloadListConfirmationAlert/AddToDownloadListConfirmationAlert.js.map +1 -1
- package/dist/components/index.d.ts +1 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +242 -240
- package/dist/components/index.js.map +1 -1
- package/dist/components/styled/HoverPopover.css +1 -1
- package/dist/components/styled/HoverPopover.d.ts.map +1 -1
- package/dist/components/styled/HoverPopover.js +6 -5
- package/dist/components/styled/HoverPopover.js.map +1 -1
- package/dist/components/styled/HoverPopover.module.scss +2 -1
- package/dist/components/styled/HoverPopover.module.scss.js +1 -1
- package/dist/components/styled/StyledFormControl.js +1 -1
- package/dist/components/styled/StyledFormControl.js.map +1 -1
- package/dist/components/table/CsvPreview/CsvPreview.js +2 -3
- package/dist/components/table/CsvPreview/CsvPreview.js.map +1 -1
- package/dist/components/table/CsvPreview/CsvPreviewDialog.js +2 -3
- package/dist/components/table/CsvPreview/CsvPreviewDialog.js.map +1 -1
- package/dist/features/curator/GridPage/GridPage.js +2 -3
- package/dist/features/curator/GridPage/GridPage.js.map +1 -1
- package/dist/features/curator/GridPage/components/GridPageTitle.js +2 -3
- package/dist/features/curator/GridPage/components/GridPageTitle.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts +5 -2
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js +46 -33
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.js +52 -27
- package/dist/features/entity/metadata-task/components/MetadataTasksPage.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.d.ts +7 -0
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.d.ts.map +1 -0
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js +322 -0
- package/dist/features/entity/metadata-task/components/MetadataTasksTableAssigneeCell.js.map +1 -0
- package/dist/features/entity/metadata-task/hooks/useGetOrCreateGridSessionForSource.d.ts +7 -1
- package/dist/features/entity/metadata-task/hooks/useGetOrCreateGridSessionForSource.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGetOrCreateGridSessionForSource.js +7 -7
- package/dist/features/entity/metadata-task/hooks/useGetOrCreateGridSessionForSource.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.d.ts +9 -5
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.js +79 -16
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask_legacy.d.ts +12 -0
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask_legacy.d.ts.map +1 -0
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask_legacy.js +20 -0
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask_legacy.js.map +1 -0
- package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.d.ts +3 -3
- package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.js +54 -41
- package/dist/features/entity/metadata-task/hooks/useMetadataTaskTable.js.map +1 -1
- package/dist/features/entity/metadata-task/utils/getCreateGridRequestForMetadataTask.d.ts +2 -2
- package/dist/features/entity/metadata-task/utils/getCreateGridRequestForMetadataTask.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/utils/getCreateGridRequestForMetadataTask.js +11 -4
- package/dist/features/entity/metadata-task/utils/getCreateGridRequestForMetadataTask.js.map +1 -1
- package/dist/features/entity/metadata-task/utils/taskHasAssignee.d.ts +3 -0
- package/dist/features/entity/metadata-task/utils/taskHasAssignee.d.ts.map +1 -0
- package/dist/features/entity/metadata-task/utils/taskHasAssignee.js +7 -0
- package/dist/features/entity/metadata-task/utils/taskHasAssignee.js.map +1 -0
- package/dist/index.js +306 -304
- package/dist/index.js.map +1 -1
- package/dist/mocks/curation/mockCurationTask.d.ts +10 -0
- package/dist/mocks/curation/mockCurationTask.d.ts.map +1 -0
- package/dist/mocks/curation/mockCurationTask.js +24 -0
- package/dist/mocks/curation/mockCurationTask.js.map +1 -0
- package/dist/style/components/_data-grid-extra.css +1 -1
- package/dist/style/components/_data-grid-extra.scss +16 -0
- package/dist/synapse-client/SynapseClient.d.ts +1 -1
- package/dist/synapse-client/SynapseClient.d.ts.map +1 -1
- package/dist/synapse-client/SynapseClient.js +3 -2
- package/dist/synapse-client/SynapseClient.js.map +1 -1
- package/dist/synapse-queries/KeyFactory.d.ts +8 -3
- package/dist/synapse-queries/KeyFactory.d.ts.map +1 -1
- package/dist/synapse-queries/KeyFactory.js +22 -7
- package/dist/synapse-queries/KeyFactory.js.map +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.d.ts +6 -3
- package/dist/synapse-queries/curation/task/useCurationTask.d.ts.map +1 -1
- package/dist/synapse-queries/curation/task/useCurationTask.js +62 -18
- package/dist/synapse-queries/curation/task/useCurationTask.js.map +1 -1
- 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/grid/useGridSession.d.ts +17 -2
- package/dist/synapse-queries/grid/useGridSession.d.ts.map +1 -1
- package/dist/synapse-queries/grid/useGridSession.js +63 -30
- package/dist/synapse-queries/grid/useGridSession.js.map +1 -1
- package/dist/synapse-queries/index.js +103 -99
- package/dist/synapse-queries/team/index.js +18 -15
- package/dist/synapse-queries/team/useTeamMembers.d.ts +34 -0
- package/dist/synapse-queries/team/useTeamMembers.d.ts.map +1 -1
- package/dist/synapse-queries/team/useTeamMembers.js +110 -69
- package/dist/synapse-queries/team/useTeamMembers.js.map +1 -1
- package/dist/synapse-queries/types.d.ts +13 -0
- package/dist/synapse-queries/types.d.ts.map +1 -0
- package/dist/synapse-queries/types.js +2 -0
- package/dist/synapse-queries/types.js.map +1 -0
- package/dist/synapse-queries/user/index.js +12 -11
- package/dist/synapse-queries/user/useUserGroupHeader.d.ts +5 -0
- package/dist/synapse-queries/user/useUserGroupHeader.d.ts.map +1 -1
- package/dist/synapse-queries/user/useUserGroupHeader.js +28 -21
- package/dist/synapse-queries/user/useUserGroupHeader.js.map +1 -1
- package/dist/theme/palette/Palettes.d.ts +2 -0
- package/dist/theme/palette/Palettes.d.ts.map +1 -1
- package/dist/theme/palette/Palettes.js +46 -40
- package/dist/theme/palette/Palettes.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/hooks/useOverlay.d.ts +2 -2
- package/dist/utils/hooks/useOverlay.d.ts.map +1 -1
- package/dist/utils/hooks/useOverlay.js +41 -41
- package/dist/utils/hooks/useOverlay.js.map +1 -1
- package/package.json +4 -4
- package/dist/assets/ArcusBioIcon.svg +0 -1
- package/dist/assets/ArcusBioIcon.svg.js +0 -7
- package/dist/assets/ArcusBioIcon.svg.js.map +0 -1
|
@@ -1,16 +1,16 @@
|
|
|
1
|
-
import { jsx as
|
|
2
|
-
import { modelColsToGrid as
|
|
3
|
-
import
|
|
4
|
-
import { useState as h, useEffect as
|
|
5
|
-
import { DynamicDataSheetGrid as
|
|
1
|
+
import { jsx as D } from "react/jsx-runtime";
|
|
2
|
+
import { modelColsToGrid as B } from "./utils/modelColsToGrid.js";
|
|
3
|
+
import H from "classnames";
|
|
4
|
+
import { useState as h, useEffect as q, useCallback as s, useMemo as f, useRef as E } from "react";
|
|
5
|
+
import { DynamicDataSheetGrid as F } from "@sage-bionetworks/react-datasheet-grid";
|
|
6
6
|
import "@sage-bionetworks/react-datasheet-grid/dist/style.css";
|
|
7
7
|
import '../../style/components/_data-grid-extra.css';/* empty css */
|
|
8
|
-
import { renderViewContextMenu as
|
|
9
|
-
import { GRID_ROW_REACT_KEY_PROPERTY as
|
|
10
|
-
import { getCellClassName as
|
|
11
|
-
import { useColumnResizeHandles as
|
|
12
|
-
import { calculateDefaultColumnWidth as
|
|
13
|
-
function
|
|
8
|
+
import { renderViewContextMenu as J, renderRecordSetContextMenu as L, renderAddRowsComponent as Q } from "./components/contextMenu.js";
|
|
9
|
+
import { GRID_ROW_REACT_KEY_PROPERTY as X } from "./utils/DataGridUtils.js";
|
|
10
|
+
import { getCellClassName as Z } from "./utils/getCellClassName.js";
|
|
11
|
+
import { useColumnResizeHandles as $ } from "./hooks/useColumnResizeHandles.js";
|
|
12
|
+
import { calculateDefaultColumnWidth as ee } from "./utils/calculateColumnWidth.js";
|
|
13
|
+
function fe(N) {
|
|
14
14
|
const {
|
|
15
15
|
gridRef: a,
|
|
16
16
|
rowValues: C,
|
|
@@ -20,134 +20,136 @@ function me(E) {
|
|
|
20
20
|
entityIsView: i,
|
|
21
21
|
jsonSchema: d,
|
|
22
22
|
lastSelection: R,
|
|
23
|
-
handleChange:
|
|
24
|
-
handleSelectionChange:
|
|
25
|
-
onSelectedRowChange: p
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
23
|
+
handleChange: W,
|
|
24
|
+
handleSelectionChange: x,
|
|
25
|
+
onSelectedRowChange: p,
|
|
26
|
+
remoteSelections: S
|
|
27
|
+
} = N, [g, v] = h({}), [_, z] = h(!1);
|
|
28
|
+
q(() => {
|
|
29
|
+
!r || !o || v((e) => {
|
|
29
30
|
const n = o.map((l) => r[l]);
|
|
30
31
|
if (!n.some((l) => !e[l]))
|
|
31
32
|
return e;
|
|
32
33
|
const w = { ...e };
|
|
33
|
-
return n.forEach((l,
|
|
34
|
+
return n.forEach((l, U) => {
|
|
34
35
|
if (!w[l]) {
|
|
35
|
-
const
|
|
36
|
-
showPinIcon:
|
|
37
|
-
hasDescription: !!
|
|
36
|
+
const A = c[l], Y = {
|
|
37
|
+
showPinIcon: U === 0,
|
|
38
|
+
hasDescription: !!A?.description
|
|
38
39
|
};
|
|
39
|
-
w[l] =
|
|
40
|
+
w[l] = ee(
|
|
40
41
|
l,
|
|
41
|
-
|
|
42
|
-
|
|
42
|
+
A,
|
|
43
|
+
Y
|
|
43
44
|
);
|
|
44
45
|
}
|
|
45
46
|
}), w;
|
|
46
47
|
});
|
|
47
48
|
}, [r, o, c]);
|
|
48
|
-
const
|
|
49
|
+
const P = s(
|
|
49
50
|
(e) => {
|
|
50
|
-
typeof e != "number" || e < 0 || !o || e >= o.length || e === 0 &&
|
|
51
|
+
typeof e != "number" || e < 0 || !o || e >= o.length || e === 0 && z((n) => !n);
|
|
51
52
|
},
|
|
52
53
|
[o]
|
|
53
|
-
),
|
|
54
|
-
() =>
|
|
54
|
+
), b = f(() => _ ? /* @__PURE__ */ new Set([0]) : /* @__PURE__ */ new Set(), [_]), u = f(
|
|
55
|
+
() => B(
|
|
55
56
|
r,
|
|
56
57
|
o,
|
|
57
58
|
c,
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
g,
|
|
60
|
+
b,
|
|
61
|
+
P
|
|
61
62
|
),
|
|
62
63
|
[
|
|
63
64
|
r,
|
|
64
65
|
o,
|
|
65
66
|
c,
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
67
|
+
g,
|
|
68
|
+
b,
|
|
69
|
+
P
|
|
69
70
|
]
|
|
70
|
-
), [m,
|
|
71
|
-
() => i ?
|
|
71
|
+
), [m, y] = h(null), G = f(
|
|
72
|
+
() => i ? J : L,
|
|
72
73
|
[i]
|
|
73
|
-
),
|
|
74
|
-
() => i ? !1 :
|
|
74
|
+
), M = f(
|
|
75
|
+
() => i ? !1 : Q,
|
|
75
76
|
[i]
|
|
76
|
-
),
|
|
77
|
-
({ rowData: e, rowIndex: n }) =>
|
|
77
|
+
), O = s(
|
|
78
|
+
({ rowData: e, rowIndex: n }) => H({
|
|
78
79
|
"row-valid": !!d && e.__validationStatus === "valid",
|
|
79
80
|
"row-invalid": !!d && e.__validationStatus === "invalid",
|
|
80
81
|
"row-unknown": !!d && e.__validationStatus === "pending",
|
|
81
82
|
"row-selected": m === n
|
|
82
83
|
}),
|
|
83
84
|
[d, m]
|
|
84
|
-
),
|
|
85
|
+
), T = s(
|
|
85
86
|
({
|
|
86
87
|
rowData: e,
|
|
87
88
|
rowIndex: n,
|
|
88
89
|
columnId: t
|
|
89
|
-
}) =>
|
|
90
|
+
}) => Z({
|
|
90
91
|
rowData: e,
|
|
91
92
|
rowIndex: n,
|
|
92
93
|
columnId: t || "",
|
|
93
94
|
selectedRowIndex: m,
|
|
94
95
|
lastSelection: R,
|
|
95
|
-
colValues: u
|
|
96
|
+
colValues: u,
|
|
97
|
+
remoteSelections: S
|
|
96
98
|
}),
|
|
97
|
-
[m, R, u]
|
|
98
|
-
),
|
|
99
|
+
[m, R, u, S]
|
|
100
|
+
), V = s(
|
|
99
101
|
({ rowData: e }) => ({
|
|
100
102
|
...e
|
|
101
103
|
}),
|
|
102
104
|
[]
|
|
103
|
-
),
|
|
105
|
+
), j = s(
|
|
104
106
|
({ cell: e }) => {
|
|
105
|
-
e ? (
|
|
107
|
+
e ? (y(e.row), p?.(e.row, C[e.row])) : (y(null), p?.(null, null));
|
|
106
108
|
},
|
|
107
109
|
[p, C]
|
|
108
|
-
),
|
|
110
|
+
), I = E(null), k = E(
|
|
109
111
|
null
|
|
110
|
-
),
|
|
112
|
+
), K = s(
|
|
111
113
|
(e, n) => {
|
|
112
114
|
if (a.current) {
|
|
113
115
|
const t = a.current.activeCell;
|
|
114
|
-
t ?
|
|
116
|
+
t ? k.current = {
|
|
115
117
|
col: t.col,
|
|
116
118
|
row: t.row
|
|
117
|
-
} :
|
|
119
|
+
} : k.current = null;
|
|
118
120
|
}
|
|
119
|
-
|
|
121
|
+
v((t) => ({
|
|
120
122
|
...t,
|
|
121
123
|
[e]: n
|
|
122
124
|
}));
|
|
123
125
|
},
|
|
124
126
|
[a]
|
|
125
127
|
);
|
|
126
|
-
return
|
|
127
|
-
wrapperRef:
|
|
128
|
+
return $({
|
|
129
|
+
wrapperRef: I,
|
|
128
130
|
colValues: u,
|
|
129
|
-
onColumnResize:
|
|
130
|
-
}), /* @__PURE__ */
|
|
131
|
-
|
|
131
|
+
onColumnResize: K
|
|
132
|
+
}), /* @__PURE__ */ D("div", { ref: I, style: { position: "relative", width: "100%" }, children: /* @__PURE__ */ D(
|
|
133
|
+
F,
|
|
132
134
|
{
|
|
133
135
|
ref: a,
|
|
134
136
|
value: C,
|
|
135
137
|
columns: u,
|
|
136
138
|
autoAddRow: !i,
|
|
137
139
|
disableSmartDelete: !0,
|
|
138
|
-
addRowsComponent:
|
|
139
|
-
contextMenuComponent:
|
|
140
|
-
rowKey:
|
|
141
|
-
rowClassName:
|
|
142
|
-
cellClassName:
|
|
143
|
-
duplicateRow:
|
|
144
|
-
onChange:
|
|
145
|
-
onActiveCellChange:
|
|
146
|
-
onSelectionChange:
|
|
140
|
+
addRowsComponent: M,
|
|
141
|
+
contextMenuComponent: G,
|
|
142
|
+
rowKey: X,
|
|
143
|
+
rowClassName: O,
|
|
144
|
+
cellClassName: T,
|
|
145
|
+
duplicateRow: V,
|
|
146
|
+
onChange: W,
|
|
147
|
+
onActiveCellChange: j,
|
|
148
|
+
onSelectionChange: x
|
|
147
149
|
}
|
|
148
150
|
) });
|
|
149
151
|
}
|
|
150
152
|
export {
|
|
151
|
-
|
|
153
|
+
fe as default
|
|
152
154
|
};
|
|
153
155
|
//# sourceMappingURL=DataGrid.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataGrid.js","sources":["../../../src/components/DataGrid/DataGrid.tsx"],"sourcesContent":["import { modelColsToGrid } from '@/components/DataGrid/utils/modelColsToGrid'\nimport { SchemaPropertiesMap } from '@/utils/jsonschema/getSchemaPropertyInfo'\nimport classNames from 'classnames'\nimport { JSONSchema7 } from 'json-schema'\nimport { useEffect, useMemo, useState, useRef, useCallback } from 'react'\nimport {\n DynamicDataSheetGrid,\n DataSheetGridRef,\n} from '@sage-bionetworks/react-datasheet-grid'\nimport '@sage-bionetworks/react-datasheet-grid/dist/style.css'\nimport '../../style/components/_data-grid-extra.scss'\nimport { SelectionWithId } from '@sage-bionetworks/react-datasheet-grid'\nimport {\n renderAddRowsComponent,\n renderRecordSetContextMenu,\n renderViewContextMenu,\n} from './components/contextMenu'\nimport { DataGridRow, Operation } from './DataGridTypes'\nimport { GRID_ROW_REACT_KEY_PROPERTY } from './utils/DataGridUtils'\nimport { getCellClassName } from './utils/getCellClassName'\nimport { useColumnResizeHandles } from './hooks/useColumnResizeHandles'\nimport {\n calculateDefaultColumnWidth,\n HeaderOptions,\n} from './utils/calculateColumnWidth'\n\ntype DataGridProps = {\n gridRef: React.RefObject<DataSheetGridRef | null>\n columnNames: string[]\n columnOrder: number[]\n schemaPropertiesInfo: SchemaPropertiesMap\n rowValues: DataGridRow[]\n entityIsView: boolean\n jsonSchema: JSONSchema7 | undefined\n lastSelection: SelectionWithId | null\n handleChange: (newValue: DataGridRow[], operations: Operation[]) => void\n handleSelectionChange: (opts: { selection: SelectionWithId | null }) => void\n onSelectedRowChange?: (\n rowIndex: number | null,\n row: DataGridRow | null,\n ) => void\n}\n\n/**\n * Component that renders a data grid/spreadsheet using react-datasheet-grid.\n * @param props\n * @constructor\n */\nexport default function DataGrid(props: DataGridProps) {\n const {\n gridRef,\n rowValues,\n columnNames,\n columnOrder,\n schemaPropertiesInfo,\n entityIsView,\n jsonSchema,\n lastSelection,\n handleChange,\n handleSelectionChange,\n onSelectedRowChange,\n } = props\n\n // Move columnWidths state into DataGrid\n const [columnWidths, setColumnWidths] = useState<Record<string, number>>({})\n\n // Pin state management for first column\n const [isPinned, setIsPinned] = useState(false)\n\n // Initialize column widths with defaults when columns first become available\n useEffect(() => {\n if (!columnNames || !columnOrder) {\n return\n }\n\n // Initialize widths for any columns that don't have them yet\n setColumnWidths(prev => {\n const modelColumnNames = columnOrder.map(idx => columnNames[idx])\n\n // Check if any columns need initialization\n const needsUpdate = modelColumnNames.some(name => !prev[name])\n\n if (!needsUpdate) {\n return prev // Return same reference to avoid triggering updates\n }\n\n const newWidths = { ...prev }\n modelColumnNames.forEach((columnName, arrayIndex) => {\n if (!newWidths[columnName]) {\n // Calculate default width using centralized function\n const propertyInfo = schemaPropertiesInfo[columnName]\n const headerOptions: HeaderOptions = {\n showPinIcon: arrayIndex === 0,\n hasDescription: !!propertyInfo?.description,\n }\n newWidths[columnName] = calculateDefaultColumnWidth(\n columnName,\n propertyInfo,\n headerOptions,\n )\n }\n })\n return newWidths\n })\n }, [columnNames, columnOrder, schemaPropertiesInfo])\n\n // Handler to toggle pin state for the first column only\n const handleTogglePin = useCallback(\n (columnIndex: number) => {\n // Validate columnIndex\n if (\n typeof columnIndex !== 'number' ||\n columnIndex < 0 ||\n !columnOrder ||\n columnIndex >= columnOrder.length\n ) {\n return\n }\n\n if (columnIndex !== 0) return // Only allow first column pinning\n\n setIsPinned(prev => !prev)\n },\n [columnOrder],\n )\n\n // Memoize the pinned columns set to prevent recalculation during scroll\n const pinnedColumnsSet = useMemo<Set<number>>(() => {\n return isPinned ? new Set([0]) : new Set()\n }, [isPinned])\n\n const colValues = useMemo(\n () =>\n modelColsToGrid(\n columnNames,\n columnOrder,\n schemaPropertiesInfo,\n columnWidths,\n pinnedColumnsSet,\n handleTogglePin,\n ),\n [\n columnNames,\n columnOrder,\n schemaPropertiesInfo,\n columnWidths,\n pinnedColumnsSet,\n handleTogglePin,\n ],\n )\n const [selectedRowIndex, setSelectedRowIndex] = useState<number | null>(null)\n\n // Memoize contextMenuComponent\n const contextMenuComponent = useMemo(\n () => (entityIsView ? renderViewContextMenu : renderRecordSetContextMenu),\n [entityIsView],\n )\n\n // Memoize addRowsComponent\n const addRowsComponent = useMemo(\n () => (entityIsView ? false : renderAddRowsComponent),\n [entityIsView],\n )\n\n // Wrap rowClassName in useCallback\n const rowClassNameCallback = useCallback(\n ({ rowData, rowIndex }: { rowData: DataGridRow; rowIndex: number }) =>\n classNames({\n 'row-valid': !!jsonSchema && rowData.__validationStatus === 'valid',\n 'row-invalid': !!jsonSchema && rowData.__validationStatus === 'invalid',\n 'row-unknown': !!jsonSchema && rowData.__validationStatus === 'pending',\n 'row-selected': selectedRowIndex === rowIndex,\n }),\n [jsonSchema, selectedRowIndex],\n )\n\n // Wrap cellClassName in useCallback\n const cellClassNameCallback = useCallback(\n ({\n rowData,\n rowIndex,\n columnId,\n }: {\n rowData: unknown\n rowIndex: number\n columnId?: string\n }) => {\n return getCellClassName({\n rowData: rowData as DataGridRow,\n rowIndex,\n columnId: columnId || '',\n selectedRowIndex,\n lastSelection,\n colValues,\n })\n },\n [selectedRowIndex, lastSelection, colValues],\n )\n\n // Wrap duplicateRow in useCallback\n const duplicateRowCallback = useCallback(\n ({ rowData }: { rowData: DataGridRow }) => ({\n ...rowData,\n }),\n [],\n )\n\n // Wrap onActiveCellChange in useCallback\n const handleActiveCellChange = useCallback(\n ({ cell }: { cell: { row: number; col: number } | null }) => {\n if (cell) {\n setSelectedRowIndex(cell.row)\n onSelectedRowChange?.(cell.row, rowValues[cell.row])\n } else {\n setSelectedRowIndex(null)\n onSelectedRowChange?.(null, null)\n }\n },\n [onSelectedRowChange, rowValues],\n )\n\n // Wrapper ref for the grid container\n const wrapperRef = useRef<HTMLDivElement | null>(null)\n\n // Store the active cell before column resize so we can restore it\n const activeCellBeforeResizeRef = useRef<{ col: number; row: number } | null>(\n null,\n )\n\n // Handle column resize callback\n const handleColumnResize = useCallback(\n (columnName: string, newWidth: number) => {\n // Save the current active cell before updating widths (which will trigger remount)\n if (gridRef.current) {\n const activeCell = gridRef.current.activeCell\n if (activeCell) {\n activeCellBeforeResizeRef.current = {\n col: activeCell.col,\n row: activeCell.row,\n }\n } else {\n // Explicitly clear the ref if there's no active cell\n activeCellBeforeResizeRef.current = null\n }\n }\n\n setColumnWidths(prev => ({\n ...prev,\n [columnName]: newWidth,\n }))\n },\n [gridRef],\n )\n\n // Setup column resize handles\n useColumnResizeHandles({\n wrapperRef,\n colValues,\n onColumnResize: handleColumnResize,\n })\n\n return (\n <div ref={wrapperRef} style={{ position: 'relative', width: '100%' }}>\n <DynamicDataSheetGrid\n ref={gridRef}\n value={rowValues}\n columns={colValues}\n autoAddRow={!entityIsView}\n disableSmartDelete\n addRowsComponent={addRowsComponent}\n contextMenuComponent={contextMenuComponent}\n rowKey={GRID_ROW_REACT_KEY_PROPERTY}\n rowClassName={rowClassNameCallback}\n cellClassName={cellClassNameCallback}\n duplicateRow={duplicateRowCallback}\n onChange={handleChange}\n onActiveCellChange={handleActiveCellChange}\n onSelectionChange={handleSelectionChange}\n />\n </div>\n )\n}\n"],"names":["DataGrid","props","gridRef","rowValues","columnNames","columnOrder","schemaPropertiesInfo","entityIsView","jsonSchema","lastSelection","handleChange","handleSelectionChange","onSelectedRowChange","columnWidths","setColumnWidths","useState","isPinned","setIsPinned","useEffect","prev","modelColumnNames","idx","name","newWidths","columnName","arrayIndex","propertyInfo","headerOptions","calculateDefaultColumnWidth","handleTogglePin","useCallback","columnIndex","pinnedColumnsSet","useMemo","colValues","modelColsToGrid","selectedRowIndex","setSelectedRowIndex","contextMenuComponent","renderViewContextMenu","renderRecordSetContextMenu","addRowsComponent","renderAddRowsComponent","rowClassNameCallback","rowData","rowIndex","classNames","cellClassNameCallback","columnId","getCellClassName","duplicateRowCallback","handleActiveCellChange","cell","wrapperRef","useRef","activeCellBeforeResizeRef","handleColumnResize","newWidth","activeCell","useColumnResizeHandles","jsx","DynamicDataSheetGrid","GRID_ROW_REACT_KEY_PROPERTY"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataGrid.js","sources":["../../../src/components/DataGrid/DataGrid.tsx"],"sourcesContent":["import { modelColsToGrid } from '@/components/DataGrid/utils/modelColsToGrid'\nimport { SchemaPropertiesMap } from '@/utils/jsonschema/getSchemaPropertyInfo'\nimport classNames from 'classnames'\nimport { JSONSchema7 } from 'json-schema'\nimport { useEffect, useMemo, useState, useRef, useCallback } from 'react'\nimport {\n DynamicDataSheetGrid,\n DataSheetGridRef,\n} from '@sage-bionetworks/react-datasheet-grid'\nimport '@sage-bionetworks/react-datasheet-grid/dist/style.css'\nimport '../../style/components/_data-grid-extra.scss'\nimport { SelectionWithId } from '@sage-bionetworks/react-datasheet-grid'\nimport {\n renderAddRowsComponent,\n renderRecordSetContextMenu,\n renderViewContextMenu,\n} from './components/contextMenu'\nimport { DataGridRow, Operation } from './DataGridTypes'\nimport { GRID_ROW_REACT_KEY_PROPERTY } from './utils/DataGridUtils'\nimport { getCellClassName } from './utils/getCellClassName'\nimport { useColumnResizeHandles } from './hooks/useColumnResizeHandles'\nimport {\n calculateDefaultColumnWidth,\n HeaderOptions,\n} from './utils/calculateColumnWidth'\nimport type { RemoteSelection } from './hooks/useRemoteSelections'\n\ntype DataGridProps = {\n gridRef: React.RefObject<DataSheetGridRef | null>\n columnNames: string[]\n columnOrder: number[]\n schemaPropertiesInfo: SchemaPropertiesMap\n rowValues: DataGridRow[]\n entityIsView: boolean\n jsonSchema: JSONSchema7 | undefined\n lastSelection: SelectionWithId | null\n handleChange: (newValue: DataGridRow[], operations: Operation[]) => void\n handleSelectionChange: (opts: { selection: SelectionWithId | null }) => void\n onSelectedRowChange?: (\n rowIndex: number | null,\n row: DataGridRow | null,\n ) => void\n remoteSelections?: readonly RemoteSelection[]\n}\n\n/**\n * Component that renders a data grid/spreadsheet using react-datasheet-grid.\n * @param props\n * @constructor\n */\nexport default function DataGrid(props: DataGridProps) {\n const {\n gridRef,\n rowValues,\n columnNames,\n columnOrder,\n schemaPropertiesInfo,\n entityIsView,\n jsonSchema,\n lastSelection,\n handleChange,\n handleSelectionChange,\n onSelectedRowChange,\n remoteSelections,\n } = props\n\n // Move columnWidths state into DataGrid\n const [columnWidths, setColumnWidths] = useState<Record<string, number>>({})\n\n // Pin state management for first column\n const [isPinned, setIsPinned] = useState(false)\n\n // Initialize column widths with defaults when columns first become available\n useEffect(() => {\n if (!columnNames || !columnOrder) {\n return\n }\n\n // Initialize widths for any columns that don't have them yet\n setColumnWidths(prev => {\n const modelColumnNames = columnOrder.map(idx => columnNames[idx])\n\n // Check if any columns need initialization\n const needsUpdate = modelColumnNames.some(name => !prev[name])\n\n if (!needsUpdate) {\n return prev // Return same reference to avoid triggering updates\n }\n\n const newWidths = { ...prev }\n modelColumnNames.forEach((columnName, arrayIndex) => {\n if (!newWidths[columnName]) {\n // Calculate default width using centralized function\n const propertyInfo = schemaPropertiesInfo[columnName]\n const headerOptions: HeaderOptions = {\n showPinIcon: arrayIndex === 0,\n hasDescription: !!propertyInfo?.description,\n }\n newWidths[columnName] = calculateDefaultColumnWidth(\n columnName,\n propertyInfo,\n headerOptions,\n )\n }\n })\n return newWidths\n })\n }, [columnNames, columnOrder, schemaPropertiesInfo])\n\n // Handler to toggle pin state for the first column only\n const handleTogglePin = useCallback(\n (columnIndex: number) => {\n // Validate columnIndex\n if (\n typeof columnIndex !== 'number' ||\n columnIndex < 0 ||\n !columnOrder ||\n columnIndex >= columnOrder.length\n ) {\n return\n }\n\n if (columnIndex !== 0) return // Only allow first column pinning\n\n setIsPinned(prev => !prev)\n },\n [columnOrder],\n )\n\n // Memoize the pinned columns set to prevent recalculation during scroll\n const pinnedColumnsSet = useMemo<Set<number>>(() => {\n return isPinned ? new Set([0]) : new Set()\n }, [isPinned])\n\n const colValues = useMemo(\n () =>\n modelColsToGrid(\n columnNames,\n columnOrder,\n schemaPropertiesInfo,\n columnWidths,\n pinnedColumnsSet,\n handleTogglePin,\n ),\n [\n columnNames,\n columnOrder,\n schemaPropertiesInfo,\n columnWidths,\n pinnedColumnsSet,\n handleTogglePin,\n ],\n )\n const [selectedRowIndex, setSelectedRowIndex] = useState<number | null>(null)\n\n // Memoize contextMenuComponent\n const contextMenuComponent = useMemo(\n () => (entityIsView ? renderViewContextMenu : renderRecordSetContextMenu),\n [entityIsView],\n )\n\n // Memoize addRowsComponent\n const addRowsComponent = useMemo(\n () => (entityIsView ? false : renderAddRowsComponent),\n [entityIsView],\n )\n\n // Wrap rowClassName in useCallback\n const rowClassNameCallback = useCallback(\n ({ rowData, rowIndex }: { rowData: DataGridRow; rowIndex: number }) =>\n classNames({\n 'row-valid': !!jsonSchema && rowData.__validationStatus === 'valid',\n 'row-invalid': !!jsonSchema && rowData.__validationStatus === 'invalid',\n 'row-unknown': !!jsonSchema && rowData.__validationStatus === 'pending',\n 'row-selected': selectedRowIndex === rowIndex,\n }),\n [jsonSchema, selectedRowIndex],\n )\n\n // Wrap cellClassName in useCallback\n const cellClassNameCallback = useCallback(\n ({\n rowData,\n rowIndex,\n columnId,\n }: {\n rowData: unknown\n rowIndex: number\n columnId?: string\n }) => {\n return getCellClassName({\n rowData: rowData as DataGridRow,\n rowIndex,\n columnId: columnId || '',\n selectedRowIndex,\n lastSelection,\n colValues,\n remoteSelections,\n })\n },\n [selectedRowIndex, lastSelection, colValues, remoteSelections],\n )\n\n // Wrap duplicateRow in useCallback\n const duplicateRowCallback = useCallback(\n ({ rowData }: { rowData: DataGridRow }) => ({\n ...rowData,\n }),\n [],\n )\n\n // Wrap onActiveCellChange in useCallback\n const handleActiveCellChange = useCallback(\n ({ cell }: { cell: { row: number; col: number } | null }) => {\n if (cell) {\n setSelectedRowIndex(cell.row)\n onSelectedRowChange?.(cell.row, rowValues[cell.row])\n } else {\n setSelectedRowIndex(null)\n onSelectedRowChange?.(null, null)\n }\n },\n [onSelectedRowChange, rowValues],\n )\n\n // Wrapper ref for the grid container\n const wrapperRef = useRef<HTMLDivElement | null>(null)\n\n // Store the active cell before column resize so we can restore it\n const activeCellBeforeResizeRef = useRef<{ col: number; row: number } | null>(\n null,\n )\n\n // Handle column resize callback\n const handleColumnResize = useCallback(\n (columnName: string, newWidth: number) => {\n // Save the current active cell before updating widths (which will trigger remount)\n if (gridRef.current) {\n const activeCell = gridRef.current.activeCell\n if (activeCell) {\n activeCellBeforeResizeRef.current = {\n col: activeCell.col,\n row: activeCell.row,\n }\n } else {\n // Explicitly clear the ref if there's no active cell\n activeCellBeforeResizeRef.current = null\n }\n }\n\n setColumnWidths(prev => ({\n ...prev,\n [columnName]: newWidth,\n }))\n },\n [gridRef],\n )\n\n // Setup column resize handles\n useColumnResizeHandles({\n wrapperRef,\n colValues,\n onColumnResize: handleColumnResize,\n })\n\n return (\n <div ref={wrapperRef} style={{ position: 'relative', width: '100%' }}>\n <DynamicDataSheetGrid\n ref={gridRef}\n value={rowValues}\n columns={colValues}\n autoAddRow={!entityIsView}\n disableSmartDelete\n addRowsComponent={addRowsComponent}\n contextMenuComponent={contextMenuComponent}\n rowKey={GRID_ROW_REACT_KEY_PROPERTY}\n rowClassName={rowClassNameCallback}\n cellClassName={cellClassNameCallback}\n duplicateRow={duplicateRowCallback}\n onChange={handleChange}\n onActiveCellChange={handleActiveCellChange}\n onSelectionChange={handleSelectionChange}\n />\n </div>\n )\n}\n"],"names":["DataGrid","props","gridRef","rowValues","columnNames","columnOrder","schemaPropertiesInfo","entityIsView","jsonSchema","lastSelection","handleChange","handleSelectionChange","onSelectedRowChange","remoteSelections","columnWidths","setColumnWidths","useState","isPinned","setIsPinned","useEffect","prev","modelColumnNames","idx","name","newWidths","columnName","arrayIndex","propertyInfo","headerOptions","calculateDefaultColumnWidth","handleTogglePin","useCallback","columnIndex","pinnedColumnsSet","useMemo","colValues","modelColsToGrid","selectedRowIndex","setSelectedRowIndex","contextMenuComponent","renderViewContextMenu","renderRecordSetContextMenu","addRowsComponent","renderAddRowsComponent","rowClassNameCallback","rowData","rowIndex","classNames","cellClassNameCallback","columnId","getCellClassName","duplicateRowCallback","handleActiveCellChange","cell","wrapperRef","useRef","activeCellBeforeResizeRef","handleColumnResize","newWidth","activeCell","useColumnResizeHandles","jsx","DynamicDataSheetGrid","GRID_ROW_REACT_KEY_PROPERTY"],"mappings":"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"}
|
|
@@ -5,6 +5,8 @@ type DataGridWebSocketConstructorArgs = {
|
|
|
5
5
|
onGridReady?: () => void;
|
|
6
6
|
onStatusChange?: (isOpen: boolean, instance: DataGridWebSocket) => void;
|
|
7
7
|
onModelCreate?: (model: GridModel) => void;
|
|
8
|
+
onReplicaConnected?: () => void;
|
|
9
|
+
onReplicaDisconnected?: () => void;
|
|
8
10
|
maxPayloadSizeBytes?: number;
|
|
9
11
|
socket?: WebSocket;
|
|
10
12
|
model?: GridModel | null;
|
|
@@ -22,6 +24,8 @@ export declare class DataGridWebSocket {
|
|
|
22
24
|
private onModelCreate;
|
|
23
25
|
private onGridReady;
|
|
24
26
|
private onStatusChange;
|
|
27
|
+
private onReplicaConnected;
|
|
28
|
+
private onReplicaDisconnected;
|
|
25
29
|
constructor(args: DataGridWebSocketConstructorArgs);
|
|
26
30
|
private attachSocketHandlers;
|
|
27
31
|
disconnect(): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataGridWebSocket.d.ts","sourceRoot":"","sources":["../../../src/components/DataGrid/DataGridWebSocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAyC/D,KAAK,gCAAgC,GAAG;IACtC,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACvE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAA;IAC1C,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAA;AAQD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,mBAAmB,CAAQ;IACnC,OAAO,CAAC,kBAAkB,CAA2B;IACrD,OAAO,CAAC,eAAe,CAAwB;IAE/C,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,cAAc,CAAqD;
|
|
1
|
+
{"version":3,"file":"DataGridWebSocket.d.ts","sourceRoot":"","sources":["../../../src/components/DataGrid/DataGridWebSocket.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,qCAAqC,CAAA;AAyC/D,KAAK,gCAAgC,GAAG;IACtC,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACvE,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK,IAAI,CAAA;IAC1C,kBAAkB,CAAC,EAAE,MAAM,IAAI,CAAA;IAC/B,qBAAqB,CAAC,EAAE,MAAM,IAAI,CAAA;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,MAAM,CAAC,EAAE,SAAS,CAAA;IAClB,KAAK,CAAC,EAAE,SAAS,GAAG,IAAI,CAAA;IACxB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB,CAAA;AAQD,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,KAAK,CAAyB;IACtC,OAAO,CAAC,cAAc,CAAgB;IACtC,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,cAAc,CAAuB;IAC7C,OAAO,CAAC,mBAAmB,CAAQ;IACnC,OAAO,CAAC,kBAAkB,CAA2B;IACrD,OAAO,CAAC,eAAe,CAAwB;IAE/C,OAAO,CAAC,aAAa,CAA4B;IACjD,OAAO,CAAC,WAAW,CAAY;IAC/B,OAAO,CAAC,cAAc,CAAqD;IAC3E,OAAO,CAAC,kBAAkB,CAAY;IACtC,OAAO,CAAC,qBAAqB,CAAY;gBAE7B,IAAI,EAAE,gCAAgC;IAyClD,OAAO,CAAC,oBAAoB;IAwBrB,UAAU;IAWjB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAcrB,OAAO,CAAC,aAAa;IAerB,OAAO,CAAC,cAAc;IAwBtB,OAAO,CAAC,kBAAkB;YAiBZ,qBAAqB;IAYnC,OAAO,CAAC,sBAAsB;IAQ9B,OAAO,CAAC,kBAAkB;IAuD1B,OAAO,CAAC,WAAW;IAWZ,SAAS;IAIhB;;OAEG;IACH,OAAO,CAAC,kBAAkB;IA0B1B,OAAO,CAAC,eAAe;YAST,sBAAsB;CAYrC"}
|
|
@@ -1,46 +1,50 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
import { splitPatch as
|
|
8
|
-
import { Model as
|
|
9
|
-
import { decode as
|
|
10
|
-
import { Encoder as
|
|
11
|
-
import
|
|
12
|
-
import
|
|
13
|
-
import { Decoder as
|
|
14
|
-
import { decode as
|
|
15
|
-
import { fetchWithExponentialTimeout as
|
|
16
|
-
const
|
|
17
|
-
class
|
|
1
|
+
import f from "./utils/json-rx/JsonRx.js";
|
|
2
|
+
import g from "./utils/json-rx/JsonRxNotification.js";
|
|
3
|
+
import c from "./utils/json-rx/JsonRxRequestComplete.js";
|
|
4
|
+
import b from "./utils/json-rx/JsonRxResponse.js";
|
|
5
|
+
import y from "./utils/json-rx/JsonRxResponseComplete.js";
|
|
6
|
+
import k from "./utils/MessageCounter.js";
|
|
7
|
+
import { splitPatch as S } from "./utils/splitPatch.js";
|
|
8
|
+
import { Model as u } from "json-joy/lib/json-crdt";
|
|
9
|
+
import { decode as C } from "json-joy/lib/json-crdt-patch/codec/compact";
|
|
10
|
+
import { Encoder as R } from "json-joy/lib/json-crdt/codec/structural/verbose/Encoder";
|
|
11
|
+
import a from "lodash-es/noop";
|
|
12
|
+
import M from "lodash-es/throttle";
|
|
13
|
+
import { Decoder as P } from "json-joy/lib/json-crdt/codec/indexed/binary/Decoder";
|
|
14
|
+
import { decode as w } from "cbor2";
|
|
15
|
+
import { fetchWithExponentialTimeout as v } from "@sage-bionetworks/synapse-client";
|
|
16
|
+
const x = 30 * 1024, D = 250;
|
|
17
|
+
class q {
|
|
18
18
|
socket;
|
|
19
19
|
model = null;
|
|
20
20
|
messageCounter;
|
|
21
21
|
replicaId;
|
|
22
|
-
verboseEncoder = new
|
|
22
|
+
verboseEncoder = new R();
|
|
23
23
|
maxPayloadSizeBytes;
|
|
24
24
|
throttledSendPatch;
|
|
25
|
-
snapshotDecoder = new
|
|
25
|
+
snapshotDecoder = new P();
|
|
26
26
|
onModelCreate;
|
|
27
27
|
onGridReady;
|
|
28
28
|
onStatusChange;
|
|
29
|
+
onReplicaConnected;
|
|
30
|
+
onReplicaDisconnected;
|
|
29
31
|
constructor(o) {
|
|
30
32
|
const {
|
|
31
33
|
replicaId: e,
|
|
32
34
|
url: s,
|
|
33
35
|
onGridReady: t,
|
|
34
36
|
onStatusChange: n,
|
|
35
|
-
onModelCreate:
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
onModelCreate: i,
|
|
38
|
+
onReplicaConnected: d,
|
|
39
|
+
onReplicaDisconnected: h,
|
|
40
|
+
maxPayloadSizeBytes: l,
|
|
41
|
+
socket: m,
|
|
42
|
+
model: r,
|
|
43
|
+
patchThrottleMs: p
|
|
40
44
|
} = o;
|
|
41
|
-
this.messageCounter = new
|
|
45
|
+
this.messageCounter = new k(), this.replicaId = e, this.maxPayloadSizeBytes = l ?? x, this.socket = m ?? new WebSocket(s), this.onModelCreate = i ?? a, this.onGridReady = t ?? a, this.onStatusChange = n ?? a, this.onReplicaConnected = d ?? a, this.onReplicaDisconnected = h ?? a, r && (this.model = r), this.attachSocketHandlers(), this.throttledSendPatch = M(
|
|
42
46
|
() => this.sendPatchImmediate(),
|
|
43
|
-
|
|
47
|
+
p ?? D,
|
|
44
48
|
{ leading: !1, trailing: !0 }
|
|
45
49
|
);
|
|
46
50
|
}
|
|
@@ -73,10 +77,10 @@ class L {
|
|
|
73
77
|
}
|
|
74
78
|
}
|
|
75
79
|
handleMessage(o) {
|
|
76
|
-
const e =
|
|
77
|
-
e instanceof
|
|
80
|
+
const e = f.fromJson(JSON.parse(o));
|
|
81
|
+
e instanceof b ? this.handleResponse(
|
|
78
82
|
e
|
|
79
|
-
) : e instanceof
|
|
83
|
+
) : e instanceof y ? this.handleResponseComplete() : e instanceof g ? this.handleNotification(e) : console.warn("Unexpected WebSocket message format:", e);
|
|
80
84
|
}
|
|
81
85
|
handleResponse(o) {
|
|
82
86
|
const e = o.getPayload();
|
|
@@ -97,8 +101,8 @@ class L {
|
|
|
97
101
|
}
|
|
98
102
|
handlePatchPayload(o) {
|
|
99
103
|
try {
|
|
100
|
-
const e = o.map(
|
|
101
|
-
this.model ? this.model.applyBatch(e) : (this.model =
|
|
104
|
+
const e = o.map(C);
|
|
105
|
+
this.model ? this.model.applyBatch(e) : (this.model = u.fromPatches(e).fork(
|
|
102
106
|
this.replicaId
|
|
103
107
|
), this.onModelCreate(this.model)), this.sendClockSync();
|
|
104
108
|
} catch (e) {
|
|
@@ -143,7 +147,7 @@ class L {
|
|
|
143
147
|
{
|
|
144
148
|
const s = this.verboseEncoder.encode(this.model);
|
|
145
149
|
console.debug("New patch received, syncing data:", s.time);
|
|
146
|
-
const t = new
|
|
150
|
+
const t = new c(
|
|
147
151
|
this.messageCounter.getNext(),
|
|
148
152
|
"synchronize-clock",
|
|
149
153
|
s.time
|
|
@@ -151,6 +155,12 @@ class L {
|
|
|
151
155
|
this.sendMessage(t);
|
|
152
156
|
}
|
|
153
157
|
break;
|
|
158
|
+
case "replica-connected":
|
|
159
|
+
console.debug("A replica connected to the grid session"), this.onReplicaConnected();
|
|
160
|
+
break;
|
|
161
|
+
case "replica-disconnected":
|
|
162
|
+
console.debug("A replica disconnected from the grid session"), this.onReplicaDisconnected();
|
|
163
|
+
break;
|
|
154
164
|
default:
|
|
155
165
|
console.warn("Unknown notification method:", e);
|
|
156
166
|
break;
|
|
@@ -172,9 +182,9 @@ class L {
|
|
|
172
182
|
if (!this.model)
|
|
173
183
|
return console.warn("Model is not initialized. Cannot send patch."), !1;
|
|
174
184
|
const o = this.model.api.flush(), e = o.ops.length > 0;
|
|
175
|
-
return e &&
|
|
185
|
+
return e && S(o, this.maxPayloadSizeBytes).forEach((t) => {
|
|
176
186
|
console.debug("Sending patch to server:", t);
|
|
177
|
-
const n = new
|
|
187
|
+
const n = new c(
|
|
178
188
|
this.messageCounter.getNext(),
|
|
179
189
|
"patch",
|
|
180
190
|
t
|
|
@@ -183,7 +193,7 @@ class L {
|
|
|
183
193
|
}), e;
|
|
184
194
|
}
|
|
185
195
|
sendSyncMessage(o) {
|
|
186
|
-
const e = new
|
|
196
|
+
const e = new c(
|
|
187
197
|
this.messageCounter.getNext(),
|
|
188
198
|
"synchronize-clock",
|
|
189
199
|
o ?? []
|
|
@@ -191,13 +201,13 @@ class L {
|
|
|
191
201
|
this.sendMessage(e);
|
|
192
202
|
}
|
|
193
203
|
async fetchAndDecodeSnapshot(o) {
|
|
194
|
-
const t = await (await (await
|
|
204
|
+
const t = await (await (await v(o)).blob()).arrayBuffer(), n = w(new Uint8Array(t));
|
|
195
205
|
return this.snapshotDecoder.decode(
|
|
196
206
|
n
|
|
197
207
|
);
|
|
198
208
|
}
|
|
199
209
|
}
|
|
200
210
|
export {
|
|
201
|
-
|
|
211
|
+
q as DataGridWebSocket
|
|
202
212
|
};
|
|
203
213
|
//# sourceMappingURL=DataGridWebSocket.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataGridWebSocket.js","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 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\n constructor(args: DataGridWebSocketConstructorArgs) {\n const {\n replicaId,\n url,\n onGridReady,\n onStatusChange,\n onModelCreate,\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\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 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 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 const msg = new JsonRxRequestComplete(\n this.messageCounter.getNext(),\n 'synchronize-clock',\n verbModel.time,\n )\n this.sendMessage(msg)\n }\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.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"],"names":["DEFAULT_MAX_PAYLOAD_SIZE_BYTES","DEFAULT_PATCH_THROTTLE_MS","DataGridWebSocket","VerboseEncoder","SnapshotDecoder","args","replicaId","url","onGridReady","onStatusChange","onModelCreate","maxPayloadSizeBytes","socket","model","patchThrottleMs","MessageCounter","noop","throttle","event","error","verbModel","rawMessage","message","JsonRx","JsonRxResponse","JsonRxResponseComplete","JsonRxNotification","payload","encodedPatch","patches","decode","Model","err","snapshotUrl","decodedModel","methodName","msg","JsonRxRequestComplete","patch","hasOperationsToDispatch","splitPatch","compactEncodedPatch","clock","buffer","fetchWithExponentialTimeout","decodedFromCbor","decodeCbor"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"DataGridWebSocket.js","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 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\n constructor(args: DataGridWebSocketConstructorArgs) {\n const {\n replicaId,\n url,\n onGridReady,\n onStatusChange,\n onModelCreate,\n onReplicaConnected,\n onReplicaDisconnected,\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\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 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 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 const msg = new JsonRxRequestComplete(\n this.messageCounter.getNext(),\n 'synchronize-clock',\n verbModel.time,\n )\n this.sendMessage(msg)\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.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"],"names":["DEFAULT_MAX_PAYLOAD_SIZE_BYTES","DEFAULT_PATCH_THROTTLE_MS","DataGridWebSocket","VerboseEncoder","SnapshotDecoder","args","replicaId","url","onGridReady","onStatusChange","onModelCreate","onReplicaConnected","onReplicaDisconnected","maxPayloadSizeBytes","socket","model","patchThrottleMs","MessageCounter","noop","throttle","event","error","verbModel","rawMessage","message","JsonRx","JsonRxResponse","JsonRxResponseComplete","JsonRxNotification","payload","encodedPatch","patches","decode","Model","err","snapshotUrl","decodedModel","methodName","msg","JsonRxRequestComplete","patch","hasOperationsToDispatch","splitPatch","compactEncodedPatch","clock","buffer","fetchWithExponentialTimeout","decodedFromCbor","decodeCbor"],"mappings":";;;;;;;;;;;;;;;AA0DA,MAAMA,IAAiC,KAAK,MACtCC,IAA4B;AAE3B,MAAMC,EAAkB;AAAA,EACrB;AAAA,EACA,QAA0B;AAAA,EAC1B;AAAA,EACA;AAAA,EACA,iBAAiB,IAAIC,EAAA;AAAA,EACrB;AAAA,EACA;AAAA,EACA,kBAAkB,IAAIC,EAAA;AAAA,EAEtB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAYC,GAAwC;AAClD,UAAM;AAAA,MACJ,WAAAC;AAAA,MACA,KAAAC;AAAA,MACA,aAAAC;AAAA,MACA,gBAAAC;AAAA,MACA,eAAAC;AAAA,MACA,oBAAAC;AAAA,MACA,uBAAAC;AAAA,MACA,qBAAAC;AAAA,MACA,QAAAC;AAAA,MACA,OAAAC;AAAA,MACA,iBAAAC;AAAA,IAAA,IACEX;AACJ,SAAK,iBAAiB,IAAIY,EAAA,GAC1B,KAAK,YAAYX,GACjB,KAAK,sBACHO,KAAuBb,GACzB,KAAK,SAASc,KAAU,IAAI,UAAUP,CAAG,GAGzC,KAAK,gBAAgBG,KAAiBQ,GACtC,KAAK,cAAcV,KAAeU,GAClC,KAAK,iBAAiBT,KAAkBS,GACxC,KAAK,qBAAqBP,KAAsBO,GAChD,KAAK,wBAAwBN,KAAyBM,GAGlDH,MACF,KAAK,QAAQA,IAGf,KAAK,qBAAA,GAEL,KAAK,qBAAqBI;AAAA,MACxB,MAAM,KAAK,mBAAA;AAAA,MACXH,KAAmBf;AAAA,MACnB,EAAE,SAAS,IAAO,UAAU,GAAA;AAAA,IAAK;AAAA,EAErC;AAAA,EAEQ,uBAAuB;AAC7B,SAAK,OAAO,SAAS,MAAM;AACzB,cAAQ,MAAM,mCAAmC,GACjD,KAAK,eAAe,IAAM,IAAI;AAAA,IAChC,GAEA,KAAK,OAAO,YAAY,CAACmB,MAAwB;AAC/C,MAAI,OAAOA,EAAM,QAAS,WACxB,KAAK,cAAcA,EAAM,IAAI,IAE7B,QAAQ,MAAM,qCAAqCA,EAAM,IAAI;AAAA,IAEjE,GAEA,KAAK,OAAO,UAAU,MAAM;AAC1B,cAAQ,MAAM,wCAAwC,GACtD,KAAK,eAAe,IAAO,IAAI;AAAA,IACjC,GAEA,KAAK,OAAO,UAAU,CAACC,MAAiB;AACtC,cAAQ,MAAM,oBAAoBA,CAAK;AAAA,IACzC;AAAA,EACF;AAAA,EAEO,aAAa;AAClB,SAAK,mBAAmB,MAAA,GACxB,KAAK,mBAAmB,OAAA,GACpB,KAAK,OAAO,eAAe,UAAU,QACvC,KAAK,OAAO,MAAA,GACZ,QAAQ,MAAM,6BAA6B,KAE3C,QAAQ,KAAK,yCAAyC;AAAA,EAE1D;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,gBAAgB;AACtB,QAAI,CAAC,KAAK,OAAO;AACf,cAAQ,MAAM,8CAA8C;AAC5D;AAAA,IACF;AAGA,QAAI,CADoB,KAAK,mBAAA,GACP;AAEpB,YAAMC,IAAY,KAAK,eAAe,OAAO,KAAK,KAAK;AACvD,WAAK,gBAAgBA,EAAU,IAAI;AAAA,IACrC;AAAA,EACF;AAAA,EAEQ,cAAcC,GAAoB;AACxC,UAAMC,IAAUC,EAAO,SAAS,KAAK,MAAMF,CAAU,CAAC;AACtD,IAAIC,aAAmBE,IACrB,KAAK;AAAA,MACHF;AAAA,IAAA,IAEOA,aAAmBG,IAC5B,KAAK,uBAAA,IACIH,aAAmBI,IAC5B,KAAK,mBAAmBJ,CAAO,IAE/B,QAAQ,KAAK,wCAAwCA,CAAO;AAAA,EAEhE;AAAA,EAEQ,eACNA,GACA;AACA,UAAMK,IAAUL,EAAQ,WAAA;AAExB,YAAQK,EAAQ,MAAA;AAAA,MACd,KAAK;AACH,aAAK,mBAAmB,CAACA,EAAQ,IAAI,CAAC;AACtC;AAAA,MAEF,KAAK;AACH,QAAK,KAAK,mBAAmBA,EAAQ,IAAI;AACzC;AAAA,MAEF,KAAK;AACH,QAAK,KAAK,sBAAsBA,EAAQ,IAAI;AAC5C;AAAA,MAEF;AACE,gBAAQ,KAAK,yBAAyBA,CAAO;AAC7C;AAAA,IAAA;AAAA,EAEN;AAAA,EAEQ,mBAAmBC,GAAmC;AAC5D,QAAI;AACF,YAAMC,IAAUD,EAAa,IAAIE,CAAM;AACvC,MAAK,KAAK,QAMR,KAAK,MAAM,WAAWD,CAAO,KAL7B,KAAK,QAAQE,EAAM,YAAYF,CAAO,EAAE;AAAA,QACtC,KAAK;AAAA,MAAA,GAEP,KAAK,cAAc,KAAK,KAAK,IAI/B,KAAK,cAAA;AAAA,IACP,SAASG,GAAK;AACZ,cAAQ,MAAM,0CAA0CA,CAAG;AAAA,IAC7D;AAAA,EACF;AAAA,EAEA,MAAc,sBAAsBC,GAAqB;AACvD,YAAQ,MAAM,sCAAsCA,CAAW;AAC/D,QAAI;AACF,YAAMC,IAAe,MAAM,KAAK,uBAAuBD,CAAW;AAClE,WAAK,QAAQC,EAAa,KAAK,KAAK,SAAS,GAC7C,KAAK,cAAc,KAAK,KAAK,GAC7B,KAAK,cAAA;AAAA,IACP,SAASF,GAAK;AACZ,cAAQ,MAAM,sCAAsCA,CAAG;AAAA,IACzD;AAAA,EACF;AAAA,EAEQ,yBAAyB;AAE/B,SAAK,YAAA,GACL,QAAQ;AAAA,MACN;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEQ,mBAAmBV,GAA6B;AACtD,UAAMa,IAAab,EAAQ,cAAA;AAG3B,YAFA,QAAQ,MAAM,sCAAsCa,CAAU,GAEtDA,GAAA;AAAA,MACN,KAAK;AACH,gBAAQ,MAAM,2BAA2B;AACzC;AAAA,MAEF,KAAK;AACH,gBAAQ,MAAM,iCAAiC,GAC/C,KAAK;AAAA,UACH,KAAK,QAAQ,KAAK,eAAe,OAAO,KAAK,KAAK,EAAE,OAAO;AAAA,QAAA;AAE7D;AAAA,MAEF,KAAK;AACH,gBAAQ,KAAK,sBAAsBb,EAAQ,WAAA,CAAY;AACvD;AAAA,MAEF,KAAK;AACH,YAAI,CAAC,KAAK,OAAO;AACf,kBAAQ;AAAA,YACN;AAAA,UAAA;AAEF;AAAA,QACF;AACA;AACE,gBAAMF,IAAY,KAAK,eAAe,OAAO,KAAK,KAAK;AACvD,kBAAQ,MAAM,qCAAqCA,EAAU,IAAI;AACjE,gBAAMgB,IAAM,IAAIC;AAAA,YACd,KAAK,eAAe,QAAA;AAAA,YACpB;AAAA,YACAjB,EAAU;AAAA,UAAA;AAEZ,eAAK,YAAYgB,CAAG;AAAA,QACtB;AACA;AAAA,MAEF,KAAK;AACH,gBAAQ,MAAM,yCAAyC,GACvD,KAAK,mBAAA;AACL;AAAA,MAEF,KAAK;AACH,gBAAQ,MAAM,8CAA8C,GAC5D,KAAK,sBAAA;AACL;AAAA,MAEF;AACE,gBAAQ,KAAK,gCAAgCD,CAAU;AACvD;AAAA,IAAA;AAAA,EAEN;AAAA,EAEQ,YAAYb,GAAwB;AAC1C,IAAI,KAAK,OAAO,eAAe,UAAU,OACvC,KAAK,OAAO,KAAK,KAAK,UAAUA,EAAQ,QAAA,CAAS,CAAC,IAElD,QAAQ;AAAA,MACN;AAAA,MACA,KAAK,OAAO;AAAA,IAAA;AAAA,EAGlB;AAAA,EAEO,YAAY;AACjB,SAAK,mBAAA;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKQ,qBAA8B;AACpC,QAAI,CAAC,KAAK;AACR,qBAAQ,KAAK,8CAA8C,GACpD;AAGT,UAAMgB,IAAQ,KAAK,MAAM,IAAI,MAAA,GACvBC,IAA0BD,EAAM,IAAI,SAAS;AAEnD,WAAIC,KAEcC,EAAWF,GAAO,KAAK,mBAAmB,EAClD,QAAQ,CAAAG,MAAuB;AACrC,cAAQ,MAAM,4BAA4BA,CAAmB;AAC7D,YAAML,IAAM,IAAIC;AAAA,QACd,KAAK,eAAe,QAAA;AAAA,QACpB;AAAA,QACAI;AAAA,MAAA;AAEF,WAAK,YAAYL,CAAG;AAAA,IACtB,CAAC,GAGIG;AAAA,EACT;AAAA,EAEQ,gBAAgBG,GAAoD;AAC1E,UAAMpB,IAAU,IAAIe;AAAA,MAClB,KAAK,eAAe,QAAA;AAAA,MACpB;AAAA,MACAK,KAAS,CAAA;AAAA,IAAC;AAEZ,SAAK,YAAYpB,CAAO;AAAA,EAC1B;AAAA,EAEA,MAAc,uBACZW,GACoB;AAGpB,UAAMU,IAAS,OADF,OADI,MAAMC,EAA4BX,CAAW,GAClC,KAAA,GACF,YAAA,GACpBY,IAAkBC,EAAW,IAAI,WAAWH,CAAM,CAAC;AAIzD,WAHqB,KAAK,gBAAgB;AAAA,MACxCE;AAAA,IAAA;AAAA,EAGJ;AACF;"}
|
|
@@ -51,7 +51,6 @@ import "../../assets/icons/account-validated.svg.js";
|
|
|
51
51
|
import "../../utils/functions/DateFormatter.js";
|
|
52
52
|
import "@react-hookz/web";
|
|
53
53
|
import "dayjs";
|
|
54
|
-
import "../../assets/ArcusBioIcon.svg.js";
|
|
55
54
|
import "@mui/material/SvgIcon";
|
|
56
55
|
import "../../assets/icons/AccessPending.svg.js";
|
|
57
56
|
import "../../assets/icons/AccessPendingCloud.svg.js";
|
|
@@ -217,7 +216,7 @@ import "@mui/material/Grid";
|
|
|
217
216
|
import "@mui/icons-material/ArrowForwardIos";
|
|
218
217
|
import "../PortalAclEditor/PortalAclEditor.js";
|
|
219
218
|
import "../SynapseHomepageV2/HomepageStyles.js";
|
|
220
|
-
function
|
|
219
|
+
function Rr(o) {
|
|
221
220
|
const { sourceEntityId: t, gridSessionId: i } = o, { data: e, isLoading: n } = y(t), s = e?.concreteType ? l(e.concreteType) : void 0, { mutate: c, isPending: a } = u({
|
|
222
221
|
onSuccess: (p) => {
|
|
223
222
|
p.type === "entityview" ? S(p.data) : p.type === "table" ? h(p.data) : r("Successfully updated RecordSet.", "success");
|
|
@@ -267,6 +266,6 @@ function T(o) {
|
|
|
267
266
|
) ?? [];
|
|
268
267
|
}
|
|
269
268
|
export {
|
|
270
|
-
|
|
269
|
+
Rr as default
|
|
271
270
|
};
|
|
272
271
|
//# sourceMappingURL=MergeGridWithSourceTableButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MergeGridWithSourceTableButton.js","sources":["../../../src/components/DataGrid/MergeGridWithSourceTableButton.tsx"],"sourcesContent":["import GridMenuButton from '@/components/DataGrid/components/GridMenuButton/GridMenuButton'\nimport useMergeGridWithSource from '@/components/DataGrid/useMergeGridWithSource'\nimport { displayToast } from '@/components/index'\nimport { useGetEntity } from '@/synapse-queries'\nimport { convertToEntityType } from '@/utils/functions/EntityTypeUtils'\nimport {\n EntityType,\n EntityUpdateResults,\n instanceOfEntityUpdateResults,\n instanceOfUploadToTableResult,\n SynchronizeGridResponse,\n TableUpdateTransactionResponse,\n} from '@sage-bionetworks/synapse-client'\n\nexport type MergeGridWithSourceTableButtonProps = {\n sourceEntityId: string\n gridSessionId: string\n sourceEntityType?: EntityType\n}\n\nexport default function MergeGridWithSourceTableButton(\n props: MergeGridWithSourceTableButtonProps,\n) {\n const { sourceEntityId, gridSessionId } = props\n\n const { data: entity, isLoading: entityLoading } =\n useGetEntity(sourceEntityId)\n\n const sourceEntityType = entity?.concreteType\n ? convertToEntityType(entity.concreteType)\n : undefined\n\n const { mutate: mergeGrid, isPending } = useMergeGridWithSource({\n onSuccess: result => {\n if (result.type === 'entityview') {\n onSynchronizeSuccess(result.data)\n } else if (result.type === 'table') {\n onMergeTableSuccess(result.data)\n } else {\n displayToast('Successfully updated RecordSet.', 'success')\n }\n },\n onError: e => displayToast(e.message, 'danger'),\n })\n\n const buttonText =\n sourceEntityType === 'entityview' ? 'Sync changes' : 'Apply changes'\n\n return (\n <GridMenuButton\n loading={isPending}\n disabled={entityLoading}\n onClick={() => {\n mergeGrid({ gridSessionId, sourceEntityId, sourceEntityType })\n }}\n variant=\"contained\"\n >\n {buttonText}\n </GridMenuButton>\n )\n}\n\nfunction onSynchronizeSuccess(result: SynchronizeGridResponse) {\n if (result.errorMessages == null || result.errorMessages.length === 0) {\n displayToast('Successfully synchronized metadata.', 'success')\n } else {\n displayToast(\n <ul>\n {result.errorMessages.map((msg, index) => (\n <li key={index}>{msg}</li>\n ))}\n </ul>,\n 'warning',\n { title: 'Some changes could not be applied' },\n )\n }\n}\n\nfunction onMergeTableSuccess(result: TableUpdateTransactionResponse) {\n if (result.results?.length) {\n // There should only be one result since the CSV upload is done in one step\n const updateResult = result.results[0]\n if (instanceOfEntityUpdateResults(updateResult)) {\n // This is an update to the contents of a View\n const failureMessages =\n getEntityUpdateResultsErrorMessages(updateResult).join('\\n')\n\n if (failureMessages) {\n displayToast(\n `Some changes could not be applied:\\n${failureMessages}`,\n 'danger',\n )\n } else {\n displayToast('Changes applied successfully', 'success')\n }\n } else if (instanceOfUploadToTableResult(updateResult)) {\n // This is an update to a TableEntity\n const rowsUpdatedStr = updateResult.rowsProcessed?.toLocaleString()\n displayToast(`Successfully updated ${rowsUpdatedStr} rows.`, 'success')\n }\n }\n}\n\nfunction getEntityUpdateResultsErrorMessages(\n results: EntityUpdateResults,\n): string[] {\n return (\n results.updateResults\n ?.filter(e => !!e.failureCode)\n .map(\n r => `${r.entityId}: ${r.failureMessage} (code: ${r.failureCode})`,\n ) ?? []\n )\n}\n"],"names":["MergeGridWithSourceTableButton","props","sourceEntityId","gridSessionId","entity","entityLoading","useGetEntity","sourceEntityType","convertToEntityType","mergeGrid","isPending","useMergeGridWithSource","result","onSynchronizeSuccess","onMergeTableSuccess","displayToast","e","jsx","GridMenuButton","msg","index","updateResult","instanceOfEntityUpdateResults","failureMessages","getEntityUpdateResultsErrorMessages","instanceOfUploadToTableResult","rowsUpdatedStr","results","r"],"mappings":"
|
|
1
|
+
{"version":3,"file":"MergeGridWithSourceTableButton.js","sources":["../../../src/components/DataGrid/MergeGridWithSourceTableButton.tsx"],"sourcesContent":["import GridMenuButton from '@/components/DataGrid/components/GridMenuButton/GridMenuButton'\nimport useMergeGridWithSource from '@/components/DataGrid/useMergeGridWithSource'\nimport { displayToast } from '@/components/index'\nimport { useGetEntity } from '@/synapse-queries'\nimport { convertToEntityType } from '@/utils/functions/EntityTypeUtils'\nimport {\n EntityType,\n EntityUpdateResults,\n instanceOfEntityUpdateResults,\n instanceOfUploadToTableResult,\n SynchronizeGridResponse,\n TableUpdateTransactionResponse,\n} from '@sage-bionetworks/synapse-client'\n\nexport type MergeGridWithSourceTableButtonProps = {\n sourceEntityId: string\n gridSessionId: string\n sourceEntityType?: EntityType\n}\n\nexport default function MergeGridWithSourceTableButton(\n props: MergeGridWithSourceTableButtonProps,\n) {\n const { sourceEntityId, gridSessionId } = props\n\n const { data: entity, isLoading: entityLoading } =\n useGetEntity(sourceEntityId)\n\n const sourceEntityType = entity?.concreteType\n ? convertToEntityType(entity.concreteType)\n : undefined\n\n const { mutate: mergeGrid, isPending } = useMergeGridWithSource({\n onSuccess: result => {\n if (result.type === 'entityview') {\n onSynchronizeSuccess(result.data)\n } else if (result.type === 'table') {\n onMergeTableSuccess(result.data)\n } else {\n displayToast('Successfully updated RecordSet.', 'success')\n }\n },\n onError: e => displayToast(e.message, 'danger'),\n })\n\n const buttonText =\n sourceEntityType === 'entityview' ? 'Sync changes' : 'Apply changes'\n\n return (\n <GridMenuButton\n loading={isPending}\n disabled={entityLoading}\n onClick={() => {\n mergeGrid({ gridSessionId, sourceEntityId, sourceEntityType })\n }}\n variant=\"contained\"\n >\n {buttonText}\n </GridMenuButton>\n )\n}\n\nfunction onSynchronizeSuccess(result: SynchronizeGridResponse) {\n if (result.errorMessages == null || result.errorMessages.length === 0) {\n displayToast('Successfully synchronized metadata.', 'success')\n } else {\n displayToast(\n <ul>\n {result.errorMessages.map((msg, index) => (\n <li key={index}>{msg}</li>\n ))}\n </ul>,\n 'warning',\n { title: 'Some changes could not be applied' },\n )\n }\n}\n\nfunction onMergeTableSuccess(result: TableUpdateTransactionResponse) {\n if (result.results?.length) {\n // There should only be one result since the CSV upload is done in one step\n const updateResult = result.results[0]\n if (instanceOfEntityUpdateResults(updateResult)) {\n // This is an update to the contents of a View\n const failureMessages =\n getEntityUpdateResultsErrorMessages(updateResult).join('\\n')\n\n if (failureMessages) {\n displayToast(\n `Some changes could not be applied:\\n${failureMessages}`,\n 'danger',\n )\n } else {\n displayToast('Changes applied successfully', 'success')\n }\n } else if (instanceOfUploadToTableResult(updateResult)) {\n // This is an update to a TableEntity\n const rowsUpdatedStr = updateResult.rowsProcessed?.toLocaleString()\n displayToast(`Successfully updated ${rowsUpdatedStr} rows.`, 'success')\n }\n }\n}\n\nfunction getEntityUpdateResultsErrorMessages(\n results: EntityUpdateResults,\n): string[] {\n return (\n results.updateResults\n ?.filter(e => !!e.failureCode)\n .map(\n r => `${r.entityId}: ${r.failureMessage} (code: ${r.failureCode})`,\n ) ?? []\n )\n}\n"],"names":["MergeGridWithSourceTableButton","props","sourceEntityId","gridSessionId","entity","entityLoading","useGetEntity","sourceEntityType","convertToEntityType","mergeGrid","isPending","useMergeGridWithSource","result","onSynchronizeSuccess","onMergeTableSuccess","displayToast","e","jsx","GridMenuButton","msg","index","updateResult","instanceOfEntityUpdateResults","failureMessages","getEntityUpdateResultsErrorMessages","instanceOfUploadToTableResult","rowsUpdatedStr","results","r"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAoBA,SAAwBA,GACtBC,GACA;AACA,QAAM,EAAE,gBAAAC,GAAgB,eAAAC,EAAA,IAAkBF,GAEpC,EAAE,MAAMG,GAAQ,WAAWC,EAAA,IAC/BC,EAAaJ,CAAc,GAEvBK,IAAmBH,GAAQ,eAC7BI,EAAoBJ,EAAO,YAAY,IACvC,QAEE,EAAE,QAAQK,GAAW,WAAAC,EAAA,IAAcC,EAAuB;AAAA,IAC9D,WAAW,CAAAC,MAAU;AACnB,MAAIA,EAAO,SAAS,eAClBC,EAAqBD,EAAO,IAAI,IACvBA,EAAO,SAAS,UACzBE,EAAoBF,EAAO,IAAI,IAE/BG,EAAa,mCAAmC,SAAS;AAAA,IAE7D;AAAA,IACA,SAAS,CAAAC,MAAKD,EAAaC,EAAE,SAAS,QAAQ;AAAA,EAAA,CAC/C;AAKD,SACE,gBAAAC;AAAA,IAACC;AAAA,IAAA;AAAA,MACC,SAASR;AAAA,MACT,UAAUL;AAAA,MACV,SAAS,MAAM;AACb,QAAAI,EAAU,EAAE,eAAAN,GAAe,gBAAAD,GAAgB,kBAAAK,EAAA,CAAkB;AAAA,MAC/D;AAAA,MACA,SAAQ;AAAA,MAEP,UAXHA,MAAqB,eAAe,iBAAiB;AAAA,IAWlD;AAAA,EAAA;AAGP;AAEA,SAASM,EAAqBD,GAAiC;AAC7D,EAAIA,EAAO,iBAAiB,QAAQA,EAAO,cAAc,WAAW,IAClEG,EAAa,uCAAuC,SAAS,IAE7DA;AAAA,IACE,gBAAAE,EAAC,MAAA,EACE,UAAAL,EAAO,cAAc,IAAI,CAACO,GAAKC,MAC9B,gBAAAH,EAAC,MAAA,EAAgB,UAAAE,EAAA,GAARC,CAAY,CACtB,GACH;AAAA,IACA;AAAA,IACA,EAAE,OAAO,oCAAA;AAAA,EAAoC;AAGnD;AAEA,SAASN,EAAoBF,GAAwC;AACnE,MAAIA,EAAO,SAAS,QAAQ;AAE1B,UAAMS,IAAeT,EAAO,QAAQ,CAAC;AACrC,QAAIU,EAA8BD,CAAY,GAAG;AAE/C,YAAME,IACJC,EAAoCH,CAAY,EAAE,KAAK;AAAA,CAAI;AAE7D,MAAIE,IACFR;AAAA,QACE;AAAA,EAAuCQ,CAAe;AAAA,QACtD;AAAA,MAAA,IAGFR,EAAa,gCAAgC,SAAS;AAAA,IAE1D,WAAWU,EAA8BJ,CAAY,GAAG;AAEtD,YAAMK,IAAiBL,EAAa,eAAe,eAAA;AACnD,MAAAN,EAAa,wBAAwBW,CAAc,UAAU,SAAS;AAAA,IACxE;AAAA,EACF;AACF;AAEA,SAASF,EACPG,GACU;AACV,SACEA,EAAQ,eACJ,OAAO,CAAAX,MAAK,CAAC,CAACA,EAAE,WAAW,EAC5B;AAAA,IACC,CAAAY,MAAK,GAAGA,EAAE,QAAQ,KAAKA,EAAE,cAAc,WAAWA,EAAE,WAAW;AAAA,EAAA,KAC5D,CAAA;AAEX;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseGrid.d.ts","sourceRoot":"","sources":["../../../src/components/DataGrid/SynapseGrid.tsx"],"names":[],"mappings":"AAaA,OAAO,EACL,iBAAiB,EAElB,MAAM,kCAAkC,CAAA;
|
|
1
|
+
{"version":3,"file":"SynapseGrid.d.ts","sourceRoot":"","sources":["../../../src/components/DataGrid/SynapseGrid.tsx"],"names":[],"mappings":"AAaA,OAAO,EACL,iBAAiB,EAElB,MAAM,kCAAkC,CAAA;AA4BzC,MAAM,MAAM,gBAAgB,GAAG;IAC7B,mBAAmB,CAAC,EAAE,MAAM,CAAA;IAC5B,aAAa,CAAC,EAAE,OAAO,CAAA;CACxB,CAAA;AAED,MAAM,MAAM,iBAAiB,GAAG;IAC9B,cAAc,EAAE,CAAC,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;IACpD,mBAAmB,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAA;CACjD,CAAA;AAED,QAAA,MAAM,WAAW,gHAudhB,CAAA;AAED,eAAe,WAAW,CAAA"}
|