Skip to content

Commit

Permalink
UITEN-278 - create reading room from tenant settings (#393)
Browse files Browse the repository at this point in the history
* UITEN-278 - create reading room from tenant settings

* UITEN-278 - update package.json

* UITEN-278 - Add prop type validation

* UITEN-278 - update jest config

* UITEN-278 - add unit test

* UITEN-278 - update to final form

* UITEN-278 - update uni test

* UITEN-278 - refinement

* UITEN-278 - add validators, refine code

* UITEN-278 - refine

* UITEN-278 - disable lint rule

* UITEN-278 - refine

* UITEN-278 - fix prop types sonar problem

* UITEN-278 - update permission check on reading room access

* UITEN-278 - fix review comments
  • Loading branch information
Terala-Priyanka authored Apr 29, 2024
1 parent 8db6552 commit 75343f0
Show file tree
Hide file tree
Showing 9 changed files with 406 additions and 101 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 @@
* [UITEN-287](https://folio-org.atlassian.net/browse/UITEN-287) Add new permission to create, edit and remove reading room access in tenant settings.
* [UITEN-277](https://issues.folio.org/browse/UITEN-277) Ensure Reading Room Access settings page is wrapped by `Title Manager`.
* [UITEN-276](https://issues.folio.org/browse/UITEN-276) Reading Room Access (settings): Basic Layout.
* [UITEN-278] (https://issues.folio.org/browse/UITEN-278) Reading Room Access (settings): Create new reading room.

## [8.1.0](https://github.com/folio-org/ui-tenant-settings/tree/v8.1.0)(2024-03-19)
[Full Changelog](https://github.com/folio-org/ui-tenant-settings/compare/v8.0.0...v8.1.0)
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,7 @@
"displayName": "Settings (tenant): Can view reading room access",
"subPermissions": [
"reading-room.collection.get",
"inventory-storage.service-points.collection.get",
"settings.tenant-settings.enabled"
],
"visible": true
Expand Down Expand Up @@ -242,8 +243,8 @@
"devDependencies": {
"@babel/core": "^7.20.12",
"@babel/eslint-parser": "^7.19.1",
"@babel/plugin-transform-class-properties": "^7.12.1",
"@babel/plugin-proposal-decorators": "^7.0.0",
"@babel/plugin-transform-class-properties": "^7.12.1",
"@babel/plugin-transform-private-methods": "^7.18.6",
"@babel/plugin-transform-private-property-in-object": "^7.21.11",
"@babel/plugin-transform-runtime": "^7.10.5",
Expand Down
168 changes: 96 additions & 72 deletions src/settings/ReadingRoomAccess/ReadingRoomAccess.js
Original file line number Diff line number Diff line change
@@ -1,68 +1,18 @@
import React from 'react';
import React, { useCallback, useMemo } from 'react';
import PropTypes from 'prop-types';
import { useIntl } from 'react-intl';
import _ from 'lodash';

import { TitleManager, useStripes } from '@folio/stripes/core';
import {
Label,
Checkbox,
} from '@folio/stripes/components';
import { Label } from '@folio/stripes/components';
import { ControlledVocab } from '@folio/stripes/smart-components';

const readingRoomsData = {
values: { records: [
{
'id': 1,
'name': 'RR1',
'public': true,
'servicePoint': [
{
name: 'Circ Desk 1',
id: '3a40852d-49fd-4df2-a1f9-6e2641a6e91f',
},
{
id: 'c4c90014-c8c9-4ade-8f24-b5e313319f4b',
name: 'Circ Desk 2'
},
],
// metadata: {
// 'createdDate': '2024-03-21T10:59:25.085+00:00',
// 'createdByUserId': 'af5ad81e-6857-5b65-9c0c-60942e56f872',
// 'updatedDate': '2024-03-21T10:59:25.085+00:00',
// 'updatedByUserId': 'af5ad81e-6857-5b65-9c0c-60942e56f872'
// }
},
{
'id': 2,
'name': 'RR2',
'public': true,
'servicePoint': [{
name: 'Circ Desk 1',
id: '3a40852d-49fd-4df2-a1f9-6e2641a6e91f',
}],
// metadata: {
// 'createdDate': '2024-03-21T10:59:25.085+00:00',
// 'createdByUserId': 'af5ad81e-6857-5b65-9c0c-60942e56f872',
// 'updatedDate': '2024-03-21T10:59:25.085+00:00',
// 'updatedByUserId': 'af5ad81e-6857-5b65-9c0c-60942e56f872'
// }
},
] },
updaters: {
records: []
},
updaterIds: [],
};
import { readingRoomAccessColumns } from './constant';
import { getFormatter } from './getFormatter';
import { getFieldComponents } from './getFieldComponents';
import { getValidators } from './getValidators';

const hiddenFields = ['numberOfObjects', 'lastUpdated'];
const visibleFields = ['name', 'public', 'servicePoint'];
const formatter = {
'public': (record) => <Checkbox checked={record.public} disabled />,
'servicePoint': (value) => {
const asp = value.servicePoint || [];
const items = asp.map(a => <li key={a.name}>{a.name}</li>);
return <ul className="marginBottom0">{items}</ul>;
}
};
const translations = {
cannotDeleteTermHeader: 'ui-tenant-settings.settings.addresses.cannotDeleteTermHeader',
cannotDeleteTermMessage: 'ui-tenant-settings.settings.addresses.cannotDeleteTermMessage',
Expand All @@ -74,49 +24,123 @@ const translations = {
const ReadingRoomAccess = (props) => {
const intl = useIntl();
const stripes = useStripes();
const { resources } = props;

// service points defined in the tenant
const servicePoints = _.get(resources, ['RRAServicePoints', 'records', 0, 'servicepoints'], []);
/**
* A reading room can have more than one service points assigned to it.
* but a servicepoint cannot be mapped to more than one reading room
*/
const sps = [];
const rrs = _.get(resources, ['values', 'records']);

rrs.forEach(rr => {
const asp = rr.servicePoints || [];
asp.forEach(s => {
if (!sps.includes(s.value)) {
sps.push(s.value);
}
});
});

const options = servicePoints.reduce((acc, s) => {
if (!sps.includes(s.id) || s.name === 'None') {
acc.push({ value: s.id, label: s.name });
}
return acc;
}, []);

const fieldLabels = useMemo(() => ({
[readingRoomAccessColumns.NAME]: intl.formatMessage({ id: 'ui-tenant-settings.settings.reading-room-access.name' }),
[readingRoomAccessColumns.ISPUBLIC]: intl.formatMessage({ id: 'ui-tenant-settings.settings.reading-room-access.public' }),
[readingRoomAccessColumns.SERVICEPOINTS]: intl.formatMessage({ id: 'ui-tenant-settings.settings.reading-room-access.asp' }),
}), [intl]);

const visibleFields = useMemo(() => ([
readingRoomAccessColumns.NAME,
readingRoomAccessColumns.ISPUBLIC,
readingRoomAccessColumns.SERVICEPOINTS,
]), []);

const getRequiredLabel = useCallback(columnLabel => (
<Label required>{columnLabel}</Label>
), []);

const columnMapping = {
name: (
<Label
tagName="span"
required
>
{
intl.formatMessage({ id:'ui-tenant-settings.settings.reading-room-access.name' })
const columnMapping = useMemo(() => ({
[readingRoomAccessColumns.NAME]: getRequiredLabel(fieldLabels[readingRoomAccessColumns.NAME]),
[readingRoomAccessColumns.ISPUBLIC]: fieldLabels[readingRoomAccessColumns.ISPUBLIC],
[readingRoomAccessColumns.SERVICEPOINTS]: getRequiredLabel(fieldLabels[readingRoomAccessColumns.SERVICEPOINTS])
}), [fieldLabels, getRequiredLabel]);

const formatter = useMemo(() => getFormatter({ fieldLabels }), [fieldLabels]);

const validateItem = useCallback((item, items) => {
const errors = Object.values(readingRoomAccessColumns).reduce((acc, field) => {
const error = getValidators(field)?.(item, items);

if (error) {
acc[field] = error;
}
</Label>),
public: intl.formatMessage({ id:'ui-tenant-settings.settings.reading-room-access.public' }),
servicePoint: intl.formatMessage({ id:'ui-tenant-settings.settings.reading-room-access.asp' }),
};

const editable = false; // stripes.hasPerm('ui-users.settings.reading-room-access.all');
return acc;
}, {});

return errors;
}, []);

const validate = (item, index, items) => validateItem(item, items) || {};

const editable = stripes.hasPerm('ui-tenant-settings.settings.reading-room-access.all');

return (
<TitleManager page={intl.formatMessage({ id: 'ui-tenant-settings.settings.reading-room.title' })}>
<ControlledVocab
{...props}
id="reading-room-access-settings"
baseUrl="reading-room"
stripes={stripes}
label={intl.formatMessage({ id: 'ui-tenant-settings.settings.reading-room-access.label' })}
objectLabel={intl.formatMessage({ id: 'ui-tenant-settings.settings.reading-room-access.label' })}
resources={readingRoomsData}
records="readingRooms"
visibleFields={visibleFields}
columnMapping={columnMapping}
hiddenFields={hiddenFields}
formatter={formatter}
translations={translations}
editable={editable}
fieldComponents={getFieldComponents(fieldLabels, options)}
validate={validate}
actionSuppressor={{ // TODO: action suppressor will be removed in the scope of another ticket
edit: () => true,
delete: () => true,
}}
formType="final-form"
/>
</TitleManager>
);
};

ReadingRoomAccess.manifest = Object.freeze({
values: {
type: 'okapi',
records: 'readingRooms',
path: 'reading-room',
GET: {
path: 'reading-room?query=cql.allRecords=1 sortby name&limit=100'
}
},
updaterIds: [],
RRAServicePoints: {
type: 'okapi',
resource: 'service-points',
path: 'service-points?limit=200',
},
});

ReadingRoomAccess.propTypes = {
resources: PropTypes.object,
mutator: PropTypes.object
};

export default ReadingRoomAccess;
Loading

0 comments on commit 75343f0

Please sign in to comment.