From 26df4f4eee33477cf28f9d273ac8fc2cc3ad78f6 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Fri, 20 Sep 2024 07:55:17 -0400 Subject: [PATCH 01/21] feat: add publishCollection use case --- package-lock.json | 9 ++++----- package.json | 2 +- .../domain/repositories/CollectionRepository.ts | 1 + src/collection/domain/useCases/publishCollection.ts | 10 ++++++++++ .../repositories/CollectionJSDataverseRepository.ts | 6 +++++- .../CollectionJSDataverseRepository.spec.ts | 13 +++++++++++++ 6 files changed, 34 insertions(+), 7 deletions(-) create mode 100644 src/collection/domain/useCases/publishCollection.ts diff --git a/package-lock.json b/package-lock.json index 6e6758dc4..a09c42843 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "0.1.0", "dependencies": { "@faker-js/faker": "7.6.0", - "@iqss/dataverse-client-javascript": "2.0.0-pr187.f29c0e6", + "@iqss/dataverse-client-javascript": "2.0.0-pr193.8ac7738", "@iqss/dataverse-design-system": "*", "@istanbuljs/nyc-config-typescript": "1.0.2", "@tanstack/react-table": "8.9.2", @@ -3674,10 +3674,9 @@ }, "node_modules/@iqss/dataverse-client-javascript": { "name": "@IQSS/dataverse-client-javascript", - "version": "2.0.0-pr187.f29c0e6", - "resolved": "https://npm.pkg.github.com/download/@IQSS/dataverse-client-javascript/2.0.0-pr187.f29c0e6/324f487a2b1437df668e34159404161888279638", - "integrity": "sha512-0OX9nmh7dY3Gg5euE7buCqTeyh+1B+GhFcDz2gJoND4oM3kIZalYS+bLsEoEekR2o25agP6b+ANyQ5kvZeFuig==", - "license": "MIT", + "version": "2.0.0-pr193.8ac7738", + "resolved": "https://npm.pkg.github.com/download/@IQSS/dataverse-client-javascript/2.0.0-pr193.8ac7738/0ee4b3b9c50bd1a634816ec9642a1e4be042dab8", + "integrity": "sha512-aNPC7HPQGwcuzBHsobbJIrjh/JlHoklWeC5XQQ2VL23GytGcxV0R0+ctfbGH8V9uFK4YGZ22xFSlTwxdsuWSmA==", "dependencies": { "@types/node": "^18.15.11", "@types/turndown": "^5.0.1", diff --git a/package.json b/package.json index 6549c4e3f..ee4b10502 100644 --- a/package.json +++ b/package.json @@ -13,7 +13,7 @@ }, "dependencies": { "@faker-js/faker": "7.6.0", - "@iqss/dataverse-client-javascript": "2.0.0-pr187.f29c0e6", + "@iqss/dataverse-client-javascript": "2.0.0-pr193.8ac7738", "@iqss/dataverse-design-system": "*", "@istanbuljs/nyc-config-typescript": "1.0.2", "@tanstack/react-table": "8.9.2", diff --git a/src/collection/domain/repositories/CollectionRepository.ts b/src/collection/domain/repositories/CollectionRepository.ts index 3cc8c3e96..a5c86078d 100644 --- a/src/collection/domain/repositories/CollectionRepository.ts +++ b/src/collection/domain/repositories/CollectionRepository.ts @@ -8,4 +8,5 @@ export interface CollectionRepository { create(collection: CollectionDTO, hostCollection?: string): Promise getFacets(collectionIdOrAlias: number | string): Promise getUserPermissions(collectionIdOrAlias: number | string): Promise + publish(collectionIdOrAlias: number | string): Promise } diff --git a/src/collection/domain/useCases/publishCollection.ts b/src/collection/domain/useCases/publishCollection.ts new file mode 100644 index 000000000..cea14fca1 --- /dev/null +++ b/src/collection/domain/useCases/publishCollection.ts @@ -0,0 +1,10 @@ +import { CollectionRepository } from '../repositories/CollectionRepository' + +export function publishCollection( + collectionRepository: CollectionRepository, + collectionId: number | string +): Promise { + return collectionRepository.publish(collectionId).catch((error: Error) => { + throw new Error(error.message) + }) +} diff --git a/src/collection/infrastructure/repositories/CollectionJSDataverseRepository.ts b/src/collection/infrastructure/repositories/CollectionJSDataverseRepository.ts index 0eda9f56c..83e49aaca 100644 --- a/src/collection/infrastructure/repositories/CollectionJSDataverseRepository.ts +++ b/src/collection/infrastructure/repositories/CollectionJSDataverseRepository.ts @@ -4,7 +4,8 @@ import { createCollection, getCollection, getCollectionFacets, - getCollectionUserPermissions + getCollectionUserPermissions, + publishCollection } from '@iqss/dataverse-client-javascript' import { JSCollectionMapper } from '../mappers/JSCollectionMapper' import { CollectionDTO } from '../../domain/useCases/DTOs/CollectionDTO' @@ -33,4 +34,7 @@ export class CollectionJSDataverseRepository implements CollectionRepository { .execute(collectionIdOrAlias) .then((jsCollectionUserPermissions) => jsCollectionUserPermissions) } + publish(collectionIdOrAlias: number | string): Promise { + return publishCollection.execute(collectionIdOrAlias) + } } diff --git a/tests/e2e-integration/integration/collection/CollectionJSDataverseRepository.spec.ts b/tests/e2e-integration/integration/collection/CollectionJSDataverseRepository.spec.ts index 7339fe403..1f5137f7a 100644 --- a/tests/e2e-integration/integration/collection/CollectionJSDataverseRepository.spec.ts +++ b/tests/e2e-integration/integration/collection/CollectionJSDataverseRepository.spec.ts @@ -49,4 +49,17 @@ describe('Collection JSDataverse Repository', () => { expect(collection).to.deep.equal(collectionExpected) }) }) + it('publishes the collection', async () => { + const timestamp = new Date().valueOf() + const uniqueCollectionId = `test-publish-collection-${timestamp}` + const collectionResponse = await CollectionHelper.create(uniqueCollectionId) + await collectionRepository.publish(collectionResponse.id) + await collectionRepository.getById(collectionResponse.id).then((collection) => { + if (!collection) { + throw new Error('Collection not found') + } + + expect(collection.isReleased).to.deep.equal(true) + }) + }) }) From ecfd384eebb55e8bc79cb5ef5f825fc6b45d4e0c Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Sat, 21 Sep 2024 14:39:31 -0400 Subject: [PATCH 02/21] feat: add PublishDatasetModal component and Story --- public/locales/en/collection.json | 6 +- public/locales/en/shared.json | 4 +- .../domain/useCases/publishCollection.ts | 4 +- src/sections/Route.enum.ts | 1 + .../PublishCollectionModal.module.scss | 10 +++ .../PublishCollectionModal.tsx | 73 +++++++++++++++++++ .../usePublishCollection.tsx | 55 ++++++++++++++ .../collection/CollectionMockRepository.ts | 7 ++ .../PublishCollectionModal.stories.tsx | 26 +++++++ 9 files changed, 182 insertions(+), 4 deletions(-) create mode 100644 src/sections/collection/publish-collection/PublishCollectionModal.module.scss create mode 100644 src/sections/collection/publish-collection/PublishCollectionModal.tsx create mode 100644 src/sections/collection/publish-collection/usePublishCollection.tsx create mode 100644 src/stories/collection/publish-collection/PublishCollectionModal.stories.tsx diff --git a/public/locales/en/collection.json b/public/locales/en/collection.json index 79a4473af..13765fcee 100644 --- a/public/locales/en/collection.json +++ b/public/locales/en/collection.json @@ -3,5 +3,9 @@ "authenticated": "This collection currently has no datasets. You can add to it by using the Add Data button on this page.", "anonymous": "This collection currently has no datasets. Please <1>log in to see if you are able to add to it." }, - "createdAlert": "You have successfully created your collection! To learn more about what you can do with your collection, check out the User Guide." + "publish": { + "question": "Are you sure you want to publish your collection? Once you do so it must remain published.", + + }, + "createdAlert": "You have successfully created your collection! To learn more about what you can do with your collection, check out the User Guide." } diff --git a/public/locales/en/shared.json b/public/locales/en/shared.json index 55aedf5cd..bf54c2bfd 100644 --- a/public/locales/en/shared.json +++ b/public/locales/en/shared.json @@ -1,5 +1,7 @@ { "asterisksIndicateRequiredFields": "Asterisks indicate required fields", "remove": "Remove", - "add": "Add" + "add": "Add", + "cancel": "Cancel", + "continue": "Continue" } diff --git a/src/collection/domain/useCases/publishCollection.ts b/src/collection/domain/useCases/publishCollection.ts index cea14fca1..0e0805927 100644 --- a/src/collection/domain/useCases/publishCollection.ts +++ b/src/collection/domain/useCases/publishCollection.ts @@ -2,9 +2,9 @@ import { CollectionRepository } from '../repositories/CollectionRepository' export function publishCollection( collectionRepository: CollectionRepository, - collectionId: number | string + id: string ): Promise { - return collectionRepository.publish(collectionId).catch((error: Error) => { + return collectionRepository.publish(id).catch((error: Error) => { throw new Error(error.message) }) } diff --git a/src/sections/Route.enum.ts b/src/sections/Route.enum.ts index cca272366..bf81cadc9 100644 --- a/src/sections/Route.enum.ts +++ b/src/sections/Route.enum.ts @@ -27,5 +27,6 @@ export const RouteWithParams = { export enum QueryParamKey { VERSION = 'version', PERSISTENT_ID = 'persistentId', + COLLECTION_ID = 'collectionId', QUERY = 'q' } diff --git a/src/sections/collection/publish-collection/PublishCollectionModal.module.scss b/src/sections/collection/publish-collection/PublishCollectionModal.module.scss new file mode 100644 index 000000000..9e5edbad1 --- /dev/null +++ b/src/sections/collection/publish-collection/PublishCollectionModal.module.scss @@ -0,0 +1,10 @@ +@import "node_modules/@iqss/dataverse-design-system/src/lib/assets/styles/design-tokens/colors.module"; + +.errorText { + color: $dv-danger-color; +} + +.warningText { + margin-bottom: 0; + color: $dv-warning-color; +} \ No newline at end of file diff --git a/src/sections/collection/publish-collection/PublishCollectionModal.tsx b/src/sections/collection/publish-collection/PublishCollectionModal.tsx new file mode 100644 index 000000000..8dbf4291e --- /dev/null +++ b/src/sections/collection/publish-collection/PublishCollectionModal.tsx @@ -0,0 +1,73 @@ +import { useTranslation } from 'react-i18next' +import { Button, Modal, Stack } from '@iqss/dataverse-design-system' +import { usePublishCollection } from './usePublishCollection' + +import styles from './PublishCollectionModal.module.scss' +import { useNavigate } from 'react-router-dom' +import { QueryParamKey, Route } from '../../Route.enum' +import { CollectionRepository } from '../../../collection/domain/repositories/CollectionRepository' +import { SubmissionStatus } from '../../shared/form/DatasetMetadataForm/useSubmitDataset' + +interface PublishCollectionModalProps { + show: boolean + repository: CollectionRepository + collectionId: string + handleClose: () => void +} + +export function PublishCollectionModal({ + show, + repository, + collectionId, + handleClose +}: PublishCollectionModalProps) { + const { t: tCollection } = useTranslation('collection') + const { t: tShared } = useTranslation('shared') + + const navigate = useNavigate() + const { submissionStatus, submitPublish, publishError } = usePublishCollection( + repository, + collectionId, + onPublishSucceed + ) + + function onPublishSucceed() { + navigate(`${Route.COLLECTIONS}?${QueryParamKey.COLLECTION_ID}=${collectionId}`) + handleClose() + } + + return ( + + + Publish Dataset + + + +

{tCollection('publish.question')}

+ + {submissionStatus === SubmissionStatus.Errored && + `${tCollection('publish.error')} ${publishError ? publishError : ''}`} + +
+
+ + + + +
+ ) +} diff --git a/src/sections/collection/publish-collection/usePublishCollection.tsx b/src/sections/collection/publish-collection/usePublishCollection.tsx new file mode 100644 index 000000000..2a58b7a39 --- /dev/null +++ b/src/sections/collection/publish-collection/usePublishCollection.tsx @@ -0,0 +1,55 @@ +import { useState } from 'react' +import { CollectionRepository } from '../../../collection/domain/repositories/CollectionRepository' +import { publishCollection } from '../../../collection/domain/useCases/publishCollection' + +import { SubmissionStatus } from '../../shared/form/DatasetMetadataForm/useSubmitDataset' + +type UsePublishCollectionReturnType = + | { + submissionStatus: + | SubmissionStatus.NotSubmitted + | SubmissionStatus.IsSubmitting + | SubmissionStatus.SubmitComplete + submitPublish: () => void + publishError: null + } + | { + submissionStatus: SubmissionStatus.Errored + submitPublish: () => void + publishError: string + } + +export function usePublishCollection( + repository: CollectionRepository, + collectionId: string, + onPublishSucceed: () => void +): UsePublishCollectionReturnType { + const [submissionStatus, setSubmissionStatus] = useState( + SubmissionStatus.NotSubmitted + ) + const [publishError, setPublishError] = useState(null) + + const submitPublish = (): void => { + setSubmissionStatus(SubmissionStatus.IsSubmitting) + + publishCollection(repository, collectionId) + .then(() => { + setPublishError(null) + setSubmissionStatus(SubmissionStatus.SubmitComplete) + onPublishSucceed() + return + }) + .catch((err) => { + const errorMessage = err instanceof Error && err.message ? err.message : 'Unknown Error' // TODO: i18n + + setPublishError(errorMessage) + setSubmissionStatus(SubmissionStatus.Errored) + }) + } + + return { + submissionStatus, + submitPublish, + publishError + } as UsePublishCollectionReturnType +} diff --git a/src/stories/collection/CollectionMockRepository.ts b/src/stories/collection/CollectionMockRepository.ts index 6d2030b30..974272771 100644 --- a/src/stories/collection/CollectionMockRepository.ts +++ b/src/stories/collection/CollectionMockRepository.ts @@ -38,4 +38,11 @@ export class CollectionMockRepository implements CollectionRepository { }, FakerHelper.loadingTimout()) }) } + publish(_persistentId: string): Promise { + return new Promise((resolve) => { + setTimeout(() => { + resolve() + }, FakerHelper.loadingTimout()) + }) + } } diff --git a/src/stories/collection/publish-collection/PublishCollectionModal.stories.tsx b/src/stories/collection/publish-collection/PublishCollectionModal.stories.tsx new file mode 100644 index 000000000..77d29092e --- /dev/null +++ b/src/stories/collection/publish-collection/PublishCollectionModal.stories.tsx @@ -0,0 +1,26 @@ +import { Meta, StoryObj } from '@storybook/react' +import { PublishCollectionModal } from '../../../sections/collection/publish-collection/PublishCollectionModal' +import { CollectionMockRepository } from '../CollectionMockRepository' +import { WithI18next } from '../../WithI18next' +import { WithLoggedInUser } from '../../WithLoggedInUser' + +const meta: Meta = { + title: 'Sections/Collection Page/PublishCollectionModal', + component: PublishCollectionModal, + decorators: [WithI18next] +} + +export default meta + +type Story = StoryObj + +export const Default: Story = { + decorators: [WithLoggedInUser], + render: () => ( + {}}> + ) +} From b493f6ef0060d1808f4b4053c830a996ecf90961 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Sun, 22 Sep 2024 10:07:17 -0400 Subject: [PATCH 03/21] test: add PublishCollectionModal.spec.tsx --- public/locales/en/collection.json | 2 +- .../PublishCollectionModal.tsx | 4 +- .../PublishCollectionModal.spec.tsx | 45 +++++++++++++++++++ 3 files changed, 48 insertions(+), 3 deletions(-) create mode 100644 tests/component/sections/collection/collection-publish/PublishCollectionModal.spec.tsx diff --git a/public/locales/en/collection.json b/public/locales/en/collection.json index 13765fcee..b41e2922b 100644 --- a/public/locales/en/collection.json +++ b/public/locales/en/collection.json @@ -5,7 +5,7 @@ }, "publish": { "question": "Are you sure you want to publish your collection? Once you do so it must remain published.", - + "error": "There was an error publishing your collection." }, "createdAlert": "You have successfully created your collection! To learn more about what you can do with your collection, check out the User Guide." } diff --git a/src/sections/collection/publish-collection/PublishCollectionModal.tsx b/src/sections/collection/publish-collection/PublishCollectionModal.tsx index 8dbf4291e..61e3ce8c8 100644 --- a/src/sections/collection/publish-collection/PublishCollectionModal.tsx +++ b/src/sections/collection/publish-collection/PublishCollectionModal.tsx @@ -21,8 +21,8 @@ export function PublishCollectionModal({ collectionId, handleClose }: PublishCollectionModalProps) { - const { t: tCollection } = useTranslation('collection') const { t: tShared } = useTranslation('shared') + const { t: tCollection } = useTranslation('collection') const navigate = useNavigate() const { submissionStatus, submitPublish, publishError } = usePublishCollection( @@ -39,7 +39,7 @@ export function PublishCollectionModal({ return ( - Publish Dataset + Publish Collection diff --git a/tests/component/sections/collection/collection-publish/PublishCollectionModal.spec.tsx b/tests/component/sections/collection/collection-publish/PublishCollectionModal.spec.tsx new file mode 100644 index 000000000..4cb56939e --- /dev/null +++ b/tests/component/sections/collection/collection-publish/PublishCollectionModal.spec.tsx @@ -0,0 +1,45 @@ +import { CollectionRepository } from '../../../../../src/collection/domain/repositories/CollectionRepository' +import { PublishCollectionModal } from '../../../../../src/sections/collection/publish-collection/PublishCollectionModal' + +describe('PublishCollectionModal', () => { + it('displays an error message when publishCollection fails', () => { + const handleClose = cy.stub() + const repository = {} as CollectionRepository // Mock the repository as needed + const errorMessage = 'Publishing failed' + repository.publish = cy.stub().as('repositoryPublish').rejects(new Error(errorMessage)) + + cy.mountAuthenticated( + + ) + + // Trigger the Publish action + cy.findByRole('button', { name: 'Continue' }).click() + + // Check if the error message is displayed + cy.contains(errorMessage).should('exist') + }) + it('renders the PublishDatasetModal and triggers submitPublish on button click', () => { + const handleClose = cy.stub() + const repository = {} as CollectionRepository // Mock the repository as needed + repository.publish = cy.stub().as('repositoryPublish').resolves() + cy.customMount( + + ) + + // Check if the modal is rendered + cy.findByText('Publish Collection').should('exist') + cy.contains('Are you sure you want to publish your collection?').should('exist') + cy.findByText('Continue').click() + cy.get('@repositoryPublish').should('have.been.calledWith', 'testCollectionId') + }) +}) From 9fcf940b93708760613abaa0064fdbe17a3123aa Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Sun, 22 Sep 2024 11:33:50 -0400 Subject: [PATCH 04/21] feat: add Publish Button to Collection page --- public/locales/en/collection.json | 1 + src/sections/collection/Collection.tsx | 8 +++- .../collection/PublishCollectionButton.tsx | 41 +++++++++++++++++++ .../PublishDatasetMenu.tsx | 1 - 4 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 src/sections/collection/PublishCollectionButton.tsx diff --git a/public/locales/en/collection.json b/public/locales/en/collection.json index b41e2922b..375b57a33 100644 --- a/public/locales/en/collection.json +++ b/public/locales/en/collection.json @@ -4,6 +4,7 @@ "anonymous": "This collection currently has no datasets. Please <1>log in to see if you are able to add to it." }, "publish": { + "button": "Publish", "question": "Are you sure you want to publish your collection? Once you do so it must remain published.", "error": "There was an error publishing your collection." }, diff --git a/src/sections/collection/Collection.tsx b/src/sections/collection/Collection.tsx index 8a0e34aed..87fdec104 100644 --- a/src/sections/collection/Collection.tsx +++ b/src/sections/collection/Collection.tsx @@ -15,6 +15,7 @@ import { CollectionInfo } from './CollectionInfo' import { Trans, useTranslation } from 'react-i18next' import { useScrollTop } from '../../shared/hooks/useScrollTop' import { useGetCollectionUserPermissions } from '../../shared/hooks/useGetCollectionUserPermissions' +import { PublishCollectionButton } from './PublishCollectionButton' interface CollectionProps { repository: CollectionRepository @@ -43,7 +44,7 @@ export function Collection({ const canUserAddCollection = Boolean(collectionUserPermissions?.canAddCollection) const canUserAddDataset = Boolean(collectionUserPermissions?.canAddDataset) - + const canUserPublishCollection = user && Boolean(collectionUserPermissions?.canPublishCollection) const showAddDataActions = user && (canUserAddCollection || canUserAddDataset) const { t } = useTranslation('collection') @@ -78,6 +79,11 @@ export function Collection({ /> )} + {canUserPublishCollection && ( +
+ +
+ )} {showAddDataActions && (
{ + setShowModal(true) + } + + return ( + <> + setShowModal(false)} + /> + + + ) +} diff --git a/src/sections/dataset/dataset-action-buttons/publish-dataset-menu/PublishDatasetMenu.tsx b/src/sections/dataset/dataset-action-buttons/publish-dataset-menu/PublishDatasetMenu.tsx index de6b0bd87..bf6fce3ef 100644 --- a/src/sections/dataset/dataset-action-buttons/publish-dataset-menu/PublishDatasetMenu.tsx +++ b/src/sections/dataset/dataset-action-buttons/publish-dataset-menu/PublishDatasetMenu.tsx @@ -27,7 +27,6 @@ export function PublishDatasetMenu({ dataset, datasetRepository }: PublishDatase } const handleSelect = () => { - // TODO - Implement upload files setShowModal(true) } From c1593e1b8ebb30e64fe2c0e0699062bb18aa80ce Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Sun, 22 Sep 2024 11:49:47 -0400 Subject: [PATCH 05/21] fix: add isReleased condition to display button --- src/sections/collection/Collection.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sections/collection/Collection.tsx b/src/sections/collection/Collection.tsx index 87fdec104..01fe49e0c 100644 --- a/src/sections/collection/Collection.tsx +++ b/src/sections/collection/Collection.tsx @@ -79,7 +79,8 @@ export function Collection({ /> )} - {canUserPublishCollection && ( + + {!collection.isReleased && canUserPublishCollection && (
From 76d4e397a3c32c11275206aa8f211220ac1b40d4 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Mon, 23 Sep 2024 14:21:56 -0400 Subject: [PATCH 06/21] fix: navigation to Collections page --- .../publish-collection/PublishCollectionModal.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/sections/collection/publish-collection/PublishCollectionModal.tsx b/src/sections/collection/publish-collection/PublishCollectionModal.tsx index 61e3ce8c8..1c6e2ae16 100644 --- a/src/sections/collection/publish-collection/PublishCollectionModal.tsx +++ b/src/sections/collection/publish-collection/PublishCollectionModal.tsx @@ -4,9 +4,9 @@ import { usePublishCollection } from './usePublishCollection' import styles from './PublishCollectionModal.module.scss' import { useNavigate } from 'react-router-dom' -import { QueryParamKey, Route } from '../../Route.enum' import { CollectionRepository } from '../../../collection/domain/repositories/CollectionRepository' import { SubmissionStatus } from '../../shared/form/DatasetMetadataForm/useSubmitDataset' +import { RouteWithParams } from '../../Route.enum' interface PublishCollectionModalProps { show: boolean @@ -32,7 +32,9 @@ export function PublishCollectionModal({ ) function onPublishSucceed() { - navigate(`${Route.COLLECTIONS}?${QueryParamKey.COLLECTION_ID}=${collectionId}`) + navigate(RouteWithParams.COLLECTIONS(collectionId), { + state: { published: true } + }) handleClose() } From eeb3a8af89074c7ab43c41a93c94243fe67085a8 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Mon, 23 Sep 2024 14:22:35 -0400 Subject: [PATCH 07/21] feat: add Published Alert to Collections page --- public/locales/en/collection.json | 3 ++- src/sections/collection/Collection.tsx | 10 ++++++++-- src/sections/collection/CollectionFactory.tsx | 4 +++- src/sections/collection/useCollection.tsx | 10 +++++++--- 4 files changed, 20 insertions(+), 7 deletions(-) diff --git a/public/locales/en/collection.json b/public/locales/en/collection.json index 375b57a33..d1022e0b1 100644 --- a/public/locales/en/collection.json +++ b/public/locales/en/collection.json @@ -8,5 +8,6 @@ "question": "Are you sure you want to publish your collection? Once you do so it must remain published.", "error": "There was an error publishing your collection." }, - "createdAlert": "You have successfully created your collection! To learn more about what you can do with your collection, check out the User Guide." + "publishedAlert" : "Your collection is now public.", + "createdAlert": "You have successfully created your collection! To learn more about what you can do with your collection, check out the User Guide." } diff --git a/src/sections/collection/Collection.tsx b/src/sections/collection/Collection.tsx index 01fe49e0c..5811890ca 100644 --- a/src/sections/collection/Collection.tsx +++ b/src/sections/collection/Collection.tsx @@ -22,6 +22,7 @@ interface CollectionProps { datasetRepository: DatasetRepository id: string created: boolean + published: boolean page?: number infiniteScrollEnabled?: boolean } @@ -31,12 +32,13 @@ export function Collection({ id, datasetRepository, created, + published, page, infiniteScrollEnabled = false }: CollectionProps) { useScrollTop() const { user } = useSession() - const { collection, isLoading } = useCollection(repository, id) + const { collection, isLoading } = useCollection(repository, id, published) const { collectionUserPermissions } = useGetCollectionUserPermissions({ collectionIdOrAlias: id, collectionRepository: repository @@ -79,7 +81,11 @@ export function Collection({ /> )} - + {published && ( + + {t('publishedAlert')} + + )} {!collection.isReleased && canUserPublishCollection && (
diff --git a/src/sections/collection/CollectionFactory.tsx b/src/sections/collection/CollectionFactory.tsx index 3d6af655c..4758293e6 100644 --- a/src/sections/collection/CollectionFactory.tsx +++ b/src/sections/collection/CollectionFactory.tsx @@ -18,8 +18,9 @@ function CollectionWithSearchParams() { const { collectionId = 'root' } = useParams<{ collectionId: string }>() const location = useLocation() const page = searchParams.get('page') ? parseInt(searchParams.get('page') as string) : undefined - const state = location.state as { created: boolean } | undefined + const state = location.state as { published: boolean; created: boolean } | undefined const created = state?.created ?? false + const published = state?.published ?? false return ( ) diff --git a/src/sections/collection/useCollection.tsx b/src/sections/collection/useCollection.tsx index d75e763a7..77ee0cd39 100644 --- a/src/sections/collection/useCollection.tsx +++ b/src/sections/collection/useCollection.tsx @@ -3,13 +3,17 @@ import { Collection } from '../../collection/domain/models/Collection' import { useEffect, useState } from 'react' import { getCollectionById } from '../../collection/domain/useCases/getCollectionById' -export function useCollection(collectionRepository: CollectionRepository, collectionId: string) { +export function useCollection( + collectionRepository: CollectionRepository, + collectionId: string, + published: boolean +) { const [isLoading, setIsLoading] = useState(true) const [collection, setCollection] = useState() useEffect(() => { setIsLoading(true) - + setCollection(undefined) getCollectionById(collectionRepository, collectionId) .then((collection: Collection | undefined) => { setCollection(collection) @@ -20,7 +24,7 @@ export function useCollection(collectionRepository: CollectionRepository, collec .finally(() => { setIsLoading(false) }) - }, [collectionRepository, collectionId]) + }, [collectionRepository, collectionId, published]) return { collection, isLoading } } From 080b4f2e21b8fe52a14af77dbed5059bbab3069c Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Mon, 23 Sep 2024 14:22:58 -0400 Subject: [PATCH 08/21] test: update component and e2e test --- .../PublishCollectionModal.spec.tsx | 2 +- .../e2e/sections/collection/Collection.spec.ts | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/tests/component/sections/collection/collection-publish/PublishCollectionModal.spec.tsx b/tests/component/sections/collection/collection-publish/PublishCollectionModal.spec.tsx index 4cb56939e..f6051500b 100644 --- a/tests/component/sections/collection/collection-publish/PublishCollectionModal.spec.tsx +++ b/tests/component/sections/collection/collection-publish/PublishCollectionModal.spec.tsx @@ -39,7 +39,7 @@ describe('PublishCollectionModal', () => { // Check if the modal is rendered cy.findByText('Publish Collection').should('exist') cy.contains('Are you sure you want to publish your collection?').should('exist') - cy.findByText('Continue').click() + cy.findByRole('button', { name: 'Continue' }).click() cy.get('@repositoryPublish').should('have.been.calledWith', 'testCollectionId') }) }) diff --git a/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts b/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts index 097db570d..411c7d713 100644 --- a/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts +++ b/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts @@ -31,7 +31,23 @@ describe('Collection Page', () => { cy.findAllByText(title).should('be.visible') }) }) + it('Successfully publishes a collection', () => { + const timestamp = new Date().valueOf() + const uniqueCollectionId = `test-publish-collection-${timestamp}` + cy.wrap(CollectionHelper.create(uniqueCollectionId)) + .its('id') + .then((collectionId: string) => { + console.log('collectionId', collectionId) + cy.visit(`/spa/collections/${collectionId}`) + cy.findByText('Unpublished').should('exist') + cy.findByRole('button', { name: 'Publish' }).click() + cy.findByText(/Publish Collection/i).should('exist') + cy.findByRole('button', { name: 'Continue' }).click() + cy.contains('Your collection is now public.').should('exist') + cy.findByText('Unpublished').should('not.exist') + }) + }) it('Navigates to Create Dataset page when New Dataset link clicked', () => { cy.visit('/spa/collections') From df5308987244764fabeb743beb407af6c1cba591 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Mon, 23 Sep 2024 14:36:06 -0400 Subject: [PATCH 09/21] fix: lint errors --- src/sections/collection/useCollection.tsx | 2 +- src/stories/collection/Collection.stories.tsx | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/sections/collection/useCollection.tsx b/src/sections/collection/useCollection.tsx index 77ee0cd39..74c99159f 100644 --- a/src/sections/collection/useCollection.tsx +++ b/src/sections/collection/useCollection.tsx @@ -6,7 +6,7 @@ import { getCollectionById } from '../../collection/domain/useCases/getCollectio export function useCollection( collectionRepository: CollectionRepository, collectionId: string, - published: boolean + published?: boolean ) { const [isLoading, setIsLoading] = useState(true) const [collection, setCollection] = useState() diff --git a/src/stories/collection/Collection.stories.tsx b/src/stories/collection/Collection.stories.tsx index 92d541d54..269ff71f0 100644 --- a/src/stories/collection/Collection.stories.tsx +++ b/src/stories/collection/Collection.stories.tsx @@ -30,6 +30,7 @@ export const Default: Story = { datasetRepository={new DatasetMockRepository()} id="collection" created={false} + published={false} /> ) } @@ -42,6 +43,7 @@ export const InfiniteScrollingEnabled: Story = { id="collection" infiniteScrollEnabled={true} created={false} + published={false} /> ) } @@ -53,6 +55,7 @@ export const Loading: Story = { datasetRepository={new DatasetLoadingMockRepository()} id="collection" created={false} + published={false} /> ) } @@ -64,6 +67,7 @@ export const NoResults: Story = { datasetRepository={new NoDatasetsMockRepository()} id="collection" created={false} + published={false} /> ) } @@ -76,6 +80,7 @@ export const LoggedIn: Story = { datasetRepository={new DatasetMockRepository()} id="collection" created={false} + published={false} /> ) } @@ -88,6 +93,19 @@ export const Created: Story = { datasetRepository={new NoDatasetsMockRepository()} id="collection" created={true} + published={false} + /> + ) +} +export const Published: Story = { + decorators: [WithLoggedInUser], + render: () => ( + ) } From 063b8569686483c7890deb660ed65b82f52a7b7e Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Mon, 23 Sep 2024 14:41:05 -0400 Subject: [PATCH 10/21] fix: json format --- public/locales/en/collection.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/public/locales/en/collection.json b/public/locales/en/collection.json index d1022e0b1..87fb0b666 100644 --- a/public/locales/en/collection.json +++ b/public/locales/en/collection.json @@ -8,6 +8,6 @@ "question": "Are you sure you want to publish your collection? Once you do so it must remain published.", "error": "There was an error publishing your collection." }, - "publishedAlert" : "Your collection is now public.", + "publishedAlert": "Your collection is now public.", "createdAlert": "You have successfully created your collection! To learn more about what you can do with your collection, check out the User Guide." } From f6f08822689412321b642845291fb1f29f73628a Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Tue, 1 Oct 2024 10:24:07 -0400 Subject: [PATCH 11/21] test: add test that Publish Button doesn't exist --- tests/e2e-integration/e2e/sections/collection/Collection.spec.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts b/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts index 411c7d713..58a226def 100644 --- a/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts +++ b/tests/e2e-integration/e2e/sections/collection/Collection.spec.ts @@ -46,6 +46,7 @@ describe('Collection Page', () => { cy.findByRole('button', { name: 'Continue' }).click() cy.contains('Your collection is now public.').should('exist') cy.findByText('Unpublished').should('not.exist') + cy.findByRole('button', { name: 'Publish' }).should('not.exist') }) }) it('Navigates to Create Dataset page when New Dataset link clicked', () => { From 13b56ee981a41096df476488302472fc421c1a91 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Tue, 1 Oct 2024 10:25:11 -0400 Subject: [PATCH 12/21] format: add space --- src/sections/collection/Collection.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/sections/collection/Collection.tsx b/src/sections/collection/Collection.tsx index 5811890ca..63638ab53 100644 --- a/src/sections/collection/Collection.tsx +++ b/src/sections/collection/Collection.tsx @@ -15,7 +15,7 @@ import { CollectionInfo } from './CollectionInfo' import { Trans, useTranslation } from 'react-i18next' import { useScrollTop } from '../../shared/hooks/useScrollTop' import { useGetCollectionUserPermissions } from '../../shared/hooks/useGetCollectionUserPermissions' -import { PublishCollectionButton } from './PublishCollectionButton' +import { PublishCollectionButton } from './publish-collection/PublishCollectionButton' interface CollectionProps { repository: CollectionRepository @@ -47,6 +47,7 @@ export function Collection({ const canUserAddCollection = Boolean(collectionUserPermissions?.canAddCollection) const canUserAddDataset = Boolean(collectionUserPermissions?.canAddDataset) const canUserPublishCollection = user && Boolean(collectionUserPermissions?.canPublishCollection) + const showAddDataActions = user && (canUserAddCollection || canUserAddDataset) const { t } = useTranslation('collection') From 5e2bd7c8a94bc16d04c7669212a3f3b85ace5f58 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Tue, 1 Oct 2024 10:25:44 -0400 Subject: [PATCH 13/21] fix: Publish button props --- .../PublishCollectionButton.tsx | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) rename src/sections/collection/{ => publish-collection}/PublishCollectionButton.tsx (69%) diff --git a/src/sections/collection/PublishCollectionButton.tsx b/src/sections/collection/publish-collection/PublishCollectionButton.tsx similarity index 69% rename from src/sections/collection/PublishCollectionButton.tsx rename to src/sections/collection/publish-collection/PublishCollectionButton.tsx index a01adfd66..e1d04b373 100644 --- a/src/sections/collection/PublishCollectionButton.tsx +++ b/src/sections/collection/publish-collection/PublishCollectionButton.tsx @@ -1,10 +1,10 @@ import { useTranslation } from 'react-i18next' import { useState } from 'react' -import { CollectionRepository } from '../../collection/domain/repositories/CollectionRepository' -import { PublishCollectionModal } from './publish-collection/PublishCollectionModal' +import { CollectionRepository } from '../../../collection/domain/repositories/CollectionRepository' +import { PublishCollectionModal } from './PublishCollectionModal' import { Button } from '@iqss/dataverse-design-system' import { GlobeAmericas } from 'react-bootstrap-icons' -import styles from '../shared/add-data-actions/AddDataActionsButton.module.scss' +import styles from '../../shared/add-data-actions/AddDataActionsButton.module.scss' interface PublishCollectionButtonProps { repository: CollectionRepository @@ -17,10 +17,6 @@ export function PublishCollectionButton({ const { t } = useTranslation('collection') const [showModal, setShowModal] = useState(false) - const handleSelect = () => { - setShowModal(true) - } - return ( <> } variant="secondary" - onClick={handleSelect} - type="submit"> + onClick={() => setShowModal(true)} + type="button"> {t('publish.button')} From 47ac8bf5e10fe22cf05e30e7bb11a9b45a74b389 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Tue, 1 Oct 2024 10:26:35 -0400 Subject: [PATCH 14/21] fix: render syntax --- .../publish-collection/PublishCollectionModal.stories.tsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/stories/collection/publish-collection/PublishCollectionModal.stories.tsx b/src/stories/collection/publish-collection/PublishCollectionModal.stories.tsx index 77d29092e..4b415ed80 100644 --- a/src/stories/collection/publish-collection/PublishCollectionModal.stories.tsx +++ b/src/stories/collection/publish-collection/PublishCollectionModal.stories.tsx @@ -21,6 +21,7 @@ export const Default: Story = { show={true} repository={new CollectionMockRepository()} collectionId={'testAlias'} - handleClose={() => {}}> + handleClose={() => {}} + /> ) } From 6d1faab6c8561af3c3ac57d93916e079388bee3a Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Tue, 1 Oct 2024 10:27:20 -0400 Subject: [PATCH 15/21] feat: Add centered prop to Modal --- packages/design-system/src/lib/components/modal/Modal.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/packages/design-system/src/lib/components/modal/Modal.tsx b/packages/design-system/src/lib/components/modal/Modal.tsx index daf21f78a..a3d324c33 100644 --- a/packages/design-system/src/lib/components/modal/Modal.tsx +++ b/packages/design-system/src/lib/components/modal/Modal.tsx @@ -8,12 +8,13 @@ import { ModalFooter } from './ModalFooter' interface ModalProps { show: boolean onHide: () => void + centered?: boolean size?: 'sm' | 'lg' | 'xl' } -function Modal({ show, onHide, size, children }: PropsWithChildren) { +function Modal({ show, onHide, centered, size, children }: PropsWithChildren) { return ( - + {children} ) From 6732194c97f003d5e6a4bfa81171c052ce1517d2 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Tue, 1 Oct 2024 10:28:27 -0400 Subject: [PATCH 16/21] fix: Publish Modal appearance, Publish Button props, add translation --- public/locales/en/collection.json | 1 + .../PublishCollectionModal.tsx | 18 +++++++++--------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/public/locales/en/collection.json b/public/locales/en/collection.json index 87fb0b666..7f143849d 100644 --- a/public/locales/en/collection.json +++ b/public/locales/en/collection.json @@ -4,6 +4,7 @@ "anonymous": "This collection currently has no datasets. Please <1>log in to see if you are able to add to it." }, "publish": { + "title": "Publish Collection", "button": "Publish", "question": "Are you sure you want to publish your collection? Once you do so it must remain published.", "error": "There was an error publishing your collection." diff --git a/src/sections/collection/publish-collection/PublishCollectionModal.tsx b/src/sections/collection/publish-collection/PublishCollectionModal.tsx index 1c6e2ae16..09ee47662 100644 --- a/src/sections/collection/publish-collection/PublishCollectionModal.tsx +++ b/src/sections/collection/publish-collection/PublishCollectionModal.tsx @@ -39,25 +39,25 @@ export function PublishCollectionModal({ } return ( - + - Publish Collection + {tCollection('title')}

{tCollection('publish.question')}

- - {submissionStatus === SubmissionStatus.Errored && - `${tCollection('publish.error')} ${publishError ? publishError : ''}`} - + {submissionStatus === SubmissionStatus.Errored && ( +

+ `${tCollection('publish.error')} ${publishError ? publishError : ''}` +

+ )}
From ac783ca592448c9382d92395642104e4235cb8f1 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Tue, 1 Oct 2024 16:31:22 -0400 Subject: [PATCH 17/21] fix: translation label --- .../collection/publish-collection/PublishCollectionModal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sections/collection/publish-collection/PublishCollectionModal.tsx b/src/sections/collection/publish-collection/PublishCollectionModal.tsx index 09ee47662..260ea6b22 100644 --- a/src/sections/collection/publish-collection/PublishCollectionModal.tsx +++ b/src/sections/collection/publish-collection/PublishCollectionModal.tsx @@ -41,7 +41,7 @@ export function PublishCollectionModal({ return ( - {tCollection('title')} + {tCollection('publish.title')} From 43477b8e021dd049efa9f766f5da44f4974b2490 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Thu, 3 Oct 2024 13:35:56 -0400 Subject: [PATCH 18/21] fix: collection.json formatting --- public/locales/en/collection.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/public/locales/en/collection.json b/public/locales/en/collection.json index e41b2e72b..f950adb7f 100644 --- a/public/locales/en/collection.json +++ b/public/locales/en/collection.json @@ -23,12 +23,12 @@ "datasetFilterTypeLabel": "Datasets", "fileFilterTypeLabel": "Files", "searchThisCollectionPlaceholder": "Search this collection...", - "searchSubmitButtonLabel": "Search submit" + "searchSubmitButtonLabel": "Search submit", "publish": { "title": "Publish Collection", "button": "Publish", "question": "Are you sure you want to publish your collection? Once you do so it must remain published.", "error": "There was an error publishing your collection." }, - "publishedAlert": "Your collection is now public.", + "publishedAlert": "Your collection is now public." } From c20f84cf0426209397ca52eb610af2c01a67fb96 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Thu, 3 Oct 2024 13:36:28 -0400 Subject: [PATCH 19/21] fix: Publish Button layout --- src/sections/collection/Collection.module.scss | 6 ++++++ src/sections/collection/Collection.tsx | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/sections/collection/Collection.module.scss b/src/sections/collection/Collection.module.scss index 25af1b00f..dc776bdbd 100644 --- a/src/sections/collection/Collection.module.scss +++ b/src/sections/collection/Collection.module.scss @@ -11,6 +11,12 @@ gap: 10px; } +.action-buttons { + display: flex; + justify-content: flex-end; + margin-bottom: 10px; +} + .subtext { color: $dv-subtext-color; } diff --git a/src/sections/collection/Collection.tsx b/src/sections/collection/Collection.tsx index 58e006f50..0db7f0916 100644 --- a/src/sections/collection/Collection.tsx +++ b/src/sections/collection/Collection.tsx @@ -68,7 +68,7 @@ export function Collection({ )} {!collection.isReleased && canUserPublishCollection && ( -
+
Date: Thu, 3 Oct 2024 14:40:26 -0400 Subject: [PATCH 20/21] test: add Unpublished to Collection.stories.tsx --- src/stories/collection/Collection.stories.tsx | 13 +++++++++++++ .../UnpublishedCollectionMockRepository.ts | 14 ++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/stories/collection/UnpublishedCollectionMockRepository.ts diff --git a/src/stories/collection/Collection.stories.tsx b/src/stories/collection/Collection.stories.tsx index d4477be3e..c56e42f20 100644 --- a/src/stories/collection/Collection.stories.tsx +++ b/src/stories/collection/Collection.stories.tsx @@ -5,6 +5,7 @@ import { WithLayout } from '../WithLayout' import { WithLoggedInUser } from '../WithLoggedInUser' import { CollectionMockRepository } from './CollectionMockRepository' import { CollectionLoadingMockRepository } from './CollectionLoadingMockRepository' +import { UnpublishedCollectionMockRepository } from '@/stories/collection/UnpublishedCollectionMockRepository' const meta: Meta = { title: 'Pages/Collection', @@ -59,6 +60,18 @@ export const LoggedIn: Story = { /> ) } +export const Unpublished: Story = { + decorators: [WithLoggedInUser], + render: () => ( + + ) +} export const Created: Story = { decorators: [WithLoggedInUser], diff --git a/src/stories/collection/UnpublishedCollectionMockRepository.ts b/src/stories/collection/UnpublishedCollectionMockRepository.ts new file mode 100644 index 000000000..c9194f4f7 --- /dev/null +++ b/src/stories/collection/UnpublishedCollectionMockRepository.ts @@ -0,0 +1,14 @@ +import { CollectionMother } from '../../../tests/component/collection/domain/models/CollectionMother' +import { Collection } from '../../collection/domain/models/Collection' +import { FakerHelper } from '../../../tests/component/shared/FakerHelper' +import { CollectionMockRepository } from '@/stories/collection/CollectionMockRepository' + +export class UnpublishedCollectionMockRepository extends CollectionMockRepository { + getById(_id: string): Promise { + return new Promise((resolve) => { + setTimeout(() => { + resolve(CollectionMother.createUnpublished()) + }, FakerHelper.loadingTimout()) + }) + } +} From a9f576b3ad159a84db8a2854f8df1b63b6c978d3 Mon Sep 17 00:00:00 2001 From: Ellen Kraffmiller Date: Thu, 3 Oct 2024 14:59:27 -0400 Subject: [PATCH 21/21] Update src/sections/collection/Collection.module.scss Co-authored-by: German Gonzalo Saracca --- src/sections/collection/Collection.module.scss | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/sections/collection/Collection.module.scss b/src/sections/collection/Collection.module.scss index dc776bdbd..f3d91b901 100644 --- a/src/sections/collection/Collection.module.scss +++ b/src/sections/collection/Collection.module.scss @@ -14,7 +14,7 @@ .action-buttons { display: flex; justify-content: flex-end; - margin-bottom: 10px; + margin-bottom: 1rem; } .subtext {