From 6af18e54b9b6a07f859de7ac6b6d034b5f0a0280 Mon Sep 17 00:00:00 2001 From: MellyGray Date: Thu, 16 Nov 2023 12:41:24 +0100 Subject: [PATCH 01/27] feat(Home): add list of datasets --- merged-coverage/lcov.info | 2 +- public/locales/en/helloDataverse.json | 6 ---- public/locales/en/home.json | 3 ++ src/Router.tsx | 4 +-- .../HelloDataverse.module.scss | 26 ----------------- .../hello-dataverse/HelloDataverse.tsx | 24 --------------- src/sections/home/Home.module.scss | 17 +++++++++++ src/sections/home/Home.tsx | 29 +++++++++++++++++++ .../HelloDataverse.stories.tsx | 17 ----------- src/stories/home/Home.stories.tsx | 17 +++++++++++ .../hello-dataverse/HelloDataverse.spec.tsx | 8 ----- tests/component/sections/home/Home.spec.tsx | 8 +++++ .../Home.spec.ts} | 2 +- 13 files changed, 78 insertions(+), 85 deletions(-) delete mode 100644 public/locales/en/helloDataverse.json create mode 100644 public/locales/en/home.json delete mode 100644 src/sections/hello-dataverse/HelloDataverse.module.scss delete mode 100644 src/sections/hello-dataverse/HelloDataverse.tsx create mode 100644 src/sections/home/Home.module.scss create mode 100644 src/sections/home/Home.tsx delete mode 100644 src/stories/hello-dataverse/HelloDataverse.stories.tsx create mode 100644 src/stories/home/Home.stories.tsx delete mode 100644 tests/component/sections/hello-dataverse/HelloDataverse.spec.tsx create mode 100644 tests/component/sections/home/Home.spec.tsx rename tests/e2e-integration/e2e/sections/{hello-dataverse/HelloDataverse.spec.ts => home/Home.spec.ts} (94%) diff --git a/merged-coverage/lcov.info b/merged-coverage/lcov.info index 9c8729e8c..8d7a2182a 100644 --- a/merged-coverage/lcov.info +++ b/merged-coverage/lcov.info @@ -7,7 +7,7 @@ DA:5,108 BRDA:1,0,0,108 BRDA:1,0,1,108 end_of_record -SF:src/sections/hello-dataverse/HelloDataverse.tsx +SF:src/sections/hello-dataverse/Home.tsx DA:5,76 DA:6,76 DA:8,38 diff --git a/public/locales/en/helloDataverse.json b/public/locales/en/helloDataverse.json deleted file mode 100644 index 8c947e521..000000000 --- a/public/locales/en/helloDataverse.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "title": "Hello Dataverse", - "linkText": "Dataverse", - "description": "Edit <1>src/sections/hello-dataverse/HelloDataverse.tsx and save to reload.", - "altImage": "Dataverse logo" -} diff --git a/public/locales/en/home.json b/public/locales/en/home.json new file mode 100644 index 000000000..05fb1e2e2 --- /dev/null +++ b/public/locales/en/home.json @@ -0,0 +1,3 @@ +{ + "title": "Hello Dataverse" +} diff --git a/src/Router.tsx b/src/Router.tsx index 38d016834..16470fa31 100644 --- a/src/Router.tsx +++ b/src/Router.tsx @@ -1,5 +1,5 @@ import { createBrowserRouter, RouterProvider } from 'react-router-dom' -import { HelloDataverse } from './sections/hello-dataverse/HelloDataverse' +import { Home } from './sections/home/Home' import { Layout } from './sections/layout/Layout' import { Route } from './sections/Route.enum' import { DatasetFactory } from './sections/dataset/DatasetFactory' @@ -12,7 +12,7 @@ const router = createBrowserRouter( children: [ { path: Route.HOME, - element: + element: }, { path: `${Route.DATASETS}`, diff --git a/src/sections/hello-dataverse/HelloDataverse.module.scss b/src/sections/hello-dataverse/HelloDataverse.module.scss deleted file mode 100644 index 505b1cb9c..000000000 --- a/src/sections/hello-dataverse/HelloDataverse.module.scss +++ /dev/null @@ -1,26 +0,0 @@ -@import "node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/colors.module"; -@import "src/sections/assets/variables"; - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-height: $body-available-height; - font-size: calc(10px + 2vmin); - text-align: center; -} - -.title { - color: $dv-brand-color; -} - -.logo { - height: 40vmin; - pointer-events: none; -} - -.link { - color: $dv-link-color; -} - diff --git a/src/sections/hello-dataverse/HelloDataverse.tsx b/src/sections/hello-dataverse/HelloDataverse.tsx deleted file mode 100644 index e955d0e66..000000000 --- a/src/sections/hello-dataverse/HelloDataverse.tsx +++ /dev/null @@ -1,24 +0,0 @@ -import logo from '../assets/logo.svg' -import styles from './HelloDataverse.module.scss' -import { Trans, useTranslation } from 'react-i18next' - -export function HelloDataverse() { - const { t } = useTranslation('helloDataverse') - - return ( -
-

{t('title')}

- {t('altImage')} -

- }} /> -

- - {t('linkText')} - -
- ) -} diff --git a/src/sections/home/Home.module.scss b/src/sections/home/Home.module.scss new file mode 100644 index 000000000..51e2f9ef9 --- /dev/null +++ b/src/sections/home/Home.module.scss @@ -0,0 +1,17 @@ +@import "node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/colors.module"; +@import "node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/typography.module"; +@import "src/sections/assets/variables"; + +.container { + padding:15px; + border: 1px solid #ddd; + border-radius: 4px; +} + +.title { + color: $dv-brand-color; +} + +.results { + font-weight: $dv-font-weight-bold; +} \ No newline at end of file diff --git a/src/sections/home/Home.tsx b/src/sections/home/Home.tsx new file mode 100644 index 000000000..3dad156fc --- /dev/null +++ b/src/sections/home/Home.tsx @@ -0,0 +1,29 @@ +import styles from './Home.module.scss' +import { Row } from '@iqss/dataverse-design-system' +import { useTranslation } from 'react-i18next' + +export function Home() { + const { t } = useTranslation('home') + + return ( + +
+

{t('title')}

+
+
+
+

1 to 10 of 41 Results

+
+ + + +
+
+ ) +} diff --git a/src/stories/hello-dataverse/HelloDataverse.stories.tsx b/src/stories/hello-dataverse/HelloDataverse.stories.tsx deleted file mode 100644 index f95572055..000000000 --- a/src/stories/hello-dataverse/HelloDataverse.stories.tsx +++ /dev/null @@ -1,17 +0,0 @@ -import type { Meta, StoryObj } from '@storybook/react' -import { HelloDataverse } from '../../sections/hello-dataverse/HelloDataverse' -import { WithI18next } from '../WithI18next' -import { WithLayout } from '../WithLayout' - -const meta: Meta = { - title: 'Pages/Hello Dataverse', - component: HelloDataverse, - decorators: [WithI18next, WithLayout] -} - -export default meta -type Story = StoryObj - -export const Default: Story = { - render: () => -} diff --git a/src/stories/home/Home.stories.tsx b/src/stories/home/Home.stories.tsx new file mode 100644 index 000000000..dd2702d60 --- /dev/null +++ b/src/stories/home/Home.stories.tsx @@ -0,0 +1,17 @@ +import type { Meta, StoryObj } from '@storybook/react' +import { Home } from '../../sections/home/Home' +import { WithI18next } from '../WithI18next' +import { WithLayout } from '../WithLayout' + +const meta: Meta = { + title: 'Pages/Home', + component: Home, + decorators: [WithI18next, WithLayout] +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + render: () => +} diff --git a/tests/component/sections/hello-dataverse/HelloDataverse.spec.tsx b/tests/component/sections/hello-dataverse/HelloDataverse.spec.tsx deleted file mode 100644 index 7e1668691..000000000 --- a/tests/component/sections/hello-dataverse/HelloDataverse.spec.tsx +++ /dev/null @@ -1,8 +0,0 @@ -import { HelloDataverse } from '../../../../src/sections/hello-dataverse/HelloDataverse' - -describe('HelloDataverse page', () => { - it('renders hello dataverse title', () => { - cy.customMount() - cy.findByRole('heading').should('contain.text', 'Hello Dataverse') - }) -}) diff --git a/tests/component/sections/home/Home.spec.tsx b/tests/component/sections/home/Home.spec.tsx new file mode 100644 index 000000000..f88ac210c --- /dev/null +++ b/tests/component/sections/home/Home.spec.tsx @@ -0,0 +1,8 @@ +import { Home } from '../../../../src/sections/home/Home' + +describe('Home page', () => { + it('renders hello dataverse title', () => { + cy.customMount() + cy.findByRole('heading').should('contain.text', 'Hello Dataverse') + }) +}) diff --git a/tests/e2e-integration/e2e/sections/hello-dataverse/HelloDataverse.spec.ts b/tests/e2e-integration/e2e/sections/home/Home.spec.ts similarity index 94% rename from tests/e2e-integration/e2e/sections/hello-dataverse/HelloDataverse.spec.ts rename to tests/e2e-integration/e2e/sections/home/Home.spec.ts index 4e364a2ea..80c80d60f 100644 --- a/tests/e2e-integration/e2e/sections/hello-dataverse/HelloDataverse.spec.ts +++ b/tests/e2e-integration/e2e/sections/home/Home.spec.ts @@ -1,4 +1,4 @@ -describe('Hello Dataverse', () => { +describe('Home Page', () => { it('successfully loads', () => { cy.visit('/spa') cy.findAllByText(/Hello Dataverse/i).should('exist') From b0b43f95e34a41258019fda9bc8871ac0a5c99cb Mon Sep 17 00:00:00 2001 From: MellyGray Date: Thu, 16 Nov 2023 16:26:51 +0100 Subject: [PATCH 02/27] feat(Home): connect the datasets list to the use case --- src/Router.tsx | 4 +- .../domain/repositories/DatasetRepository.ts | 1 + src/dataset/domain/useCases/getDatasets.ts | 8 ++++ .../DatasetJSDataverseRepository.ts | 10 +++++ src/sections/home/Home.tsx | 23 +++++++----- src/sections/home/HomeFactory.tsx | 10 +++++ src/sections/home/useDatasets.tsx | 28 ++++++++++++++ src/stories/dataset/DatasetMockRepository.ts | 37 +++++++++++++++++++ src/stories/dataset/WithDataset.tsx | 17 +-------- src/stories/home/Home.stories.tsx | 3 +- .../dataset/domain/models/DatasetMother.ts | 4 ++ tests/component/sections/home/Home.spec.tsx | 20 +++++++++- 12 files changed, 136 insertions(+), 29 deletions(-) create mode 100644 src/dataset/domain/useCases/getDatasets.ts create mode 100644 src/sections/home/HomeFactory.tsx create mode 100644 src/sections/home/useDatasets.tsx create mode 100644 src/stories/dataset/DatasetMockRepository.ts diff --git a/src/Router.tsx b/src/Router.tsx index 16470fa31..286a80f63 100644 --- a/src/Router.tsx +++ b/src/Router.tsx @@ -1,8 +1,8 @@ import { createBrowserRouter, RouterProvider } from 'react-router-dom' -import { Home } from './sections/home/Home' import { Layout } from './sections/layout/Layout' import { Route } from './sections/Route.enum' import { DatasetFactory } from './sections/dataset/DatasetFactory' +import { HomeFactory } from './sections/home/HomeFactory' const router = createBrowserRouter( [ @@ -12,7 +12,7 @@ const router = createBrowserRouter( children: [ { path: Route.HOME, - element: + element: HomeFactory.create() }, { path: `${Route.DATASETS}`, diff --git a/src/dataset/domain/repositories/DatasetRepository.ts b/src/dataset/domain/repositories/DatasetRepository.ts index a836e867b..dab6f535e 100644 --- a/src/dataset/domain/repositories/DatasetRepository.ts +++ b/src/dataset/domain/repositories/DatasetRepository.ts @@ -3,4 +3,5 @@ import { Dataset } from '../models/Dataset' export interface DatasetRepository { getByPersistentId: (persistentId: string, version?: string) => Promise getByPrivateUrlToken: (privateUrlToken: string) => Promise + getAll: () => Promise } diff --git a/src/dataset/domain/useCases/getDatasets.ts b/src/dataset/domain/useCases/getDatasets.ts new file mode 100644 index 000000000..e3afc87f4 --- /dev/null +++ b/src/dataset/domain/useCases/getDatasets.ts @@ -0,0 +1,8 @@ +import { DatasetRepository } from '../repositories/DatasetRepository' +import { Dataset } from '../models/Dataset' + +export async function getDatasets(datasetRepository: DatasetRepository): Promise { + return datasetRepository.getAll().catch((error: Error) => { + throw new Error(error.message) + }) +} diff --git a/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts b/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts index c3fc7fbf0..7592cb7e8 100644 --- a/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts +++ b/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts @@ -10,8 +10,18 @@ import { ReadError } from '@iqss/dataverse-client-javascript' import { JSDatasetMapper } from '../mappers/JSDatasetMapper' +import { DatasetMother } from '../../../../tests/component/dataset/domain/models/DatasetMother' export class DatasetJSDataverseRepository implements DatasetRepository { + getAll(): Promise { + // TODO - Implement using the js-dataverse-client + return new Promise((resolve) => { + setTimeout(() => { + resolve(DatasetMother.createMany(200)) + }, 1000) + }) + } + getByPersistentId( persistentId: string, version?: string, diff --git a/src/sections/home/Home.tsx b/src/sections/home/Home.tsx index 3dad156fc..706e11767 100644 --- a/src/sections/home/Home.tsx +++ b/src/sections/home/Home.tsx @@ -1,9 +1,16 @@ import styles from './Home.module.scss' import { Row } from '@iqss/dataverse-design-system' import { useTranslation } from 'react-i18next' +import { useDatasets } from './useDatasets' +import { DatasetRepository } from '../../dataset/domain/repositories/DatasetRepository' -export function Home() { +interface HomeProps { + datasetRepository: DatasetRepository +} + +export function Home({ datasetRepository }: HomeProps) { const { t } = useTranslation('home') + const { datasets } = useDatasets(datasetRepository) return ( @@ -14,15 +21,11 @@ export function Home() {

1 to 10 of 41 Results

- - - + {datasets.map((dataset) => ( + + ))}
) diff --git a/src/sections/home/HomeFactory.tsx b/src/sections/home/HomeFactory.tsx new file mode 100644 index 000000000..f37a69caa --- /dev/null +++ b/src/sections/home/HomeFactory.tsx @@ -0,0 +1,10 @@ +import { ReactElement } from 'react' +import { Home } from './Home' +import { DatasetJSDataverseRepository } from '../../dataset/infrastructure/repositories/DatasetJSDataverseRepository' + +const datasetRepository = new DatasetJSDataverseRepository() +export class HomeFactory { + static create(): ReactElement { + return + } +} diff --git a/src/sections/home/useDatasets.tsx b/src/sections/home/useDatasets.tsx new file mode 100644 index 000000000..8a370b5ae --- /dev/null +++ b/src/sections/home/useDatasets.tsx @@ -0,0 +1,28 @@ +import { useEffect, useState } from 'react' +import { DatasetRepository } from '../../dataset/domain/repositories/DatasetRepository' +import { Dataset } from '../../dataset/domain/models/Dataset' +import { getDatasets } from '../../dataset/domain/useCases/getDatasets' + +export function useDatasets(datasetRepository: DatasetRepository) { + const [datasets, setDatasets] = useState([]) + const [isLoading, setIsLoading] = useState(true) + + useEffect(() => { + setIsLoading(true) + + getDatasets(datasetRepository) + .then((datasets: Dataset[]) => { + setDatasets(datasets) + return datasets + }) + .catch(() => { + console.error('There was an error getting the datasets') + setIsLoading(false) + }) + }, [datasetRepository]) + + return { + datasets, + isLoading + } +} diff --git a/src/stories/dataset/DatasetMockRepository.ts b/src/stories/dataset/DatasetMockRepository.ts new file mode 100644 index 000000000..561397605 --- /dev/null +++ b/src/stories/dataset/DatasetMockRepository.ts @@ -0,0 +1,37 @@ +import { Dataset } from '../../dataset/domain/models/Dataset' +import { DatasetRepository } from '../../dataset/domain/repositories/DatasetRepository' +import { DatasetMother } from '../../../tests/component/dataset/domain/models/DatasetMother' + +export class DatasetMockRepository implements DatasetRepository { + // eslint-disable-next-line unused-imports/no-unused-vars + getAll(): Promise { + return new Promise((resolve) => { + setTimeout(() => { + resolve(DatasetMother.createMany(200)) + }, 1000) + }) + } + + getByPersistentId( + // eslint-disable-next-line unused-imports/no-unused-vars + persistentId: string, + // eslint-disable-next-line unused-imports/no-unused-vars + version?: string | undefined + ): Promise { + return new Promise((resolve) => { + setTimeout(() => { + resolve(DatasetMother.createRealistic()) + }, 1000) + }) + } + getByPrivateUrlToken( + // eslint-disable-next-line unused-imports/no-unused-vars + privateUrlToken: string + ): Promise { + return new Promise((resolve) => { + setTimeout(() => { + resolve(DatasetMother.createRealistic()) + }, 1000) + }) + } +} diff --git a/src/stories/dataset/WithDataset.tsx b/src/stories/dataset/WithDataset.tsx index 6c1df0ddf..b559c9532 100644 --- a/src/stories/dataset/WithDataset.tsx +++ b/src/stories/dataset/WithDataset.tsx @@ -1,23 +1,10 @@ import { StoryFn } from '@storybook/react' import { DatasetProvider } from '../../sections/dataset/DatasetProvider' import { DatasetRepository } from '../../dataset/domain/repositories/DatasetRepository' -import { Dataset } from '../../dataset/domain/models/Dataset' -import { DatasetMother } from '../../../tests/component/dataset/domain/models/DatasetMother' +import { DatasetMockRepository } from './DatasetMockRepository' export const WithDataset = (Story: StoryFn) => { - const datasetRepository = {} as DatasetRepository - datasetRepository.getByPersistentId = ( - // eslint-disable-next-line unused-imports/no-unused-vars - persistentId: string, - // eslint-disable-next-line unused-imports/no-unused-vars - version?: string | undefined - ): Promise => { - return new Promise((resolve) => { - setTimeout(() => { - resolve(DatasetMother.createRealistic()) - }, 1000) - }) - } + const datasetRepository: DatasetRepository = new DatasetMockRepository() return ( = { title: 'Pages/Home', @@ -13,5 +14,5 @@ export default meta type Story = StoryObj export const Default: Story = { - render: () => + render: () => } diff --git a/tests/component/dataset/domain/models/DatasetMother.ts b/tests/component/dataset/domain/models/DatasetMother.ts index bca8773c5..da2642ce3 100644 --- a/tests/component/dataset/domain/models/DatasetMother.ts +++ b/tests/component/dataset/domain/models/DatasetMother.ts @@ -190,6 +190,10 @@ export class DatasetMother { return undefined } + static createMany(count: number): Dataset[] { + return Array.from({ length: count }, () => this.create()) + } + static create(props?: Partial): Dataset { const dataset = { persistentId: faker.datatype.uuid(), diff --git a/tests/component/sections/home/Home.spec.tsx b/tests/component/sections/home/Home.spec.tsx index f88ac210c..efc76cf76 100644 --- a/tests/component/sections/home/Home.spec.tsx +++ b/tests/component/sections/home/Home.spec.tsx @@ -1,8 +1,26 @@ import { Home } from '../../../../src/sections/home/Home' +import { DatasetRepository } from '../../../../src/dataset/domain/repositories/DatasetRepository' +import { DatasetMother } from '../../dataset/domain/models/DatasetMother' +const datasetRepository: DatasetRepository = {} as DatasetRepository +const datasets = DatasetMother.createMany(10) describe('Home page', () => { + beforeEach(() => { + datasetRepository.getAll = cy.stub().resolves(datasets) + }) + it('renders hello dataverse title', () => { - cy.customMount() + cy.customMount() cy.findByRole('heading').should('contain.text', 'Hello Dataverse') }) + + it('renders the datasets list', () => { + cy.customMount() + + cy.wrap(datasetRepository.getAll).should('be.calledOnce') + + datasets.forEach((dataset) => { + cy.findByText(dataset.getTitle()).should('exist') + }) + }) }) From cd2bb71e9cf8e4a366aee4f6f595ad219dcaccf4 Mon Sep 17 00:00:00 2001 From: MellyGray Date: Thu, 16 Nov 2023 16:59:24 +0100 Subject: [PATCH 03/27] feat(Home): refactor datasets list --- src/sections/home/Home.tsx | 14 ++--------- .../home/datasets-list/DatasetsList.tsx | 23 +++++++++++++++++++ .../datasets-list/DatasetsList.stories.tsx | 18 +++++++++++++++ .../home/datasets-list/DatasetsList.spec.tsx | 23 +++++++++++++++++++ 4 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 src/sections/home/datasets-list/DatasetsList.tsx create mode 100644 src/stories/home/datasets-list/DatasetsList.stories.tsx create mode 100644 tests/component/sections/home/datasets-list/DatasetsList.spec.tsx diff --git a/src/sections/home/Home.tsx b/src/sections/home/Home.tsx index 706e11767..f8e94915e 100644 --- a/src/sections/home/Home.tsx +++ b/src/sections/home/Home.tsx @@ -1,8 +1,8 @@ import styles from './Home.module.scss' import { Row } from '@iqss/dataverse-design-system' import { useTranslation } from 'react-i18next' -import { useDatasets } from './useDatasets' import { DatasetRepository } from '../../dataset/domain/repositories/DatasetRepository' +import { DatasetsList } from './datasets-list/DatasetsList' interface HomeProps { datasetRepository: DatasetRepository @@ -10,23 +10,13 @@ interface HomeProps { export function Home({ datasetRepository }: HomeProps) { const { t } = useTranslation('home') - const { datasets } = useDatasets(datasetRepository) return (

{t('title')}

-
-
-

1 to 10 of 41 Results

-
- {datasets.map((dataset) => ( - - ))} -
+
) } diff --git a/src/sections/home/datasets-list/DatasetsList.tsx b/src/sections/home/datasets-list/DatasetsList.tsx new file mode 100644 index 000000000..2cc9ba1e9 --- /dev/null +++ b/src/sections/home/datasets-list/DatasetsList.tsx @@ -0,0 +1,23 @@ +import { useDatasets } from '../useDatasets' +import styles from '../Home.module.scss' +import { DatasetRepository } from '../../../dataset/domain/repositories/DatasetRepository' + +interface DatasetsListProps { + datasetRepository: DatasetRepository +} +export function DatasetsList({ datasetRepository }: DatasetsListProps) { + const { datasets } = useDatasets(datasetRepository) + + return ( +
+
+

1 to 10 of 41 Results

+
+ {datasets.map((dataset) => ( + + ))} +
+ ) +} diff --git a/src/stories/home/datasets-list/DatasetsList.stories.tsx b/src/stories/home/datasets-list/DatasetsList.stories.tsx new file mode 100644 index 000000000..b12cec54e --- /dev/null +++ b/src/stories/home/datasets-list/DatasetsList.stories.tsx @@ -0,0 +1,18 @@ +import { Meta, StoryObj } from '@storybook/react' +import { Home } from '../../../sections/home/Home' +import { WithI18next } from '../../WithI18next' +import { DatasetMockRepository } from '../../dataset/DatasetMockRepository' +import { DatasetsList } from '../../../sections/home/datasets-list/DatasetsList' + +const meta: Meta = { + title: 'Sections/Home/DatasetsList', + component: Home, + decorators: [WithI18next] +} + +export default meta +type Story = StoryObj + +export const Default: Story = { + render: () => +} diff --git a/tests/component/sections/home/datasets-list/DatasetsList.spec.tsx b/tests/component/sections/home/datasets-list/DatasetsList.spec.tsx new file mode 100644 index 000000000..4c523a931 --- /dev/null +++ b/tests/component/sections/home/datasets-list/DatasetsList.spec.tsx @@ -0,0 +1,23 @@ +import { DatasetRepository } from '../../../../../src/dataset/domain/repositories/DatasetRepository' +import { DatasetMother } from '../../../dataset/domain/models/DatasetMother' +import { DatasetsList } from '../../../../../src/sections/home/datasets-list/DatasetsList' + +const datasetRepository: DatasetRepository = {} as DatasetRepository +const datasets = DatasetMother.createMany(10) +describe('Datasets List', () => { + beforeEach(() => { + datasetRepository.getAll = cy.stub().resolves(datasets) + }) + + it('renders the datasets list', () => { + cy.customMount() + + cy.wrap(datasetRepository.getAll).should('be.calledOnce') + + datasets.forEach((dataset) => { + cy.findByRole('link', { name: dataset.getTitle() }) + .should('exist') + .should('have.attr', 'href', `/datasets?persistentId=${dataset.persistentId}`) + }) + }) +}) From 9222e4d2aabb35645637bb16a68e5ee2cbb82e66 Mon Sep 17 00:00:00 2001 From: MellyGray Date: Fri, 17 Nov 2023 12:15:56 +0100 Subject: [PATCH 04/27] refactor: get dataset title --- src/dataset/domain/models/Dataset.ts | 2 +- src/sections/dataset/Dataset.tsx | 4 ++-- src/sections/home/datasets-list/DatasetsList.tsx | 2 +- .../dataset-citation/DatasetCitation.stories.tsx | 10 +++++----- tests/component/sections/dataset/Dataset.spec.tsx | 6 +++--- .../sections/dataset/DatasetProvider.spec.tsx | 8 ++++---- tests/component/sections/home/Home.spec.tsx | 2 +- .../sections/home/datasets-list/DatasetsList.spec.tsx | 2 +- .../datasets/DatasetJSDataverseRepository.spec.ts | 8 ++++---- 9 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/dataset/domain/models/Dataset.ts b/src/dataset/domain/models/Dataset.ts index 409a7ab5e..532d22acf 100644 --- a/src/dataset/domain/models/Dataset.ts +++ b/src/dataset/domain/models/Dataset.ts @@ -299,7 +299,7 @@ export class Dataset { public readonly privateUrl?: PrivateUrl ) {} - public getTitle(): string { + public get title(): string { return this.metadataBlocks[0].fields.title } diff --git a/src/sections/dataset/Dataset.tsx b/src/sections/dataset/Dataset.tsx index c5444efb3..64eecc69e 100644 --- a/src/sections/dataset/Dataset.tsx +++ b/src/sections/dataset/Dataset.tsx @@ -47,14 +47,14 @@ export function Dataset({ fileRepository }: DatasetProps) {
-

{dataset.getTitle()}

+

{dataset.title}

{datasets.map((dataset) => ( ))} diff --git a/src/stories/dataset/dataset-citation/DatasetCitation.stories.tsx b/src/stories/dataset/dataset-citation/DatasetCitation.stories.tsx index dc89d2f59..fcbf35dd0 100644 --- a/src/stories/dataset/dataset-citation/DatasetCitation.stories.tsx +++ b/src/stories/dataset/dataset-citation/DatasetCitation.stories.tsx @@ -22,7 +22,7 @@ export const Default: Story = {



@@ -40,7 +40,7 @@ export const WithThumbnail: Story = {






@@ -105,7 +105,7 @@ export const Deaccessioned: Story = {



@@ -129,7 +129,7 @@ export const Anonymized: Story = {



diff --git a/tests/component/sections/dataset/Dataset.spec.tsx b/tests/component/sections/dataset/Dataset.spec.tsx index 70b899057..002d4e92e 100644 --- a/tests/component/sections/dataset/Dataset.spec.tsx +++ b/tests/component/sections/dataset/Dataset.spec.tsx @@ -41,7 +41,7 @@ describe('Dataset', () => { mountWithDataset(, testDataset) cy.findByTestId('dataset-skeleton').should('exist') - cy.findByText(testDataset.getTitle()).should('not.exist') + cy.findByText(testDataset.title()).should('not.exist') }) it('renders page not found when dataset is null', () => { @@ -57,7 +57,7 @@ describe('Dataset', () => { mountWithDataset(, testDataset) - cy.findAllByText(testDataset.getTitle()).should('exist') + cy.findAllByText(testDataset.title()).should('exist') testDataset.labels.forEach((label) => { cy.findAllByText(label.value).should('exist') @@ -69,7 +69,7 @@ describe('Dataset', () => { mountWithDataset(, testDataset) - cy.findAllByText(testDataset.getTitle()).should('exist') + cy.findAllByText(testDataset.title()).should('exist') const metadataTab = cy.findByRole('tab', { name: 'Metadata' }) metadataTab.should('exist') diff --git a/tests/component/sections/dataset/DatasetProvider.spec.tsx b/tests/component/sections/dataset/DatasetProvider.spec.tsx index 03684cf44..a6e4863f1 100644 --- a/tests/component/sections/dataset/DatasetProvider.spec.tsx +++ b/tests/component/sections/dataset/DatasetProvider.spec.tsx @@ -9,7 +9,7 @@ function TestComponent() { return (
- {dataset ? {dataset.getTitle()} : Dataset Not Found} + {dataset ? {dataset.title()} : Dataset Not Found} {isLoading &&
Loading...
}
) @@ -39,7 +39,7 @@ describe('DatasetProvider', () => { cy.findByText('Loading...').should('exist') cy.wrap(datasetRepository.getByPersistentId).should('be.calledOnceWith', dataset.persistentId) - cy.findByText(dataset.getTitle()).should('exist') + cy.findByText(dataset.title()).should('exist') cy.findByText('Loading...').should('not.exist') }) @@ -60,7 +60,7 @@ describe('DatasetProvider', () => { dataset.persistentId, 'draft' ) - cy.findByText(dataset.getTitle()).should('exist') + cy.findByText(dataset.title()).should('exist') cy.findByText('Loading...').should('not.exist') }) @@ -80,7 +80,7 @@ describe('DatasetProvider', () => { 'be.calledOnce', 'some-private-url-token' ) - cy.findByText(dataset.getTitle()).should('exist') + cy.findByText(dataset.title()).should('exist') cy.findByText('Loading...').should('not.exist') }) diff --git a/tests/component/sections/home/Home.spec.tsx b/tests/component/sections/home/Home.spec.tsx index efc76cf76..86b95c5aa 100644 --- a/tests/component/sections/home/Home.spec.tsx +++ b/tests/component/sections/home/Home.spec.tsx @@ -20,7 +20,7 @@ describe('Home page', () => { cy.wrap(datasetRepository.getAll).should('be.calledOnce') datasets.forEach((dataset) => { - cy.findByText(dataset.getTitle()).should('exist') + cy.findByText(dataset.title()).should('exist') }) }) }) diff --git a/tests/component/sections/home/datasets-list/DatasetsList.spec.tsx b/tests/component/sections/home/datasets-list/DatasetsList.spec.tsx index 4c523a931..57f7ec4eb 100644 --- a/tests/component/sections/home/datasets-list/DatasetsList.spec.tsx +++ b/tests/component/sections/home/datasets-list/DatasetsList.spec.tsx @@ -15,7 +15,7 @@ describe('Datasets List', () => { cy.wrap(datasetRepository.getAll).should('be.calledOnce') datasets.forEach((dataset) => { - cy.findByRole('link', { name: dataset.getTitle() }) + cy.findByRole('link', { name: dataset.title() }) .should('exist') .should('have.attr', 'href', `/datasets?persistentId=${dataset.persistentId}`) }) diff --git a/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts b/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts index 65f01dbfc..3bb5cef31 100644 --- a/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts +++ b/tests/e2e-integration/integration/datasets/DatasetJSDataverseRepository.spec.ts @@ -98,7 +98,7 @@ describe('Dataset JSDataverse Repository', () => { } const datasetExpected = datasetData(dataset.persistentId, dataset.version.id) - expect(dataset.getTitle()).to.deep.equal(datasetExpected.title) + expect(dataset.title()).to.deep.equal(datasetExpected.title) expect(dataset.citation).to.deep.equal(datasetExpected.citation) // expect(dataset.labels).to.deep.equal(datasetExpected.labels) TODO - Implemnent isReleased property in js-dataverse to get the Unpublished label expect(dataset.license).to.deep.equal(datasetExpected.license) @@ -133,7 +133,7 @@ describe('Dataset JSDataverse Repository', () => { 0 ) const expectedPublicationDate = getCurrentDateInYYYYMMDDFormat() - expect(dataset.getTitle()).to.deep.equal(datasetExpected.title) + expect(dataset.title()).to.deep.equal(datasetExpected.title) expect(dataset.version).to.deep.equal(newVersion) expect(dataset.metadataBlocks[0].fields.publicationDate).to.deep.equal( expectedPublicationDate @@ -153,7 +153,7 @@ describe('Dataset JSDataverse Repository', () => { } const datasetExpected = datasetData(dataset.persistentId, dataset.version.id) - expect(dataset.getTitle()).to.deep.equal(datasetExpected.title) + expect(dataset.title()).to.deep.equal(datasetExpected.title) expect(dataset.version).to.deep.equal(datasetExpected.version) }) }) @@ -168,7 +168,7 @@ describe('Dataset JSDataverse Repository', () => { } const datasetExpected = datasetData(dataset.persistentId, dataset.version.id) - expect(dataset.getTitle()).to.deep.equal(datasetExpected.title) + expect(dataset.title()).to.deep.equal(datasetExpected.title) expect(dataset.version).to.deep.equal(datasetExpected.version) }) }) From 2afdf82f6404f765ef19b84838c8eca6d6230b30 Mon Sep 17 00:00:00 2001 From: MellyGray Date: Mon, 20 Nov 2023 11:08:56 +0100 Subject: [PATCH 05/27] feat: add pagination to Datasets List --- public/locales/en/files.json | 3 - public/locales/en/pagination.json | 4 ++ .../domain/models/DatasetPaginationInfo.ts | 7 ++ .../domain/models/TotalDatasetsCount.ts | 1 + .../domain/repositories/DatasetRepository.ts | 5 +- src/dataset/domain/useCases/getDatasets.ts | 8 ++- .../domain/useCases/getTotalDatasetsCount.ts | 10 +++ .../DatasetJSDataverseRepository.ts | 14 +++- src/files/domain/models/FilePaginationInfo.ts | 53 ++------------ .../domain/repositories/FileRepository.ts | 2 +- .../useCases/getFilesByDatasetPersistentId.ts | 2 +- .../FileJSDataverseRepository.ts | 2 +- .../mappers/DomainFileMapper.ts | 2 +- .../dataset/dataset-files/DatasetFiles.tsx | 9 +-- .../dataset-files/files-table/FilesTable.tsx | 4 +- .../FilesTableColumnsDefinition.tsx | 2 +- .../files-table/file-info/FileInfoHeader.tsx | 7 +- .../row-selection/useFileSelection.ts | 4 +- .../files-table/useFilesTable.tsx | 2 +- .../dataset/dataset-files/useFiles.tsx | 4 +- .../home/datasets-list/DatasetsList.tsx | 20 +++++- src/sections/home/useDatasets.tsx | 51 ++++++++++++-- .../pagination}/PageNumbersButtons.tsx | 0 .../PageNumbersButtonsWithEllipsis.tsx | 0 .../pagination}/PageSizeSelector.tsx | 10 ++- .../pagination/Pagination.module.scss} | 7 ++ .../pagination/PaginationControls.tsx} | 30 +++++--- .../pagination/PaginationResultsInfo.tsx | 23 +++++++ src/shared/domain/models/PaginationInfo.ts | 69 +++++++++++++++++++ src/stories/dataset/DatasetMockRepository.ts | 14 +++- .../FilesPagination.stories.tsx | 17 +++-- src/stories/files/FileMockRepository.ts | 2 +- .../dataset-files/DatasetFiles.spec.tsx | 14 ++-- .../files-pagination/FilesPagination.spec.tsx | 14 ++-- .../PageNumbersButtonsWithEllipsis.spec.tsx | 2 +- .../files-table/FilesTable.spec.tsx | 2 +- .../dataset/dataset-files/useFiles.spec.tsx | 4 +- .../files/FileJSDataverseRepository.spec.ts | 2 +- 38 files changed, 299 insertions(+), 127 deletions(-) create mode 100644 public/locales/en/pagination.json create mode 100644 src/dataset/domain/models/DatasetPaginationInfo.ts create mode 100644 src/dataset/domain/models/TotalDatasetsCount.ts create mode 100644 src/dataset/domain/useCases/getTotalDatasetsCount.ts rename src/sections/{dataset/dataset-files/files-pagination => shared/pagination}/PageNumbersButtons.tsx (100%) rename src/sections/{dataset/dataset-files/files-pagination => shared/pagination}/PageNumbersButtonsWithEllipsis.tsx (100%) rename src/sections/{dataset/dataset-files/files-pagination => shared/pagination}/PageSizeSelector.tsx (80%) rename src/sections/{dataset/dataset-files/files-pagination/FilesPagination.module.scss => shared/pagination/Pagination.module.scss} (55%) rename src/sections/{dataset/dataset-files/files-pagination/FilesPagination.tsx => shared/pagination/PaginationControls.tsx} (70%) create mode 100644 src/sections/shared/pagination/PaginationResultsInfo.tsx create mode 100644 src/shared/domain/models/PaginationInfo.ts diff --git a/public/locales/en/files.json b/public/locales/en/files.json index 3e8938625..67d016720 100644 --- a/public/locales/en/files.json +++ b/public/locales/en/files.json @@ -8,9 +8,6 @@ "clearSelection": "Clear selection." }, "zipDownloadExceedsLimit": "The overall size of the files selected ({{selectionTotalSize}}) for download exceeds the zip limit of {{zipDownloadSizeLimit}}. Please unselect some files to continue.", - "pagination": { - "pageSize": "Files per page" - }, "tabularData": { "variables": "Variables", "observations": "Observations" diff --git a/public/locales/en/pagination.json b/public/locales/en/pagination.json new file mode 100644 index 000000000..0fe6a88c9 --- /dev/null +++ b/public/locales/en/pagination.json @@ -0,0 +1,4 @@ +{ + "results": "{{start}} to {{end}} of {{total}} {{item}}s", + "pageSize": "{{item}}s per page" +} \ No newline at end of file diff --git a/src/dataset/domain/models/DatasetPaginationInfo.ts b/src/dataset/domain/models/DatasetPaginationInfo.ts new file mode 100644 index 000000000..e9d88e6f4 --- /dev/null +++ b/src/dataset/domain/models/DatasetPaginationInfo.ts @@ -0,0 +1,7 @@ +import { PaginationInfo } from '../../../shared/domain/models/PaginationInfo' + +export class DatasetPaginationInfo extends PaginationInfo { + constructor(page = 1, pageSize = 10, totalItems = 0, itemName = 'Dataset') { + super(page, pageSize, totalItems, itemName) + } +} diff --git a/src/dataset/domain/models/TotalDatasetsCount.ts b/src/dataset/domain/models/TotalDatasetsCount.ts new file mode 100644 index 000000000..acc302966 --- /dev/null +++ b/src/dataset/domain/models/TotalDatasetsCount.ts @@ -0,0 +1 @@ +export type TotalDatasetsCount = number diff --git a/src/dataset/domain/repositories/DatasetRepository.ts b/src/dataset/domain/repositories/DatasetRepository.ts index dab6f535e..7c9bcea2d 100644 --- a/src/dataset/domain/repositories/DatasetRepository.ts +++ b/src/dataset/domain/repositories/DatasetRepository.ts @@ -1,7 +1,10 @@ import { Dataset } from '../models/Dataset' +import { TotalDatasetsCount } from '../models/TotalDatasetsCount' +import { DatasetPaginationInfo } from '../models/DatasetPaginationInfo' export interface DatasetRepository { getByPersistentId: (persistentId: string, version?: string) => Promise getByPrivateUrlToken: (privateUrlToken: string) => Promise - getAll: () => Promise + getAll: (paginationInfo: DatasetPaginationInfo) => Promise + getTotalDatasetsCount: () => Promise } diff --git a/src/dataset/domain/useCases/getDatasets.ts b/src/dataset/domain/useCases/getDatasets.ts index e3afc87f4..1abdf2eb0 100644 --- a/src/dataset/domain/useCases/getDatasets.ts +++ b/src/dataset/domain/useCases/getDatasets.ts @@ -1,8 +1,12 @@ import { DatasetRepository } from '../repositories/DatasetRepository' import { Dataset } from '../models/Dataset' +import { DatasetPaginationInfo } from '../models/DatasetPaginationInfo' -export async function getDatasets(datasetRepository: DatasetRepository): Promise { - return datasetRepository.getAll().catch((error: Error) => { +export async function getDatasets( + datasetRepository: DatasetRepository, + paginationInfo: DatasetPaginationInfo +): Promise { + return datasetRepository.getAll(paginationInfo).catch((error: Error) => { throw new Error(error.message) }) } diff --git a/src/dataset/domain/useCases/getTotalDatasetsCount.ts b/src/dataset/domain/useCases/getTotalDatasetsCount.ts new file mode 100644 index 000000000..5ba855d06 --- /dev/null +++ b/src/dataset/domain/useCases/getTotalDatasetsCount.ts @@ -0,0 +1,10 @@ +import { DatasetRepository } from '../repositories/DatasetRepository' +import { TotalDatasetsCount } from '../models/TotalDatasetsCount' + +export async function getTotalDatasetsCount( + datasetRepository: DatasetRepository +): Promise { + return datasetRepository.getTotalDatasetsCount().catch((error: Error) => { + throw new Error(error.message) + }) +} diff --git a/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts b/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts index 7592cb7e8..636f61058 100644 --- a/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts +++ b/src/dataset/infrastructure/repositories/DatasetJSDataverseRepository.ts @@ -11,9 +11,12 @@ import { } from '@iqss/dataverse-client-javascript' import { JSDatasetMapper } from '../mappers/JSDatasetMapper' import { DatasetMother } from '../../../../tests/component/dataset/domain/models/DatasetMother' +import { TotalDatasetsCount } from '../../domain/models/TotalDatasetsCount' +import { DatasetPaginationInfo } from '../../domain/models/DatasetPaginationInfo' export class DatasetJSDataverseRepository implements DatasetRepository { - getAll(): Promise { + // eslint-disable-next-line unused-imports/no-unused-vars + getAll(paginationInfo: DatasetPaginationInfo): Promise { // TODO - Implement using the js-dataverse-client return new Promise((resolve) => { setTimeout(() => { @@ -22,6 +25,15 @@ export class DatasetJSDataverseRepository implements DatasetRepository { }) } + getTotalDatasetsCount(): Promise { + // TODO - Implement using the js-dataverse-client + return new Promise((resolve) => { + setTimeout(() => { + resolve(200) + }, 1000) + }) + } + getByPersistentId( persistentId: string, version?: string, diff --git a/src/files/domain/models/FilePaginationInfo.ts b/src/files/domain/models/FilePaginationInfo.ts index 5f0e1ddcc..f2b4386af 100644 --- a/src/files/domain/models/FilePaginationInfo.ts +++ b/src/files/domain/models/FilePaginationInfo.ts @@ -1,52 +1,7 @@ -export class FilePaginationInfo { - constructor( - public readonly page: number = 1, - public readonly pageSize: number = 10, - public readonly totalFiles: number = 0 - ) {} +import { PaginationInfo } from '../../../shared/domain/models/PaginationInfo' - withTotal(total: number): FilePaginationInfo { - return new FilePaginationInfo(this.page, this.pageSize, total) - } - goToPage(page: number): FilePaginationInfo { - return new FilePaginationInfo(page, this.pageSize, this.totalFiles) - } - - goToPreviousPage(): FilePaginationInfo { - if (!this.previousPage) throw new Error('No previous page') - return this.goToPage(this.previousPage) - } - - goToNextPage(): FilePaginationInfo { - if (!this.nextPage) throw new Error('No next page') - return this.goToPage(this.nextPage) - } - - withPageSize(pageSize: number): FilePaginationInfo { - const getNewPage = (oldPageSize: number, newPageSize: number) => { - const newPage = Math.ceil((this.page * oldPageSize) / newPageSize) - return newPage > 0 ? newPage : 1 - } - return new FilePaginationInfo(getNewPage(this.pageSize, pageSize), pageSize, this.totalFiles) - } - - get totalPages(): number { - return Math.ceil(this.totalFiles / this.pageSize) - } - - get hasPreviousPage(): boolean { - return this.page > 1 - } - - get hasNextPage(): boolean { - return this.page < this.totalPages - } - - get previousPage(): number | undefined { - return this.hasPreviousPage ? this.page - 1 : undefined - } - - get nextPage(): number | undefined { - return this.hasNextPage ? this.page + 1 : undefined +export class FilePaginationInfo extends PaginationInfo { + constructor(page = 1, pageSize = 10, totalItems = 0, itemName = 'File') { + super(page, pageSize, totalItems, itemName) } } diff --git a/src/files/domain/repositories/FileRepository.ts b/src/files/domain/repositories/FileRepository.ts index 976fd5a66..afb6e4153 100644 --- a/src/files/domain/repositories/FileRepository.ts +++ b/src/files/domain/repositories/FileRepository.ts @@ -1,9 +1,9 @@ import { File } from '../models/File' import { FileCriteria } from '../models/FileCriteria' import { FilesCountInfo } from '../models/FilesCountInfo' -import { FilePaginationInfo } from '../models/FilePaginationInfo' import { FileUserPermissions } from '../models/FileUserPermissions' import { DatasetVersion } from '../../../dataset/domain/models/Dataset' +import { FilePaginationInfo } from '../models/FilePaginationInfo' export interface FileRepository { getAllByDatasetPersistentId: ( diff --git a/src/files/domain/useCases/getFilesByDatasetPersistentId.ts b/src/files/domain/useCases/getFilesByDatasetPersistentId.ts index 326633b7d..9370c7ebe 100644 --- a/src/files/domain/useCases/getFilesByDatasetPersistentId.ts +++ b/src/files/domain/useCases/getFilesByDatasetPersistentId.ts @@ -1,8 +1,8 @@ import { FileRepository } from '../repositories/FileRepository' import { File } from '../models/File' import { FileCriteria } from '../models/FileCriteria' -import { FilePaginationInfo } from '../models/FilePaginationInfo' import { DatasetVersion } from '../../../dataset/domain/models/Dataset' +import { FilePaginationInfo } from '../models/FilePaginationInfo' export async function getFilesByDatasetPersistentId( fileRepository: FileRepository, diff --git a/src/files/infrastructure/FileJSDataverseRepository.ts b/src/files/infrastructure/FileJSDataverseRepository.ts index e16c3c004..62da698cc 100644 --- a/src/files/infrastructure/FileJSDataverseRepository.ts +++ b/src/files/infrastructure/FileJSDataverseRepository.ts @@ -1,7 +1,6 @@ import { FileRepository } from '../domain/repositories/FileRepository' import { File, FilePublishingStatus } from '../domain/models/File' import { FilesCountInfo } from '../domain/models/FilesCountInfo' -import { FilePaginationInfo } from '../domain/models/FilePaginationInfo' import { FileUserPermissions } from '../domain/models/FileUserPermissions' import { FileDownloadSizeMode, @@ -16,6 +15,7 @@ import { FileCriteria } from '../domain/models/FileCriteria' import { DomainFileMapper } from './mappers/DomainFileMapper' import { JSFileMapper } from './mappers/JSFileMapper' import { DatasetVersion } from '../../dataset/domain/models/Dataset' +import { FilePaginationInfo } from '../domain/models/FilePaginationInfo' const includeDeaccessioned = true diff --git a/src/files/infrastructure/mappers/DomainFileMapper.ts b/src/files/infrastructure/mappers/DomainFileMapper.ts index cda15bf92..cb39b39d0 100644 --- a/src/files/infrastructure/mappers/DomainFileMapper.ts +++ b/src/files/infrastructure/mappers/DomainFileMapper.ts @@ -1,4 +1,3 @@ -import { FilePaginationInfo } from '../../domain/models/FilePaginationInfo' import { FileAccessOption, FileCriteria, @@ -11,6 +10,7 @@ import { FileOrderCriteria as JSFileOrderCriteria } from '@iqss/dataverse-client-javascript' import { FileType } from '../../domain/models/File' +import { FilePaginationInfo } from '../../domain/models/FilePaginationInfo' export class DomainFileMapper { static toJSPagination(paginationInfo: FilePaginationInfo): { limit?: number; offset?: number } { diff --git a/src/sections/dataset/dataset-files/DatasetFiles.tsx b/src/sections/dataset/dataset-files/DatasetFiles.tsx index cccd061a5..8e3f0a07c 100644 --- a/src/sections/dataset/dataset-files/DatasetFiles.tsx +++ b/src/sections/dataset/dataset-files/DatasetFiles.tsx @@ -4,9 +4,9 @@ import { FilesTable } from './files-table/FilesTable' import { FileCriteriaForm } from './file-criteria-form/FileCriteriaForm' import { FileCriteria } from '../../../files/domain/models/FileCriteria' import { useFiles } from './useFiles' -import { FilePaginationInfo } from '../../../files/domain/models/FilePaginationInfo' -import { FilesPagination } from './files-pagination/FilesPagination' +import { PaginationControls } from '../../shared/pagination/PaginationControls' import { DatasetVersion } from '../../../dataset/domain/models/Dataset' +import { FilePaginationInfo } from '../../../files/domain/models/FilePaginationInfo' interface DatasetFilesProps { filesRepository: FileRepository @@ -44,10 +44,11 @@ export function DatasetFiles({ filesTotalDownloadSize={filesTotalDownloadSize} criteria={criteria} /> - diff --git a/src/sections/dataset/dataset-files/files-table/FilesTable.tsx b/src/sections/dataset/dataset-files/files-table/FilesTable.tsx index fc71ef801..b1988bba8 100644 --- a/src/sections/dataset/dataset-files/files-table/FilesTable.tsx +++ b/src/sections/dataset/dataset-files/files-table/FilesTable.tsx @@ -6,10 +6,10 @@ import { File } from '../../../../files/domain/models/File' import { RowSelectionMessage } from './row-selection/RowSelectionMessage' import { ZipDownloadLimitMessage } from './zip-download-limit-message/ZipDownloadLimitMessage' import { SpinnerSymbol } from './spinner-symbol/SpinnerSymbol' -import { FilePaginationInfo } from '../../../../files/domain/models/FilePaginationInfo' import { useEffect, useState } from 'react' import { FileSelection } from './row-selection/useFileSelection' import { FileCriteria } from '../../../../files/domain/models/FileCriteria' +import { FilePaginationInfo } from '../../../../files/domain/models/FilePaginationInfo' interface FilesTableProps { files: File[] @@ -56,7 +56,7 @@ export function FilesTable({ } return ( - {`${startIndex} to ${endIndex} of ${fileCount} Files`} + ) } diff --git a/src/sections/dataset/dataset-files/files-table/row-selection/useFileSelection.ts b/src/sections/dataset/dataset-files/files-table/row-selection/useFileSelection.ts index ede451ad0..6fe2a12eb 100644 --- a/src/sections/dataset/dataset-files/files-table/row-selection/useFileSelection.ts +++ b/src/sections/dataset/dataset-files/files-table/row-selection/useFileSelection.ts @@ -1,8 +1,8 @@ import { useEffect, useState } from 'react' -import { FilePaginationInfo } from '../../../../../files/domain/models/FilePaginationInfo' import { File } from '../../../../../files/domain/models/File' import { Row } from '@tanstack/react-table' import { RowSelection } from '../useFilesTable' +import { FilePaginationInfo } from '../../../../../files/domain/models/FilePaginationInfo' export type FileSelection = { [key: string]: File | undefined @@ -61,7 +61,7 @@ export function useFileSelection( const selectAllFiles = () => { setCurrentPageRowSelection(createRowSelection(paginationInfo.pageSize)) - const totalFilesFileSelection = createFileSelection(paginationInfo.totalFiles) + const totalFilesFileSelection = createFileSelection(paginationInfo.totalItems) const newFileSelection = { ...totalFilesFileSelection, ...fileSelection } setFileSelection(newFileSelection) } diff --git a/src/sections/dataset/dataset-files/files-table/useFilesTable.tsx b/src/sections/dataset/dataset-files/files-table/useFilesTable.tsx index b403e9782..0d4f35fd1 100644 --- a/src/sections/dataset/dataset-files/files-table/useFilesTable.tsx +++ b/src/sections/dataset/dataset-files/files-table/useFilesTable.tsx @@ -2,8 +2,8 @@ import { useEffect, useState } from 'react' import { File } from '../../../../files/domain/models/File' import { getCoreRowModel, Row, useReactTable } from '@tanstack/react-table' import { createColumnsDefinition } from './FilesTableColumnsDefinition' -import { FilePaginationInfo } from '../../../../files/domain/models/FilePaginationInfo' import { useFileSelection } from './row-selection/useFileSelection' +import { FilePaginationInfo } from '../../../../files/domain/models/FilePaginationInfo' export type RowSelection = { [key: string]: boolean diff --git a/src/sections/dataset/dataset-files/useFiles.tsx b/src/sections/dataset/dataset-files/useFiles.tsx index 538da0921..ce628deb3 100644 --- a/src/sections/dataset/dataset-files/useFiles.tsx +++ b/src/sections/dataset/dataset-files/useFiles.tsx @@ -5,11 +5,11 @@ import { getFilesByDatasetPersistentId } from '../../../files/domain/useCases/ge import { FileCriteria } from '../../../files/domain/models/FileCriteria' import { FilesCountInfo } from '../../../files/domain/models/FilesCountInfo' import { getFilesCountInfoByDatasetPersistentId } from '../../../files/domain/useCases/getFilesCountInfoByDatasetPersistentId' -import { FilePaginationInfo } from '../../../files/domain/models/FilePaginationInfo' import { useFilePermissions } from '../../file/file-permissions/FilePermissionsContext' import { FilePermission } from '../../../files/domain/models/FileUserPermissions' import { DatasetVersion } from '../../../dataset/domain/models/Dataset' import { getFilesTotalDownloadSize } from '../../../files/domain/useCases/getFilesTotalDownloadSize' +import { FilePaginationInfo } from '../../../files/domain/models/FilePaginationInfo' export function useFiles( filesRepository: FileRepository, @@ -33,7 +33,7 @@ export function useFiles( ) .then((filesCountInfo: FilesCountInfo) => { setFilesCountInfo(filesCountInfo) - if (filesCountInfo.total !== paginationInfo.totalFiles) { + if (filesCountInfo.total !== paginationInfo.totalItems) { onPaginationInfoChange(paginationInfo.withTotal(filesCountInfo.total)) } return filesCountInfo diff --git a/src/sections/home/datasets-list/DatasetsList.tsx b/src/sections/home/datasets-list/DatasetsList.tsx index c54b8c472..bef1eb5bf 100644 --- a/src/sections/home/datasets-list/DatasetsList.tsx +++ b/src/sections/home/datasets-list/DatasetsList.tsx @@ -1,23 +1,37 @@ import { useDatasets } from '../useDatasets' import styles from '../Home.module.scss' import { DatasetRepository } from '../../../dataset/domain/repositories/DatasetRepository' +import { useState } from 'react' +import { PaginationResultsInfo } from '../../shared/pagination/PaginationResultsInfo' +import { PaginationControls } from '../../shared/pagination/PaginationControls' +import { DatasetPaginationInfo } from '../../../dataset/domain/models/DatasetPaginationInfo' interface DatasetsListProps { datasetRepository: DatasetRepository } export function DatasetsList({ datasetRepository }: DatasetsListProps) { - const { datasets } = useDatasets(datasetRepository) + const [paginationInfo, setPaginationInfo] = useState( + new DatasetPaginationInfo() + ) + const { datasets } = useDatasets(datasetRepository, setPaginationInfo, paginationInfo) return (
-
-

1 to 10 of 41 Results

+
+
{datasets.map((dataset) => ( ))} +
) } diff --git a/src/sections/home/useDatasets.tsx b/src/sections/home/useDatasets.tsx index 8a370b5ae..47b2d73dc 100644 --- a/src/sections/home/useDatasets.tsx +++ b/src/sections/home/useDatasets.tsx @@ -2,27 +2,64 @@ import { useEffect, useState } from 'react' import { DatasetRepository } from '../../dataset/domain/repositories/DatasetRepository' import { Dataset } from '../../dataset/domain/models/Dataset' import { getDatasets } from '../../dataset/domain/useCases/getDatasets' +import { getTotalDatasetsCount } from '../../dataset/domain/useCases/getTotalDatasetsCount' +import { TotalDatasetsCount } from '../../dataset/domain/models/TotalDatasetsCount' +import { DatasetPaginationInfo } from '../../dataset/domain/models/DatasetPaginationInfo' -export function useDatasets(datasetRepository: DatasetRepository) { +export function useDatasets( + datasetRepository: DatasetRepository, + onPaginationInfoChange: (paginationInfo: DatasetPaginationInfo) => void, + paginationInfo: DatasetPaginationInfo +) { const [datasets, setDatasets] = useState([]) const [isLoading, setIsLoading] = useState(true) + const [totalDatasetsCount, setTotalDatasetsCount] = useState() + + const fetchTotalDatasetsCount: () => Promise = () => { + return getTotalDatasetsCount(datasetRepository) + .then((totalDatasetsCount: TotalDatasetsCount) => { + setTotalDatasetsCount(totalDatasetsCount) + if (totalDatasetsCount !== paginationInfo.totalItems) { + onPaginationInfoChange(paginationInfo.withTotal(totalDatasetsCount)) + } + return totalDatasetsCount + }) + .catch(() => { + throw new Error('There was an error getting the datasets count info') + }) + } + const fetchDatasets = (totalDatasetsCount: TotalDatasetsCount) => { + if (totalDatasetsCount) { + if (totalDatasetsCount === 0) { + setIsLoading(false) + return + } + return getDatasets(datasetRepository, paginationInfo.withTotal(totalDatasetsCount)) + .then((datasets: Dataset[]) => { + setDatasets(datasets) + setIsLoading(false) + return datasets + }) + .catch(() => { + throw new Error('There was an error getting the datasets') + }) + } + } useEffect(() => { setIsLoading(true) - getDatasets(datasetRepository) - .then((datasets: Dataset[]) => { - setDatasets(datasets) - return datasets - }) + fetchTotalDatasetsCount() + .then((totalDatasetsCount) => fetchDatasets(totalDatasetsCount)) .catch(() => { console.error('There was an error getting the datasets') setIsLoading(false) }) - }, [datasetRepository]) + }, [datasetRepository, paginationInfo.page]) return { datasets, + totalDatasetsCount, isLoading } } diff --git a/src/sections/dataset/dataset-files/files-pagination/PageNumbersButtons.tsx b/src/sections/shared/pagination/PageNumbersButtons.tsx similarity index 100% rename from src/sections/dataset/dataset-files/files-pagination/PageNumbersButtons.tsx rename to src/sections/shared/pagination/PageNumbersButtons.tsx diff --git a/src/sections/dataset/dataset-files/files-pagination/PageNumbersButtonsWithEllipsis.tsx b/src/sections/shared/pagination/PageNumbersButtonsWithEllipsis.tsx similarity index 100% rename from src/sections/dataset/dataset-files/files-pagination/PageNumbersButtonsWithEllipsis.tsx rename to src/sections/shared/pagination/PageNumbersButtonsWithEllipsis.tsx diff --git a/src/sections/dataset/dataset-files/files-pagination/PageSizeSelector.tsx b/src/sections/shared/pagination/PageSizeSelector.tsx similarity index 80% rename from src/sections/dataset/dataset-files/files-pagination/PageSizeSelector.tsx rename to src/sections/shared/pagination/PageSizeSelector.tsx index a5acbf945..2378453df 100644 --- a/src/sections/dataset/dataset-files/files-pagination/PageSizeSelector.tsx +++ b/src/sections/shared/pagination/PageSizeSelector.tsx @@ -1,20 +1,24 @@ -import styles from './FilesPagination.module.scss' +import styles from './Pagination.module.scss' import { useTranslation } from 'react-i18next' export function PageSizeSelector({ + itemName, pageSize, setPageSize }: { + itemName: string pageSize: number setPageSize: (pageSize: number) => void }) { - const { t } = useTranslation('files') + const { t } = useTranslation('pagination') const availableSizes = [10, 25, 50] return (