From ec3a92f6c55944e674650a466a737b5d04691762 Mon Sep 17 00:00:00 2001 From: Mariia Aloshyna <55138456+mariia-aloshyna@users.noreply.github.com> Date: Fri, 19 Apr 2024 22:19:05 +0300 Subject: [PATCH] Release v11.0.2 (#2452) --- CHANGELOG.md | 8 ++++++++ package.json | 14 ++++++++++++-- src/ViewInstance.js | 4 ++-- src/ViewInstance.test.js | 16 +++++----------- src/ViewInstanceWrapper.js | 15 +++++++++++++-- src/ViewInstanceWrapper.test.js | 7 ++++++- src/components/InstancesList/InstancesList.js | 3 ++- .../ItemViewSubheader/ItemViewSubheader.js | 6 +++--- translations/ui-inventory/en.json | 1 + 9 files changed, 52 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d3bf93a0f..bc01970ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,13 @@ # Change history for ui-inventory +## [11.0.2](https://github.com/folio-org/ui-inventory/tree/v11.0.2) (2024-04-19) +[Full Changelog](https://github.com/folio-org/ui-inventory/compare/v11.0.1...v11.0.2) + +* ECS: Shared instance cannot be edited from member tenant, even with permissions in both Central and member tenants. Fixes UIIN-2845. +* Restricted status displays as Order Closed. Fixes UIIN-2821. +* Add a new "Inventory: Create and download In transit items report" permission. Fixes UIIN-2776. +* Include mod-search permissions to "Inventory: Module is enabled" UI permission. Refs UIIN-2860. + ## [11.0.1](https://github.com/folio-org/ui-inventory/tree/v11.0.1) (2024-04-11) [Full Changelog](https://github.com/folio-org/ui-inventory/compare/v11.0.0...v11.0.1) diff --git a/package.json b/package.json index c03d18ade..949828c6d 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@folio/inventory", - "version": "11.0.1", + "version": "11.0.2", "description": "Inventory manager", "repository": "folio-org/ui-inventory", "publishConfig": { @@ -119,7 +119,9 @@ "search.config.languages.collection.get", "search.config.languages.item.delete", "search.index.inventory.reindex.post", - "search.facets.collection.get" + "search.facets.collection.get", + "consortium-search.holdings.collection.get", + "consortium-search.items.collection.get" ] }, { @@ -834,6 +836,14 @@ ], "visible": true }, + { + "permissionName": "ui-inventory.items.create-in-transit-report", + "displayName": "Inventory: Create and download In transit items report", + "subPermissions": [ + "circulation.inventory.items-in-transit-report.get" + ], + "visible": true + }, { "permissionName": "ui-inventory.single-record-import", "displayName": "Inventory: Import single bibliographic records", diff --git a/src/ViewInstance.js b/src/ViewInstance.js index c49ebb447..202272021 100644 --- a/src/ViewInstance.js +++ b/src/ViewInstance.js @@ -652,7 +652,7 @@ class ViewInstance extends React.Component { }; hasCentralTenantPerm = (perm) => { - return this.props.centralTenantPermissions.some(({ permissionName }) => permissionName === perm); + return this.props.centralTenantPermissions.has(perm); } createActionMenuGetter = (instance, data) => ({ onToggle }) => { @@ -1161,7 +1161,7 @@ class ViewInstance extends React.Component { ViewInstance.propTypes = { isShared: PropTypes.bool, canUseSingleRecordImport: PropTypes.bool, - centralTenantPermissions: PropTypes.arrayOf(PropTypes.object).isRequired, + centralTenantPermissions: PropTypes.instanceOf(Set).isRequired, selectedInstance: PropTypes.object, centralTenantId: PropTypes.string, refetchInstance: PropTypes.func, diff --git a/src/ViewInstance.test.js b/src/ViewInstance.test.js index b857b1e49..26610ee96 100644 --- a/src/ViewInstance.test.js +++ b/src/ViewInstance.test.js @@ -153,7 +153,7 @@ const mockStripes = { }, }; const defaultProp = { - centralTenantPermissions: [], + centralTenantPermissions: new Set([]), selectedInstance: instance, centralTenantId: 'centralTenantId', consortiumId: 'consortiumId', @@ -863,9 +863,7 @@ describe('ViewInstance', () => { StripesConnectedInstance.prototype.instance.mockImplementation(() => sharedInstance); renderViewInstance({ - centralTenantPermissions: [{ - permissionName: 'ui-quick-marc.quick-marc-editor.all', - }], + centralTenantPermissions: new Set(['ui-quick-marc.quick-marc-editor.all']), isShared: true, tenantId: 'tenantId', }); @@ -886,7 +884,7 @@ describe('ViewInstance', () => { StripesConnectedInstance.prototype.instance.mockImplementation(() => sharedInstance); renderViewInstance({ - centralTenantPermissions: [], + centralTenantPermissions: new Set([]), isShared: true, tenantId: 'tenantId', }); @@ -914,9 +912,7 @@ describe('ViewInstance', () => { }; renderViewInstance({ - centralTenantPermissions: [{ - permissionName: 'ui-quick-marc.quick-marc-editor.all', - }], + centralTenantPermissions: new Set(['ui-quick-marc.quick-marc-editor.all']), stripes, isShared: true, tenantId: 'tenantId', @@ -1082,9 +1078,7 @@ describe('ViewInstance', () => { describe('when user is in member tenant and instance is shared and has central tenant permission to set record for deletion', () => { it('should render "Set record for deletion" action item', () => { renderViewInstance({ - centralTenantPermissions: [{ - permissionName: 'ui-inventory.instance.set-deletion-and-staff-suppress', - }], + centralTenantPermissions: new Set(['ui-inventory.instance.set-deletion-and-staff-suppress']), isShared: true, tenantId: 'tenantId', }); diff --git a/src/ViewInstanceWrapper.js b/src/ViewInstanceWrapper.js index bb207be22..44005da71 100644 --- a/src/ViewInstanceWrapper.js +++ b/src/ViewInstanceWrapper.js @@ -1,4 +1,4 @@ -import React from 'react'; +import React, { useMemo } from 'react'; import PropTypes from 'prop-types'; import { checkIfUserInMemberTenant } from '@folio/stripes/core'; @@ -42,6 +42,17 @@ const ViewInstanceWrapper = (props) => { enabled: Boolean(isShared && checkIfUserInMemberTenant(stripes)), }); + const flattenCentralTenantPermissions = useMemo(() => { + // Set is used to collect unique permission names because subPermissions can duplicate + return new Set(centralTenantPermissions?.reduce((acc, currentPermission) => { + return [ + ...acc, + currentPermission.permissionName, + ...currentPermission.subPermissions, + ]; + }, [])); + }, [centralTenantPermissions]); + const mutateInstance = (entity, { onError }) => { mutateEntity(entity, { onSuccess: refetch, onError }); }; @@ -59,7 +70,7 @@ const ViewInstanceWrapper = (props) => { isLoading={isLoading} isError={isError} error={error} - centralTenantPermissions={centralTenantPermissions} + centralTenantPermissions={flattenCentralTenantPermissions} isCentralTenantPermissionsLoading={isCentralTenantPermissionsLoading} /> ); diff --git a/src/ViewInstanceWrapper.test.js b/src/ViewInstanceWrapper.test.js index a50319620..fe72dcc4b 100644 --- a/src/ViewInstanceWrapper.test.js +++ b/src/ViewInstanceWrapper.test.js @@ -70,7 +70,12 @@ describe('ViewInstanceWrapper', () => { it('should fetch the central tenant permissions', () => { const userPermissions = [{ permissionName: 'ui-quick-marc.quick-marc-editor.all', + subPermissions: ['ui-inventory.instance.create'], + }, { + permissionName: 'ui-inventory.instance.create', + subPermissions: [], }]; + const flattenUserPermissions = new Set(['ui-quick-marc.quick-marc-editor.all', 'ui-inventory.instance.create']); useInstance.mockReturnValue({ instance: { @@ -95,7 +100,7 @@ describe('ViewInstanceWrapper', () => { enabled: true, }); - expect(ViewInstance.mock.calls[0][0].centralTenantPermissions).toEqual(userPermissions); + expect(ViewInstance.mock.calls[0][0].centralTenantPermissions).toEqual(flattenUserPermissions); expect(ViewInstance.mock.calls[0][0].isCentralTenantPermissionsLoading).toBeFalsy(); }); }); diff --git a/src/components/InstancesList/InstancesList.js b/src/components/InstancesList/InstancesList.js index 67216accf..a394f7e7e 100644 --- a/src/components/InstancesList/InstancesList.js +++ b/src/components/InstancesList/InstancesList.js @@ -753,6 +753,7 @@ class InstancesList extends React.Component { const visibleColumns = this.getVisibleColumns(); const columnMapping = this.getColumnMapping(); const canExportMarc = stripes.hasPerm('ui-data-export.app.enabled'); + const canCreateItemsInTransitReport = stripes.hasPerm('ui-inventory.items.create-in-transit-report'); const buildOnClickHandler = onClickHandler => { return () => { @@ -843,7 +844,7 @@ class InstancesList extends React.Component { icon: 'report', messageId: 'ui-inventory.exportInProgress', }) : - !checkIfUserInCentralTenant(stripes) && this.getActionItem({ + canCreateItemsInTransitReport && !checkIfUserInCentralTenant(stripes) && this.getActionItem({ id: 'dropdown-clickable-get-report', icon: 'report', messageId: 'ui-inventory.inTransitReport', diff --git a/src/components/ItemViewSubheader/ItemViewSubheader.js b/src/components/ItemViewSubheader/ItemViewSubheader.js index 89f076f5f..49dab0644 100644 --- a/src/components/ItemViewSubheader/ItemViewSubheader.js +++ b/src/components/ItemViewSubheader/ItemViewSubheader.js @@ -32,9 +32,9 @@ const ITEM_STATUS_TRANSLATIONS_ID_MAP = { [itemStatusesMap.LOST_AND_PAID]: 'ui-inventory.item.status.lostAndPaid.lowercase', [itemStatusesMap.MISSING]: 'ui-inventory.item.status.missing.lowercase', [itemStatusesMap.ON_ORDER]: 'ui-inventory.item.status.onOrder.lowercase', - [itemStatusesMap.ORDER_CLOSED]: 'ui-inventory.item.status.paged.lowercase', - [itemStatusesMap.PAGED]: 'ui-inventory.item.status.restricted.lowercase', - [itemStatusesMap.RESTRICTED]: 'ui-inventory.item.status.orderClosed.lowercase', + [itemStatusesMap.ORDER_CLOSED]: 'ui-inventory.item.status.orderClosed.lowercase', + [itemStatusesMap.PAGED]: 'ui-inventory.item.status.paged.lowercase', + [itemStatusesMap.RESTRICTED]: 'ui-inventory.item.status.restricted.lowercase', [itemStatusesMap.UNAVAILABLE]: 'ui-inventory.item.status.unavailable.lowercase', [itemStatusesMap.UNKNOWN]: 'ui-inventory.item.status.unknown.lowercase', [itemStatusesMap.WITHDRAWN]: 'ui-inventory.item.status.withdrawn.lowercase', diff --git a/translations/ui-inventory/en.json b/translations/ui-inventory/en.json index dbf8ecae5..2a38c4f53 100644 --- a/translations/ui-inventory/en.json +++ b/translations/ui-inventory/en.json @@ -752,6 +752,7 @@ "permission.items.mark-long-missing": "Inventory: Mark items long missing", "permission.items.mark-in-process-non-requestable": "Inventory: Mark items in process (non-requestable)", "permission.consortia.inventory.share.local.instance": "Inventory: Share local instance with consortium", + "permission.items.create-in-transit-report": "Inventory: Create and download In transit items report", "moveItems.moveButton": "Move to", "moveItems.selectAll": "Select/unselect all items for movement",