synapse-react-client 4.0.13 → 4.0.15-SWC-7835
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SWC.index.js +1 -1
- package/dist/components/ChallengeRegisterButton/ChallengeRegisterButton.d.ts.map +1 -1
- package/dist/components/ChallengeRegisterButton/ChallengeRegisterButton.js +76 -45
- package/dist/components/ChallengeRegisterButton/ChallengeRegisterButton.js.map +1 -1
- package/dist/components/ChallengeRequirementsModal/ChallengeRequirementsModal.d.ts.map +1 -1
- package/dist/components/ChallengeRequirementsModal/ChallengeRequirementsModal.js +2 -2
- package/dist/components/ChallengeRequirementsModal/ChallengeRequirementsModal.js.map +1 -1
- package/dist/components/ChallengeTeamWizard/ChallengeTeamWizard.d.ts.map +1 -1
- package/dist/components/ChallengeTeamWizard/ChallengeTeamWizard.js +2 -2
- package/dist/components/ChallengeTeamWizard/ChallengeTeamWizard.js.map +1 -1
- package/dist/components/DataGrid/utils/DataGridUtils.js +1 -1
- package/dist/components/DataGrid/utils/DataGridUtils.js.map +1 -1
- package/dist/components/EntityDownloadButton/EntityDownloadButton.d.ts +6 -0
- package/dist/components/EntityDownloadButton/EntityDownloadButton.d.ts.map +1 -1
- package/dist/components/EntityDownloadButton/EntityDownloadButton.js +6 -1
- package/dist/components/EntityDownloadButton/EntityDownloadButton.js.map +1 -1
- package/dist/components/FullTextSearch/FullTextSearch.d.ts.map +1 -1
- package/dist/components/FullTextSearch/FullTextSearch.js +28 -20
- package/dist/components/FullTextSearch/FullTextSearch.js.map +1 -1
- package/dist/components/FullTextSearch/FullTextSearchUtils.d.ts.map +1 -1
- package/dist/components/FullTextSearch/FullTextSearchUtils.js +7 -2
- package/dist/components/FullTextSearch/FullTextSearchUtils.js.map +1 -1
- package/dist/components/GenericCard/BioregistryRules.d.ts.map +1 -1
- package/dist/components/GenericCard/BioregistryRules.js +9 -1
- package/dist/components/GenericCard/BioregistryRules.js.map +1 -1
- package/dist/components/Goals/Goals.Desktop.d.ts +3 -1
- package/dist/components/Goals/Goals.Desktop.d.ts.map +1 -1
- package/dist/components/Goals/Goals.Desktop.js +2 -3
- package/dist/components/Goals/Goals.Desktop.js.map +1 -1
- package/dist/components/Goals/Goals.d.ts +1 -0
- package/dist/components/Goals/Goals.d.ts.map +1 -1
- package/dist/components/Goals/Goals.js +33 -27
- package/dist/components/Goals/Goals.js.map +1 -1
- package/dist/components/Markdown/widget/MarkdownTableOfContents.d.ts.map +1 -1
- package/dist/components/Markdown/widget/MarkdownTableOfContents.js +15 -11
- package/dist/components/Markdown/widget/MarkdownTableOfContents.js.map +1 -1
- package/dist/components/QueryWrapper/useOnQueryDataChange.d.ts.map +1 -1
- package/dist/components/QueryWrapper/useOnQueryDataChange.js +19 -17
- package/dist/components/QueryWrapper/useOnQueryDataChange.js.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js +2 -2
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryWrapper.d.ts.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryWrapper.js +30 -30
- package/dist/components/SearchQueryWrapper/SearchQueryWrapper.js.map +1 -1
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.d.ts +1 -1
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.d.ts.map +1 -1
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.js +4 -2
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.js.map +1 -1
- package/dist/components/SynapseHomepageV2/WordPressNews.d.ts.map +1 -1
- package/dist/components/SynapseHomepageV2/WordPressNews.js +13 -36
- package/dist/components/SynapseHomepageV2/WordPressNews.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SearchPagePortalBanners.d.ts.map +1 -1
- package/dist/components/SynapseSearchPageResults/SearchPagePortalBanners.js +1 -1
- package/dist/components/SynapseSearchPageResults/SearchPagePortalBanners.js.map +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchPageRouter.d.ts.map +1 -1
- package/dist/components/SynapseSearchPageResults/SynapseSearchPageRouter.js +14 -12
- package/dist/components/SynapseSearchPageResults/SynapseSearchPageRouter.js.map +1 -1
- package/dist/components/SynapseTable/SearchV2.d.ts +11 -0
- package/dist/components/SynapseTable/SearchV2.d.ts.map +1 -1
- package/dist/components/SynapseTable/SearchV2.js.map +1 -1
- package/dist/components/WordPress/WordPressLatestPostChip.css +1 -0
- package/dist/components/WordPress/WordPressLatestPostChip.d.ts +5 -0
- package/dist/components/WordPress/WordPressLatestPostChip.d.ts.map +1 -0
- package/dist/components/WordPress/WordPressLatestPostChip.js +29 -0
- package/dist/components/WordPress/WordPressLatestPostChip.js.map +1 -0
- package/dist/components/WordPress/WordPressLatestPostChip.module.js +9 -0
- package/dist/components/WordPress/WordPressLatestPostChip.module.js.map +1 -0
- package/dist/components/WordPress/WordPressLatestPostChip.module.scss +33 -0
- package/dist/components/WordPress/useWordPressCategories.d.ts +3 -0
- package/dist/components/WordPress/useWordPressCategories.d.ts.map +1 -0
- package/dist/components/WordPress/useWordPressCategories.js +19 -0
- package/dist/components/WordPress/useWordPressCategories.js.map +1 -0
- package/dist/components/WordPress/useWordPressPosts.d.ts +3 -0
- package/dist/components/WordPress/useWordPressPosts.d.ts.map +1 -0
- package/dist/components/WordPress/useWordPressPosts.js +23 -0
- package/dist/components/WordPress/useWordPressPosts.js.map +1 -0
- package/dist/features/curator/dashboard/components/CurationTaskCard.js +1 -1
- package/dist/features/curator/dashboard/components/CurationTaskCard.js.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js +6 -6
- package/dist/features/entity/metadata-task/components/MetadataTaskTableActionCell.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.js +24 -20
- package/dist/features/entity/metadata-task/hooks/useGridSessionForCurationTask.js.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.d.ts +2 -2
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.js +30 -21
- package/dist/features/entity/metadata-task/hooks/useOpenCuratorButton.js.map +1 -1
- package/dist/features/entity/metadata-task/utils/constants.d.ts +1 -0
- package/dist/features/entity/metadata-task/utils/constants.d.ts.map +1 -1
- package/dist/features/entity/metadata-task/utils/constants.js +2 -2
- package/dist/features/entity/metadata-task/utils/constants.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/hooks/useShowDesktop.d.ts.map +1 -1
- package/dist/utils/hooks/useShowDesktop.js +4 -9
- package/dist/utils/hooks/useShowDesktop.js.map +1 -1
- package/package.json +4 -4
package/dist/SWC.index.js
CHANGED
|
@@ -109,7 +109,7 @@ var x = { BackendDestinationEnum: r }, S = {
|
|
|
109
109
|
sendSearchResultsReturnedEvent: y,
|
|
110
110
|
sendSearchResultReturnedEvent: v,
|
|
111
111
|
sendSearchResultClickedEvent: _
|
|
112
|
-
}, T = "4.0.
|
|
112
|
+
}, T = "4.0.15-SWC-7835";
|
|
113
113
|
//#endregion
|
|
114
114
|
export { w as Analytics, a as HttpClient, d as Palettes, o as SynapseClient, C as SynapseComponents, n as SynapseConstants, S as SynapseContext, x as SynapseEnums, m as SynapseQueries, T as SynapseReactClientVersion, p as SynapseSessionManager, i as xssOptions };
|
|
115
115
|
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChallengeRegisterButton.d.ts","sourceRoot":"","sources":["../../../src/components/ChallengeRegisterButton/ChallengeRegisterButton.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,kBAAkB,EAAqB,MAAM,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"ChallengeRegisterButton.d.ts","sourceRoot":"","sources":["../../../src/components/ChallengeRegisterButton/ChallengeRegisterButton.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,kBAAkB,EAAqB,MAAM,SAAS,CAAA;AAO/D,MAAM,WAAW,4BAA4B;IAC3C,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,kBAAkB,KAAK,IAAI,CAAA;IAC7C,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;IACxB,YAAY,CAAC,EAAE,MAAM,IAAI,CAAA;CAC1B;AAED,QAAA,MAAM,uBAAuB,GAAI,oDAK9B,4BAA4B,KAAG,KAAK,CAAC,SAiIvC,CAAA;AAED,eAAe,uBAAuB,CAAA"}
|
|
@@ -10,60 +10,91 @@ import { useEffect as o } from "react";
|
|
|
10
10
|
import { Box as s } from "@mui/material";
|
|
11
11
|
import { jsx as c, jsxs as l } from "react/jsx-runtime";
|
|
12
12
|
import u from "@mui/icons-material/ExitToApp";
|
|
13
|
+
import d from "@mui/icons-material/PendingActions";
|
|
13
14
|
//#region src/components/ChallengeRegisterButton/ChallengeRegisterButton.tsx
|
|
14
|
-
var
|
|
15
|
-
let { isAuthenticated:
|
|
15
|
+
var f = ({ projectId: f, onError: p, onJoinClick: m, onLeaveClick: h }) => {
|
|
16
|
+
let { isAuthenticated: g } = e(), { data: _ } = r({ enabled: g }), { data: v, isLoading: y, error: b } = t(f, { enabled: g }), { data: x, isLoading: S, error: C } = i(v?.participantTeamId, _?.ownerId, { enabled: !!v && !!_ }), w = !!x, { data: T, error: E, isLoading: D } = n(v?.id, 20, 0, { enabled: !!v && g }), O = T && T.results.length > 0, k = w && O, A = w && !O, j = b || C || E;
|
|
16
17
|
return o(() => {
|
|
17
|
-
|
|
18
|
-
}, [
|
|
18
|
+
j && p && p(j);
|
|
19
|
+
}, [j, p]), y || S || D ? /* @__PURE__ */ c(a, {
|
|
19
20
|
showSpinner: !0,
|
|
20
21
|
children: "Loading..."
|
|
21
|
-
}) : /* @__PURE__ */ l(s, { children: [
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
backgroundColor: "#109488",
|
|
28
|
-
fontSize: "1.12em",
|
|
29
|
-
textTransform: "none",
|
|
30
|
-
padding: "4px 18px",
|
|
31
|
-
fontWeight: 400,
|
|
32
|
-
":hover": {
|
|
22
|
+
}) : /* @__PURE__ */ l(s, { children: [
|
|
23
|
+
!k && !A && /* @__PURE__ */ c(a, {
|
|
24
|
+
disableElevation: !0,
|
|
25
|
+
variant: "contained",
|
|
26
|
+
onClick: () => g && m ? m() : void 0,
|
|
27
|
+
sx: {
|
|
33
28
|
color: "white",
|
|
34
|
-
backgroundColor: "#109488"
|
|
29
|
+
backgroundColor: "#109488",
|
|
30
|
+
fontSize: "1.12em",
|
|
31
|
+
textTransform: "none",
|
|
32
|
+
padding: "4px 18px",
|
|
33
|
+
fontWeight: 400,
|
|
34
|
+
":hover": {
|
|
35
|
+
color: "white",
|
|
36
|
+
backgroundColor: "#109488"
|
|
37
|
+
},
|
|
38
|
+
":active": {
|
|
39
|
+
color: "white",
|
|
40
|
+
backgroundColor: "#109488"
|
|
41
|
+
},
|
|
42
|
+
":visited": {
|
|
43
|
+
color: "white",
|
|
44
|
+
backgroundColor: "#109488"
|
|
45
|
+
}
|
|
35
46
|
},
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
47
|
+
children: "Register for this Challenge"
|
|
48
|
+
}),
|
|
49
|
+
A && /* @__PURE__ */ c(a, {
|
|
50
|
+
disableElevation: !0,
|
|
51
|
+
variant: "contained",
|
|
52
|
+
endIcon: /* @__PURE__ */ c(d, {}),
|
|
53
|
+
onClick: () => g && m ? m() : void 0,
|
|
54
|
+
sx: {
|
|
55
|
+
color: "#4A2E1B",
|
|
56
|
+
backgroundColor: "#FFD486",
|
|
57
|
+
fontSize: "1.12em",
|
|
58
|
+
textTransform: "none",
|
|
59
|
+
padding: "4px 18px",
|
|
60
|
+
fontWeight: 400,
|
|
61
|
+
":hover": {
|
|
62
|
+
color: "#4A2E1B",
|
|
63
|
+
backgroundColor: "#FFD486"
|
|
64
|
+
},
|
|
65
|
+
":active": {
|
|
66
|
+
color: "#4A2E1B",
|
|
67
|
+
backgroundColor: "#FFD486"
|
|
68
|
+
},
|
|
69
|
+
":visited": {
|
|
70
|
+
color: "#4A2E1B",
|
|
71
|
+
backgroundColor: "#FFD486"
|
|
72
|
+
}
|
|
39
73
|
},
|
|
40
|
-
|
|
74
|
+
children: "Complete Registration"
|
|
75
|
+
}),
|
|
76
|
+
k && /* @__PURE__ */ c(a, {
|
|
77
|
+
disableElevation: !0,
|
|
78
|
+
variant: "outlined",
|
|
79
|
+
endIcon: /* @__PURE__ */ c(u, {}),
|
|
80
|
+
onClick: () => h ? h() : void 0,
|
|
81
|
+
sx: {
|
|
82
|
+
borderColor: "white",
|
|
41
83
|
color: "white",
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
fontSize: "1.12em",
|
|
55
|
-
textTransform: "none",
|
|
56
|
-
padding: "4px 18px",
|
|
57
|
-
fontWeight: 400,
|
|
58
|
-
":hover": {
|
|
59
|
-
color: "#172430",
|
|
60
|
-
borderColor: "#172430"
|
|
61
|
-
}
|
|
62
|
-
},
|
|
63
|
-
children: "Leave Challenge"
|
|
64
|
-
})] });
|
|
84
|
+
fontSize: "1.12em",
|
|
85
|
+
textTransform: "none",
|
|
86
|
+
padding: "4px 18px",
|
|
87
|
+
fontWeight: 400,
|
|
88
|
+
":hover": {
|
|
89
|
+
color: "#172430",
|
|
90
|
+
borderColor: "#172430"
|
|
91
|
+
}
|
|
92
|
+
},
|
|
93
|
+
children: "Leave Challenge"
|
|
94
|
+
})
|
|
95
|
+
] });
|
|
65
96
|
};
|
|
66
97
|
//#endregion
|
|
67
|
-
export {
|
|
98
|
+
export { f as default };
|
|
68
99
|
|
|
69
100
|
//# sourceMappingURL=ChallengeRegisterButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChallengeRegisterButton.js","names":[],"sources":["../../../src/components/ChallengeRegisterButton/ChallengeRegisterButton.tsx"],"sourcesContent":["import {\n useGetCurrentUserProfile,\n useGetEntityChallenge,\n useGetIsUserMemberOfTeam,\n useGetUserSubmissionTeams,\n} from '@/synapse-queries'\nimport React from 'react'\nimport { SynapseClientError, useSynapseContext } from '@/utils'\nimport ExitToAppIcon from '@mui/icons-material/ExitToApp'\nimport { Box } from '@mui/material'\nimport { useEffect } from 'react'\nimport SpinnerButton from '../SpinnerButton/SpinnerButton'\n\nexport interface ChallengeRegisterButtonProps {\n projectId: string\n onError?: (error: SynapseClientError) => void\n onJoinClick?: () => void\n onLeaveClick?: () => void\n}\n\nconst ChallengeRegisterButton = ({\n projectId,\n onError,\n onJoinClick,\n onLeaveClick,\n}: ChallengeRegisterButtonProps): React.ReactNode => {\n const { isAuthenticated } = useSynapseContext()\n const { data: userProfile } = useGetCurrentUserProfile({\n enabled: isAuthenticated,\n })\n\n const {\n data: challenge,\n isLoading: isLoadingChallenge,\n error: getChallengeError,\n } = useGetEntityChallenge(projectId, {\n enabled: isAuthenticated,\n })\n\n // Verify that user is a member of the participant team\n const {\n data: teamMembership,\n isLoading: isLoadingTeamMembership,\n error: getTeamMembershipError,\n } = useGetIsUserMemberOfTeam(\n challenge?.participantTeamId!,\n userProfile?.ownerId!,\n {\n enabled: !!challenge && !!userProfile,\n },\n )\n\n const isRegistered = Boolean(teamMembership)\n\n const {\n data: userSubmissionTeams,\n error: getSubmissionTeamsError,\n isLoading: isLoadingSubmissionTeams,\n } = useGetUserSubmissionTeams(challenge?.id!, 20, 0, {\n enabled: !!challenge && isAuthenticated,\n })\n\n const hasSubmissionTeam =\n userSubmissionTeams && userSubmissionTeams.results.length > 0\n const isMemberOfBothParticipantAndSubmissionTeams =\n isRegistered && hasSubmissionTeam\n\n const error =\n getChallengeError || getTeamMembershipError || getSubmissionTeamsError\n\n useEffect(() => {\n if (error && onError) onError(error)\n }, [error, onError])\n\n const isLoading =\n isLoadingChallenge || isLoadingTeamMembership || isLoadingSubmissionTeams\n\n if (isLoading) {\n return <SpinnerButton showSpinner>Loading...</SpinnerButton>\n }\n\n return (\n <Box>\n {!isMemberOfBothParticipantAndSubmissionTeams && (\n <SpinnerButton\n disableElevation={true}\n variant=\"contained\"\n onClick={() =>\n isAuthenticated && onJoinClick ? onJoinClick() : undefined\n }\n sx={{\n color: '
|
|
1
|
+
{"version":3,"file":"ChallengeRegisterButton.js","names":[],"sources":["../../../src/components/ChallengeRegisterButton/ChallengeRegisterButton.tsx"],"sourcesContent":["import {\n useGetCurrentUserProfile,\n useGetEntityChallenge,\n useGetIsUserMemberOfTeam,\n useGetUserSubmissionTeams,\n} from '@/synapse-queries'\nimport React from 'react'\nimport { SynapseClientError, useSynapseContext } from '@/utils'\nimport ExitToAppIcon from '@mui/icons-material/ExitToApp'\nimport PendingActionsIcon from '@mui/icons-material/PendingActions'\nimport { Box } from '@mui/material'\nimport { useEffect } from 'react'\nimport SpinnerButton from '../SpinnerButton/SpinnerButton'\n\nexport interface ChallengeRegisterButtonProps {\n projectId: string\n onError?: (error: SynapseClientError) => void\n onJoinClick?: () => void\n onLeaveClick?: () => void\n}\n\nconst ChallengeRegisterButton = ({\n projectId,\n onError,\n onJoinClick,\n onLeaveClick,\n}: ChallengeRegisterButtonProps): React.ReactNode => {\n const { isAuthenticated } = useSynapseContext()\n const { data: userProfile } = useGetCurrentUserProfile({\n enabled: isAuthenticated,\n })\n\n const {\n data: challenge,\n isLoading: isLoadingChallenge,\n error: getChallengeError,\n } = useGetEntityChallenge(projectId, {\n enabled: isAuthenticated,\n })\n\n // Verify that user is a member of the participant team\n const {\n data: teamMembership,\n isLoading: isLoadingTeamMembership,\n error: getTeamMembershipError,\n } = useGetIsUserMemberOfTeam(\n challenge?.participantTeamId!,\n userProfile?.ownerId!,\n {\n enabled: !!challenge && !!userProfile,\n },\n )\n\n const isRegistered = Boolean(teamMembership)\n\n const {\n data: userSubmissionTeams,\n error: getSubmissionTeamsError,\n isLoading: isLoadingSubmissionTeams,\n } = useGetUserSubmissionTeams(challenge?.id!, 20, 0, {\n enabled: !!challenge && isAuthenticated,\n })\n\n const hasSubmissionTeam =\n userSubmissionTeams && userSubmissionTeams.results.length > 0\n const isMemberOfBothParticipantAndSubmissionTeams =\n isRegistered && hasSubmissionTeam\n const isMemberOfParticipantTeamOnly = isRegistered && !hasSubmissionTeam\n\n const error =\n getChallengeError || getTeamMembershipError || getSubmissionTeamsError\n\n useEffect(() => {\n if (error && onError) onError(error)\n }, [error, onError])\n\n const isLoading =\n isLoadingChallenge || isLoadingTeamMembership || isLoadingSubmissionTeams\n\n if (isLoading) {\n return <SpinnerButton showSpinner>Loading...</SpinnerButton>\n }\n\n return (\n <Box>\n {!isMemberOfBothParticipantAndSubmissionTeams &&\n !isMemberOfParticipantTeamOnly && (\n <SpinnerButton\n disableElevation={true}\n variant=\"contained\"\n onClick={() =>\n isAuthenticated && onJoinClick ? onJoinClick() : undefined\n }\n sx={{\n color: 'white',\n backgroundColor: '#109488',\n fontSize: '1.12em',\n textTransform: 'none',\n padding: '4px 18px',\n fontWeight: 400,\n ':hover': { color: 'white', backgroundColor: '#109488' },\n ':active': { color: 'white', backgroundColor: '#109488' },\n ':visited': { color: 'white', backgroundColor: '#109488' },\n }}\n >\n Register for this Challenge\n </SpinnerButton>\n )}\n {isMemberOfParticipantTeamOnly && (\n <SpinnerButton\n disableElevation={true}\n variant=\"contained\"\n endIcon={<PendingActionsIcon />}\n onClick={() =>\n isAuthenticated && onJoinClick ? onJoinClick() : undefined\n }\n sx={{\n color: '#4A2E1B',\n backgroundColor: '#FFD486',\n fontSize: '1.12em',\n textTransform: 'none',\n padding: '4px 18px',\n fontWeight: 400,\n ':hover': { color: '#4A2E1B', backgroundColor: '#FFD486' },\n ':active': { color: '#4A2E1B', backgroundColor: '#FFD486' },\n ':visited': { color: '#4A2E1B', backgroundColor: '#FFD486' },\n }}\n >\n Complete Registration\n </SpinnerButton>\n )}\n {isMemberOfBothParticipantAndSubmissionTeams && (\n <SpinnerButton\n disableElevation={true}\n variant=\"outlined\"\n endIcon={<ExitToAppIcon />}\n onClick={() => (onLeaveClick ? onLeaveClick() : undefined)}\n sx={{\n borderColor: 'white',\n color: 'white',\n fontSize: '1.12em',\n textTransform: 'none',\n padding: '4px 18px',\n fontWeight: 400,\n ':hover': {\n color: '#172430',\n borderColor: '#172430',\n },\n }}\n >\n Leave Challenge\n </SpinnerButton>\n )}\n </Box>\n )\n}\n\nexport default ChallengeRegisterButton\n"],"mappings":";;;;;;;;;;;;;;AAqBA,IAAM,KAA2B,EAC/B,cACA,YACA,gBACA,sBACmD;CACnD,IAAM,EAAE,uBAAoB,GAAmB,EACzC,EAAE,MAAM,MAAgB,EAAyB,EACrD,SAAS,GACV,CAAC,EAEI,EACJ,MAAM,GACN,WAAW,GACX,OAAO,MACL,EAAsB,GAAW,EACnC,SAAS,GACV,CAAC,EAGI,EACJ,MAAM,GACN,WAAW,GACX,OAAO,MACL,EACF,GAAW,mBACX,GAAa,SACb,EACE,SAAS,CAAC,CAAC,KAAa,CAAC,CAAC,GAC3B,CACF,EAEK,IAAe,EAAQ,GAEvB,EACJ,MAAM,GACN,OAAO,GACP,WAAW,MACT,EAA0B,GAAW,IAAK,IAAI,GAAG,EACnD,SAAS,CAAC,CAAC,KAAa,GACzB,CAAC,EAEI,IACJ,KAAuB,EAAoB,QAAQ,SAAS,GACxD,IACJ,KAAgB,GACZ,IAAgC,KAAgB,CAAC,GAEjD,IACJ,KAAqB,KAA0B;AAajD,QAXA,QAAgB;AACd,EAAI,KAAS,KAAS,EAAQ,EAAM;IACnC,CAAC,GAAO,EAAQ,CAAC,EAGlB,KAAsB,KAA2B,IAG1C,kBAAC,GAAD;EAAe,aAAA;YAAY;EAA0B,CAAA,GAI5D,kBAAC,GAAD,EAAA,UAAA;EACG,CAAC,KACA,CAAC,KACC,kBAAC,GAAD;GACE,kBAAkB;GAClB,SAAQ;GACR,eACE,KAAmB,IAAc,GAAa,GAAG,KAAA;GAEnD,IAAI;IACF,OAAO;IACP,iBAAiB;IACjB,UAAU;IACV,eAAe;IACf,SAAS;IACT,YAAY;IACZ,UAAU;KAAE,OAAO;KAAS,iBAAiB;KAAW;IACxD,WAAW;KAAE,OAAO;KAAS,iBAAiB;KAAW;IACzD,YAAY;KAAE,OAAO;KAAS,iBAAiB;KAAW;IAC3D;aACF;GAEe,CAAA;EAEnB,KACC,kBAAC,GAAD;GACE,kBAAkB;GAClB,SAAQ;GACR,SAAS,kBAAC,GAAD,EAAsB,CAAA;GAC/B,eACE,KAAmB,IAAc,GAAa,GAAG,KAAA;GAEnD,IAAI;IACF,OAAO;IACP,iBAAiB;IACjB,UAAU;IACV,eAAe;IACf,SAAS;IACT,YAAY;IACZ,UAAU;KAAE,OAAO;KAAW,iBAAiB;KAAW;IAC1D,WAAW;KAAE,OAAO;KAAW,iBAAiB;KAAW;IAC3D,YAAY;KAAE,OAAO;KAAW,iBAAiB;KAAW;IAC7D;aACF;GAEe,CAAA;EAEjB,KACC,kBAAC,GAAD;GACE,kBAAkB;GAClB,SAAQ;GACR,SAAS,kBAAC,GAAD,EAAiB,CAAA;GAC1B,eAAgB,IAAe,GAAc,GAAG,KAAA;GAChD,IAAI;IACF,aAAa;IACb,OAAO;IACP,UAAU;IACV,eAAe;IACf,SAAS;IACT,YAAY;IACZ,UAAU;KACR,OAAO;KACP,aAAa;KACd;IACF;aACF;GAEe,CAAA;EAEd,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChallengeRequirementsModal.d.ts","sourceRoot":"","sources":["../../../src/components/ChallengeRequirementsModal/ChallengeRequirementsModal.tsx"],"names":[],"mappings":"AAmBA,MAAM,MAAM,+BAA+B,GAAG;IAC5C,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,kBAAkB,EAAE,MAAM,IAAI,CAAA;CAC/B,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,0BAA0B,CAChD,KAAK,EAAE,+BAA+B,
|
|
1
|
+
{"version":3,"file":"ChallengeRequirementsModal.d.ts","sourceRoot":"","sources":["../../../src/components/ChallengeRequirementsModal/ChallengeRequirementsModal.tsx"],"names":[],"mappings":"AAmBA,MAAM,MAAM,+BAA+B,GAAG;IAC5C,IAAI,EAAE,OAAO,CAAA;IACb,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,IAAI,CAAA;IACpB,kBAAkB,EAAE,MAAM,IAAI,CAAA;CAC/B,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,OAAO,UAAU,0BAA0B,CAChD,KAAK,EAAE,+BAA+B,2CA4HvC"}
|
|
@@ -33,9 +33,9 @@ function y(y) {
|
|
|
33
33
|
P,
|
|
34
34
|
B,
|
|
35
35
|
L
|
|
36
|
-
].filter((e) => !!e), G =
|
|
36
|
+
].filter((e) => !!e), G = "Next Step";
|
|
37
37
|
return I && (G = "Registering..."), d(W) ? !j || !b ? /* @__PURE__ */ g(h, {}) : /* @__PURE__ */ g(l, {
|
|
38
|
-
dialogTitle: "Challenge Terms and Conditions",
|
|
38
|
+
dialogTitle: "Challenge Registration (Step 1 of 2): Terms and Conditions",
|
|
39
39
|
subjectId: j,
|
|
40
40
|
subjectType: v.TEAM,
|
|
41
41
|
teamId: D?.participantTeamId,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChallengeRequirementsModal.js","names":[],"sources":["../../../src/components/ChallengeRequirementsModal/ChallengeRequirementsModal.tsx"],"sourcesContent":["import {\n useGetAccessRequirementsForTeam,\n useGetAccessRequirementStatuses,\n useGetCurrentUserProfile,\n useGetEntity,\n useGetEntityChallenge,\n} from '@/synapse-queries'\nimport {\n useAddMemberToTeam,\n useGetMembershipStatus,\n} from '@/synapse-queries/team/useTeamMembers'\nimport { SynapseClientError, useSynapseContext } from '@/utils'\nimport { Alert, Button, Typography } from '@mui/material'\nimport { RestrictableObjectType } from '@sage-bionetworks/synapse-types'\nimport { isEmpty } from 'lodash-es'\nimport { useCallback } from 'react'\nimport AccessRequirementList from '../AccessRequirementList/AccessRequirementList'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\n\nexport type ChallengeRequirementsModalProps = {\n open: boolean\n projectId: string\n onCancel: () => void\n onRegisterComplete: () => void\n}\n\n/**\n * The challenge requirements modal will\n * 1. Display the access requirements that must be accepted to join a participant team. The component will guide the user through meeting the requirements.\n * 2. If the user has accepted the requirements, the user can click 'Register' to join the team\n * If the user has not accepted the requirements, the user cannot register for the challenge.\n */\nexport default function ChallengeRequirementsModal(\n props: ChallengeRequirementsModalProps,\n) {\n const { open, projectId, onRegisterComplete, onCancel } = props\n const { data: project, error: getEntityError } = useGetEntity(projectId)\n\n const { isAuthenticated } = useSynapseContext()\n\n const { data: challenge, error: getChallengeError } =\n useGetEntityChallenge(projectId)\n const { data: userProfile, error: getProfileError } =\n useGetCurrentUserProfile({\n enabled: isAuthenticated,\n })\n\n const participantTeamId = challenge?.participantTeamId\n const userId = userProfile?.ownerId\n\n const { data: teamMembershipStatus, error: getMembershipStatusError } =\n useGetMembershipStatus(participantTeamId!, userId!, {\n enabled: Boolean(participantTeamId && userId),\n })\n\n const {\n mutateAsync: addTeamMember,\n isPending: registrationIsPending,\n error: registrationError,\n } = useAddMemberToTeam()\n\n const {\n data: fetchedRequirementsForTeam,\n isSuccess: hasFetchedRequirements,\n error: getAccessRequirementsError,\n } = useGetAccessRequirementsForTeam(challenge?.participantTeamId!, {\n enabled: Boolean(challenge?.participantTeamId),\n })\n\n const requirementStatusesQueryResults = useGetAccessRequirementStatuses(\n fetchedRequirementsForTeam?.map(ar => String(ar.id)) ?? [],\n )\n\n const meetsAllRequirements =\n hasFetchedRequirements &&\n requirementStatusesQueryResults.every(queryResult => {\n return queryResult.status === 'success' && queryResult.data.isApproved\n })\n\n const registerForChallenge = useCallback(async () => {\n if (participantTeamId && userId && !teamMembershipStatus?.isMember) {\n await addTeamMember({\n teamId: participantTeamId,\n userId,\n })\n }\n onRegisterComplete()\n }, [\n addTeamMember,\n onRegisterComplete,\n participantTeamId,\n teamMembershipStatus?.isMember,\n userId,\n ])\n\n const errors = [\n getEntityError,\n getChallengeError,\n getProfileError,\n getMembershipStatusError,\n getAccessRequirementsError,\n registrationError,\n ].filter((e): e is SynapseClientError => Boolean(e))\n\n // It's possible that the user joined the team, but requirements on the team changed since they became a member\n // They do not need to re-join the team, but they should still be prompted to accept the requirements\n let registerButtonText =
|
|
1
|
+
{"version":3,"file":"ChallengeRequirementsModal.js","names":[],"sources":["../../../src/components/ChallengeRequirementsModal/ChallengeRequirementsModal.tsx"],"sourcesContent":["import {\n useGetAccessRequirementsForTeam,\n useGetAccessRequirementStatuses,\n useGetCurrentUserProfile,\n useGetEntity,\n useGetEntityChallenge,\n} from '@/synapse-queries'\nimport {\n useAddMemberToTeam,\n useGetMembershipStatus,\n} from '@/synapse-queries/team/useTeamMembers'\nimport { SynapseClientError, useSynapseContext } from '@/utils'\nimport { Alert, Button, Typography } from '@mui/material'\nimport { RestrictableObjectType } from '@sage-bionetworks/synapse-types'\nimport { isEmpty } from 'lodash-es'\nimport { useCallback } from 'react'\nimport AccessRequirementList from '../AccessRequirementList/AccessRequirementList'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\n\nexport type ChallengeRequirementsModalProps = {\n open: boolean\n projectId: string\n onCancel: () => void\n onRegisterComplete: () => void\n}\n\n/**\n * The challenge requirements modal will\n * 1. Display the access requirements that must be accepted to join a participant team. The component will guide the user through meeting the requirements.\n * 2. If the user has accepted the requirements, the user can click 'Register' to join the team\n * If the user has not accepted the requirements, the user cannot register for the challenge.\n */\nexport default function ChallengeRequirementsModal(\n props: ChallengeRequirementsModalProps,\n) {\n const { open, projectId, onRegisterComplete, onCancel } = props\n const { data: project, error: getEntityError } = useGetEntity(projectId)\n\n const { isAuthenticated } = useSynapseContext()\n\n const { data: challenge, error: getChallengeError } =\n useGetEntityChallenge(projectId)\n const { data: userProfile, error: getProfileError } =\n useGetCurrentUserProfile({\n enabled: isAuthenticated,\n })\n\n const participantTeamId = challenge?.participantTeamId\n const userId = userProfile?.ownerId\n\n const { data: teamMembershipStatus, error: getMembershipStatusError } =\n useGetMembershipStatus(participantTeamId!, userId!, {\n enabled: Boolean(participantTeamId && userId),\n })\n\n const {\n mutateAsync: addTeamMember,\n isPending: registrationIsPending,\n error: registrationError,\n } = useAddMemberToTeam()\n\n const {\n data: fetchedRequirementsForTeam,\n isSuccess: hasFetchedRequirements,\n error: getAccessRequirementsError,\n } = useGetAccessRequirementsForTeam(challenge?.participantTeamId!, {\n enabled: Boolean(challenge?.participantTeamId),\n })\n\n const requirementStatusesQueryResults = useGetAccessRequirementStatuses(\n fetchedRequirementsForTeam?.map(ar => String(ar.id)) ?? [],\n )\n\n const meetsAllRequirements =\n hasFetchedRequirements &&\n requirementStatusesQueryResults.every(queryResult => {\n return queryResult.status === 'success' && queryResult.data.isApproved\n })\n\n const registerForChallenge = useCallback(async () => {\n if (participantTeamId && userId && !teamMembershipStatus?.isMember) {\n await addTeamMember({\n teamId: participantTeamId,\n userId,\n })\n }\n onRegisterComplete()\n }, [\n addTeamMember,\n onRegisterComplete,\n participantTeamId,\n teamMembershipStatus?.isMember,\n userId,\n ])\n\n const errors = [\n getEntityError,\n getChallengeError,\n getProfileError,\n getMembershipStatusError,\n getAccessRequirementsError,\n registrationError,\n ].filter((e): e is SynapseClientError => Boolean(e))\n\n // It's possible that the user joined the team, but requirements on the team changed since they became a member\n // They do not need to re-join the team, but they should still be prompted to accept the requirements\n let registerButtonText = 'Next Step'\n if (registrationIsPending) {\n registerButtonText = 'Registering...'\n }\n\n if (!isEmpty(errors)) {\n return (\n <Alert severity=\"error\">\n {errors.map((e, index) => (\n <Typography variant={'body1'} key={index}>\n {e.reason}\n </Typography>\n ))}\n </Alert>\n )\n }\n\n if (!participantTeamId || !open) {\n return <></>\n }\n\n return (\n <AccessRequirementList\n dialogTitle={`Challenge Registration (Step 1 of 2): Terms and Conditions`}\n subjectId={participantTeamId}\n subjectType={RestrictableObjectType.TEAM}\n teamId={challenge?.participantTeamId}\n renderAsModal={true}\n requestObjectName={project?.name}\n onHide={() => {\n onCancel()\n }}\n customDialogActions={\n <>\n <Button variant={'outlined'} onClick={onCancel}>\n Cancel\n </Button>\n <Button\n variant={'contained'}\n onClick={() => {\n registerForChallenge()\n }}\n startIcon={registrationIsPending ? <SynapseSpinner /> : undefined}\n disabled={!meetsAllRequirements || registrationIsPending}\n >\n {registerButtonText}\n </Button>\n </>\n }\n />\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAgCA,SAAwB,EACtB,GACA;CACA,IAAM,EAAE,SAAM,cAAW,uBAAoB,gBAAa,GACpD,EAAE,MAAM,GAAS,OAAO,MAAmB,EAAa,EAAU,EAElE,EAAE,uBAAoB,GAAmB,EAEzC,EAAE,MAAM,GAAW,OAAO,MAC9B,EAAsB,EAAU,EAC5B,EAAE,MAAM,GAAa,OAAO,MAChC,EAAyB,EACvB,SAAS,GACV,CAAC,EAEE,IAAoB,GAAW,mBAC/B,IAAS,GAAa,SAEtB,EAAE,MAAM,GAAsB,OAAO,MACzC,EAAuB,GAAoB,GAAS,EAClD,SAAS,GAAQ,KAAqB,IACvC,CAAC,EAEE,EACJ,aAAa,GACb,WAAW,GACX,OAAO,MACL,GAAoB,EAElB,EACJ,MAAM,GACN,WAAW,GACX,OAAO,MACL,EAAgC,GAAW,mBAAoB,EACjE,SAAS,EAAQ,GAAW,mBAC7B,CAAC,EAEI,IAAkC,EACtC,GAA4B,KAAI,MAAM,OAAO,EAAG,GAAG,CAAC,IAAI,EAAE,CAC3D,EAEK,IACJ,KACA,EAAgC,OAAM,MAC7B,EAAY,WAAW,aAAa,EAAY,KAAK,WAC5D,EAEE,IAAuB,EAAY,YAAY;AAOnD,EANI,KAAqB,KAAU,CAAC,GAAsB,YACxD,MAAM,EAAc;GAClB,QAAQ;GACR;GACD,CAAC,EAEJ,GAAoB;IACnB;EACD;EACA;EACA;EACA,GAAsB;EACtB;EACD,CAAC,EAEI,IAAS;EACb;EACA;EACA;EACA;EACA;EACA;EACD,CAAC,QAAQ,MAA+B,EAAQ,EAAG,EAIhD,IAAqB;AAqBzB,QApBI,MACF,IAAqB,mBAGlB,EAAQ,EAAO,GAYhB,CAAC,KAAqB,CAAC,IAClB,kBAAA,GAAA,EAAK,CAAA,GAIZ,kBAAC,GAAD;EACE,aAAa;EACb,WAAW;EACX,aAAa,EAAuB;EACpC,QAAQ,GAAW;EACnB,eAAe;EACf,mBAAmB,GAAS;EAC5B,cAAc;AACZ,MAAU;;EAEZ,qBACE,kBAAA,GAAA,EAAA,UAAA,CACE,kBAAC,GAAD;GAAQ,SAAS;GAAY,SAAS;aAAU;GAEvC,CAAA,EACT,kBAAC,GAAD;GACE,SAAS;GACT,eAAe;AACb,OAAsB;;GAExB,WAAW,IAAwB,kBAAC,GAAD,EAAkB,CAAA,GAAG,KAAA;GACxD,UAAU,CAAC,KAAwB;aAElC;GACM,CAAA,CACR,EAAA,CAAA;EAEL,CAAA,GA1CA,kBAAC,GAAD;EAAO,UAAS;YACb,EAAO,KAAK,GAAG,MACd,kBAAC,GAAD;GAAY,SAAS;aAClB,EAAE;GACQ,EAFsB,EAEtB,CACb;EACI,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChallengeTeamWizard.d.ts","sourceRoot":"","sources":["../../../src/components/ChallengeTeamWizard/ChallengeTeamWizard.tsx"],"names":[],"mappings":"AAuDA,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAA;AAED;;;;GAIG;AACH,iBAAS,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,
|
|
1
|
+
{"version":3,"file":"ChallengeTeamWizard.d.ts","sourceRoot":"","sources":["../../../src/components/ChallengeTeamWizard/ChallengeTeamWizard.tsx"],"names":[],"mappings":"AAuDA,MAAM,MAAM,wBAAwB,GAAG;IACrC,SAAS,EAAE,MAAM,CAAA;IACjB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,OAAO,EAAE,MAAM,IAAI,CAAA;CACpB,CAAA;AAED;;;;GAIG;AACH,iBAAS,mBAAmB,CAAC,KAAK,EAAE,wBAAwB,2CA8W3D;AAED,eAAe,mBAAmB,CAAA"}
|
|
@@ -23,7 +23,7 @@ var C = /* @__PURE__ */ function(e) {
|
|
|
23
23
|
}(C || {});
|
|
24
24
|
function w(e) {
|
|
25
25
|
switch (e) {
|
|
26
|
-
case C.SELECT_YOUR_CHALLENGE_TEAM: return "Select Your
|
|
26
|
+
case C.SELECT_YOUR_CHALLENGE_TEAM: return "Select Your Submission Team";
|
|
27
27
|
case C.ACCEPT_INVITATION: return "Invitation to Join Team";
|
|
28
28
|
case C.JOIN_REQUEST_FORM: return "Request Team Membership";
|
|
29
29
|
case C.JOIN_REQUEST_SENT: return "Request Sent";
|
|
@@ -181,7 +181,7 @@ function T(T) {
|
|
|
181
181
|
onCancel: le,
|
|
182
182
|
open: D,
|
|
183
183
|
actions: de,
|
|
184
|
-
title: w(A)
|
|
184
|
+
title: `Challenge Registration (Step 2 of 2): ${w(A)}`,
|
|
185
185
|
content: /* @__PURE__ */ x(t, { children: /* @__PURE__ */ x(g, {
|
|
186
186
|
sx: {
|
|
187
187
|
display: "flex",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ChallengeTeamWizard.js","names":[],"sources":["../../../src/components/ChallengeTeamWizard/ChallengeTeamWizard.tsx"],"sourcesContent":["import {\n useAddMemberToTeam,\n useGetCurrentUserProfile,\n useGetEntityChallenge,\n useGetMembershipStatus,\n useGetUserSubmissionTeams,\n} from '@/synapse-queries'\nimport { useSynapseContext } from '@/utils'\nimport { Alert, Box, Button, Tooltip, Typography } from '@mui/material'\nimport { noop } from 'lodash-es'\nimport { useCallback, useMemo, useRef, useState } from 'react'\nimport { DialogBase } from '../DialogBase'\nimport { SignInPrompt, SynapseErrorBoundary } from '../error/ErrorBanner'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport {\n CreateChallengeTeam,\n CreateChallengeTeamHandle,\n} from './CreateChallengeTeam'\nimport {\n MembershipRequestForm,\n MembershipRequestFormHandle,\n} from './MembershipRequestForm'\nimport {\n AcceptMembershipInvitationButton,\n OpenMembershipInvitation,\n} from './OpenMembershipInvitation'\nimport { RegistrationSuccessful } from './RegistrationSuccessful'\nimport { SelectChallengeTeam } from './SelectChallengeTeam'\n\nenum ChallengeTeamWizardStep {\n SELECT_YOUR_CHALLENGE_TEAM = 'SELECT_YOUR_CHALLENGE_TEAM',\n ACCEPT_INVITATION = 'ACCEPT_INVITATION',\n JOIN_REQUEST_FORM = 'JOIN_REQUEST_FORM',\n JOIN_REQUEST_SENT = 'JOIN_REQUEST_SENT',\n CREATE_NEW_TEAM = 'CREATE_NEW_TEAM',\n REGISTRATION_SUCCESSFUL = 'REGISTRATION_SUCCESSFUL',\n}\n\nfunction getStepDialogTitle(step: ChallengeTeamWizardStep) {\n switch (step) {\n case ChallengeTeamWizardStep.SELECT_YOUR_CHALLENGE_TEAM:\n return 'Select Your Challenge Team'\n case ChallengeTeamWizardStep.ACCEPT_INVITATION:\n return 'Invitation to Join Team'\n case ChallengeTeamWizardStep.JOIN_REQUEST_FORM:\n return 'Request Team Membership'\n case ChallengeTeamWizardStep.JOIN_REQUEST_SENT:\n return 'Request Sent'\n case ChallengeTeamWizardStep.CREATE_NEW_TEAM:\n return 'Create Team'\n case ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL:\n return 'Registration Successful!'\n }\n}\n\nexport type ChallengeTeamWizardProps = {\n projectId: string\n isShowingModal?: boolean\n onClose: () => void\n}\n\n/**\n * The ChallengeTeamWizard is used to guide a user through the process of joining or creating a team for a challenge.\n *\n * A required precondition is that the user is NOT on any registered submission team for the challenge.\n */\nfunction ChallengeTeamWizard(props: ChallengeTeamWizardProps) {\n const { projectId, isShowingModal = false, onClose } = props\n const { isAuthenticated } = useSynapseContext()\n\n const [step, setStep] = useState<ChallengeTeamWizardStep>(\n ChallengeTeamWizardStep.SELECT_YOUR_CHALLENGE_TEAM,\n )\n const [selectedTeamId, setSelectedTeamId] = useState<string | undefined>()\n\n // Tracks if the form to create a new team is valid, so the wizard can control the `disabled` status of the confirm button\n const [canCreateNewTeam, setCanCreateNewTeam] = useState(false)\n // true if the user has created a new team to register for the challenge\n const [hasCreatedNewTeam, setHasCreatedNewTeam] = useState<boolean>(false)\n\n const membershipRequestFormRef = useRef<MembershipRequestFormHandle>(null)\n const createTeamRef = useRef<CreateChallengeTeamHandle>(null)\n\n const { data: userProfile, isLoading: isLoadingUserProfile } =\n useGetCurrentUserProfile({\n enabled: isAuthenticated,\n })\n\n // Retrieve the challenge associated with the projectId passed through props\n const { data: challenge, isLoading: isLoadingChallenge } =\n useGetEntityChallenge(projectId)\n\n const {\n mutateAsync: addTeamMember,\n isPending: addMemberToTeamIsPending,\n error: addUserToTeamError,\n } = useAddMemberToTeam()\n\n // Determine whether the given user belongs to any submission teams\n const { data: userSubmissionTeams, error: userSubmissionTeamError } =\n useGetUserSubmissionTeams(challenge?.id!, 1, 0, {\n enabled: Boolean(isAuthenticated && challenge),\n })\n\n const isMemberOfSubmissionTeam =\n userSubmissionTeams && userSubmissionTeams.results.length > 0\n\n const {\n data: selectedTeamMembershipStatus,\n isLoading: selectedTeamMembershipStatusIsLoading,\n error: selectedTeamMembershipStatusError,\n } = useGetMembershipStatus(selectedTeamId!, String(userProfile?.ownerId), {\n enabled: isAuthenticated && !!selectedTeamId && !!userProfile,\n })\n\n const addUserToTeam = useCallback(async () => {\n if (!selectedTeamId || !userProfile) return\n await addTeamMember({\n teamId: selectedTeamId,\n userId: userProfile.ownerId,\n })\n setStep(ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL)\n }, [addTeamMember, setStep, selectedTeamId, userProfile])\n\n const hide = useCallback(() => {\n setHasCreatedNewTeam(false)\n setSelectedTeamId(undefined)\n onClose()\n }, [onClose])\n\n const isLoading = isLoadingUserProfile || isLoadingChallenge\n\n const backButton = useMemo(() => {\n switch (step) {\n case ChallengeTeamWizardStep.SELECT_YOUR_CHALLENGE_TEAM:\n case ChallengeTeamWizardStep.JOIN_REQUEST_SENT:\n case ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL:\n // Cannot go back from these steps\n return <></>\n case ChallengeTeamWizardStep.ACCEPT_INVITATION:\n case ChallengeTeamWizardStep.JOIN_REQUEST_FORM:\n case ChallengeTeamWizardStep.CREATE_NEW_TEAM:\n default:\n // All the other steps go back to team selection\n return (\n <Button\n variant={'outlined'}\n onClick={() => {\n setStep(ChallengeTeamWizardStep.SELECT_YOUR_CHALLENGE_TEAM)\n setSelectedTeamId(undefined)\n }}\n >\n Back\n </Button>\n )\n }\n }, [step])\n\n const closeButton = useMemo(() => {\n return (\n <Button\n variant={'contained'}\n onClick={() => {\n onClose()\n }}\n >\n Close\n </Button>\n )\n }, [onClose])\n\n // Determine modal content based on step.id\n const { actions = <></>, content = <></> } = useMemo(() => {\n if (!isAuthenticated) {\n return {\n content: (\n <Alert severity={'error'}>\n <SignInPrompt />\n </Alert>\n ),\n }\n }\n\n if (isMemberOfSubmissionTeam) {\n return {\n content: (\n <Alert severity={'error'}>\n <Typography>\n You are already a member of a registered submission team for this\n Challenge.\n </Typography>\n </Alert>\n ),\n }\n }\n\n switch (step) {\n case ChallengeTeamWizardStep.SELECT_YOUR_CHALLENGE_TEAM: {\n let buttonText = 'Join Team'\n let disableJoiningSelectedTeam = false\n let buttonOnClickBehavior: () => void = noop\n let buttonTooltip = ''\n if (\n selectedTeamMembershipStatus &&\n selectedTeamMembershipStatus.hasOpenInvitation\n ) {\n // The user has been invited to join the selected team\n buttonText = 'View Invitation to Join Team'\n buttonOnClickBehavior = () => {\n setStep(ChallengeTeamWizardStep.ACCEPT_INVITATION)\n }\n } else if (\n selectedTeamMembershipStatus &&\n selectedTeamMembershipStatus.hasOpenRequest\n ) {\n // User already has an open request to join the selected team, disable button to avoid request spamming\n buttonText = 'Join Request Pending'\n disableJoiningSelectedTeam = true\n buttonTooltip =\n 'You have already submitted a request to join this team.'\n } else if (\n selectedTeamMembershipStatus &&\n selectedTeamMembershipStatus.membershipApprovalRequired\n ) {\n // The user has to send a request to join the selected team\n buttonText = 'Request to Join Team'\n buttonOnClickBehavior = () => {\n setStep(ChallengeTeamWizardStep.JOIN_REQUEST_FORM)\n }\n } else if (\n selectedTeamMembershipStatus &&\n selectedTeamMembershipStatus.canJoin\n ) {\n // The user can freely join the selected team\n buttonText = 'Join Team'\n buttonOnClickBehavior = () => {\n void addUserToTeam()\n }\n }\n return {\n content: challenge && !isMemberOfSubmissionTeam && (\n <SelectChallengeTeam\n challengeId={challenge.id}\n onCreateTeam={() =>\n setStep(ChallengeTeamWizardStep.CREATE_NEW_TEAM)\n }\n selectedTeamId={selectedTeamId}\n onSelectTeam={teamId => setSelectedTeamId(teamId)}\n />\n ),\n actions: (\n <>\n {backButton}\n <Tooltip title={buttonTooltip}>\n {/* Wrap button in span to show tooltip when button is disabled */}\n <span>\n <Button\n onClick={buttonOnClickBehavior}\n startIcon={\n addMemberToTeamIsPending ? <SynapseSpinner /> : undefined\n }\n disabled={\n !selectedTeamId ||\n selectedTeamMembershipStatusIsLoading ||\n addMemberToTeamIsPending ||\n disableJoiningSelectedTeam\n }\n variant={'contained'}\n >\n {buttonText}\n </Button>\n </span>\n </Tooltip>\n </>\n ),\n }\n }\n case ChallengeTeamWizardStep.ACCEPT_INVITATION:\n return {\n content: <OpenMembershipInvitation teamId={selectedTeamId!} />,\n actions: (\n <>\n {backButton}\n <AcceptMembershipInvitationButton\n teamId={selectedTeamId!}\n onSuccess={() => {\n setStep(ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL)\n }}\n />\n </>\n ),\n }\n case ChallengeTeamWizardStep.JOIN_REQUEST_FORM:\n return {\n content: (\n <MembershipRequestForm\n ref={membershipRequestFormRef}\n teamId={selectedTeamId!}\n onRequestSubmitted={() => {\n setStep(ChallengeTeamWizardStep.JOIN_REQUEST_SENT)\n }}\n />\n ),\n actions: (\n <>\n {backButton}\n <Button\n variant={'contained'}\n onClick={() => {\n membershipRequestFormRef?.current?.submit()\n }}\n >\n Send Request\n </Button>\n </>\n ),\n }\n\n case ChallengeTeamWizardStep.JOIN_REQUEST_SENT:\n return {\n content: (\n <Typography variant=\"body1\" sx={{ lineHeight: '20px' }}>\n Team Manager(s) have received your request. Check your Synapse\n email address for status of your request.\n </Typography>\n ),\n actions: (\n <>\n {backButton}\n {closeButton}\n </>\n ),\n }\n case ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL:\n return {\n content: (\n <RegistrationSuccessful\n createdNewTeam={hasCreatedNewTeam}\n teamId={selectedTeamId}\n />\n ),\n actions: (\n <>\n {backButton}\n {closeButton}\n </>\n ),\n }\n case ChallengeTeamWizardStep.CREATE_NEW_TEAM: {\n return {\n content: (\n <CreateChallengeTeam\n ref={createTeamRef}\n challengeId={challenge?.id!}\n onCanSubmitChange={canSubmit => setCanCreateNewTeam(canSubmit)}\n onFinished={teamId => {\n setHasCreatedNewTeam(true)\n setSelectedTeamId(teamId)\n setStep(ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL)\n }}\n />\n ),\n actions: (\n <>\n {backButton}\n <Button\n variant={'contained'}\n disabled={!canCreateNewTeam}\n onClick={() => {\n createTeamRef?.current?.submit()\n }}\n >\n Create Team\n </Button>\n </>\n ),\n }\n }\n }\n }, [\n isAuthenticated,\n isMemberOfSubmissionTeam,\n step,\n selectedTeamId,\n backButton,\n closeButton,\n hasCreatedNewTeam,\n selectedTeamMembershipStatus,\n challenge,\n addMemberToTeamIsPending,\n selectedTeamMembershipStatusIsLoading,\n addUserToTeam,\n canCreateNewTeam,\n ])\n\n const errorMessage =\n addUserToTeamError?.message ||\n selectedTeamMembershipStatusError?.message ||\n userSubmissionTeamError?.message\n\n return (\n <DialogBase\n onCancel={hide}\n open={isShowingModal}\n actions={actions}\n title={getStepDialogTitle(step)}\n content={\n <SynapseErrorBoundary>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n gap: 1,\n }}\n >\n {isLoading ? (\n <SynapseSpinner size={40} />\n ) : (\n <>\n {content}\n {errorMessage && (\n <Alert severity={'error'}>{errorMessage}</Alert>\n )}\n </>\n )}\n </Box>\n </SynapseErrorBoundary>\n }\n />\n )\n}\n\nexport default ChallengeTeamWizard\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ChallengeTeamWizard.js","names":[],"sources":["../../../src/components/ChallengeTeamWizard/ChallengeTeamWizard.tsx"],"sourcesContent":["import {\n useAddMemberToTeam,\n useGetCurrentUserProfile,\n useGetEntityChallenge,\n useGetMembershipStatus,\n useGetUserSubmissionTeams,\n} from '@/synapse-queries'\nimport { useSynapseContext } from '@/utils'\nimport { Alert, Box, Button, Tooltip, Typography } from '@mui/material'\nimport { noop } from 'lodash-es'\nimport { useCallback, useMemo, useRef, useState } from 'react'\nimport { DialogBase } from '../DialogBase'\nimport { SignInPrompt, SynapseErrorBoundary } from '../error/ErrorBanner'\nimport { SynapseSpinner } from '../LoadingScreen/LoadingScreen'\nimport {\n CreateChallengeTeam,\n CreateChallengeTeamHandle,\n} from './CreateChallengeTeam'\nimport {\n MembershipRequestForm,\n MembershipRequestFormHandle,\n} from './MembershipRequestForm'\nimport {\n AcceptMembershipInvitationButton,\n OpenMembershipInvitation,\n} from './OpenMembershipInvitation'\nimport { RegistrationSuccessful } from './RegistrationSuccessful'\nimport { SelectChallengeTeam } from './SelectChallengeTeam'\n\nenum ChallengeTeamWizardStep {\n SELECT_YOUR_CHALLENGE_TEAM = 'SELECT_YOUR_CHALLENGE_TEAM',\n ACCEPT_INVITATION = 'ACCEPT_INVITATION',\n JOIN_REQUEST_FORM = 'JOIN_REQUEST_FORM',\n JOIN_REQUEST_SENT = 'JOIN_REQUEST_SENT',\n CREATE_NEW_TEAM = 'CREATE_NEW_TEAM',\n REGISTRATION_SUCCESSFUL = 'REGISTRATION_SUCCESSFUL',\n}\n\nfunction getStepDialogTitle(step: ChallengeTeamWizardStep) {\n switch (step) {\n case ChallengeTeamWizardStep.SELECT_YOUR_CHALLENGE_TEAM:\n return 'Select Your Submission Team'\n case ChallengeTeamWizardStep.ACCEPT_INVITATION:\n return 'Invitation to Join Team'\n case ChallengeTeamWizardStep.JOIN_REQUEST_FORM:\n return 'Request Team Membership'\n case ChallengeTeamWizardStep.JOIN_REQUEST_SENT:\n return 'Request Sent'\n case ChallengeTeamWizardStep.CREATE_NEW_TEAM:\n return 'Create Team'\n case ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL:\n return 'Registration Successful!'\n }\n}\n\nexport type ChallengeTeamWizardProps = {\n projectId: string\n isShowingModal?: boolean\n onClose: () => void\n}\n\n/**\n * The ChallengeTeamWizard is used to guide a user through the process of joining or creating a team for a challenge.\n *\n * A required precondition is that the user is NOT on any registered submission team for the challenge.\n */\nfunction ChallengeTeamWizard(props: ChallengeTeamWizardProps) {\n const { projectId, isShowingModal = false, onClose } = props\n const { isAuthenticated } = useSynapseContext()\n\n const [step, setStep] = useState<ChallengeTeamWizardStep>(\n ChallengeTeamWizardStep.SELECT_YOUR_CHALLENGE_TEAM,\n )\n const [selectedTeamId, setSelectedTeamId] = useState<string | undefined>()\n\n // Tracks if the form to create a new team is valid, so the wizard can control the `disabled` status of the confirm button\n const [canCreateNewTeam, setCanCreateNewTeam] = useState(false)\n // true if the user has created a new team to register for the challenge\n const [hasCreatedNewTeam, setHasCreatedNewTeam] = useState<boolean>(false)\n\n const membershipRequestFormRef = useRef<MembershipRequestFormHandle>(null)\n const createTeamRef = useRef<CreateChallengeTeamHandle>(null)\n\n const { data: userProfile, isLoading: isLoadingUserProfile } =\n useGetCurrentUserProfile({\n enabled: isAuthenticated,\n })\n\n // Retrieve the challenge associated with the projectId passed through props\n const { data: challenge, isLoading: isLoadingChallenge } =\n useGetEntityChallenge(projectId)\n\n const {\n mutateAsync: addTeamMember,\n isPending: addMemberToTeamIsPending,\n error: addUserToTeamError,\n } = useAddMemberToTeam()\n\n // Determine whether the given user belongs to any submission teams\n const { data: userSubmissionTeams, error: userSubmissionTeamError } =\n useGetUserSubmissionTeams(challenge?.id!, 1, 0, {\n enabled: Boolean(isAuthenticated && challenge),\n })\n\n const isMemberOfSubmissionTeam =\n userSubmissionTeams && userSubmissionTeams.results.length > 0\n\n const {\n data: selectedTeamMembershipStatus,\n isLoading: selectedTeamMembershipStatusIsLoading,\n error: selectedTeamMembershipStatusError,\n } = useGetMembershipStatus(selectedTeamId!, String(userProfile?.ownerId), {\n enabled: isAuthenticated && !!selectedTeamId && !!userProfile,\n })\n\n const addUserToTeam = useCallback(async () => {\n if (!selectedTeamId || !userProfile) return\n await addTeamMember({\n teamId: selectedTeamId,\n userId: userProfile.ownerId,\n })\n setStep(ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL)\n }, [addTeamMember, setStep, selectedTeamId, userProfile])\n\n const hide = useCallback(() => {\n setHasCreatedNewTeam(false)\n setSelectedTeamId(undefined)\n onClose()\n }, [onClose])\n\n const isLoading = isLoadingUserProfile || isLoadingChallenge\n\n const backButton = useMemo(() => {\n switch (step) {\n case ChallengeTeamWizardStep.SELECT_YOUR_CHALLENGE_TEAM:\n case ChallengeTeamWizardStep.JOIN_REQUEST_SENT:\n case ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL:\n // Cannot go back from these steps\n return <></>\n case ChallengeTeamWizardStep.ACCEPT_INVITATION:\n case ChallengeTeamWizardStep.JOIN_REQUEST_FORM:\n case ChallengeTeamWizardStep.CREATE_NEW_TEAM:\n default:\n // All the other steps go back to team selection\n return (\n <Button\n variant={'outlined'}\n onClick={() => {\n setStep(ChallengeTeamWizardStep.SELECT_YOUR_CHALLENGE_TEAM)\n setSelectedTeamId(undefined)\n }}\n >\n Back\n </Button>\n )\n }\n }, [step])\n\n const closeButton = useMemo(() => {\n return (\n <Button\n variant={'contained'}\n onClick={() => {\n onClose()\n }}\n >\n Close\n </Button>\n )\n }, [onClose])\n\n // Determine modal content based on step.id\n const { actions = <></>, content = <></> } = useMemo(() => {\n if (!isAuthenticated) {\n return {\n content: (\n <Alert severity={'error'}>\n <SignInPrompt />\n </Alert>\n ),\n }\n }\n\n if (isMemberOfSubmissionTeam) {\n return {\n content: (\n <Alert severity={'error'}>\n <Typography>\n You are already a member of a registered submission team for this\n Challenge.\n </Typography>\n </Alert>\n ),\n }\n }\n\n switch (step) {\n case ChallengeTeamWizardStep.SELECT_YOUR_CHALLENGE_TEAM: {\n let buttonText = 'Join Team'\n let disableJoiningSelectedTeam = false\n let buttonOnClickBehavior: () => void = noop\n let buttonTooltip = ''\n if (\n selectedTeamMembershipStatus &&\n selectedTeamMembershipStatus.hasOpenInvitation\n ) {\n // The user has been invited to join the selected team\n buttonText = 'View Invitation to Join Team'\n buttonOnClickBehavior = () => {\n setStep(ChallengeTeamWizardStep.ACCEPT_INVITATION)\n }\n } else if (\n selectedTeamMembershipStatus &&\n selectedTeamMembershipStatus.hasOpenRequest\n ) {\n // User already has an open request to join the selected team, disable button to avoid request spamming\n buttonText = 'Join Request Pending'\n disableJoiningSelectedTeam = true\n buttonTooltip =\n 'You have already submitted a request to join this team.'\n } else if (\n selectedTeamMembershipStatus &&\n selectedTeamMembershipStatus.membershipApprovalRequired\n ) {\n // The user has to send a request to join the selected team\n buttonText = 'Request to Join Team'\n buttonOnClickBehavior = () => {\n setStep(ChallengeTeamWizardStep.JOIN_REQUEST_FORM)\n }\n } else if (\n selectedTeamMembershipStatus &&\n selectedTeamMembershipStatus.canJoin\n ) {\n // The user can freely join the selected team\n buttonText = 'Join Team'\n buttonOnClickBehavior = () => {\n void addUserToTeam()\n }\n }\n return {\n content: challenge && !isMemberOfSubmissionTeam && (\n <SelectChallengeTeam\n challengeId={challenge.id}\n onCreateTeam={() =>\n setStep(ChallengeTeamWizardStep.CREATE_NEW_TEAM)\n }\n selectedTeamId={selectedTeamId}\n onSelectTeam={teamId => setSelectedTeamId(teamId)}\n />\n ),\n actions: (\n <>\n {backButton}\n <Tooltip title={buttonTooltip}>\n {/* Wrap button in span to show tooltip when button is disabled */}\n <span>\n <Button\n onClick={buttonOnClickBehavior}\n startIcon={\n addMemberToTeamIsPending ? <SynapseSpinner /> : undefined\n }\n disabled={\n !selectedTeamId ||\n selectedTeamMembershipStatusIsLoading ||\n addMemberToTeamIsPending ||\n disableJoiningSelectedTeam\n }\n variant={'contained'}\n >\n {buttonText}\n </Button>\n </span>\n </Tooltip>\n </>\n ),\n }\n }\n case ChallengeTeamWizardStep.ACCEPT_INVITATION:\n return {\n content: <OpenMembershipInvitation teamId={selectedTeamId!} />,\n actions: (\n <>\n {backButton}\n <AcceptMembershipInvitationButton\n teamId={selectedTeamId!}\n onSuccess={() => {\n setStep(ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL)\n }}\n />\n </>\n ),\n }\n case ChallengeTeamWizardStep.JOIN_REQUEST_FORM:\n return {\n content: (\n <MembershipRequestForm\n ref={membershipRequestFormRef}\n teamId={selectedTeamId!}\n onRequestSubmitted={() => {\n setStep(ChallengeTeamWizardStep.JOIN_REQUEST_SENT)\n }}\n />\n ),\n actions: (\n <>\n {backButton}\n <Button\n variant={'contained'}\n onClick={() => {\n membershipRequestFormRef?.current?.submit()\n }}\n >\n Send Request\n </Button>\n </>\n ),\n }\n\n case ChallengeTeamWizardStep.JOIN_REQUEST_SENT:\n return {\n content: (\n <Typography variant=\"body1\" sx={{ lineHeight: '20px' }}>\n Team Manager(s) have received your request. Check your Synapse\n email address for status of your request.\n </Typography>\n ),\n actions: (\n <>\n {backButton}\n {closeButton}\n </>\n ),\n }\n case ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL:\n return {\n content: (\n <RegistrationSuccessful\n createdNewTeam={hasCreatedNewTeam}\n teamId={selectedTeamId}\n />\n ),\n actions: (\n <>\n {backButton}\n {closeButton}\n </>\n ),\n }\n case ChallengeTeamWizardStep.CREATE_NEW_TEAM: {\n return {\n content: (\n <CreateChallengeTeam\n ref={createTeamRef}\n challengeId={challenge?.id!}\n onCanSubmitChange={canSubmit => setCanCreateNewTeam(canSubmit)}\n onFinished={teamId => {\n setHasCreatedNewTeam(true)\n setSelectedTeamId(teamId)\n setStep(ChallengeTeamWizardStep.REGISTRATION_SUCCESSFUL)\n }}\n />\n ),\n actions: (\n <>\n {backButton}\n <Button\n variant={'contained'}\n disabled={!canCreateNewTeam}\n onClick={() => {\n createTeamRef?.current?.submit()\n }}\n >\n Create Team\n </Button>\n </>\n ),\n }\n }\n }\n }, [\n isAuthenticated,\n isMemberOfSubmissionTeam,\n step,\n selectedTeamId,\n backButton,\n closeButton,\n hasCreatedNewTeam,\n selectedTeamMembershipStatus,\n challenge,\n addMemberToTeamIsPending,\n selectedTeamMembershipStatusIsLoading,\n addUserToTeam,\n canCreateNewTeam,\n ])\n\n const errorMessage =\n addUserToTeamError?.message ||\n selectedTeamMembershipStatusError?.message ||\n userSubmissionTeamError?.message\n\n return (\n <DialogBase\n onCancel={hide}\n open={isShowingModal}\n actions={actions}\n title={`Challenge Registration (Step 2 of 2): ${getStepDialogTitle(\n step,\n )}`}\n content={\n <SynapseErrorBoundary>\n <Box\n sx={{\n display: 'flex',\n flexDirection: 'column',\n gap: 1,\n }}\n >\n {isLoading ? (\n <SynapseSpinner size={40} />\n ) : (\n <>\n {content}\n {errorMessage && (\n <Alert severity={'error'}>{errorMessage}</Alert>\n )}\n </>\n )}\n </Box>\n </SynapseErrorBoundary>\n }\n />\n )\n}\n\nexport default ChallengeTeamWizard\n"],"mappings":"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"}
|
|
@@ -24,7 +24,7 @@ function r(e, t) {
|
|
|
24
24
|
if (r.length !== i.length) return !1;
|
|
25
25
|
for (let n of r) {
|
|
26
26
|
let r = e[n], i = t[n], a = (e) => e == null || e === "";
|
|
27
|
-
if (!(a(r) && a(i)) &&
|
|
27
|
+
if (!(a(r) && a(i)) && !Object.is(r, i)) return !1;
|
|
28
28
|
}
|
|
29
29
|
return !0;
|
|
30
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DataGridUtils.js","names":["SYNAPSE_ENTITY_ID_REGEX","DataGridRow","Operation","QueryInput","GRID_ROW_REACT_KEY_PROPERTY","parseQueryInput","input","trimmedInput","trim","type","toUpperCase","startsWith","test","rowsAreIdentical","a","b","isDataKey","key","aKeys","Object","keys","filter","bKeys","length","aVal","bVal","isNullish","v","undefined","
|
|
1
|
+
{"version":3,"file":"DataGridUtils.js","names":["SYNAPSE_ENTITY_ID_REGEX","DataGridRow","Operation","QueryInput","GRID_ROW_REACT_KEY_PROPERTY","parseQueryInput","input","trimmedInput","trim","type","toUpperCase","startsWith","test","rowsAreIdentical","a","b","isDataKey","key","aKeys","Object","keys","filter","bKeys","length","aVal","bVal","isNullish","v","undefined","is","removeNoOpOperations","newValue","rowValues","operations","isNoop","operation","oldVal","slice","fromRowIndex","toRowIndex","newVal","comparisonResults","map","oldItem","idx","every","Boolean","op"],"sources":["../../../../src/components/DataGrid/utils/DataGridUtils.ts"],"sourcesContent":["import { SYNAPSE_ENTITY_ID_REGEX } from '@/utils/functions/RegularExpressions'\nimport { DataGridRow, Operation, QueryInput } from '../DataGridTypes'\n\n// We embed a value into the in row data passed to react-datasheet-grid for use as a render optimization\nexport const GRID_ROW_REACT_KEY_PROPERTY = '__rowKey'\n\n// Query Input can either be an empty string, a SQL query, or a session ID\nexport const parseQueryInput = (input: string): QueryInput => {\n const trimmedInput = input.trim()\n if (!trimmedInput) {\n return { type: 'empty', input: '' }\n } else if (trimmedInput.toUpperCase().startsWith('SELECT')) {\n return { type: 'sql', input: trimmedInput }\n } else if (SYNAPSE_ENTITY_ID_REGEX.test(trimmedInput)) {\n return { type: 'recordSetId', input: trimmedInput }\n } else if (/^[A-Za-z]\\w*=+$/.test(trimmedInput)) {\n return { type: 'sessionId', input: trimmedInput }\n }\n return { type: 'unknown', input: trimmedInput }\n}\n\nexport function rowsAreIdentical(a: DataGridRow, b: DataGridRow): boolean {\n const isDataKey = (key: string) => !key.startsWith('__')\n const aKeys = Object.keys(a).filter(isDataKey)\n const bKeys = Object.keys(b).filter(isDataKey)\n if (aKeys.length !== bKeys.length) return false\n for (const key of aKeys) {\n const aVal = a[key] as string | number | boolean | null | undefined\n const bVal = b[key] as string | number | boolean | null | undefined\n // Treat null, undefined, and empty string as equivalent\n const isNullish = (v: unknown) => v === null || v === undefined || v === ''\n if (isNullish(aVal) && isNullish(bVal)) continue\n if (!Object.is(aVal, bVal)) return false\n }\n return true\n}\n\n/**\n * Remove no-op operations created by react-datasheet-grid that would result in invalid or undesired changes to the json-joy CRDT model\n * @param newValue\n * @param rowValues\n * @param operations\n */\nexport function removeNoOpOperations(\n newValue: DataGridRow[],\n rowValues: DataGridRow[],\n operations: Operation[],\n) {\n function isNoop(operation: Operation): boolean {\n if (operation.type === 'UPDATE') {\n const oldVal = rowValues.slice(\n operation.fromRowIndex,\n operation.toRowIndex,\n )\n const newVal = newValue.slice(\n operation.fromRowIndex,\n operation.toRowIndex,\n )\n\n const comparisonResults = oldVal.map((oldItem, idx) =>\n rowsAreIdentical(oldItem, newVal[idx]),\n )\n return comparisonResults.every(Boolean)\n }\n return false\n }\n\n return operations.filter(op => !isNoop(op))\n}\n"],"mappings":";;AAIA,IAAaI,IAA8B,YAG9BC,KAAmBC,MAA8B;CAC5D,IAAMC,IAAeD,EAAME,MAAM;AAUjC,QATKD,IAEMA,EAAaG,aAAa,CAACC,WAAW,SAAS,GACjD;EAAEF,MAAM;EAAOH,OAAOC;EAAc,GAClCP,EAAwBY,KAAKL,EAAa,GAC5C;EAAEE,MAAM;EAAeH,OAAOC;EAAc,GAC1C,kBAAkBK,KAAKL,EAAa,GACtC;EAAEE,MAAM;EAAaH,OAAOC;EAAc,GAE5C;EAAEE,MAAM;EAAWH,OAAOC;EAAc,GARtC;EAAEE,MAAM;EAASH,OAAO;EAAI;;AAWvC,SAAgBO,EAAiBC,GAAgBC,GAAyB;CACxE,IAAMC,KAAaC,MAAgB,CAACA,EAAIN,WAAW,KAAK,EAClDO,IAAQC,OAAOC,KAAKN,EAAE,CAACO,OAAOL,EAAU,EACxCM,IAAQH,OAAOC,KAAKL,EAAE,CAACM,OAAOL,EAAU;AAC9C,KAAIE,EAAMK,WAAWD,EAAMC,OAAQ,QAAO;AAC1C,MAAK,IAAMN,KAAOC,GAAO;EACvB,IAAMM,IAAOV,EAAEG,IACTQ,IAAOV,EAAEE,IAETS,KAAaC,MAAeA,KAAM,QAA2BA,MAAM;AACrED,UAAUF,EAAK,IAAIE,EAAUD,EAAK,KAClC,CAACN,OAAOU,GAAGL,GAAMC,EAAK,CAAE,QAAO;;AAErC,QAAO;;AAST,SAAgBK,EACdC,GACAC,GACAC,GACA;CACA,SAASC,EAAOC,GAA+B;AAC7C,MAAIA,EAAU1B,SAAS,UAAU;GAC/B,IAAM2B,IAASJ,EAAUK,MACvBF,EAAUG,cACVH,EAAUI,WACX,EACKC,IAAST,EAASM,MACtBF,EAAUG,cACVH,EAAUI,WACX;AAKD,UAH0BH,EAAOM,KAAKC,GAASC,MAC7C/B,EAAiB8B,GAASH,EAAOI,GACnC,CACOH,CAAkBI,MAAMC,QAAQ;;AAEzC,SAAO;;AAGT,QAAOb,EAAWZ,QAAO0B,MAAM,CAACb,EAAOa,EAAG,CAAC"}
|
|
@@ -2,6 +2,12 @@ import { EntityType } from '@sage-bionetworks/synapse-client';
|
|
|
2
2
|
import { RefObject } from 'react';
|
|
3
3
|
export declare const PYTHON_CLIENT_IMPORT_AND_LOGIN = "import synapseclient\nsyn = synapseclient.Synapse()\nsyn.login(authToken=\"YOUR_TOKEN_HERE\")";
|
|
4
4
|
export declare const R_CLIENT_IMPORT_AND_LOGIN = "library(synapser)\nsynLogin(authToken=\"YOUR_TOKEN_HERE\")";
|
|
5
|
+
type ProgrammaticAccessCode = {
|
|
6
|
+
cliCode: string | undefined;
|
|
7
|
+
rCode: string | undefined;
|
|
8
|
+
pythonCode: string | undefined;
|
|
9
|
+
};
|
|
10
|
+
export declare function getProgrammaticAccessCode(type: EntityType, entityId: string, version: number | undefined): ProgrammaticAccessCode;
|
|
5
11
|
declare enum DownloadAction {
|
|
6
12
|
downloadFile = 0,
|
|
7
13
|
addToCart = 1,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityDownloadButton.d.ts","sourceRoot":"","sources":["../../../src/components/EntityDownloadButton/EntityDownloadButton.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAK7D,OAAO,EAAE,SAAS,EAAY,MAAM,OAAO,CAAA;AAkB3C,eAAO,MAAM,8BAA8B,kGAEJ,CAAA;AAGvC,eAAO,MAAM,yBAAyB,+DACA,CAAA;
|
|
1
|
+
{"version":3,"file":"EntityDownloadButton.d.ts","sourceRoot":"","sources":["../../../src/components/EntityDownloadButton/EntityDownloadButton.tsx"],"names":[],"mappings":"AAiBA,OAAO,EAAE,UAAU,EAAE,MAAM,kCAAkC,CAAA;AAK7D,OAAO,EAAE,SAAS,EAAY,MAAM,OAAO,CAAA;AAkB3C,eAAO,MAAM,8BAA8B,kGAEJ,CAAA;AAGvC,eAAO,MAAM,yBAAyB,+DACA,CAAA;AAEtC,KAAK,sBAAsB,GAAG;IAC5B,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;CAC/B,CAAA;AAGD,wBAAgB,yBAAyB,CACvC,IAAI,EAAE,UAAU,EAChB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GAAG,SAAS,GAC1B,sBAAsB,CAkDxB;AAED,aAAK,cAAc;IACjB,YAAY,IAAA;IACZ,SAAS,IAAA;IACT,kBAAkB,IAAA;IAClB,wBAAwB,IAAA;IACxB,WAAW,IAAA;CACZ;AA6FD,wBAAgB,+BAA+B,CAC7C,IAAI,EAAE,UAAU,GACf,cAAc,EAAE,EAAE,CAoCpB;AA2ED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,UAAU,CAAA;IACtB,6BAA6B,CAAC,EAAE,SAAS,CAAC,WAAW,GAAG,IAAI,CAAC,CAAA;IAC7D,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,2CAgLA"}
|
|
@@ -59,6 +59,11 @@ read.table(query$filepath, sep=",")`,
|
|
|
59
59
|
query = syn.tableQuery("SELECT * FROM ${r}")
|
|
60
60
|
query.asDataFrame()`
|
|
61
61
|
};
|
|
62
|
+
case C.searchindex: return {
|
|
63
|
+
cliCode: void 0,
|
|
64
|
+
rCode: void 0,
|
|
65
|
+
pythonCode: void 0
|
|
66
|
+
};
|
|
62
67
|
default: throw Error(`Unhandled EntityType: ${e}`);
|
|
63
68
|
}
|
|
64
69
|
}
|
|
@@ -207,6 +212,6 @@ function F(n) {
|
|
|
207
212
|
] });
|
|
208
213
|
}
|
|
209
214
|
//#endregion
|
|
210
|
-
export { F as EntityDownloadButton, E as PYTHON_CLIENT_IMPORT_AND_LOGIN, D as R_CLIENT_IMPORT_AND_LOGIN, M as getDownloadActionsForEntityType };
|
|
215
|
+
export { F as EntityDownloadButton, E as PYTHON_CLIENT_IMPORT_AND_LOGIN, D as R_CLIENT_IMPORT_AND_LOGIN, M as getDownloadActionsForEntityType, O as getProgrammaticAccessCode };
|
|
211
216
|
|
|
212
217
|
//# sourceMappingURL=EntityDownloadButton.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"EntityDownloadButton.js","names":[],"sources":["../../../src/components/EntityDownloadButton/EntityDownloadButton.tsx"],"sourcesContent":["import { useGetEntity, useGetVersions } from '@/synapse-queries'\nimport {\n useAddFileToDownloadList,\n useGetAddToDownloadListStats,\n} from '@/synapse-queries/index'\nimport { useSynapseContext } from '@/utils'\nimport {\n entityTypeToFriendlyName,\n hasFilesInView,\n isContainerType,\n isDataset,\n isEntityView,\n isVersionableEntity,\n} from '@/utils/functions/EntityTypeUtils'\nimport { useDirectDownloadHandler } from '@/utils/hooks/useDirectDownloadHandler'\nimport { isFileEntity } from '@/utils/types/IsType'\nimport { DownloadOutlined as DownloadIcon } from '@mui/icons-material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n FileHandleAssociateType,\n QueryBundleRequest,\n} from '@sage-bionetworks/synapse-types'\nimport { RefObject, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { displayFilesWereAddedToDownloadListSuccess } from '../download_list/DownloadConfirmationUtils'\nimport { EntityDownloadConfirmation } from '../EntityDownloadConfirmation'\nimport { DropdownMenu, DropdownMenuItem } from '../menu/DropdownMenu'\nimport { ModalDownload } from '../ModalDownload/ModalDownload'\nimport { ProgrammaticInstructionsModal } from '../ProgrammaticInstructionsModal/ProgrammaticInstructionsModal'\nimport { displayToast } from '../ToastMessage/index'\n\n// WIP\n// Per Nick Grosenbacher: For this to be reusable, I think we would also need to accept versionNumber as a prop. Where we would have the following behavior:\n// - If the version number is present, use it\n// - If the version number is null, do not use it,\n// - If the version number is undefined, then we would try to do the 'smart' thing-- get the latest version for datasets, otherwise don't use it.\n\n// Have to keep these consts outside of getProgrammaticAccessCode because\n// they are being called in ProgrammaticTableDownload.tsx\n// Python client import and login instructions\nexport const PYTHON_CLIENT_IMPORT_AND_LOGIN = `import synapseclient\nsyn = synapseclient.Synapse()\nsyn.login(authToken=\"YOUR_TOKEN_HERE\")`\n\n// R client import and login instructions\nexport const R_CLIENT_IMPORT_AND_LOGIN = `library(synapser)\nsynLogin(authToken=\"YOUR_TOKEN_HERE\")`\n\ntype ProgrammaticAccessCode = {\n cliCode: string | undefined\n rCode: string | undefined\n pythonCode: string | undefined\n}\n\n// Generate programmatic access code snippet content based on entity type\nfunction getProgrammaticAccessCode(\n type: EntityType,\n entityId: string,\n version: number | undefined,\n): ProgrammaticAccessCode {\n const id =\n type === EntityType.dataset && version ? `${entityId}.${version}` : entityId\n switch (type) {\n case EntityType.file:\n case EntityType.folder:\n case EntityType.project:\n case EntityType.link:\n return {\n cliCode: `synapse get -r ${entityId}`,\n rCode: `${R_CLIENT_IMPORT_AND_LOGIN} \\n\n# Download file\nsynGet('${entityId}')`,\n pythonCode: `${PYTHON_CLIENT_IMPORT_AND_LOGIN} \\n\n# Download file\nsyn.get('${entityId}')`,\n }\n case EntityType.dockerrepo:\n return {\n cliCode: `docker login -u <synapse username> -p <synapse password> docker.synapse.org \\n\ndocker pull docker.synapse.org/${entityId}/myrepo`,\n rCode: undefined,\n pythonCode: undefined,\n }\n case EntityType.dataset:\n case EntityType.entityview:\n case EntityType.datasetcollection:\n case EntityType.table:\n case EntityType.materializedview:\n case EntityType.submissionview:\n case EntityType.virtualtable:\n case EntityType.recordset:\n return {\n cliCode: `synapse get -q \"SELECT * FROM ${id}\"`,\n rCode: `${R_CLIENT_IMPORT_AND_LOGIN} \\n\nquery <- synTableQuery(\"SELECT * FROM ${id}\")\nread.table(query$filepath, sep=\",\")`,\n pythonCode: `${PYTHON_CLIENT_IMPORT_AND_LOGIN} \\n\nquery = syn.tableQuery(\"SELECT * FROM ${id}\")\nquery.asDataFrame()`,\n }\n default:\n throw new Error(`Unhandled EntityType: ${type}`)\n }\n}\n\nenum DownloadAction {\n downloadFile,\n addToCart,\n programmaticAccess,\n programmaticAccessDocker,\n exportTable,\n}\n\n// Function that creates menu items for download actions\nfunction getMenuItemForAction(\n entityId: string,\n entityName: string,\n entityType: EntityType,\n downloadAction: DownloadAction,\n setShowProgrammaticAccess: (show: boolean) => void,\n setShowExportMetadata: (show: boolean) => void,\n addFileToDownloadList: (params: {\n entityId: string\n entityVersionNumber: number | undefined\n }) => void,\n setShowDownloadConfirmation: (show: boolean) => void,\n versionNumber?: number,\n addToCartDisabled?: boolean,\n onDownloadFile?: () => void,\n isAuthenticated?: boolean,\n): DropdownMenuItem {\n switch (downloadAction) {\n case DownloadAction.downloadFile:\n return {\n text: 'Download File',\n onClick: () => {\n if (onDownloadFile) onDownloadFile()\n },\n tooltipText: isAuthenticated\n ? 'Download this file directly'\n : 'Sign in to download this file',\n disabled: !isAuthenticated,\n }\n case DownloadAction.addToCart:\n return {\n text: 'Add to Download List',\n disabled: addToCartDisabled,\n tooltipText: getAddToCartTooltip(entityType, !!addToCartDisabled),\n onClick: () => {\n if (\n entityType === EntityType.file ||\n entityType === EntityType.recordset\n ) {\n addFileToDownloadList({\n entityId,\n entityVersionNumber: versionNumber,\n })\n } else {\n setShowDownloadConfirmation(true)\n }\n },\n }\n case DownloadAction.programmaticAccess:\n return {\n text: 'Programmatic Access',\n onClick: () => {\n setShowProgrammaticAccess(true)\n },\n tooltipText: 'View programmatic access options',\n }\n case DownloadAction.programmaticAccessDocker:\n return {\n text: 'Programmatic Access (Docker)',\n onClick: () => {\n setShowProgrammaticAccess(true)\n },\n tooltipText: 'View programmatic options to pull Docker image',\n }\n case DownloadAction.exportTable:\n return {\n text: 'Export Table',\n onClick: () => {\n setShowExportMetadata(true)\n },\n tooltipText: 'Export table data',\n }\n }\n}\n\n/**\n * Determines the tooltip message based on the entity type and its \"add to cart\" status.\n */\nconst getAddToCartTooltip = (\n entityType: EntityType,\n isDisabled: boolean,\n): string => {\n if (!isDisabled) {\n return 'Add file(s) to your download list'\n }\n const entityFriendlyName = entityTypeToFriendlyName(entityType)\n return `This ${entityFriendlyName} has no accessible files`\n}\n\n// Function that returns DropdownMenuItem\nexport function getDownloadActionsForEntityType(\n type: EntityType,\n): DownloadAction[][] {\n switch (type) {\n case EntityType.file:\n case EntityType.recordset:\n return [\n [DownloadAction.downloadFile],\n [DownloadAction.addToCart, DownloadAction.programmaticAccess],\n ]\n case EntityType.project:\n case EntityType.folder:\n return [[DownloadAction.addToCart, DownloadAction.programmaticAccess]]\n case EntityType.dockerrepo:\n return [[DownloadAction.programmaticAccessDocker]]\n case EntityType.entityview:\n case EntityType.dataset:\n return [\n [\n DownloadAction.exportTable,\n DownloadAction.programmaticAccess,\n DownloadAction.addToCart,\n ],\n ]\n case EntityType.datasetcollection:\n case EntityType.table:\n case EntityType.materializedview:\n case EntityType.submissionview:\n case EntityType.virtualtable:\n return [[DownloadAction.exportTable, DownloadAction.programmaticAccess]]\n case EntityType.link:\n return [[DownloadAction.programmaticAccess]]\n case EntityType.searchindex:\n return []\n default:\n // this will fail if a new EntityType is added and not handled\n throw new Error(`Unhandled EntityType: ${type}`)\n }\n}\n\n// get the appropriate version number for download based on entity type\n// for datasets: returns the most recent released version if any exist, undefined otherwise\n// for other entities: returns the current version number\nfunction useGetLatestVersionNumber(entityId: string, entityType: EntityType) {\n // get entity data\n const { data: entityData, isLoading: entityDataLoading } =\n useGetEntity(entityId) // No version = latest\n\n // for datasets, check if any versions exist and use the most recent one\n const mustGetVersion = entityType === EntityType.dataset\n const { data: versionsData, isLoading: versionsLoading } = useGetVersions(\n entityId,\n 0,\n 1,\n {\n enabled: mustGetVersion,\n },\n )\n\n let latestVersionNumber: number | undefined\n\n if (mustGetVersion) {\n // for datasets, check if any versions exist\n if (versionsData?.results && versionsData.results.length > 0) {\n // Use the most recent released version (first in the list, since versions are returned in descending order)\n latestVersionNumber = versionsData.results[0].versionNumber\n } else {\n // no versions exist, use undefined (will use current/draft version)\n latestVersionNumber = undefined\n }\n } else {\n // for non-datasets, use the entity's version number\n latestVersionNumber =\n entityData && isVersionableEntity(entityData)\n ? entityData.versionNumber\n : undefined\n }\n\n const isLoading = entityDataLoading || versionsLoading\n\n return { latestVersionNumber, isLoading }\n}\n\n// create default queryBundleRequest with appropriate SQL\nfunction getDefaultQueryBundleRequestForEntity(\n entityId: string,\n versionNumber: number | undefined,\n entityType: EntityType,\n): QueryBundleRequest {\n let sql: string\n\n if (entityType === EntityType.dataset) {\n // for datasets:\n // - if a version number exists (released version), use it: syn123.5\n // - if no version number (no released versions), use current/draft: syn123\n sql = versionNumber\n ? `SELECT * FROM ${entityId}.${versionNumber}`\n : `SELECT * FROM ${entityId}`\n } else {\n // For non-datasets, always use entity ID without version\n sql = `SELECT * FROM ${entityId}`\n }\n\n return {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n entityId: `${entityId}`,\n query: {\n sql: sql,\n },\n partMask: 0,\n }\n}\n\nexport function EntityDownloadButton(props: {\n entityId: string\n name: string\n entityType: EntityType\n downloadConfirmationContainer?: RefObject<HTMLElement | null>\n disabled?: boolean\n}) {\n // get the appropriate version number for the entity\n const { latestVersionNumber } = useGetLatestVersionNumber(\n props.entityId,\n props.entityType,\n )\n // create queryBundleRequest with appropriate SQL based on entity type and version\n const defaultQueryBundleRequest = getDefaultQueryBundleRequestForEntity(\n props.entityId,\n latestVersionNumber,\n props.entityType,\n )\n\n // Get context and download functionality\n const { downloadCartPageUrl, isAuthenticated } = useSynapseContext()\n const { mutate: addFileToDownloadList } = useAddFileToDownloadList({\n onSuccess: data => {\n if (data.numberOfFilesAdded > 0) {\n displayFilesWereAddedToDownloadListSuccess(downloadCartPageUrl)\n } else {\n displayToast('0 Files added to your Download List', 'info')\n }\n },\n onError: error => {\n displayToast(error.reason, 'danger')\n },\n })\n\n // state to manage programmatic access modal visibility\n const [showProgrammaticAccess, setShowProgrammaticAccess] =\n useState<boolean>(false)\n\n // state to manage download confirmation visibility and loading\n const [showDownloadConfirmation, setShowDownloadConfirmation] =\n useState<boolean>(false)\n const [downloadConfirmationLoading, setDownloadConfirmationLoading] =\n useState<boolean>(false)\n\n const handleCloseProgrammaticAccess = () => {\n setShowProgrammaticAccess(false)\n }\n\n const isFolderOrProject = isContainerType(props.entityType)\n\n const {\n data: folderOrProjectStats,\n isLoading: isLoadingFolderOrProjectStats,\n } = useGetAddToDownloadListStats(\n {\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListStatsRequest',\n request: {\n parentId: props.entityId,\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListRequest',\n recursive: true,\n },\n },\n {\n enabled: isFolderOrProject,\n },\n )\n\n const folderOrProjectHasNoFiles =\n isFolderOrProject &&\n (isLoadingFolderOrProjectStats || folderOrProjectStats?.fileCount === 0)\n\n const { data: entityData } = useGetEntity(props.entityId)\n\n const { downloadFile } = useDirectDownloadHandler()\n\n const fileHandleId =\n entityData && isFileEntity(entityData)\n ? entityData.dataFileHandleId\n : undefined\n\n const onDownloadFile = fileHandleId\n ? () => {\n void downloadFile({\n fileHandleId,\n associatedObjectId: props.entityId,\n associatedObjectType: FileHandleAssociateType.FileEntity,\n })\n }\n : undefined\n\n const entityViewHasNoFiles =\n entityData && isEntityView(entityData) && !hasFilesInView(entityData)\n\n const datasetHasNoFiles =\n entityData &&\n isDataset(entityData) &&\n (!entityData.items || entityData.items.length === 0)\n\n const addToCartDisabled =\n folderOrProjectHasNoFiles || entityViewHasNoFiles || datasetHasNoFiles\n\n // state to manage export metadata modal visibility\n const [showExportMetadata, setShowExportMetadata] = useState<boolean>(false)\n\n const handleCloseExportMetadata = () => {\n setShowExportMetadata(false)\n }\n\n // Create download menu items\n const downloadActions = getDownloadActionsForEntityType(props.entityType)\n const downloadMenuItems = downloadActions.map(actionGroup =>\n actionGroup.map(action =>\n getMenuItemForAction(\n props.entityId,\n props.name,\n props.entityType,\n action,\n setShowProgrammaticAccess,\n setShowExportMetadata,\n addFileToDownloadList,\n setShowDownloadConfirmation,\n latestVersionNumber,\n addToCartDisabled,\n onDownloadFile,\n isAuthenticated,\n ),\n ),\n )\n\n // Return programmatic access modal content\n const { cliCode, rCode, pythonCode } = getProgrammaticAccessCode(\n props.entityType,\n props.entityId,\n latestVersionNumber,\n )\n\n const downloadConfirmation = showDownloadConfirmation ? (\n <EntityDownloadConfirmation\n entityId={props.entityId}\n handleClose={() => setShowDownloadConfirmation(false)}\n onIsLoadingChange={setDownloadConfirmationLoading}\n />\n ) : null\n\n return (\n <>\n <DropdownMenu\n items={downloadMenuItems}\n dropdownButtonText=\"Download\"\n buttonTooltip=\"Download options for this entity\"\n buttonProps={{\n variant: 'outlined',\n startIcon: <DownloadIcon />,\n disabled: props.disabled || downloadConfirmationLoading,\n }}\n />\n {downloadConfirmation &&\n (props.downloadConfirmationContainer?.current\n ? createPortal(\n downloadConfirmation,\n props.downloadConfirmationContainer.current,\n )\n : downloadConfirmation)}\n <ProgrammaticInstructionsModal\n show={showProgrammaticAccess}\n title={`Programmatic Access: ${props.name}`}\n onClose={handleCloseProgrammaticAccess}\n pythonCode={pythonCode}\n rCode={rCode}\n cliCode={cliCode}\n helpUrl=\"https://help.synapse.org/docs/Synapse-Docker-Registry.2011037752.html#SynapseDockerRegistry-UsingDockerImagesStoredintheSynapseDockerRegistry\"\n />\n {showExportMetadata && (\n <ModalDownload\n queryBundleRequest={defaultQueryBundleRequest}\n onClose={handleCloseExportMetadata}\n />\n )}\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAwCA,IAAa,IAAiC,iGAKjC,IAA4B;AAUzC,SAAS,EACP,GACA,GACA,GACwB;CACxB,IAAM,IACJ,MAAS,EAAW,WAAW,IAAU,GAAG,EAAS,GAAG,MAAY;AACtE,SAAQ,GAAR;EACE,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW,KACd,QAAO;GACL,SAAS,kBAAkB;GAC3B,OAAO,GAAG,EAA0B;;UAElC,EAAS;GACX,YAAY,GAAG,EAA+B;;WAE3C,EAAS;GACb;EACH,KAAK,EAAW,WACd,QAAO;GACL,SAAS;iCACgB,EAAS;GAClC,OAAO,KAAA;GACP,YAAY,KAAA;GACb;EACH,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW,UACd,QAAO;GACL,SAAS,iCAAiC,EAAG;GAC7C,OAAO,GAAG,EAA0B;wCACJ,EAAG;;GAEnC,YAAY,GAAG,EAA+B;wCACd,EAAG;;GAEpC;EACH,QACE,OAAU,MAAM,yBAAyB,IAAO;;;AAItD,IAAK,IAAL,yBAAA,GAAA;QACE,EAAA,EAAA,eAAA,KAAA,gBACA,EAAA,EAAA,YAAA,KAAA,aACA,EAAA,EAAA,qBAAA,KAAA,sBACA,EAAA,EAAA,2BAAA,KAAA,4BACA,EAAA,EAAA,cAAA,KAAA;EALG,KAAA,EAAA,CAMJ;AAGD,SAAS,EACP,GACA,GACA,GACA,GACA,GACA,GACA,GAIA,GACA,GACA,GACA,GACA,GACkB;AAClB,SAAQ,GAAR;EACE,KAAK,EAAe,aAClB,QAAO;GACL,MAAM;GACN,eAAe;AACb,IAAI,KAAgB,GAAgB;;GAEtC,aAAa,IACT,gCACA;GACJ,UAAU,CAAC;GACZ;EACH,KAAK,EAAe,UAClB,QAAO;GACL,MAAM;GACN,UAAU;GACV,aAAa,EAAoB,GAAY,CAAC,CAAC,EAAkB;GACjE,eAAe;AACb,IACE,MAAe,EAAW,QAC1B,MAAe,EAAW,YAE1B,EAAsB;KACpB;KACA,qBAAqB;KACtB,CAAC,GAEF,EAA4B,GAAK;;GAGtC;EACH,KAAK,EAAe,mBAClB,QAAO;GACL,MAAM;GACN,eAAe;AACb,MAA0B,GAAK;;GAEjC,aAAa;GACd;EACH,KAAK,EAAe,yBAClB,QAAO;GACL,MAAM;GACN,eAAe;AACb,MAA0B,GAAK;;GAEjC,aAAa;GACd;EACH,KAAK,EAAe,YAClB,QAAO;GACL,MAAM;GACN,eAAe;AACb,MAAsB,GAAK;;GAE7B,aAAa;GACd;;;AAOP,IAAM,KACJ,GACA,MAEK,IAIE,QADoB,EAAyB,EACrC,CAAmB,4BAHzB;AAOX,SAAgB,EACd,GACoB;AACpB,SAAQ,GAAR;EACE,KAAK,EAAW;EAChB,KAAK,EAAW,UACd,QAAO,CACL,CAAC,EAAe,aAAa,EAC7B,CAAC,EAAe,WAAW,EAAe,mBAAmB,CAC9D;EACH,KAAK,EAAW;EAChB,KAAK,EAAW,OACd,QAAO,CAAC,CAAC,EAAe,WAAW,EAAe,mBAAmB,CAAC;EACxE,KAAK,EAAW,WACd,QAAO,CAAC,CAAC,EAAe,yBAAyB,CAAC;EACpD,KAAK,EAAW;EAChB,KAAK,EAAW,QACd,QAAO,CACL;GACE,EAAe;GACf,EAAe;GACf,EAAe;GAChB,CACF;EACH,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW,aACd,QAAO,CAAC,CAAC,EAAe,aAAa,EAAe,mBAAmB,CAAC;EAC1E,KAAK,EAAW,KACd,QAAO,CAAC,CAAC,EAAe,mBAAmB,CAAC;EAC9C,KAAK,EAAW,YACd,QAAO,EAAE;EACX,QAEE,OAAU,MAAM,yBAAyB,IAAO;;;AAOtD,SAAS,EAA0B,GAAkB,GAAwB;CAE3E,IAAM,EAAE,MAAM,GAAY,WAAW,MACnC,EAAa,EAAS,EAGlB,IAAiB,MAAe,EAAW,SAC3C,EAAE,MAAM,GAAc,WAAW,MAAoB,EACzD,GACA,GACA,GACA,EACE,SAAS,GACV,CACF,EAEG;AAqBJ,QAnBA,AAWE,IAXE,IAEE,GAAc,WAAW,EAAa,QAAQ,SAAS,IAEnC,EAAa,QAAQ,GAAG,gBAGxB,KAAA,IAKtB,KAAc,EAAoB,EAAW,GACzC,EAAW,gBACX,KAAA,GAKD;EAAE;EAAqB,WAFZ,KAAqB;EAEE;;AAI3C,SAAS,EACP,GACA,GACA,GACoB;CACpB,IAAI;AAcJ,QAZA,AASE,IATE,MAAe,EAAW,WAItB,IACF,iBAAiB,EAAS,GAAG,MAC7B,iBAAiB,KAMhB;EACL,cAAc;EACd,UAAU,GAAG;EACb,OAAO,EACA,QACN;EACD,UAAU;EACX;;AAGH,SAAgB,EAAqB,GAMlC;CAED,IAAM,EAAE,2BAAwB,EAC9B,EAAM,UACN,EAAM,WACP,EAEK,IAA4B,EAChC,EAAM,UACN,GACA,EAAM,WACP,EAGK,EAAE,wBAAqB,uBAAoB,GAAmB,EAC9D,EAAE,QAAQ,MAA0B,EAAyB;EACjE,YAAW,MAAQ;AACjB,GAAI,EAAK,qBAAqB,IAC5B,EAA2C,EAAoB,GAE/D,EAAa,uCAAuC,OAAO;;EAG/D,UAAS,MAAS;AAChB,KAAa,EAAM,QAAQ,SAAS;;EAEvC,CAAC,EAGI,CAAC,GAAwB,KAC7B,EAAkB,GAAM,EAGpB,CAAC,GAA0B,KAC/B,EAAkB,GAAM,EACpB,CAAC,GAA6B,KAClC,EAAkB,GAAM,EAEpB,UAAsC;AAC1C,IAA0B,GAAM;IAG5B,IAAoB,EAAgB,EAAM,WAAW,EAErD,EACJ,MAAM,GACN,WAAW,MACT,EACF;EACE,cACE;EACF,SAAS;GACP,UAAU,EAAM;GAChB,cACE;GACF,WAAW;GACZ;EACF,EACD,EACE,SAAS,GACV,CACF,EAEK,IACJ,MACC,KAAiC,GAAsB,cAAc,IAElE,EAAE,MAAM,MAAe,EAAa,EAAM,SAAS,EAEnD,EAAE,oBAAiB,GAA0B,EAE7C,IACJ,KAAc,EAAa,EAAW,GAClC,EAAW,mBACX,KAAA,GAEA,IAAiB,UACb;AACC,IAAa;GAChB;GACA,oBAAoB,EAAM;GAC1B,sBAAsB,EAAwB;GAC/C,CAAC;KAEJ,KAAA,GAEE,IACJ,KAAc,EAAa,EAAW,IAAI,CAAC,EAAe,EAAW,EAEjE,IACJ,KACA,EAAU,EAAW,KACpB,CAAC,EAAW,SAAS,EAAW,MAAM,WAAW,IAE9C,IACJ,KAA6B,KAAwB,GAGjD,CAAC,GAAoB,KAAyB,EAAkB,GAAM,EAEtE,WAAkC;AACtC,IAAsB,GAAM;IAKxB,KADkB,EAAgC,EAAM,WACpC,CAAgB,KAAI,MAC5C,EAAY,KAAI,MACd,EACE,EAAM,UACN,EAAM,MACN,EAAM,YACN,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,EACD,CACF,CACF,EAGK,EAAE,aAAS,WAAO,mBAAe,EACrC,EAAM,YACN,EAAM,UACN,EACD,EAEK,IAAuB,IAC3B,kBAAC,GAAD;EACE,UAAU,EAAM;EAChB,mBAAmB,EAA4B,GAAM;EACrD,mBAAmB;EACnB,CAAA,GACA;AAEJ,QACE,mBAAA,GAAA,EAAA,UAAA;EACE,kBAAC,GAAD;GACE,OAAO;GACP,oBAAmB;GACnB,eAAc;GACd,aAAa;IACX,SAAS;IACT,WAAW,kBAAC,GAAD,EAAgB,CAAA;IAC3B,UAAU,EAAM,YAAY;IAC7B;GACD,CAAA;EACD,MACE,EAAM,+BAA+B,UAClC,EACE,GACA,EAAM,8BAA8B,QACrC,GACD;EACN,kBAAC,GAAD;GACE,MAAM;GACN,OAAO,wBAAwB,EAAM;GACrC,SAAS;GACG;GACL;GACE;GACT,SAAQ;GACR,CAAA;EACD,KACC,kBAAC,GAAD;GACE,oBAAoB;GACpB,SAAS;GACT,CAAA;EAEH,EAAA,CAAA"}
|
|
1
|
+
{"version":3,"file":"EntityDownloadButton.js","names":[],"sources":["../../../src/components/EntityDownloadButton/EntityDownloadButton.tsx"],"sourcesContent":["import { useGetEntity, useGetVersions } from '@/synapse-queries'\nimport {\n useAddFileToDownloadList,\n useGetAddToDownloadListStats,\n} from '@/synapse-queries/index'\nimport { useSynapseContext } from '@/utils'\nimport {\n entityTypeToFriendlyName,\n hasFilesInView,\n isContainerType,\n isDataset,\n isEntityView,\n isVersionableEntity,\n} from '@/utils/functions/EntityTypeUtils'\nimport { useDirectDownloadHandler } from '@/utils/hooks/useDirectDownloadHandler'\nimport { isFileEntity } from '@/utils/types/IsType'\nimport { DownloadOutlined as DownloadIcon } from '@mui/icons-material'\nimport { EntityType } from '@sage-bionetworks/synapse-client'\nimport {\n FileHandleAssociateType,\n QueryBundleRequest,\n} from '@sage-bionetworks/synapse-types'\nimport { RefObject, useState } from 'react'\nimport { createPortal } from 'react-dom'\nimport { displayFilesWereAddedToDownloadListSuccess } from '../download_list/DownloadConfirmationUtils'\nimport { EntityDownloadConfirmation } from '../EntityDownloadConfirmation'\nimport { DropdownMenu, DropdownMenuItem } from '../menu/DropdownMenu'\nimport { ModalDownload } from '../ModalDownload/ModalDownload'\nimport { ProgrammaticInstructionsModal } from '../ProgrammaticInstructionsModal/ProgrammaticInstructionsModal'\nimport { displayToast } from '../ToastMessage/index'\n\n// WIP\n// Per Nick Grosenbacher: For this to be reusable, I think we would also need to accept versionNumber as a prop. Where we would have the following behavior:\n// - If the version number is present, use it\n// - If the version number is null, do not use it,\n// - If the version number is undefined, then we would try to do the 'smart' thing-- get the latest version for datasets, otherwise don't use it.\n\n// Have to keep these consts outside of getProgrammaticAccessCode because\n// they are being called in ProgrammaticTableDownload.tsx\n// Python client import and login instructions\nexport const PYTHON_CLIENT_IMPORT_AND_LOGIN = `import synapseclient\nsyn = synapseclient.Synapse()\nsyn.login(authToken=\"YOUR_TOKEN_HERE\")`\n\n// R client import and login instructions\nexport const R_CLIENT_IMPORT_AND_LOGIN = `library(synapser)\nsynLogin(authToken=\"YOUR_TOKEN_HERE\")`\n\ntype ProgrammaticAccessCode = {\n cliCode: string | undefined\n rCode: string | undefined\n pythonCode: string | undefined\n}\n\n// Generate programmatic access code snippet content based on entity type\nexport function getProgrammaticAccessCode(\n type: EntityType,\n entityId: string,\n version: number | undefined,\n): ProgrammaticAccessCode {\n const id =\n type === EntityType.dataset && version ? `${entityId}.${version}` : entityId\n switch (type) {\n case EntityType.file:\n case EntityType.folder:\n case EntityType.project:\n case EntityType.link:\n return {\n cliCode: `synapse get -r ${entityId}`,\n rCode: `${R_CLIENT_IMPORT_AND_LOGIN} \\n\n# Download file\nsynGet('${entityId}')`,\n pythonCode: `${PYTHON_CLIENT_IMPORT_AND_LOGIN} \\n\n# Download file\nsyn.get('${entityId}')`,\n }\n case EntityType.dockerrepo:\n return {\n cliCode: `docker login -u <synapse username> -p <synapse password> docker.synapse.org \\n\ndocker pull docker.synapse.org/${entityId}/myrepo`,\n rCode: undefined,\n pythonCode: undefined,\n }\n case EntityType.dataset:\n case EntityType.entityview:\n case EntityType.datasetcollection:\n case EntityType.table:\n case EntityType.materializedview:\n case EntityType.submissionview:\n case EntityType.virtualtable:\n case EntityType.recordset:\n return {\n cliCode: `synapse get -q \"SELECT * FROM ${id}\"`,\n rCode: `${R_CLIENT_IMPORT_AND_LOGIN} \\n\nquery <- synTableQuery(\"SELECT * FROM ${id}\")\nread.table(query$filepath, sep=\",\")`,\n pythonCode: `${PYTHON_CLIENT_IMPORT_AND_LOGIN} \\n\nquery = syn.tableQuery(\"SELECT * FROM ${id}\")\nquery.asDataFrame()`,\n }\n case EntityType.searchindex:\n return {\n cliCode: undefined,\n rCode: undefined,\n pythonCode: undefined,\n }\n default:\n throw new Error(`Unhandled EntityType: ${type}`)\n }\n}\n\nenum DownloadAction {\n downloadFile,\n addToCart,\n programmaticAccess,\n programmaticAccessDocker,\n exportTable,\n}\n\n// Function that creates menu items for download actions\nfunction getMenuItemForAction(\n entityId: string,\n entityName: string,\n entityType: EntityType,\n downloadAction: DownloadAction,\n setShowProgrammaticAccess: (show: boolean) => void,\n setShowExportMetadata: (show: boolean) => void,\n addFileToDownloadList: (params: {\n entityId: string\n entityVersionNumber: number | undefined\n }) => void,\n setShowDownloadConfirmation: (show: boolean) => void,\n versionNumber?: number,\n addToCartDisabled?: boolean,\n onDownloadFile?: () => void,\n isAuthenticated?: boolean,\n): DropdownMenuItem {\n switch (downloadAction) {\n case DownloadAction.downloadFile:\n return {\n text: 'Download File',\n onClick: () => {\n if (onDownloadFile) onDownloadFile()\n },\n tooltipText: isAuthenticated\n ? 'Download this file directly'\n : 'Sign in to download this file',\n disabled: !isAuthenticated,\n }\n case DownloadAction.addToCart:\n return {\n text: 'Add to Download List',\n disabled: addToCartDisabled,\n tooltipText: getAddToCartTooltip(entityType, !!addToCartDisabled),\n onClick: () => {\n if (\n entityType === EntityType.file ||\n entityType === EntityType.recordset\n ) {\n addFileToDownloadList({\n entityId,\n entityVersionNumber: versionNumber,\n })\n } else {\n setShowDownloadConfirmation(true)\n }\n },\n }\n case DownloadAction.programmaticAccess:\n return {\n text: 'Programmatic Access',\n onClick: () => {\n setShowProgrammaticAccess(true)\n },\n tooltipText: 'View programmatic access options',\n }\n case DownloadAction.programmaticAccessDocker:\n return {\n text: 'Programmatic Access (Docker)',\n onClick: () => {\n setShowProgrammaticAccess(true)\n },\n tooltipText: 'View programmatic options to pull Docker image',\n }\n case DownloadAction.exportTable:\n return {\n text: 'Export Table',\n onClick: () => {\n setShowExportMetadata(true)\n },\n tooltipText: 'Export table data',\n }\n }\n}\n\n/**\n * Determines the tooltip message based on the entity type and its \"add to cart\" status.\n */\nconst getAddToCartTooltip = (\n entityType: EntityType,\n isDisabled: boolean,\n): string => {\n if (!isDisabled) {\n return 'Add file(s) to your download list'\n }\n const entityFriendlyName = entityTypeToFriendlyName(entityType)\n return `This ${entityFriendlyName} has no accessible files`\n}\n\n// Function that returns DropdownMenuItem\nexport function getDownloadActionsForEntityType(\n type: EntityType,\n): DownloadAction[][] {\n switch (type) {\n case EntityType.file:\n case EntityType.recordset:\n return [\n [DownloadAction.downloadFile],\n [DownloadAction.addToCart, DownloadAction.programmaticAccess],\n ]\n case EntityType.project:\n case EntityType.folder:\n return [[DownloadAction.addToCart, DownloadAction.programmaticAccess]]\n case EntityType.dockerrepo:\n return [[DownloadAction.programmaticAccessDocker]]\n case EntityType.entityview:\n case EntityType.dataset:\n return [\n [\n DownloadAction.exportTable,\n DownloadAction.programmaticAccess,\n DownloadAction.addToCart,\n ],\n ]\n case EntityType.datasetcollection:\n case EntityType.table:\n case EntityType.materializedview:\n case EntityType.submissionview:\n case EntityType.virtualtable:\n return [[DownloadAction.exportTable, DownloadAction.programmaticAccess]]\n case EntityType.link:\n return [[DownloadAction.programmaticAccess]]\n case EntityType.searchindex:\n return []\n default:\n // this will fail if a new EntityType is added and not handled\n throw new Error(`Unhandled EntityType: ${type}`)\n }\n}\n\n// get the appropriate version number for download based on entity type\n// for datasets: returns the most recent released version if any exist, undefined otherwise\n// for other entities: returns the current version number\nfunction useGetLatestVersionNumber(entityId: string, entityType: EntityType) {\n // get entity data\n const { data: entityData, isLoading: entityDataLoading } =\n useGetEntity(entityId) // No version = latest\n\n // for datasets, check if any versions exist and use the most recent one\n const mustGetVersion = entityType === EntityType.dataset\n const { data: versionsData, isLoading: versionsLoading } = useGetVersions(\n entityId,\n 0,\n 1,\n {\n enabled: mustGetVersion,\n },\n )\n\n let latestVersionNumber: number | undefined\n\n if (mustGetVersion) {\n // for datasets, check if any versions exist\n if (versionsData?.results && versionsData.results.length > 0) {\n // Use the most recent released version (first in the list, since versions are returned in descending order)\n latestVersionNumber = versionsData.results[0].versionNumber\n } else {\n // no versions exist, use undefined (will use current/draft version)\n latestVersionNumber = undefined\n }\n } else {\n // for non-datasets, use the entity's version number\n latestVersionNumber =\n entityData && isVersionableEntity(entityData)\n ? entityData.versionNumber\n : undefined\n }\n\n const isLoading = entityDataLoading || versionsLoading\n\n return { latestVersionNumber, isLoading }\n}\n\n// create default queryBundleRequest with appropriate SQL\nfunction getDefaultQueryBundleRequestForEntity(\n entityId: string,\n versionNumber: number | undefined,\n entityType: EntityType,\n): QueryBundleRequest {\n let sql: string\n\n if (entityType === EntityType.dataset) {\n // for datasets:\n // - if a version number exists (released version), use it: syn123.5\n // - if no version number (no released versions), use current/draft: syn123\n sql = versionNumber\n ? `SELECT * FROM ${entityId}.${versionNumber}`\n : `SELECT * FROM ${entityId}`\n } else {\n // For non-datasets, always use entity ID without version\n sql = `SELECT * FROM ${entityId}`\n }\n\n return {\n concreteType: 'org.sagebionetworks.repo.model.table.QueryBundleRequest',\n entityId: `${entityId}`,\n query: {\n sql: sql,\n },\n partMask: 0,\n }\n}\n\nexport function EntityDownloadButton(props: {\n entityId: string\n name: string\n entityType: EntityType\n downloadConfirmationContainer?: RefObject<HTMLElement | null>\n disabled?: boolean\n}) {\n // get the appropriate version number for the entity\n const { latestVersionNumber } = useGetLatestVersionNumber(\n props.entityId,\n props.entityType,\n )\n // create queryBundleRequest with appropriate SQL based on entity type and version\n const defaultQueryBundleRequest = getDefaultQueryBundleRequestForEntity(\n props.entityId,\n latestVersionNumber,\n props.entityType,\n )\n\n // Get context and download functionality\n const { downloadCartPageUrl, isAuthenticated } = useSynapseContext()\n const { mutate: addFileToDownloadList } = useAddFileToDownloadList({\n onSuccess: data => {\n if (data.numberOfFilesAdded > 0) {\n displayFilesWereAddedToDownloadListSuccess(downloadCartPageUrl)\n } else {\n displayToast('0 Files added to your Download List', 'info')\n }\n },\n onError: error => {\n displayToast(error.reason, 'danger')\n },\n })\n\n // state to manage programmatic access modal visibility\n const [showProgrammaticAccess, setShowProgrammaticAccess] =\n useState<boolean>(false)\n\n // state to manage download confirmation visibility and loading\n const [showDownloadConfirmation, setShowDownloadConfirmation] =\n useState<boolean>(false)\n const [downloadConfirmationLoading, setDownloadConfirmationLoading] =\n useState<boolean>(false)\n\n const handleCloseProgrammaticAccess = () => {\n setShowProgrammaticAccess(false)\n }\n\n const isFolderOrProject = isContainerType(props.entityType)\n\n const {\n data: folderOrProjectStats,\n isLoading: isLoadingFolderOrProjectStats,\n } = useGetAddToDownloadListStats(\n {\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListStatsRequest',\n request: {\n parentId: props.entityId,\n concreteType:\n 'org.sagebionetworks.repo.model.download.AddToDownloadListRequest',\n recursive: true,\n },\n },\n {\n enabled: isFolderOrProject,\n },\n )\n\n const folderOrProjectHasNoFiles =\n isFolderOrProject &&\n (isLoadingFolderOrProjectStats || folderOrProjectStats?.fileCount === 0)\n\n const { data: entityData } = useGetEntity(props.entityId)\n\n const { downloadFile } = useDirectDownloadHandler()\n\n const fileHandleId =\n entityData && isFileEntity(entityData)\n ? entityData.dataFileHandleId\n : undefined\n\n const onDownloadFile = fileHandleId\n ? () => {\n void downloadFile({\n fileHandleId,\n associatedObjectId: props.entityId,\n associatedObjectType: FileHandleAssociateType.FileEntity,\n })\n }\n : undefined\n\n const entityViewHasNoFiles =\n entityData && isEntityView(entityData) && !hasFilesInView(entityData)\n\n const datasetHasNoFiles =\n entityData &&\n isDataset(entityData) &&\n (!entityData.items || entityData.items.length === 0)\n\n const addToCartDisabled =\n folderOrProjectHasNoFiles || entityViewHasNoFiles || datasetHasNoFiles\n\n // state to manage export metadata modal visibility\n const [showExportMetadata, setShowExportMetadata] = useState<boolean>(false)\n\n const handleCloseExportMetadata = () => {\n setShowExportMetadata(false)\n }\n\n // Create download menu items\n const downloadActions = getDownloadActionsForEntityType(props.entityType)\n const downloadMenuItems = downloadActions.map(actionGroup =>\n actionGroup.map(action =>\n getMenuItemForAction(\n props.entityId,\n props.name,\n props.entityType,\n action,\n setShowProgrammaticAccess,\n setShowExportMetadata,\n addFileToDownloadList,\n setShowDownloadConfirmation,\n latestVersionNumber,\n addToCartDisabled,\n onDownloadFile,\n isAuthenticated,\n ),\n ),\n )\n\n // Return programmatic access modal content\n const { cliCode, rCode, pythonCode } = getProgrammaticAccessCode(\n props.entityType,\n props.entityId,\n latestVersionNumber,\n )\n\n const downloadConfirmation = showDownloadConfirmation ? (\n <EntityDownloadConfirmation\n entityId={props.entityId}\n handleClose={() => setShowDownloadConfirmation(false)}\n onIsLoadingChange={setDownloadConfirmationLoading}\n />\n ) : null\n\n return (\n <>\n <DropdownMenu\n items={downloadMenuItems}\n dropdownButtonText=\"Download\"\n buttonTooltip=\"Download options for this entity\"\n buttonProps={{\n variant: 'outlined',\n startIcon: <DownloadIcon />,\n disabled: props.disabled || downloadConfirmationLoading,\n }}\n />\n {downloadConfirmation &&\n (props.downloadConfirmationContainer?.current\n ? createPortal(\n downloadConfirmation,\n props.downloadConfirmationContainer.current,\n )\n : downloadConfirmation)}\n <ProgrammaticInstructionsModal\n show={showProgrammaticAccess}\n title={`Programmatic Access: ${props.name}`}\n onClose={handleCloseProgrammaticAccess}\n pythonCode={pythonCode}\n rCode={rCode}\n cliCode={cliCode}\n helpUrl=\"https://help.synapse.org/docs/Synapse-Docker-Registry.2011037752.html#SynapseDockerRegistry-UsingDockerImagesStoredintheSynapseDockerRegistry\"\n />\n {showExportMetadata && (\n <ModalDownload\n queryBundleRequest={defaultQueryBundleRequest}\n onClose={handleCloseExportMetadata}\n />\n )}\n </>\n )\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAwCA,IAAa,IAAiC,iGAKjC,IAA4B;AAUzC,SAAgB,EACd,GACA,GACA,GACwB;CACxB,IAAM,IACJ,MAAS,EAAW,WAAW,IAAU,GAAG,EAAS,GAAG,MAAY;AACtE,SAAQ,GAAR;EACE,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW,KACd,QAAO;GACL,SAAS,kBAAkB;GAC3B,OAAO,GAAG,EAA0B;;UAElC,EAAS;GACX,YAAY,GAAG,EAA+B;;WAE3C,EAAS;GACb;EACH,KAAK,EAAW,WACd,QAAO;GACL,SAAS;iCACgB,EAAS;GAClC,OAAO,KAAA;GACP,YAAY,KAAA;GACb;EACH,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW,UACd,QAAO;GACL,SAAS,iCAAiC,EAAG;GAC7C,OAAO,GAAG,EAA0B;wCACJ,EAAG;;GAEnC,YAAY,GAAG,EAA+B;wCACd,EAAG;;GAEpC;EACH,KAAK,EAAW,YACd,QAAO;GACL,SAAS,KAAA;GACT,OAAO,KAAA;GACP,YAAY,KAAA;GACb;EACH,QACE,OAAU,MAAM,yBAAyB,IAAO;;;AAItD,IAAK,IAAL,yBAAA,GAAA;QACE,EAAA,EAAA,eAAA,KAAA,gBACA,EAAA,EAAA,YAAA,KAAA,aACA,EAAA,EAAA,qBAAA,KAAA,sBACA,EAAA,EAAA,2BAAA,KAAA,4BACA,EAAA,EAAA,cAAA,KAAA;EALG,KAAA,EAAA,CAMJ;AAGD,SAAS,EACP,GACA,GACA,GACA,GACA,GACA,GACA,GAIA,GACA,GACA,GACA,GACA,GACkB;AAClB,SAAQ,GAAR;EACE,KAAK,EAAe,aAClB,QAAO;GACL,MAAM;GACN,eAAe;AACb,IAAI,KAAgB,GAAgB;;GAEtC,aAAa,IACT,gCACA;GACJ,UAAU,CAAC;GACZ;EACH,KAAK,EAAe,UAClB,QAAO;GACL,MAAM;GACN,UAAU;GACV,aAAa,EAAoB,GAAY,CAAC,CAAC,EAAkB;GACjE,eAAe;AACb,IACE,MAAe,EAAW,QAC1B,MAAe,EAAW,YAE1B,EAAsB;KACpB;KACA,qBAAqB;KACtB,CAAC,GAEF,EAA4B,GAAK;;GAGtC;EACH,KAAK,EAAe,mBAClB,QAAO;GACL,MAAM;GACN,eAAe;AACb,MAA0B,GAAK;;GAEjC,aAAa;GACd;EACH,KAAK,EAAe,yBAClB,QAAO;GACL,MAAM;GACN,eAAe;AACb,MAA0B,GAAK;;GAEjC,aAAa;GACd;EACH,KAAK,EAAe,YAClB,QAAO;GACL,MAAM;GACN,eAAe;AACb,MAAsB,GAAK;;GAE7B,aAAa;GACd;;;AAOP,IAAM,KACJ,GACA,MAEK,IAIE,QADoB,EAAyB,EACrC,CAAmB,4BAHzB;AAOX,SAAgB,EACd,GACoB;AACpB,SAAQ,GAAR;EACE,KAAK,EAAW;EAChB,KAAK,EAAW,UACd,QAAO,CACL,CAAC,EAAe,aAAa,EAC7B,CAAC,EAAe,WAAW,EAAe,mBAAmB,CAC9D;EACH,KAAK,EAAW;EAChB,KAAK,EAAW,OACd,QAAO,CAAC,CAAC,EAAe,WAAW,EAAe,mBAAmB,CAAC;EACxE,KAAK,EAAW,WACd,QAAO,CAAC,CAAC,EAAe,yBAAyB,CAAC;EACpD,KAAK,EAAW;EAChB,KAAK,EAAW,QACd,QAAO,CACL;GACE,EAAe;GACf,EAAe;GACf,EAAe;GAChB,CACF;EACH,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW;EAChB,KAAK,EAAW,aACd,QAAO,CAAC,CAAC,EAAe,aAAa,EAAe,mBAAmB,CAAC;EAC1E,KAAK,EAAW,KACd,QAAO,CAAC,CAAC,EAAe,mBAAmB,CAAC;EAC9C,KAAK,EAAW,YACd,QAAO,EAAE;EACX,QAEE,OAAU,MAAM,yBAAyB,IAAO;;;AAOtD,SAAS,EAA0B,GAAkB,GAAwB;CAE3E,IAAM,EAAE,MAAM,GAAY,WAAW,MACnC,EAAa,EAAS,EAGlB,IAAiB,MAAe,EAAW,SAC3C,EAAE,MAAM,GAAc,WAAW,MAAoB,EACzD,GACA,GACA,GACA,EACE,SAAS,GACV,CACF,EAEG;AAqBJ,QAnBA,AAWE,IAXE,IAEE,GAAc,WAAW,EAAa,QAAQ,SAAS,IAEnC,EAAa,QAAQ,GAAG,gBAGxB,KAAA,IAKtB,KAAc,EAAoB,EAAW,GACzC,EAAW,gBACX,KAAA,GAKD;EAAE;EAAqB,WAFZ,KAAqB;EAEE;;AAI3C,SAAS,EACP,GACA,GACA,GACoB;CACpB,IAAI;AAcJ,QAZA,AASE,IATE,MAAe,EAAW,WAItB,IACF,iBAAiB,EAAS,GAAG,MAC7B,iBAAiB,KAMhB;EACL,cAAc;EACd,UAAU,GAAG;EACb,OAAO,EACA,QACN;EACD,UAAU;EACX;;AAGH,SAAgB,EAAqB,GAMlC;CAED,IAAM,EAAE,2BAAwB,EAC9B,EAAM,UACN,EAAM,WACP,EAEK,IAA4B,EAChC,EAAM,UACN,GACA,EAAM,WACP,EAGK,EAAE,wBAAqB,uBAAoB,GAAmB,EAC9D,EAAE,QAAQ,MAA0B,EAAyB;EACjE,YAAW,MAAQ;AACjB,GAAI,EAAK,qBAAqB,IAC5B,EAA2C,EAAoB,GAE/D,EAAa,uCAAuC,OAAO;;EAG/D,UAAS,MAAS;AAChB,KAAa,EAAM,QAAQ,SAAS;;EAEvC,CAAC,EAGI,CAAC,GAAwB,KAC7B,EAAkB,GAAM,EAGpB,CAAC,GAA0B,KAC/B,EAAkB,GAAM,EACpB,CAAC,GAA6B,KAClC,EAAkB,GAAM,EAEpB,UAAsC;AAC1C,IAA0B,GAAM;IAG5B,IAAoB,EAAgB,EAAM,WAAW,EAErD,EACJ,MAAM,GACN,WAAW,MACT,EACF;EACE,cACE;EACF,SAAS;GACP,UAAU,EAAM;GAChB,cACE;GACF,WAAW;GACZ;EACF,EACD,EACE,SAAS,GACV,CACF,EAEK,IACJ,MACC,KAAiC,GAAsB,cAAc,IAElE,EAAE,MAAM,MAAe,EAAa,EAAM,SAAS,EAEnD,EAAE,oBAAiB,GAA0B,EAE7C,IACJ,KAAc,EAAa,EAAW,GAClC,EAAW,mBACX,KAAA,GAEA,IAAiB,UACb;AACC,IAAa;GAChB;GACA,oBAAoB,EAAM;GAC1B,sBAAsB,EAAwB;GAC/C,CAAC;KAEJ,KAAA,GAEE,IACJ,KAAc,EAAa,EAAW,IAAI,CAAC,EAAe,EAAW,EAEjE,IACJ,KACA,EAAU,EAAW,KACpB,CAAC,EAAW,SAAS,EAAW,MAAM,WAAW,IAE9C,IACJ,KAA6B,KAAwB,GAGjD,CAAC,GAAoB,KAAyB,EAAkB,GAAM,EAEtE,WAAkC;AACtC,IAAsB,GAAM;IAKxB,KADkB,EAAgC,EAAM,WACpC,CAAgB,KAAI,MAC5C,EAAY,KAAI,MACd,EACE,EAAM,UACN,EAAM,MACN,EAAM,YACN,GACA,GACA,GACA,GACA,GACA,GACA,GACA,GACA,EACD,CACF,CACF,EAGK,EAAE,aAAS,WAAO,mBAAe,EACrC,EAAM,YACN,EAAM,UACN,EACD,EAEK,IAAuB,IAC3B,kBAAC,GAAD;EACE,UAAU,EAAM;EAChB,mBAAmB,EAA4B,GAAM;EACrD,mBAAmB;EACnB,CAAA,GACA;AAEJ,QACE,mBAAA,GAAA,EAAA,UAAA;EACE,kBAAC,GAAD;GACE,OAAO;GACP,oBAAmB;GACnB,eAAc;GACd,aAAa;IACX,SAAS;IACT,WAAW,kBAAC,GAAD,EAAgB,CAAA;IAC3B,UAAU,EAAM,YAAY;IAC7B;GACD,CAAA;EACD,MACE,EAAM,+BAA+B,UAClC,EACE,GACA,EAAM,8BAA8B,QACrC,GACD;EACN,kBAAC,GAAD;GACE,MAAM;GACN,OAAO,wBAAwB,EAAM;GACrC,SAAS;GACG;GACL;GACE;GACT,SAAQ;GACR,CAAA;EACD,KACC,kBAAC,GAAD;GACE,oBAAoB;GACpB,SAAS;GACT,CAAA;EAEH,EAAA,CAAA"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FullTextSearch.d.ts","sourceRoot":"","sources":["../../../src/components/FullTextSearch/FullTextSearch.tsx"],"names":[],"mappings":"AACA,OAAO,KAMN,MAAM,OAAO,CAAA;AASd,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAMpD,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB,CAAA;AAED,wBAAgB,cAAc,CAAC,EAC7B,SAAS,GACV,EAAE,mBAAmB,GAAG,KAAK,CAAC,SAAS,
|
|
1
|
+
{"version":3,"file":"FullTextSearch.d.ts","sourceRoot":"","sources":["../../../src/components/FullTextSearch/FullTextSearch.tsx"],"names":[],"mappings":"AACA,OAAO,KAMN,MAAM,OAAO,CAAA;AASd,OAAO,EAAE,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAMpD,MAAM,MAAM,mBAAmB,GAAG;IAChC,SAAS,CAAC,EAAE,SAAS,CAAA;CACtB,CAAA;AAED,wBAAgB,cAAc,CAAC,EAC7B,SAAS,GACV,EAAE,mBAAmB,GAAG,KAAK,CAAC,SAAS,CA6KvC;AAED,eAAe,cAAc,CAAA"}
|