Skip to content

Commit

Permalink
UIBULKED-571 Errors in response to UI calls
Browse files Browse the repository at this point in the history
  • Loading branch information
vashjs committed Dec 10, 2024
1 parent 7db3438 commit 6432548
Show file tree
Hide file tree
Showing 19 changed files with 189 additions and 71 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
* [UIBULKED-560](https://folio-org.atlassian.net/browse/UIBULKED-560) Update actions menu.
* [UIBULKED-585](https://folio-org.atlassian.net/browse/UUIBULKED-585) Adding missing translation and filters.
* [UIBULKED-561](https://folio-org.atlassian.net/browse/UUIBULKED-561) Add administrative data accordion to MARC bulk edit form.
* [UIBULKED-571](https://folio-org.atlassian.net/browse/UIBULKED-571) Errors in response to UI calls.

## [4.2.2](https://github.com/folio-org/ui-bulk-edit/tree/v4.2.2) (2024-11-15)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ jest.mock('../../../hooks/api', () => ({
useErrorsPreview: () => ({
errors: [],
}),
useUserGroupsMap: () => ({}),
}));

const setCountOfRecordsMock = jest.fn();
Expand Down
6 changes: 3 additions & 3 deletions src/components/PermissionsModal/hooks/useAllPermissions.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { useQuery } from 'react-query';
import { useNamespace, useOkapiKy } from '@folio/stripes/core';
import { FILTER_KEYS } from '../constants/core';
import { useErrorMessages } from '../../../hooks/useErrorMessages';
import { MOD_PERMISSIONS } from '../../../constants';

export const ALL_PERMISSIONS_KEY = 'ALL_PERMISSIONS_KEY';

export const useAllPermissions = (options = {}) => {
const ky = useOkapiKy();
const [namespaceKey] = useNamespace({ key: ALL_PERMISSIONS_KEY });
const { showErrorMessage } = useErrorMessages();
const { showExternalModuleError } = useErrorMessages();

const { data: permissions, isLoading: isPermissionsLoading } = useQuery(
{
Expand All @@ -20,8 +21,7 @@ export const useAllPermissions = (options = {}) => {
...permission,
type: permission.mutable ? FILTER_KEYS.PERMISSION_SETS : FILTER_KEYS.PERMISSIONS,
})),
onError: showErrorMessage,
onSuccess: showErrorMessage,
onError: (error) => showExternalModuleError(MOD_PERMISSIONS, error),
...options,
},
);
Expand Down
45 changes: 45 additions & 0 deletions src/constants/errorStatuses.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
export const ERROR_STATUSES = {
// 4xx Client Errors
400: 'Bad Request',
401: 'Unauthorized',
402: 'Payment Required',
403: 'Forbidden',
404: 'Not Found',
405: 'Method Not Allowed',
406: 'Not Acceptable',
407: 'Proxy Authentication Required',
408: 'Request Timeout',
409: 'Conflict',
410: 'Gone',
411: 'Length Required',
412: 'Precondition Failed',
413: 'Payload Too Large',
414: 'URI Too Long',
415: 'Unsupported Media Type',
416: 'Range Not Satisfiable',
417: 'Expectation Failed',
418: "I'm a teapot",
421: 'Misdirected Request',
422: 'Unprocessable Content',
423: 'Locked',
424: 'Failed Dependency',
425: 'Too Early',
426: 'Upgrade Required',
428: 'Precondition Required',
429: 'Too Many Requests',
431: 'Request Header Fields Too Large',
451: 'Unavailable For Legal Reasons',

// 5xx Server Errors
500: 'Internal Server Error',
501: 'Not Implemented',
502: 'Bad Gateway',
503: 'Service Unavailable',
504: 'Gateway Timeout',
505: 'HTTP Version Not Supported',
506: 'Variant Also Negotiates',
507: 'Insufficient Storage',
508: 'Loop Detected',
510: 'Not Extended',
511: 'Network Authentication Required'
};
2 changes: 2 additions & 0 deletions src/constants/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ export * from './inAppActions';
export * from '../utils/date';
export * from './files';
export * from './logsActions';
export * from './errorStatuses';
export * from './moduleNames';
5 changes: 5 additions & 0 deletions src/constants/moduleNames.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export const MOD_INVENTORY_STORAGE = 'mod-inventory-storage';
export const MOD_USERS = 'mod-users';
export const MOD_PERMISSIONS = 'mod-permissions';
export const MOD_FQM_MANAGER = 'mod-fqm-manager';
export const MOD_CONSORTIA = 'mod-consortia';
1 change: 0 additions & 1 deletion src/hooks/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ export * from './useBulkOperationStart';
export * from './useUpload';
export * from './useBulkEditLogs';
export * from './useErrorsPreview';
export * from './useUserGroupsMap';
export * from './usePatronGroup';
export * from './useLoanTypes';
export * from './useBulkOperationDetails';
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/api/useElectronicAccess.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { useNamespace, useOkapiKy } from '@folio/stripes/core';
import { useQuery } from 'react-query';
import { useErrorMessages } from '../useErrorMessages';
import { MOD_INVENTORY_STORAGE } from '../../constants';

