synapse-react-client 4.0.24 → 4.0.26
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 +1 -0
- package/dist/SWC.index.d.ts.map +1 -1
- package/dist/SWC.index.js +2 -1
- package/dist/SWC.index.js.map +1 -1
- package/dist/components/AccessRequirementList/ManagedACTAccessRequirementRequestFlow/DataAccessRequestAccessorsFilesForm/DataAccessRequestAccessorsFilesForm.js.map +1 -1
- package/dist/components/AclEditor/useUpdateAcl.js.map +1 -1
- package/dist/components/Authentication/TwoFactorBackupCodes.js.map +1 -1
- package/dist/components/Authentication/TwoFactorEnrollmentForm.js.map +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +3 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts.map +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.js +43 -30
- package/dist/components/Breadcrumbs/Breadcrumbs.js.map +1 -1
- package/dist/components/CannedRejectionDialog/CannedRejectionDialog.js.map +1 -1
- package/dist/components/ChallengeSubmission/SubmissionDirectoryList.js.map +1 -1
- package/dist/components/CopyToClipboardString/CopyToClipboardString.d.ts +7 -1
- package/dist/components/CopyToClipboardString/CopyToClipboardString.d.ts.map +1 -1
- package/dist/components/CopyToClipboardString/CopyToClipboardString.js +22 -16
- package/dist/components/CopyToClipboardString/CopyToClipboardString.js.map +1 -1
- package/dist/components/DataExplorer/DataExplorer.css +1 -1
- package/dist/components/DataExplorer/DataExplorer.d.ts +16 -2
- package/dist/components/DataExplorer/DataExplorer.d.ts.map +1 -1
- package/dist/components/DataExplorer/DataExplorer.js +82 -75
- package/dist/components/DataExplorer/DataExplorer.js.map +1 -1
- package/dist/components/DataExplorer/DataExplorer.module.js +16 -16
- package/dist/components/DataExplorer/DataExplorer.module.js.map +1 -1
- package/dist/components/DataExplorer/DataExplorer.module.scss +1 -1
- package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.d.ts.map +1 -1
- package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.js +14 -1
- package/dist/components/DataGrid/components/ColumnHeaderWithTooltip.js.map +1 -1
- package/dist/components/DataGrid/utils/columnFactory.d.ts.map +1 -1
- package/dist/components/DataGrid/utils/columnFactory.js +15 -19
- package/dist/components/DataGrid/utils/columnFactory.js.map +1 -1
- package/dist/components/EntityFinder/tree/EntityTree.js.map +1 -1
- package/dist/components/EntityFinder/tree/VirtualizedTree.js.map +1 -1
- package/dist/components/EntityIcon.d.ts +1 -0
- package/dist/components/EntityIcon.d.ts.map +1 -1
- package/dist/components/EntityIcon.js +37 -36
- package/dist/components/EntityIcon.js.map +1 -1
- package/dist/components/EntitySidebar/EntitySidebar.css +1 -0
- package/dist/components/EntitySidebar/EntitySidebar.d.ts +7 -0
- package/dist/components/EntitySidebar/EntitySidebar.d.ts.map +1 -0
- package/dist/components/EntitySidebar/EntitySidebar.js +62 -0
- package/dist/components/EntitySidebar/EntitySidebar.js.map +1 -0
- package/dist/components/EntitySidebar/EntitySidebar.module.js +17 -0
- package/dist/components/EntitySidebar/EntitySidebar.module.js.map +1 -0
- package/dist/components/EntitySidebar/EntitySidebar.module.scss +87 -0
- package/dist/components/Evaluation/EvaluationRoundEditorList.js.map +1 -1
- package/dist/components/GenericCard/BioregistryRules.js.map +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.d.ts +2 -1
- package/dist/components/GenericCard/TableRowGenericCard.d.ts.map +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.js +3 -2
- package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
- package/dist/components/HeaderCard.d.ts.map +1 -1
- package/dist/components/HeaderCard.js +4 -0
- package/dist/components/HeaderCard.js.map +1 -1
- package/dist/components/HexGrid/HexGrid.d.ts +2 -1
- package/dist/components/HexGrid/HexGrid.d.ts.map +1 -1
- package/dist/components/HexGrid/HexGrid.js +13 -13
- package/dist/components/HexGrid/HexGrid.js.map +1 -1
- package/dist/components/IconSvg/IconSvg.d.ts +2 -1
- package/dist/components/IconSvg/IconSvg.d.ts.map +1 -1
- package/dist/components/IconSvg/IconSvg.js +112 -89
- package/dist/components/IconSvg/IconSvg.js.map +1 -1
- package/dist/components/Plot/UpsetPlot.js.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.d.ts +3 -0
- package/dist/components/ProvenanceGraph/ProvenanceGraph.d.ts.map +1 -1
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js +140 -85
- package/dist/components/ProvenanceGraph/ProvenanceGraph.js.map +1 -1
- package/dist/components/SchemaDrivenAnnotationEditor/field/AdditionalPropertiesSchemaField.js.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js +3 -3
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js.map +1 -1
- package/dist/components/StorybookComponentWrapper.js.map +1 -1
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.css +1 -1
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.js +9 -8
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.js.map +1 -1
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.scss +4 -1
- package/dist/components/SynapseHomepageV2/WordPressNews.d.ts +2 -1
- package/dist/components/SynapseHomepageV2/WordPressNews.d.ts.map +1 -1
- package/dist/components/SynapseHomepageV2/WordPressNews.js +8 -7
- package/dist/components/SynapseHomepageV2/WordPressNews.js.map +1 -1
- package/dist/components/SynapseHomepageV2/WordPressNewsItem.d.ts +5 -1
- package/dist/components/SynapseHomepageV2/WordPressNewsItem.d.ts.map +1 -1
- package/dist/components/SynapseHomepageV2/WordPressNewsItem.js +19 -11
- package/dist/components/SynapseHomepageV2/WordPressNewsItem.js.map +1 -1
- package/dist/components/SynapseTable/TablePagination.js.map +1 -1
- package/dist/components/SynapseTable/datasets/DatasetItemsEditor.js.map +1 -1
- package/dist/components/TableColumnSchemaEditor/TableColumnSchemaForm.js.map +1 -1
- package/dist/components/TanStackTable/StyledTanStackTable.js.map +1 -1
- package/dist/components/WordPress/useWordPressPosts.js +1 -1
- package/dist/components/WordPress/useWordPressPosts.js.map +1 -1
- package/dist/components/entity/page/breadcrumbs/EntityPageBreadcrumbs.d.ts +1 -8
- package/dist/components/entity/page/breadcrumbs/EntityPageBreadcrumbs.d.ts.map +1 -1
- package/dist/components/entity/page/breadcrumbs/EntityPageBreadcrumbs.js +17 -12
- package/dist/components/entity/page/breadcrumbs/EntityPageBreadcrumbs.js.map +1 -1
- package/dist/components/entity/page/title_bar/EntityPageTitleBar.d.ts.map +1 -1
- package/dist/components/entity/page/title_bar/EntityPageTitleBar.js +20 -16
- package/dist/components/entity/page/title_bar/EntityPageTitleBar.js.map +1 -1
- package/dist/components/entity/page/title_bar/TitleBarProperties.d.ts +0 -1
- package/dist/components/entity/page/title_bar/TitleBarProperties.d.ts.map +1 -1
- package/dist/components/entity/page/title_bar/TitleBarProperties.js +17 -82
- package/dist/components/entity/page/title_bar/TitleBarProperties.js.map +1 -1
- package/dist/components/entity/page/title_bar/useGetEntityTitleBarProperties.d.ts.map +1 -1
- package/dist/components/entity/page/title_bar/useGetEntityTitleBarProperties.js +3 -4
- package/dist/components/entity/page/title_bar/useGetEntityTitleBarProperties.js.map +1 -1
- package/dist/components/menu/ComplexMenu.d.ts.map +1 -1
- package/dist/components/menu/ComplexMenu.js +5 -3
- package/dist/components/menu/ComplexMenu.js.map +1 -1
- package/dist/style/components/_data-grid-extra.css +1 -1
- package/dist/style/components/_data-grid-extra.scss +0 -6
- package/dist/testutils/ReactQueryMockUtils.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/types/ThemeTypes.d.ts +2 -2
- package/dist/utils/functions/IsEqualTreatUndefinedAsMissing.js.map +1 -1
- package/dist/utils/hooks/useDebouncedEffect.js.map +1 -1
- package/dist/utils/hooks/useDetectSSOCode.js.map +1 -1
- package/dist/utils/hooks/useImmutableTableQuery/useImmutableTableQuery.js.map +1 -1
- package/dist/utils/hooks/useLogin.js.map +1 -1
- package/package.json +6 -6
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import './DataExplorer.css';var e = {
|
|
2
|
-
dataExplorerTitle: "
|
|
3
|
-
dataExplorerSubtitle: "
|
|
4
|
-
dataExplorerButton: "
|
|
5
|
-
dataExplorerTextContainer: "
|
|
6
|
-
dataExplorerContainer: "
|
|
7
|
-
dataContainer: "
|
|
8
|
-
dataRowTitle: "
|
|
9
|
-
dataRowInner: "
|
|
10
|
-
dataRow: "
|
|
11
|
-
viewCta: "
|
|
12
|
-
dataRowLeft: "
|
|
13
|
-
iconContainer: "
|
|
14
|
-
dataRowNamePill: "
|
|
15
|
-
|
|
16
|
-
viewCtaText: "
|
|
17
|
-
viewCtaIcon: "
|
|
2
|
+
dataExplorerTitle: "_dataExplorerTitle_1ezpn_1",
|
|
3
|
+
dataExplorerSubtitle: "_dataExplorerSubtitle_1ezpn_7",
|
|
4
|
+
dataExplorerButton: "_dataExplorerButton_1ezpn_12",
|
|
5
|
+
dataExplorerTextContainer: "_dataExplorerTextContainer_1ezpn_17",
|
|
6
|
+
dataExplorerContainer: "_dataExplorerContainer_1ezpn_27",
|
|
7
|
+
dataContainer: "_dataContainer_1ezpn_41",
|
|
8
|
+
dataRowTitle: "_dataRowTitle_1ezpn_51",
|
|
9
|
+
dataRowInner: "_dataRowInner_1ezpn_67",
|
|
10
|
+
dataRow: "_dataRow_1ezpn_51",
|
|
11
|
+
viewCta: "_viewCta_1ezpn_96",
|
|
12
|
+
dataRowLeft: "_dataRowLeft_1ezpn_101",
|
|
13
|
+
iconContainer: "_iconContainer_1ezpn_109",
|
|
14
|
+
dataRowNamePill: "_dataRowNamePill_1ezpn_119",
|
|
15
|
+
facetCount: "_facetCount_1ezpn_127",
|
|
16
|
+
viewCtaText: "_viewCtaText_1ezpn_160",
|
|
17
|
+
viewCtaIcon: "_viewCtaIcon_1ezpn_167"
|
|
18
18
|
};
|
|
19
19
|
//#endregion
|
|
20
20
|
export { e as default };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataExplorer.module.js","names":[],"sources":["../../../src/components/DataExplorer/DataExplorer.module.scss"],"sourcesContent":["@use 'sass:map';\n@use '../../style/abstracts/variables' as SrcVariables;\n\n.dataExplorerTitle:global(.MuiTypography-root) {\n color: var(--data-explorer-title-color, var(--synapse-primary-action-color));\n font-size: 36px;\n line-height: 40px; /* 111.111% */\n}\n\n.dataExplorerSubtitle:global(.MuiTypography-root) {\n line-height: 140%;\n}\n\n.dataExplorerButton {\n @media (min-width: map.get(SrcVariables.$breakpoints, 'large')) {\n width: fit-content;\n }\n}\n\n.dataExplorerTextContainer {\n gap: 16px;\n\n @media (min-width: map.get(SrcVariables.$breakpoints, 'large')) {\n flex: 0 0 30%;\n max-width: 30%;\n }\n}\n\n.dataExplorerContainer {\n display: flex;\n padding: 40px 0;\n align-items: flex-start;\n gap: 60px;\n flex: 1 0 0;\n flex-direction: column;\n\n @media (min-width: map.get(SrcVariables.$breakpoints, 'large')) {\n flex-direction: row;\n }\n}\n\n.dataContainer {\n display: inline-grid;\n row-gap: 8px;\n column-gap: 8px;\n flex: 1 1 60%;\n min-width: 0;\n grid-template-rows: repeat(9, fit-content(100%));\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n\n.dataRowTitle {\n color: var(--synapse-primary-action-color, #4d558d);\n font-size: 16px;\n font-weight: 400;\n line-height: 26.4px;\n flex: 0 1 auto;\n min-width: 0;\n overflow-wrap: break-word;\n word-break: break-word;\n\n @media (min-width: map.get(SrcVariables.$breakpoints, 'large')) {\n font-size: 19.8px;\n }\n}\n\n.dataRowInner {\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex: 1;\n min-width: 0;\n}\n\n.dataRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8.8px 26.4px;\n min-height: 66.6px;\n gap: 17.6px;\n justify-self: stretch;\n position: relative;\n border-radius: 3.3px;\n border: 1px solid transparent;\n text-decoration: none !important;\n transition:\n background-color 200ms ease,\n border-color 200ms ease,\n box-shadow 200ms ease,\n transform 200ms ease;\n\n &:hover {\n background-color: #fff;\n border-color: #e1e1e1;\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.1);\n transform: scale(1.1);\n z-index: 1;\n .viewCta {\n opacity: 1;\n pointer-events: auto;\n }\n }\n}\n\n.dataRowLeft {\n display: inline-flex;\n align-items: center;\n gap: 16px;\n min-width: 0;\n flex: 1;\n}\n\n.iconContainer {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 49px;\n height: 49px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.dataRowNamePill {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1 1 0;\n min-width: 0;\n}\n\n.
|
|
1
|
+
{"version":3,"file":"DataExplorer.module.js","names":[],"sources":["../../../src/components/DataExplorer/DataExplorer.module.scss"],"sourcesContent":["@use 'sass:map';\n@use '../../style/abstracts/variables' as SrcVariables;\n\n.dataExplorerTitle:global(.MuiTypography-root) {\n color: var(--data-explorer-title-color, var(--synapse-primary-action-color));\n font-size: 36px;\n line-height: 40px; /* 111.111% */\n}\n\n.dataExplorerSubtitle:global(.MuiTypography-root) {\n line-height: 140%;\n}\n\n.dataExplorerButton {\n @media (min-width: map.get(SrcVariables.$breakpoints, 'large')) {\n width: fit-content;\n }\n}\n\n.dataExplorerTextContainer {\n gap: 16px;\n\n @media (min-width: map.get(SrcVariables.$breakpoints, 'large')) {\n flex: 0 0 30%;\n max-width: 30%;\n }\n}\n\n.dataExplorerContainer {\n display: flex;\n padding: 40px 0;\n align-items: flex-start;\n gap: 60px;\n flex: 1 0 0;\n flex-direction: column;\n\n @media (min-width: map.get(SrcVariables.$breakpoints, 'large')) {\n flex-direction: row;\n }\n}\n\n.dataContainer {\n display: inline-grid;\n row-gap: 8px;\n column-gap: 8px;\n flex: 1 1 60%;\n min-width: 0;\n grid-template-rows: repeat(9, fit-content(100%));\n grid-template-columns: repeat(2, minmax(0, 1fr));\n}\n\n.dataRowTitle {\n color: var(--synapse-primary-action-color, #4d558d);\n font-size: 16px;\n font-weight: 400;\n line-height: 26.4px;\n flex: 0 1 auto;\n min-width: 0;\n overflow-wrap: break-word;\n word-break: break-word;\n\n @media (min-width: map.get(SrcVariables.$breakpoints, 'large')) {\n font-size: 19.8px;\n }\n}\n\n.dataRowInner {\n display: flex;\n align-items: center;\n justify-content: space-between;\n flex: 1;\n min-width: 0;\n}\n\n.dataRow {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 8.8px 26.4px;\n min-height: 66.6px;\n gap: 17.6px;\n justify-self: stretch;\n position: relative;\n border-radius: 3.3px;\n border: 1px solid transparent;\n text-decoration: none !important;\n transition:\n background-color 200ms ease,\n border-color 200ms ease,\n box-shadow 200ms ease,\n transform 200ms ease;\n\n &:hover {\n background-color: #fff;\n border-color: #e1e1e1;\n box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.1);\n transform: scale(1.1);\n z-index: 1;\n .viewCta {\n opacity: 1;\n pointer-events: auto;\n }\n }\n}\n\n.dataRowLeft {\n display: inline-flex;\n align-items: center;\n gap: 16px;\n min-width: 0;\n flex: 1;\n}\n\n.iconContainer {\n display: flex;\n align-items: center;\n justify-content: center;\n width: 49px;\n height: 49px;\n border-radius: 50%;\n flex-shrink: 0;\n}\n\n.dataRowNamePill {\n display: flex;\n align-items: center;\n gap: 8px;\n flex: 1 1 0;\n min-width: 0;\n}\n\n.facetCount {\n display: flex;\n padding: 4px 8px;\n justify-content: center;\n align-items: center;\n gap: 10px;\n border-radius: 80px;\n border: 1px solid #d8d5e0;\n color: #787090;\n font-size: 14px;\n font-weight: 400;\n line-height: 24px; /* 171.429% */\n flex-shrink: 0;\n}\n\n.viewCta {\n position: absolute;\n right: 0;\n top: 0;\n bottom: 0;\n display: inline-flex;\n align-items: center;\n padding-right: 26.4px;\n padding-left: 40px;\n gap: 4px;\n opacity: 0;\n white-space: nowrap;\n color: var(--synapse-primary-action-color, #4d558d);\n background: linear-gradient(to right, transparent, #fff 25%, #fff 100%);\n border-radius: 0 2px 2px 0;\n transition: opacity 200ms ease;\n}\n\n.viewCtaText {\n color: var(--synapse-primary-action-color, #4d558d);\n font-size: 16px;\n font-weight: 400;\n line-height: 26.4px; /* 165% */\n}\n\n.viewCtaIcon:global(.MuiSvgIcon-root) {\n font-size: 24px;\n color: var(--synapse-primary-action-color, #5a488f);\n}\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnHeaderWithTooltip.d.ts","sourceRoot":"","sources":["../../../../src/components/DataGrid/components/ColumnHeaderWithTooltip.tsx"],"names":[],"mappings":"AAIA,KAAK,4BAA4B,GAAG;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;CACzB,CAAA;AAKD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,IAAI,EACJ,WAAW,EACX,UAAkB,EAClB,WAAmB,EACnB,WAAmB,EACnB,QAAgB,EAChB,WAAW,GACZ,EAAE,4BAA4B,
|
|
1
|
+
{"version":3,"file":"ColumnHeaderWithTooltip.d.ts","sourceRoot":"","sources":["../../../../src/components/DataGrid/components/ColumnHeaderWithTooltip.tsx"],"names":[],"mappings":"AAIA,KAAK,4BAA4B,GAAG;IAClC,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;CACzB,CAAA;AAKD;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,EACtC,IAAI,EACJ,WAAW,EACX,UAAkB,EAClB,WAAmB,EACnB,WAAmB,EACnB,QAAgB,EAChB,WAAW,GACZ,EAAE,4BAA4B,2CA8F9B"}
|
|
@@ -50,7 +50,20 @@ function u(u) {
|
|
|
50
50
|
title: l,
|
|
51
51
|
placement: "top",
|
|
52
52
|
enterNextDelay: 500,
|
|
53
|
-
children: /* @__PURE__ */ r(
|
|
53
|
+
children: /* @__PURE__ */ r(e, {
|
|
54
|
+
component: "span",
|
|
55
|
+
sx: {
|
|
56
|
+
display: "inline-flex",
|
|
57
|
+
alignItems: "center",
|
|
58
|
+
justifyContent: "center",
|
|
59
|
+
backgroundColor: "primary.main",
|
|
60
|
+
color: "primary.contrastText",
|
|
61
|
+
borderRadius: "50%",
|
|
62
|
+
width: "1.25em",
|
|
63
|
+
height: "1.25em"
|
|
64
|
+
},
|
|
65
|
+
children: /* @__PURE__ */ r(a, { sx: { fontSize: "1em" } })
|
|
66
|
+
})
|
|
54
67
|
}), d[9] = b, d[10] = k);
|
|
55
68
|
let A;
|
|
56
69
|
d[11] !== S || d[12] !== v || d[13] !== x ? (A = x && v && /* @__PURE__ */ r(n, {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ColumnHeaderWithTooltip.js","names":["Box","IconButton","Tooltip","Key","PushPin","PushPinOutlined","TOOLTIP_DELAY_SHOW","ColumnHeaderWithTooltipProps","name","description","isRequired","isUpsertKey","showPinIcon","isPinned","onTogglePin","UPSERT_KEY_TOOLTIP_TEXT","ColumnHeaderWithTooltip","t0","$","_c","t1","t2","t3","t4","undefined","t5","Symbol","for","display","gridTemplateColumns","gap","width","alignItems","minWidth","t6","overflow","textOverflow","whiteSpace","t7","t8","color","ml","t9","t10","flexShrink","t11","fontSize","t12","e","stopPropagation","opacity","t13","t14"],"sources":["../../../../src/components/DataGrid/components/ColumnHeaderWithTooltip.tsx"],"sourcesContent":["import { Box, IconButton, Tooltip } from '@mui/material'\nimport { Key, PushPin, PushPinOutlined } from '@mui/icons-material'\nimport { TOOLTIP_DELAY_SHOW } from '@/components/SynapseTable/SynapseTableConstants'\n\ntype ColumnHeaderWithTooltipProps = {\n name: string\n description?: string\n isRequired?: boolean\n isUpsertKey?: boolean\n showPinIcon?: boolean\n isPinned?: boolean\n onTogglePin?: () => void\n}\n\nconst UPSERT_KEY_TOOLTIP_TEXT =\n 'This property field is the primary key. It is used to match the existing rows when applying updates. If a value already exists the row is updated; if not, a new row is added. If multiple primary keys are defined, all primary key values must match for an existing row to be updated.'\n\n/**\n * Renders a column header. When a description is provided, hovering the column\n * name shows it as a native tooltip; otherwise the column name is shown (useful\n * for truncated headers). An optional pin icon is shown on the right.\n */\nexport function ColumnHeaderWithTooltip({\n name,\n description,\n isRequired = false,\n isUpsertKey = false,\n showPinIcon = false,\n isPinned = false,\n onTogglePin,\n}: ColumnHeaderWithTooltipProps) {\n return (\n <Box\n data-column-id={name}\n sx={{\n display: 'grid',\n gridTemplateColumns: 'minmax(0, 1fr) auto',\n gap: 0.5,\n width: '100%',\n alignItems: 'center',\n minWidth: 0,\n }}\n >\n {/* Text area - shrinks first */}\n <Box\n component=\"span\"\n sx={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n minWidth: 0,\n }}\n title={description || name}\n >\n {name}\n {isRequired && (\n <Box component=\"span\" sx={{ color: 'error.main', ml: 0.25 }}>\n *\n </Box>\n )}\n </Box>\n\n {/* Icons area - fixed size, never shrinks */}\n <Box\n sx={{ display: 'flex', gap: 0.5, flexShrink: 0, alignItems: 'center' }}\n >\n {isUpsertKey && (\n <Tooltip\n title={UPSERT_KEY_TOOLTIP_TEXT}\n placement=\"top\"\n enterNextDelay={TOOLTIP_DELAY_SHOW}\n >\n <Key sx={{ fontSize: '1em' }} />\n </Tooltip>\n )}\n {showPinIcon && onTogglePin && (\n <Tooltip\n title={isPinned ? 'Unpin column' : 'Pin column'}\n placement=\"top\"\n enterNextDelay={TOOLTIP_DELAY_SHOW}\n >\n <IconButton\n size=\"small\"\n color=\"inherit\"\n aria-label={isPinned ? 'Unpin column' : 'Pin column'}\n // Use onMouseDown instead of onClick to prevent column selection\n // when clicking the pin icon. stopPropagation prevents event bubbling.\n onMouseDown={e => {\n e.stopPropagation()\n onTogglePin()\n }}\n sx={{\n color: 'inherit',\n opacity: isPinned ? 1 : 0.7,\n '&:hover': {\n opacity: 1,\n },\n }}\n >\n {isPinned ? (\n <PushPin fontSize=\"inherit\" />\n ) : (\n <PushPinOutlined fontSize=\"inherit\" />\n )}\n </IconButton>\n </Tooltip>\n )}\n </Box>\n </Box>\n )\n}\n"],"mappings":";;;;;;AAcA,IAAMe,IACJ;AAOF,SAAOC,EAAAC,GAAA;CAAA,IAAAC,IAAAC,EAAA,EAAA,GAAiC,EAAAX,SAAAC,gBAAAC,YAAAU,GAAAT,aAAAU,GAAAT,aAAAU,GAAAT,UAAAU,GAAAT,mBAAAG,GAGtCP,IAAAU,MAAAI,KAAAA,IAAA,KAAAJ,GACAT,IAAAU,MAAAG,KAAAA,IAAA,KAAAH,GACAT,IAAAU,MAAAE,KAAAA,IAAA,KAAAF,GACAT,IAAAU,MAAAC,KAAAA,IAAA,KAAAD,GAAgBE;CAAA,AAAAP,EAAA,OAAAQ,OAAAC,IAAA,2BAAA,KAMRF,IAAA;EAAAG,SACO;EAAMC,qBACM;EAAqBC,KACrC;EAAGC,OACD;EAAMC,YACD;EAAQC,UACV;CACZ,GAACf,EAAA,KAAAO,KAAAA,IAAAP,EAAA;CAAA,IAAAgB;CAAA,AAAAhB,EAAA,OAAAQ,OAAAC,IAAA,2BAAA,KAKKO,IAAA;EAAAC,UACQ;EAAQC,cACJ;EAAUC,YACZ;EAAQJ,UACV;CACZ,GAACf,EAAA,KAAAgB,KAAAA,IAAAhB,EAAA;CACM,IAAAoB,IAAA7B,KAAAD,GAAmB+B;CAAA,AAAArB,EAAA,OAAAR,IAOzB6B,IAAArB,EAAA,MAJAqB,IAAA7B,KACC,kBAAC,GAAD;EAAe,WAAA;EAAW,IAAA;GAAA8B,OAAS;GAAYC,IAAM;EAAK;YAAG;CAAzD,CAAA,GAGLvB,EAAA,KAAAR,GAAAQ,EAAA,KAAAqB;CAAA,IAAAG;CAAA,AAAAxB,EAAA,OAAAV,KAAAU,EAAA,OAAAoB,KAAApB,EAAA,OAAAqB,KAfHG,IAAA,kBAAC,GAAD;EACY,WAAA;EACN,IAAAR;EAMG,OAAAI;YART,CAUG9B,GACA+B,CAXC;KAgBErB,EAAA,KAAAV,GAAAU,EAAA,KAAAoB,GAAApB,EAAA,KAAAqB,GAAArB,EAAA,KAAAwB,KAAAA,IAAAxB,EAAA;CAAA,IAAAyB;CAAA,AAAAzB,EAAA,OAAAQ,OAAAC,IAAA,2BAAA,KAIAgB,IAAA;EAAAf,SAAW;EAAME,KAAO;EAAGc,YAAc;EAACZ,YAAc;CAAS,GAACd,EAAA,KAAAyB,KAAAA,IAAAzB,EAAA;CAAA,IAAA2B;CAAA,AAAA3B,EAAA,OAAAP,
|
|
1
|
+
{"version":3,"file":"ColumnHeaderWithTooltip.js","names":["Box","IconButton","Tooltip","Key","PushPin","PushPinOutlined","TOOLTIP_DELAY_SHOW","ColumnHeaderWithTooltipProps","name","description","isRequired","isUpsertKey","showPinIcon","isPinned","onTogglePin","UPSERT_KEY_TOOLTIP_TEXT","ColumnHeaderWithTooltip","t0","$","_c","t1","t2","t3","t4","undefined","t5","Symbol","for","display","gridTemplateColumns","gap","width","alignItems","minWidth","t6","overflow","textOverflow","whiteSpace","t7","t8","color","ml","t9","t10","flexShrink","t11","justifyContent","backgroundColor","borderRadius","height","fontSize","t12","e","stopPropagation","opacity","t13","t14"],"sources":["../../../../src/components/DataGrid/components/ColumnHeaderWithTooltip.tsx"],"sourcesContent":["import { Box, IconButton, Tooltip } from '@mui/material'\nimport { Key, PushPin, PushPinOutlined } from '@mui/icons-material'\nimport { TOOLTIP_DELAY_SHOW } from '@/components/SynapseTable/SynapseTableConstants'\n\ntype ColumnHeaderWithTooltipProps = {\n name: string\n description?: string\n isRequired?: boolean\n isUpsertKey?: boolean\n showPinIcon?: boolean\n isPinned?: boolean\n onTogglePin?: () => void\n}\n\nconst UPSERT_KEY_TOOLTIP_TEXT =\n 'This property field is the primary key. It is used to match the existing rows when applying updates. If a value already exists the row is updated; if not, a new row is added. If multiple primary keys are defined, all primary key values must match for an existing row to be updated.'\n\n/**\n * Renders a column header. When a description is provided, hovering the column\n * name shows it as a native tooltip; otherwise the column name is shown (useful\n * for truncated headers). An optional pin icon is shown on the right.\n */\nexport function ColumnHeaderWithTooltip({\n name,\n description,\n isRequired = false,\n isUpsertKey = false,\n showPinIcon = false,\n isPinned = false,\n onTogglePin,\n}: ColumnHeaderWithTooltipProps) {\n return (\n <Box\n data-column-id={name}\n sx={{\n display: 'grid',\n gridTemplateColumns: 'minmax(0, 1fr) auto',\n gap: 0.5,\n width: '100%',\n alignItems: 'center',\n minWidth: 0,\n }}\n >\n {/* Text area - shrinks first */}\n <Box\n component=\"span\"\n sx={{\n overflow: 'hidden',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n minWidth: 0,\n }}\n title={description || name}\n >\n {name}\n {isRequired && (\n <Box component=\"span\" sx={{ color: 'error.main', ml: 0.25 }}>\n *\n </Box>\n )}\n </Box>\n\n {/* Icons area - fixed size, never shrinks */}\n <Box\n sx={{ display: 'flex', gap: 0.5, flexShrink: 0, alignItems: 'center' }}\n >\n {isUpsertKey && (\n <Tooltip\n title={UPSERT_KEY_TOOLTIP_TEXT}\n placement=\"top\"\n enterNextDelay={TOOLTIP_DELAY_SHOW}\n >\n <Box\n component=\"span\"\n sx={{\n display: 'inline-flex',\n alignItems: 'center',\n justifyContent: 'center',\n backgroundColor: 'primary.main',\n color: 'primary.contrastText',\n borderRadius: '50%',\n width: '1.25em',\n height: '1.25em',\n }}\n >\n <Key sx={{ fontSize: '1em' }} />\n </Box>\n </Tooltip>\n )}\n {showPinIcon && onTogglePin && (\n <Tooltip\n title={isPinned ? 'Unpin column' : 'Pin column'}\n placement=\"top\"\n enterNextDelay={TOOLTIP_DELAY_SHOW}\n >\n <IconButton\n size=\"small\"\n color=\"inherit\"\n aria-label={isPinned ? 'Unpin column' : 'Pin column'}\n // Use onMouseDown instead of onClick to prevent column selection\n // when clicking the pin icon. stopPropagation prevents event bubbling.\n onMouseDown={e => {\n e.stopPropagation()\n onTogglePin()\n }}\n sx={{\n color: 'inherit',\n opacity: isPinned ? 1 : 0.7,\n '&:hover': {\n opacity: 1,\n },\n }}\n >\n {isPinned ? (\n <PushPin fontSize=\"inherit\" />\n ) : (\n <PushPinOutlined fontSize=\"inherit\" />\n )}\n </IconButton>\n </Tooltip>\n )}\n </Box>\n </Box>\n )\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"columnFactory.d.ts","sourceRoot":"","sources":["../../../../src/components/DataGrid/utils/columnFactory.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAA;AAC7E,OAAO,EAGL,MAAM,EAIP,MAAM,wCAAwC,CAAA;AAuE/C,KAAK,YAAY,GAAG;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;IAC7B,gBAAgB,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAA;IACrD,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;CACxC,CAAA;
|
|
1
|
+
{"version":3,"file":"columnFactory.d.ts","sourceRoot":"","sources":["../../../../src/components/DataGrid/utils/columnFactory.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,wCAAwC,CAAA;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAA;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0CAA0C,CAAA;AAC7E,OAAO,EAGL,MAAM,EAIP,MAAM,wCAAwC,CAAA;AAuE/C,KAAK,YAAY,GAAG;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,QAAQ,EAAE,YAAY,GAAG,IAAI,CAAA;IAC7B,gBAAgB,EAAE,eAAe,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,CAAA;IACrD,UAAU,EAAE,OAAO,CAAA;IACnB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,kBAAkB,CAAA;CACxC,CAAA;AAoLD,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAGzD"}
|
|
@@ -54,21 +54,18 @@ function g(e, t) {
|
|
|
54
54
|
return n.displayName = `CellWithTooltip(${t})`, n;
|
|
55
55
|
}
|
|
56
56
|
function _(e, t) {
|
|
57
|
-
return t ? "header-upsert-key" : e ? "header-cell-required" : "header-cell";
|
|
58
|
-
}
|
|
59
|
-
function v(e, t) {
|
|
60
57
|
return ({ rowData: n }) => ({
|
|
61
58
|
...n,
|
|
62
59
|
[e]: a(t)
|
|
63
60
|
});
|
|
64
61
|
}
|
|
65
|
-
function
|
|
62
|
+
function v(e) {
|
|
66
63
|
return (t) => {
|
|
67
64
|
let n = t.trim();
|
|
68
65
|
return n === "" ? a(e) : n;
|
|
69
66
|
};
|
|
70
67
|
}
|
|
71
|
-
function
|
|
68
|
+
function y(e, t) {
|
|
72
69
|
let n = {
|
|
73
70
|
showPinIcon: e.showPinIcon,
|
|
74
71
|
hasDescription: !!e.description
|
|
@@ -85,31 +82,30 @@ function b(e, t) {
|
|
|
85
82
|
isPinned: e.isPinned,
|
|
86
83
|
onTogglePin: e.onTogglePin
|
|
87
84
|
}),
|
|
88
|
-
headerClassName: _(e.isRequired, !!e.isUpsertKey),
|
|
89
85
|
minWidth: a,
|
|
90
86
|
basis: a,
|
|
91
87
|
grow: 0,
|
|
92
88
|
shrink: 0,
|
|
93
89
|
disabled: e.disabled,
|
|
94
|
-
deleteValue:
|
|
90
|
+
deleteValue: _(e.columnName, e.isRequired),
|
|
95
91
|
pasteValue: o(s.pasteValue, e.columnName, e.schemaPropertyInfo),
|
|
96
92
|
stickyLeft: e.isPinned
|
|
97
93
|
};
|
|
98
94
|
}
|
|
99
|
-
var
|
|
100
|
-
multipleEnum: (e) =>
|
|
95
|
+
var b = {
|
|
96
|
+
multipleEnum: (e) => y(e, n({
|
|
101
97
|
choices: e.enumeratedValues ?? [],
|
|
102
98
|
colType: e.typeInfo?.type || null,
|
|
103
99
|
limitTags: 3,
|
|
104
100
|
clearValue: a(e.isRequired)
|
|
105
101
|
})),
|
|
106
|
-
boolean: (e) =>
|
|
102
|
+
boolean: (e) => y(e, t({
|
|
107
103
|
choices: [!0, !1],
|
|
108
104
|
colType: "boolean",
|
|
109
105
|
clearValue: a(e.isRequired)
|
|
110
106
|
})),
|
|
111
|
-
number: (e) =>
|
|
112
|
-
enumerated: (e) =>
|
|
107
|
+
number: (e) => y(e, m),
|
|
108
|
+
enumerated: (e) => y(e, t({
|
|
113
109
|
choices: e.enumeratedValues ?? [],
|
|
114
110
|
colType: e.typeInfo?.type || null,
|
|
115
111
|
clearValue: a(e.isRequired)
|
|
@@ -124,27 +120,27 @@ var x = {
|
|
|
124
120
|
enumeratedValues: null
|
|
125
121
|
}, i);
|
|
126
122
|
return {
|
|
127
|
-
...
|
|
123
|
+
...y(t, n),
|
|
128
124
|
minWidth: a,
|
|
129
125
|
basis: a
|
|
130
126
|
};
|
|
131
127
|
},
|
|
132
128
|
text: (e) => ({
|
|
133
|
-
...
|
|
129
|
+
...y(e, p({
|
|
134
130
|
continuousUpdates: !1,
|
|
135
131
|
deletedValue: void 0,
|
|
136
|
-
parseUserInput:
|
|
132
|
+
parseUserInput: v(e.isRequired)
|
|
137
133
|
})),
|
|
138
134
|
cellClassName: "MuiInputBase-input"
|
|
139
135
|
})
|
|
140
136
|
};
|
|
141
|
-
function
|
|
137
|
+
function x(e, t) {
|
|
142
138
|
return e ? e.format === "date-time" ? "date-time" : e.isArray ? "multipleEnum" : e.type === "boolean" ? "boolean" : e.type === "number" || e.type === "integer" ? "number" : t && t.length > 0 ? "enumerated" : "text" : t && t.length > 0 ? "enumerated" : "text";
|
|
143
139
|
}
|
|
144
|
-
function
|
|
145
|
-
return x
|
|
140
|
+
function S(e) {
|
|
141
|
+
return b[x(e.typeInfo, e.enumeratedValues)](e);
|
|
146
142
|
}
|
|
147
143
|
//#endregion
|
|
148
|
-
export {
|
|
144
|
+
export { S as createColumn };
|
|
149
145
|
|
|
150
146
|
//# sourceMappingURL=columnFactory.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"columnFactory.js","names":["dateTimeColumn","EnumeratedValue","FlatTypeInfo","SchemaPropertyInfo","CellComponent","CellProps","Column","createTextColumn","floatColumn","keyColumn","autocompleteColumn","autocompleteMultipleEnumColumn","calculateDefaultColumnWidth","HeaderOptions","ColumnHeaderWithTooltip","Tooltip","SmartToyTwoTone","DataGridRow","wrapPasteValueWithSchemaCoercion","getEmptyValue","withChangeIndicatorTooltip","OriginalComponent","T","C","colName","CellWithTooltip","props","$","_c","changeInfo","rowData","__cellChangeInfo","isAgent","category","t0","t1","tooltipText","position","top","right","width","height","zIndex","pointerEvents","t2","focus","fontSize","alignSelf","flexShrink","mr","color","backgroundColor","t3","displayName","ColumnConfig","columnName","description","disabled","typeInfo","enumeratedValues","isRequired","customWidth","showPinIcon","isPinned","onTogglePin","isUpsertKey","schemaPropertyInfo","getHeaderClassName","createDeleteValue","Record","createParseUserInput","value","trimmedValue","trim","createBaseColumn","config","columnImpl","headerOptions","hasDescription","undefined","keyed","component","title","headerClassName","minWidth","basis","grow","shrink","deleteValue","pasteValue","stickyLeft","COLUMN_FACTORIES","multipleEnum","choices","colType","type","limitTags","clearValue","boolean","number","enumerated","date-time","text","continuousUpdates","deletedValue","parseUserInput","cellClassName","getColumnType","length","format","isArray","createColumn","columnType"],"sources":["../../../../src/components/DataGrid/utils/columnFactory.tsx"],"sourcesContent":["import { dateTimeColumn } from '@/components/DataGrid/columns/DateTimeColumn'\nimport { EnumeratedValue } from '@/utils/jsonschema/getEnumeratedValues'\nimport { FlatTypeInfo } from '@/utils/jsonschema/getType'\nimport { SchemaPropertyInfo } from '@/utils/jsonschema/getSchemaPropertyInfo'\nimport {\n CellComponent,\n CellProps,\n Column,\n createTextColumn,\n floatColumn,\n keyColumn,\n} from '@sage-bionetworks/react-datasheet-grid'\nimport { autocompleteColumn } from '../columns/AutocompleteColumn'\nimport { autocompleteMultipleEnumColumn } from '../columns/AutocompleteMultipleEnumColumn'\nimport {\n calculateDefaultColumnWidth,\n HeaderOptions,\n} from './calculateColumnWidth'\nimport { ColumnHeaderWithTooltip } from '../components/ColumnHeaderWithTooltip'\nimport { Tooltip } from '@mui/material'\nimport { SmartToyTwoTone } from '@mui/icons-material'\nimport type { DataGridRow } from '../DataGridTypes'\nimport { wrapPasteValueWithSchemaCoercion } from './schemaAwarePasteValue'\nimport { getEmptyValue } from './getEmptyValue'\n\n/**\n * Wraps a column cell component to overlay change-attribution indicators:\n * - Non-agent changes: invisible 7×7px tooltip trigger over the CSS triangle (top-right).\n * - Agent changes: robot icon (1em, vertically centered on the right) with no triangle.\n */\nfunction withChangeIndicatorTooltip<T, C>(\n OriginalComponent: CellComponent<T, C>,\n colName: string,\n): CellComponent<T, C> {\n function CellWithTooltip(props: CellProps<T, C>) {\n const changeInfo = (props.rowData as DataGridRow).__cellChangeInfo?.[\n colName\n ]\n const isAgent =\n changeInfo?.category === 'own-agent' ||\n changeInfo?.category === 'other-agent'\n return (\n <>\n <OriginalComponent {...props} />\n {changeInfo && !isAgent && (\n <Tooltip title={changeInfo.tooltipText} placement=\"top-end\">\n <div\n style={{\n position: 'absolute',\n top: 0,\n right: 0,\n width: 7,\n height: 7,\n zIndex: 21,\n pointerEvents: 'auto',\n }}\n />\n </Tooltip>\n )}\n {isAgent && !props.focus && (\n <Tooltip title={changeInfo.tooltipText} placement=\"left\">\n <SmartToyTwoTone\n sx={{\n fontSize: '1em',\n alignSelf: 'center',\n flexShrink: 0,\n mr: 0.5,\n zIndex: 21,\n pointerEvents: 'auto',\n color: 'grey.400',\n backgroundColor: 'transparent',\n }}\n />\n </Tooltip>\n )}\n </>\n )\n }\n CellWithTooltip.displayName = `CellWithTooltip(${colName})`\n return CellWithTooltip\n}\n\ntype ColumnConfig = {\n columnName: string\n description?: string\n disabled?: boolean\n typeInfo: FlatTypeInfo | null\n enumeratedValues: EnumeratedValue[] | string[] | null\n isRequired: boolean\n customWidth?: number\n showPinIcon?: boolean\n isPinned?: boolean\n onTogglePin?: () => void\n isUpsertKey?: boolean\n /**\n * Optional column-level schema info. When provided, paste behavior coerces\n * empty pasted cells to the schema-correct blank (undefined for optional\n * columns, null for required columns). Omit to preserve the column impl's\n * default paste behavior.\n */\n schemaPropertyInfo?: SchemaPropertyInfo\n}\n\nfunction getHeaderClassName(isRequired: boolean, isUpsertKey: boolean): string {\n return isUpsertKey\n ? 'header-upsert-key'\n : isRequired\n ? 'header-cell-required'\n : 'header-cell'\n}\n\nfunction createDeleteValue(columnName: string, isRequired?: boolean) {\n return ({ rowData }: { rowData: Record<string, unknown> }) => ({\n ...rowData,\n [columnName]: getEmptyValue(isRequired),\n })\n}\n\nfunction createParseUserInput(isRequired?: boolean) {\n return (value: string) => {\n const trimmedValue = value.trim()\n if (trimmedValue === '') {\n return getEmptyValue(isRequired)\n }\n return trimmedValue\n }\n}\n\nfunction createBaseColumn(config: ColumnConfig, columnImpl: any) {\n const headerOptions: HeaderOptions = {\n showPinIcon: config.showPinIcon,\n hasDescription: !!config.description,\n }\n\n const width =\n config.customWidth ??\n calculateDefaultColumnWidth(\n config.columnName,\n undefined, // propertyInfo is not available here, passed from higher level\n headerOptions,\n )\n\n const keyed = keyColumn(config.columnName, columnImpl)\n return {\n ...keyed,\n component: withChangeIndicatorTooltip(keyed.component!, config.columnName),\n title: (\n <ColumnHeaderWithTooltip\n name={config.columnName}\n description={config.description}\n isRequired={config.isRequired}\n isUpsertKey={config.isUpsertKey}\n showPinIcon={config.showPinIcon}\n isPinned={config.isPinned}\n onTogglePin={config.onTogglePin}\n />\n ),\n headerClassName: getHeaderClassName(\n config.isRequired,\n !!config.isUpsertKey,\n ),\n minWidth: width,\n basis: width,\n grow: 0,\n shrink: 0,\n disabled: config.disabled,\n deleteValue: createDeleteValue(config.columnName, config.isRequired),\n pasteValue: wrapPasteValueWithSchemaCoercion(\n keyed.pasteValue,\n config.columnName,\n config.schemaPropertyInfo,\n ),\n stickyLeft: config.isPinned,\n }\n}\n\nconst COLUMN_FACTORIES = {\n multipleEnum: (config: ColumnConfig) => {\n return createBaseColumn(\n config,\n autocompleteMultipleEnumColumn({\n choices: config.enumeratedValues ?? [],\n colType: config.typeInfo?.type || null,\n limitTags: 3,\n clearValue: getEmptyValue(config.isRequired),\n }),\n )\n },\n\n boolean: (config: ColumnConfig) => {\n return createBaseColumn(\n config,\n autocompleteColumn({\n choices: [true, false],\n colType: 'boolean',\n clearValue: getEmptyValue(config.isRequired),\n }),\n )\n },\n\n number: (config: ColumnConfig) => {\n return createBaseColumn(config, floatColumn)\n },\n\n enumerated: (config: ColumnConfig) => {\n return createBaseColumn(\n config,\n autocompleteColumn({\n choices: config.enumeratedValues ?? [],\n colType: config.typeInfo?.type || null,\n clearValue: getEmptyValue(config.isRequired),\n }),\n )\n },\n\n 'date-time': (config: ColumnConfig) => {\n const columnImpl = dateTimeColumn({\n colType: config.typeInfo?.type || null,\n })\n\n // Date-time needs special width calculation\n const headerOptions: HeaderOptions = {\n showPinIcon: config.showPinIcon,\n hasDescription: !!config.description,\n }\n\n const width =\n config.customWidth ??\n calculateDefaultColumnWidth(\n config.columnName,\n {\n type: config.typeInfo ?? undefined,\n isRequired: config.isRequired,\n enumeratedValues: null,\n },\n headerOptions,\n )\n\n return {\n ...createBaseColumn(config, columnImpl),\n minWidth: width,\n basis: width,\n }\n },\n\n text: (config: ColumnConfig) => {\n const columnImpl = createTextColumn({\n continuousUpdates: false,\n deletedValue: undefined,\n parseUserInput: createParseUserInput(config.isRequired),\n })\n\n return {\n ...createBaseColumn(config, columnImpl),\n cellClassName: 'MuiInputBase-input',\n }\n },\n}\n\nfunction getColumnType(\n typeInfo: FlatTypeInfo | null,\n enumeratedValues?: EnumeratedValue[] | string[] | null,\n): keyof typeof COLUMN_FACTORIES {\n if (!typeInfo) {\n return enumeratedValues && enumeratedValues.length > 0\n ? 'enumerated'\n : 'text'\n }\n\n if (typeInfo.format === 'date-time') {\n return 'date-time'\n }\n\n // Handle arrays - check if it's an array of enums\n if (typeInfo.isArray) {\n return 'multipleEnum'\n }\n\n if (typeInfo.type === 'boolean') {\n return 'boolean'\n }\n\n if (typeInfo.type === 'number' || typeInfo.type === 'integer') {\n return 'number'\n }\n\n if (enumeratedValues && enumeratedValues.length > 0) {\n return 'enumerated'\n }\n\n return 'text'\n}\n\nexport function createColumn(config: ColumnConfig): Column {\n const columnType = getColumnType(config.typeInfo, config.enumeratedValues)\n return COLUMN_FACTORIES[columnType](config)\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"columnFactory.js","names":["dateTimeColumn","EnumeratedValue","FlatTypeInfo","SchemaPropertyInfo","CellComponent","CellProps","Column","createTextColumn","floatColumn","keyColumn","autocompleteColumn","autocompleteMultipleEnumColumn","calculateDefaultColumnWidth","HeaderOptions","ColumnHeaderWithTooltip","Tooltip","SmartToyTwoTone","DataGridRow","wrapPasteValueWithSchemaCoercion","getEmptyValue","withChangeIndicatorTooltip","OriginalComponent","T","C","colName","CellWithTooltip","props","$","_c","changeInfo","rowData","__cellChangeInfo","isAgent","category","t0","t1","tooltipText","position","top","right","width","height","zIndex","pointerEvents","t2","focus","fontSize","alignSelf","flexShrink","mr","color","backgroundColor","t3","displayName","ColumnConfig","columnName","description","disabled","typeInfo","enumeratedValues","isRequired","customWidth","showPinIcon","isPinned","onTogglePin","isUpsertKey","schemaPropertyInfo","createDeleteValue","Record","createParseUserInput","value","trimmedValue","trim","createBaseColumn","config","columnImpl","headerOptions","hasDescription","undefined","keyed","component","title","minWidth","basis","grow","shrink","deleteValue","pasteValue","stickyLeft","COLUMN_FACTORIES","multipleEnum","choices","colType","type","limitTags","clearValue","boolean","number","enumerated","date-time","text","continuousUpdates","deletedValue","parseUserInput","cellClassName","getColumnType","length","format","isArray","createColumn","columnType"],"sources":["../../../../src/components/DataGrid/utils/columnFactory.tsx"],"sourcesContent":["import { dateTimeColumn } from '@/components/DataGrid/columns/DateTimeColumn'\nimport { EnumeratedValue } from '@/utils/jsonschema/getEnumeratedValues'\nimport { FlatTypeInfo } from '@/utils/jsonschema/getType'\nimport { SchemaPropertyInfo } from '@/utils/jsonschema/getSchemaPropertyInfo'\nimport {\n CellComponent,\n CellProps,\n Column,\n createTextColumn,\n floatColumn,\n keyColumn,\n} from '@sage-bionetworks/react-datasheet-grid'\nimport { autocompleteColumn } from '../columns/AutocompleteColumn'\nimport { autocompleteMultipleEnumColumn } from '../columns/AutocompleteMultipleEnumColumn'\nimport {\n calculateDefaultColumnWidth,\n HeaderOptions,\n} from './calculateColumnWidth'\nimport { ColumnHeaderWithTooltip } from '../components/ColumnHeaderWithTooltip'\nimport { Tooltip } from '@mui/material'\nimport { SmartToyTwoTone } from '@mui/icons-material'\nimport type { DataGridRow } from '../DataGridTypes'\nimport { wrapPasteValueWithSchemaCoercion } from './schemaAwarePasteValue'\nimport { getEmptyValue } from './getEmptyValue'\n\n/**\n * Wraps a column cell component to overlay change-attribution indicators:\n * - Non-agent changes: invisible 7×7px tooltip trigger over the CSS triangle (top-right).\n * - Agent changes: robot icon (1em, vertically centered on the right) with no triangle.\n */\nfunction withChangeIndicatorTooltip<T, C>(\n OriginalComponent: CellComponent<T, C>,\n colName: string,\n): CellComponent<T, C> {\n function CellWithTooltip(props: CellProps<T, C>) {\n const changeInfo = (props.rowData as DataGridRow).__cellChangeInfo?.[\n colName\n ]\n const isAgent =\n changeInfo?.category === 'own-agent' ||\n changeInfo?.category === 'other-agent'\n return (\n <>\n <OriginalComponent {...props} />\n {changeInfo && !isAgent && (\n <Tooltip title={changeInfo.tooltipText} placement=\"top-end\">\n <div\n style={{\n position: 'absolute',\n top: 0,\n right: 0,\n width: 7,\n height: 7,\n zIndex: 21,\n pointerEvents: 'auto',\n }}\n />\n </Tooltip>\n )}\n {isAgent && !props.focus && (\n <Tooltip title={changeInfo.tooltipText} placement=\"left\">\n <SmartToyTwoTone\n sx={{\n fontSize: '1em',\n alignSelf: 'center',\n flexShrink: 0,\n mr: 0.5,\n zIndex: 21,\n pointerEvents: 'auto',\n color: 'grey.400',\n backgroundColor: 'transparent',\n }}\n />\n </Tooltip>\n )}\n </>\n )\n }\n CellWithTooltip.displayName = `CellWithTooltip(${colName})`\n return CellWithTooltip\n}\n\ntype ColumnConfig = {\n columnName: string\n description?: string\n disabled?: boolean\n typeInfo: FlatTypeInfo | null\n enumeratedValues: EnumeratedValue[] | string[] | null\n isRequired: boolean\n customWidth?: number\n showPinIcon?: boolean\n isPinned?: boolean\n onTogglePin?: () => void\n isUpsertKey?: boolean\n /**\n * Optional column-level schema info. When provided, paste behavior coerces\n * empty pasted cells to the schema-correct blank (undefined for optional\n * columns, null for required columns). Omit to preserve the column impl's\n * default paste behavior.\n */\n schemaPropertyInfo?: SchemaPropertyInfo\n}\n\nfunction createDeleteValue(columnName: string, isRequired?: boolean) {\n return ({ rowData }: { rowData: Record<string, unknown> }) => ({\n ...rowData,\n [columnName]: getEmptyValue(isRequired),\n })\n}\n\nfunction createParseUserInput(isRequired?: boolean) {\n return (value: string) => {\n const trimmedValue = value.trim()\n if (trimmedValue === '') {\n return getEmptyValue(isRequired)\n }\n return trimmedValue\n }\n}\n\nfunction createBaseColumn(config: ColumnConfig, columnImpl: any) {\n const headerOptions: HeaderOptions = {\n showPinIcon: config.showPinIcon,\n hasDescription: !!config.description,\n }\n\n const width =\n config.customWidth ??\n calculateDefaultColumnWidth(\n config.columnName,\n undefined, // propertyInfo is not available here, passed from higher level\n headerOptions,\n )\n\n const keyed = keyColumn(config.columnName, columnImpl)\n return {\n ...keyed,\n component: withChangeIndicatorTooltip(keyed.component!, config.columnName),\n title: (\n <ColumnHeaderWithTooltip\n name={config.columnName}\n description={config.description}\n isRequired={config.isRequired}\n isUpsertKey={config.isUpsertKey}\n showPinIcon={config.showPinIcon}\n isPinned={config.isPinned}\n onTogglePin={config.onTogglePin}\n />\n ),\n minWidth: width,\n basis: width,\n grow: 0,\n shrink: 0,\n disabled: config.disabled,\n deleteValue: createDeleteValue(config.columnName, config.isRequired),\n pasteValue: wrapPasteValueWithSchemaCoercion(\n keyed.pasteValue,\n config.columnName,\n config.schemaPropertyInfo,\n ),\n stickyLeft: config.isPinned,\n }\n}\n\nconst COLUMN_FACTORIES = {\n multipleEnum: (config: ColumnConfig) => {\n return createBaseColumn(\n config,\n autocompleteMultipleEnumColumn({\n choices: config.enumeratedValues ?? [],\n colType: config.typeInfo?.type || null,\n limitTags: 3,\n clearValue: getEmptyValue(config.isRequired),\n }),\n )\n },\n\n boolean: (config: ColumnConfig) => {\n return createBaseColumn(\n config,\n autocompleteColumn({\n choices: [true, false],\n colType: 'boolean',\n clearValue: getEmptyValue(config.isRequired),\n }),\n )\n },\n\n number: (config: ColumnConfig) => {\n return createBaseColumn(config, floatColumn)\n },\n\n enumerated: (config: ColumnConfig) => {\n return createBaseColumn(\n config,\n autocompleteColumn({\n choices: config.enumeratedValues ?? [],\n colType: config.typeInfo?.type || null,\n clearValue: getEmptyValue(config.isRequired),\n }),\n )\n },\n\n 'date-time': (config: ColumnConfig) => {\n const columnImpl = dateTimeColumn({\n colType: config.typeInfo?.type || null,\n })\n\n // Date-time needs special width calculation\n const headerOptions: HeaderOptions = {\n showPinIcon: config.showPinIcon,\n hasDescription: !!config.description,\n }\n\n const width =\n config.customWidth ??\n calculateDefaultColumnWidth(\n config.columnName,\n {\n type: config.typeInfo ?? undefined,\n isRequired: config.isRequired,\n enumeratedValues: null,\n },\n headerOptions,\n )\n\n return {\n ...createBaseColumn(config, columnImpl),\n minWidth: width,\n basis: width,\n }\n },\n\n text: (config: ColumnConfig) => {\n const columnImpl = createTextColumn({\n continuousUpdates: false,\n deletedValue: undefined,\n parseUserInput: createParseUserInput(config.isRequired),\n })\n\n return {\n ...createBaseColumn(config, columnImpl),\n cellClassName: 'MuiInputBase-input',\n }\n },\n}\n\nfunction getColumnType(\n typeInfo: FlatTypeInfo | null,\n enumeratedValues?: EnumeratedValue[] | string[] | null,\n): keyof typeof COLUMN_FACTORIES {\n if (!typeInfo) {\n return enumeratedValues && enumeratedValues.length > 0\n ? 'enumerated'\n : 'text'\n }\n\n if (typeInfo.format === 'date-time') {\n return 'date-time'\n }\n\n // Handle arrays - check if it's an array of enums\n if (typeInfo.isArray) {\n return 'multipleEnum'\n }\n\n if (typeInfo.type === 'boolean') {\n return 'boolean'\n }\n\n if (typeInfo.type === 'number' || typeInfo.type === 'integer') {\n return 'number'\n }\n\n if (enumeratedValues && enumeratedValues.length > 0) {\n return 'enumerated'\n }\n\n return 'text'\n}\n\nexport function createColumn(config: ColumnConfig): Column {\n const columnType = getColumnType(config.typeInfo, config.enumeratedValues)\n return COLUMN_FACTORIES[columnType](config)\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityTree.js","names":[],"sources":["../../../../src/components/EntityFinder/tree/EntityTree.tsx"],"sourcesContent":["import {\n useGetEntityHeader,\n useGetEntityPath,\n useGetFavorites,\n useGetProjectsInfinite,\n} from '@/synapse-queries'\nimport useGetEntityBundle from '@/synapse-queries/entity/useEntityBundle'\nimport { convertToEntityType } from '@/utils/functions/EntityTypeUtils'\nimport { SYNAPSE_ENTITY_ID_REGEX } from '@/utils/functions/RegularExpressions'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n ALL_ENTITY_BUNDLE_FIELDS,\n EntityPath,\n Reference,\n} from '@sage-bionetworks/synapse-types'\nimport {\n Dispatch,\n SetStateAction,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react'\nimport DropdownSelect from '../../DropdownSelect/DropdownSelect'\nimport { SynapseSpinner } from '../../LoadingScreen/LoadingScreen'\nimport { displayToast } from '../../ToastMessage/ToastMessage'\nimport { BreadcrumbItem } from '../Breadcrumbs'\nimport { toEntityHeader } from '../details/configurations/ProjectListDetails'\nimport {\n EntityDetailsListDataConfiguration,\n EntityDetailsListDataConfigurationType,\n} from '../details/EntityDetailsList'\nimport { EntityFinderHeader } from '../EntityFinderHeader'\nimport { EntitySelectionMapType } from '../useEntitySelection'\nimport {\n EntityTreeNodeType,\n RootNodeConfiguration,\n VirtualizedTree,\n} from './VirtualizedTree'\n\nconst isEntityIdInPath = (entityId: string, path: EntityPath): boolean => {\n for (const eh of path.path) {\n if (entityId === eh.id) {\n return true\n }\n }\n return false\n}\n\nexport enum FinderScope {\n CURRENT_PROJECT = 'Current Project',\n ALL_PROJECTS = 'All Projects',\n CREATED_BY_ME = 'Projects Created By Me',\n FAVORITES = 'My Favorites',\n}\n\nfunction getScopeOptionDefaultContainer(\n scope: FinderScope,\n): EntityTreeContainer {\n switch (scope) {\n case FinderScope.FAVORITES:\n return 'root'\n case FinderScope.CURRENT_PROJECT:\n case FinderScope.ALL_PROJECTS:\n case FinderScope.CREATED_BY_ME:\n return null\n }\n}\n\nfunction getScopeOptionNodeName(scope: FinderScope): string {\n switch (scope) {\n case FinderScope.CURRENT_PROJECT:\n case FinderScope.ALL_PROJECTS:\n case FinderScope.CREATED_BY_ME:\n return 'Projects'\n case FinderScope.FAVORITES:\n return 'Favorites'\n }\n}\n\n/**\n * Indicates which container is selected when the tree is used to control another component. If 'root', then the top-level entities\n * should be shown in the other component. If a synID, then that entity's children should be shown in the other component. If null,\n * then a selection has not been made.\n */\nexport type EntityTreeContainer = string | 'root' | null\n\n// if the first item is selected (matching the dropdown), then output a configuration. otherwise, output a synId\nexport type EntityTreeProps = {\n initialScope?: FinderScope\n /** To show the current project, projectId must be defined */\n projectId?: string\n initialContainer: EntityTreeContainer\n currentContainer: EntityTreeContainer\n setCurrentContainer: Dispatch<SetStateAction<EntityTreeContainer>>\n showDropdown: boolean\n selectedEntities: EntitySelectionMapType\n visibleTypes?: EntityType[]\n toggleSelection?: (entity: Reference) => void\n setDetailsViewConfiguration?: (\n configuration: EntityDetailsListDataConfiguration,\n ) => void\n setBreadcrumbItems?: (items: BreadcrumbItem[]) => void\n /** Determines whether to show the root node corresponding to the selected scope */\n showScopeAsRootNode?: boolean\n treeNodeType: EntityTreeNodeType\n /** The entity types that may be selected. */\n selectableTypes: EntityType[]\n hideScopeSelector?: boolean\n}\n\n/**\n * The TreeView displays a user's entities hierarchically, allowing a user to quickly dive into an entity tree.\n *\n * The tree view currently can only be used to drive a DetailsView using the `setDetailsViewConfiguration` property.\n */\nexport function EntityTree(props: EntityTreeProps) {\n const {\n initialScope = FinderScope.CURRENT_PROJECT,\n projectId,\n initialContainer = null,\n currentContainer,\n setCurrentContainer,\n visibleTypes = [EntityType.project, EntityType.folder],\n toggleSelection,\n selectedEntities,\n setDetailsViewConfiguration,\n setBreadcrumbItems,\n showScopeAsRootNode = true,\n treeNodeType,\n selectableTypes,\n hideScopeSelector = false,\n } = props\n\n const DEFAULT_CONFIGURATION: EntityDetailsListDataConfiguration = {\n type: EntityDetailsListDataConfigurationType.PROMPT,\n }\n\n const [scope, setScope] = useState(initialScope)\n\n useEffect(() => {\n if (setDetailsViewConfiguration) {\n setDetailsViewConfiguration(DEFAULT_CONFIGURATION)\n }\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const setSelectedId = useCallback(\n (entityId: string) => {\n if (toggleSelection) {\n toggleSelection({ targetId: entityId })\n }\n setCurrentContainer(entityId)\n },\n [setCurrentContainer, toggleSelection],\n )\n\n // For these scopes, use the `useGetProjectsInfinite` hook\n const useProjectData =\n scope === FinderScope.ALL_PROJECTS || scope === FinderScope.CREATED_BY_ME\n\n const {\n data: projectData,\n fetchNextPage: fetchNextPageProjects,\n hasNextPage: hasNextPageProjects,\n isLoading: isLoadingProjects,\n } = useGetProjectsInfinite(\n scope === FinderScope.CREATED_BY_ME\n ? { filter: 'CREATED', sort: 'PROJECT_NAME', sortDirection: 'ASC' }\n : { sort: 'PROJECT_NAME', sortDirection: 'ASC' },\n {\n enabled: useProjectData,\n // Don't refetch the projects. Updating the entity headers will drop all the children that VirtualizedTree has fetched\n refetchInterval: Infinity,\n },\n )\n\n const { data: currentContainerBundle, isSuccess: isSuccessBundle } =\n useGetEntityBundle(currentContainer!, undefined, ALL_ENTITY_BUNDLE_FIELDS, {\n enabled: !!currentContainer && currentContainer !== 'root',\n throwOnError: true,\n })\n\n const { data: favorites, isLoading: isLoadingFavorites } = useGetFavorites(\n 'NAME',\n 'ASC',\n {\n select: data =>\n data.filter(eh => visibleTypes.includes(convertToEntityType(eh.type))),\n // Don't refetch the projects. Updating the entity headers will drop all the children that VirtualizedTree has fetched\n refetchInterval: Infinity,\n throwOnError: true,\n },\n )\n\n const { data: initialContainerPath } = useGetEntityPath(initialContainer!, {\n enabled: !!(\n projectId &&\n initialContainer &&\n initialContainer.match(SYNAPSE_ENTITY_ID_REGEX)\n ),\n refetchInterval: Infinity,\n throwOnError: true,\n })\n\n const { data: projectHeader, isLoading: isLoadingProjectHeader } =\n useGetEntityHeader(projectId, undefined, {\n enabled: !!(projectId ?? initialContainerPath?.path[1]?.id),\n refetchInterval: Infinity,\n })\n\n useEffect(() => {\n if (\n FinderScope.CURRENT_PROJECT === scope &&\n projectId &&\n !isLoadingProjectHeader &&\n !projectHeader\n ) {\n // The header wasn't returned, so the user doesn't have access to the current project\n // Let's change the scope to something else\n displayToast(\n `You don't have access to the current project (${projectId}).`,\n 'warning',\n )\n setScope(FinderScope.CREATED_BY_ME)\n }\n }, [isLoadingProjectHeader, projectHeader, projectId, scope])\n\n // Populates the first level of entities in the tree view\n const {\n topLevelEntities,\n isLoading,\n }: {\n topLevelEntities: Pick<EntityFinderHeader, 'name' | 'id' | 'type'>[]\n isLoading: boolean\n } = useMemo(() => {\n let topLevelEntities: Pick<EntityFinderHeader, 'name' | 'id' | 'type'>[] =\n []\n let isLoading: boolean = false\n switch (scope) {\n case FinderScope.ALL_PROJECTS:\n case FinderScope.CREATED_BY_ME:\n if (projectData) {\n topLevelEntities = projectData.pages\n .flatMap(page => page.results)\n .map(toEntityHeader)\n }\n isLoading = isLoadingProjects\n break\n case FinderScope.FAVORITES: {\n topLevelEntities = favorites ?? []\n isLoading = isLoadingFavorites\n break\n }\n case FinderScope.CURRENT_PROJECT:\n if (projectHeader) {\n // use projectHeader as topLevelEntities\n topLevelEntities = [projectHeader]\n isLoading = isLoadingProjectHeader\n }\n break\n default:\n throw new Error('No scope selected')\n }\n return { topLevelEntities, isLoading }\n }, [\n favorites,\n isLoadingFavorites,\n isLoadingProjectHeader,\n isLoadingProjects,\n projectData,\n projectHeader,\n scope,\n ])\n\n // Creates the configuration for the details view and invokes the callback\n useEffect(() => {\n if (setDetailsViewConfiguration || setBreadcrumbItems) {\n let detailsViewConfig: EntityDetailsListDataConfiguration\n let breadcrumbItems: BreadcrumbItem[] = []\n if (currentContainer === null) {\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.PROMPT,\n }\n breadcrumbItems = []\n } else if (currentContainer === 'root') {\n switch (scope) {\n case FinderScope.ALL_PROJECTS:\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.USER_PROJECTS,\n }\n break\n case FinderScope.CREATED_BY_ME:\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.USER_PROJECTS,\n getProjectParams: {\n filter: 'CREATED',\n },\n }\n break\n case FinderScope.CURRENT_PROJECT:\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.HEADER_LIST,\n headerList: topLevelEntities,\n }\n break\n case FinderScope.FAVORITES:\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.USER_FAVORITES,\n }\n break\n }\n breadcrumbItems = [\n {\n name: scope,\n isCurrent: true,\n action: () => {\n setCurrentContainer('root')\n },\n },\n ]\n } else {\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.PARENT_CONTAINER,\n parentContainerId: currentContainer,\n }\n if (currentContainerBundle) {\n breadcrumbItems = [\n {\n name: scope,\n isCurrent: false,\n action: () => {\n setCurrentContainer('root')\n },\n },\n ...currentContainerBundle.path.path\n .slice(1) // Remove the root entity, syn4489\n .map(entity => {\n return {\n name: entity.name ?? entity.id,\n isCurrent: entity.id === currentContainer,\n action: () => {\n setCurrentContainer(entity.id)\n },\n }\n }),\n ]\n }\n }\n if (setDetailsViewConfiguration) {\n setDetailsViewConfiguration(detailsViewConfig)\n }\n if (setBreadcrumbItems) {\n setBreadcrumbItems(breadcrumbItems)\n }\n }\n }, [\n scope,\n currentContainer,\n topLevelEntities,\n setDetailsViewConfiguration,\n setBreadcrumbItems,\n currentContainerBundle,\n isSuccessBundle,\n setCurrentContainer,\n ])\n\n const rootNodeConfiguration: RootNodeConfiguration = useMemo(\n () => ({\n show: showScopeAsRootNode,\n nodeText: getScopeOptionNodeName(scope),\n children: topLevelEntities,\n fetchNextPage: async () => {\n await fetchNextPageProjects()\n },\n hasNextPage: useProjectData && hasNextPageProjects && !isLoadingProjects,\n }),\n [\n showScopeAsRootNode,\n scope,\n topLevelEntities,\n useProjectData,\n hasNextPageProjects,\n isLoadingProjects,\n fetchNextPageProjects,\n ],\n )\n\n const shouldAutoExpand = useCallback(\n (entityId: string) => {\n if (entityId === 'root') {\n return true\n } else {\n return !!(\n scope === FinderScope.CURRENT_PROJECT &&\n initialContainerPath &&\n isEntityIdInPath(entityId, initialContainerPath)\n )\n }\n },\n [scope, initialContainerPath],\n )\n\n const filteredOptions = Object.values(FinderScope).filter(\n scopeOption =>\n !(scopeOption === FinderScope.CURRENT_PROJECT && projectId == null),\n )\n\n const selectedIndex = filteredOptions.indexOf(scope)\n\n return (\n <div\n className={`TreeView ${\n treeNodeType === EntityTreeNodeType.SINGLE_PANE\n ? 'SelectTree'\n : 'BrowseTree'\n }`}\n >\n {!hideScopeSelector && (\n <div className=\"Header\" onClick={e => e.stopPropagation()}>\n <DropdownSelect\n variant={'outlined'}\n options={filteredOptions}\n selectedIndex={selectedIndex}\n setSelectedIndex={index => {\n const selectedScope = filteredOptions[index]\n if (scope !== selectedScope) {\n setScope(selectedScope)\n setCurrentContainer(\n getScopeOptionDefaultContainer(selectedScope),\n )\n }\n }}\n size=\"small\"\n fullWidth\n />\n </div>\n )}\n {isLoading ? (\n <div className=\"Placeholder\">\n <SynapseSpinner size={30} />\n </div>\n ) : (\n <div className=\"Tree\" role=\"tree\">\n <VirtualizedTree\n selected={selectedEntities}\n visibleTypes={visibleTypes}\n autoExpand={shouldAutoExpand}\n rootNodeConfiguration={rootNodeConfiguration}\n treeNodeType={treeNodeType}\n selectableTypes={selectableTypes}\n currentContainer={currentContainer}\n setSelectedId={setSelectedId}\n />\n </div>\n )}\n </div>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"EntityTree.js","names":[],"sources":["../../../../src/components/EntityFinder/tree/EntityTree.tsx"],"sourcesContent":["import {\n useGetEntityHeader,\n useGetEntityPath,\n useGetFavorites,\n useGetProjectsInfinite,\n} from '@/synapse-queries'\nimport useGetEntityBundle from '@/synapse-queries/entity/useEntityBundle'\nimport { convertToEntityType } from '@/utils/functions/EntityTypeUtils'\nimport { SYNAPSE_ENTITY_ID_REGEX } from '@/utils/functions/RegularExpressions'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n ALL_ENTITY_BUNDLE_FIELDS,\n EntityPath,\n Reference,\n} from '@sage-bionetworks/synapse-types'\nimport {\n Dispatch,\n SetStateAction,\n useCallback,\n useEffect,\n useMemo,\n useState,\n} from 'react'\nimport DropdownSelect from '../../DropdownSelect/DropdownSelect'\nimport { SynapseSpinner } from '../../LoadingScreen/LoadingScreen'\nimport { displayToast } from '../../ToastMessage/ToastMessage'\nimport { BreadcrumbItem } from '../Breadcrumbs'\nimport { toEntityHeader } from '../details/configurations/ProjectListDetails'\nimport {\n EntityDetailsListDataConfiguration,\n EntityDetailsListDataConfigurationType,\n} from '../details/EntityDetailsList'\nimport { EntityFinderHeader } from '../EntityFinderHeader'\nimport { EntitySelectionMapType } from '../useEntitySelection'\nimport {\n EntityTreeNodeType,\n RootNodeConfiguration,\n VirtualizedTree,\n} from './VirtualizedTree'\n\nconst isEntityIdInPath = (entityId: string, path: EntityPath): boolean => {\n for (const eh of path.path) {\n if (entityId === eh.id) {\n return true\n }\n }\n return false\n}\n\nexport enum FinderScope {\n CURRENT_PROJECT = 'Current Project',\n ALL_PROJECTS = 'All Projects',\n CREATED_BY_ME = 'Projects Created By Me',\n FAVORITES = 'My Favorites',\n}\n\nfunction getScopeOptionDefaultContainer(\n scope: FinderScope,\n): EntityTreeContainer {\n switch (scope) {\n case FinderScope.FAVORITES:\n return 'root'\n case FinderScope.CURRENT_PROJECT:\n case FinderScope.ALL_PROJECTS:\n case FinderScope.CREATED_BY_ME:\n return null\n }\n}\n\nfunction getScopeOptionNodeName(scope: FinderScope): string {\n switch (scope) {\n case FinderScope.CURRENT_PROJECT:\n case FinderScope.ALL_PROJECTS:\n case FinderScope.CREATED_BY_ME:\n return 'Projects'\n case FinderScope.FAVORITES:\n return 'Favorites'\n }\n}\n\n/**\n * Indicates which container is selected when the tree is used to control another component. If 'root', then the top-level entities\n * should be shown in the other component. If a synID, then that entity's children should be shown in the other component. If null,\n * then a selection has not been made.\n */\nexport type EntityTreeContainer = string | 'root' | null\n\n// if the first item is selected (matching the dropdown), then output a configuration. otherwise, output a synId\nexport type EntityTreeProps = {\n initialScope?: FinderScope\n /** To show the current project, projectId must be defined */\n projectId?: string\n initialContainer: EntityTreeContainer\n currentContainer: EntityTreeContainer\n setCurrentContainer: Dispatch<SetStateAction<EntityTreeContainer>>\n showDropdown: boolean\n selectedEntities: EntitySelectionMapType\n visibleTypes?: EntityType[]\n toggleSelection?: (entity: Reference) => void\n setDetailsViewConfiguration?: (\n configuration: EntityDetailsListDataConfiguration,\n ) => void\n setBreadcrumbItems?: (items: BreadcrumbItem[]) => void\n /** Determines whether to show the root node corresponding to the selected scope */\n showScopeAsRootNode?: boolean\n treeNodeType: EntityTreeNodeType\n /** The entity types that may be selected. */\n selectableTypes: EntityType[]\n hideScopeSelector?: boolean\n}\n\n/**\n * The TreeView displays a user's entities hierarchically, allowing a user to quickly dive into an entity tree.\n *\n * The tree view currently can only be used to drive a DetailsView using the `setDetailsViewConfiguration` property.\n */\nexport function EntityTree(props: EntityTreeProps) {\n const {\n initialScope = FinderScope.CURRENT_PROJECT,\n projectId,\n initialContainer = null,\n currentContainer,\n setCurrentContainer,\n visibleTypes = [EntityType.project, EntityType.folder],\n toggleSelection,\n selectedEntities,\n setDetailsViewConfiguration,\n setBreadcrumbItems,\n showScopeAsRootNode = true,\n treeNodeType,\n selectableTypes,\n hideScopeSelector = false,\n } = props\n\n const DEFAULT_CONFIGURATION: EntityDetailsListDataConfiguration = {\n type: EntityDetailsListDataConfigurationType.PROMPT,\n }\n\n const [scope, setScope] = useState(initialScope)\n\n useEffect(() => {\n if (setDetailsViewConfiguration) {\n setDetailsViewConfiguration(DEFAULT_CONFIGURATION)\n }\n // oxlint-disable-next-line react-hooks/exhaustive-deps\n }, [])\n\n const setSelectedId = useCallback(\n (entityId: string) => {\n if (toggleSelection) {\n toggleSelection({ targetId: entityId })\n }\n setCurrentContainer(entityId)\n },\n [setCurrentContainer, toggleSelection],\n )\n\n // For these scopes, use the `useGetProjectsInfinite` hook\n const useProjectData =\n scope === FinderScope.ALL_PROJECTS || scope === FinderScope.CREATED_BY_ME\n\n const {\n data: projectData,\n fetchNextPage: fetchNextPageProjects,\n hasNextPage: hasNextPageProjects,\n isLoading: isLoadingProjects,\n } = useGetProjectsInfinite(\n scope === FinderScope.CREATED_BY_ME\n ? { filter: 'CREATED', sort: 'PROJECT_NAME', sortDirection: 'ASC' }\n : { sort: 'PROJECT_NAME', sortDirection: 'ASC' },\n {\n enabled: useProjectData,\n // Don't refetch the projects. Updating the entity headers will drop all the children that VirtualizedTree has fetched\n refetchInterval: Infinity,\n },\n )\n\n const { data: currentContainerBundle, isSuccess: isSuccessBundle } =\n useGetEntityBundle(currentContainer!, undefined, ALL_ENTITY_BUNDLE_FIELDS, {\n enabled: !!currentContainer && currentContainer !== 'root',\n throwOnError: true,\n })\n\n const { data: favorites, isLoading: isLoadingFavorites } = useGetFavorites(\n 'NAME',\n 'ASC',\n {\n select: data =>\n data.filter(eh => visibleTypes.includes(convertToEntityType(eh.type))),\n // Don't refetch the projects. Updating the entity headers will drop all the children that VirtualizedTree has fetched\n refetchInterval: Infinity,\n throwOnError: true,\n },\n )\n\n const { data: initialContainerPath } = useGetEntityPath(initialContainer!, {\n enabled: !!(\n projectId &&\n initialContainer &&\n initialContainer.match(SYNAPSE_ENTITY_ID_REGEX)\n ),\n refetchInterval: Infinity,\n throwOnError: true,\n })\n\n const { data: projectHeader, isLoading: isLoadingProjectHeader } =\n useGetEntityHeader(projectId, undefined, {\n enabled: !!(projectId ?? initialContainerPath?.path[1]?.id),\n refetchInterval: Infinity,\n })\n\n useEffect(() => {\n if (\n FinderScope.CURRENT_PROJECT === scope &&\n projectId &&\n !isLoadingProjectHeader &&\n !projectHeader\n ) {\n // The header wasn't returned, so the user doesn't have access to the current project\n // Let's change the scope to something else\n displayToast(\n `You don't have access to the current project (${projectId}).`,\n 'warning',\n )\n setScope(FinderScope.CREATED_BY_ME)\n }\n }, [isLoadingProjectHeader, projectHeader, projectId, scope])\n\n // Populates the first level of entities in the tree view\n const {\n topLevelEntities,\n isLoading,\n }: {\n topLevelEntities: Pick<EntityFinderHeader, 'name' | 'id' | 'type'>[]\n isLoading: boolean\n } = useMemo(() => {\n let topLevelEntities: Pick<EntityFinderHeader, 'name' | 'id' | 'type'>[] =\n []\n let isLoading: boolean = false\n switch (scope) {\n case FinderScope.ALL_PROJECTS:\n case FinderScope.CREATED_BY_ME:\n if (projectData) {\n topLevelEntities = projectData.pages\n .flatMap(page => page.results)\n .map(toEntityHeader)\n }\n isLoading = isLoadingProjects\n break\n case FinderScope.FAVORITES: {\n topLevelEntities = favorites ?? []\n isLoading = isLoadingFavorites\n break\n }\n case FinderScope.CURRENT_PROJECT:\n if (projectHeader) {\n // use projectHeader as topLevelEntities\n topLevelEntities = [projectHeader]\n isLoading = isLoadingProjectHeader\n }\n break\n default:\n throw new Error('No scope selected')\n }\n return { topLevelEntities, isLoading }\n }, [\n favorites,\n isLoadingFavorites,\n isLoadingProjectHeader,\n isLoadingProjects,\n projectData,\n projectHeader,\n scope,\n ])\n\n // Creates the configuration for the details view and invokes the callback\n useEffect(() => {\n if (setDetailsViewConfiguration || setBreadcrumbItems) {\n let detailsViewConfig: EntityDetailsListDataConfiguration\n let breadcrumbItems: BreadcrumbItem[] = []\n if (currentContainer === null) {\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.PROMPT,\n }\n breadcrumbItems = []\n } else if (currentContainer === 'root') {\n switch (scope) {\n case FinderScope.ALL_PROJECTS:\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.USER_PROJECTS,\n }\n break\n case FinderScope.CREATED_BY_ME:\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.USER_PROJECTS,\n getProjectParams: {\n filter: 'CREATED',\n },\n }\n break\n case FinderScope.CURRENT_PROJECT:\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.HEADER_LIST,\n headerList: topLevelEntities,\n }\n break\n case FinderScope.FAVORITES:\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.USER_FAVORITES,\n }\n break\n }\n breadcrumbItems = [\n {\n name: scope,\n isCurrent: true,\n action: () => {\n setCurrentContainer('root')\n },\n },\n ]\n } else {\n detailsViewConfig = {\n type: EntityDetailsListDataConfigurationType.PARENT_CONTAINER,\n parentContainerId: currentContainer,\n }\n if (currentContainerBundle) {\n breadcrumbItems = [\n {\n name: scope,\n isCurrent: false,\n action: () => {\n setCurrentContainer('root')\n },\n },\n ...currentContainerBundle.path.path\n .slice(1) // Remove the root entity, syn4489\n .map(entity => {\n return {\n name: entity.name ?? entity.id,\n isCurrent: entity.id === currentContainer,\n action: () => {\n setCurrentContainer(entity.id)\n },\n }\n }),\n ]\n }\n }\n if (setDetailsViewConfiguration) {\n setDetailsViewConfiguration(detailsViewConfig)\n }\n if (setBreadcrumbItems) {\n setBreadcrumbItems(breadcrumbItems)\n }\n }\n }, [\n scope,\n currentContainer,\n topLevelEntities,\n setDetailsViewConfiguration,\n setBreadcrumbItems,\n currentContainerBundle,\n isSuccessBundle,\n setCurrentContainer,\n ])\n\n const rootNodeConfiguration: RootNodeConfiguration = useMemo(\n () => ({\n show: showScopeAsRootNode,\n nodeText: getScopeOptionNodeName(scope),\n children: topLevelEntities,\n fetchNextPage: async () => {\n await fetchNextPageProjects()\n },\n hasNextPage: useProjectData && hasNextPageProjects && !isLoadingProjects,\n }),\n [\n showScopeAsRootNode,\n scope,\n topLevelEntities,\n useProjectData,\n hasNextPageProjects,\n isLoadingProjects,\n fetchNextPageProjects,\n ],\n )\n\n const shouldAutoExpand = useCallback(\n (entityId: string) => {\n if (entityId === 'root') {\n return true\n } else {\n return !!(\n scope === FinderScope.CURRENT_PROJECT &&\n initialContainerPath &&\n isEntityIdInPath(entityId, initialContainerPath)\n )\n }\n },\n [scope, initialContainerPath],\n )\n\n const filteredOptions = Object.values(FinderScope).filter(\n scopeOption =>\n !(scopeOption === FinderScope.CURRENT_PROJECT && projectId == null),\n )\n\n const selectedIndex = filteredOptions.indexOf(scope)\n\n return (\n <div\n className={`TreeView ${\n treeNodeType === EntityTreeNodeType.SINGLE_PANE\n ? 'SelectTree'\n : 'BrowseTree'\n }`}\n >\n {!hideScopeSelector && (\n <div className=\"Header\" onClick={e => e.stopPropagation()}>\n <DropdownSelect\n variant={'outlined'}\n options={filteredOptions}\n selectedIndex={selectedIndex}\n setSelectedIndex={index => {\n const selectedScope = filteredOptions[index]\n if (scope !== selectedScope) {\n setScope(selectedScope)\n setCurrentContainer(\n getScopeOptionDefaultContainer(selectedScope),\n )\n }\n }}\n size=\"small\"\n fullWidth\n />\n </div>\n )}\n {isLoading ? (\n <div className=\"Placeholder\">\n <SynapseSpinner size={30} />\n </div>\n ) : (\n <div className=\"Tree\" role=\"tree\">\n <VirtualizedTree\n selected={selectedEntities}\n visibleTypes={visibleTypes}\n autoExpand={shouldAutoExpand}\n rootNodeConfiguration={rootNodeConfiguration}\n treeNodeType={treeNodeType}\n selectableTypes={selectableTypes}\n currentContainer={currentContainer}\n setSelectedId={setSelectedId}\n />\n </div>\n )}\n </div>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAwCA,IAAM,KAAoB,GAAkB,MAA8B;CACxE,KAAK,IAAM,KAAM,EAAK,MACpB,IAAI,MAAa,EAAG,IAClB,OAAO;CAGX,OAAO;AACT,GAEY,IAAL,yBAAA,GAAA;QACL,EAAA,kBAAA,mBACA,EAAA,eAAA,gBACA,EAAA,gBAAA,0BACA,EAAA,YAAA;AACF,EAAA,CAAA,CAAA;AAEA,SAAS,GACP,GACqB;CACrB,QAAQ,GAAR;EACE,KAAA,gBACE,OAAO;EACT,KAAA;EACA,KAAA;EACA,KAAA,0BACE,OAAO;CACX;AACF;AAEA,SAAS,EAAuB,GAA4B;CAC1D,QAAQ,GAAR;EACE,KAAA;EACA,KAAA;EACA,KAAA,0BACE,OAAO;EACT,KAAA,gBACE,OAAO;CACX;AACF;AAsCA,SAAgB,EAAW,GAAwB;CACjD,IAAM,EACJ,kBAAA,mBACA,cACA,sBAAmB,MACnB,qBACA,wBACA,kBAAe,CAAC,EAAW,SAAS,EAAW,MAAM,GACrD,oBACA,sBACA,gCACA,uBACA,yBAAsB,IACtB,iBACA,oBACA,uBAAoB,OAClB,GAEE,IAA4D,EAChE,MAAM,EAAuC,OAC/C,GAEM,CAAC,GAAO,KAAY,EAAS,CAAY;CAE/C,QAAgB;EACd,AAAI,KACF,EAA4B,CAAqB;CAGrD,GAAG,CAAC,CAAC;CAEL,IAAM,IAAgB,GACnB,MAAqB;EAIpB,AAHI,KACF,EAAgB,EAAE,UAAU,EAAS,CAAC,GAExC,EAAoB,CAAQ;CAC9B,GACA,CAAC,GAAqB,CAAe,CACvC,GAGM,IACJ,MAAA,kBAAsC,MAAA,0BAElC,EACJ,MAAM,GACN,eAAe,GACf,aAAa,GACb,WAAW,MACT,EACF,MAAA,2BACI;EAAE,QAAQ;EAAW,MAAM;EAAgB,eAAe;CAAM,IAChE;EAAE,MAAM;EAAgB,eAAe;CAAM,GACjD;EACE,SAAS;EAET,iBAAiB;CACnB,CACF,GAEM,EAAE,MAAM,GAAwB,WAAW,MAC/C,EAAmB,GAAmB,KAAA,GAAW,GAA0B;EACzE,SAAS,CAAC,CAAC,KAAoB,MAAqB;EACpD,cAAc;CAChB,CAAC,GAEG,EAAE,MAAM,GAAW,WAAW,MAAuB,GACzD,QACA,OACA;EACE,SAAQ,MACN,EAAK,QAAO,MAAM,EAAa,SAAS,EAAoB,EAAG,IAAI,CAAC,CAAC;EAEvE,iBAAiB;EACjB,cAAc;CAChB,CACF,GAEM,EAAE,MAAM,MAAyB,EAAiB,GAAmB;EACzE,SAAS,CAAC,EACR,KACA,KACA,EAAiB,MAAM,CAAuB;EAEhD,iBAAiB;EACjB,cAAc;CAChB,CAAC,GAEK,EAAE,MAAM,GAAe,WAAW,MACtC,GAAmB,GAAW,KAAA,GAAW;EACvC,SAAS,CAAC,EAAE,KAAa,GAAsB,KAAK,IAAI;EACxD,iBAAiB;CACnB,CAAC;CAEH,QAAgB;EACd,AACkC,MADlC,qBAEE,KACA,CAAC,KACD,CAAC,MAID,EACE,iDAAiD,EAAU,KAC3D,SACF,GACA,EAAA,wBAAkC;CAEtC,GAAG;EAAC;EAAwB;EAAe;EAAW;CAAK,CAAC;CAG5D,IAAM,EACJ,qBACA,kBAIE,QAAc;EAChB,IAAI,IACF,CAAC,GACC,IAAqB;EACzB,QAAQ,GAAR;GACE,KAAA;GACA,KAAA;IAME,AALI,MACF,IAAmB,EAAY,MAC5B,SAAQ,MAAQ,EAAK,OAAO,EAC5B,IAAI,CAAc,IAEvB,IAAY;IACZ;GACF,KAAA;IAEE,AADA,IAAmB,KAAa,CAAC,GACjC,IAAY;IACZ;GAEF,KAAA;IACE,AAAI,MAEF,IAAmB,CAAC,CAAa,GACjC,IAAY;IAEd;GACF,SACE,MAAU,MAAM,mBAAmB;EACvC;EACA,OAAO;GAAE;GAAkB;EAAU;CACvC,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAGD,QAAgB;EACd,IAAI,KAA+B,GAAoB;GACrD,IAAI,GACA,IAAoC,CAAC;GACzC,IAAI,MAAqB,MAIvB,AAHA,IAAoB,EAClB,MAAM,EAAuC,OAC/C,GACA,IAAkB,CAAC;QACd,IAAI,MAAqB,QAAQ;IACtC,QAAQ,GAAR;KACE,KAAA;MACE,IAAoB,EAClB,MAAM,EAAuC,cAC/C;MACA;KACF,KAAA;MACE,IAAoB;OAClB,MAAM,EAAuC;OAC7C,kBAAkB,EAChB,QAAQ,UACV;MACF;MACA;KACF,KAAA;MACE,IAAoB;OAClB,MAAM,EAAuC;OAC7C,YAAY;MACd;MACA;KACF,KAAA;MACE,IAAoB,EAClB,MAAM,EAAuC,eAC/C;MACA;IACJ;IACA,IAAkB,CAChB;KACE,MAAM;KACN,WAAW;KACX,cAAc;MACZ,EAAoB,MAAM;KAC5B;IACF,CACF;GACF,OAKE,AAJA,IAAoB;IAClB,MAAM,EAAuC;IAC7C,mBAAmB;GACrB,GACI,MACF,IAAkB,CAChB;IACE,MAAM;IACN,WAAW;IACX,cAAc;KACZ,EAAoB,MAAM;IAC5B;GACF,GACA,GAAG,EAAuB,KAAK,KAC5B,MAAM,CAAC,EACP,KAAI,OACI;IACL,MAAM,EAAO,QAAQ,EAAO;IAC5B,WAAW,EAAO,OAAO;IACzB,cAAc;KACZ,EAAoB,EAAO,EAAE;IAC/B;GACF,EACD,CACL;GAMJ,AAHI,KACF,EAA4B,CAAiB,GAE3C,KACF,EAAmB,CAAe;EAEtC;CACF,GAAG;EACD;EACA;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CAAC;CAED,IAAM,KAA+C,SAC5C;EACL,MAAM;EACN,UAAU,EAAuB,CAAK;EACtC,UAAU;EACV,eAAe,YAAY;GACzB,MAAM,EAAsB;EAC9B;EACA,aAAa,KAAkB,KAAuB,CAAC;CACzD,IACA;EACE;EACA;EACA;EACA;EACA;EACA;EACA;CACF,CACF,GAEM,KAAmB,GACtB,MACK,MAAa,SACR,KAEA,CAAC,EACN,MAAA,qBACA,KACA,EAAiB,GAAU,CAAoB,IAIrD,CAAC,GAAO,CAAoB,CAC9B,GAEM,IAAkB,OAAO,OAAO,CAAW,EAAE,QACjD,MACE,EAAE,MAAA,qBAA+C,KAAa,KAClE,GAEM,KAAgB,EAAgB,QAAQ,CAAK;CAEnD,OACE,kBAAC,OAAD;EACE,WAAW,YACT,MAAiB,EAAmB,cAChC,eACA;YAJR,CAOG,CAAC,KACA,kBAAC,OAAD;GAAK,WAAU;GAAS,UAAS,MAAK,EAAE,gBAAgB;aACtD,kBAAC,GAAD;IACE,SAAS;IACT,SAAS;IACM;IACf,mBAAkB,MAAS;KACzB,IAAM,IAAgB,EAAgB;KACtC,AAAI,MAAU,MACZ,EAAS,CAAa,GACtB,EACE,GAA+B,CAAa,CAC9C;IAEJ;IACA,MAAK;IACL,WAAA;GACD,CAAA;EACE,CAAA,GAEN,KACC,kBAAC,OAAD;GAAK,WAAU;aACb,kBAAC,GAAD,EAAgB,MAAM,GAAK,CAAA;EACxB,CAAA,IAEL,kBAAC,OAAD;GAAK,WAAU;GAAO,MAAK;aACzB,kBAAC,IAAD;IACE,UAAU;IACI;IACd,YAAY;IACW;IACT;IACG;IACC;IACH;GAChB,CAAA;EACE,CAAA,CAEJ;;AAET"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"VirtualizedTree.js","names":[],"sources":["../../../../src/components/EntityFinder/tree/VirtualizedTree.tsx"],"sourcesContent":["import React from 'react'\nimport { getEntityChildren } from '@/synapse-client'\nimport { useSynapseContext } from '@/utils'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport {\n getEntityTypeFromHeader,\n isContainerType,\n} from '@/utils/functions/EntityTypeUtils'\nimport { Writable } from '@/utils/types/Writable'\nimport { ChevronRight, ExpandMore } from '@mui/icons-material'\nimport { Skeleton, Tooltip, Typography } from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { EntityChildrenRequest } from '@sage-bionetworks/synapse-types'\nimport { useQueryClient } from '@tanstack/react-query'\nimport dayjs from 'dayjs'\nimport { cloneDeep } from 'lodash-es'\nimport { ReactNode, useCallback, useEffect, useRef, useState } from 'react'\nimport { useInView } from 'react-intersection-observer'\nimport AutoSizer from 'react-virtualized-auto-sizer'\nimport {\n TreeWalker,\n TreeWalkerValue,\n VariableSizeNodeData,\n VariableSizeNodePublicState,\n VariableSizeTree,\n} from 'react-vtree'\nimport { NodeComponentProps } from 'react-vtree/dist/es/Tree'\nimport { EntityBadgeIcons } from '../../EntityBadgeIcons'\nimport { EntityTypeIcon } from '../../EntityIcon'\nimport { SynapseSpinner } from '../../LoadingScreen/LoadingScreen'\nimport { UserBadge } from '../../UserCard/UserBadge'\nimport { EntityFinderHeader } from '../EntityFinderHeader'\nimport { EntitySelectionMapType } from '../useEntitySelection'\n\nexport enum EntityTreeNodeType {\n /** The tree component's appearance and interactions will facilitate selection. Nodes will be larger and styles will indicate primary selection */\n SINGLE_PANE,\n /** The tree component's appearance and interactions will facilitate browsing. Nodes will be smaller and styles will indicate secondary selection */\n DUAL_PANE,\n}\n\ntype NodeChildren = Readonly<{\n /** The node's children. If undefined, then children have not been fetched. */\n children?: EntityHeaderNode[]\n /** The token used to fetch the next page of children for this entity. If this property is nullish and children is defined, then all children have been fetched. */\n childrenNextPageToken?: string | null\n}>\n\nexport type EntityHeaderNode = (\n | EntityFinderHeader\n // Only will have a subset of fields if the node is fetched via the entity path:\n | Pick<EntityFinderHeader, 'id' | 'name' | 'type'>\n) &\n NodeChildren\ntype PaginationNode = { __paginationNode: true }\n\ntype TreeNode = EntityHeaderNode | RootNodeConfiguration | PaginationNode\n\nfunction getTreeNodeType(\n node: TreeNode,\n): 'entityHeader' | 'rootNodeConfiguration' | 'pagination' {\n if ('__paginationNode' in node) {\n return 'pagination'\n }\n return 'id' in node ? 'entityHeader' : 'rootNodeConfiguration'\n}\n\nfunction isPaginationNode(node: TreeNode): node is PaginationNode {\n return getTreeNodeType(node) === 'pagination'\n}\n\nfunction isEntityHeaderNode(node: TreeNode): node is EntityHeaderNode {\n return getTreeNodeType(node) === 'entityHeader'\n}\n\nfunction isRootNodeConfiguration(\n node: TreeNode,\n): node is RootNodeConfiguration {\n return getTreeNodeType(node) === 'rootNodeConfiguration'\n}\n\nfunction hasMoreChildren(node: TreeNode) {\n if (isPaginationNode(node)) {\n return false\n } else if (isRootNodeConfiguration(node)) {\n return node.hasNextPage\n }\n\n return node.children == null || node.childrenNextPageToken != null\n}\n\nfunction isLeafNode(node: TreeNode) {\n if (isPaginationNode(node)) {\n return true\n } else if (isRootNodeConfiguration(node)) {\n return false\n } else {\n return (\n // Entity is not a container\n !isContainerType(getEntityTypeFromHeader(node)) ||\n // OR Children have been fetched (nonnull) and there are 0 children\n (node.children != null && node.children.length === 0)\n )\n }\n}\n\nfunction maybeHasChildren(\n node: TreeNode,\n): node is RootNodeConfiguration | EntityHeaderNode {\n if (isPaginationNode(node)) {\n return false\n } else if (isRootNodeConfiguration(node)) {\n return node.children.length > 0 || node.hasNextPage\n } else {\n return !isLeafNode(node)\n }\n}\n\nexport type TreeData = VariableSizeNodeData &\n Readonly<{\n node: TreeNode\n getNextPageOfChildren: () => Promise<void>\n isLeaf: boolean\n nestingLevel: number\n setSelectedId: (entityId: string) => void\n treeNodeType: EntityTreeNodeType\n isSelected: boolean\n isDisabled: boolean\n }>\n\ntype NodeMeta = Readonly<{\n nestingLevel: number\n node: TreeNode\n}>\n\nexport type RootNodeConfiguration = {\n show: boolean\n nodeText: string\n children: EntityHeaderNode[]\n /** If undefined, no more entities to fetch */\n fetchNextPage: () => Promise<void>\n hasNextPage: boolean\n}\n\n/**\n * Converts a TreeNode and related data into a TreeWalkerValue that react-vtree can use to render the tree.\n * Exported for testing purposes only.\n * @param config\n * @returns\n */\nexport const getNodeData = (config: {\n node: TreeNode\n nestingLevel: number\n getNextPageOfChildren: () => Promise<void>\n setSelectedId: (entityId: string) => void\n treeNodeType: EntityTreeNodeType\n selected: EntitySelectionMapType\n selectableTypes: EntityType[]\n autoExpand: (entityId: string) => boolean\n defaultHeight: number\n currentContainer?: string | 'root' | null\n}): TreeWalkerValue<TreeData, NodeMeta> => {\n const {\n node,\n nestingLevel,\n getNextPageOfChildren,\n setSelectedId,\n treeNodeType,\n selected,\n selectableTypes,\n autoExpand,\n defaultHeight,\n currentContainer,\n } = config\n\n if (isPaginationNode(node)) {\n throw new Error('Cannot create data for a pagination node')\n }\n\n const id = isRootNodeConfiguration(node) ? 'root' : node.id\n\n const isSelected =\n treeNodeType === EntityTreeNodeType.SINGLE_PANE\n ? selected.has(id)\n : currentContainer === id\n const isDisabled =\n !isRootNodeConfiguration(node) &&\n !selectableTypes.includes(getEntityTypeFromHeader(node))\n\n const isOpenByDefault = autoExpand(id)\n /*\n * If the node is open by default and we haven't fetched its children,\n * fetch the first page (otherwise we won't fetch unless re-toggled)\n */\n if (isOpenByDefault && node.children == null && hasMoreChildren(node)) {\n getNextPageOfChildren()\n }\n\n return {\n data: {\n node,\n getNextPageOfChildren,\n id: id,\n isLeaf: isLeafNode(node),\n isOpenByDefault: isOpenByDefault,\n nestingLevel,\n setSelectedId,\n treeNodeType,\n isSelected,\n isDisabled,\n defaultHeight,\n },\n nestingLevel,\n node,\n }\n}\n\n/**\n * Node component for the react-vtree virtualized tree. Exported only for testing purposes\n */\nexport function Node(\n props: NodeComponentProps<TreeData, VariableSizeNodePublicState<TreeData>>,\n) {\n const {\n data: {\n node,\n getNextPageOfChildren,\n isLeaf,\n id,\n nestingLevel,\n setSelectedId,\n treeNodeType,\n isSelected,\n isDisabled,\n },\n isOpen,\n style,\n setOpen,\n } = props\n\n const [isLoading, setLoading] = useState(false)\n\n const nodeText = isEntityHeaderNode(node) ? (\n <span>{node.name}</span>\n ) : isRootNodeConfiguration(node) ? (\n <span>{node.nodeText}</span>\n ) : (\n // Pagination node\n <Skeleton width={100} />\n )\n\n // We only use this for pagination nodes. If the pagination node comes into view, then immediately call `getNextPageOfChildren`\n const { ref, inView } = useInView()\n\n useEffect(() => {\n if (isPaginationNode(node) && inView) {\n getNextPageOfChildren()\n }\n }, [node, inView, getNextPageOfChildren])\n\n const toggleExpand = useCallback(async () => {\n if (hasMoreChildren(node)) {\n setLoading(true)\n await getNextPageOfChildren()\n await setOpen(!isOpen)\n setLoading(false)\n } else {\n await setOpen(!isOpen)\n }\n }, [getNextPageOfChildren, node, isOpen, setOpen])\n\n /**\n * If in the dual-pane view, expand a node when it becomes selected\n */\n useEffect(() => {\n if (\n treeNodeType === EntityTreeNodeType.DUAL_PANE &&\n isSelected &&\n !isOpen\n ) {\n toggleExpand()\n }\n // Intentionally only toggle the expanded state when isSelected changes, otherwise the node cannot be un-expanded\n // eslint-disable-next-line react-hooks/exhaustive-deps\n }, [isSelected])\n\n /**\n * If the height is 0, the node is purposefully hidden. Just render a fragment.\n */\n if ('height' in style && style.height === 0) {\n return <></>\n }\n\n let tooltipContent: ReactNode = ''\n if (isEntityHeaderNode(node)) {\n tooltipContent = (\n <div style={{ textAlign: 'center' }}>\n <Typography\n component=\"span\"\n variant=\"smallText1\"\n sx={{\n display: 'inline',\n }}\n >\n {node.name}\n <br />\n <b>ID: </b>\n {node.id}\n {'modifiedBy' in node && (\n <>\n <br />\n <b>Modified By: </b>\n <UserBadge\n userId={node.modifiedBy.toString()}\n showFullName\n disableLink\n showCardOnHover={false}\n />\n </>\n )}\n {'modifiedOn' in node && (\n <>\n <br />\n <b>Modified On: </b>\n {formatDate(dayjs(node.modifiedOn))}\n </>\n )}\n </Typography>\n </div>\n )\n }\n\n const ExpandIcon = isOpen ? ExpandMore : ChevronRight\n\n return (\n <div\n className={`Node ${\n treeNodeType === EntityTreeNodeType.SINGLE_PANE\n ? 'SelectNode'\n : 'BrowseNode'\n }`}\n aria-selected={isSelected}\n aria-disabled={isDisabled}\n onClick={event => {\n event.stopPropagation()\n if (!isDisabled) {\n setSelectedId(id)\n }\n }}\n style={{\n ...style,\n paddingLeft: `${nestingLevel * 20}px`,\n }}\n >\n {!isLeaf && (\n <>\n {isLoading ? (\n <SynapseSpinner size={10} />\n ) : (\n <button\n aria-label={isOpen ? 'Collapse' : 'Expand'}\n onClick={event => {\n event.stopPropagation()\n toggleExpand()\n }}\n >\n <ExpandIcon className=\"ExpandButton\" />\n </button>\n )}\n </>\n )}\n {treeNodeType === EntityTreeNodeType.SINGLE_PANE && ( // SWC-5592\n <div className=\"EntityIcon\">\n {isEntityHeaderNode(node) && (\n <EntityTypeIcon type={getEntityTypeFromHeader(node)} />\n )}\n </div>\n )}\n\n <Tooltip title={tooltipContent} placement=\"right\">\n <div className=\"EntityName\" ref={ref}>\n {nodeText}\n </div>\n </Tooltip>\n\n {treeNodeType === EntityTreeNodeType.SINGLE_PANE && (\n <EntityBadgeIcons\n entityId={id}\n showHasDiscussionThread={false}\n showHasWiki={false}\n showUnlink={false}\n canOpenModal={false}\n />\n )}\n </div>\n )\n}\n\n/**\n * Extracted from the React component for testing purposes\n * @returns a generator function compatible with react-vtree\n */\nexport function getTreeWalkerFunction(\n rootNode: RootNodeConfiguration,\n setSelectedId: VirtualizedTreeProps['setSelectedId'],\n treeNodeType: VirtualizedTreeProps['treeNodeType'],\n selected: VirtualizedTreeProps['selected'],\n selectableTypes: VirtualizedTreeProps['selectableTypes'],\n autoExpand: VirtualizedTreeProps['autoExpand'],\n itemSize: (index?: number) => number,\n currentContainer: VirtualizedTreeProps['currentContainer'],\n fetchNextPageOfChildren: (node: Writable<EntityHeaderNode>) => Promise<void>,\n): TreeWalker<TreeData, NodeMeta> {\n return function* treeWalker() {\n // Step [1]: Define the root node of our tree.\n yield getNodeData({\n node: rootNode,\n nestingLevel: 0,\n getNextPageOfChildren: rootNode.fetchNextPage,\n setSelectedId,\n treeNodeType,\n selected,\n selectableTypes,\n autoExpand,\n defaultHeight: itemSize(),\n currentContainer,\n })\n\n while (true) {\n // Step [2]: Get the parent node and nesting level, which will be passed into the Generator.next function by react-vtree.\n // Yielding `undefined` indicates to react-vtree that we've finished iterating children from the last time we were in the loop.\n const parentMeta = yield\n\n if (maybeHasChildren(parentMeta.node)) {\n // Step [3]: Yielding all the known children of the parent\n if (parentMeta.node.children) {\n for (let i = 0; i < parentMeta.node.children.length; i++) {\n const childNode = parentMeta.node.children[i]\n\n yield getNodeData({\n node: childNode,\n nestingLevel: parentMeta.nestingLevel + 1,\n getNextPageOfChildren: () => fetchNextPageOfChildren(childNode),\n setSelectedId,\n treeNodeType,\n selected,\n selectableTypes,\n autoExpand,\n defaultHeight: itemSize(),\n currentContainer,\n })\n }\n }\n\n // Step [4] - If the parent node has more children, render a \"pagination node\" that will fetch more children when it comes into view (via intersection observer)\n if (hasMoreChildren(parentMeta.node)) {\n const paginationNode: PaginationNode = {\n __paginationNode: true,\n }\n const paginationTreeWalkerValue: TreeWalkerValue<TreeData, NodeMeta> =\n {\n data: {\n id: parentMeta.data.id + '-pagination',\n node: paginationNode,\n isOpenByDefault: false,\n getNextPageOfChildren: parentMeta.data.getNextPageOfChildren,\n isLeaf: true,\n isSelected: false,\n defaultHeight: itemSize(),\n isDisabled: true,\n nestingLevel: parentMeta.nestingLevel + 1,\n setSelectedId: () => {},\n treeNodeType,\n },\n nestingLevel: parentMeta.nestingLevel + 1,\n node: {\n __paginationNode: true,\n },\n }\n yield paginationTreeWalkerValue\n }\n }\n }\n }\n}\n\nexport type VirtualizedTreeProps = Readonly<{\n treeNodeType: EntityTreeNodeType\n rootNodeConfiguration: RootNodeConfiguration\n setSelectedId: (entityId: string) => void\n selected: EntitySelectionMapType\n /* currentContainer is the container whose contents are shown on in the right pane in dual-pane configuration, and may only be defined when treeNodeType is DUAL_PANE */\n currentContainer?: string | 'root' | null\n autoExpand: (entityId: string) => boolean\n selectableTypes: EntityType[]\n visibleTypes: EntityType[]\n}>\n\n/**\n * Component that utilizes react-vtree to efficiently display a tree of entities. react-vtree utilizes react-window\n * to only render visible nodes, which eliminates performance issues as seen in SWC-5978.\n */\nexport const VirtualizedTree = (\n props: VirtualizedTreeProps,\n): React.ReactNode => {\n const {\n rootNodeConfiguration,\n setSelectedId,\n treeNodeType,\n selected,\n currentContainer,\n selectableTypes,\n visibleTypes,\n autoExpand,\n } = props\n\n const { accessToken, keyFactory } = useSynapseContext()\n const queryClient = useQueryClient()\n\n const [rootNode, setRootNode] = useState<RootNodeConfiguration>(\n rootNodeConfiguration,\n )\n\n const treeInstance = useRef<VariableSizeTree<TreeData>>(null)\n\n useEffect(() => {\n setRootNode(rootNodeConfiguration)\n }, [rootNodeConfiguration, rootNodeConfiguration.children])\n\n // This function is used by VariableSizeTree to identify the size of each node in the tree.\n const itemSize = useCallback(\n (index?: number) => {\n /**\n * We must have a root node, but we don't always want to show it.\n * In those cases, set the height of the root node to 0.\n */\n if (index === 0 && !rootNodeConfiguration.show) {\n return 0\n }\n /**\n * The height of all other nodes in the tree varies depending on the tree node type.\n */\n return treeNodeType === EntityTreeNodeType.DUAL_PANE ? 30 : 60\n },\n [treeNodeType, rootNodeConfiguration.show],\n )\n\n /**\n * Fetches the next page of children for a given node. After fetching the children, this method will make a deep clone of the\n * full tree, including the new data, and updates the state of the component\n */\n const fetchNextPageOfChildren = useCallback(\n // Because we update the root node with a copy at the end of this function, we can write to the node under update.\n async (node: Writable<EntityHeaderNode>) => {\n // Fetch the children of the node\n const entityChildrenRequest: EntityChildrenRequest = {\n parentId: node.id,\n nextPageToken: node.childrenNextPageToken,\n includeTypes: visibleTypes,\n }\n const children = await queryClient.fetchQuery({\n queryKey: keyFactory.getEntityChildrenQueryKey(\n entityChildrenRequest,\n false,\n ),\n queryFn: () => getEntityChildren(entityChildrenRequest, accessToken),\n })\n // Update the node data -- add the children and store the nextPageToken\n if (node.children) {\n for (const newChild of children.page) {\n // SWC-6751 - Prevent adding duplicate entries in case this function is called twice\n if (!node.children.find(child => child.id == newChild.id)) {\n node.children.push(newChild)\n }\n }\n } else {\n node.children = children.page\n }\n node.childrenNextPageToken = children.nextPageToken\n\n // Ensure the node for which we fetched children is expanded/open\n if (treeInstance.current) {\n await treeInstance.current.recomputeTree({\n [node.id]: {\n open: true,\n },\n })\n }\n\n // cloneDeep is required to re-render the tree with the new children\n setRootNode(cloneDeep(rootNode))\n },\n [visibleTypes, queryClient, keyFactory, rootNode, accessToken],\n )\n\n /**\n * treeWalker is a generator function used by react-vtree to generate the tree structure. The tree is re-built when the function is updated,\n * so the dependencies specified in useCallback are important.\n */\n const memoizedTreeWalker = useCallback(\n getTreeWalkerFunction(\n rootNode,\n setSelectedId,\n treeNodeType,\n selected,\n selectableTypes,\n autoExpand,\n itemSize,\n currentContainer,\n fetchNextPageOfChildren,\n ),\n [\n rootNode,\n setSelectedId,\n treeNodeType,\n selected,\n selectableTypes,\n autoExpand,\n currentContainer,\n fetchNextPageOfChildren,\n itemSize,\n ],\n )\n\n return (\n <AutoSizer disableWidth>\n {({ height }: { height: number }) => (\n <VariableSizeTree\n ref={treeInstance}\n treeWalker={memoizedTreeWalker}\n itemSize={itemSize}\n height={height}\n async={true}\n width=\"100%\"\n >\n {Node}\n </VariableSizeTree>\n )}\n </AutoSizer>\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"VirtualizedTree.js","names":[],"sources":["../../../../src/components/EntityFinder/tree/VirtualizedTree.tsx"],"sourcesContent":["import React from 'react'\nimport { getEntityChildren } from '@/synapse-client'\nimport { useSynapseContext } from '@/utils'\nimport { formatDate } from '@/utils/functions/DateFormatter'\nimport {\n getEntityTypeFromHeader,\n isContainerType,\n} from '@/utils/functions/EntityTypeUtils'\nimport { Writable } from '@/utils/types/Writable'\nimport { ChevronRight, ExpandMore } from '@mui/icons-material'\nimport { Skeleton, Tooltip, Typography } from '@mui/material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport { EntityChildrenRequest } from '@sage-bionetworks/synapse-types'\nimport { useQueryClient } from '@tanstack/react-query'\nimport dayjs from 'dayjs'\nimport { cloneDeep } from 'lodash-es'\nimport { ReactNode, useCallback, useEffect, useRef, useState } from 'react'\nimport { useInView } from 'react-intersection-observer'\nimport AutoSizer from 'react-virtualized-auto-sizer'\nimport {\n TreeWalker,\n TreeWalkerValue,\n VariableSizeNodeData,\n VariableSizeNodePublicState,\n VariableSizeTree,\n} from 'react-vtree'\nimport { NodeComponentProps } from 'react-vtree/dist/es/Tree'\nimport { EntityBadgeIcons } from '../../EntityBadgeIcons'\nimport { EntityTypeIcon } from '../../EntityIcon'\nimport { SynapseSpinner } from '../../LoadingScreen/LoadingScreen'\nimport { UserBadge } from '../../UserCard/UserBadge'\nimport { EntityFinderHeader } from '../EntityFinderHeader'\nimport { EntitySelectionMapType } from '../useEntitySelection'\n\nexport enum EntityTreeNodeType {\n /** The tree component's appearance and interactions will facilitate selection. Nodes will be larger and styles will indicate primary selection */\n SINGLE_PANE,\n /** The tree component's appearance and interactions will facilitate browsing. Nodes will be smaller and styles will indicate secondary selection */\n DUAL_PANE,\n}\n\ntype NodeChildren = Readonly<{\n /** The node's children. If undefined, then children have not been fetched. */\n children?: EntityHeaderNode[]\n /** The token used to fetch the next page of children for this entity. If this property is nullish and children is defined, then all children have been fetched. */\n childrenNextPageToken?: string | null\n}>\n\nexport type EntityHeaderNode = (\n | EntityFinderHeader\n // Only will have a subset of fields if the node is fetched via the entity path:\n | Pick<EntityFinderHeader, 'id' | 'name' | 'type'>\n) &\n NodeChildren\ntype PaginationNode = { __paginationNode: true }\n\ntype TreeNode = EntityHeaderNode | RootNodeConfiguration | PaginationNode\n\nfunction getTreeNodeType(\n node: TreeNode,\n): 'entityHeader' | 'rootNodeConfiguration' | 'pagination' {\n if ('__paginationNode' in node) {\n return 'pagination'\n }\n return 'id' in node ? 'entityHeader' : 'rootNodeConfiguration'\n}\n\nfunction isPaginationNode(node: TreeNode): node is PaginationNode {\n return getTreeNodeType(node) === 'pagination'\n}\n\nfunction isEntityHeaderNode(node: TreeNode): node is EntityHeaderNode {\n return getTreeNodeType(node) === 'entityHeader'\n}\n\nfunction isRootNodeConfiguration(\n node: TreeNode,\n): node is RootNodeConfiguration {\n return getTreeNodeType(node) === 'rootNodeConfiguration'\n}\n\nfunction hasMoreChildren(node: TreeNode) {\n if (isPaginationNode(node)) {\n return false\n } else if (isRootNodeConfiguration(node)) {\n return node.hasNextPage\n }\n\n return node.children == null || node.childrenNextPageToken != null\n}\n\nfunction isLeafNode(node: TreeNode) {\n if (isPaginationNode(node)) {\n return true\n } else if (isRootNodeConfiguration(node)) {\n return false\n } else {\n return (\n // Entity is not a container\n !isContainerType(getEntityTypeFromHeader(node)) ||\n // OR Children have been fetched (nonnull) and there are 0 children\n (node.children != null && node.children.length === 0)\n )\n }\n}\n\nfunction maybeHasChildren(\n node: TreeNode,\n): node is RootNodeConfiguration | EntityHeaderNode {\n if (isPaginationNode(node)) {\n return false\n } else if (isRootNodeConfiguration(node)) {\n return node.children.length > 0 || node.hasNextPage\n } else {\n return !isLeafNode(node)\n }\n}\n\nexport type TreeData = VariableSizeNodeData &\n Readonly<{\n node: TreeNode\n getNextPageOfChildren: () => Promise<void>\n isLeaf: boolean\n nestingLevel: number\n setSelectedId: (entityId: string) => void\n treeNodeType: EntityTreeNodeType\n isSelected: boolean\n isDisabled: boolean\n }>\n\ntype NodeMeta = Readonly<{\n nestingLevel: number\n node: TreeNode\n}>\n\nexport type RootNodeConfiguration = {\n show: boolean\n nodeText: string\n children: EntityHeaderNode[]\n /** If undefined, no more entities to fetch */\n fetchNextPage: () => Promise<void>\n hasNextPage: boolean\n}\n\n/**\n * Converts a TreeNode and related data into a TreeWalkerValue that react-vtree can use to render the tree.\n * Exported for testing purposes only.\n * @param config\n * @returns\n */\nexport const getNodeData = (config: {\n node: TreeNode\n nestingLevel: number\n getNextPageOfChildren: () => Promise<void>\n setSelectedId: (entityId: string) => void\n treeNodeType: EntityTreeNodeType\n selected: EntitySelectionMapType\n selectableTypes: EntityType[]\n autoExpand: (entityId: string) => boolean\n defaultHeight: number\n currentContainer?: string | 'root' | null\n}): TreeWalkerValue<TreeData, NodeMeta> => {\n const {\n node,\n nestingLevel,\n getNextPageOfChildren,\n setSelectedId,\n treeNodeType,\n selected,\n selectableTypes,\n autoExpand,\n defaultHeight,\n currentContainer,\n } = config\n\n if (isPaginationNode(node)) {\n throw new Error('Cannot create data for a pagination node')\n }\n\n const id = isRootNodeConfiguration(node) ? 'root' : node.id\n\n const isSelected =\n treeNodeType === EntityTreeNodeType.SINGLE_PANE\n ? selected.has(id)\n : currentContainer === id\n const isDisabled =\n !isRootNodeConfiguration(node) &&\n !selectableTypes.includes(getEntityTypeFromHeader(node))\n\n const isOpenByDefault = autoExpand(id)\n /*\n * If the node is open by default and we haven't fetched its children,\n * fetch the first page (otherwise we won't fetch unless re-toggled)\n */\n if (isOpenByDefault && node.children == null && hasMoreChildren(node)) {\n getNextPageOfChildren()\n }\n\n return {\n data: {\n node,\n getNextPageOfChildren,\n id: id,\n isLeaf: isLeafNode(node),\n isOpenByDefault: isOpenByDefault,\n nestingLevel,\n setSelectedId,\n treeNodeType,\n isSelected,\n isDisabled,\n defaultHeight,\n },\n nestingLevel,\n node,\n }\n}\n\n/**\n * Node component for the react-vtree virtualized tree. Exported only for testing purposes\n */\nexport function Node(\n props: NodeComponentProps<TreeData, VariableSizeNodePublicState<TreeData>>,\n) {\n const {\n data: {\n node,\n getNextPageOfChildren,\n isLeaf,\n id,\n nestingLevel,\n setSelectedId,\n treeNodeType,\n isSelected,\n isDisabled,\n },\n isOpen,\n style,\n setOpen,\n } = props\n\n const [isLoading, setLoading] = useState(false)\n\n const nodeText = isEntityHeaderNode(node) ? (\n <span>{node.name}</span>\n ) : isRootNodeConfiguration(node) ? (\n <span>{node.nodeText}</span>\n ) : (\n // Pagination node\n <Skeleton width={100} />\n )\n\n // We only use this for pagination nodes. If the pagination node comes into view, then immediately call `getNextPageOfChildren`\n const { ref, inView } = useInView()\n\n useEffect(() => {\n if (isPaginationNode(node) && inView) {\n getNextPageOfChildren()\n }\n }, [node, inView, getNextPageOfChildren])\n\n const toggleExpand = useCallback(async () => {\n if (hasMoreChildren(node)) {\n setLoading(true)\n await getNextPageOfChildren()\n await setOpen(!isOpen)\n setLoading(false)\n } else {\n await setOpen(!isOpen)\n }\n }, [getNextPageOfChildren, node, isOpen, setOpen])\n\n /**\n * If in the dual-pane view, expand a node when it becomes selected\n */\n useEffect(() => {\n if (\n treeNodeType === EntityTreeNodeType.DUAL_PANE &&\n isSelected &&\n !isOpen\n ) {\n toggleExpand()\n }\n // Intentionally only toggle the expanded state when isSelected changes, otherwise the node cannot be un-expanded\n // oxlint-disable-next-line react-hooks/exhaustive-deps\n }, [isSelected])\n\n /**\n * If the height is 0, the node is purposefully hidden. Just render a fragment.\n */\n if ('height' in style && style.height === 0) {\n return <></>\n }\n\n let tooltipContent: ReactNode = ''\n if (isEntityHeaderNode(node)) {\n tooltipContent = (\n <div style={{ textAlign: 'center' }}>\n <Typography\n component=\"span\"\n variant=\"smallText1\"\n sx={{\n display: 'inline',\n }}\n >\n {node.name}\n <br />\n <b>ID: </b>\n {node.id}\n {'modifiedBy' in node && (\n <>\n <br />\n <b>Modified By: </b>\n <UserBadge\n userId={node.modifiedBy.toString()}\n showFullName\n disableLink\n showCardOnHover={false}\n />\n </>\n )}\n {'modifiedOn' in node && (\n <>\n <br />\n <b>Modified On: </b>\n {formatDate(dayjs(node.modifiedOn))}\n </>\n )}\n </Typography>\n </div>\n )\n }\n\n const ExpandIcon = isOpen ? ExpandMore : ChevronRight\n\n return (\n <div\n className={`Node ${\n treeNodeType === EntityTreeNodeType.SINGLE_PANE\n ? 'SelectNode'\n : 'BrowseNode'\n }`}\n aria-selected={isSelected}\n aria-disabled={isDisabled}\n onClick={event => {\n event.stopPropagation()\n if (!isDisabled) {\n setSelectedId(id)\n }\n }}\n style={{\n ...style,\n paddingLeft: `${nestingLevel * 20}px`,\n }}\n >\n {!isLeaf && (\n <>\n {isLoading ? (\n <SynapseSpinner size={10} />\n ) : (\n <button\n aria-label={isOpen ? 'Collapse' : 'Expand'}\n onClick={event => {\n event.stopPropagation()\n toggleExpand()\n }}\n >\n <ExpandIcon className=\"ExpandButton\" />\n </button>\n )}\n </>\n )}\n {treeNodeType === EntityTreeNodeType.SINGLE_PANE && ( // SWC-5592\n <div className=\"EntityIcon\">\n {isEntityHeaderNode(node) && (\n <EntityTypeIcon type={getEntityTypeFromHeader(node)} />\n )}\n </div>\n )}\n\n <Tooltip title={tooltipContent} placement=\"right\">\n <div className=\"EntityName\" ref={ref}>\n {nodeText}\n </div>\n </Tooltip>\n\n {treeNodeType === EntityTreeNodeType.SINGLE_PANE && (\n <EntityBadgeIcons\n entityId={id}\n showHasDiscussionThread={false}\n showHasWiki={false}\n showUnlink={false}\n canOpenModal={false}\n />\n )}\n </div>\n )\n}\n\n/**\n * Extracted from the React component for testing purposes\n * @returns a generator function compatible with react-vtree\n */\nexport function getTreeWalkerFunction(\n rootNode: RootNodeConfiguration,\n setSelectedId: VirtualizedTreeProps['setSelectedId'],\n treeNodeType: VirtualizedTreeProps['treeNodeType'],\n selected: VirtualizedTreeProps['selected'],\n selectableTypes: VirtualizedTreeProps['selectableTypes'],\n autoExpand: VirtualizedTreeProps['autoExpand'],\n itemSize: (index?: number) => number,\n currentContainer: VirtualizedTreeProps['currentContainer'],\n fetchNextPageOfChildren: (node: Writable<EntityHeaderNode>) => Promise<void>,\n): TreeWalker<TreeData, NodeMeta> {\n return function* treeWalker() {\n // Step [1]: Define the root node of our tree.\n yield getNodeData({\n node: rootNode,\n nestingLevel: 0,\n getNextPageOfChildren: rootNode.fetchNextPage,\n setSelectedId,\n treeNodeType,\n selected,\n selectableTypes,\n autoExpand,\n defaultHeight: itemSize(),\n currentContainer,\n })\n\n while (true) {\n // Step [2]: Get the parent node and nesting level, which will be passed into the Generator.next function by react-vtree.\n // Yielding `undefined` indicates to react-vtree that we've finished iterating children from the last time we were in the loop.\n const parentMeta = yield\n\n if (maybeHasChildren(parentMeta.node)) {\n // Step [3]: Yielding all the known children of the parent\n if (parentMeta.node.children) {\n for (let i = 0; i < parentMeta.node.children.length; i++) {\n const childNode = parentMeta.node.children[i]\n\n yield getNodeData({\n node: childNode,\n nestingLevel: parentMeta.nestingLevel + 1,\n getNextPageOfChildren: () => fetchNextPageOfChildren(childNode),\n setSelectedId,\n treeNodeType,\n selected,\n selectableTypes,\n autoExpand,\n defaultHeight: itemSize(),\n currentContainer,\n })\n }\n }\n\n // Step [4] - If the parent node has more children, render a \"pagination node\" that will fetch more children when it comes into view (via intersection observer)\n if (hasMoreChildren(parentMeta.node)) {\n const paginationNode: PaginationNode = {\n __paginationNode: true,\n }\n const paginationTreeWalkerValue: TreeWalkerValue<TreeData, NodeMeta> =\n {\n data: {\n id: parentMeta.data.id + '-pagination',\n node: paginationNode,\n isOpenByDefault: false,\n getNextPageOfChildren: parentMeta.data.getNextPageOfChildren,\n isLeaf: true,\n isSelected: false,\n defaultHeight: itemSize(),\n isDisabled: true,\n nestingLevel: parentMeta.nestingLevel + 1,\n setSelectedId: () => {},\n treeNodeType,\n },\n nestingLevel: parentMeta.nestingLevel + 1,\n node: {\n __paginationNode: true,\n },\n }\n yield paginationTreeWalkerValue\n }\n }\n }\n }\n}\n\nexport type VirtualizedTreeProps = Readonly<{\n treeNodeType: EntityTreeNodeType\n rootNodeConfiguration: RootNodeConfiguration\n setSelectedId: (entityId: string) => void\n selected: EntitySelectionMapType\n /* currentContainer is the container whose contents are shown on in the right pane in dual-pane configuration, and may only be defined when treeNodeType is DUAL_PANE */\n currentContainer?: string | 'root' | null\n autoExpand: (entityId: string) => boolean\n selectableTypes: EntityType[]\n visibleTypes: EntityType[]\n}>\n\n/**\n * Component that utilizes react-vtree to efficiently display a tree of entities. react-vtree utilizes react-window\n * to only render visible nodes, which eliminates performance issues as seen in SWC-5978.\n */\nexport const VirtualizedTree = (\n props: VirtualizedTreeProps,\n): React.ReactNode => {\n const {\n rootNodeConfiguration,\n setSelectedId,\n treeNodeType,\n selected,\n currentContainer,\n selectableTypes,\n visibleTypes,\n autoExpand,\n } = props\n\n const { accessToken, keyFactory } = useSynapseContext()\n const queryClient = useQueryClient()\n\n const [rootNode, setRootNode] = useState<RootNodeConfiguration>(\n rootNodeConfiguration,\n )\n\n const treeInstance = useRef<VariableSizeTree<TreeData>>(null)\n\n useEffect(() => {\n setRootNode(rootNodeConfiguration)\n }, [rootNodeConfiguration, rootNodeConfiguration.children])\n\n // This function is used by VariableSizeTree to identify the size of each node in the tree.\n const itemSize = useCallback(\n (index?: number) => {\n /**\n * We must have a root node, but we don't always want to show it.\n * In those cases, set the height of the root node to 0.\n */\n if (index === 0 && !rootNodeConfiguration.show) {\n return 0\n }\n /**\n * The height of all other nodes in the tree varies depending on the tree node type.\n */\n return treeNodeType === EntityTreeNodeType.DUAL_PANE ? 30 : 60\n },\n [treeNodeType, rootNodeConfiguration.show],\n )\n\n /**\n * Fetches the next page of children for a given node. After fetching the children, this method will make a deep clone of the\n * full tree, including the new data, and updates the state of the component\n */\n const fetchNextPageOfChildren = useCallback(\n // Because we update the root node with a copy at the end of this function, we can write to the node under update.\n async (node: Writable<EntityHeaderNode>) => {\n // Fetch the children of the node\n const entityChildrenRequest: EntityChildrenRequest = {\n parentId: node.id,\n nextPageToken: node.childrenNextPageToken,\n includeTypes: visibleTypes,\n }\n const children = await queryClient.fetchQuery({\n queryKey: keyFactory.getEntityChildrenQueryKey(\n entityChildrenRequest,\n false,\n ),\n queryFn: () => getEntityChildren(entityChildrenRequest, accessToken),\n })\n // Update the node data -- add the children and store the nextPageToken\n if (node.children) {\n for (const newChild of children.page) {\n // SWC-6751 - Prevent adding duplicate entries in case this function is called twice\n if (!node.children.find(child => child.id == newChild.id)) {\n node.children.push(newChild)\n }\n }\n } else {\n node.children = children.page\n }\n node.childrenNextPageToken = children.nextPageToken\n\n // Ensure the node for which we fetched children is expanded/open\n if (treeInstance.current) {\n await treeInstance.current.recomputeTree({\n [node.id]: {\n open: true,\n },\n })\n }\n\n // cloneDeep is required to re-render the tree with the new children\n setRootNode(cloneDeep(rootNode))\n },\n [visibleTypes, queryClient, keyFactory, rootNode, accessToken],\n )\n\n /**\n * treeWalker is a generator function used by react-vtree to generate the tree structure. The tree is re-built when the function is updated,\n * so the dependencies specified in useCallback are important.\n */\n const memoizedTreeWalker = useCallback(\n getTreeWalkerFunction(\n rootNode,\n setSelectedId,\n treeNodeType,\n selected,\n selectableTypes,\n autoExpand,\n itemSize,\n currentContainer,\n fetchNextPageOfChildren,\n ),\n [\n rootNode,\n setSelectedId,\n treeNodeType,\n selected,\n selectableTypes,\n autoExpand,\n currentContainer,\n fetchNextPageOfChildren,\n itemSize,\n ],\n )\n\n return (\n <AutoSizer disableWidth>\n {({ height }: { height: number }) => (\n <VariableSizeTree\n ref={treeInstance}\n treeWalker={memoizedTreeWalker}\n itemSize={itemSize}\n height={height}\n async={true}\n width=\"100%\"\n >\n {Node}\n </VariableSizeTree>\n )}\n </AutoSizer>\n )\n}\n"],"mappings":"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"}
|
|
@@ -7,6 +7,7 @@ type EntityTypeIconProps = {
|
|
|
7
7
|
className?: string;
|
|
8
8
|
includeTooltip?: boolean;
|
|
9
9
|
wrap?: boolean;
|
|
10
|
+
variant?: 'twoTone' | 'outlined';
|
|
10
11
|
};
|
|
11
12
|
export declare function EntityTypeIcon(props: Omit<IconSvgProps, 'icon'> & EntityTypeIconProps): import("react/jsx-runtime").JSX.Element;
|
|
12
13
|
export default EntityTypeIcon;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityIcon.d.ts","sourceRoot":"","sources":["../../src/components/EntityIcon.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAY,MAAM,OAAO,CAAA;AAC/C,OAAgB,EAEd,YAAY,
|
|
1
|
+
{"version":3,"file":"EntityIcon.d.ts","sourceRoot":"","sources":["../../src/components/EntityIcon.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAY,MAAM,OAAO,CAAA;AAC/C,OAAgB,EAEd,YAAY,EAGb,MAAM,mBAAmB,CAAA;AA6B1B,KAAK,mBAAmB,GAAG;IACzB,IAAI,EAAE,UAAU,CAAA;IAChB,KAAK,CAAC,EAAE,aAAa,CAAA;IACrB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,OAAO,CAAC,EAAE,SAAS,GAAG,UAAU,CAAA;CACjC,CAAA;AAED,wBAAgB,cAAc,CAC5B,KAAK,EAAE,IAAI,CAAC,YAAY,EAAE,MAAM,CAAC,GAAG,mBAAmB,2CA8BxD;AAED,eAAe,cAAc,CAAA"}
|