synapse-react-client 4.0.11 → 4.0.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/SWC.index.d.ts +1 -1
- package/dist/SWC.index.js +1 -1
- package/dist/components/AdaptiveTwoColumnLayout/AdaptiveTwoColumnLayout.d.ts +44 -0
- package/dist/components/AdaptiveTwoColumnLayout/AdaptiveTwoColumnLayout.d.ts.map +1 -0
- package/dist/components/AdaptiveTwoColumnLayout/AdaptiveTwoColumnLayout.js +46 -0
- package/dist/components/AdaptiveTwoColumnLayout/AdaptiveTwoColumnLayout.js.map +1 -0
- package/dist/components/DownloadCart/DownloadCartPage.d.ts.map +1 -1
- package/dist/components/DownloadCart/DownloadCartPage.js +183 -185
- package/dist/components/DownloadCart/DownloadCartPage.js.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.d.ts.map +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js +1 -1
- package/dist/components/DownloadCart/DownloadIneligibleForPackagingFilesFromListButton.js.map +1 -1
- package/dist/components/EntityAclEditor/EntityAclEditor.js +8 -8
- package/dist/components/EntityAclEditor/EntityAclEditor.js.map +1 -1
- package/dist/components/EntityAclEditor/InheritanceMessage.d.ts.map +1 -1
- package/dist/components/EntityAclEditor/InheritanceMessage.js +1 -2
- package/dist/components/EntityAclEditor/InheritanceMessage.js.map +1 -1
- package/dist/components/FullTextSearch/FullTextSearch.d.ts.map +1 -1
- package/dist/components/FullTextSearch/FullTextSearch.js +86 -47
- package/dist/components/FullTextSearch/FullTextSearch.js.map +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.d.ts.map +1 -1
- package/dist/components/GenericCard/TableRowGenericCard.js +157 -157
- package/dist/components/GenericCard/TableRowGenericCard.js.map +1 -1
- package/dist/components/HeaderCard.d.ts.map +1 -1
- package/dist/components/HeaderCard.js +131 -130
- package/dist/components/HeaderCard.js.map +1 -1
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.d.ts +4 -1
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.d.ts.map +1 -1
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.js +3 -2
- package/dist/components/MailchimpSubscribeSection/MailchimpSubscribeSection.js.map +1 -1
- package/dist/components/QueryContext/QueryContext.d.ts +6 -0
- package/dist/components/QueryContext/QueryContext.d.ts.map +1 -1
- package/dist/components/QueryContext/QueryContext.js.map +1 -1
- package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.d.ts.map +1 -1
- package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js +12 -11
- package/dist/components/QueryVisualizationWrapper/QueryVisualizationWrapper.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.d.ts +5 -0
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.d.ts.map +1 -1
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js +32 -29
- package/dist/components/QueryWrapperPlotNav/QueryWrapperPlotNav.js.map +1 -1
- package/dist/components/QueryWrapperPlotNav/UseRowSet.d.ts.map +1 -1
- package/dist/components/QueryWrapperPlotNav/UseRowSet.js +4 -1
- package/dist/components/QueryWrapperPlotNav/UseRowSet.js.map +1 -1
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts +59 -0
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.d.ts.map +1 -0
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js +174 -0
- package/dist/components/SearchQueryWrapper/SearchQueryUseQueryOptions.js.map +1 -0
- package/dist/components/SearchQueryWrapper/SearchQueryWrapper.d.ts +40 -0
- package/dist/components/SearchQueryWrapper/SearchQueryWrapper.d.ts.map +1 -0
- package/dist/components/SearchQueryWrapper/SearchQueryWrapper.js +100 -0
- package/dist/components/SearchQueryWrapper/SearchQueryWrapper.js.map +1 -0
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.d.ts +56 -0
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.d.ts.map +1 -0
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.js +73 -0
- package/dist/components/SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav.js.map +1 -0
- package/dist/components/ShareThisPage/ShareThisPage.js +1 -1
- package/dist/components/ShareThisPage/ShareThisPage.js.map +1 -1
- package/dist/components/SynapseChat/GridAgentChat.d.ts.map +1 -1
- package/dist/components/SynapseChat/GridAgentChat.js +20 -14
- package/dist/components/SynapseChat/GridAgentChat.js.map +1 -1
- package/dist/components/SynapseChat/SynapseChat.d.ts +3 -1
- package/dist/components/SynapseChat/SynapseChat.d.ts.map +1 -1
- package/dist/components/SynapseChat/SynapseChat.js +51 -36
- package/dist/components/SynapseChat/SynapseChat.js.map +1 -1
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.css +1 -1
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.js +8 -7
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.js.map +1 -1
- package/dist/components/SynapseHomepageV2/HotdropsAndNews.module.scss +16 -0
- package/dist/components/SynapseHomepageV2/WordPressNews.d.ts +3 -1
- package/dist/components/SynapseHomepageV2/WordPressNews.d.ts.map +1 -1
- package/dist/components/SynapseHomepageV2/WordPressNews.js +9 -8
- package/dist/components/SynapseHomepageV2/WordPressNews.js.map +1 -1
- package/dist/components/SynapseHomepageV2/WordPressNewsItem.d.ts +2 -1
- package/dist/components/SynapseHomepageV2/WordPressNewsItem.d.ts.map +1 -1
- package/dist/components/SynapseHomepageV2/WordPressNewsItem.js +2 -2
- package/dist/components/SynapseHomepageV2/WordPressNewsItem.js.map +1 -1
- package/dist/components/SynapseTable/SearchV2.d.ts +7 -0
- package/dist/components/SynapseTable/SearchV2.d.ts.map +1 -1
- package/dist/components/SynapseTable/SearchV2.js.map +1 -1
- package/dist/components/SynapseTable/SynapseTableRenderers.d.ts.map +1 -1
- package/dist/components/SynapseTable/SynapseTableRenderers.js +1 -1
- package/dist/components/SynapseTable/SynapseTableRenderers.js.map +1 -1
- package/dist/components/SynapseTable/usePrefetchTableData.d.ts.map +1 -1
- package/dist/components/SynapseTable/usePrefetchTableData.js +6 -5
- package/dist/components/SynapseTable/usePrefetchTableData.js.map +1 -1
- package/dist/components/ToastMessage/ToastMessage.d.ts +1 -1
- package/dist/components/ToastMessage/ToastMessage.d.ts.map +1 -1
- package/dist/components/ToastMessage/ToastMessage.js +2 -2
- package/dist/components/ToastMessage/ToastMessage.js.map +1 -1
- package/dist/components/error/ErrorPage.d.ts +0 -4
- package/dist/components/error/ErrorPage.d.ts.map +1 -1
- package/dist/components/error/ErrorPage.js +25 -30
- package/dist/components/error/ErrorPage.js.map +1 -1
- package/dist/components/index.d.ts +4 -0
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +41 -39
- package/dist/components/widgets/query-filter/FacetFilterControls.d.ts.map +1 -1
- package/dist/components/widgets/query-filter/FacetFilterControls.js +2 -2
- package/dist/components/widgets/query-filter/FacetFilterControls.js.map +1 -1
- package/dist/index.js +52 -50
- package/dist/index.js.map +1 -1
- package/dist/mocks/entity/index.d.ts.map +1 -1
- package/dist/mocks/entity/index.js +18 -16
- package/dist/mocks/entity/index.js.map +1 -1
- package/dist/mocks/mockSearchQueryData.d.ts +14 -0
- package/dist/mocks/mockSearchQueryData.d.ts.map +1 -0
- package/dist/mocks/mockSearchQueryData.js +564 -0
- package/dist/mocks/mockSearchQueryData.js.map +1 -0
- package/dist/mocks/msw/handlers/searchQueryHandlers.d.ts +22 -0
- package/dist/mocks/msw/handlers/searchQueryHandlers.d.ts.map +1 -0
- package/dist/mocks/msw/handlers/searchQueryHandlers.js +63 -0
- package/dist/mocks/msw/handlers/searchQueryHandlers.js.map +1 -0
- package/dist/mocks/msw/handlers.d.ts.map +1 -1
- package/dist/mocks/msw/handlers.js +9 -7
- package/dist/mocks/msw/handlers.js.map +1 -1
- package/dist/style/components/_cards.scss +15 -0
- package/dist/style/main.css +1 -1
- package/dist/synapse-client/SynapseClient.d.ts +7 -1
- package/dist/synapse-client/SynapseClient.d.ts.map +1 -1
- package/dist/synapse-client/SynapseClient.js +422 -417
- package/dist/synapse-client/SynapseClient.js.map +1 -1
- package/dist/synapse-client/index.js +3 -3
- package/dist/synapse-queries/KeyFactory.d.ts +2 -0
- package/dist/synapse-queries/KeyFactory.d.ts.map +1 -1
- package/dist/synapse-queries/KeyFactory.js +3 -0
- package/dist/synapse-queries/KeyFactory.js.map +1 -1
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/dist/utils/APIConstants.d.ts +2 -0
- package/dist/utils/APIConstants.d.ts.map +1 -1
- package/dist/utils/APIConstants.js +2 -2
- package/dist/utils/APIConstants.js.map +1 -1
- package/dist/utils/functions/calculateFriendlyFileSize.d.ts.map +1 -1
- package/dist/utils/functions/calculateFriendlyFileSize.js +3 -3
- package/dist/utils/functions/calculateFriendlyFileSize.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchV2.js","names":[],"sources":["../../../src/components/SynapseTable/SearchV2.tsx"],"sourcesContent":["import {\n isColumnMultiValueFunctionQueryFilter,\n isColumnSingleValueQueryFilter,\n LockedColumn,\n} from '@/utils'\nimport { Collapse } from '@mui/material'\nimport {\n ColumnModel,\n ColumnMultiValueFunction,\n ColumnMultiValueFunctionQueryFilter,\n ColumnSingleValueFilterOperator,\n ColumnSingleValueQueryFilter,\n ColumnTypeEnum,\n QueryFilter,\n} from '@sage-bionetworks/synapse-types'\nimport {\n Component,\n createRef,\n FormEvent,\n RefObject,\n SyntheticEvent,\n} from 'react'\nimport { CSSTransition } from 'react-transition-group'\nimport IconSvg from '../IconSvg/IconSvg'\nimport { QueryContextType } from '../QueryContext'\nimport { QueryVisualizationContextType } from '../QueryVisualizationWrapper'\nimport { useGetQueryMetadata } from '../QueryWrapper/useGetQueryMetadata'\nimport { ReadonlyDeep } from 'type-fest'\n\ntype SearchState = {\n show: boolean\n /* \n When the component is revealed in queryplotnav we want to focus on the input field and reveal the dropdown\n there is an issue where the method handleClickOutsideForm will override the state from componentDidUpdate\n so we track when componentDidUpdate just fired so that `show` is not overriden on the click event which\n triggers componentDidUpdate \n */\n didUpdateRanLast: boolean\n searchText: string\n columnName: string\n}\n\nexport type SearchableColumnsV2 = string[]\n\nexport type SearchV2Props = {\n queryContext: QueryContextType\n queryVisualizationContext: QueryVisualizationContextType\n isQueryWrapperMenuChild?: boolean\n defaultColumn?: string\n searchable?: SearchableColumnsV2\n lockedColumn?: LockedColumn\n /**\n * PLFM-8897, PORTALS-3534: Full-Text Search configuration.\n * For Tables that have FTS enabled...\n * If specified, use the specified mode and distance (if BOOLEAN mode). Otherwise default to NATURAL_LANGUAGE mode.\n */\n ftsConfig?: ReadonlyDeep<FTSConfig>\n}\n\nexport type TextMatchesMode = 'NATURAL_LANGUAGE' | 'BOOLEAN'\nexport type FTSConfig = {\n textMatchesMode: TextMatchesMode\n distance?: number // In BOOLEAN mode, this operator tests whether two or more words all start within a specified distance from each other, measured in words.\n searchHelpURL?: string\n}\n\ntype InternalSearchProps = SearchV2Props & {\n columnModels: ColumnModel[] | undefined\n}\n\nclass _Search extends Component<InternalSearchProps, SearchState> {\n public searchFormRef: RefObject<HTMLFormElement | null>\n public radioFormRef: RefObject<HTMLFormElement | null>\n\n constructor(props: InternalSearchProps) {\n super(props)\n this.state = {\n show: false,\n didUpdateRanLast: false,\n searchText: '',\n columnName: this.props.defaultColumn ?? '',\n }\n this.searchFormRef = createRef()\n this.radioFormRef = createRef()\n }\n\n componentDidMount() {\n // @ts-expect-error\n document.addEventListener('click', this.handleClickOutsideForm)\n }\n\n componentDidUpdate(prevProps: InternalSearchProps) {\n if (\n !prevProps.queryVisualizationContext?.showSearchBar &&\n this.props.queryVisualizationContext?.showSearchBar\n ) {\n this.setState({\n show: true,\n didUpdateRanLast: true,\n })\n this.searchFormRef?.current?.querySelector('input')?.focus()\n }\n }\n\n componentWillUnmount() {\n // @ts-expect-error\n document.removeEventListener('click', this.handleClickOutsideForm)\n }\n\n handleClickOutsideForm = (event: SyntheticEvent) => {\n if (\n // @ts-expect-error\n !this.searchFormRef.current?.contains(event?.target) &&\n // @ts-expect-error\n !this.radioFormRef.current?.contains(event?.target)\n ) {\n if (this.state.didUpdateRanLast) {\n this.setState({\n didUpdateRanLast: false,\n })\n } else {\n this.setState({\n show: false,\n })\n }\n }\n }\n\n public search = (event: SyntheticEvent<HTMLFormElement>) => {\n // form completion by default causes the page to reload, so we prevent that\n event.preventDefault()\n const { searchText } = this.state\n let { columnName } = this.state\n const { searchable, lockedColumn } = this.props\n if (columnName === '') {\n if (searchable) {\n // If searchable column names are defined in the config, grab the first one (that is not locked)\n columnName = searchable.filter(\n colName => colName !== lockedColumn?.columnName,\n )[0]\n } else {\n // Otherwise, get the first column model that can be searched.\n // And for study details page: if lockedColumn is defined, remove it from the search\n const searchableColumnModels = this.props.columnModels\n ?.filter(el => el.name !== lockedColumn?.columnName)\n .filter(el => this.isSupportedColumn(el))\n columnName = searchableColumnModels?.[0].name ?? ''\n }\n }\n this.setState({\n show: false,\n })\n const { executeQueryRequest, getCurrentQueryRequest } =\n this.props.queryContext\n\n const lastQueryRequestDeepClone = getCurrentQueryRequest()\n\n const { additionalFilters = [] } = lastQueryRequestDeepClone.query\n\n const indexOfColumn = additionalFilters.findIndex((el: QueryFilter) => {\n if (\n isColumnSingleValueQueryFilter(el) ||\n (isColumnMultiValueFunctionQueryFilter(el) &&\n el.columnName === columnName)\n ) {\n return true\n }\n return false\n })\n if (indexOfColumn === -1) {\n // get the column model to figure out what kind of filter we should apply.\n const columnModel: ColumnModel | undefined =\n this.props.columnModels?.filter(el => el.name === columnName)[0]\n if (columnModel?.columnType.endsWith('_LIST')) {\n const columnMultiValueQueryFilter: ColumnMultiValueFunctionQueryFilter =\n {\n columnName,\n function: ColumnMultiValueFunction.HAS_LIKE,\n _function: ColumnMultiValueFunction.HAS_LIKE,\n values: [`%${searchText}%`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnMultiValueFunctionQueryFilter',\n }\n additionalFilters.push(columnMultiValueQueryFilter)\n } else {\n if (columnModel?.columnType == ColumnTypeEnum.ENTITYID) {\n const columnSingleValueQueryFilter: ColumnSingleValueQueryFilter = {\n columnName,\n operator: ColumnSingleValueFilterOperator.EQUAL,\n values: [`${searchText.toLowerCase().replace('syn', '')}`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnSingleValueQueryFilter',\n }\n additionalFilters.push(columnSingleValueQueryFilter)\n } else {\n const columnSingleValueQueryFilter: ColumnSingleValueQueryFilter = {\n columnName,\n operator: ColumnSingleValueFilterOperator.LIKE,\n values: [`%${searchText}%`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnSingleValueQueryFilter',\n }\n additionalFilters.push(columnSingleValueQueryFilter)\n }\n }\n } else {\n ;(\n additionalFilters[indexOfColumn] as\n | ColumnSingleValueQueryFilter\n | ColumnMultiValueFunctionQueryFilter\n ).values.push(`%${searchText}%`)\n }\n lastQueryRequestDeepClone.query.additionalFilters = additionalFilters\n executeQueryRequest(lastQueryRequestDeepClone)\n }\n\n public handleChange = (event: FormEvent<HTMLInputElement>) => {\n this.setState({\n searchText: event.currentTarget.value,\n })\n }\n\n public isSupportedColumn = (columnModel?: ColumnModel) => {\n switch (columnModel?.columnType) {\n case ColumnTypeEnum.FILEHANDLEID:\n case ColumnTypeEnum.DATE:\n case ColumnTypeEnum.DATE_LIST:\n case ColumnTypeEnum.USERID:\n // case ColumnTypeEnum.ENTITYID: //PORTALS-2995: users may want to search on Synapse ID\n return false\n default:\n return true\n }\n }\n\n public isSupportedColumnAndInProps = (columnModel?: ColumnModel) => {\n if (this.isSupportedColumn(columnModel)) {\n // return true if the searchable array contains this column name\n const { searchable } = this.props\n return searchable?.some(e => e === columnModel?.name)\n }\n return false\n }\n\n render() {\n const {\n searchable,\n lockedColumn,\n columnModels,\n queryVisualizationContext: { showSearchBar, getColumnDisplayName },\n } = this.props\n const { searchText, show, columnName } = this.state\n let searchColumns: string[] = []\n\n // searchable specifies the order of the columns to search\n if (searchable) {\n searchColumns = searchable\n .map(el => columnModels?.find(model => model.name === el))\n .filter(this.isSupportedColumnAndInProps)\n .map(el => el!.name)\n } else if (columnModels) {\n searchColumns = columnModels\n ?.filter(this.isSupportedColumn)\n .map(el => el.name)\n }\n\n // For study details page: if lockedColumn is defined, remove it from the radio dropdown\n if (searchColumns.length && lockedColumn?.columnName) {\n searchColumns = searchColumns.filter(\n el => el !== lockedColumn?.columnName,\n )\n }\n return (\n <div className={`QueryWrapperSearchInput`}>\n <Collapse in={showSearchBar}>\n <form\n className=\"QueryWrapperSearchInput__searchbar\"\n onSubmit={this.search}\n onClick={() => {\n this.setState({ show: true })\n }}\n ref={this.searchFormRef}\n >\n <span className=\"QueryWrapperSearchInput__searchbar__searchicon\">\n <IconSvg icon=\"search\" />\n </span>\n <input\n onChange={this.handleChange}\n onClick={() => {\n this.setState({\n show: true,\n })\n }}\n placeholder=\"Enter Search Terms\"\n value={searchText}\n type=\"text\"\n />\n {this.state.searchText.length > 0 && (\n <button\n className=\"QueryWrapperSearchInput__searchbar__clearbutton\"\n type=\"button\"\n onClick={() => {\n this.setState({\n searchText: '',\n })\n }}\n >\n <IconSvg icon=\"close\" />\n </button>\n )}\n </form>\n </Collapse>\n <div className=\"QueryWrapperSearchInput__dropdown_pos\">\n <CSSTransition\n nodeRef={this.radioFormRef}\n in={show}\n classNames=\"QueryWrapperSearchInput__animate_dropdown\"\n timeout={{ enter: 0, exit: 300 }}\n >\n <form\n ref={this.radioFormRef}\n className=\"QueryWrapperSearchInput__column-select QueryWrapperSearchInput__animate_height\"\n >\n <p className=\"deemphasized\">\n <i> Search In Field: </i>\n </p>\n {searchColumns.map((name, index) => {\n const displayName = getColumnDisplayName(name)\n const isSelected =\n (columnName === '' && index === 0) || columnName === name\n return (\n <div className=\"radio\" key={`search-field-${name}-${index}`}>\n <label>\n <span>\n <input\n id={name}\n type=\"radio\"\n value={name}\n checked={isSelected}\n onClick={() => {\n this.searchFormRef?.current\n ?.querySelector('input')\n ?.focus()\n this.setState({\n columnName: name,\n })\n }}\n />\n <span>{displayName}</span>\n </span>\n </label>\n </div>\n )\n })}\n </form>\n </CSSTransition>\n </div>\n </div>\n )\n }\n}\n\nexport default function Search(props: SearchV2Props) {\n const { data: queryMetadata } = useGetQueryMetadata()\n return <_Search {...props} columnModels={queryMetadata?.columnModels} />\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SearchV2.js","names":[],"sources":["../../../src/components/SynapseTable/SearchV2.tsx"],"sourcesContent":["import {\n isColumnMultiValueFunctionQueryFilter,\n isColumnSingleValueQueryFilter,\n LockedColumn,\n} from '@/utils'\nimport { Collapse } from '@mui/material'\nimport {\n ColumnModel,\n ColumnMultiValueFunction,\n ColumnMultiValueFunctionQueryFilter,\n ColumnSingleValueFilterOperator,\n ColumnSingleValueQueryFilter,\n ColumnTypeEnum,\n QueryFilter,\n} from '@sage-bionetworks/synapse-types'\nimport {\n Component,\n createRef,\n FormEvent,\n RefObject,\n SyntheticEvent,\n} from 'react'\nimport { CSSTransition } from 'react-transition-group'\nimport IconSvg from '../IconSvg/IconSvg'\nimport { QueryContextType } from '../QueryContext'\nimport { QueryVisualizationContextType } from '../QueryVisualizationWrapper'\nimport { useGetQueryMetadata } from '../QueryWrapper/useGetQueryMetadata'\nimport { ReadonlyDeep } from 'type-fest'\n\ntype SearchState = {\n show: boolean\n /* \n When the component is revealed in queryplotnav we want to focus on the input field and reveal the dropdown\n there is an issue where the method handleClickOutsideForm will override the state from componentDidUpdate\n so we track when componentDidUpdate just fired so that `show` is not overriden on the click event which\n triggers componentDidUpdate \n */\n didUpdateRanLast: boolean\n searchText: string\n columnName: string\n}\n\nexport type SearchableColumnsV2 = string[]\n\nexport type SearchV2Props = {\n queryContext: QueryContextType\n queryVisualizationContext: QueryVisualizationContextType\n isQueryWrapperMenuChild?: boolean\n defaultColumn?: string\n searchable?: SearchableColumnsV2\n lockedColumn?: LockedColumn\n /**\n * PLFM-8897, PORTALS-3534: Full-Text Search configuration.\n * For Tables that have FTS enabled...\n * If specified, use the specified mode and distance (if BOOLEAN mode). Otherwise default to NATURAL_LANGUAGE mode.\n */\n ftsConfig?: ReadonlyDeep<FTSConfig>\n}\n\nexport type TextMatchesMode = 'NATURAL_LANGUAGE' | 'BOOLEAN'\nexport type FTSConfig = {\n textMatchesMode: TextMatchesMode\n distance?: number // In BOOLEAN mode, this operator tests whether two or more words all start within a specified distance from each other, measured in words.\n searchHelpURL?: string\n /**\n * Optional function to provide autocomplete suggestions for the search bar.\n * When provided, the search input will show a dropdown of suggestions as the user types.\n * @param searchText - The current text in the search input\n * @returns A promise resolving to an array of suggestion strings\n */\n getSuggestions?: (searchText: string) => Promise<string[]>\n}\n\ntype InternalSearchProps = SearchV2Props & {\n columnModels: ColumnModel[] | undefined\n}\n\nclass _Search extends Component<InternalSearchProps, SearchState> {\n public searchFormRef: RefObject<HTMLFormElement | null>\n public radioFormRef: RefObject<HTMLFormElement | null>\n\n constructor(props: InternalSearchProps) {\n super(props)\n this.state = {\n show: false,\n didUpdateRanLast: false,\n searchText: '',\n columnName: this.props.defaultColumn ?? '',\n }\n this.searchFormRef = createRef()\n this.radioFormRef = createRef()\n }\n\n componentDidMount() {\n // @ts-expect-error\n document.addEventListener('click', this.handleClickOutsideForm)\n }\n\n componentDidUpdate(prevProps: InternalSearchProps) {\n if (\n !prevProps.queryVisualizationContext?.showSearchBar &&\n this.props.queryVisualizationContext?.showSearchBar\n ) {\n this.setState({\n show: true,\n didUpdateRanLast: true,\n })\n this.searchFormRef?.current?.querySelector('input')?.focus()\n }\n }\n\n componentWillUnmount() {\n // @ts-expect-error\n document.removeEventListener('click', this.handleClickOutsideForm)\n }\n\n handleClickOutsideForm = (event: SyntheticEvent) => {\n if (\n // @ts-expect-error\n !this.searchFormRef.current?.contains(event?.target) &&\n // @ts-expect-error\n !this.radioFormRef.current?.contains(event?.target)\n ) {\n if (this.state.didUpdateRanLast) {\n this.setState({\n didUpdateRanLast: false,\n })\n } else {\n this.setState({\n show: false,\n })\n }\n }\n }\n\n public search = (event: SyntheticEvent<HTMLFormElement>) => {\n // form completion by default causes the page to reload, so we prevent that\n event.preventDefault()\n const { searchText } = this.state\n let { columnName } = this.state\n const { searchable, lockedColumn } = this.props\n if (columnName === '') {\n if (searchable) {\n // If searchable column names are defined in the config, grab the first one (that is not locked)\n columnName = searchable.filter(\n colName => colName !== lockedColumn?.columnName,\n )[0]\n } else {\n // Otherwise, get the first column model that can be searched.\n // And for study details page: if lockedColumn is defined, remove it from the search\n const searchableColumnModels = this.props.columnModels\n ?.filter(el => el.name !== lockedColumn?.columnName)\n .filter(el => this.isSupportedColumn(el))\n columnName = searchableColumnModels?.[0].name ?? ''\n }\n }\n this.setState({\n show: false,\n })\n const { executeQueryRequest, getCurrentQueryRequest } =\n this.props.queryContext\n\n const lastQueryRequestDeepClone = getCurrentQueryRequest()\n\n const { additionalFilters = [] } = lastQueryRequestDeepClone.query\n\n const indexOfColumn = additionalFilters.findIndex((el: QueryFilter) => {\n if (\n isColumnSingleValueQueryFilter(el) ||\n (isColumnMultiValueFunctionQueryFilter(el) &&\n el.columnName === columnName)\n ) {\n return true\n }\n return false\n })\n if (indexOfColumn === -1) {\n // get the column model to figure out what kind of filter we should apply.\n const columnModel: ColumnModel | undefined =\n this.props.columnModels?.filter(el => el.name === columnName)[0]\n if (columnModel?.columnType.endsWith('_LIST')) {\n const columnMultiValueQueryFilter: ColumnMultiValueFunctionQueryFilter =\n {\n columnName,\n function: ColumnMultiValueFunction.HAS_LIKE,\n _function: ColumnMultiValueFunction.HAS_LIKE,\n values: [`%${searchText}%`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnMultiValueFunctionQueryFilter',\n }\n additionalFilters.push(columnMultiValueQueryFilter)\n } else {\n if (columnModel?.columnType == ColumnTypeEnum.ENTITYID) {\n const columnSingleValueQueryFilter: ColumnSingleValueQueryFilter = {\n columnName,\n operator: ColumnSingleValueFilterOperator.EQUAL,\n values: [`${searchText.toLowerCase().replace('syn', '')}`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnSingleValueQueryFilter',\n }\n additionalFilters.push(columnSingleValueQueryFilter)\n } else {\n const columnSingleValueQueryFilter: ColumnSingleValueQueryFilter = {\n columnName,\n operator: ColumnSingleValueFilterOperator.LIKE,\n values: [`%${searchText}%`],\n concreteType:\n 'org.sagebionetworks.repo.model.table.ColumnSingleValueQueryFilter',\n }\n additionalFilters.push(columnSingleValueQueryFilter)\n }\n }\n } else {\n ;(\n additionalFilters[indexOfColumn] as\n | ColumnSingleValueQueryFilter\n | ColumnMultiValueFunctionQueryFilter\n ).values.push(`%${searchText}%`)\n }\n lastQueryRequestDeepClone.query.additionalFilters = additionalFilters\n executeQueryRequest(lastQueryRequestDeepClone)\n }\n\n public handleChange = (event: FormEvent<HTMLInputElement>) => {\n this.setState({\n searchText: event.currentTarget.value,\n })\n }\n\n public isSupportedColumn = (columnModel?: ColumnModel) => {\n switch (columnModel?.columnType) {\n case ColumnTypeEnum.FILEHANDLEID:\n case ColumnTypeEnum.DATE:\n case ColumnTypeEnum.DATE_LIST:\n case ColumnTypeEnum.USERID:\n // case ColumnTypeEnum.ENTITYID: //PORTALS-2995: users may want to search on Synapse ID\n return false\n default:\n return true\n }\n }\n\n public isSupportedColumnAndInProps = (columnModel?: ColumnModel) => {\n if (this.isSupportedColumn(columnModel)) {\n // return true if the searchable array contains this column name\n const { searchable } = this.props\n return searchable?.some(e => e === columnModel?.name)\n }\n return false\n }\n\n render() {\n const {\n searchable,\n lockedColumn,\n columnModels,\n queryVisualizationContext: { showSearchBar, getColumnDisplayName },\n } = this.props\n const { searchText, show, columnName } = this.state\n let searchColumns: string[] = []\n\n // searchable specifies the order of the columns to search\n if (searchable) {\n searchColumns = searchable\n .map(el => columnModels?.find(model => model.name === el))\n .filter(this.isSupportedColumnAndInProps)\n .map(el => el!.name)\n } else if (columnModels) {\n searchColumns = columnModels\n ?.filter(this.isSupportedColumn)\n .map(el => el.name)\n }\n\n // For study details page: if lockedColumn is defined, remove it from the radio dropdown\n if (searchColumns.length && lockedColumn?.columnName) {\n searchColumns = searchColumns.filter(\n el => el !== lockedColumn?.columnName,\n )\n }\n return (\n <div className={`QueryWrapperSearchInput`}>\n <Collapse in={showSearchBar}>\n <form\n className=\"QueryWrapperSearchInput__searchbar\"\n onSubmit={this.search}\n onClick={() => {\n this.setState({ show: true })\n }}\n ref={this.searchFormRef}\n >\n <span className=\"QueryWrapperSearchInput__searchbar__searchicon\">\n <IconSvg icon=\"search\" />\n </span>\n <input\n onChange={this.handleChange}\n onClick={() => {\n this.setState({\n show: true,\n })\n }}\n placeholder=\"Enter Search Terms\"\n value={searchText}\n type=\"text\"\n />\n {this.state.searchText.length > 0 && (\n <button\n className=\"QueryWrapperSearchInput__searchbar__clearbutton\"\n type=\"button\"\n onClick={() => {\n this.setState({\n searchText: '',\n })\n }}\n >\n <IconSvg icon=\"close\" />\n </button>\n )}\n </form>\n </Collapse>\n <div className=\"QueryWrapperSearchInput__dropdown_pos\">\n <CSSTransition\n nodeRef={this.radioFormRef}\n in={show}\n classNames=\"QueryWrapperSearchInput__animate_dropdown\"\n timeout={{ enter: 0, exit: 300 }}\n >\n <form\n ref={this.radioFormRef}\n className=\"QueryWrapperSearchInput__column-select QueryWrapperSearchInput__animate_height\"\n >\n <p className=\"deemphasized\">\n <i> Search In Field: </i>\n </p>\n {searchColumns.map((name, index) => {\n const displayName = getColumnDisplayName(name)\n const isSelected =\n (columnName === '' && index === 0) || columnName === name\n return (\n <div className=\"radio\" key={`search-field-${name}-${index}`}>\n <label>\n <span>\n <input\n id={name}\n type=\"radio\"\n value={name}\n checked={isSelected}\n onClick={() => {\n this.searchFormRef?.current\n ?.querySelector('input')\n ?.focus()\n this.setState({\n columnName: name,\n })\n }}\n />\n <span>{displayName}</span>\n </span>\n </label>\n </div>\n )\n })}\n </form>\n </CSSTransition>\n </div>\n </div>\n )\n }\n}\n\nexport default function Search(props: SearchV2Props) {\n const { data: queryMetadata } = useGetQueryMetadata()\n return <_Search {...props} columnModels={queryMetadata?.columnModels} />\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseTableRenderers.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseTable/SynapseTableRenderers.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIL,GAAG,EACJ,MAAM,iCAAiC,CAAA;AACxC,OAAO,EACL,WAAW,EAEX,aAAa,EACd,MAAM,uBAAuB,CAAA;AA2D9B,eAAO,MAAM,kBAAkB,gEAQ7B,CAAA;AAuBF,eAAO,MAAM,uBAAuB,gEAQlC,CAAA;AAiBF,eAAO,MAAM,oBAAoB,gEAQ/B,CAAA;AAyEF,eAAO,MAAM,YAAY,gEAQvB,CAAA;AAEF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,2CAiEzC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"SynapseTableRenderers.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseTable/SynapseTableRenderers.tsx"],"names":[],"mappings":"AAEA,OAAO,EAIL,GAAG,EACJ,MAAM,iCAAiC,CAAA;AACxC,OAAO,EACL,WAAW,EAEX,aAAa,EACd,MAAM,uBAAuB,CAAA;AA2D9B,eAAO,MAAM,kBAAkB,gEAQ7B,CAAA;AAuBF,eAAO,MAAM,uBAAuB,gEAQlC,CAAA;AAiBF,eAAO,MAAM,oBAAoB,gEAQ/B,CAAA;AAyEF,eAAO,MAAM,YAAY,gEAQvB,CAAA;AAEF,wBAAgB,qBAAqB,CACnC,KAAK,EAAE,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,2CAiEzC;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC,2CAyCnE"}
|
|
@@ -133,7 +133,7 @@ function L(e) {
|
|
|
133
133
|
function R(e) {
|
|
134
134
|
let { cell: t, table: r } = e, { data: i } = n(), a = M(e), s = P(e), c = s === void 0 ? void 0 : parseInt(s), l = r.options.meta?.rowSet?.headers ?? [], u = l.find((e) => e.name === t.column.id), d = i?.columnModels ?? [], { columnLinks: f } = o();
|
|
135
135
|
if (u) {
|
|
136
|
-
let n = (f ?? []).find((e) => e.matchColumnName === u.name), r = u.columnType, i = t.column.getIsSorted() ? "SRC-boldText" : "";
|
|
136
|
+
let n = (f ?? []).find((e) => e.matchColumnName === u.name), r = d.find((e) => e.name === u.name)?.columnType ?? u.columnType, i = t.column.getIsSorted() ? "SRC-boldText" : "";
|
|
137
137
|
return /* @__PURE__ */ v(p, {
|
|
138
138
|
columnType: r,
|
|
139
139
|
columnValue: t.getValue(),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SynapseTableRenderers.js","names":[],"sources":["../../../src/components/SynapseTable/SynapseTableRenderers.tsx"],"sourcesContent":["import { useGetEntityHeader } from '@/synapse-queries'\nimport { Checkbox } from '@mui/material'\nimport {\n ColumnTypeEnum,\n FacetColumnResult,\n FacetColumnResultValues,\n Row,\n} from '@sage-bionetworks/synapse-types'\nimport {\n CellContext,\n createColumnHelper,\n HeaderContext,\n} from '@tanstack/react-table'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { isEqual } from 'lodash-es'\nimport { useCallback } from 'react'\nimport AddToDownloadListV2 from '../AddToDownloadListV2'\nimport FileEntityDirectDownload from '../DirectDownload/FileEntityDirectDownload'\nimport HasAccessV2 from '../HasAccess'\nimport { useQueryContext } from '../QueryContext'\nimport { useQueryVisualizationContext } from '../QueryVisualizationWrapper'\nimport {\n isRowSelectedAtom,\n selectedRowsAtom,\n} from '../QueryWrapper/TableRowSelectionState'\nimport { useGetQueryMetadata } from '../QueryWrapper/useGetQueryMetadata'\nimport ColumnHeader from '../TanStackTable/ColumnHeader'\nimport { EnumFacetFilter } from '../widgets/query-filter/EnumFacetFilter/EnumFacetFilter'\nimport EntityIDColumnCopyIcon from './EntityIDColumnCopyIcon'\nimport SynapseTableCell from './SynapseTableCell'\nimport { useSynapseTableContext } from './SynapseTableContext'\nimport { useInView } from 'react-intersection-observer'\n\n// Add a prefix to these column IDs so they don't collide with actual column names\nconst columnIdPrefix =\n 'org.sagebionetworks.web.client.SynapseTablePredefinedColumn'\n\nconst columnHelper = createColumnHelper<Row>()\n\nfunction RowSelectionCell<TValue = unknown>(props: CellContext<Row, TValue>) {\n const { row, table } = props\n const rowSet = table.options.meta?.rowSet\n\n const isRowSelected = useAtomValue(isRowSelectedAtom)\n const [selectedRows, setSelectedRows] = useAtom(selectedRowsAtom)\n\n return (\n <div>\n <Checkbox\n inputProps={{ 'aria-label': 'Select row' }}\n checked={isRowSelected(row.original, rowSet!.headers)}\n onChange={(_event, checked) => {\n const cloneSelectedRows = [...selectedRows]\n if (checked) {\n cloneSelectedRows.push(row.original)\n } else {\n const index = cloneSelectedRows.findIndex(selectedRow =>\n isEqual(selectedRow, row.original),\n )\n if (index > -1) {\n cloneSelectedRows.splice(index, 1)\n }\n }\n // update context on change\n setSelectedRows(cloneSelectedRows)\n }}\n />\n </div>\n )\n}\n\nexport const rowSelectionColumn = columnHelper.display({\n id: `${columnIdPrefix}.RowSelectionColumn`,\n enableResizing: false,\n cell: RowSelectionCell,\n maxSize: 36,\n meta: {\n textAlign: 'center',\n },\n})\n\nfunction AddToDownloadListCell<TValue = unknown>(\n props: CellContext<Row, TValue>,\n) {\n const entityId = getEntityOrRowId(props)!\n const versionNumberString = getEntityOrRowVersion(props)\n const versionNumber = versionNumberString\n ? parseInt(versionNumberString)\n : undefined\n const { data: entityHeader } = useGetEntityHeader(entityId)\n return (\n <div data-testid={'AddToDownloadListCell'}>\n {entityHeader?.type === 'org.sagebionetworks.repo.model.FileEntity' && (\n <AddToDownloadListV2\n entityId={entityId}\n entityVersionNumber={versionNumber}\n />\n )}\n </div>\n )\n}\n\nexport const addToDownloadListColumn = columnHelper.display({\n id: `${columnIdPrefix}.AddToDownloadListColumn`,\n enableResizing: false,\n cell: AddToDownloadListCell,\n maxSize: 50,\n meta: {\n textAlign: 'center',\n },\n})\n\nfunction DirectDownloadCell<TValue = unknown>(props: CellContext<Row, TValue>) {\n const entityId = getEntityOrRowId(props)!\n const versionNumber = getEntityOrRowVersion(props)\n\n return (\n <div data-testid={'DirectDownloadCell'}>\n <FileEntityDirectDownload\n entityId={entityId}\n entityVersionNumber={versionNumber}\n iconSvgPropOverrides={{ sx: { color: 'primary.main' } }}\n />\n </div>\n )\n}\n\nexport const directDownloadColumn = columnHelper.display({\n id: `${columnIdPrefix}.DirectDownload`,\n enableResizing: false,\n cell: DirectDownloadCell,\n maxSize: 50,\n meta: {\n textAlign: 'center',\n },\n})\n\n/**\n * Given the (tanstack react) Table CellContext, return the rowId of the current Synapse Table Row.\n * If a rowEntityIDColumnName was provided in the table config, then instead return the entityID found in\n * that cell of the current Row.\n */\nfunction getEntityOrRowId<TValue = unknown>(\n props: CellContext<Row, TValue>,\n): string | undefined {\n const { row, table } = props\n const rowEntityIDColumnIndex = table.options.meta?.rowEntityIDColumnIndex\n const entityId =\n rowEntityIDColumnIndex !== undefined\n ? row.original.values[rowEntityIDColumnIndex]!\n : row.original.rowId?.toString()\n return entityId\n}\n\n/**\n * Given the (tanstack react) Table CellContext, return true if the table configuration defines a row entity version column name.\n * This will be used as the entity that represents the current Row.\n * @param props\n * @returns\n */\nfunction isRowEntityColumn<TValue = unknown>(\n props: CellContext<Row, TValue>,\n): boolean {\n const { table } = props\n return table.options.meta?.rowEntityVersionColumnIndex !== undefined\n}\n\n/**\n * Given the (tanstack react) Table CellContext, return the version of the current Synapse Table Row.\n * If a rowEntityVersionColumnName was provided in the table config, then instead return the version found in\n * that cell of the current Row.\n */\nfunction getEntityOrRowVersion<TValue = unknown>(\n props: CellContext<Row, TValue>,\n): string | undefined {\n const { row, table } = props\n const rowEntityVersionColumnIndex =\n table.options.meta?.rowEntityVersionColumnIndex\n const versionNumber =\n rowEntityVersionColumnIndex !== undefined\n ? row.original.values[rowEntityVersionColumnIndex]!\n : row.original.versionNumber?.toString()\n return versionNumber\n}\n\nfunction AccessCell<TValue = unknown>(props: CellContext<Row, TValue>) {\n const { showExternalAccessIcon } = useSynapseTableContext()\n const { ref, inView } = useInView({ triggerOnce: true })\n const entityId = getEntityOrRowId(props)!\n\n // If showExternalAccessIcon is true, defer rendering until the cell is in view to limit simultaneous API calls\n const canRenderAccessIcon =\n !showExternalAccessIcon || (showExternalAccessIcon && inView)\n\n return (\n <div ref={ref} data-testid=\"AccessCell\">\n {canRenderAccessIcon && (\n <HasAccessV2\n key={entityId}\n entityId={entityId}\n showButtonText={false}\n showExternalAccessIcon={showExternalAccessIcon}\n />\n )}\n </div>\n )\n}\n\nexport const accessColumn = columnHelper.display({\n id: `${columnIdPrefix}.Access`,\n enableResizing: false,\n cell: AccessCell,\n maxSize: 50,\n meta: {\n textAlign: 'center',\n },\n})\n\nexport function TableDataColumnHeader(\n props: HeaderContext<Row, string | null>,\n) {\n const { column } = props\n const { lockedColumn } = useQueryContext()\n const { data: queryMetadata } = useGetQueryMetadata()\n const columnModels = queryMetadata?.columnModels ?? []\n const selectColumns = queryMetadata?.selectColumns ?? []\n const selectColumn = selectColumns.find(sc => sc.name === column.id)\n const columnModel = columnModels.find(cm => cm.name === column.id)\n const facets = queryMetadata?.facets ?? []\n const { getColumnDisplayName, getHelpText } = useQueryVisualizationContext()\n\n const displayColumnName = selectColumn\n ? getColumnDisplayName(selectColumn.name)\n : column.id\n const columnHelpText = selectColumn\n ? getHelpText(selectColumn.name)\n : undefined\n // we have to figure out if the current column is a facet selection\n const facetIndex: number = facets.findIndex(\n (facetColumnResult: FacetColumnResult) => {\n return (\n facetColumnResult.columnName === columnModel?.name &&\n // Exclude JSON subcolumn facets, since there may be more than one on a given column\n facetColumnResult.jsonPath == undefined\n )\n },\n )\n // the header must be included in the facets and it has to be enumerable for current rendering capabilities\n const isFacetSelection: boolean =\n facetIndex !== -1 && facets[facetIndex].facetType === 'enumeration'\n const facet = facets[facetIndex] as FacetColumnResultValues\n const isLockedColumn =\n selectColumn &&\n selectColumn.name.toLowerCase() === lockedColumn?.columnName?.toLowerCase() // used in details page to disable filter the column\n const isEntityIDColumn =\n selectColumn &&\n selectColumn.name == 'id' &&\n selectColumn.columnType == ColumnTypeEnum.ENTITYID\n\n // TODO: enableFiltering should be specified on the column, but for now it's easier to override `getCanFilter` here where we have the facet information\n props.column.getCanFilter = useCallback(\n () => Boolean(isFacetSelection && !isLockedColumn && columnModel),\n [isFacetSelection, isLockedColumn, columnModel],\n )\n\n return (\n <ColumnHeader\n {...props}\n title={displayColumnName}\n helpText={columnHelpText}\n filterControl={\n <span>\n <EnumFacetFilter\n containerAs=\"Dropdown\"\n facet={facet}\n defaultShowAllValues={true}\n />\n </span>\n }\n additionalButtons={\n <>{isEntityIDColumn && <EntityIDColumnCopyIcon size={'small'} />}</>\n }\n />\n )\n}\n\nexport function TableDataCell(props: CellContext<Row, string | null>) {\n const { cell, table } = props\n const { data: queryMetadata } = useGetQueryMetadata()\n const entityOrRowId = getEntityOrRowId(props)\n const entityOrRowVersion = getEntityOrRowVersion(props)\n const versionNumber =\n entityOrRowVersion !== undefined ? parseInt(entityOrRowVersion) : undefined\n const selectColumns = table.options.meta?.rowSet?.headers ?? []\n const selectColumn = selectColumns.find(cm => cm.name === cell.column.id)\n const columnModels = queryMetadata?.columnModels ?? []\n const { columnLinks } = useSynapseTableContext()\n if (selectColumn) {\n const columnLinkConfig = (columnLinks ?? []).find(el => {\n return el.matchColumnName === selectColumn.name\n })\n const columnType = selectColumn.columnType\n const isBold = cell.column.getIsSorted() ? 'SRC-boldText' : ''\n return (\n <SynapseTableCell\n key={cell.id}\n columnType={columnType}\n columnValue={cell.getValue()}\n isBold={isBold}\n columnLinkConfig={columnLinkConfig}\n columnName={selectColumn.name}\n rowData={cell.row.original.values}\n selectColumns={selectColumns}\n columnModels={columnModels}\n rowId={entityOrRowId}\n rowVersionNumber={versionNumber}\n isRowEntityColumn={isRowEntityColumn(props)}\n />\n )\n } else return <td key={cell.id}></td>\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"SynapseTableRenderers.js","names":[],"sources":["../../../src/components/SynapseTable/SynapseTableRenderers.tsx"],"sourcesContent":["import { useGetEntityHeader } from '@/synapse-queries'\nimport { Checkbox } from '@mui/material'\nimport {\n ColumnTypeEnum,\n FacetColumnResult,\n FacetColumnResultValues,\n Row,\n} from '@sage-bionetworks/synapse-types'\nimport {\n CellContext,\n createColumnHelper,\n HeaderContext,\n} from '@tanstack/react-table'\nimport { useAtom, useAtomValue } from 'jotai'\nimport { isEqual } from 'lodash-es'\nimport { useCallback } from 'react'\nimport AddToDownloadListV2 from '../AddToDownloadListV2'\nimport FileEntityDirectDownload from '../DirectDownload/FileEntityDirectDownload'\nimport HasAccessV2 from '../HasAccess'\nimport { useQueryContext } from '../QueryContext'\nimport { useQueryVisualizationContext } from '../QueryVisualizationWrapper'\nimport {\n isRowSelectedAtom,\n selectedRowsAtom,\n} from '../QueryWrapper/TableRowSelectionState'\nimport { useGetQueryMetadata } from '../QueryWrapper/useGetQueryMetadata'\nimport ColumnHeader from '../TanStackTable/ColumnHeader'\nimport { EnumFacetFilter } from '../widgets/query-filter/EnumFacetFilter/EnumFacetFilter'\nimport EntityIDColumnCopyIcon from './EntityIDColumnCopyIcon'\nimport SynapseTableCell from './SynapseTableCell'\nimport { useSynapseTableContext } from './SynapseTableContext'\nimport { useInView } from 'react-intersection-observer'\n\n// Add a prefix to these column IDs so they don't collide with actual column names\nconst columnIdPrefix =\n 'org.sagebionetworks.web.client.SynapseTablePredefinedColumn'\n\nconst columnHelper = createColumnHelper<Row>()\n\nfunction RowSelectionCell<TValue = unknown>(props: CellContext<Row, TValue>) {\n const { row, table } = props\n const rowSet = table.options.meta?.rowSet\n\n const isRowSelected = useAtomValue(isRowSelectedAtom)\n const [selectedRows, setSelectedRows] = useAtom(selectedRowsAtom)\n\n return (\n <div>\n <Checkbox\n inputProps={{ 'aria-label': 'Select row' }}\n checked={isRowSelected(row.original, rowSet!.headers)}\n onChange={(_event, checked) => {\n const cloneSelectedRows = [...selectedRows]\n if (checked) {\n cloneSelectedRows.push(row.original)\n } else {\n const index = cloneSelectedRows.findIndex(selectedRow =>\n isEqual(selectedRow, row.original),\n )\n if (index > -1) {\n cloneSelectedRows.splice(index, 1)\n }\n }\n // update context on change\n setSelectedRows(cloneSelectedRows)\n }}\n />\n </div>\n )\n}\n\nexport const rowSelectionColumn = columnHelper.display({\n id: `${columnIdPrefix}.RowSelectionColumn`,\n enableResizing: false,\n cell: RowSelectionCell,\n maxSize: 36,\n meta: {\n textAlign: 'center',\n },\n})\n\nfunction AddToDownloadListCell<TValue = unknown>(\n props: CellContext<Row, TValue>,\n) {\n const entityId = getEntityOrRowId(props)!\n const versionNumberString = getEntityOrRowVersion(props)\n const versionNumber = versionNumberString\n ? parseInt(versionNumberString)\n : undefined\n const { data: entityHeader } = useGetEntityHeader(entityId)\n return (\n <div data-testid={'AddToDownloadListCell'}>\n {entityHeader?.type === 'org.sagebionetworks.repo.model.FileEntity' && (\n <AddToDownloadListV2\n entityId={entityId}\n entityVersionNumber={versionNumber}\n />\n )}\n </div>\n )\n}\n\nexport const addToDownloadListColumn = columnHelper.display({\n id: `${columnIdPrefix}.AddToDownloadListColumn`,\n enableResizing: false,\n cell: AddToDownloadListCell,\n maxSize: 50,\n meta: {\n textAlign: 'center',\n },\n})\n\nfunction DirectDownloadCell<TValue = unknown>(props: CellContext<Row, TValue>) {\n const entityId = getEntityOrRowId(props)!\n const versionNumber = getEntityOrRowVersion(props)\n\n return (\n <div data-testid={'DirectDownloadCell'}>\n <FileEntityDirectDownload\n entityId={entityId}\n entityVersionNumber={versionNumber}\n iconSvgPropOverrides={{ sx: { color: 'primary.main' } }}\n />\n </div>\n )\n}\n\nexport const directDownloadColumn = columnHelper.display({\n id: `${columnIdPrefix}.DirectDownload`,\n enableResizing: false,\n cell: DirectDownloadCell,\n maxSize: 50,\n meta: {\n textAlign: 'center',\n },\n})\n\n/**\n * Given the (tanstack react) Table CellContext, return the rowId of the current Synapse Table Row.\n * If a rowEntityIDColumnName was provided in the table config, then instead return the entityID found in\n * that cell of the current Row.\n */\nfunction getEntityOrRowId<TValue = unknown>(\n props: CellContext<Row, TValue>,\n): string | undefined {\n const { row, table } = props\n const rowEntityIDColumnIndex = table.options.meta?.rowEntityIDColumnIndex\n const entityId =\n rowEntityIDColumnIndex !== undefined\n ? row.original.values[rowEntityIDColumnIndex]!\n : row.original.rowId?.toString()\n return entityId\n}\n\n/**\n * Given the (tanstack react) Table CellContext, return true if the table configuration defines a row entity version column name.\n * This will be used as the entity that represents the current Row.\n * @param props\n * @returns\n */\nfunction isRowEntityColumn<TValue = unknown>(\n props: CellContext<Row, TValue>,\n): boolean {\n const { table } = props\n return table.options.meta?.rowEntityVersionColumnIndex !== undefined\n}\n\n/**\n * Given the (tanstack react) Table CellContext, return the version of the current Synapse Table Row.\n * If a rowEntityVersionColumnName was provided in the table config, then instead return the version found in\n * that cell of the current Row.\n */\nfunction getEntityOrRowVersion<TValue = unknown>(\n props: CellContext<Row, TValue>,\n): string | undefined {\n const { row, table } = props\n const rowEntityVersionColumnIndex =\n table.options.meta?.rowEntityVersionColumnIndex\n const versionNumber =\n rowEntityVersionColumnIndex !== undefined\n ? row.original.values[rowEntityVersionColumnIndex]!\n : row.original.versionNumber?.toString()\n return versionNumber\n}\n\nfunction AccessCell<TValue = unknown>(props: CellContext<Row, TValue>) {\n const { showExternalAccessIcon } = useSynapseTableContext()\n const { ref, inView } = useInView({ triggerOnce: true })\n const entityId = getEntityOrRowId(props)!\n\n // If showExternalAccessIcon is true, defer rendering until the cell is in view to limit simultaneous API calls\n const canRenderAccessIcon =\n !showExternalAccessIcon || (showExternalAccessIcon && inView)\n\n return (\n <div ref={ref} data-testid=\"AccessCell\">\n {canRenderAccessIcon && (\n <HasAccessV2\n key={entityId}\n entityId={entityId}\n showButtonText={false}\n showExternalAccessIcon={showExternalAccessIcon}\n />\n )}\n </div>\n )\n}\n\nexport const accessColumn = columnHelper.display({\n id: `${columnIdPrefix}.Access`,\n enableResizing: false,\n cell: AccessCell,\n maxSize: 50,\n meta: {\n textAlign: 'center',\n },\n})\n\nexport function TableDataColumnHeader(\n props: HeaderContext<Row, string | null>,\n) {\n const { column } = props\n const { lockedColumn } = useQueryContext()\n const { data: queryMetadata } = useGetQueryMetadata()\n const columnModels = queryMetadata?.columnModels ?? []\n const selectColumns = queryMetadata?.selectColumns ?? []\n const selectColumn = selectColumns.find(sc => sc.name === column.id)\n const columnModel = columnModels.find(cm => cm.name === column.id)\n const facets = queryMetadata?.facets ?? []\n const { getColumnDisplayName, getHelpText } = useQueryVisualizationContext()\n\n const displayColumnName = selectColumn\n ? getColumnDisplayName(selectColumn.name)\n : column.id\n const columnHelpText = selectColumn\n ? getHelpText(selectColumn.name)\n : undefined\n // we have to figure out if the current column is a facet selection\n const facetIndex: number = facets.findIndex(\n (facetColumnResult: FacetColumnResult) => {\n return (\n facetColumnResult.columnName === columnModel?.name &&\n // Exclude JSON subcolumn facets, since there may be more than one on a given column\n facetColumnResult.jsonPath == undefined\n )\n },\n )\n // the header must be included in the facets and it has to be enumerable for current rendering capabilities\n const isFacetSelection: boolean =\n facetIndex !== -1 && facets[facetIndex].facetType === 'enumeration'\n const facet = facets[facetIndex] as FacetColumnResultValues\n const isLockedColumn =\n selectColumn &&\n selectColumn.name.toLowerCase() === lockedColumn?.columnName?.toLowerCase() // used in details page to disable filter the column\n const isEntityIDColumn =\n selectColumn &&\n selectColumn.name == 'id' &&\n selectColumn.columnType == ColumnTypeEnum.ENTITYID\n\n // TODO: enableFiltering should be specified on the column, but for now it's easier to override `getCanFilter` here where we have the facet information\n props.column.getCanFilter = useCallback(\n () => Boolean(isFacetSelection && !isLockedColumn && columnModel),\n [isFacetSelection, isLockedColumn, columnModel],\n )\n\n return (\n <ColumnHeader\n {...props}\n title={displayColumnName}\n helpText={columnHelpText}\n filterControl={\n <span>\n <EnumFacetFilter\n containerAs=\"Dropdown\"\n facet={facet}\n defaultShowAllValues={true}\n />\n </span>\n }\n additionalButtons={\n <>{isEntityIDColumn && <EntityIDColumnCopyIcon size={'small'} />}</>\n }\n />\n )\n}\n\nexport function TableDataCell(props: CellContext<Row, string | null>) {\n const { cell, table } = props\n const { data: queryMetadata } = useGetQueryMetadata()\n const entityOrRowId = getEntityOrRowId(props)\n const entityOrRowVersion = getEntityOrRowVersion(props)\n const versionNumber =\n entityOrRowVersion !== undefined ? parseInt(entityOrRowVersion) : undefined\n const selectColumns = table.options.meta?.rowSet?.headers ?? []\n const selectColumn = selectColumns.find(cm => cm.name === cell.column.id)\n const columnModels = queryMetadata?.columnModels ?? []\n const { columnLinks } = useSynapseTableContext()\n if (selectColumn) {\n const columnLinkConfig = (columnLinks ?? []).find(el => {\n return el.matchColumnName === selectColumn.name\n })\n // Prefer the authoritative ColumnModel type over the SelectColumn type.\n // For regular table queries the two are always identical. For search queries,\n // SelectColumn types are fabricated as 'STRING' during the conversion from\n // SearchQueryResults, but columnModels (from the entity bundle) carry the\n // correct types (DATE, USERID, etc.) and are available once that bundle loads.\n const columnType =\n columnModels.find(cm => cm.name === selectColumn.name)?.columnType ??\n selectColumn.columnType\n const isBold = cell.column.getIsSorted() ? 'SRC-boldText' : ''\n return (\n <SynapseTableCell\n key={cell.id}\n columnType={columnType}\n columnValue={cell.getValue()}\n isBold={isBold}\n columnLinkConfig={columnLinkConfig}\n columnName={selectColumn.name}\n rowData={cell.row.original.values}\n selectColumns={selectColumns}\n columnModels={columnModels}\n rowId={entityOrRowId}\n rowVersionNumber={versionNumber}\n isRowEntityColumn={isRowEntityColumn(props)}\n />\n )\n } else return <td key={cell.id}></td>\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePrefetchTableData.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseTable/usePrefetchTableData.ts"],"names":[],"mappings":"AAUA,OAAO,EAOL,MAAM,EAEP,MAAM,iCAAiC,CAAA;AAuNxC;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG;IAC3D,qBAAqB,EAAE,OAAO,CAAA;CAC/B,CAkBA;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"usePrefetchTableData.d.ts","sourceRoot":"","sources":["../../../src/components/SynapseTable/usePrefetchTableData.ts"],"names":[],"mappings":"AAUA,OAAO,EAOL,MAAM,EAEP,MAAM,iCAAiC,CAAA;AAuNxC;;;;;GAKG;AACH,wBAAgB,2BAA2B,CAAC,MAAM,EAAE,MAAM,GAAG;IAC3D,qBAAqB,EAAE,OAAO,CAAA;CAC/B,CAkBA;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,IAAI,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAyC5E"}
|
|
@@ -95,19 +95,20 @@ function E(e) {
|
|
|
95
95
|
return { dataHasBeenPrefetched: !n && !r && !i && !a };
|
|
96
96
|
}
|
|
97
97
|
function D() {
|
|
98
|
-
let { keyFactory: t, accessToken: n } = e(), { currentQueryRequest: r } = u(),
|
|
98
|
+
let { keyFactory: t, accessToken: n } = e(), { currentQueryRequest: r, getRowDataQueryOptionsForPage: i } = u(), a = b();
|
|
99
99
|
return m((e) => {
|
|
100
|
-
let
|
|
100
|
+
let o;
|
|
101
|
+
return o = i ? i(e) : p(f({
|
|
101
102
|
type: "goToPage",
|
|
102
103
|
pageNumber: e
|
|
103
|
-
}, g(r)), void 0, t, n);
|
|
104
|
-
return i.prefetchQuery(a);
|
|
104
|
+
}, g(r)), void 0, t, n).rowDataQueryOptions, a.prefetchQuery(o);
|
|
105
105
|
}, [
|
|
106
106
|
n,
|
|
107
107
|
r,
|
|
108
|
+
i,
|
|
108
109
|
t,
|
|
109
110
|
void 0,
|
|
110
|
-
|
|
111
|
+
a
|
|
111
112
|
]);
|
|
112
113
|
}
|
|
113
114
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"usePrefetchTableData.js","names":[],"sources":["../../../src/components/SynapseTable/usePrefetchTableData.ts"],"sourcesContent":["import {\n useGetEntity,\n useGetEntityHeaders,\n useGetFileBatch,\n useGetRestrictionInformationBatch,\n useGetUserGroupHeaders,\n} from '@/synapse-queries'\nimport { useSynapseContext } from '@/utils'\nimport { getFieldIndex, getTypeIndices } from '@/utils/functions/queryUtils'\nimport { goToPage as transformQueryToGoToPage } from '@/utils/hooks/useImmutableTableQuery/TableQueryReducerActions'\nimport {\n ColumnTypeEnum,\n FileHandleAssociateType,\n FileHandleAssociation,\n QueryBundleRequest,\n ReferenceList,\n RestrictableObjectType,\n RowSet,\n Table,\n} from '@sage-bionetworks/synapse-types'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { cloneDeep } from 'lodash-es'\nimport { useCallback, useMemo } from 'react'\nimport { useQueryContext } from '../QueryContext'\nimport { getTableQueryUseQueryOptions } from '../QueryWrapper/TableQueryUseQueryOptions'\nimport { useGetQueryMetadata } from '../QueryWrapper/useGetQueryMetadata'\nimport {\n isEntityViewOrDatasetOrCollection,\n isFileViewOrDataset,\n} from './SynapseTableUtils'\n\nfunction usePrefetchFileHandleData(rowSet: RowSet) {\n const { entityId, versionNumber } = useQueryContext()\n\n const { data: entity } = useGetEntity<Table>(entityId, versionNumber)\n const { data: queryMetadata } = useGetQueryMetadata()\n\n const fileHandleIdColumnIndices = getTypeIndices(\n ColumnTypeEnum.FILEHANDLEID,\n queryMetadata?.selectColumns,\n )\n\n let fileHandlesToPrefetch: FileHandleAssociation[] = []\n\n // Now add all IDs from the entity ID columns\n if (entity && rowSet && queryMetadata && queryMetadata.selectColumns) {\n fileHandlesToPrefetch = rowSet.rows.reduce(\n (prev: FileHandleAssociation[], curr) => {\n fileHandleIdColumnIndices.forEach(index => {\n const value = curr.values[index]\n if (value) {\n const selectColumn = queryMetadata?.selectColumns![index]\n if (\n isFileViewOrDataset(entity) &&\n selectColumn.name === 'dataFileHandleId'\n ) {\n // The association is the entity\n prev.push({\n fileHandleId: value,\n associateObjectId: String(curr.rowId),\n associateObjectType: FileHandleAssociateType.FileEntity,\n })\n } else {\n // The association is the table entity\n prev.push({\n fileHandleId: value,\n associateObjectId: entity.id!,\n associateObjectType: FileHandleAssociateType.TableEntity,\n })\n }\n }\n })\n return prev\n },\n\n fileHandlesToPrefetch,\n )\n }\n\n return useGetFileBatch(\n {\n requestedFiles: fileHandlesToPrefetch,\n includeFileHandles: true,\n includePreSignedURLs: false,\n includePreviewPreSignedURLs: false,\n },\n {\n enabled: fileHandlesToPrefetch.length > 0,\n },\n )\n}\n\nfunction useGetEntitiesInTable(rowSet: RowSet) {\n const { entityId, versionNumber } = useQueryContext()\n const { data: entity } = useGetEntity<Table>(entityId, versionNumber)\n const { data: queryMetadata } = useGetQueryMetadata()\n\n let entitiesInTable: ReferenceList = []\n\n // If this is a file view/dataset, collect all the row IDs; they correspond to entities that we'll end up fetching\n if (entity && isEntityViewOrDatasetOrCollection(entity)) {\n entitiesInTable = rowSet.rows.reduce((prev: ReferenceList, curr) => {\n const { rowId, versionNumber } = curr\n if (rowId) {\n prev.push({\n targetId: `syn${rowId}`,\n targetVersionNumber: versionNumber,\n })\n }\n return prev\n }, entitiesInTable)\n }\n\n let entityIdColumnIndices = getTypeIndices(\n ColumnTypeEnum.ENTITYID,\n queryMetadata?.selectColumns,\n )\n\n if (entity && isEntityViewOrDatasetOrCollection(entity)) {\n // If this is a view/dataset, we don't need to fetch the entities in the entity ID column\n // Collecting the row IDs in the last step was sufficient\n const idColumnIndex = getFieldIndex('id', queryMetadata)\n entityIdColumnIndices = entityIdColumnIndices.filter(\n index => index !== idColumnIndex,\n )\n }\n\n const entityIdListColumnIndices = getTypeIndices(\n ColumnTypeEnum.ENTITYID_LIST,\n queryMetadata?.selectColumns,\n )\n\n entitiesInTable = rowSet.rows.reduce((prev: ReferenceList, curr) => {\n // Get all IDs from the entity ID columns\n entityIdColumnIndices.forEach(index => {\n const value = curr.values[index]\n if (\n value &&\n !prev.find(e => e.targetId === value && e.targetVersionNumber == null)\n ) {\n prev.push({ targetId: value })\n }\n })\n // Get all IDs from the entity ID list columns\n entityIdListColumnIndices.forEach(index => {\n const value = curr.values[index]\n if (value) {\n const ids = JSON.parse(value) as string[]\n ids.forEach(id => {\n if (\n id &&\n !prev.find(e => e.targetId === id && e.targetVersionNumber == null)\n ) {\n prev.push({ targetId: id })\n }\n })\n }\n })\n\n return prev\n }, entitiesInTable)\n\n return entitiesInTable\n}\n\nfunction usePrefetchEntityData(entitiesToPrefetch: ReferenceList) {\n return useGetEntityHeaders(entitiesToPrefetch, {\n enabled: entitiesToPrefetch.length > 0,\n })\n}\n\nfunction usePrefetchUserGroupHeaderData(rowSet: RowSet) {\n const { data: queryMetadata } = useGetQueryMetadata()\n\n const userIdColumnIndices = getTypeIndices(\n ColumnTypeEnum.USERID,\n queryMetadata?.selectColumns,\n )\n\n const userIdListColumnIndices = getTypeIndices(\n ColumnTypeEnum.USERID_LIST,\n queryMetadata?.selectColumns,\n )\n\n const principalIdsToPrefetch: string[] = rowSet.rows.reduce(\n (prev: string[], curr) => {\n // Add all IDs from the USERID columns\n userIdColumnIndices.forEach(index => {\n const value = curr.values[index]\n if (value && !prev.includes(value)) {\n prev.push(value)\n }\n })\n // Add all IDs from the USERID_LIST columns\n userIdListColumnIndices.forEach(index => {\n const value = curr.values[index]\n if (value) {\n const userIds = JSON.parse(value) as number[]\n userIds.forEach(userId => {\n if (!prev.includes(String(userId))) {\n prev.push(String(userId))\n }\n })\n }\n })\n return prev\n },\n [],\n )\n\n return useGetUserGroupHeaders(principalIdsToPrefetch, {\n enabled: principalIdsToPrefetch.length > 0,\n })\n}\n\nfunction usePrefetchEntityRestrictionData(entitiesToPrefetch: ReferenceList) {\n // This information only varies by entity ID, not version number. The restriction information is the same for all versions.\n const uniqueEntityIds = useMemo(() => {\n const entityIds = entitiesToPrefetch.map(e => e.targetId)\n // Dedupe the list in case there were duplicates, e.g. there were multiple versions of the same entity\n return Array.from(new Set(entityIds))\n }, [entitiesToPrefetch])\n\n return useGetRestrictionInformationBatch(\n {\n objectIds: uniqueEntityIds,\n restrictableObjectType: RestrictableObjectType.ENTITY,\n },\n {\n enabled: entitiesToPrefetch.length > 0,\n },\n )\n}\n\n/**\n * Uses react-query to prefetch data rendered by SynapseTable. Each SynapseTableCell instance load data to render rich\n * content (e.g. entity data) for the cell based on its column type. This hook uses react-query hooks that will\n * fetch and de-normalize batch requests, so when the SynapseTableCell component renders, the data is already loaded\n * in the cache. In practice, this avoids Synapse backend throttling and 'waterfall' content rendering.\n */\nexport function usePrefetchResourcesInTable(rowSet: RowSet): {\n dataHasBeenPrefetched: boolean\n} {\n const entitiesToPrefetch = useGetEntitiesInTable(rowSet)\n const { isLoading: isLoadingEntityData } =\n usePrefetchEntityData(entitiesToPrefetch)\n const { isLoading: isLoadingEntityRestrictionData } =\n usePrefetchEntityRestrictionData(entitiesToPrefetch)\n const { isLoading: isLoadingFileHandleData } =\n usePrefetchFileHandleData(rowSet)\n const { isLoading: isLoadingUserGroupData } =\n usePrefetchUserGroupHeaderData(rowSet)\n\n return {\n dataHasBeenPrefetched:\n !isLoadingEntityData &&\n !isLoadingEntityRestrictionData &&\n !isLoadingFileHandleData &&\n !isLoadingUserGroupData,\n }\n}\n\n/**\n * Uses react-query to prefetch an entire page of row data.\n *\n * @returns A function that will prefetch the data for a given page number.\n */\nexport function usePrefetchTableRows(): (pageNumber: number) => Promise<void> {\n const { keyFactory, accessToken } = useSynapseContext()\n const { currentQueryRequest } = useQueryContext()\n const queryClient = useQueryClient()\n\n // locked column does not matter for row data\n const lockedColumn = undefined\n return useCallback(\n (pageNumber: number) => {\n // Get the query for the next page\n const queryWithUpdatedPage = transformQueryToGoToPage(\n { type: 'goToPage', pageNumber },\n cloneDeep(currentQueryRequest) as QueryBundleRequest,\n )\n\n // Transform the query into UseQueryOptions\n const { rowDataQueryOptions } = getTableQueryUseQueryOptions(\n queryWithUpdatedPage,\n lockedColumn,\n keyFactory,\n accessToken,\n )\n\n // Finally, prefetch the data\n return queryClient.prefetchQuery(rowDataQueryOptions)\n },\n [accessToken, currentQueryRequest, keyFactory, lockedColumn, queryClient],\n )\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"usePrefetchTableData.js","names":[],"sources":["../../../src/components/SynapseTable/usePrefetchTableData.ts"],"sourcesContent":["import {\n useGetEntity,\n useGetEntityHeaders,\n useGetFileBatch,\n useGetRestrictionInformationBatch,\n useGetUserGroupHeaders,\n} from '@/synapse-queries'\nimport { useSynapseContext } from '@/utils'\nimport { getFieldIndex, getTypeIndices } from '@/utils/functions/queryUtils'\nimport { goToPage as transformQueryToGoToPage } from '@/utils/hooks/useImmutableTableQuery/TableQueryReducerActions'\nimport {\n ColumnTypeEnum,\n FileHandleAssociateType,\n FileHandleAssociation,\n QueryBundleRequest,\n ReferenceList,\n RestrictableObjectType,\n RowSet,\n Table,\n} from '@sage-bionetworks/synapse-types'\nimport { useQueryClient } from '@tanstack/react-query'\nimport { cloneDeep } from 'lodash-es'\nimport { useCallback, useMemo } from 'react'\nimport { useQueryContext } from '../QueryContext'\nimport { getTableQueryUseQueryOptions } from '../QueryWrapper/TableQueryUseQueryOptions'\nimport { useGetQueryMetadata } from '../QueryWrapper/useGetQueryMetadata'\nimport {\n isEntityViewOrDatasetOrCollection,\n isFileViewOrDataset,\n} from './SynapseTableUtils'\n\nfunction usePrefetchFileHandleData(rowSet: RowSet) {\n const { entityId, versionNumber } = useQueryContext()\n\n const { data: entity } = useGetEntity<Table>(entityId, versionNumber)\n const { data: queryMetadata } = useGetQueryMetadata()\n\n const fileHandleIdColumnIndices = getTypeIndices(\n ColumnTypeEnum.FILEHANDLEID,\n queryMetadata?.selectColumns,\n )\n\n let fileHandlesToPrefetch: FileHandleAssociation[] = []\n\n // Now add all IDs from the entity ID columns\n if (entity && rowSet && queryMetadata && queryMetadata.selectColumns) {\n fileHandlesToPrefetch = rowSet.rows.reduce(\n (prev: FileHandleAssociation[], curr) => {\n fileHandleIdColumnIndices.forEach(index => {\n const value = curr.values[index]\n if (value) {\n const selectColumn = queryMetadata?.selectColumns![index]\n if (\n isFileViewOrDataset(entity) &&\n selectColumn.name === 'dataFileHandleId'\n ) {\n // The association is the entity\n prev.push({\n fileHandleId: value,\n associateObjectId: String(curr.rowId),\n associateObjectType: FileHandleAssociateType.FileEntity,\n })\n } else {\n // The association is the table entity\n prev.push({\n fileHandleId: value,\n associateObjectId: entity.id!,\n associateObjectType: FileHandleAssociateType.TableEntity,\n })\n }\n }\n })\n return prev\n },\n\n fileHandlesToPrefetch,\n )\n }\n\n return useGetFileBatch(\n {\n requestedFiles: fileHandlesToPrefetch,\n includeFileHandles: true,\n includePreSignedURLs: false,\n includePreviewPreSignedURLs: false,\n },\n {\n enabled: fileHandlesToPrefetch.length > 0,\n },\n )\n}\n\nfunction useGetEntitiesInTable(rowSet: RowSet) {\n const { entityId, versionNumber } = useQueryContext()\n const { data: entity } = useGetEntity<Table>(entityId, versionNumber)\n const { data: queryMetadata } = useGetQueryMetadata()\n\n let entitiesInTable: ReferenceList = []\n\n // If this is a file view/dataset, collect all the row IDs; they correspond to entities that we'll end up fetching\n if (entity && isEntityViewOrDatasetOrCollection(entity)) {\n entitiesInTable = rowSet.rows.reduce((prev: ReferenceList, curr) => {\n const { rowId, versionNumber } = curr\n if (rowId) {\n prev.push({\n targetId: `syn${rowId}`,\n targetVersionNumber: versionNumber,\n })\n }\n return prev\n }, entitiesInTable)\n }\n\n let entityIdColumnIndices = getTypeIndices(\n ColumnTypeEnum.ENTITYID,\n queryMetadata?.selectColumns,\n )\n\n if (entity && isEntityViewOrDatasetOrCollection(entity)) {\n // If this is a view/dataset, we don't need to fetch the entities in the entity ID column\n // Collecting the row IDs in the last step was sufficient\n const idColumnIndex = getFieldIndex('id', queryMetadata)\n entityIdColumnIndices = entityIdColumnIndices.filter(\n index => index !== idColumnIndex,\n )\n }\n\n const entityIdListColumnIndices = getTypeIndices(\n ColumnTypeEnum.ENTITYID_LIST,\n queryMetadata?.selectColumns,\n )\n\n entitiesInTable = rowSet.rows.reduce((prev: ReferenceList, curr) => {\n // Get all IDs from the entity ID columns\n entityIdColumnIndices.forEach(index => {\n const value = curr.values[index]\n if (\n value &&\n !prev.find(e => e.targetId === value && e.targetVersionNumber == null)\n ) {\n prev.push({ targetId: value })\n }\n })\n // Get all IDs from the entity ID list columns\n entityIdListColumnIndices.forEach(index => {\n const value = curr.values[index]\n if (value) {\n const ids = JSON.parse(value) as string[]\n ids.forEach(id => {\n if (\n id &&\n !prev.find(e => e.targetId === id && e.targetVersionNumber == null)\n ) {\n prev.push({ targetId: id })\n }\n })\n }\n })\n\n return prev\n }, entitiesInTable)\n\n return entitiesInTable\n}\n\nfunction usePrefetchEntityData(entitiesToPrefetch: ReferenceList) {\n return useGetEntityHeaders(entitiesToPrefetch, {\n enabled: entitiesToPrefetch.length > 0,\n })\n}\n\nfunction usePrefetchUserGroupHeaderData(rowSet: RowSet) {\n const { data: queryMetadata } = useGetQueryMetadata()\n\n const userIdColumnIndices = getTypeIndices(\n ColumnTypeEnum.USERID,\n queryMetadata?.selectColumns,\n )\n\n const userIdListColumnIndices = getTypeIndices(\n ColumnTypeEnum.USERID_LIST,\n queryMetadata?.selectColumns,\n )\n\n const principalIdsToPrefetch: string[] = rowSet.rows.reduce(\n (prev: string[], curr) => {\n // Add all IDs from the USERID columns\n userIdColumnIndices.forEach(index => {\n const value = curr.values[index]\n if (value && !prev.includes(value)) {\n prev.push(value)\n }\n })\n // Add all IDs from the USERID_LIST columns\n userIdListColumnIndices.forEach(index => {\n const value = curr.values[index]\n if (value) {\n const userIds = JSON.parse(value) as number[]\n userIds.forEach(userId => {\n if (!prev.includes(String(userId))) {\n prev.push(String(userId))\n }\n })\n }\n })\n return prev\n },\n [],\n )\n\n return useGetUserGroupHeaders(principalIdsToPrefetch, {\n enabled: principalIdsToPrefetch.length > 0,\n })\n}\n\nfunction usePrefetchEntityRestrictionData(entitiesToPrefetch: ReferenceList) {\n // This information only varies by entity ID, not version number. The restriction information is the same for all versions.\n const uniqueEntityIds = useMemo(() => {\n const entityIds = entitiesToPrefetch.map(e => e.targetId)\n // Dedupe the list in case there were duplicates, e.g. there were multiple versions of the same entity\n return Array.from(new Set(entityIds))\n }, [entitiesToPrefetch])\n\n return useGetRestrictionInformationBatch(\n {\n objectIds: uniqueEntityIds,\n restrictableObjectType: RestrictableObjectType.ENTITY,\n },\n {\n enabled: entitiesToPrefetch.length > 0,\n },\n )\n}\n\n/**\n * Uses react-query to prefetch data rendered by SynapseTable. Each SynapseTableCell instance load data to render rich\n * content (e.g. entity data) for the cell based on its column type. This hook uses react-query hooks that will\n * fetch and de-normalize batch requests, so when the SynapseTableCell component renders, the data is already loaded\n * in the cache. In practice, this avoids Synapse backend throttling and 'waterfall' content rendering.\n */\nexport function usePrefetchResourcesInTable(rowSet: RowSet): {\n dataHasBeenPrefetched: boolean\n} {\n const entitiesToPrefetch = useGetEntitiesInTable(rowSet)\n const { isLoading: isLoadingEntityData } =\n usePrefetchEntityData(entitiesToPrefetch)\n const { isLoading: isLoadingEntityRestrictionData } =\n usePrefetchEntityRestrictionData(entitiesToPrefetch)\n const { isLoading: isLoadingFileHandleData } =\n usePrefetchFileHandleData(rowSet)\n const { isLoading: isLoadingUserGroupData } =\n usePrefetchUserGroupHeaderData(rowSet)\n\n return {\n dataHasBeenPrefetched:\n !isLoadingEntityData &&\n !isLoadingEntityRestrictionData &&\n !isLoadingFileHandleData &&\n !isLoadingUserGroupData,\n }\n}\n\n/**\n * Uses react-query to prefetch an entire page of row data.\n *\n * @returns A function that will prefetch the data for a given page number.\n */\nexport function usePrefetchTableRows(): (pageNumber: number) => Promise<void> {\n const { keyFactory, accessToken } = useSynapseContext()\n const { currentQueryRequest, getRowDataQueryOptionsForPage } =\n useQueryContext()\n const queryClient = useQueryClient()\n\n // locked column does not matter for row data\n const lockedColumn = undefined\n return useCallback(\n (pageNumber: number) => {\n let rowDataQueryOptions\n if (getRowDataQueryOptionsForPage) {\n // Use the context-provided factory (e.g. SearchQueryWrapper) to avoid calling\n // the standard table query API with a synthetic entity ID.\n rowDataQueryOptions = getRowDataQueryOptionsForPage(pageNumber)\n } else {\n // Standard table query path\n const queryWithUpdatedPage = transformQueryToGoToPage(\n { type: 'goToPage', pageNumber },\n cloneDeep(currentQueryRequest) as QueryBundleRequest,\n )\n rowDataQueryOptions = getTableQueryUseQueryOptions(\n queryWithUpdatedPage,\n lockedColumn,\n keyFactory,\n accessToken,\n ).rowDataQueryOptions\n }\n\n // Finally, prefetch the data\n return queryClient.prefetchQuery(rowDataQueryOptions)\n },\n [\n accessToken,\n currentQueryRequest,\n getRowDataQueryOptionsForPage,\n keyFactory,\n lockedColumn,\n queryClient,\n ],\n )\n}\n"],"mappings":"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"}
|
|
@@ -38,6 +38,6 @@ type ToastMessageOptions = {
|
|
|
38
38
|
*
|
|
39
39
|
* The rest of the options params are undefined by default.
|
|
40
40
|
*/
|
|
41
|
-
export declare const displayToast: (message: ReactNode, variant?: "info" | "success" | "warning" | "danger", toastMessageOptions?: ToastMessageOptions) => (() => void);
|
|
41
|
+
export declare const displayToast: (message: ReactNode, variant?: "info" | "success" | "warning" | "danger", toastMessageOptions?: ToastMessageOptions | null) => (() => void);
|
|
42
42
|
export {};
|
|
43
43
|
//# sourceMappingURL=ToastMessage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToastMessage.d.ts","sourceRoot":"","sources":["../../../src/components/ToastMessage/ToastMessage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAU,MAAM,OAAO,CAAA;AAGhD,OAAuB,EACrB,iBAAiB,EAClB,MAAM,kCAAkC,CAAA;AAEzC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,IAAI,EACJ,QAAQ,GACT,EAAE,iBAAiB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAiBvC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,KAAK,CAAC,SAAS,CAiBvD;AAED,KAAK,mBAAmB,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,mBAAmB,CAAC,EAAE,iBAAiB,CAAA;IACvC,qBAAqB,CAAC,EAAE,iBAAiB,CAAA;IACzC,2BAA2B,CAAC,EAAE,OAAO,CAAA;IACrC,6BAA6B,CAAC,EAAE,OAAO,CAAA;CACxC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,GACvB,SAAS,SAAS,EAClB,UAAU,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,EACnD,sBAAqB,
|
|
1
|
+
{"version":3,"file":"ToastMessage.d.ts","sourceRoot":"","sources":["../../../src/components/ToastMessage/ToastMessage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAU,MAAM,OAAO,CAAA;AAGhD,OAAuB,EACrB,iBAAiB,EAClB,MAAM,kCAAkC,CAAA;AAEzC,MAAM,MAAM,iBAAiB,GAAG;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,OAAO,CAAA;IACb,QAAQ,EAAE,OAAO,CAAA;CAClB,CAAA;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,EAC3B,IAAI,EACJ,IAAI,EACJ,QAAQ,GACT,EAAE,iBAAiB,GAAG,KAAK,CAAC,GAAG,CAAC,OAAO,CAiBvC;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,IAAI,KAAK,CAAC,SAAS,CAiBvD;AAED,KAAK,mBAAmB,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAA;IAEd,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,mBAAmB,CAAC,EAAE,iBAAiB,CAAA;IACvC,qBAAqB,CAAC,EAAE,iBAAiB,CAAA;IACzC,2BAA2B,CAAC,EAAE,OAAO,CAAA;IACrC,6BAA6B,CAAC,EAAE,OAAO,CAAA;CACxC,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY,GACvB,SAAS,SAAS,EAClB,UAAU,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ,EACnD,sBAAqB,mBAAmB,GAAG,IAAS,KACnD,CAAC,MAAM,IAAI,CAkEb,CAAA"}
|
|
@@ -37,7 +37,7 @@ function u() {
|
|
|
37
37
|
var d = (t, r, i = {}) => {
|
|
38
38
|
let o = n("synToast-"), s = () => {
|
|
39
39
|
a.dismiss(o);
|
|
40
|
-
}, { title: l = void 0, primaryButtonConfig: u = void 0, secondaryButtonConfig: d = void 0, dismissOnPrimaryButtonClick: f = !1, dismissOnSecondaryButtonClick: p = !1 } = i;
|
|
40
|
+
}, { title: l = void 0, primaryButtonConfig: u = void 0, secondaryButtonConfig: d = void 0, dismissOnPrimaryButtonClick: f = !1, dismissOnSecondaryButtonClick: p = !1 } = i ?? {};
|
|
41
41
|
if (u && "onClick" in u && f) {
|
|
42
42
|
let e = u.onClick;
|
|
43
43
|
u.onClick = (t) => {
|
|
@@ -50,7 +50,7 @@ var d = (t, r, i = {}) => {
|
|
|
50
50
|
e(t), s();
|
|
51
51
|
};
|
|
52
52
|
}
|
|
53
|
-
let { autoCloseInMs: m = 15e3 } = i;
|
|
53
|
+
let { autoCloseInMs: m = 15e3 } = i ?? {};
|
|
54
54
|
return m === 0 && (m = Infinity), a(/* @__PURE__ */ c(e, {
|
|
55
55
|
isGlobal: !1,
|
|
56
56
|
onClose: s,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToastMessage.js","names":[],"sources":["../../../src/components/ToastMessage/ToastMessage.tsx"],"sourcesContent":["import { uniqueId } from 'lodash-es'\nimport React, { ReactNode, useRef } from 'react'\nimport { toast, ToastBar, Toaster } from 'react-hot-toast'\nimport { CSSTransition, TransitionGroup } from 'react-transition-group'\nimport FullWidthAlert, {\n AlertButtonConfig,\n} from '../FullWidthAlert/FullWidthAlert'\n\nexport type ToastMessageProps = {\n text: string\n show: boolean\n autohide: boolean\n}\n\n/**\n *\n * Generalization of a Material-style toast message used in a couple of places. This component is simple and\n * cannot handle issuing multiple toast messages. For more sophisticated cases, see {@link displayToast}\n */\nexport function ToastMessage({\n text,\n show,\n autohide,\n}: ToastMessageProps): React.JSX.Element {\n const modalRef = useRef<HTMLDivElement>(null)\n return (\n <TransitionGroup>\n {show && (\n <CSSTransition\n nodeRef={modalRef}\n classNames=\"SRC-card\"\n timeout={autohide ? { enter: 500, exit: 300 } : {}}\n >\n <div className=\"SRC-modal\" ref={modalRef}>\n {text}\n </div>\n </CSSTransition>\n )}\n </TransitionGroup>\n )\n}\n\n/**\n * Customized ToastContainer for using react-toastify.\n *\n * Note that this will collide with other notification systems, such as the BootstrapNotify notifications\n * in SWC.\n */\nexport function SynapseToastContainer(): React.ReactNode {\n return (\n <Toaster\n containerClassName=\"SynapseToastContainer\"\n position=\"bottom-center\"\n >\n {t => (\n <ToastBar\n toast={t}\n style={{\n ...t.style,\n animation: t.visible ? 'fadeInUp 0.5s ease' : 'fadeOutDown 1s ease', // The exit animation needs to be long enough for the element to be removed, or else it will pop back in\n }}\n ></ToastBar>\n )}\n </Toaster>\n )\n}\n\ntype ToastMessageOptions = {\n title?: string\n /* autoCloseInMs default: 15000 */\n autoCloseInMs?: number\n primaryButtonConfig?: AlertButtonConfig\n secondaryButtonConfig?: AlertButtonConfig\n dismissOnPrimaryButtonClick?: boolean\n dismissOnSecondaryButtonClick?: boolean\n}\n\n/**\n * Displays a toast message. Requires one 'SynapseToastContainer' to be somewhere in the page.\n *\n * @param message - The description of the toast message.\n * @param variant - The type of toast message to display. Default 'info'.\n\n * In ToastMessageOptions:\n *\n * @param autoCloseInMs - The amount of time in milliseconds to wait before automatically closing the toast. To prevent autoclose, set to 0 or Infinity. Default 15000.\n *\n * The rest of the options params are undefined by default.\n */\nexport const displayToast = (\n message: ReactNode,\n variant?: 'info' | 'success' | 'warning' | 'danger',\n toastMessageOptions: ToastMessageOptions = {},\n): (() => void) => {\n const id = uniqueId('synToast-')\n const onClose = () => {\n toast.dismiss(id)\n }\n\n const {\n title = undefined,\n primaryButtonConfig = undefined,\n secondaryButtonConfig = undefined,\n dismissOnPrimaryButtonClick = false,\n dismissOnSecondaryButtonClick = false,\n } = toastMessageOptions\n\n // If 'dismissOnPrimaryButtonClick' is true, then we need to invoke onClose after onClick is invoked.\n if (\n primaryButtonConfig &&\n 'onClick' in primaryButtonConfig &&\n dismissOnPrimaryButtonClick\n ) {\n const onClick = primaryButtonConfig.onClick!\n primaryButtonConfig.onClick = e => {\n onClick(e)\n onClose()\n }\n }\n\n // ditto for secondary\n if (\n secondaryButtonConfig &&\n 'onClick' in secondaryButtonConfig &&\n dismissOnSecondaryButtonClick\n ) {\n const onClick = secondaryButtonConfig.onClick!\n secondaryButtonConfig.onClick = e => {\n onClick(e)\n onClose()\n }\n }\n\n let { autoCloseInMs = 15000 } = toastMessageOptions\n // Some toast libraries use 0 to prevent autoclose\n // react-hot-toast doesn't, but we can convert it for better compatibility as we try to migrate to use just one library\n if (autoCloseInMs === 0) {\n autoCloseInMs = Infinity\n }\n\n toast(\n <FullWidthAlert\n isGlobal={false}\n onClose={onClose}\n variant={variant ?? 'info'}\n show={true}\n title={title}\n description={message}\n primaryButtonConfig={primaryButtonConfig}\n secondaryButtonConfig={secondaryButtonConfig}\n />,\n {\n id: id,\n className: 'SynapseToastMessage',\n duration: autoCloseInMs,\n },\n )\n\n return onClose\n}\n"],"mappings":";;;;;;;AAmBA,SAAgB,EAAa,EAC3B,SACA,SACA,eACuC;CACvC,IAAM,IAAW,EAAuB,KAAK;AAC7C,QACE,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,GAAD;EACE,SAAS;EACT,YAAW;EACX,SAAS,IAAW;GAAE,OAAO;GAAK,MAAM;GAAK,GAAG,EAAE;YAElD,kBAAC,OAAD;GAAK,WAAU;GAAY,KAAK;aAC7B;GACG,CAAA;EACQ,CAAA,EAEF,CAAA;;AAUtB,SAAgB,IAAyC;AACvD,QACE,kBAAC,GAAD;EACE,oBAAmB;EACnB,UAAS;aAER,MACC,kBAAC,GAAD;GACE,OAAO;GACP,OAAO;IACL,GAAG,EAAE;IACL,WAAW,EAAE,UAAU,uBAAuB;IAC/C;GACS,CAAA;EAEN,CAAA;;AA0Bd,IAAa,KACX,GACA,GACA,
|
|
1
|
+
{"version":3,"file":"ToastMessage.js","names":[],"sources":["../../../src/components/ToastMessage/ToastMessage.tsx"],"sourcesContent":["import { uniqueId } from 'lodash-es'\nimport React, { ReactNode, useRef } from 'react'\nimport { toast, ToastBar, Toaster } from 'react-hot-toast'\nimport { CSSTransition, TransitionGroup } from 'react-transition-group'\nimport FullWidthAlert, {\n AlertButtonConfig,\n} from '../FullWidthAlert/FullWidthAlert'\n\nexport type ToastMessageProps = {\n text: string\n show: boolean\n autohide: boolean\n}\n\n/**\n *\n * Generalization of a Material-style toast message used in a couple of places. This component is simple and\n * cannot handle issuing multiple toast messages. For more sophisticated cases, see {@link displayToast}\n */\nexport function ToastMessage({\n text,\n show,\n autohide,\n}: ToastMessageProps): React.JSX.Element {\n const modalRef = useRef<HTMLDivElement>(null)\n return (\n <TransitionGroup>\n {show && (\n <CSSTransition\n nodeRef={modalRef}\n classNames=\"SRC-card\"\n timeout={autohide ? { enter: 500, exit: 300 } : {}}\n >\n <div className=\"SRC-modal\" ref={modalRef}>\n {text}\n </div>\n </CSSTransition>\n )}\n </TransitionGroup>\n )\n}\n\n/**\n * Customized ToastContainer for using react-toastify.\n *\n * Note that this will collide with other notification systems, such as the BootstrapNotify notifications\n * in SWC.\n */\nexport function SynapseToastContainer(): React.ReactNode {\n return (\n <Toaster\n containerClassName=\"SynapseToastContainer\"\n position=\"bottom-center\"\n >\n {t => (\n <ToastBar\n toast={t}\n style={{\n ...t.style,\n animation: t.visible ? 'fadeInUp 0.5s ease' : 'fadeOutDown 1s ease', // The exit animation needs to be long enough for the element to be removed, or else it will pop back in\n }}\n ></ToastBar>\n )}\n </Toaster>\n )\n}\n\ntype ToastMessageOptions = {\n title?: string\n /* autoCloseInMs default: 15000 */\n autoCloseInMs?: number\n primaryButtonConfig?: AlertButtonConfig\n secondaryButtonConfig?: AlertButtonConfig\n dismissOnPrimaryButtonClick?: boolean\n dismissOnSecondaryButtonClick?: boolean\n}\n\n/**\n * Displays a toast message. Requires one 'SynapseToastContainer' to be somewhere in the page.\n *\n * @param message - The description of the toast message.\n * @param variant - The type of toast message to display. Default 'info'.\n\n * In ToastMessageOptions:\n *\n * @param autoCloseInMs - The amount of time in milliseconds to wait before automatically closing the toast. To prevent autoclose, set to 0 or Infinity. Default 15000.\n *\n * The rest of the options params are undefined by default.\n */\nexport const displayToast = (\n message: ReactNode,\n variant?: 'info' | 'success' | 'warning' | 'danger',\n toastMessageOptions: ToastMessageOptions | null = {},\n): (() => void) => {\n const id = uniqueId('synToast-')\n const onClose = () => {\n toast.dismiss(id)\n }\n\n const {\n title = undefined,\n primaryButtonConfig = undefined,\n secondaryButtonConfig = undefined,\n dismissOnPrimaryButtonClick = false,\n dismissOnSecondaryButtonClick = false,\n } = toastMessageOptions ?? {}\n\n // If 'dismissOnPrimaryButtonClick' is true, then we need to invoke onClose after onClick is invoked.\n if (\n primaryButtonConfig &&\n 'onClick' in primaryButtonConfig &&\n dismissOnPrimaryButtonClick\n ) {\n const onClick = primaryButtonConfig.onClick!\n primaryButtonConfig.onClick = e => {\n onClick(e)\n onClose()\n }\n }\n\n // ditto for secondary\n if (\n secondaryButtonConfig &&\n 'onClick' in secondaryButtonConfig &&\n dismissOnSecondaryButtonClick\n ) {\n const onClick = secondaryButtonConfig.onClick!\n secondaryButtonConfig.onClick = e => {\n onClick(e)\n onClose()\n }\n }\n\n let { autoCloseInMs = 15000 } = toastMessageOptions ?? {}\n // Some toast libraries use 0 to prevent autoclose\n // react-hot-toast doesn't, but we can convert it for better compatibility as we try to migrate to use just one library\n if (autoCloseInMs === 0) {\n autoCloseInMs = Infinity\n }\n\n toast(\n <FullWidthAlert\n isGlobal={false}\n onClose={onClose}\n variant={variant ?? 'info'}\n show={true}\n title={title}\n description={message}\n primaryButtonConfig={primaryButtonConfig}\n secondaryButtonConfig={secondaryButtonConfig}\n />,\n {\n id: id,\n className: 'SynapseToastMessage',\n duration: autoCloseInMs,\n },\n )\n\n return onClose\n}\n"],"mappings":";;;;;;;AAmBA,SAAgB,EAAa,EAC3B,SACA,SACA,eACuC;CACvC,IAAM,IAAW,EAAuB,KAAK;AAC7C,QACE,kBAAC,GAAD,EAAA,UACG,KACC,kBAAC,GAAD;EACE,SAAS;EACT,YAAW;EACX,SAAS,IAAW;GAAE,OAAO;GAAK,MAAM;GAAK,GAAG,EAAE;YAElD,kBAAC,OAAD;GAAK,WAAU;GAAY,KAAK;aAC7B;GACG,CAAA;EACQ,CAAA,EAEF,CAAA;;AAUtB,SAAgB,IAAyC;AACvD,QACE,kBAAC,GAAD;EACE,oBAAmB;EACnB,UAAS;aAER,MACC,kBAAC,GAAD;GACE,OAAO;GACP,OAAO;IACL,GAAG,EAAE;IACL,WAAW,EAAE,UAAU,uBAAuB;IAC/C;GACS,CAAA;EAEN,CAAA;;AA0Bd,IAAa,KACX,GACA,GACA,IAAkD,EAAE,KACnC;CACjB,IAAM,IAAK,EAAS,YAAY,EAC1B,UAAgB;AACpB,IAAM,QAAQ,EAAG;IAGb,EACJ,WAAQ,KAAA,GACR,yBAAsB,KAAA,GACtB,2BAAwB,KAAA,GACxB,iCAA8B,IAC9B,mCAAgC,OAC9B,KAAuB,EAAE;AAG7B,KACE,KACA,aAAa,KACb,GACA;EACA,IAAM,IAAU,EAAoB;AACpC,IAAoB,WAAU,MAAK;AAEjC,GADA,EAAQ,EAAE,EACV,GAAS;;;AAKb,KACE,KACA,aAAa,KACb,GACA;EACA,IAAM,IAAU,EAAsB;AACtC,IAAsB,WAAU,MAAK;AAEnC,GADA,EAAQ,EAAE,EACV,GAAS;;;CAIb,IAAI,EAAE,mBAAgB,SAAU,KAAuB,EAAE;AAyBzD,QAtBI,MAAkB,MACpB,IAAgB,WAGlB,EACE,kBAAC,GAAD;EACE,UAAU;EACD;EACT,SAAS,KAAW;EACpB,MAAM;EACC;EACP,aAAa;EACQ;EACE;EACvB,CAAA,EACF;EACM;EACJ,WAAW;EACX,UAAU;EACX,CACF,EAEM"}
|
|
@@ -2,10 +2,6 @@ import { DoiObjectType } from '@sage-bionetworks/synapse-client/generated/models
|
|
|
2
2
|
export type ErrorPageProps = {
|
|
3
3
|
type: SynapseErrorType;
|
|
4
4
|
message?: string;
|
|
5
|
-
/** @deprecated use `id` and objectType: DoiObjectType.ENTITY */
|
|
6
|
-
entityId?: string;
|
|
7
|
-
/** @deprecated use `version` and objectType: DoiObjectType.ENTITY */
|
|
8
|
-
entityVersion?: number;
|
|
9
5
|
/** The ID of the object that was attempted to be retrieved, which may be used to show a 'tombstone' */
|
|
10
6
|
id?: string;
|
|
11
7
|
/** The version of the object that was attempted to be retrieved, which may be used to show a 'tombstone' */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorPage.d.ts","sourceRoot":"","sources":["../../../src/components/error/ErrorPage.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,MAAM,iEAAiE,CAAA;AAE/F,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,gBAAgB,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,
|
|
1
|
+
{"version":3,"file":"ErrorPage.d.ts","sourceRoot":"","sources":["../../../src/components/error/ErrorPage.tsx"],"names":[],"mappings":"AAQA,OAAO,EAAE,aAAa,EAAE,MAAM,iEAAiE,CAAA;AAE/F,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,gBAAgB,CAAA;IACtB,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,uGAAuG;IACvG,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,4GAA4G;IAC5G,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,yGAAyG;IACzG,UAAU,CAAC,EAAE,aAAa,CAAA;IAC1B,wGAAwG;IACxG,QAAQ,CAAC,EAAE,MAAM,CAAA;IAEjB,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAA;CAClC,CAAA;AAED,eAAO,MAAM,kBAAkB,qCAAqC,CAAA;AACpE,eAAO,MAAM,mBAAmB,iDAA4C,CAAA;AAC5E,eAAO,MAAM,eAAe,oCAA+B,CAAA;AAC3D,eAAO,MAAM,gBAAgB,sBAAsB,CAAA;AACnD,eAAO,MAAM,oBAAoB,oCAAoC,CAAA;AACrE,eAAO,MAAM,uBAAuB,8BAA8B,CAAA;AAClE,eAAO,MAAM,+BAA+B,4HAC+E,CAAA;AAC3H,eAAO,MAAM,qBAAqB,oEACiC,CAAA;AACnE,eAAO,MAAM,iBAAiB,4EAC6C,CAAA;AAC3E,eAAO,MAAM,0CAA0C,mEACW,CAAA;AAClE,eAAO,MAAM,8CAA8C,gFACoB,CAAA;AAE/E,oBAAY,gBAAgB;IAC1B,IAAI,SAAS;IACb,aAAa,kBAAkB;IAC/B,SAAS,cAAc;CACxB;AAmDD,iBAAS,SAAS,CAAC,KAAK,EAAE,cAAc,2CA2IvC;AAED,eAAe,SAAS,CAAA"}
|
|
@@ -40,38 +40,38 @@ var g = "Synapse is down for maintenance.", _ = "You don’t have permission to
|
|
|
40
40
|
}
|
|
41
41
|
};
|
|
42
42
|
function A(t) {
|
|
43
|
-
let { type: n,
|
|
43
|
+
let { type: n, message: r, gotoPlace: g, id: _, version: v, objectType: x, portalId: E } = t, [A, j] = c(!1), { isAuthenticated: M } = e(), N = s(() => O(n), [n]), P = s(() => k(n), [n]), F = s(() => {
|
|
44
44
|
let e = [];
|
|
45
45
|
switch (n) {
|
|
46
46
|
case D.ACCESS_DENIED:
|
|
47
|
-
|
|
47
|
+
M ? e.push(C) : e.push(S);
|
|
48
48
|
break;
|
|
49
49
|
case D.NOT_FOUND:
|
|
50
50
|
e.push(w);
|
|
51
51
|
break;
|
|
52
52
|
}
|
|
53
|
-
return
|
|
53
|
+
return r && e.push(r), e;
|
|
54
54
|
}, [
|
|
55
55
|
n,
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
]),
|
|
56
|
+
M,
|
|
57
|
+
r
|
|
58
|
+
]), I = s(() => {
|
|
59
59
|
let e = [];
|
|
60
|
-
return n === D.ACCESS_DENIED && (
|
|
60
|
+
return n === D.ACCESS_DENIED && (M ? _ && e.push({
|
|
61
61
|
linkText: b,
|
|
62
62
|
onClick: () => window.open("https://sagebionetworks.jira.com/servicedesk/customer/portals", "_blank"),
|
|
63
63
|
description: ""
|
|
64
64
|
}) : e.push({
|
|
65
65
|
linkText: y,
|
|
66
|
-
onClick: () =>
|
|
66
|
+
onClick: () => g("/LoginPlace:0"),
|
|
67
67
|
description: T
|
|
68
68
|
})), e;
|
|
69
69
|
}, [
|
|
70
70
|
n,
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
]),
|
|
71
|
+
M,
|
|
72
|
+
_,
|
|
73
|
+
g
|
|
74
|
+
]), L = o(() => j(!1), []);
|
|
75
75
|
return /* @__PURE__ */ m(f, { children: [/* @__PURE__ */ m(l, {
|
|
76
76
|
sx: {
|
|
77
77
|
display: {
|
|
@@ -96,7 +96,7 @@ function A(t) {
|
|
|
96
96
|
pt: "50px",
|
|
97
97
|
pb: "50px"
|
|
98
98
|
},
|
|
99
|
-
children:
|
|
99
|
+
children: N
|
|
100
100
|
}), /* @__PURE__ */ m(l, {
|
|
101
101
|
sx: {
|
|
102
102
|
justifySelf: "start",
|
|
@@ -117,13 +117,13 @@ function A(t) {
|
|
|
117
117
|
fontWeight: 700,
|
|
118
118
|
lineHeight: "36px"
|
|
119
119
|
},
|
|
120
|
-
children:
|
|
120
|
+
children: P
|
|
121
121
|
}),
|
|
122
|
-
|
|
122
|
+
F.map((e) => /* @__PURE__ */ p(d, {
|
|
123
123
|
variant: "body1",
|
|
124
124
|
children: e
|
|
125
125
|
}, e)),
|
|
126
|
-
|
|
126
|
+
I.map((e) => {
|
|
127
127
|
let { onClick: t, linkText: n, description: r } = e;
|
|
128
128
|
return /* @__PURE__ */ m(l, { children: [/* @__PURE__ */ p(u, {
|
|
129
129
|
sx: { fontSize: "16px" },
|
|
@@ -134,23 +134,18 @@ function A(t) {
|
|
|
134
134
|
children: r
|
|
135
135
|
})] }, n);
|
|
136
136
|
}),
|
|
137
|
-
|
|
138
|
-
id:
|
|
139
|
-
version:
|
|
140
|
-
type:
|
|
141
|
-
|
|
142
|
-
x && A && /* @__PURE__ */ p(i, {
|
|
143
|
-
id: x,
|
|
144
|
-
version: E,
|
|
145
|
-
type: A,
|
|
146
|
-
portalId: j
|
|
137
|
+
_ && x && /* @__PURE__ */ p(i, {
|
|
138
|
+
id: _,
|
|
139
|
+
version: v,
|
|
140
|
+
type: x,
|
|
141
|
+
portalId: E
|
|
147
142
|
})
|
|
148
143
|
]
|
|
149
144
|
})]
|
|
150
|
-
}),
|
|
151
|
-
isOpen:
|
|
152
|
-
onHide:
|
|
153
|
-
entityId:
|
|
145
|
+
}), _ && x === h.ENTITY && /* @__PURE__ */ p(a, {
|
|
146
|
+
isOpen: A,
|
|
147
|
+
onHide: L,
|
|
148
|
+
entityId: _
|
|
154
149
|
})] });
|
|
155
150
|
}
|
|
156
151
|
//#endregion
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorPage.js","names":[],"sources":["../../../src/components/error/ErrorPage.tsx"],"sourcesContent":["import { ReactComponent as MaintenanceSvg } from '@/assets/icons/error_page/maintenance.svg'\nimport { ReactComponent as NoAccessSvg } from '@/assets/icons/error_page/no-access.svg'\nimport { ReactComponent as UnavailableSvg } from '@/assets/icons/error_page/unavailable.svg'\nimport { useSynapseContext } from '@/utils'\nimport { Box, Link, Typography } from '@mui/material'\nimport { useCallback, useMemo, useState } from 'react'\nimport SynapseObjectDOIInfo from './SynapseObjectDOIInfo'\nimport SendMessageToEntityOwnerDialog from './SendMessageToEntityOwnerDialog'\nimport { DoiObjectType } from '@sage-bionetworks/synapse-client/generated/models/DoiObjectType'\n\nexport type ErrorPageProps = {\n type: SynapseErrorType\n message?: string // custom message to report\n /** @deprecated use `id` and objectType: DoiObjectType.ENTITY */\n entityId?: string\n /** @deprecated use `version` and objectType: DoiObjectType.ENTITY */\n entityVersion?: number\n\n /** The ID of the object that was attempted to be retrieved, which may be used to show a 'tombstone' */\n id?: string\n /** The version of the object that was attempted to be retrieved, which may be used to show a 'tombstone' */\n version?: number\n /** The type of the object that was attempted to be retrieved, which may be used to show a 'tombstone' */\n objectType?: DoiObjectType\n /** If on a portal that may mint DOIs, this portal ID may be used to find a DOI to show a 'tombstone' */\n portalId?: string\n\n gotoPlace: (href: string) => void\n}\n\nexport const SYNAPSE_DOWN_TITLE = 'Synapse is down for maintenance.'\nexport const ACCESS_DENIED_TITLE = 'You don’t have permission to view this.'\nexport const NOT_FOUND_TITLE = 'This page isn’t available.'\nexport const LOG_IN_LINK_TEXT = 'Log in to Synapse'\nexport const CONTACT_US_LINK_TEXT = 'Contact us for more information'\nexport const CONTACT_ADMIN_LINK_TEXT = 'Contact the Administrator'\nexport const ACCESS_DENIED_ANONYMOUS_MESSAGE =\n 'Try logging in. If you still see this message after logging in, you have not been granted access to view this resource.'\nexport const ACCESS_DENIED_MESSAGE =\n 'This account has not been granted access to view this resource.'\nexport const NOT_FOUND_MESSAGE =\n 'The link you followed may be broken, or the page may have been removed.'\nexport const ACCESS_DENIED_ANONYMOUS_ACTION_DESCRIPTION =\n 'A Synapse account is free, and lets you view public resources.'\nexport const ACCESS_DENIED_CONTACT_ADMIN_ACTION_DESCRIPTION =\n 'Write a message to the owner of the resource asking for permission to view.'\n\nexport enum SynapseErrorType {\n DOWN = 'DOWN',\n ACCESS_DENIED = 'ACCESS_DENIED',\n NOT_FOUND = 'NOT_FOUND',\n}\n\nconst getImage = (type: SynapseErrorType) => {\n switch (type) {\n case SynapseErrorType.DOWN:\n return (\n <MaintenanceSvg\n role=\"img\"\n aria-label=\"Synapse is Down image\"\n title={SynapseErrorType.DOWN}\n />\n )\n case SynapseErrorType.ACCESS_DENIED:\n return (\n <NoAccessSvg\n role=\"img\"\n aria-label=\"Access denied image\"\n title={SynapseErrorType.ACCESS_DENIED}\n />\n )\n case SynapseErrorType.NOT_FOUND:\n return (\n <UnavailableSvg\n role=\"img\"\n aria-label=\"Resource not found image\"\n title={SynapseErrorType.NOT_FOUND}\n />\n )\n default:\n return <></>\n }\n}\nconst getTitle = (type: SynapseErrorType) => {\n switch (type) {\n case SynapseErrorType.DOWN:\n return SYNAPSE_DOWN_TITLE\n case SynapseErrorType.ACCESS_DENIED:\n return ACCESS_DENIED_TITLE\n case SynapseErrorType.NOT_FOUND:\n return NOT_FOUND_TITLE\n default:\n return ''\n }\n}\n\ntype ErrorPageAction = {\n linkText: string\n onClick: () => void\n description: string\n}\n\nfunction ErrorPage(props: ErrorPageProps) {\n const {\n type,\n entityId = '',\n entityVersion,\n message,\n gotoPlace,\n id,\n version,\n objectType,\n portalId,\n } = props\n const [isSendMessageToAdminDialogOpen, setSendMessageToAdminDialogOpen] =\n useState<boolean>(false)\n const { isAuthenticated } = useSynapseContext()\n const image = useMemo(() => getImage(type), [type])\n const title = useMemo(() => getTitle(type), [type])\n\n const messages = useMemo(() => {\n const msgs: string[] = []\n switch (type) {\n case SynapseErrorType.ACCESS_DENIED:\n if (!isAuthenticated) {\n msgs.push(ACCESS_DENIED_ANONYMOUS_MESSAGE)\n } else {\n msgs.push(ACCESS_DENIED_MESSAGE)\n }\n break\n case SynapseErrorType.NOT_FOUND:\n msgs.push(NOT_FOUND_MESSAGE)\n break\n }\n if (message) {\n msgs.push(message)\n }\n return msgs\n }, [type, isAuthenticated, message])\n\n const actions = useMemo(() => {\n const acts: ErrorPageAction[] = []\n if (type === SynapseErrorType.ACCESS_DENIED) {\n if (!isAuthenticated) {\n acts.push({\n linkText: LOG_IN_LINK_TEXT,\n onClick: () => gotoPlace('/LoginPlace:0'),\n description: ACCESS_DENIED_ANONYMOUS_ACTION_DESCRIPTION,\n })\n } else if (entityId) {\n acts.push({\n linkText: CONTACT_US_LINK_TEXT,\n onClick: () =>\n window.open(\n 'https://sagebionetworks.jira.com/servicedesk/customer/portals',\n '_blank',\n ),\n description: '',\n })\n // SWC-7073: Remove ability to send a message to the admins until we have a better option for the majority of the cases (service desk, contact emails, ...)\n // acts.push({\n // linkText: CONTACT_ADMIN_LINK_TEXT,\n // onClick: () => setSendMessageToAdminDialogOpen(true),\n // description: ACCESS_DENIED_CONTACT_ADMIN_ACTION_DESCRIPTION,\n // })\n }\n }\n return acts\n }, [type, isAuthenticated, entityId, gotoPlace])\n\n const handleCloseDialog = useCallback(\n () => setSendMessageToAdminDialogOpen(false),\n [],\n )\n return (\n <>\n <Box\n sx={{\n display: { xs: 'flex', lg: 'grid' },\n columnGap: '80px',\n flexDirection: { xs: 'column', lg: undefined },\n gridTemplateColumns: { lg: '40% 60%' },\n }}\n >\n <Box\n sx={{\n justifySelf: 'end',\n alignSelf: 'center',\n '& svg': {\n height: '360px',\n maxWidth: '300px',\n },\n pt: '50px',\n pb: '50px',\n }}\n >\n {image}\n </Box>\n <Box\n sx={{\n justifySelf: 'start',\n alignSelf: 'center',\n display: 'flex',\n flexDirection: 'column',\n gap: '20px',\n m: { xs: '15px', lg: undefined },\n mr: { lg: '100px' },\n }}\n >\n <Typography\n sx={{ fontSize: '30px', fontWeight: 700, lineHeight: '36px' }}\n >\n {title}\n </Typography>\n {messages.map(message => {\n return (\n <Typography variant=\"body1\" key={message}>\n {message}\n </Typography>\n )\n })}\n {actions.map(action => {\n const { onClick, linkText, description } = action\n return (\n <Box key={linkText}>\n <Link sx={{ fontSize: '16px' }} onClick={onClick}>\n {linkText}\n </Link>\n <Typography variant=\"body1\">{description}</Typography>\n </Box>\n )\n })}\n {entityId && (\n <SynapseObjectDOIInfo\n id={entityId}\n version={entityVersion}\n type={DoiObjectType.ENTITY}\n />\n )}\n {id && objectType && (\n <SynapseObjectDOIInfo\n id={id}\n version={version}\n type={objectType}\n portalId={portalId}\n />\n )}\n </Box>\n </Box>\n {entityId && (\n <SendMessageToEntityOwnerDialog\n isOpen={isSendMessageToAdminDialogOpen}\n onHide={handleCloseDialog}\n entityId={entityId}\n />\n )}\n </>\n )\n}\n\nexport default ErrorPage\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ErrorPage.js","names":[],"sources":["../../../src/components/error/ErrorPage.tsx"],"sourcesContent":["import { ReactComponent as MaintenanceSvg } from '@/assets/icons/error_page/maintenance.svg'\nimport { ReactComponent as NoAccessSvg } from '@/assets/icons/error_page/no-access.svg'\nimport { ReactComponent as UnavailableSvg } from '@/assets/icons/error_page/unavailable.svg'\nimport { useSynapseContext } from '@/utils'\nimport { Box, Link, Typography } from '@mui/material'\nimport { useCallback, useMemo, useState } from 'react'\nimport SynapseObjectDOIInfo from './SynapseObjectDOIInfo'\nimport SendMessageToEntityOwnerDialog from './SendMessageToEntityOwnerDialog'\nimport { DoiObjectType } from '@sage-bionetworks/synapse-client/generated/models/DoiObjectType'\n\nexport type ErrorPageProps = {\n type: SynapseErrorType\n message?: string // custom message to report\n /** The ID of the object that was attempted to be retrieved, which may be used to show a 'tombstone' */\n id?: string\n /** The version of the object that was attempted to be retrieved, which may be used to show a 'tombstone' */\n version?: number\n /** The type of the object that was attempted to be retrieved, which may be used to show a 'tombstone' */\n objectType?: DoiObjectType\n /** If on a portal that may mint DOIs, this portal ID may be used to find a DOI to show a 'tombstone' */\n portalId?: string\n\n gotoPlace: (href: string) => void\n}\n\nexport const SYNAPSE_DOWN_TITLE = 'Synapse is down for maintenance.'\nexport const ACCESS_DENIED_TITLE = 'You don’t have permission to view this.'\nexport const NOT_FOUND_TITLE = 'This page isn’t available.'\nexport const LOG_IN_LINK_TEXT = 'Log in to Synapse'\nexport const CONTACT_US_LINK_TEXT = 'Contact us for more information'\nexport const CONTACT_ADMIN_LINK_TEXT = 'Contact the Administrator'\nexport const ACCESS_DENIED_ANONYMOUS_MESSAGE =\n 'Try logging in. If you still see this message after logging in, you have not been granted access to view this resource.'\nexport const ACCESS_DENIED_MESSAGE =\n 'This account has not been granted access to view this resource.'\nexport const NOT_FOUND_MESSAGE =\n 'The link you followed may be broken, or the page may have been removed.'\nexport const ACCESS_DENIED_ANONYMOUS_ACTION_DESCRIPTION =\n 'A Synapse account is free, and lets you view public resources.'\nexport const ACCESS_DENIED_CONTACT_ADMIN_ACTION_DESCRIPTION =\n 'Write a message to the owner of the resource asking for permission to view.'\n\nexport enum SynapseErrorType {\n DOWN = 'DOWN',\n ACCESS_DENIED = 'ACCESS_DENIED',\n NOT_FOUND = 'NOT_FOUND',\n}\n\nconst getImage = (type: SynapseErrorType) => {\n switch (type) {\n case SynapseErrorType.DOWN:\n return (\n <MaintenanceSvg\n role=\"img\"\n aria-label=\"Synapse is Down image\"\n title={SynapseErrorType.DOWN}\n />\n )\n case SynapseErrorType.ACCESS_DENIED:\n return (\n <NoAccessSvg\n role=\"img\"\n aria-label=\"Access denied image\"\n title={SynapseErrorType.ACCESS_DENIED}\n />\n )\n case SynapseErrorType.NOT_FOUND:\n return (\n <UnavailableSvg\n role=\"img\"\n aria-label=\"Resource not found image\"\n title={SynapseErrorType.NOT_FOUND}\n />\n )\n default:\n return <></>\n }\n}\nconst getTitle = (type: SynapseErrorType) => {\n switch (type) {\n case SynapseErrorType.DOWN:\n return SYNAPSE_DOWN_TITLE\n case SynapseErrorType.ACCESS_DENIED:\n return ACCESS_DENIED_TITLE\n case SynapseErrorType.NOT_FOUND:\n return NOT_FOUND_TITLE\n default:\n return ''\n }\n}\n\ntype ErrorPageAction = {\n linkText: string\n onClick: () => void\n description: string\n}\n\nfunction ErrorPage(props: ErrorPageProps) {\n const { type, message, gotoPlace, id, version, objectType, portalId } = props\n const [isSendMessageToAdminDialogOpen, setSendMessageToAdminDialogOpen] =\n useState<boolean>(false)\n const { isAuthenticated } = useSynapseContext()\n const image = useMemo(() => getImage(type), [type])\n const title = useMemo(() => getTitle(type), [type])\n\n const messages = useMemo(() => {\n const msgs: string[] = []\n switch (type) {\n case SynapseErrorType.ACCESS_DENIED:\n if (!isAuthenticated) {\n msgs.push(ACCESS_DENIED_ANONYMOUS_MESSAGE)\n } else {\n msgs.push(ACCESS_DENIED_MESSAGE)\n }\n break\n case SynapseErrorType.NOT_FOUND:\n msgs.push(NOT_FOUND_MESSAGE)\n break\n }\n if (message) {\n msgs.push(message)\n }\n return msgs\n }, [type, isAuthenticated, message])\n\n const actions = useMemo(() => {\n const acts: ErrorPageAction[] = []\n if (type === SynapseErrorType.ACCESS_DENIED) {\n if (!isAuthenticated) {\n acts.push({\n linkText: LOG_IN_LINK_TEXT,\n onClick: () => gotoPlace('/LoginPlace:0'),\n description: ACCESS_DENIED_ANONYMOUS_ACTION_DESCRIPTION,\n })\n } else if (id) {\n acts.push({\n linkText: CONTACT_US_LINK_TEXT,\n onClick: () =>\n window.open(\n 'https://sagebionetworks.jira.com/servicedesk/customer/portals',\n '_blank',\n ),\n description: '',\n })\n // SWC-7073: Remove ability to send a message to the admins until we have a better option for the majority of the cases (service desk, contact emails, ...)\n // acts.push({\n // linkText: CONTACT_ADMIN_LINK_TEXT,\n // onClick: () => setSendMessageToAdminDialogOpen(true),\n // description: ACCESS_DENIED_CONTACT_ADMIN_ACTION_DESCRIPTION,\n // })\n }\n }\n return acts\n }, [type, isAuthenticated, id, gotoPlace])\n\n const handleCloseDialog = useCallback(\n () => setSendMessageToAdminDialogOpen(false),\n [],\n )\n return (\n <>\n <Box\n sx={{\n display: { xs: 'flex', lg: 'grid' },\n columnGap: '80px',\n flexDirection: { xs: 'column', lg: undefined },\n gridTemplateColumns: { lg: '40% 60%' },\n }}\n >\n <Box\n sx={{\n justifySelf: 'end',\n alignSelf: 'center',\n '& svg': {\n height: '360px',\n maxWidth: '300px',\n },\n pt: '50px',\n pb: '50px',\n }}\n >\n {image}\n </Box>\n <Box\n sx={{\n justifySelf: 'start',\n alignSelf: 'center',\n display: 'flex',\n flexDirection: 'column',\n gap: '20px',\n m: { xs: '15px', lg: undefined },\n mr: { lg: '100px' },\n }}\n >\n <Typography\n sx={{ fontSize: '30px', fontWeight: 700, lineHeight: '36px' }}\n >\n {title}\n </Typography>\n {messages.map(message => {\n return (\n <Typography variant=\"body1\" key={message}>\n {message}\n </Typography>\n )\n })}\n {actions.map(action => {\n const { onClick, linkText, description } = action\n return (\n <Box key={linkText}>\n <Link sx={{ fontSize: '16px' }} onClick={onClick}>\n {linkText}\n </Link>\n <Typography variant=\"body1\">{description}</Typography>\n </Box>\n )\n })}\n {id && objectType && (\n <SynapseObjectDOIInfo\n id={id}\n version={version}\n type={objectType}\n portalId={portalId}\n />\n )}\n </Box>\n </Box>\n {id && objectType === DoiObjectType.ENTITY && (\n <SendMessageToEntityOwnerDialog\n isOpen={isSendMessageToAdminDialogOpen}\n onHide={handleCloseDialog}\n entityId={id}\n />\n )}\n </>\n )\n}\n\nexport default ErrorPage\n"],"mappings":"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"}
|
|
@@ -59,6 +59,10 @@ export * from './QueryContext';
|
|
|
59
59
|
export * from './QueryCount';
|
|
60
60
|
export * from './QueryWrapper';
|
|
61
61
|
export * from './QueryWrapperPlotNav';
|
|
62
|
+
export { SearchQueryWrapper } from './SearchQueryWrapper/SearchQueryWrapper';
|
|
63
|
+
export type { SearchQueryWrapperProps } from './SearchQueryWrapper/SearchQueryWrapper';
|
|
64
|
+
export { default as SearchQueryWrapperPlotNav, isSearchQueryWrapperPlotNavProps, } from './SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav';
|
|
65
|
+
export type { SearchQueryWrapperPlotNavProps } from './SearchQueryWrapperPlotNav/SearchQueryWrapperPlotNav';
|
|
62
66
|
export * from './RegisterPageLogoutPrompt';
|
|
63
67
|
export * from './RenderIfInView';
|
|
64
68
|
export * from './Resources';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"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"}
|