Skip to content

Commit

Permalink
Merge branch 'master' into UIIN-2634
Browse files Browse the repository at this point in the history
  • Loading branch information
OleksandrHladchenko1 authored Oct 27, 2023
2 parents deb0c21 + e583600 commit 6823dbd
Show file tree
Hide file tree
Showing 27 changed files with 308 additions and 165 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@
* Remove error message after switch from Instance Edit screen to another app. Fixes UIIN-2600.
* Enable/disable consortial holdings/item actions based on User permissions. Refs UIIN-2452.
* User receives an error when searching for an item in the Inventory app. Fixes UIIN-2634.
* 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.

## [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)
Expand Down
11 changes: 6 additions & 5 deletions src/Holding/CreateHolding/CreateHolding.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ const CreateHolding = ({
const callout = useCallout();
const { instance, isLoading: isInstanceLoading } = useInstance(instanceId);
const sourceId = referenceData.holdingsSourcesByName?.FOLIO?.id;
const { location: { state: { tenantFrom } } } = history;
const tenantFrom = location?.state?.tenantFrom || stripes.okapi.tenant;

const goBack = useCallback(() => {
history.push({
Expand All @@ -39,21 +39,22 @@ const CreateHolding = ({
});
}, [location.search, instanceId]);

const onCancel = useCallback(() => {
switchAffiliation(stripes, tenantFrom, goBack);
const onCancel = useCallback(async () => {
await switchAffiliation(stripes, tenantFrom, goBack);
}, [stripes, tenantFrom, goBack]);

const onSubmit = useCallback((newHolding) => {
return mutator.holding.POST(newHolding)
.then((holdingsRecord) => {
.then(async (holdingsRecord) => {
await onCancel();

callout.sendCallout({
type: 'success',
message: <FormattedMessage
id="ui-inventory.holdingsRecord.successfullySaved"
values={{ hrid: holdingsRecord.hrid }}
/>,
});
onCancel();
});
}, [onCancel, callout]);

Expand Down
25 changes: 22 additions & 3 deletions src/Holding/DuplicateHolding/DuplicateHolding.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,20 @@ import {
} from '../../hooks';
import HoldingsForm from '../../edit/holdings/HoldingsForm';
import withLocation from '../../withLocation';
import { switchAffiliation } from '../../utils';

const DuplicateHolding = ({
goTo,
history,
instanceId,
holdingId,
location: { search, state: locationState },
location: {
search,
state: {
backPathname: locationState,
tenantFrom,
} = {},
},
referenceTables,
}) => {
const callout = useCallout();
Expand All @@ -37,10 +44,18 @@ const DuplicateHolding = ({
sourceId,
}), [holding, sourceId]);

const goToDuplicatedHolding = useCallback((id) => {
history.push({
pathname: `/inventory/view/${instanceId}/${id}`,
search,
state: { tenantTo: stripes.okapi.tenant },
});
}, [search, instanceId]);

const onSuccess = useCallback(async (response) => {
const { id, hrid } = await response.json();

goTo(`/inventory/view/${instanceId}/${id}`);
await switchAffiliation(stripes, tenantFrom, () => goToDuplicatedHolding(id));

return callout.sendCallout({
type: 'success',
Expand All @@ -53,13 +68,17 @@ const DuplicateHolding = ({

const { mutateHolding } = useHoldingMutation({ onSuccess });

const onCancel = useCallback(() => {
const goBack = useCallback(() => {
history.push({
pathname: locationState?.backPathname ?? `/inventory/view/${instanceId}`,
search,
});
}, [search, instanceId]);

const onCancel = useCallback(async () => {
await switchAffiliation(stripes, tenantFrom, goBack);
}, [stripes, tenantFrom, goBack]);

const onSubmit = useCallback(holdingValues => (
mutateHolding(holdingValues)
), [mutateHolding]);
Expand Down
25 changes: 19 additions & 6 deletions src/Holding/EditHolding/EditHolding.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@ import {
} from '../../hooks';
import HoldingsForm from '../../edit/holdings/HoldingsForm';
import withLocation from '../../withLocation';
import { parseHttpError } from '../../utils';
import {
parseHttpError,
switchAffiliation,
} from '../../utils';

const EditHolding = ({
goTo,
Expand All @@ -28,7 +31,13 @@ const EditHolding = ({
referenceTables,
}) => {
const callout = useCallout();
const { search, state: locationState } = location;
const {
search,
state: {
backPathname: locationState,
tenantFrom,
} = {},
} = location;
const stripes = useStripes();
const [httpError, setHttpError] = useState();
const { instance, isLoading: isInstanceLoading } = useInstanceQuery(instanceId);
Expand All @@ -42,17 +51,21 @@ const EditHolding = ({
referenceTables?.holdingsSources?.find(source => source.id === holding?.sourceId)?.name === 'MARC'
), [holding]);

const onCancel = useCallback(() => {
const goBack = useCallback(() => {
history.push({
pathname: locationState?.backPathname ?? `/inventory/view/${instanceId}`,
search,
});
}, [search, instanceId]);

const onSuccess = useCallback(() => {
onCancel();
const onCancel = useCallback(async () => {
await switchAffiliation(stripes, tenantFrom, goBack);
}, [stripes, tenantFrom, goBack]);

const onSuccess = useCallback(async () => {
await onCancel();

return callout.sendCallout({
callout.sendCallout({
type: 'success',
message: <FormattedMessage
id="ui-inventory.holdingsRecord.successfullySaved"
Expand Down
8 changes: 6 additions & 2 deletions src/Instance/HoldingsList/Holding/HoldingButtonsGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,9 @@ const HoldingButtonsGroup = ({
<Button
id={`clickable-view-holdings-${holding.id}`}
data-test-view-holdings
onClick={() => switchAffiliation(stripes, tenantId, onViewHolding)}
onClick={async () => {
await switchAffiliation(stripes, tenantId, onViewHolding);
}}
>
<FormattedMessage id="ui-inventory.viewHoldings" />
</Button>
Expand All @@ -58,7 +60,9 @@ const HoldingButtonsGroup = ({
<Button
id={`clickable-new-item-${holding.id}`}
data-test-add-item
onClick={() => switchAffiliation(stripes, tenantId, onAddItem)}
onClick={async () => {
await switchAffiliation(stripes, tenantId, onAddItem);
}}
buttonStyle="primary paneHeaderNewButton"
>
<FormattedMessage id="ui-inventory.addItem" />
Expand Down
13 changes: 6 additions & 7 deletions src/Instance/HoldingsList/HoldingsListContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,8 @@ const HoldingsListContainer = ({
const stripes = useStripes();
const { holdingsRecords: holdings, isLoading } = useInstanceHoldingsQuery(instance.id, { tenantId });

const canViewHoldings = stripes.hasPerm('ui-inventory.instance.view');
const canCreateItem = stripes.hasPerm('ui-inventory.item.edit');
const canViewItems = stripes.hasPerm('ui-inventory.instance.view');
const canViewHoldingsAndItems = stripes.hasPerm('ui-inventory.instance.view');
const canCreateItem = stripes.hasPerm('ui-inventory.item.create');

if (isLoading) return <Loading size="large" />;

Expand All @@ -31,9 +30,9 @@ const HoldingsListContainer = ({
holdings={holdings}
instance={instance}
tenantId={tenantId}
showViewHoldingsButton={canViewHoldings}
showViewHoldingsButton={canViewHoldingsAndItems}
showAddItemButton={canCreateItem}
isBarcodeAsHotlink={canViewItems}
isBarcodeAsHotlink={canViewHoldingsAndItems}
pathToAccordionsState={pathToAccordionsState}
/>
) : (
Expand All @@ -42,9 +41,9 @@ const HoldingsListContainer = ({
holdings={holdings}
instance={instance}
tenantId={tenantId}
showViewHoldingsButton={canViewHoldings}
showViewHoldingsButton={canViewHoldingsAndItems}
showAddItemButton={canCreateItem}
isBarcodeAsHotlink={canViewItems}
isBarcodeAsHotlink={canViewHoldingsAndItems}
pathToAccordionsState={pathToAccordionsState}
/>
)
Expand Down
99 changes: 61 additions & 38 deletions src/Instance/InstanceDetails/InstanceDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ const InstanceDetails = forwardRef(({
userTenantPermissions,
isShared,
isLoading,
isInstanceSharing,
...rest
}, ref) => {
const intl = useIntl();
Expand All @@ -85,12 +86,15 @@ const InstanceDetails = forwardRef(({
const accordionState = useMemo(() => getAccordionState(instance, accordions), [instance]);
const [helperApp, setHelperApp] = useState();

const isBasicPane = isInstanceSharing || isLoading;
const tags = instance?.tags?.tagList;
const isUserInCentralTenant = checkIfUserInCentralTenant(stripes);

const canCreateHoldings = stripes.hasPerm('ui-inventory.holdings.edit');
const canCreateHoldings = stripes.hasPerm('ui-inventory.holdings.create');

const detailsLastMenu = useMemo(() => {
if (isBasicPane) return null;

return (
<PaneMenu>
{
Expand All @@ -106,31 +110,15 @@ const InstanceDetails = forwardRef(({
}
</PaneMenu>
);
}, [tagsEnabled, tags, intl]);

if (isLoading) {
return (
<Pane
id="pane-instancedetails"
defaultWidth="fill"
paneTitle={intl.formatMessage({ id: 'ui-inventory.edit' })}
appIcon={<AppIcon app="inventory" iconKey="instance" />}
dismissible
onClose={onClose}
>
<div style={{ paddingTop: '1rem' }}>
<Icon
icon="spinner-ellipsis"
width="100px"
/>
</div>
</Pane>
);
}

const isConsortialHoldingsVisible = instance?.shared || isInstanceShadowCopy(instance?.source);
}, [isBasicPane, tagsEnabled, tags, intl]);
const detailsActionMenu = useMemo(
() => (isBasicPane ? null : actionMenu),
[isBasicPane, actionMenu],
);

const renderPaneTitle = () => {
if (isBasicPane) return intl.formatMessage({ id: 'ui-inventory.edit' });

const isInstanceShared = Boolean(isShared || isInstanceShadowCopy(instance?.source));

return (
Expand All @@ -146,6 +134,8 @@ const InstanceDetails = forwardRef(({
};

const renderPaneSubtitle = () => {
if (isBasicPane) return null;

return (
<FormattedMessage
id="ui-inventory.instanceRecordSubtitle"
Expand All @@ -157,20 +147,32 @@ const InstanceDetails = forwardRef(({
);
};

return (
<>
<Pane
{...rest}
data-test-instance-details
appIcon={<AppIcon app="inventory" iconKey="instance" />}
paneTitle={renderPaneTitle()}
paneSub={renderPaneSubtitle()}
dismissible
onClose={onClose}
actionMenu={actionMenu}
defaultWidth="fill"
lastMenu={detailsLastMenu}
>
const renderDetails = () => {
if (isInstanceSharing) {
return (
<div>
<MessageBanner show={Boolean(isInstanceSharing)} type="warning">
<FormattedMessage id="ui-inventory.warning.instance.sharingLocalInstance" />
</MessageBanner>
</div>
);
}

if (isLoading) {
return (
<div>
<Icon
icon="spinner-ellipsis"
width="100px"
/>
</div>
);
}

const isConsortialHoldingsVisible = instance?.shared || isInstanceShadowCopy(instance?.source);

return (
<>
<TitleManager record={instance.title} />

<AccordionStatus ref={ref}>
Expand Down Expand Up @@ -291,6 +293,25 @@ const InstanceDetails = forwardRef(({
/>
</AccordionSet>
</AccordionStatus>
</>
);
};

return (
<>
<Pane
{...rest}
data-test-instance-details
appIcon={<AppIcon app="inventory" iconKey="instance" />}
paneTitle={renderPaneTitle()}
paneSub={renderPaneSubtitle()}
actionMenu={detailsActionMenu}
lastMenu={detailsLastMenu}
dismissible
onClose={onClose}
defaultWidth="fill"
>
{renderDetails()}
</Pane>
{ helperApp && <HelperApp appName={helperApp} onClose={setHelperApp} />}
</>
Expand All @@ -306,13 +327,15 @@ InstanceDetails.propTypes = {
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,
};

Expand Down
7 changes: 7 additions & 0 deletions src/Instance/InstanceDetails/InstanceDetails.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ 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,
Expand Down
Loading

0 comments on commit 6823dbd

Please sign in to comment.