From bb91a772703552667b66cac96540bbabbff87577 Mon Sep 17 00:00:00 2001 From: Mariia_Aloshyna Date: Fri, 3 Nov 2023 17:48:18 +0200 Subject: [PATCH 1/2] UIIN-2590: ECS: Show info message when user in member tenant tries to view shared instance details without permission --- CHANGELOG.md | 1 + .../InstanceDetails/InstanceDetails.js | 83 ++++--------------- .../InstanceDetails/InstanceDetails.test.js | 7 -- .../InstanceLoadingPane.js | 33 ++++++++ .../InstanceLoadingPane.test.js | 53 ++++++++++++ .../InstanceLoadingPane/index.js | 1 + .../InstanceWarningPane.js | 38 +++++++++ .../InstanceWarningPane.test.js | 58 +++++++++++++ .../InstanceWarningPane/index.js | 1 + src/Instance/InstanceDetails/index.js | 2 + src/ViewInstance.js | 36 +++++++- src/ViewInstance.test.js | 36 +++++++- src/ViewInstanceWrapper.js | 4 +- src/common/hooks/useInstance.js | 3 +- .../useInstanceQuery/useInstanceQuery.js | 3 +- src/constants.js | 4 + test/jest/__mock__/stripesIcon.mock.js | 4 +- translations/ui-inventory/en.json | 1 + 18 files changed, 287 insertions(+), 81 deletions(-) create mode 100644 src/Instance/InstanceDetails/InstanceLoadingPane/InstanceLoadingPane.js create mode 100644 src/Instance/InstanceDetails/InstanceLoadingPane/InstanceLoadingPane.test.js create mode 100644 src/Instance/InstanceDetails/InstanceLoadingPane/index.js create mode 100644 src/Instance/InstanceDetails/InstanceWarningPane/InstanceWarningPane.js create mode 100644 src/Instance/InstanceDetails/InstanceWarningPane/InstanceWarningPane.test.js create mode 100644 src/Instance/InstanceDetails/InstanceWarningPane/index.js diff --git a/CHANGELOG.md b/CHANGELOG.md index 9a7e26e6c..a8d3a5980 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ * Create new instance success toast no longer shows the instance HRID. Fixes UIIN-2635. * Optimistic locking message not working for instances in non-consortial tenant. Fixes UIIN-2628. * Add immediate warning message when a local instance is shared. Refs UIIN-2617. +* ECS: Show info message when user in member tenant tries to view shared instance details without permission. Refs UIIN-2590. ## [10.0.0](https://github.com/folio-org/ui-inventory/tree/v10.0.0) (2023-10-13) [Full Changelog](https://github.com/folio-org/ui-inventory/compare/v9.4.12...v10.0.0) diff --git a/src/Instance/InstanceDetails/InstanceDetails.js b/src/Instance/InstanceDetails/InstanceDetails.js index 5f41c0c18..ee39f3d1f 100644 --- a/src/Instance/InstanceDetails/InstanceDetails.js +++ b/src/Instance/InstanceDetails/InstanceDetails.js @@ -19,7 +19,6 @@ import { PaneMenu, Row, MessageBanner, - Icon, } from '@folio/stripes/components'; import { InstanceTitle } from './InstanceTitle'; @@ -71,8 +70,6 @@ const InstanceDetails = forwardRef(({ tagsEnabled, userTenantPermissions, isShared, - isLoading, - isInstanceSharing, ...rest }, ref) => { const intl = useIntl(); @@ -86,15 +83,12 @@ const InstanceDetails = forwardRef(({ const accordionState = useMemo(() => getAccordionState(instance, accordions), [instance]); const [helperApp, setHelperApp] = useState(); - const isBasicPane = isInstanceSharing || isLoading; + const canCreateHoldings = stripes.hasPerm('ui-inventory.holdings.create'); const tags = instance?.tags?.tagList; const isUserInCentralTenant = checkIfUserInCentralTenant(stripes); - - const canCreateHoldings = stripes.hasPerm('ui-inventory.holdings.create'); + const isConsortialHoldingsVisible = instance?.shared || isInstanceShadowCopy(instance?.source); const detailsLastMenu = useMemo(() => { - if (isBasicPane) return null; - return ( { @@ -110,15 +104,9 @@ const InstanceDetails = forwardRef(({ } ); - }, [isBasicPane, tagsEnabled, tags, intl]); - const detailsActionMenu = useMemo( - () => (isBasicPane ? null : actionMenu), - [isBasicPane, actionMenu], - ); + }, [tagsEnabled, tags, intl]); const renderPaneTitle = () => { - if (isBasicPane) return intl.formatMessage({ id: 'ui-inventory.edit' }); - const isInstanceShared = Boolean(isShared || isInstanceShadowCopy(instance?.source)); return ( @@ -134,8 +122,6 @@ const InstanceDetails = forwardRef(({ }; const renderPaneSubtitle = () => { - if (isBasicPane) return null; - return ( { - if (isInstanceSharing) { - return ( -
- - - -
- ); - } - - if (isLoading) { - return ( -
- -
- ); - } - - const isConsortialHoldingsVisible = instance?.shared || isInstanceShadowCopy(instance?.source); - - return ( - <> + return ( + <> + } + paneTitle={renderPaneTitle()} + paneSub={renderPaneSubtitle()} + actionMenu={actionMenu} + lastMenu={detailsLastMenu} + dismissible + onClose={onClose} + defaultWidth="fill" + > @@ -293,25 +267,6 @@ const InstanceDetails = forwardRef(({ /> - - ); - }; - - return ( - <> - } - paneTitle={renderPaneTitle()} - paneSub={renderPaneSubtitle()} - actionMenu={detailsActionMenu} - lastMenu={detailsLastMenu} - dismissible - onClose={onClose} - defaultWidth="fill" - > - {renderDetails()} { helperApp && } @@ -326,16 +281,12 @@ InstanceDetails.propTypes = { tagsToggle: PropTypes.func, tagsEnabled: PropTypes.bool, userTenantPermissions: PropTypes.arrayOf(PropTypes.object), - isLoading: PropTypes.bool, - isInstanceSharing: PropTypes.bool, isShared: PropTypes.bool, }; InstanceDetails.defaultProps = { instance: {}, tagsEnabled: false, - isLoading: false, - isInstanceSharing: false, isShared: false, }; diff --git a/src/Instance/InstanceDetails/InstanceDetails.test.js b/src/Instance/InstanceDetails/InstanceDetails.test.js index e8cd22f7e..daf483dcd 100644 --- a/src/Instance/InstanceDetails/InstanceDetails.test.js +++ b/src/Instance/InstanceDetails/InstanceDetails.test.js @@ -112,13 +112,6 @@ describe('InstanceDetails', () => { expect(screen.getByText('Instance relationship (analytics and bound-with)')).toBeInTheDocument(); }); - it('should show a correct Warning message banner when instance sharing is in progress', () => { - renderInstanceDetails({ isInstanceSharing: true }); - - expect(screen.getByText('Sharing this local instance will take a few moments.' + - ' A success message and updated details will be displayed upon completion.')).toBeInTheDocument(); - }); - it('should show a correct Warning message banner when staff suppressed', () => { const staffSuppressedInstance = { ...instance, diff --git a/src/Instance/InstanceDetails/InstanceLoadingPane/InstanceLoadingPane.js b/src/Instance/InstanceDetails/InstanceLoadingPane/InstanceLoadingPane.js new file mode 100644 index 000000000..28d33c5eb --- /dev/null +++ b/src/Instance/InstanceDetails/InstanceLoadingPane/InstanceLoadingPane.js @@ -0,0 +1,33 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { useIntl } from 'react-intl'; + +import { AppIcon } from '@folio/stripes/core'; +import { + Pane, + Icon, +} from '@folio/stripes/components'; + +const InstanceLoadingPane = ({ onClose }) => { + const intl = useIntl(); + + return ( + } + paneTitle={intl.formatMessage({ id: 'ui-inventory.edit' })} + dismissible + onClose={onClose} + defaultWidth="fill" + > + + + ); +}; + +InstanceLoadingPane.propTypes = { onClose: PropTypes.func.isRequired }; + +export default InstanceLoadingPane; diff --git a/src/Instance/InstanceDetails/InstanceLoadingPane/InstanceLoadingPane.test.js b/src/Instance/InstanceDetails/InstanceLoadingPane/InstanceLoadingPane.test.js new file mode 100644 index 000000000..a8f1e7bc8 --- /dev/null +++ b/src/Instance/InstanceDetails/InstanceLoadingPane/InstanceLoadingPane.test.js @@ -0,0 +1,53 @@ +import { + fireEvent, + screen, +} from '@folio/jest-config-stripes/testing-library/react'; + +import '../../../../test/jest/__mock__'; + +import { Icon } from '@folio/stripes/components'; + +import { + renderWithIntl, + translationsProperties, +} from '../../../../test/jest/helpers'; + +import InstanceLoadingPane from './InstanceLoadingPane'; + +Icon.mockClear().mockImplementation(({ icon }) => {icon}); + +const mockOnClose = jest.fn(); + +const renderInstanceLoadingPane = () => { + const component = ; + + return renderWithIntl(component, translationsProperties); +}; + +describe('InstanceLoadingPane', () => { + it('should render loading spinner', () => { + renderInstanceLoadingPane(); + + expect(screen.getByText('spinner-ellipsis')).toBeInTheDocument(); + }); + + it('should render correct header', () => { + renderInstanceLoadingPane(); + + expect(screen.getByText('Edit')).toBeInTheDocument(); + }); + + it('should not render action menu', () => { + renderInstanceLoadingPane(); + + expect(screen.queryByRole('button', { name: 'Actions' })).not.toBeInTheDocument(); + }); + + it('should call onClose cb when pane is closed', () => { + renderInstanceLoadingPane(); + + fireEvent.click(screen.getByRole('button', { name: 'Close Edit' })); + + expect(mockOnClose).toHaveBeenCalled(); + }); +}); diff --git a/src/Instance/InstanceDetails/InstanceLoadingPane/index.js b/src/Instance/InstanceDetails/InstanceLoadingPane/index.js new file mode 100644 index 000000000..29e7c58ee --- /dev/null +++ b/src/Instance/InstanceDetails/InstanceLoadingPane/index.js @@ -0,0 +1 @@ +export { default } from './InstanceLoadingPane'; diff --git a/src/Instance/InstanceDetails/InstanceWarningPane/InstanceWarningPane.js b/src/Instance/InstanceDetails/InstanceWarningPane/InstanceWarningPane.js new file mode 100644 index 000000000..8762ddf3e --- /dev/null +++ b/src/Instance/InstanceDetails/InstanceWarningPane/InstanceWarningPane.js @@ -0,0 +1,38 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { useIntl } from 'react-intl'; + +import { AppIcon } from '@folio/stripes/core'; +import { + Pane, + MessageBanner, +} from '@folio/stripes/components'; + +const InstanceWarningPane = ({ + onClose, + messageBannerText, +}) => { + const intl = useIntl(); + + return ( + } + paneTitle={intl.formatMessage({ id: 'ui-inventory.edit' })} + dismissible + onClose={onClose} + defaultWidth="fill" + > + + {messageBannerText} + + + ); +}; + +InstanceWarningPane.propTypes = { + onClose: PropTypes.func.isRequired, + messageBannerText: PropTypes.oneOfType([PropTypes.element, PropTypes.string]).isRequired, +}; + +export default InstanceWarningPane; diff --git a/src/Instance/InstanceDetails/InstanceWarningPane/InstanceWarningPane.test.js b/src/Instance/InstanceDetails/InstanceWarningPane/InstanceWarningPane.test.js new file mode 100644 index 000000000..bb4603a2d --- /dev/null +++ b/src/Instance/InstanceDetails/InstanceWarningPane/InstanceWarningPane.test.js @@ -0,0 +1,58 @@ +import { + fireEvent, + screen, +} from '@folio/jest-config-stripes/testing-library/react'; + +import '../../../../test/jest/__mock__'; + +import { Icon } from '@folio/stripes/components'; + +import { + renderWithIntl, + translationsProperties, +} from '../../../../test/jest/helpers'; + +import InstanceWarningPane from './InstanceWarningPane'; + +Icon.mockClear().mockImplementation(({ icon }) => {icon}); + +const mockOnClose = jest.fn(); + +const renderInstanceLoadingPane = (messageBannerText = 'warning text') => { + const component = ( + + ); + + return renderWithIntl(component, translationsProperties); +}; + +describe('InstanceWarningPane', () => { + it('should render warning banner', () => { + renderInstanceLoadingPane(); + + expect(screen.getByText('warning text')).toBeInTheDocument(); + }); + + it('should render correct header', () => { + renderInstanceLoadingPane(); + + expect(screen.getByText('Edit')).toBeInTheDocument(); + }); + + it('should not render action menu', () => { + renderInstanceLoadingPane(); + + expect(screen.queryByRole('button', { name: 'Actions' })).not.toBeInTheDocument(); + }); + + it('should call onClose cb when pane is closed', () => { + renderInstanceLoadingPane(); + + fireEvent.click(screen.getByRole('button', { name: 'Close Edit' })); + + expect(mockOnClose).toHaveBeenCalled(); + }); +}); diff --git a/src/Instance/InstanceDetails/InstanceWarningPane/index.js b/src/Instance/InstanceDetails/InstanceWarningPane/index.js new file mode 100644 index 000000000..ab6da1637 --- /dev/null +++ b/src/Instance/InstanceDetails/InstanceWarningPane/index.js @@ -0,0 +1 @@ +export { default } from './InstanceWarningPane'; diff --git a/src/Instance/InstanceDetails/index.js b/src/Instance/InstanceDetails/index.js index 065a56d8f..be1ebdbf8 100644 --- a/src/Instance/InstanceDetails/index.js +++ b/src/Instance/InstanceDetails/index.js @@ -11,6 +11,8 @@ export * from './InstanceTitle'; export * from './InstanceNotesView'; export * from './InstanceNewHolding'; +export { default as InstanceLoadingPane } from './InstanceLoadingPane'; +export { default as InstanceWarningPane } from './InstanceWarningPane'; export { default as SubInstanceList } from './SubInstanceList'; export { default as InstanceDetails } from './InstanceDetails'; export { default as SubInstanceGroup } from './SubInstanceGroup'; diff --git a/src/ViewInstance.js b/src/ViewInstance.js index f687c918a..2ae2cd82a 100644 --- a/src/ViewInstance.js +++ b/src/ViewInstance.js @@ -41,6 +41,7 @@ import { } from './utils'; import { AUTHORITY_LINKED_FIELDS, + HTTP_RESPONSE_STATUS_CODES, indentifierTypeNames, INSTANCE_SHARING_STATUSES, layers, @@ -53,6 +54,8 @@ import { HoldingsListContainer, MoveItemsContext, InstanceDetails, + InstanceWarningPane, + InstanceLoadingPane, } from './Instance'; import { ActionItem, @@ -884,11 +887,18 @@ class ViewInstance extends React.Component { isCentralTenantPermissionsLoading, isShared, isLoading, + isError, + error, } = this.props; const { linkedAuthoritiesLength, isInstanceSharing, } = this.state; + + const isUserLacksPermToViewSharedInstance = isError + && error?.response?.status === HTTP_RESPONSE_STATUS_CODES.FORBIDDEN + && isShared; + const ci = makeConnectedInstance(this.props, stripes.logger); const instance = ci.instance(); @@ -925,6 +935,28 @@ class ViewInstance extends React.Component { const isInstanceLoading = isLoading || !instance || isCentralTenantPermissionsLoading; const keyInStorageToHoldingsAccsState = ['holdings']; + if (isUserLacksPermToViewSharedInstance) { + return ( + } + /> + ); + } + + if (isInstanceSharing) { + return ( + } + /> + ); + } + + if (isInstanceLoading) { + return ; + } + return ( {data => ( @@ -941,8 +973,6 @@ class ViewInstance extends React.Component { tagsEnabled={tagsEnabled} ref={this.accordionStatusRef} userTenantPermissions={this.state.userTenantPermissions} - isLoading={isInstanceLoading} - isInstanceSharing={isInstanceSharing} isShared={isShared} > { @@ -1099,6 +1129,8 @@ ViewInstance.propTypes = { tagsEnabled: PropTypes.bool, updateLocation: PropTypes.func.isRequired, isLoading: PropTypes.bool, + isError: PropTypes.bool, + error: PropTypes.object, }; export default flowRight( diff --git a/src/ViewInstance.test.js b/src/ViewInstance.test.js index 188eb8000..0a6aa4779 100644 --- a/src/ViewInstance.test.js +++ b/src/ViewInstance.test.js @@ -18,7 +18,10 @@ import { checkIfUserInMemberTenant, checkIfUserInCentralTenant, } from '@folio/stripes/core'; -import { ConfirmationModal } from '@folio/stripes/components'; +import { + ConfirmationModal, + Icon, +} from '@folio/stripes/components'; import { instances } from '../test/fixtures/instances'; import { DataContext } from './contexts'; @@ -103,6 +106,8 @@ jest .mockImplementation(() => instance) .mockImplementationOnce(() => {}); +Icon.mockClear().mockImplementation(({ children, icon }) => (children || {icon})); + ConfirmationModal.mockImplementation(({ open, onCancel, @@ -286,6 +291,35 @@ describe('ViewInstance', () => { }); useStripes().hasInterface.mockReturnValue(true); }); + + it('should show a correct Warning message banner when instance sharing is in progress', async () => { + defaultProp.mutator.shareInstance.POST.mockResolvedValue({}); + checkIfUserInMemberTenant.mockClear().mockReturnValue(true); + + renderViewInstance({ isShared: false }); + + fireEvent.click(screen.getByRole('button', { name: 'Actions' })); + fireEvent.click(screen.getByRole('button', { name: 'Share local instance' })); + fireEvent.click(screen.getByRole('button', { name: 'Confirm' })); + + await waitFor(() => expect(screen.getByText('Sharing this local instance will take a few moments.' + + ' A success message and updated details will be displayed upon completion.')).toBeInTheDocument()); + }); + it('should show a correct Warning message banner when user lacks permission to vew shared instance', () => { + renderViewInstance({ + isError: true, + isShared: true, + error: { response: { status: 403 } }, + }); + + expect(screen.getByText('You do not currently have permission to access details of shared instances. ' + + 'Contact your FOLIO administrator for more information.')).toBeInTheDocument(); + }); + it('should show loading spinner when instance is loading', () => { + renderViewInstance({ isLoading: true }); + + expect(screen.getByText('spinner-ellipsis')).toBeInTheDocument(); + }); it('should display action menu items', () => { renderViewInstance(); expect(screen.getByText('Move items within an instance')).toBeInTheDocument(); diff --git a/src/ViewInstanceWrapper.js b/src/ViewInstanceWrapper.js index 170ed5ef1..c50a21283 100644 --- a/src/ViewInstanceWrapper.js +++ b/src/ViewInstanceWrapper.js @@ -17,7 +17,7 @@ const ViewInstanceWrapper = (props) => { const userId = stripes?.user?.user?.id; const centralTenantId = stripes.user.user?.consortium?.centralTenantId; const consortiumId = stripes.user.user?.consortium?.id; - const { instance, isLoading, refetch } = useInstance(id); + const { instance, isLoading, refetch, isError, error } = useInstance(id); const isShared = Boolean(instance?.shared); const tenantId = instance?.tenantId ?? stripes.okapi.tenant; @@ -42,6 +42,8 @@ const ViewInstanceWrapper = (props) => { refetchInstance={refetch} selectedInstance={instance} isLoading={isLoading} + isError={isError} + error={error} centralTenantPermissions={centralTenantPermissions} isCentralTenantPermissionsLoading={isCentralTenantPermissionsLoading} /> diff --git a/src/common/hooks/useInstance.js b/src/common/hooks/useInstance.js index 686408d17..2e5df461b 100644 --- a/src/common/hooks/useInstance.js +++ b/src/common/hooks/useInstance.js @@ -9,7 +9,7 @@ const useInstance = (id) => { const instanceTenantId = _instance?.tenantId; const isShared = _instance?.shared; - const { isLoading: isInstanceLoading, instance: data, refetch } = useInstanceQuery( + const { isLoading: isInstanceLoading, instance: data, refetch, ...rest } = useInstanceQuery( id, { tenantId: instanceTenantId }, { enabled: Boolean(id && !isSearchInstanceByIdLoading) } @@ -32,6 +32,7 @@ const useInstance = (id) => { instance, isLoading, refetch, + ...rest, }; }; diff --git a/src/common/hooks/useInstanceQuery/useInstanceQuery.js b/src/common/hooks/useInstanceQuery/useInstanceQuery.js index 1dc296331..05834e14d 100644 --- a/src/common/hooks/useInstanceQuery/useInstanceQuery.js +++ b/src/common/hooks/useInstanceQuery/useInstanceQuery.js @@ -8,7 +8,7 @@ const useInstanceQuery = (instanceId, { tenantId = '' } = {}, options = {}) => { const ky = useTenantKy({ tenantId }); const [namespace] = useNamespace({ key: 'instance' }); - const { isLoading, data: instance = {}, refetch } = useQuery( + const { isLoading, data: instance = {}, refetch, ...rest } = useQuery( [namespace, instanceId, tenantId], () => ky.get(`inventory/instances/${instanceId}`).json(), { @@ -21,6 +21,7 @@ const useInstanceQuery = (instanceId, { tenantId = '' } = {}, options = {}) => { isLoading, instance, refetch, + ...rest, }); }; diff --git a/src/constants.js b/src/constants.js index 2aaa0852c..2897e5e19 100644 --- a/src/constants.js +++ b/src/constants.js @@ -677,3 +677,7 @@ export const INSTANCE_SHARING_STATUSES = { ERROR: 'ERROR', IN_PROGRESS: 'IN_PROGRESS', }; + +export const HTTP_RESPONSE_STATUS_CODES = { + FORBIDDEN: 403, +}; diff --git a/test/jest/__mock__/stripesIcon.mock.js b/test/jest/__mock__/stripesIcon.mock.js index d50082820..ffcd3589b 100644 --- a/test/jest/__mock__/stripesIcon.mock.js +++ b/test/jest/__mock__/stripesIcon.mock.js @@ -1,7 +1,7 @@ import React from 'react'; jest.mock('@folio/stripes-components/lib/Icon', () => { - return props => { + return jest.fn(props => { return props.children ? props.children : ; - }; + }); }); diff --git a/translations/ui-inventory/en.json b/translations/ui-inventory/en.json index 91e1ac580..68a67612c 100644 --- a/translations/ui-inventory/en.json +++ b/translations/ui-inventory/en.json @@ -799,6 +799,7 @@ "warning.instance.staffSuppressed": "Warning: Instance is marked staff suppressed", "warning.instance.suppressedFromDiscoveryAndStaffSuppressed": "Warning: Instance is marked suppressed from discovery and staff suppressed", "warning.instance.sharingLocalInstance": "Sharing this local instance will take a few moments. A success message and updated details will be displayed upon completion.", + "warning.instance.accessSharedInstance": "You do not currently have permission to access details of shared instances. Contact your FOLIO administrator for more information.", "warning.holdingsRecord.suppressedFromDiscovery": "Warning: Holdings is marked suppressed from discovery", "warning.item.suppressedFromDiscovery": "Warning: Item is marked suppressed from discovery", "discoverySuppressed": "Suppressed from discovery", From 7c70b34c93413c19011d21b63b3bd8c4c9ef8ece Mon Sep 17 00:00:00 2001 From: Mariia_Aloshyna Date: Mon, 6 Nov 2023 15:51:50 +0200 Subject: [PATCH 2/2] Fix comments --- src/ViewInstanceWrapper.js | 8 +++++++- src/common/hooks/useInstance.js | 12 ++++++++++-- .../hooks/useInstanceQuery/useInstanceQuery.js | 7 ++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/ViewInstanceWrapper.js b/src/ViewInstanceWrapper.js index c50a21283..fddc7c78a 100644 --- a/src/ViewInstanceWrapper.js +++ b/src/ViewInstanceWrapper.js @@ -17,7 +17,13 @@ const ViewInstanceWrapper = (props) => { const userId = stripes?.user?.user?.id; const centralTenantId = stripes.user.user?.consortium?.centralTenantId; const consortiumId = stripes.user.user?.consortium?.id; - const { instance, isLoading, refetch, isError, error } = useInstance(id); + const { + instance, + isLoading, + refetch, + isError, + error, + } = useInstance(id); const isShared = Boolean(instance?.shared); const tenantId = instance?.tenantId ?? stripes.okapi.tenant; diff --git a/src/common/hooks/useInstance.js b/src/common/hooks/useInstance.js index 2e5df461b..585cb136d 100644 --- a/src/common/hooks/useInstance.js +++ b/src/common/hooks/useInstance.js @@ -4,12 +4,20 @@ import useSearchInstanceByIdQuery from './useSearchInstanceByIdQuery'; import useInstanceQuery from './useInstanceQuery'; const useInstance = (id) => { - const { isLoading: isSearchInstanceByIdLoading, instance: _instance } = useSearchInstanceByIdQuery(id); + const { + isLoading: isSearchInstanceByIdLoading, + instance: _instance, + } = useSearchInstanceByIdQuery(id); const instanceTenantId = _instance?.tenantId; const isShared = _instance?.shared; - const { isLoading: isInstanceLoading, instance: data, refetch, ...rest } = useInstanceQuery( + const { + isLoading: isInstanceLoading, + instance: data, + refetch, + ...rest + } = useInstanceQuery( id, { tenantId: instanceTenantId }, { enabled: Boolean(id && !isSearchInstanceByIdLoading) } diff --git a/src/common/hooks/useInstanceQuery/useInstanceQuery.js b/src/common/hooks/useInstanceQuery/useInstanceQuery.js index 05834e14d..4e478348a 100644 --- a/src/common/hooks/useInstanceQuery/useInstanceQuery.js +++ b/src/common/hooks/useInstanceQuery/useInstanceQuery.js @@ -8,7 +8,12 @@ const useInstanceQuery = (instanceId, { tenantId = '' } = {}, options = {}) => { const ky = useTenantKy({ tenantId }); const [namespace] = useNamespace({ key: 'instance' }); - const { isLoading, data: instance = {}, refetch, ...rest } = useQuery( + const { + isLoading, + data: instance = {}, + refetch, + ...rest + } = useQuery( [namespace, instanceId, tenantId], () => ky.get(`inventory/instances/${instanceId}`).json(), {