diff --git a/static.config.json b/static.config.json index 1b1a3242e..00c6b7c92 100644 --- a/static.config.json +++ b/static.config.json @@ -29,7 +29,8 @@ "ummC": "1.18.3", "ummS": "1.5.3", "ummT": "1.2.0", - "ummV": "1.9.0" + "ummV": "1.9.0", + "ummVis": "1.1.0" }, "ummJsonSchemaUrl": "http://json-schema.org/draft-07/schema#", "edl": { diff --git a/static/src/js/components/DraftList/DraftList.jsx b/static/src/js/components/DraftList/DraftList.jsx index 2cf34b4bb..c7ee99972 100644 --- a/static/src/js/components/DraftList/DraftList.jsx +++ b/static/src/js/components/DraftList/DraftList.jsx @@ -9,7 +9,6 @@ import Col from 'react-bootstrap/Col' import Row from 'react-bootstrap/Row' import { DATE_FORMAT } from '@/js/constants/dateFormat' -import conceptIdTypes from '@/js/constants/conceptIdTypes' import conceptTypeDraftsQueries from '@/js/constants/conceptTypeDraftsQueries' import constructDownloadableFile from '@/js/utils/constructDownloadableFile' import urlValueTypeToConceptTypeStringMap from '@/js/constants/urlValueToConceptStringMap' @@ -58,7 +57,7 @@ const DraftList = () => { let cellData = originalCellData - if (!cellData && draftType === conceptIdTypes.C) cellData = '' + if (!cellData && draftType === 'Collection') cellData = '' if (!cellData) cellData = '' return ( @@ -71,7 +70,7 @@ const DraftList = () => { const buildEllipsisTextCell = useCallback((originalCellData) => { let cellData = originalCellData - if (!cellData && draftType === conceptIdTypes.C) cellData = '' + if (!cellData && draftType === 'Collection') cellData = '' if (!cellData) cellData = '' return ( @@ -114,7 +113,23 @@ const DraftList = () => { dataAccessorFn: buildEllipsisTextCell } ] - const nonCollectionColumns = [ + + const visColumns = [ + { + dataKey: 'previewMetadata.name', + title: 'Name', + className: 'col-auto', + dataAccessorFn: buildPrimaryEllipsisLink + }, + { + dataKey: 'previewMetadata.title', + title: 'Long Name', + className: 'col-auto', + dataAccessorFn: buildEllipsisTextCell + } + ] + + const defaultColumns = [ { dataKey: 'ummMetadata.Name', title: 'Name', @@ -147,9 +162,18 @@ const DraftList = () => { } ] - const columns = draftType === conceptIdTypes.C - ? [...collectionColumns, ...commonColumns] - : [...nonCollectionColumns, ...commonColumns] + const getColumns = () => { + switch (draftType) { + case 'Collection': + return [...collectionColumns, ...commonColumns] + case 'Visualization': + return [...visColumns, ...commonColumns] + default: + return [...defaultColumns, ...commonColumns] + } + } + + const columns = getColumns() return ( diff --git a/static/src/js/components/DraftList/__tests__/DraftList.test.jsx b/static/src/js/components/DraftList/__tests__/DraftList.test.jsx index 37e97c989..24d216a8c 100644 --- a/static/src/js/components/DraftList/__tests__/DraftList.test.jsx +++ b/static/src/js/components/DraftList/__tests__/DraftList.test.jsx @@ -13,9 +13,16 @@ import constructDownloadableFile from '@/js/utils/constructDownloadableFile' import { GET_TOOL_DRAFTS } from '@/js/operations/queries/getToolDrafts' import { GET_COLLECTION_DRAFTS } from '@/js/operations/queries/getCollectionDrafts' +import { GET_VISUALIZATION_DRAFTS } from '@/js/operations/queries/getVisualizationDrafts' import ErrorBoundary from '@/js/components/ErrorBoundary/ErrorBoundary' +import { + mockCollectionDrafts, + mockToolDrafts, + mockVisualizationDrafts +} from './__mocks__/DraftListMocks' + import DraftList from '../DraftList' vi.mock('react-bootstrap/Placeholder', () => ({ default: vi.fn() })) @@ -27,124 +34,6 @@ vi.mock('react-router-dom', async () => ({ useParams: vi.fn().mockImplementation(() => ({ draftType: 'tools' })) })) -const mockToolDrafts = { - count: 3, - items: [ - { - conceptId: 'TD1200000092-MMT_2', - revisionDate: '2023-12-08T17:56:09.385Z', - revisionId: '1', - ummMetadata: { - Name: 'Tool TD1200000092 short name', - LongName: 'Tool TD1200000092 long name' - }, - name: 'Tool TD1200000092 short name', - previewMetadata: { - conceptId: 'TD1200000092-MMT_2', - revisionId: '1', - name: 'Tool TD1200000092 short name', - longName: 'Tool TD1200000092 long name', - __typename: 'Tool' - }, - providerId: 'MMT_2', - __typename: 'Draft' - }, - { - conceptId: 'TD1200000093-MMT_2', - revisionDate: '2023-11-08T17:56:09.385Z', - revisionId: '1', - ummMetadata: {}, - previewMetadata: { - conceptId: 'TD1200000093-MMT_2', - revisionId: '1', - name: null, - longName: null, - __typename: 'Tool' - }, - providerId: 'MMT_2', - __typename: 'Draft' - }, - { - conceptId: 'TD1200000094-MMT_2', - revisionDate: '2023-10-08T17:56:09.385Z', - revisionId: '1', - ummMetadata: { - Name: 'Tool TD1200000094 short name', - LongName: 'Tool TD1200000094 long name' - }, - previewMetadata: { - conceptId: 'TD1200000094-MMT_2', - revisionId: '1', - name: null, - longName: null, - __typename: 'Tool' - }, - providerId: 'MMT_2', - __typename: 'Draft' - } - ], - __typename: 'DraftList' -} - -const mockCollectionDrafts = { - count: 3, - items: [ - { - conceptId: 'CD1200000092-MMT_2', - revisionDate: '2023-12-08T17:56:09.385Z', - revisionId: '1', - ummMetadata: { - ShortName: 'Collection CD1200000092 short name', - EntryTitle: 'Collection CD1200000092 entry title' - }, - shortName: 'Collection CD1200000092 short name', - previewMetadata: { - conceptId: 'CD1200000092-MMT_2', - revisionId: '1', - shortName: 'Collection CD1200000092 short name', - entryTitle: 'Collection CD1200000092 entry title', - __typename: 'Collection' - }, - providerId: 'MMT_2', - __typename: 'Draft' - }, - { - conceptId: 'CD1200000093-MMT_2', - revisionDate: '2023-11-08T17:56:09.385Z', - revisionId: '1', - ummMetadata: {}, - previewMetadata: { - conceptId: 'CD1200000093-MMT_2', - revisionId: '1', - shortName: null, - entryTitle: null, - __typename: 'Collection' - }, - providerId: 'MMT_2', - __typename: 'Draft' - }, - { - conceptId: 'CD1200000094-MMT_2', - revisionDate: '2023-10-08T17:56:09.385Z', - revisionId: '1', - ummMetadata: { - ShortName: 'Collection CD1200000094 short name', - EntryTitle: 'Collection CD1200000094 entry title' - }, - previewMetadata: { - conceptId: 'CD1200000094-MMT_2', - revisionId: '1', - shortName: null, - entryTitle: null, - __typename: 'Collection' - }, - providerId: 'MMT_2', - __typename: 'Draft' - } - ], - __typename: 'DraftList' -} - const setup = ({ overrideMocks = false }) => { const mocks = [{ request: { @@ -335,4 +224,51 @@ describe('DraftList', () => { ) }) }) + + describe('when draft type Visualization is given', () => { + test('renders Visualization draft list', async () => { + useParams.mockImplementation(() => ({ draftType: 'visualizations' })) + + setup({ + overrideMocks: [{ + request: { + query: GET_VISUALIZATION_DRAFTS, + variables: { + params: { + conceptType: 'Visualization', + limit: 20, + offset: 0, + sortKey: ['-revision_date'] + } + } + }, + result: { + data: { + drafts: mockVisualizationDrafts + } + } + }] + }) + + const rows = await screen.findAllByRole('row') + + expect(within(rows[1]).getByRole('cell', { name: 'Short Name 1' })).toBeInTheDocument() + expect(within(rows[1]).getByRole('cell', { name: 'Long Name 1' })).toBeInTheDocument() + expect(within(rows[1]).getByRole('cell', { name: 'Friday, April 25, 2025 5:26 PM' })).toBeInTheDocument() + expect(within(rows[1]).getByRole('cell', { name: 'MMT_1' })).toBeInTheDocument() + expect(within(rows[1]).getByRole('button', { name: /Download JSON/ })).toBeInTheDocument() + + expect(within(rows[2]).getByRole('cell', { name: '' })).toBeInTheDocument() + expect(within(rows[2]).getByRole('cell', { name: '' })).toBeInTheDocument() + expect(within(rows[2]).getByRole('cell', { name: 'Thursday, May 15, 2025 10:30 AM' })).toBeInTheDocument() + expect(within(rows[2]).getByRole('cell', { name: 'MMT_1' })).toBeInTheDocument() + expect(within(rows[2]).getByRole('button', { name: /Download JSON/ })).toBeInTheDocument() + + expect(within(rows[3]).getByRole('cell', { name: 'Short Name 3' })).toBeInTheDocument() + expect(within(rows[3]).getByRole('cell', { name: 'Long Name 3' })).toBeInTheDocument() + expect(within(rows[3]).getByRole('cell', { name: 'Thursday, June 5, 2025 2:45 PM' })).toBeInTheDocument() + expect(within(rows[3]).getByRole('cell', { name: 'MMT_1' })).toBeInTheDocument() + expect(within(rows[3]).getByRole('button', { name: /Download JSON/ })).toBeInTheDocument() + }) + }) }) diff --git a/static/src/js/components/DraftList/__tests__/__mocks__/DraftListMocks.js b/static/src/js/components/DraftList/__tests__/__mocks__/DraftListMocks.js new file mode 100644 index 000000000..1b7103244 --- /dev/null +++ b/static/src/js/components/DraftList/__tests__/__mocks__/DraftListMocks.js @@ -0,0 +1,153 @@ +export const mockToolDrafts = { + count: 3, + items: [ + { + conceptId: 'TD1200000092-MMT_2', + revisionDate: '2023-12-08T17:56:09.385Z', + revisionId: '1', + ummMetadata: { + Name: 'Tool TD1200000092 short name', + LongName: 'Tool TD1200000092 long name' + }, + name: 'Tool TD1200000092 short name', + previewMetadata: { + conceptId: 'TD1200000092-MMT_2', + revisionId: '1', + name: 'Tool TD1200000092 short name', + longName: 'Tool TD1200000092 long name', + __typename: 'Tool' + }, + providerId: 'MMT_2', + __typename: 'Draft' + }, + { + conceptId: 'TD1200000093-MMT_2', + revisionDate: '2023-11-08T17:56:09.385Z', + revisionId: '1', + ummMetadata: {}, + previewMetadata: { + conceptId: 'TD1200000093-MMT_2', + revisionId: '1', + name: null, + longName: null, + __typename: 'Tool' + }, + providerId: 'MMT_2', + __typename: 'Draft' + }, + { + conceptId: 'TD1200000094-MMT_2', + revisionDate: '2023-10-08T17:56:09.385Z', + revisionId: '1', + ummMetadata: { + Name: 'Tool TD1200000094 short name', + LongName: 'Tool TD1200000094 long name' + }, + previewMetadata: { + conceptId: 'TD1200000094-MMT_2', + revisionId: '1', + name: null, + longName: null, + __typename: 'Tool' + }, + providerId: 'MMT_2', + __typename: 'Draft' + } + ], + __typename: 'DraftList' +} + +export const mockCollectionDrafts = { + count: 3, + items: [ + { + conceptId: 'CD1200000092-MMT_2', + revisionDate: '2023-12-08T17:56:09.385Z', + revisionId: '1', + ummMetadata: { + ShortName: 'Collection CD1200000092 short name', + EntryTitle: 'Collection CD1200000092 entry title' + }, + shortName: 'Collection CD1200000092 short name', + previewMetadata: { + conceptId: 'CD1200000092-MMT_2', + revisionId: '1', + shortName: 'Collection CD1200000092 short name', + entryTitle: 'Collection CD1200000092 entry title', + __typename: 'Collection' + }, + providerId: 'MMT_2', + __typename: 'Draft' + }, + { + conceptId: 'CD1200000093-MMT_2', + revisionDate: '2023-11-08T17:56:09.385Z', + revisionId: '1', + ummMetadata: {}, + previewMetadata: { + conceptId: 'CD1200000093-MMT_2', + revisionId: '1', + shortName: null, + entryTitle: null, + __typename: 'Collection' + }, + providerId: 'MMT_2', + __typename: 'Draft' + }, + { + conceptId: 'CD1200000094-MMT_2', + revisionDate: '2023-10-08T17:56:09.385Z', + revisionId: '1', + ummMetadata: { + ShortName: 'Collection CD1200000094 short name', + EntryTitle: 'Collection CD1200000094 entry title' + }, + previewMetadata: { + conceptId: 'CD1200000094-MMT_2', + revisionId: '1', + shortName: null, + entryTitle: null, + __typename: 'Collection' + }, + providerId: 'MMT_2', + __typename: 'Draft' + } + ], + __typename: 'DraftList' +} + +export const mockVisualizationDrafts = { + count: 3, + items: [ + { + conceptId: 'VISD1-MMT_1', + previewMetadata: { + conceptId: 'VISD1-MMT_1', + name: 'Short Name 1', + title: 'Long Name 1' + }, + providerId: 'MMT_1', + revisionDate: '2025-04-25T17:26:18.052Z' + }, + { + conceptId: 'VISD2-MMT_1', + previewMetadata: { + conceptId: 'VISD2-MMT_1', + name: '', + title: '' + }, + providerId: 'MMT_1', + revisionDate: '2025-05-15T10:30:00.000Z' + }, + { + conceptId: 'VISD3-MMT_1', + previewMetadata: { + conceptId: 'VISD3-MMT_1', + name: 'Short Name 3', + title: 'Long Name 3' + }, + providerId: 'MMT_1', + revisionDate: '2025-06-05T14:45:30.000Z' + } + ] +} diff --git a/static/src/js/components/Layout/Layout.jsx b/static/src/js/components/Layout/Layout.jsx index 3e19f590a..e6faaaeb0 100644 --- a/static/src/js/components/Layout/Layout.jsx +++ b/static/src/js/components/Layout/Layout.jsx @@ -44,7 +44,8 @@ const Layout = ({ className, displayNav }) => { ummC, ummS, ummT, - ummV + ummV, + ummVis } = getUmmVersionsConfig() const { env, displayProdWarning } = getApplicationConfig() @@ -189,6 +190,20 @@ const Layout = ({ className, displayNav }) => { } ] }, + { + title: 'Visualizations', + version: `v${ummVis}`, + children: [ + { + to: '/visualizations', + title: 'All Visualizations' + }, + { + to: '/drafts/visualizations', + title: 'Drafts' + } + ] + }, { title: 'Order Options', children: [ diff --git a/static/src/js/components/Layout/__tests__/Layout.test.jsx b/static/src/js/components/Layout/__tests__/Layout.test.jsx index ced5275eb..b352ab373 100644 --- a/static/src/js/components/Layout/__tests__/Layout.test.jsx +++ b/static/src/js/components/Layout/__tests__/Layout.test.jsx @@ -26,7 +26,8 @@ const setup = (loggedIn) => { ummC: 'mock-umm-c', ummS: 'mock-umm-s', ummT: 'mock-umm-t', - ummV: 'mock-umm-v' + ummV: 'mock-umm-v', + ummVis: 'mock-umm-vis' })) vi.setSystemTime('2024-01-01') @@ -156,6 +157,20 @@ describe('Layout component', () => { } ] }, + { + title: 'Visualizations', + version: 'vmock-umm-vis', + children: [ + { + title: 'All Visualizations', + to: '/visualizations' + }, + { + title: 'Drafts', + to: '/drafts/visualizations' + } + ] + }, { title: 'Order Options', children: [ @@ -276,6 +291,20 @@ describe('Layout component', () => { } ] }, + { + title: 'Visualizations', + version: 'vmock-umm-vis', + children: [ + { + title: 'All Visualizations', + to: '/visualizations' + }, + { + title: 'Drafts', + to: '/drafts/visualizations' + } + ] + }, { title: 'Order Options', children: [ diff --git a/static/src/js/constants/conceptTypeDraftsQueries.js b/static/src/js/constants/conceptTypeDraftsQueries.js index 613f6e01e..415c277d5 100644 --- a/static/src/js/constants/conceptTypeDraftsQueries.js +++ b/static/src/js/constants/conceptTypeDraftsQueries.js @@ -2,12 +2,14 @@ import { GET_SERVICE_DRAFTS } from '../operations/queries/getServiceDrafts' import { GET_TOOL_DRAFTS } from '../operations/queries/getToolDrafts' import { GET_VARIABLE_DRAFTS } from '../operations/queries/getVariableDrafts' import { GET_COLLECTION_DRAFTS } from '../operations/queries/getCollectionDrafts' +import { GET_VISUALIZATION_DRAFTS } from '../operations/queries/getVisualizationDrafts' const conceptTypeDraftsQueries = { Collection: GET_COLLECTION_DRAFTS, Service: GET_SERVICE_DRAFTS, Tool: GET_TOOL_DRAFTS, - Variable: GET_VARIABLE_DRAFTS + Variable: GET_VARIABLE_DRAFTS, + Visualization: GET_VISUALIZATION_DRAFTS } export default conceptTypeDraftsQueries diff --git a/static/src/js/constants/conceptTypeQueries.js b/static/src/js/constants/conceptTypeQueries.js index 48076ba6f..399005e8e 100644 --- a/static/src/js/constants/conceptTypeQueries.js +++ b/static/src/js/constants/conceptTypeQueries.js @@ -8,6 +8,7 @@ import { GET_TOOL } from '@/js/operations/queries/getTool' import { GET_TOOLS } from '@/js/operations/queries/getTools' import { GET_VARIABLE } from '@/js/operations/queries/getVariable' import { GET_VARIABLES } from '@/js/operations/queries/getVariables' +import { GET_VISUALIZATIONS } from '@/js/operations/queries/getVisualizations' const conceptTypeQueries = { Collection: GET_COLLECTION, @@ -19,7 +20,8 @@ const conceptTypeQueries = { Tool: GET_TOOL, Tools: GET_TOOLS, Variable: GET_VARIABLE, - Variables: GET_VARIABLES + Variables: GET_VARIABLES, + Visualizations: GET_VISUALIZATIONS } export default conceptTypeQueries diff --git a/static/src/js/constants/conceptTypes.js b/static/src/js/constants/conceptTypes.js index ef8347766..2e5420f9d 100644 --- a/static/src/js/constants/conceptTypes.js +++ b/static/src/js/constants/conceptTypes.js @@ -9,7 +9,8 @@ const conceptTypes = { Tool: 'Tool', Tools: 'Tools', Variable: 'Variable', - Variables: 'Variables' + Variables: 'Variables', + Visualizations: 'Visualizations' } export default conceptTypes diff --git a/static/src/js/constants/redirectsMap/redirectsMap.js b/static/src/js/constants/redirectsMap/redirectsMap.js index 154490bde..2c07b59d9 100644 --- a/static/src/js/constants/redirectsMap/redirectsMap.js +++ b/static/src/js/constants/redirectsMap/redirectsMap.js @@ -7,11 +7,13 @@ const REDIRECTS = { manage_variables: 'variables', manage_services: 'services', manage_tools: 'tools', + manage_visualizations: 'visualizations', manage_cmr: 'collections', tool_drafts: 'drafts/tools', service_drafts: 'drafts/services', collection_drafts: 'drafts/collections', - variable_drafts: 'drafts/variables' + variable_drafts: 'drafts/variables', + visualization_drafts: 'drafts/visualizations' } export default REDIRECTS diff --git a/static/src/js/constants/typeParamToHumanizedStringMap.js b/static/src/js/constants/typeParamToHumanizedStringMap.js index eb40ab50b..b26e1e145 100644 --- a/static/src/js/constants/typeParamToHumanizedStringMap.js +++ b/static/src/js/constants/typeParamToHumanizedStringMap.js @@ -2,7 +2,8 @@ const typeParamToHumanizedStringMap = { collections: 'collection', services: 'service', tools: 'tool', - variables: 'variable' + variables: 'variable', + visualizations: 'visualization' } export default typeParamToHumanizedStringMap diff --git a/static/src/js/constants/urlValueToConceptStringMap.js b/static/src/js/constants/urlValueToConceptStringMap.js index 4b3adc865..e70c04c31 100644 --- a/static/src/js/constants/urlValueToConceptStringMap.js +++ b/static/src/js/constants/urlValueToConceptStringMap.js @@ -3,7 +3,8 @@ const urlValueTypeToConceptTypeStringMap = { collections: 'Collection', tools: 'Tool', services: 'Service', - cmr: 'CMR' + cmr: 'CMR', + visualizations: 'Visualization' } export default urlValueTypeToConceptTypeStringMap diff --git a/static/src/js/operations/queries/getVisualizationDrafts.js b/static/src/js/operations/queries/getVisualizationDrafts.js new file mode 100644 index 000000000..710f99850 --- /dev/null +++ b/static/src/js/operations/queries/getVisualizationDrafts.js @@ -0,0 +1,22 @@ +import { gql } from '@apollo/client' + +export const GET_VISUALIZATION_DRAFTS = gql` + query VaisualizationDrafts($params: DraftsInput) { + drafts(params: $params) { + count + items { + conceptId + providerId + revisionDate + ummMetadata + previewMetadata { + ... on Visualization { + conceptId + name + title + } + } + } + } + } +` diff --git a/static/src/js/operations/queries/getVisualizations.js b/static/src/js/operations/queries/getVisualizations.js new file mode 100644 index 000000000..d8ded478c --- /dev/null +++ b/static/src/js/operations/queries/getVisualizations.js @@ -0,0 +1,17 @@ +import { gql } from '@apollo/client' + +export const GET_VISUALIZATIONS = gql` + query GetVisualizations($params: VisualizationsInput) { + visualizations(params: $params) { + count + items { + conceptId + revisionId + name + title + providerId + revisionDate + } + } + } +` diff --git a/static/src/js/pages/SearchList/SearchList.jsx b/static/src/js/pages/SearchList/SearchList.jsx index e63dd5778..bd6609aab 100644 --- a/static/src/js/pages/SearchList/SearchList.jsx +++ b/static/src/js/pages/SearchList/SearchList.jsx @@ -79,6 +79,15 @@ const SearchList = ({ limit }) => { } } + if (formattedType === conceptTypes.Visualizations) { + params = { + limit, + offset, + provider: providerParam, + sortKey: sortKeyParam + } + } + const { data } = useSuspenseQuery(conceptTypeQueries[formattedType], { variables: { params @@ -111,18 +120,28 @@ const SearchList = ({ limit }) => { const buildEllipsisLinkCell = useCallback((cellData, rowData) => { const { conceptId } = rowData + let newCellData = cellData + + if (!newCellData && conceptType === 'visualizations') newCellData = '' + return ( - {cellData} + {newCellData} ) }, [conceptType]) - const buildEllipsisTextCell = useCallback((cellData) => ( - - {cellData} - - ), []) + const buildEllipsisTextCell = useCallback((cellData) => { + let newCellData = cellData + + if (!newCellData && conceptType === 'visualizations') newCellData = '' + + return ( + + {newCellData} + + ) + }, []) const buildTagCell = useCallback((cellData, rowData) => { const tagCount = getTagCount(cellData) @@ -216,6 +235,42 @@ const SearchList = ({ limit }) => { ] } + if (formattedType === conceptTypes.Visualizations) { + return [ + { + className: 'col-auto', + dataAccessorFn: buildEllipsisLinkCell, + dataKey: 'name', + sortFn, + title: 'Short Name' + }, + { + className: 'col-auto', + dataAccessorFn: buildEllipsisTextCell, + dataKey: 'title', + // To be completed in MMT-4023 + // SortFn, + // sortKey: 'title', + title: 'Long Name' + }, + { + align: 'center', + className: 'col-auto text-nowrap', + dataKey: 'providerId', + sortFn, + title: 'Provider' + }, + { + align: 'end', + className: 'col-auto text-nowrap', + dataAccessorFn: (cellData) => moment.utc(cellData).format(DATE_FORMAT), + dataKey: 'revisionDate', + sortFn, + title: 'Last Modified (UTC)' + } + ] + } + return [ { className: 'col-auto', diff --git a/static/src/js/pages/SearchList/__tests__/SearchList.test.jsx b/static/src/js/pages/SearchList/__tests__/SearchList.test.jsx index cc8a42cb4..2adb76ef6 100644 --- a/static/src/js/pages/SearchList/__tests__/SearchList.test.jsx +++ b/static/src/js/pages/SearchList/__tests__/SearchList.test.jsx @@ -22,7 +22,8 @@ import { singlePageServicesSearch, singlePageToolsSearch, singlePageToolsSearchWithProvider, - singlePageVariablesSearch + singlePageVariablesSearch, + singlePageVisualizationsSearch } from './__mocks__/searchResults' import SearchList from '../SearchList' @@ -461,6 +462,54 @@ describe('SearchPage component', () => { }) }) + describe('when searching for visualizations', () => { + beforeEach(() => { + setup([singlePageVisualizationsSearch], {}, ['/visualizations']) + }) + + describe('while the request is loading', () => { + test('renders the headers', async () => { + expect(screen.getByText('Loading...')).toBeInTheDocument() + + const table = await screen.findByRole('table') + + const tableRows = within(table).getAllByRole('row') + + expect(tableRows.length).toEqual(3) + + expect(within(table).getAllByRole('columnheader')[1].textContent).toContain('Long Name') + expect(within(table).getAllByRole('columnheader')[2].textContent).toContain('Provider') + expect(within(table).getAllByRole('columnheader')[3].textContent).toContain('Last Modified') + }) + }) + + describe('when the request has loaded', () => { + test('renders the data', async () => { + expect(screen.getByText('Loading...')).toBeInTheDocument() + + const table = await screen.findByRole('table') + + const tableRows = within(table).getAllByRole('row') + + expect(tableRows.length).toEqual(3) + + const row1Cells = within(tableRows[1]).queryAllByRole('cell') + const row2Cells = within(tableRows[2]).queryAllByRole('cell') + + expect(row1Cells).toHaveLength(4) + expect(row1Cells[0].textContent).toBe('Visualization Name 1') + expect(row1Cells[1].textContent).toBe('Visualization Long Name 1') + expect(row1Cells[2].textContent).toBe('TESTPROV') + expect(row1Cells[3].textContent).toBe('Monday, April 28, 2025 3:13 PM') + expect(row2Cells).toHaveLength(4) + expect(row2Cells[0].textContent).toBe('') + expect(row2Cells[1].textContent).toBe('') + expect(row2Cells[2].textContent).toBe('TESTPROV') + expect(row2Cells[3].textContent).toBe('Monday, April 28, 2025 3:13 PM') + }) + }) + }) + describe('when a provider is defined', () => { beforeEach(() => { setup([singlePageToolsSearchWithProvider], {}, ['/tools?provider=TESTPROV']) diff --git a/static/src/js/pages/SearchList/__tests__/__mocks__/searchResults.js b/static/src/js/pages/SearchList/__tests__/__mocks__/searchResults.js index b013cbc11..8faf2d853 100644 --- a/static/src/js/pages/SearchList/__tests__/__mocks__/searchResults.js +++ b/static/src/js/pages/SearchList/__tests__/__mocks__/searchResults.js @@ -1,8 +1,9 @@ +import { GET_COLLECTIONS } from '@/js/operations/queries/getCollections' +import { GET_SERVICES } from '@/js/operations/queries/getServices' +import { GET_TOOLS } from '@/js/operations/queries/getTools' +import { GET_VARIABLES } from '@/js/operations/queries/getVariables' +import { GET_VISUALIZATIONS } from '@/js/operations/queries/getVisualizations' import { GraphQLError } from 'graphql' -import { GET_COLLECTIONS } from '../../../../operations/queries/getCollections' -import { GET_SERVICES } from '../../../../operations/queries/getServices' -import { GET_VARIABLES } from '../../../../operations/queries/getVariables' -import { GET_TOOLS } from '../../../../operations/queries/getTools' export const singlePageCollectionSearch = { request: { @@ -784,3 +785,42 @@ export const singlePageToolsSearchWithProvider = { } } } + +export const singlePageVisualizationsSearch = { + request: { + query: GET_VISUALIZATIONS, + variables: { + params: { + limit: 25, + offset: 0, + provider: null, + sortKey: null + } + } + }, + result: { + data: { + visualizations: { + count: 2, + items: [ + { + conceptId: 'VIS000000001-TESTPROV', + name: 'Visualization Name 1', + title: 'Visualization Long Name 1', + providerId: 'TESTPROV', + revisionId: '1', + revisionDate: '2025-04-28T15:13:10.461Z' + }, + { + conceptId: 'VIS000000002-TESTPROV', + name: '', + title: '', + providerId: 'TESTPROV', + revisionId: '1', + revisionDate: '2025-04-28T15:13:10.461Z' + } + ] + } + } + } +} diff --git a/static/src/js/pages/SearchPage/SearchPage.jsx b/static/src/js/pages/SearchPage/SearchPage.jsx index c560e5c8b..094a74136 100644 --- a/static/src/js/pages/SearchPage/SearchPage.jsx +++ b/static/src/js/pages/SearchPage/SearchPage.jsx @@ -209,6 +209,18 @@ const SearchBar = () => { * * ) */ + +// Remove this in MMT-4023 +const renderSearchBar = () => { + const { type: searchTypeFromPath } = useParams() + // Don't render SearchBar for Visualizations + if (searchTypeFromPath.toLowerCase() === 'visualizations') { + return null + } + + return +} + const SearchPageHeader = () => { const { type: conceptType } = useParams() @@ -216,9 +228,7 @@ const SearchPageHeader = () => { - )} + beforeActions={renderSearchBar()} breadcrumbs={ [ {