export const ELECTRONIC_ACCESS_RELATIONSHIPS_KEY = 'ELECTRONIC_ACCESS_RELATIONSHIPS_KEY';

export const useElectronicAccessRelationships = (options = {}) => {
const ky = useOkapiKy();
const [namespaceKey] = useNamespace({ key: ELECTRONIC_ACCESS_RELATIONSHIPS_KEY });
const { showErrorMessage } = useErrorMessages();
const { showExternalModuleError } = useErrorMessages();

const { data, isLoading: isElectronicAccessLoading } = useQuery(
{
queryKey: [namespaceKey],
cacheTime: Infinity,
staleTime: Infinity,
queryFn: () => ky.get('electronic-access-relationships?limit=1000&query=cql.allRecords=1 sortby name').json(),
onError: showErrorMessage,
onSuccess: showErrorMessage,
onError: (error) => showExternalModuleError(MOD_INVENTORY_STORAGE, error),
...options,
},
);
Expand Down
8 changes: 4 additions & 4 deletions src/hooks/api/useHoldingsNotes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,26 +2,26 @@ import { useNamespace, useOkapiKy } from '@folio/stripes/core';
import { useQuery } from 'react-query';
import { useIntl } from 'react-intl';
import { useMemo } from 'react';
import { OPTIONS, PARAMETERS_KEYS } from '../../constants';
import { OPTIONS, PARAMETERS_KEYS, MOD_INVENTORY_STORAGE } from '../../constants';
import { getMappedAndSortedNotes } from '../../utils/helpers';
import { useErrorMessages } from '../useErrorMessages';


export const HOLDINGS_NOTES_KEY = 'HOLDINGS_NOTES_KEY';

export const useHoldingsNotes = (options = {}) => {
const ky = useOkapiKy();
const [namespaceKey] = useNamespace({ key: HOLDINGS_NOTES_KEY });
const { formatMessage } = useIntl();
const { showErrorMessage } = useErrorMessages();
const { showExternalModuleError } = useErrorMessages();

const { data, isLoading: isHoldingsNotesLoading } = useQuery(
{
queryKey: [namespaceKey],
cacheTime: Infinity,
staleTime: Infinity,
queryFn: () => ky.get('holdings-note-types', { searchParams: { limit: 1000 } }).json(),
onError: showErrorMessage,
onSuccess: showErrorMessage,
onError: (error) => showExternalModuleError(MOD_INVENTORY_STORAGE, error),
...options,
},
);
Expand Down
7 changes: 3 additions & 4 deletions src/hooks/api/useInstanceNotes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useNamespace, useOkapiKy } from '@folio/stripes/core';
import { useQuery } from 'react-query';
import { useIntl } from 'react-intl';
import { useMemo } from 'react';
import { OPTIONS, PARAMETERS_KEYS } from '../../constants';
import { MOD_INVENTORY_STORAGE, OPTIONS, PARAMETERS_KEYS } from '../../constants';
import { getMappedAndSortedNotes } from '../../utils/helpers';
import { useErrorMessages } from '../useErrorMessages';

Expand All @@ -12,16 +12,15 @@ export const useInstanceNotes = (options = {}) => {
const ky = useOkapiKy();
const [namespaceKey] = useNamespace({ key: INSTANCE_NOTES_KEY });
const { formatMessage } = useIntl();
const { showErrorMessage } = useErrorMessages();
const { showExternalModuleError } = useErrorMessages();

const { data, isLoading: isInstanceNotesLoading } = useQuery(
{
queryKey: [namespaceKey],
cacheTime: Infinity,
staleTime: Infinity,
queryFn: () => ky.get('instance-note-types', { searchParams: { limit: 1000 } }).json(),
onError: showErrorMessage,
onSuccess: showErrorMessage,
onError: (error) => showExternalModuleError(MOD_INVENTORY_STORAGE, error),
...options,
},
);
Expand Down
7 changes: 3 additions & 4 deletions src/hooks/api/useItemNotes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { useNamespace, useOkapiKy } from '@folio/stripes/core';
import { useQuery } from 'react-query';
import { useIntl } from 'react-intl';
import { useMemo } from 'react';
import { OPTIONS, PARAMETERS_KEYS } from '../../constants';
import { MOD_INVENTORY_STORAGE, OPTIONS, PARAMETERS_KEYS } from '../../constants';
import { getMappedAndSortedNotes } from '../../utils/helpers';
import { useErrorMessages } from '../useErrorMessages';

Expand All @@ -12,16 +12,15 @@ export const useItemNotes = (options = {}) => {
const ky = useOkapiKy();
const [namespaceKey] = useNamespace({ key: ITEM_NOTES_KEY });
const { formatMessage } = useIntl();
const { showErrorMessage } = useErrorMessages();
const { showExternalModuleError } = useErrorMessages();

const { data, isLoading: isItemNotesLoading } = useQuery(
{
queryKey: [namespaceKey],
cacheTime: Infinity,
staleTime: Infinity,
queryFn: () => ky.get('item-note-types', { searchParams: { limit: 1000 } }).json(),
onError: showErrorMessage,
onSuccess: showErrorMessage,
onError: (error) => showExternalModuleError(MOD_INVENTORY_STORAGE, error),
...options,
},
);
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/api/useLoanTypes.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import { useNamespace, useOkapiKy } from '@folio/stripes/core';
import { useQuery } from 'react-query';
import { useErrorMessages } from '../useErrorMessages';
import { MOD_INVENTORY_STORAGE } from '../../constants';

export const LOAN_TYPES_KEY = 'LOAN_TYPES_KEY';

export const useLoanTypes = (options = {}) => {
const ky = useOkapiKy();
const [namespaceKey] = useNamespace({ key: LOAN_TYPES_KEY });
const { showErrorMessage } = useErrorMessages();
const { showExternalModuleError } = useErrorMessages();

const { data, isLoading } = useQuery(
{
queryKey: [namespaceKey],
cacheTime: Infinity,
staleTime: Infinity,
queryFn: () => ky.get('loan-types?query=cql.allRecords%3D1%20sortby%20name&limit=1000').json(),
onError: showErrorMessage,
onSuccess: showErrorMessage,
onError: (error) => showExternalModuleError(MOD_INVENTORY_STORAGE, error),
...options,
},
);
Expand Down
6 changes: 3 additions & 3 deletions src/hooks/api/usePatronGroup.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,21 @@ import {

import { useNamespace, useOkapiKy } from '@folio/stripes/core';
import { useErrorMessages } from '../useErrorMessages';
import { MOD_USERS } from '../../constants';

export const PATRON_GROUP_KEY = 'PATRON_GROUP_KEY';

export const usePatronGroup = (options = {}) => {
const ky = useOkapiKy();
const [namespaceKey] = useNamespace({ key: PATRON_GROUP_KEY });
const { showErrorMessage } = useErrorMessages();
const { showExternalModuleError } = useErrorMessages();

const { data, isLoading } = useQuery(
{
queryKey: [namespaceKey],
cacheTime: Infinity,
staleTime: Infinity,
onSuccess: showErrorMessage,
onError: showErrorMessage,
onError: (error) => showExternalModuleError(MOD_USERS, error),
queryFn: async () => {
const { usergroups } = await ky.get('groups', { searchParams: { limit: 200 } }).json();

Expand Down
6 changes: 3 additions & 3 deletions src/hooks/api/useRecordTypes.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
import { useNamespace, useOkapiKy } from '@folio/stripes/core';
import { useQuery } from 'react-query';
import { useErrorMessages } from '../useErrorMessages';
import { MOD_FQM_MANAGER } from '../../constants';

export const ENTITY_TYPE_KEY = 'ENTITY_TYPE_KEY';

export const useRecordTypes = ({ enabled } = {}) => {
const ky = useOkapiKy();
const [namespaceKey] = useNamespace({ key: ENTITY_TYPE_KEY });
const { showErrorMessage } = useErrorMessages();
const { showExternalModuleError } = useErrorMessages();

const { data, isLoading, error } = useQuery({
queryKey: [namespaceKey],
Expand All @@ -18,8 +19,7 @@ export const useRecordTypes = ({ enabled } = {}) => {
},
cacheTime: Infinity,
staleTime: Infinity,
onError: showErrorMessage,
onSuccess: showErrorMessage,
onError: (err) => showExternalModuleError(MOD_FQM_MANAGER, err),
enabled
});

Expand Down
38 changes: 0 additions & 38 deletions src/hooks/api/useUserGroupsMap.js

This file was deleted.

16 changes: 15 additions & 1 deletion src/hooks/useErrorMessages.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { useIntl } from 'react-intl';
import { useShowCallout } from '@folio/stripes-acq-components';

import { ERRORS } from '../constants';
import { ERRORS, ERROR_STATUSES } from '../constants';
import { useSearchParams } from './useSearchParams';


Expand Down Expand Up @@ -41,7 +41,21 @@ export const useErrorMessages = () => {
}
};

const showExternalModuleError = (moduleName, error) => {
const status = error?.status ?? 500;
const message = error?.message;

const statusError = ERROR_STATUSES[status];
const messageError = ERROR_STATUSES[message]; // Some modules return the error message as a known status

// Determine message details based on priority: messageError > message > statusError
const messageDetails = messageError || message || statusError;

showError(`${moduleName} returns status code: ${status} - ${messageDetails}.`);
};

return {
showErrorMessage,
showExternalModuleError,
};
};
Loading

0 comments on commit 6432548

Please sign in to comment.