From 6d542d9da0afbaa50d752bcadc33d36dbead16bb Mon Sep 17 00:00:00 2001 From: vashjs Date: Tue, 21 Jan 2025 10:09:19 +0100 Subject: [PATCH 1/6] UIBULKED-570 Downloading files from Logs tab --- CHANGELOG.md | 1 + .../BulkEditLogsActions.js | 13 ++++++---- src/components/BulkEditPane/BulkEditPane.js | 12 +++++---- src/constants/files.js | 8 +++--- src/constants/logsActions.js | 4 +-- src/utils/files.js | 20 --------------- src/utils/files.test.js | 25 +------------------ translations/ui-bulk-edit/en.json | 18 ++++++------- 8 files changed, 32 insertions(+), 69 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 88baa25e..a4163a63 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ * [UIBULKED-543](https://folio-org.atlassian.net/browse/UIBULKED-543) Rename Find (full field search) to Find. * [UIBULKED-599](https://folio-org.atlassian.net/browse/UIBULKED-599) Change Administrative note type is not supported for MARC instances. * [UIBULKED-597](https://folio-org.atlassian.net/browse/UIBULKED-597) Commit changes button enabled before preview is populated +* [UIBULKED-570](https://folio-org.atlassian.net/browse/UIBULKED-570) Downloading files from Logs tab ## [4.2.2](https://github.com/folio-org/ui-bulk-edit/tree/v4.2.2) (2024-11-15) diff --git a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.js b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.js index 3da8acff..3e6abf02 100644 --- a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.js +++ b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.js @@ -4,7 +4,6 @@ import React, { useEffect, } from 'react'; import PropTypes from 'prop-types'; -import { saveAs } from 'file-saver'; import { IconButton, DropdownMenu, @@ -18,10 +17,10 @@ import { FormattedMessage } from 'react-intl'; import { QUERY_KEY_DOWNLOAD_LOGS, useFileDownload } from '../../../hooks/api'; import { APPROACHES, CAPABILITIES, linkNamesMap } from '../../../constants'; import { useBulkPermissions } from '../../../hooks'; -import { getFileName } from '../../../utils/files'; +import { savePreviewFile } from '../../../utils/files'; const BulkEditLogsActions = ({ item }) => { - const fileNamePostfix = item.fqlQueryId ? `.${APPROACHES.QUERY}` : ''; + const fileNamePostfix = item?.fqlQueryId ? `.${APPROACHES.QUERY}` : ''; const { hasUsersViewPerms, @@ -34,8 +33,12 @@ const BulkEditLogsActions = ({ item }) => { enabled: false, id: item.id, fileContentType: linkNamesMap[triggeredFile], - onSuccess: data => { - saveAs(new Blob([data]), getFileName(item, triggeredFile)); + onSuccess: fileData => { + savePreviewFile({ + fileName: item?.[triggeredFile], + fileData, + }); + setTriggeredFile(null); }, }); diff --git a/src/components/BulkEditPane/BulkEditPane.js b/src/components/BulkEditPane/BulkEditPane.js index c4d48bd3..55582759 100644 --- a/src/components/BulkEditPane/BulkEditPane.js +++ b/src/components/BulkEditPane/BulkEditPane.js @@ -1,6 +1,5 @@ import React, { useCallback, useMemo, useState } from 'react'; import { FormattedMessage } from 'react-intl'; -import { saveAs } from 'file-saver'; import { Pane, @@ -38,6 +37,7 @@ import { useResetFilters } from '../../hooks/useResetFilters'; import { BulkEditInAppLayer } from './BulkEditInAppLayer/BulkEditInAppLayer'; import { BulkEditMarcLayer } from './BulkEditMarcLayer/BulkEditMarcLayer'; +import { savePreviewFile } from '../../utils/files'; export const BulkEditPane = () => { const [isFileUploaded, setIsFileUploaded] = useState(false); @@ -103,10 +103,12 @@ export const BulkEditPane = () => { queryKey: QUERY_KEY_DOWNLOAD_ACTION_MENU, enabled: !!fileInfo, id: bulkOperationId, - fileContentType: FILE_SEARCH_PARAMS[fileInfo?.param]?.replace('_MARC', ''), - onSuccess: data => { - /* istanbul ignore next */ - saveAs(new Blob([data]), fileInfo?.bulkDetails[FILE_TO_LINK[fileInfo?.param]].split('/')[1]); + fileContentType: FILE_SEARCH_PARAMS[fileInfo?.param], + onSuccess: fileData => { + savePreviewFile({ + fileData, + fileName: fileInfo?.bulkDetails[FILE_TO_LINK[fileInfo?.param]], + }); }, onSettled: () => { /* istanbul ignore next */ diff --git a/src/constants/files.js b/src/constants/files.js index 33e8ca97..0350ef15 100644 --- a/src/constants/files.js +++ b/src/constants/files.js @@ -19,10 +19,10 @@ export const FILE_SEARCH_PARAMS = { MATCHED_RECORDS_FILE: 'MATCHED_RECORDS_FILE', RECORD_MATCHING_ERROR_FILE: 'RECORD_MATCHING_ERROR_FILE', COMMITTED_RECORDS_FILE: 'COMMITTED_RECORDS_FILE', + COMMITTED_RECORDS_MARC_FILE: 'COMMITTED_RECORDS_MARC_FILE', COMMITTING_CHANGES_ERROR_FILE: 'COMMITTING_CHANGES_ERROR_FILE', PROPOSED_CHANGES_FILE: 'PROPOSED_CHANGES_FILE', PROPOSED_CHANGES_MARC_FILE: 'PROPOSED_CHANGES_MARC_FILE', - COMMITTED_RECORDS_FILE_MARC: 'COMMITTED_RECORDS_FILE_MARC', }; export const FILE_TO_LINK = { @@ -31,14 +31,14 @@ export const FILE_TO_LINK = { COMMITTED_RECORDS_FILE: 'linkToCommittedRecordsCsvFile', COMMITTING_CHANGES_ERROR_FILE: 'linkToCommittedRecordsErrorsCsvFile', PROPOSED_CHANGES_FILE: 'linkToModifiedRecordsCsvFile', - COMMITTED_RECORDS_FILE_MARC: 'linkToCommittedRecordsMarcFile' + COMMITTED_RECORDS_MARC_FILE: 'linkToCommittedRecordsMarcFile' }; export const getDownloadLinks = ({ perms, step }) => [ { KEY: FILE_KEYS.MATCHING_RECORDS_LINK, SEARCH_PARAM: FILE_SEARCH_PARAMS.MATCHED_RECORDS_FILE, - LINK_NAME: , + LINK_NAME: , IS_VISIBLE: perms.hasAnyEditPermissions && step === EDITING_STEPS.UPLOAD, }, { @@ -49,7 +49,7 @@ export const getDownloadLinks = ({ perms, step }) => [ }, { KEY: FILE_KEYS.UPDATE_CHANGES_LINK_MARC, - SEARCH_PARAM: FILE_SEARCH_PARAMS.COMMITTED_RECORDS_FILE_MARC, + SEARCH_PARAM: FILE_SEARCH_PARAMS.COMMITTED_RECORDS_MARC_FILE, LINK_NAME: , IS_VISIBLE: perms.hasAnyEditPermissions, }, diff --git a/src/constants/logsActions.js b/src/constants/logsActions.js index 469d47fb..6db1b7d1 100644 --- a/src/constants/logsActions.js +++ b/src/constants/logsActions.js @@ -3,8 +3,8 @@ export const linkNamesMap = { linkToMatchedRecordsCsvFile: 'MATCHED_RECORDS_FILE', linkToMatchedRecordsErrorsCsvFile: 'RECORD_MATCHING_ERROR_FILE', linkToModifiedRecordsCsvFile: 'PROPOSED_CHANGES_FILE', - linkToModifiedRecordsMarcFile: 'PROPOSED_CHANGES_FILE', - linkToCommittedRecordsMarcFile: 'COMMITTED_RECORDS_FILE', + linkToModifiedRecordsMarcFile: 'PROPOSED_CHANGES_MARC_FILE', + linkToCommittedRecordsMarcFile: 'COMMITTED_RECORDS_FILE_MARC', linkToCommittedRecordsCsvFile: 'COMMITTED_RECORDS_FILE', linkToCommittedRecordsErrorsCsvFile: 'COMMITTING_CHANGES_ERROR_FILE', expired: 'expired', diff --git a/src/utils/files.js b/src/utils/files.js index b7ef7ea9..5a38e7c5 100644 --- a/src/utils/files.js +++ b/src/utils/files.js @@ -1,25 +1,5 @@ import { saveAs } from 'file-saver'; -import { getFormattedFilePrefixDate } from './date'; - - -export const getFileName = (item, triggeredFile) => { - if (item.fqlQueryId) { - return { - linkToTriggeringCsvFile: `Query-${item.id}.csv`, - linkToMatchedRecordsCsvFile: `${getFormattedFilePrefixDate()}-Matched-Records-Query-${item.id}.csv`, - linkToModifiedRecordsCsvFile: `${getFormattedFilePrefixDate()}-Updates-Preview-Query-${item.id}.csv`, - linkToModifiedRecordsMarcFile: `${getFormattedFilePrefixDate()}-Updates-Preview-Query-${item.id}.mrc`, - linkToCommittedRecordsCsvFile: `${getFormattedFilePrefixDate()}-Changed-Records-Query-${item.id}.csv`, - linkToCommittedRecordsMarcFile: `${getFormattedFilePrefixDate()}-Changed-Records-Query-${item.id}.mrc`, - linkToCommittedRecordsErrorsCsvFile: `${getFormattedFilePrefixDate()}-Committing-changes-Errors-Query-${item.id}.csv`, - linkToMatchedRecordsErrorsCsvFile:`${getFormattedFilePrefixDate()}-Matching-Records-Errors-Query-${item.id}.csv`, - }[triggeredFile]; - } - - return item[triggeredFile].split('/')[1]; -}; - export const changeExtension = (fileName, extension) => { if (!fileName) return fileName; diff --git a/src/utils/files.test.js b/src/utils/files.test.js index 052a1c9c..094441fc 100644 --- a/src/utils/files.test.js +++ b/src/utils/files.test.js @@ -1,6 +1,6 @@ import { saveAs } from 'file-saver'; -import { getFileName, changeExtension, savePreviewFile } from './files'; +import { changeExtension, savePreviewFile } from './files'; import { getFormattedFilePrefixDate } from './date'; @@ -14,29 +14,6 @@ jest.mock('file-saver', () => ({ describe('files', () => { - describe('getFileName', () => { - it('should return the correct file name for Query approach - linkToTriggeringCsvFile', () => { - const item = { fqlQueryId: '111', id: 123 }; - const triggeredFile = 'linkToTriggeringCsvFile'; - const result = getFileName(item, triggeredFile); - expect(result).toBe('Query-123.csv'); - }); - - it('should return the correct file name for Query approach - linkToMatchedRecordsCsvFile', () => { - const item = { fqlQueryId: '111', id: 123 }; - const triggeredFile = 'linkToMatchedRecordsCsvFile'; - const result = getFileName(item, triggeredFile); - expect(result).toBe('mockedDate-Matched-Records-Query-123.csv'); - }); - - it('should return the correct file name for non-Query approach', () => { - const item = { fqlQueryId: null, linkToTriggeringCsvFile: 'somePath/someFile.csv' }; - const triggeredFile = 'linkToTriggeringCsvFile'; - const result = getFileName(item, triggeredFile); - expect(result).toBe('someFile.csv'); - }); - }); - describe('changeExtension', () => { it('should change the extension of a file', () => { expect(changeExtension('abc.csv', 'mrc')).toBe('abc.mrc'); diff --git a/translations/ui-bulk-edit/en.json b/translations/ui-bulk-edit/en.json index e4eccfbb..ee1ad36c 100644 --- a/translations/ui-bulk-edit/en.json +++ b/translations/ui-bulk-edit/en.json @@ -148,7 +148,7 @@ "textArea.resetAll": "Reset all", "start.downloadErrors": "Download errors (CSV)", - "start.downloadMathcedRecords": "Download matched records (CSV)", + "start.downloadMatchedRecords": "Download matched records (CSV)", "start.downloadChangedRecords": "Download changed records (CSV)", "start.downloadChangedRecords.marc": "Download changed records (MARC)", @@ -455,19 +455,19 @@ "logs.actions.linkToTriggeringCsvFile": "File that was used to trigger the bulk edit", "logs.actions.linkToMatchedRecordsCsvFile": "File with the matching records", "logs.actions.linkToMatchedRecordsErrorsCsvFile": "File with errors encountered during the record matching", - "logs.actions.linkToModifiedRecordsCsvFile": "File with the preview of proposed changes", - "logs.actions.linkToModifiedRecordsMarcFile": "File with the preview of proposed changes", - "logs.actions.linkToCommittedRecordsCsvFile": "File with updated records", - "logs.actions.linkToCommittedRecordsMarcFile": "File with updated records", + "logs.actions.linkToModifiedRecordsCsvFile": "File with the preview of proposed changes (CSV)", + "logs.actions.linkToModifiedRecordsMarcFile": "File with the preview of proposed changes (MARC)", + "logs.actions.linkToCommittedRecordsCsvFile": "File with updated records (CSV)", + "logs.actions.linkToCommittedRecordsMarcFile": "File with updated records (MARC)", "logs.actions.linkToCommittedRecordsErrorsCsvFile": "File with errors encountered when committing the changes", "logs.actions.linkToTriggeringCsvFile.QUERY": "File with identifiers of the records affected by bulk update", "logs.actions.linkToMatchedRecordsCsvFile.QUERY": "File with the matching records", "logs.actions.linkToMatchedRecordsErrorsCsvFile.QUERY": "File with errors encountered during the record matching", - "logs.actions.linkToModifiedRecordsCsvFile.QUERY": "File with the preview of proposed changes", - "logs.actions.linkToModifiedRecordsMarcFile.QUERY": "File with the preview of proposed changes", - "logs.actions.linkToCommittedRecordsCsvFile.QUERY": "File with updated records", + "logs.actions.linkToModifiedRecordsCsvFile.QUERY": "File with the preview of proposed changes (CSV)", + "logs.actions.linkToModifiedRecordsMarcFile.QUERY": "File with the preview of proposed changes (MARC)", + "logs.actions.linkToCommittedRecordsCsvFile.QUERY": "File with updated records (CSV)", "logs.actions.linkToCommittedRecordsErrorsCsvFile.QUERY": "File with errors encountered when committing the changes", - "logs.actions.linkToCommittedRecordsMarcFile.QUERY": "File with updated records", + "logs.actions.linkToCommittedRecordsMarcFile.QUERY": "File with updated records (MARC)", "logs.filter.title.status": "Statuses", "logs.filter.title.capability": "Record types", "logs.filter.title.types": "Bulk operation type", From af2cfcb31c45e0ac986c3d0918db8186f57f8d9f Mon Sep 17 00:00:00 2001 From: vashjs Date: Tue, 21 Jan 2025 15:08:27 +0100 Subject: [PATCH 2/6] update constants --- .../BulkEditLogsActions.js | 6 +-- src/components/BulkEditPane/BulkEditPane.js | 4 +- src/constants/files.js | 52 ++++++++++--------- src/constants/index.js | 1 - src/constants/logsActions.js | 11 ---- src/utils/formatters.js | 4 +- 6 files changed, 35 insertions(+), 43 deletions(-) delete mode 100644 src/constants/logsActions.js diff --git a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.js b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.js index 3e6abf02..5d5bc2ff 100644 --- a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.js +++ b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.js @@ -15,7 +15,7 @@ import { } from '@folio/stripes/components'; import { FormattedMessage } from 'react-intl'; import { QUERY_KEY_DOWNLOAD_LOGS, useFileDownload } from '../../../hooks/api'; -import { APPROACHES, CAPABILITIES, linkNamesMap } from '../../../constants'; +import { APPROACHES, CAPABILITIES, LINK_KEYS } from '../../../constants'; import { useBulkPermissions } from '../../../hooks'; import { savePreviewFile } from '../../../utils/files'; @@ -32,7 +32,7 @@ const BulkEditLogsActions = ({ item }) => { queryKey: QUERY_KEY_DOWNLOAD_LOGS, enabled: false, id: item.id, - fileContentType: linkNamesMap[triggeredFile], + fileContentType: LINK_KEYS[triggeredFile], onSuccess: fileData => { savePreviewFile({ fileName: item?.[triggeredFile], @@ -53,7 +53,7 @@ const BulkEditLogsActions = ({ item }) => { setTriggeredFile(file); }; - const availableFiles = Object.keys(linkNamesMap).filter(linkName => item[linkName]); + const availableFiles = Object.keys(LINK_KEYS).filter(linkName => item[linkName]); const renderTrigger = useCallback(({ triggerRef, onToggle, ariaProps, keyHandler }) => ( { onSuccess: fileData => { savePreviewFile({ fileData, - fileName: fileInfo?.bulkDetails[FILE_TO_LINK[fileInfo?.param]], + fileName: fileInfo?.bulkDetails[FILE_KEYS[fileInfo?.param]], }); }, onSettled: () => { diff --git a/src/constants/files.js b/src/constants/files.js index 0350ef15..c23c2d1f 100644 --- a/src/constants/files.js +++ b/src/constants/files.js @@ -2,20 +2,9 @@ import { FormattedMessage } from 'react-intl'; import React from 'react'; import { EDITING_STEPS } from './core'; -// use as marks that getFileName are ready -export const FILE_KEYS = { - MATCHING_RECORDS_LINK: 'linkToMatchedRecordsCsvFile', - MATCHING_ERRORS_LINK: 'linkToMatchedRecordsErrorsCsvFile', - PROPOSED_CHANGES_LINK: 'linkToModifiedRecordsCsvFile', - PROPOSED_CHANGES_LINK_MARC: 'linkToModifiedRecordsMarcFile', - UPDATE_CHANGES_LINK_MARC: 'linkToCommittedRecordsMarcFile', - UPDATED_RECORDS_LINK: 'linkToCommittedRecordsCsvFile', - UPDATED_ERRORS_LINK: 'linkToCommittedRecordsErrorsCsvFile', - TRIGGERING_FILE: 'linkToTriggeringCsvFile', -}; - // use as API key for /download export const FILE_SEARCH_PARAMS = { + TRIGGERING_FILE: 'TRIGGERING_FILE', MATCHED_RECORDS_FILE: 'MATCHED_RECORDS_FILE', RECORD_MATCHING_ERROR_FILE: 'RECORD_MATCHING_ERROR_FILE', COMMITTED_RECORDS_FILE: 'COMMITTED_RECORDS_FILE', @@ -25,42 +14,57 @@ export const FILE_SEARCH_PARAMS = { PROPOSED_CHANGES_MARC_FILE: 'PROPOSED_CHANGES_MARC_FILE', }; -export const FILE_TO_LINK = { - MATCHED_RECORDS_FILE: 'linkToMatchedRecordsCsvFile', - RECORD_MATCHING_ERROR_FILE: 'linkToMatchedRecordsErrorsCsvFile', - COMMITTED_RECORDS_FILE: 'linkToCommittedRecordsCsvFile', - COMMITTING_CHANGES_ERROR_FILE: 'linkToCommittedRecordsErrorsCsvFile', - PROPOSED_CHANGES_FILE: 'linkToModifiedRecordsCsvFile', - COMMITTED_RECORDS_MARC_FILE: 'linkToCommittedRecordsMarcFile' +// use as marks that getFileName are ready +export const FILE_KEYS = { + [FILE_SEARCH_PARAMS.MATCHED_RECORDS_FILE]: 'linkToMatchedRecordsCsvFile', + [FILE_SEARCH_PARAMS.RECORD_MATCHING_ERROR_FILE]: 'linkToMatchedRecordsErrorsCsvFile', + [FILE_SEARCH_PARAMS.PROPOSED_CHANGES_FILE]: 'linkToModifiedRecordsCsvFile', + [FILE_SEARCH_PARAMS.PROPOSED_CHANGES_MARC_FILE]: 'linkToModifiedRecordsMarcFile', + [FILE_SEARCH_PARAMS.COMMITTED_RECORDS_MARC_FILE]: 'linkToCommittedRecordsMarcFile', + [FILE_SEARCH_PARAMS.COMMITTED_RECORDS_FILE]: 'linkToCommittedRecordsCsvFile', + [FILE_SEARCH_PARAMS.COMMITTING_CHANGES_ERROR_FILE]: 'linkToCommittedRecordsErrorsCsvFile', + TRIGGERING_FILE: 'linkToTriggeringCsvFile', +}; + +export const LINK_KEYS = { + linkToTriggeringCsvFile: FILE_SEARCH_PARAMS.TRIGGERING_FILE, + linkToMatchedRecordsCsvFile: FILE_SEARCH_PARAMS.MATCHED_RECORDS_FILE, + linkToMatchedRecordsErrorsCsvFile: FILE_SEARCH_PARAMS.RECORD_MATCHING_ERROR_FILE, + linkToModifiedRecordsCsvFile: FILE_SEARCH_PARAMS.PROPOSED_CHANGES_FILE, + linkToModifiedRecordsMarcFile: FILE_SEARCH_PARAMS.PROPOSED_CHANGES_MARC_FILE, + linkToCommittedRecordsMarcFile: FILE_SEARCH_PARAMS.COMMITTED_RECORDS_MARC_FILE, + linkToCommittedRecordsCsvFile: FILE_SEARCH_PARAMS.COMMITTED_RECORDS_FILE, + linkToCommittedRecordsErrorsCsvFile: FILE_SEARCH_PARAMS.COMMITTING_CHANGES_ERROR_FILE, + expired: 'expired', }; export const getDownloadLinks = ({ perms, step }) => [ { - KEY: FILE_KEYS.MATCHING_RECORDS_LINK, + KEY: FILE_KEYS.MATCHED_RECORDS_FILE, SEARCH_PARAM: FILE_SEARCH_PARAMS.MATCHED_RECORDS_FILE, LINK_NAME: , IS_VISIBLE: perms.hasAnyEditPermissions && step === EDITING_STEPS.UPLOAD, }, { - KEY: FILE_KEYS.UPDATED_RECORDS_LINK, + KEY: FILE_KEYS.COMMITTED_RECORDS_FILE, SEARCH_PARAM: FILE_SEARCH_PARAMS.COMMITTED_RECORDS_FILE, LINK_NAME: , IS_VISIBLE: perms.hasAnyEditPermissions, }, { - KEY: FILE_KEYS.UPDATE_CHANGES_LINK_MARC, + KEY: FILE_KEYS.COMMITTED_RECORDS_MARC_FILE, SEARCH_PARAM: FILE_SEARCH_PARAMS.COMMITTED_RECORDS_MARC_FILE, LINK_NAME: , IS_VISIBLE: perms.hasAnyEditPermissions, }, { - KEY: FILE_KEYS.MATCHING_ERRORS_LINK, + KEY: FILE_KEYS.RECORD_MATCHING_ERROR_FILE, SEARCH_PARAM: FILE_SEARCH_PARAMS.RECORD_MATCHING_ERROR_FILE, LINK_NAME: , IS_VISIBLE: perms.hasAnyEditPermissions && step === EDITING_STEPS.UPLOAD, }, { - KEY: FILE_KEYS.UPDATED_ERRORS_LINK, + KEY: FILE_KEYS.COMMITTING_CHANGES_ERROR_FILE, SEARCH_PARAM: FILE_SEARCH_PARAMS.COMMITTING_CHANGES_ERROR_FILE, LINK_NAME: , IS_VISIBLE: perms.hasAnyEditPermissions && step === EDITING_STEPS.COMMIT, diff --git a/src/constants/index.js b/src/constants/index.js index 7fb42390..5f991a1a 100644 --- a/src/constants/index.js +++ b/src/constants/index.js @@ -4,5 +4,4 @@ export * from './columns'; export * from './inAppActions'; export * from '../utils/date'; export * from './files'; -export * from './logsActions'; export * from './moduleNames'; diff --git a/src/constants/logsActions.js b/src/constants/logsActions.js deleted file mode 100644 index 6db1b7d1..00000000 --- a/src/constants/logsActions.js +++ /dev/null @@ -1,11 +0,0 @@ -export const linkNamesMap = { - linkToTriggeringCsvFile: 'TRIGGERING_FILE', - linkToMatchedRecordsCsvFile: 'MATCHED_RECORDS_FILE', - linkToMatchedRecordsErrorsCsvFile: 'RECORD_MATCHING_ERROR_FILE', - linkToModifiedRecordsCsvFile: 'PROPOSED_CHANGES_FILE', - linkToModifiedRecordsMarcFile: 'PROPOSED_CHANGES_MARC_FILE', - linkToCommittedRecordsMarcFile: 'COMMITTED_RECORDS_FILE_MARC', - linkToCommittedRecordsCsvFile: 'COMMITTED_RECORDS_FILE', - linkToCommittedRecordsErrorsCsvFile: 'COMMITTING_CHANGES_ERROR_FILE', - expired: 'expired', -}; diff --git a/src/utils/formatters.js b/src/utils/formatters.js index 0bb5b444..c975924e 100644 --- a/src/utils/formatters.js +++ b/src/utils/formatters.js @@ -5,9 +5,9 @@ import { NoValue } from '@folio/stripes/components'; import { FolioFormattedTime } from '@folio/stripes-acq-components'; import BulkEditLogsActions from '../components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions'; -import { linkNamesMap } from '../constants'; +import { LINK_KEYS } from '../constants'; -const isActionsRendered = (item) => Object.keys(item).some(key => Object.keys(linkNamesMap).includes(key)); +const isActionsRendered = (item) => Object.keys(item).some(key => Object.keys(LINK_KEYS).includes(key)); export const getLogsResultsFormatter = () => ({ id: item => item.id, From 1e0dcddd69d74a09a2f8b7ef68ae9412167b4b96 Mon Sep 17 00:00:00 2001 From: vashjs Date: Tue, 21 Jan 2025 18:55:04 +0100 Subject: [PATCH 3/6] tests --- .../BulkEditActionMenu.test.js | 9 ++++--- .../BulkEditLogsActions.test.js | 26 +++++++------------ src/constants/files.js | 16 ++++++------ 3 files changed, 23 insertions(+), 28 deletions(-) diff --git a/src/components/BulkEditActionMenu/BulkEditActionMenu.test.js b/src/components/BulkEditActionMenu/BulkEditActionMenu.test.js index 48dd3782..9a2be345 100644 --- a/src/components/BulkEditActionMenu/BulkEditActionMenu.test.js +++ b/src/components/BulkEditActionMenu/BulkEditActionMenu.test.js @@ -33,13 +33,14 @@ jest.mock('../../hooks/api', () => ({ const onEdit = jest.fn(); const onToggle = jest.fn(); +const links = Object.values(FILE_KEYS).reduce((acc, key) => { + acc[key] = key; + return acc; +}, {}); const bulkOperation = { ...bulkEditLogsData[0], status: JOB_STATUSES.DATA_MODIFICATION, - [FILE_KEYS.MATCHING_RECORDS_LINK]: FILE_KEYS.MATCHING_RECORDS_LINK, - [FILE_KEYS.UPDATED_RECORDS_LINK]: FILE_KEYS.UPDATED_RECORDS_LINK, - [FILE_KEYS.MATCHING_ERRORS_LINK]: FILE_KEYS.MATCHING_ERRORS_LINK, - [FILE_KEYS.UPDATED_ERRORS_LINK]: FILE_KEYS.UPDATED_ERRORS_LINK, + ...links, }; const defaultProviderState = { visibleColumns: [ diff --git a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js index f8c4efc9..d58ef64e 100644 --- a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js +++ b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js @@ -10,34 +10,28 @@ import { import { queryClient } from '../../../../test/jest/utils/queryClient'; import { JOB_STATUSES, - FILE_KEYS, CAPABILITIES, + FILE_KEYS, + CAPABILITIES, + LINK_KEYS, } from '../../../constants'; import BulkEditLogsActions from './BulkEditLogsActions'; import { useBulkPermissions } from '../../../hooks'; +const links = Object.values(FILE_KEYS).reduce((acc, key) => { + acc[key] = key; + return acc; +}, {}); + const bulkOperation = { ...bulkEditLogsData[0], status: JOB_STATUSES.DATA_MODIFICATION, - [FILE_KEYS.MATCHING_RECORDS_LINK]: FILE_KEYS.MATCHING_RECORDS_LINK, - [FILE_KEYS.UPDATED_RECORDS_LINK]: FILE_KEYS.UPDATED_RECORDS_LINK, - [FILE_KEYS.MATCHING_ERRORS_LINK]: FILE_KEYS.MATCHING_ERRORS_LINK, - [FILE_KEYS.UPDATED_ERRORS_LINK]: FILE_KEYS.UPDATED_ERRORS_LINK, - [FILE_KEYS.PROPOSED_CHANGES_LINK]: FILE_KEYS.PROPOSED_CHANGES_LINK, - [FILE_KEYS.TRIGGERING_FILE]: FILE_KEYS.TRIGGERING_FILE, - [FILE_KEYS.PROPOSED_CHANGES_LINK_MARC]: FILE_KEYS.PROPOSED_CHANGES_LINK_MARC, - [FILE_KEYS.UPDATE_CHANGES_LINK_MARC]: FILE_KEYS.UPDATE_CHANGES_LINK_MARC, + ...links, }; const bulkOperationWithExpired = { ...bulkEditLogsDataWithExpiredFlag[0], status: JOB_STATUSES.DATA_MODIFICATION, - [FILE_KEYS.MATCHING_RECORDS_LINK]: FILE_KEYS.MATCHING_RECORDS_LINK, - [FILE_KEYS.UPDATED_RECORDS_LINK]: FILE_KEYS.UPDATED_RECORDS_LINK, - [FILE_KEYS.MATCHING_ERRORS_LINK]: FILE_KEYS.MATCHING_ERRORS_LINK, - [FILE_KEYS.UPDATED_ERRORS_LINK]: FILE_KEYS.UPDATED_ERRORS_LINK, - [FILE_KEYS.PROPOSED_CHANGES_LINK]: FILE_KEYS.PROPOSED_CHANGES_LINK, - [FILE_KEYS.PROPOSED_CHANGES_LINK_MARC]: FILE_KEYS.PROPOSED_CHANGES_LINK_MARC, - [FILE_KEYS.TRIGGERING_FILE]: FILE_KEYS.TRIGGERING_FILE, + ...links, }; jest.mock('../../../hooks', () => ({ ...jest.requireActual('../../../hooks'), diff --git a/src/constants/files.js b/src/constants/files.js index c23c2d1f..65d3b35e 100644 --- a/src/constants/files.js +++ b/src/constants/files.js @@ -16,14 +16,14 @@ export const FILE_SEARCH_PARAMS = { // use as marks that getFileName are ready export const FILE_KEYS = { - [FILE_SEARCH_PARAMS.MATCHED_RECORDS_FILE]: 'linkToMatchedRecordsCsvFile', - [FILE_SEARCH_PARAMS.RECORD_MATCHING_ERROR_FILE]: 'linkToMatchedRecordsErrorsCsvFile', - [FILE_SEARCH_PARAMS.PROPOSED_CHANGES_FILE]: 'linkToModifiedRecordsCsvFile', - [FILE_SEARCH_PARAMS.PROPOSED_CHANGES_MARC_FILE]: 'linkToModifiedRecordsMarcFile', - [FILE_SEARCH_PARAMS.COMMITTED_RECORDS_MARC_FILE]: 'linkToCommittedRecordsMarcFile', - [FILE_SEARCH_PARAMS.COMMITTED_RECORDS_FILE]: 'linkToCommittedRecordsCsvFile', - [FILE_SEARCH_PARAMS.COMMITTING_CHANGES_ERROR_FILE]: 'linkToCommittedRecordsErrorsCsvFile', TRIGGERING_FILE: 'linkToTriggeringCsvFile', + MATCHED_RECORDS_FILE: 'linkToMatchedRecordsCsvFile', + RECORD_MATCHING_ERROR_FILE: 'linkToMatchedRecordsErrorsCsvFile', + COMMITTED_RECORDS_FILE: 'linkToCommittedRecordsCsvFile', + COMMITTED_RECORDS_MARC_FILE: 'linkToCommittedRecordsMarcFile', + COMMITTING_CHANGES_ERROR_FILE: 'linkToCommittedRecordsErrorsCsvFile', + PROPOSED_CHANGES_FILE: 'linkToModifiedRecordsCsvFile', + PROPOSED_CHANGES_MARC_FILE: 'linkToModifiedRecordsMarcFile', }; export const LINK_KEYS = { @@ -32,8 +32,8 @@ export const LINK_KEYS = { linkToMatchedRecordsErrorsCsvFile: FILE_SEARCH_PARAMS.RECORD_MATCHING_ERROR_FILE, linkToModifiedRecordsCsvFile: FILE_SEARCH_PARAMS.PROPOSED_CHANGES_FILE, linkToModifiedRecordsMarcFile: FILE_SEARCH_PARAMS.PROPOSED_CHANGES_MARC_FILE, - linkToCommittedRecordsMarcFile: FILE_SEARCH_PARAMS.COMMITTED_RECORDS_MARC_FILE, linkToCommittedRecordsCsvFile: FILE_SEARCH_PARAMS.COMMITTED_RECORDS_FILE, + linkToCommittedRecordsMarcFile: FILE_SEARCH_PARAMS.COMMITTED_RECORDS_MARC_FILE, linkToCommittedRecordsErrorsCsvFile: FILE_SEARCH_PARAMS.COMMITTING_CHANGES_ERROR_FILE, expired: 'expired', }; From 8d27e00189a8245083416281bd55985996f70a58 Mon Sep 17 00:00:00 2001 From: vashjs Date: Tue, 21 Jan 2025 19:05:06 +0100 Subject: [PATCH 4/6] update tests --- .../BulkEditActionMenu/BulkEditActionMenu.test.js | 9 +++------ .../BulkEditLogsActions/BulkEditLogsActions.test.js | 10 ++++------ 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/src/components/BulkEditActionMenu/BulkEditActionMenu.test.js b/src/components/BulkEditActionMenu/BulkEditActionMenu.test.js index 9a2be345..7b57cfb5 100644 --- a/src/components/BulkEditActionMenu/BulkEditActionMenu.test.js +++ b/src/components/BulkEditActionMenu/BulkEditActionMenu.test.js @@ -8,6 +8,7 @@ import { useOkapiKy } from '@folio/stripes/core'; import '../../../test/jest/__mock__'; import { runAxeTest } from '@folio/stripes-testing'; +import { omit } from 'lodash'; import { bulkEditLogsData } from '../../../test/jest/__mock__/fakeData'; import { queryClient } from '../../../test/jest/utils/queryClient'; @@ -19,8 +20,8 @@ import { CRITERIA, EDITING_STEPS, JOB_STATUSES, - FILE_KEYS, FILE_SEARCH_PARAMS, + LINK_KEYS, } from '../../constants'; import { useBulkOperationDetails } from '../../hooks/api'; @@ -33,14 +34,10 @@ jest.mock('../../hooks/api', () => ({ const onEdit = jest.fn(); const onToggle = jest.fn(); -const links = Object.values(FILE_KEYS).reduce((acc, key) => { - acc[key] = key; - return acc; -}, {}); const bulkOperation = { ...bulkEditLogsData[0], status: JOB_STATUSES.DATA_MODIFICATION, - ...links, + ...omit(LINK_KEYS, ['expired']), }; const defaultProviderState = { visibleColumns: [ diff --git a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js index d58ef64e..92cb6108 100644 --- a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js +++ b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js @@ -3,6 +3,7 @@ import { render, screen } from '@testing-library/react'; import { QueryClientProvider } from 'react-query'; import { useOkapiKy } from '@folio/stripes/core'; import '../../../../test/jest/__mock__'; +import { omit } from 'lodash'; import { bulkEditLogsData, bulkEditLogsDataWithExpiredFlag, @@ -17,21 +18,18 @@ import { import BulkEditLogsActions from './BulkEditLogsActions'; import { useBulkPermissions } from '../../../hooks'; -const links = Object.values(FILE_KEYS).reduce((acc, key) => { - acc[key] = key; - return acc; -}, {}); +const linksWithoutExpired = omit(LINK_KEYS, ['expired']); const bulkOperation = { ...bulkEditLogsData[0], status: JOB_STATUSES.DATA_MODIFICATION, - ...links, + ...linksWithoutExpired, }; const bulkOperationWithExpired = { ...bulkEditLogsDataWithExpiredFlag[0], status: JOB_STATUSES.DATA_MODIFICATION, - ...links, + ...linksWithoutExpired, }; jest.mock('../../../hooks', () => ({ ...jest.requireActual('../../../hooks'), From b352f023068ae4213b8841157e44d300f12c99d6 Mon Sep 17 00:00:00 2001 From: vashjs Date: Tue, 21 Jan 2025 22:49:28 +0100 Subject: [PATCH 5/6] update tests --- .../BulkEditLogsActions.test.js | 62 ++++++++++++++++++- 1 file changed, 61 insertions(+), 1 deletion(-) diff --git a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js index 92cb6108..21c84757 100644 --- a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js +++ b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { fireEvent, render, screen } from '@testing-library/react'; import { QueryClientProvider } from 'react-query'; import { useOkapiKy } from '@folio/stripes/core'; import '../../../../test/jest/__mock__'; @@ -17,6 +17,7 @@ import { } from '../../../constants'; import BulkEditLogsActions from './BulkEditLogsActions'; import { useBulkPermissions } from '../../../hooks'; +import { useFileDownload } from '../../../hooks/api'; const linksWithoutExpired = omit(LINK_KEYS, ['expired']); @@ -34,6 +35,11 @@ const bulkOperationWithExpired = { jest.mock('../../../hooks', () => ({ ...jest.requireActual('../../../hooks'), useBulkPermissions: jest.fn(), + useFileDownload: jest.fn(), +})); + +jest.mock('../../../hooks/api', () => ({ + useFileDownload: jest.fn(), })); jest.mock('../../../hooks/useSearchParams', () => ({ @@ -49,6 +55,19 @@ const renderBulkEditLogsActions = ({ item = bulkOperation } = {}) => { }; describe('BulkEditLogsActions', () => { + const mockPermissions = { + hasUsersViewPerms: true, + hasInventoryInstanceViewPerms: true, + }; + const mockRefetch = jest.fn(); + + beforeEach(() => { + useBulkPermissions.mockReturnValue(mockPermissions); + useFileDownload.mockReturnValue({ + refetch: mockRefetch, + }); + }); + beforeEach(() => { useOkapiKy.mockClear().mockReturnValue({}); }); @@ -84,4 +103,45 @@ describe('BulkEditLogsActions', () => { expect(screen.getByTestId(fileKey)).toBeDefined(); }); }); + + it('should trigger file download when a file option is clicked', () => { + renderBulkEditLogsActions(); + + fireEvent.click(screen.getByRole('button', { name: /ellipsis/i })); + fireEvent.click(screen.getByTestId(FILE_KEYS.TRIGGERING_FILE)); + + expect(mockRefetch).toHaveBeenCalledTimes(1); + }); + + it('should not render for CAPABILITIES.HOLDING without inventory permissions', () => { + useBulkPermissions.mockReturnValue({ hasInventoryInstanceViewPerms: false }); + + const { container } = renderBulkEditLogsActions({ item: { ...bulkOperation, entityType: CAPABILITIES.HOLDING } }); + + expect(container.firstChild).toBeNull(); + }); + + it('should not render for CAPABILITIES.ITEM without inventory permissions', () => { + useBulkPermissions.mockReturnValue({ hasInventoryInstanceViewPerms: false }); + + const { container } = renderBulkEditLogsActions({ item: { ...bulkOperation, entityType: CAPABILITIES.ITEM } }); + + expect(container.firstChild).toBeNull(); + }); + + it('should not render for CAPABILITIES.INSTANCE without inventory permissions', () => { + useBulkPermissions.mockReturnValue({ hasInventoryInstanceViewPerms: false }); + + const { container } = renderBulkEditLogsActions({ item: { ...bulkOperation, entityType: CAPABILITIES.INSTANCE } }); + + expect(container.firstChild).toBeNull(); + }); + + it('should not render for CAPABILITIES.USER without hasUsersViewPerms permissions', () => { + useBulkPermissions.mockReturnValue({ hasInventoryInstanceViewPerms: true, hasUsersViewPerms: false }); + + const { container } = renderBulkEditLogsActions({ item: { ...bulkOperation, entityType: CAPABILITIES.USER } }); + + expect(container.firstChild).toBeNull(); + }); }); From 3bf4c4105536537ea14d56752faf603bb7f3ce3d Mon Sep 17 00:00:00 2001 From: vashjs Date: Tue, 21 Jan 2025 23:13:37 +0100 Subject: [PATCH 6/6] update tests --- .../BulkEditLogsActions.test.js | 43 +------------------ 1 file changed, 1 insertion(+), 42 deletions(-) diff --git a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js index 21c84757..c26abd01 100644 --- a/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js +++ b/src/components/BulkEditLogs/BulkEditLogsActions/BulkEditLogsActions.test.js @@ -1,5 +1,5 @@ import React from 'react'; -import { fireEvent, render, screen } from '@testing-library/react'; +import { render, screen } from '@testing-library/react'; import { QueryClientProvider } from 'react-query'; import { useOkapiKy } from '@folio/stripes/core'; import '../../../../test/jest/__mock__'; @@ -103,45 +103,4 @@ describe('BulkEditLogsActions', () => { expect(screen.getByTestId(fileKey)).toBeDefined(); }); }); - - it('should trigger file download when a file option is clicked', () => { - renderBulkEditLogsActions(); - - fireEvent.click(screen.getByRole('button', { name: /ellipsis/i })); - fireEvent.click(screen.getByTestId(FILE_KEYS.TRIGGERING_FILE)); - - expect(mockRefetch).toHaveBeenCalledTimes(1); - }); - - it('should not render for CAPABILITIES.HOLDING without inventory permissions', () => { - useBulkPermissions.mockReturnValue({ hasInventoryInstanceViewPerms: false }); - - const { container } = renderBulkEditLogsActions({ item: { ...bulkOperation, entityType: CAPABILITIES.HOLDING } }); - - expect(container.firstChild).toBeNull(); - }); - - it('should not render for CAPABILITIES.ITEM without inventory permissions', () => { - useBulkPermissions.mockReturnValue({ hasInventoryInstanceViewPerms: false }); - - const { container } = renderBulkEditLogsActions({ item: { ...bulkOperation, entityType: CAPABILITIES.ITEM } }); - - expect(container.firstChild).toBeNull(); - }); - - it('should not render for CAPABILITIES.INSTANCE without inventory permissions', () => { - useBulkPermissions.mockReturnValue({ hasInventoryInstanceViewPerms: false }); - - const { container } = renderBulkEditLogsActions({ item: { ...bulkOperation, entityType: CAPABILITIES.INSTANCE } }); - - expect(container.firstChild).toBeNull(); - }); - - it('should not render for CAPABILITIES.USER without hasUsersViewPerms permissions', () => { - useBulkPermissions.mockReturnValue({ hasInventoryInstanceViewPerms: true, hasUsersViewPerms: false }); - - const { container } = renderBulkEditLogsActions({ item: { ...bulkOperation, entityType: CAPABILITIES.USER } }); - - expect(container.firstChild).toBeNull(); - }); });