From 06bf9c3fa5122018cde3f292f957bc4ebb175d93 Mon Sep 17 00:00:00 2001 From: Deep Mistry Date: Tue, 30 Jan 2024 11:54:56 -0500 Subject: [PATCH 1/8] MMT-3494: Added support for Editing a publish record --- .../PublishPreview/PublishPreview.jsx | 49 ++++++++++++++++++- .../js/operations/queries/getCollection.js | 1 + .../src/js/operations/queries/getService.js | 1 + static/src/js/operations/queries/getTool.js | 1 + .../src/js/operations/queries/getVariable.js | 1 + 5 files changed, 51 insertions(+), 2 deletions(-) diff --git a/static/src/js/components/PublishPreview/PublishPreview.jsx b/static/src/js/components/PublishPreview/PublishPreview.jsx index 37b9e68d8..c37f8f8bf 100644 --- a/static/src/js/components/PublishPreview/PublishPreview.jsx +++ b/static/src/js/components/PublishPreview/PublishPreview.jsx @@ -19,6 +19,8 @@ import ErrorBanner from '../ErrorBanner/ErrorBanner' import LoadingBanner from '../LoadingBanner/LoadingBanner' import MetadataPreview from '../MetadataPreview/MetadataPreview' import Page from '../Page/Page' +import { INGEST_DRAFT } from '../../operations/mutations/ingestDraft' +import getUmmVersion from '../../utils/getUmmVersion' /** * Renders a PublishPreview component @@ -39,6 +41,7 @@ const PublishPreview = () => { const [previewMetadata, setPreviewMetadata] = useState() const [showDeleteModal, setShowDeleteModal] = useState(false) + const [ummMetadata, setUmmMetadata] = useState() const [error, setError] = useState() const [retries, setRetries] = useState(0) const [loading, setLoading] = useState(true) @@ -49,6 +52,7 @@ const PublishPreview = () => { const derivedConceptType = getConceptTypeByConceptId(conceptId) + const [ingestDraftMutation] = useMutation(INGEST_DRAFT) const [deleteMutation] = useMutation(deleteMutationTypes[derivedConceptType]) // Calls CMR-Graphql to get the record @@ -63,7 +67,8 @@ const PublishPreview = () => { const { revisionId: savedRevisionId, nativeId: savedNativeId, - providerId: savedProviderId + providerId: savedProviderId, + ummMetadata: savedUmmMetadata } = fetchedMetadata || {} if (!fetchedMetadata || (savedRevisionId && revisionId !== savedRevisionId)) { @@ -76,6 +81,7 @@ const PublishPreview = () => { setNativeId(savedNativeId) setProviderId(savedProviderId) setLoading(false) + setUmmMetadata(savedUmmMetadata) } }, onError: (getDraftError) => { @@ -100,6 +106,26 @@ const PublishPreview = () => { } }, [previewMetadata, retries]) + // Calls ingestDraft mutation with the same nativeId and ummMetadata + // TODO: Need to check if the record trying to edit is in the same provider + const handleEdit = () => { + setLoading(true) + ingestDraftMutation({ + variables: { + conceptType: derivedConceptType, + metadata: ummMetadata, + nativeId, + providerId, + ummVersion: getUmmVersion(derivedConceptType) + }, + onCompleted: (mutationData) => { + const { ingestDraft } = mutationData + const { conceptId: draftConceptId } = ingestDraft + navigate(`/drafts/${pluralize(derivedConceptType).toLowerCase()}/${draftConceptId}`) + } + }) + } + // Handles the user selecting delete from the delete model const handleDelete = () => { deleteMutation({ @@ -158,6 +184,24 @@ const PublishPreview = () => { + {/* Edit Publish record link */} + + {/* Delete Publish record button */} - + {/* Renders the Delete Modal */} { + {/* Renders the Metadata Preview */} Date: Tue, 30 Jan 2024 12:20:59 -0500 Subject: [PATCH 2/8] MMT-3494: Added test cases for edit button --- .../PublishPreview/PublishPreview.jsx | 6 ++ .../__tests__/PublishPreview.test.js | 75 +++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/static/src/js/components/PublishPreview/PublishPreview.jsx b/static/src/js/components/PublishPreview/PublishPreview.jsx index c37f8f8bf..6ec80c073 100644 --- a/static/src/js/components/PublishPreview/PublishPreview.jsx +++ b/static/src/js/components/PublishPreview/PublishPreview.jsx @@ -122,6 +122,12 @@ const PublishPreview = () => { const { ingestDraft } = mutationData const { conceptId: draftConceptId } = ingestDraft navigate(`/drafts/${pluralize(derivedConceptType).toLowerCase()}/${draftConceptId}`) + }, + onError: (getMutationError) => { + setError(getMutationError) + setLoading(false) + // Send the error to the errorLogger + errorLogger(getMutationError, 'PublishPreview ingestDraftMutation Query') } }) } diff --git a/static/src/js/components/PublishPreview/__tests__/PublishPreview.test.js b/static/src/js/components/PublishPreview/__tests__/PublishPreview.test.js index 9bca15e40..7c7be7aa4 100644 --- a/static/src/js/components/PublishPreview/__tests__/PublishPreview.test.js +++ b/static/src/js/components/PublishPreview/__tests__/PublishPreview.test.js @@ -16,6 +16,7 @@ import errorLogger from '../../../utils/errorLogger' import ErrorBanner from '../../ErrorBanner/ErrorBanner' import { GET_TOOL } from '../../../operations/queries/getTool' import { DELETE_TOOL } from '../../../operations/mutations/deleteTool' +import { INGEST_DRAFT } from '../../../operations/mutations/ingestDraft' jest.mock('../../MetadataPreview/MetadataPreview') jest.mock('../../ErrorBanner/ErrorBanner') @@ -76,6 +77,7 @@ const mock = { } ], type: 'Web User Interface', + ummMetadata: {}, url: { urlContentType: 'DistributionURL', type: 'DOWNLOAD SOFTWARE', @@ -194,6 +196,7 @@ describe('PublishPreview', () => { } ], type: 'Web User Interface', + ummMetadata: {}, url: { subtype: 'MOBILE APP', type: 'DOWNLOAD SOFTWARE', @@ -368,4 +371,76 @@ describe('PublishPreview', () => { expect(navigateSpy).toHaveBeenCalledTimes(0) }) }) + + describe('when clicking on Edit Tool Record button', () => { + test('calls the ingestDraftMutation and navigates to /drafts/tool/conceptId page', async () => { + const navigateSpy = jest.fn() + jest.spyOn(router, 'useNavigate').mockImplementation(() => navigateSpy) + + const { user } = setup({ + additionalMocks: [{ + request: { + query: INGEST_DRAFT, + variables: { + conceptType: 'Tool', + metadata: {}, + nativeId: 'MMT_PUBLISH_8b8a1965-67a5-415c-ae4c-8ecbafd84131', + providerId: 'MMT_2', + ummVersion: '1.2.0' + } + }, + result: { + data: { + ingestDraft: { + conceptId: 'TD1000000-MMT', + revisionId: '3' + } + } + } + }] + }) + + await waitForResponse() + + const editButton = screen.getByRole('button', { name: 'Edit Tool Record' }) + await user.click(editButton) + + await waitForResponse() + + expect(navigateSpy).toHaveBeenCalledTimes(1) + expect(navigateSpy).toHaveBeenCalledWith('/drafts/tools/TD1000000-MMT') + }) + + test('when ingest mutation returns an error', async () => { + const navigateSpy = jest.fn() + jest.spyOn(router, 'useNavigate').mockImplementation(() => navigateSpy) + + const { user } = setup({ + additionalMocks: [{ + request: { + query: INGEST_DRAFT, + variables: { + conceptType: 'Tool', + nativeId: 'MMT_PUBLISH_8b8a1965-67a5-415c-ae4c-8ecbafd84131', + metadata: {}, + providerId: 'MMT_2', + ummVersion: '1.2.0' + } + }, + error: new Error('An error occurred') + }] + }) + + await waitForResponse() + + const editButton = screen.getByRole('button', { name: 'Edit Tool Record' }) + await user.click(editButton) + + await waitForResponse() + + expect(navigateSpy).toHaveBeenCalledTimes(0) + expect(errorLogger).toHaveBeenCalledTimes(1) + expect(errorLogger).toHaveBeenCalledWith(new Error('An error occurred'), 'PublishPreview ingestDraftMutation Query') + }) + }) }) From 9999f5e88d153b7f461db4b2b204203967e0142c Mon Sep 17 00:00:00 2001 From: Deep Mistry Date: Tue, 30 Jan 2024 14:50:47 -0500 Subject: [PATCH 3/8] MMT-3494: Moved ingestMutation in a hook --- .../PublishPreview/PublishPreview.jsx | 35 ++++---------- static/src/js/hooks/useIngestDraftMutation.js | 48 +++++++++++++++++++ 2 files changed, 56 insertions(+), 27 deletions(-) create mode 100644 static/src/js/hooks/useIngestDraftMutation.js diff --git a/static/src/js/components/PublishPreview/PublishPreview.jsx b/static/src/js/components/PublishPreview/PublishPreview.jsx index 6ec80c073..48143111f 100644 --- a/static/src/js/components/PublishPreview/PublishPreview.jsx +++ b/static/src/js/components/PublishPreview/PublishPreview.jsx @@ -19,8 +19,8 @@ import ErrorBanner from '../ErrorBanner/ErrorBanner' import LoadingBanner from '../LoadingBanner/LoadingBanner' import MetadataPreview from '../MetadataPreview/MetadataPreview' import Page from '../Page/Page' -import { INGEST_DRAFT } from '../../operations/mutations/ingestDraft' -import getUmmVersion from '../../utils/getUmmVersion' +import useAppContext from '../../hooks/useAppContext' +import useIngestDraftMutation from '../../hooks/useIngestDraftMutation' /** * Renders a PublishPreview component @@ -37,6 +37,8 @@ const PublishPreview = () => { revisionId } = useParams() + const { user } = useAppContext() + const { providerId } = user const navigate = useNavigate() const [previewMetadata, setPreviewMetadata] = useState() @@ -46,13 +48,14 @@ const PublishPreview = () => { const [retries, setRetries] = useState(0) const [loading, setLoading] = useState(true) const [nativeId, setNativeId] = useState() - const [providerId, setProviderId] = useState() + // Const [providerId, setProviderId] = useState() const { addNotification } = useNotificationsContext() const derivedConceptType = getConceptTypeByConceptId(conceptId) - const [ingestDraftMutation] = useMutation(INGEST_DRAFT) + const ingestMutation = useIngestDraftMutation() + const [deleteMutation] = useMutation(deleteMutationTypes[derivedConceptType]) // Calls CMR-Graphql to get the record @@ -67,7 +70,6 @@ const PublishPreview = () => { const { revisionId: savedRevisionId, nativeId: savedNativeId, - providerId: savedProviderId, ummMetadata: savedUmmMetadata } = fetchedMetadata || {} @@ -79,7 +81,6 @@ const PublishPreview = () => { // The correct version of the metadata has been fetched setPreviewMetadata(fetchedMetadata) setNativeId(savedNativeId) - setProviderId(savedProviderId) setLoading(false) setUmmMetadata(savedUmmMetadata) } @@ -109,27 +110,7 @@ const PublishPreview = () => { // Calls ingestDraft mutation with the same nativeId and ummMetadata // TODO: Need to check if the record trying to edit is in the same provider const handleEdit = () => { - setLoading(true) - ingestDraftMutation({ - variables: { - conceptType: derivedConceptType, - metadata: ummMetadata, - nativeId, - providerId, - ummVersion: getUmmVersion(derivedConceptType) - }, - onCompleted: (mutationData) => { - const { ingestDraft } = mutationData - const { conceptId: draftConceptId } = ingestDraft - navigate(`/drafts/${pluralize(derivedConceptType).toLowerCase()}/${draftConceptId}`) - }, - onError: (getMutationError) => { - setError(getMutationError) - setLoading(false) - // Send the error to the errorLogger - errorLogger(getMutationError, 'PublishPreview ingestDraftMutation Query') - } - }) + ingestMutation(derivedConceptType, ummMetadata, nativeId, providerId) } // Handles the user selecting delete from the delete model diff --git a/static/src/js/hooks/useIngestDraftMutation.js b/static/src/js/hooks/useIngestDraftMutation.js new file mode 100644 index 000000000..4f2cc5671 --- /dev/null +++ b/static/src/js/hooks/useIngestDraftMutation.js @@ -0,0 +1,48 @@ +import { useMutation } from '@apollo/client' +import pluralize from 'pluralize' +import { useNavigate } from 'react-router' +import { INGEST_DRAFT } from '../operations/mutations/ingestDraft' +import getUmmVersion from '../utils/getUmmVersion' +import errorLogger from '../utils/errorLogger' +import useNotificationsContext from './useNotificationsContext' + +const useIngestDraftMutation = () => { + const [ingestDraftMutation] = useMutation(INGEST_DRAFT) + + const navigate = useNavigate() + + const { addNotification } = useNotificationsContext() + + const ingestMutation = (conceptType, metadata, nativeId, providerId) => { + ingestDraftMutation({ + variables: { + conceptType, + metadata, + nativeId, + providerId, + ummVersion: getUmmVersion(conceptType) + }, + onCompleted: (getDraftData) => { + const { ingestDraft } = getDraftData + const { conceptId } = ingestDraft + navigate(`/drafts/${pluralize(conceptType).toLowerCase()}/${conceptId}`) + addNotification({ + message: 'Draft created successfully', + variant: 'success' + }) + }, + onError: (getMutationError) => { + // Send the error to the errorLogger + errorLogger(getMutationError, 'PublishPreview ingestDraftMutation Query') + addNotification({ + message: 'Error creating draft', + variant: 'danger' + }) + } + }) + } + + return ingestMutation +} + +export default useIngestDraftMutation From a9120fbbed5457193aac7d54f446feab3ecd5905 Mon Sep 17 00:00:00 2001 From: Deep Mistry Date: Wed, 31 Jan 2024 09:13:48 -0500 Subject: [PATCH 4/8] MMT-3494: Removed one comment --- static/src/js/components/PublishPreview/PublishPreview.jsx | 1 - 1 file changed, 1 deletion(-) diff --git a/static/src/js/components/PublishPreview/PublishPreview.jsx b/static/src/js/components/PublishPreview/PublishPreview.jsx index 48143111f..b803c6102 100644 --- a/static/src/js/components/PublishPreview/PublishPreview.jsx +++ b/static/src/js/components/PublishPreview/PublishPreview.jsx @@ -48,7 +48,6 @@ const PublishPreview = () => { const [retries, setRetries] = useState(0) const [loading, setLoading] = useState(true) const [nativeId, setNativeId] = useState() - // Const [providerId, setProviderId] = useState() const { addNotification } = useNotificationsContext() From c69e436211d8b1d1f69b4fb20094aca47eff169f Mon Sep 17 00:00:00 2001 From: Deep Mistry Date: Wed, 31 Jan 2024 13:39:27 -0500 Subject: [PATCH 5/8] MMT-3494: Added loading when the user clicks publish btn --- static/src/js/components/DraftPreview/DraftPreview.jsx | 1 + 1 file changed, 1 insertion(+) diff --git a/static/src/js/components/DraftPreview/DraftPreview.jsx b/static/src/js/components/DraftPreview/DraftPreview.jsx index 9ba9b5440..4750cf58a 100644 --- a/static/src/js/components/DraftPreview/DraftPreview.jsx +++ b/static/src/js/components/DraftPreview/DraftPreview.jsx @@ -168,6 +168,7 @@ const DraftPreview = () => { // Handle the user selecting publish draft const handlePublish = () => { // Calls publish mutation hook + setLoading(true) publishMutation(derivedConceptType, nativeId) } From 9468ded50bcfcbd3a714ea2874f38321f44e815b Mon Sep 17 00:00:00 2001 From: Deep Mistry Date: Wed, 31 Jan 2024 13:59:42 -0500 Subject: [PATCH 6/8] MMT-3553: Added support for Cloning a Publish record --- .../PublishPreview/PublishPreview.jsx | 27 +++++++++++ .../__tests__/PublishPreview.test.js | 46 +++++++++++++++++++ .../__tests__/removeMetadataKeys.test.js | 16 +++++++ static/src/js/utils/removeMetadataKeys.js | 16 +++++++ 4 files changed, 105 insertions(+) create mode 100644 static/src/js/utils/__tests__/removeMetadataKeys.test.js create mode 100644 static/src/js/utils/removeMetadataKeys.js diff --git a/static/src/js/components/PublishPreview/PublishPreview.jsx b/static/src/js/components/PublishPreview/PublishPreview.jsx index b803c6102..84b5853f0 100644 --- a/static/src/js/components/PublishPreview/PublishPreview.jsx +++ b/static/src/js/components/PublishPreview/PublishPreview.jsx @@ -21,6 +21,7 @@ import MetadataPreview from '../MetadataPreview/MetadataPreview' import Page from '../Page/Page' import useAppContext from '../../hooks/useAppContext' import useIngestDraftMutation from '../../hooks/useIngestDraftMutation' +import removeMetadataKeys from '../../utils/removeMetadataKeys' /** * Renders a PublishPreview component @@ -112,6 +113,15 @@ const PublishPreview = () => { ingestMutation(derivedConceptType, ummMetadata, nativeId, providerId) } + // Calls ingestDraft mutation with a new nativeId + const handleClone = () => { + const cloneNativeId = `MMT_${crypto.randomUUID()}` + // Removes the value from the metadata that has to be unique + removeMetadataKeys(ummMetadata, ['Name', 'LongName', 'ShortName']) + + ingestMutation(derivedConceptType, ummMetadata, cloneNativeId, providerId) + } + // Handles the user selecting delete from the delete model const handleDelete = () => { deleteMutation({ @@ -187,6 +197,23 @@ const PublishPreview = () => { {' '} Record + {/* Clone Publish record link */} + {/* Delete Publish record button */} - {/* Delete Publish record button */} - {/* Renders the Delete Modal */} { - {/* Renders the Metadata Preview */} Date: Thu, 1 Feb 2024 11:25:21 -0500 Subject: [PATCH 8/8] MMT-3553: Addressed PR comments --- .../js/components/PublishPreview/PublishPreview.jsx | 5 ----- static/src/js/utils/removeMetadataKeys.js | 11 +++++++---- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/static/src/js/components/PublishPreview/PublishPreview.jsx b/static/src/js/components/PublishPreview/PublishPreview.jsx index 84b5853f0..c7b74c6b0 100644 --- a/static/src/js/components/PublishPreview/PublishPreview.jsx +++ b/static/src/js/components/PublishPreview/PublishPreview.jsx @@ -180,7 +180,6 @@ const PublishPreview = () => { - {/* Edit Publish record link */} - {/* Clone Publish record link */} - {/* Delete Publish record button */} - {/* Renders the Delete Modal */} { - {/* Renders the Metadata Preview */} { - keys.forEach((key) => { - // eslint-disable-next-line no-param-reassign - delete metadata[key] + const modifiedMetadata = metadata + + Object.keys(metadata).forEach((key) => { + if (keys.includes(key)) { + delete modifiedMetadata[key] + } }) - return metadata + return modifiedMetadata } export default removeMetadataKeys