Skip to content

Commit e0417c0

Browse files
authored
UIQM-789 Add new initialValues prop to quickMARC to initialize it with some pre-existing values. (#822)
* UIQM-789 Add new `initialValues` prop to quickMARC to initialize it with some pre-existing values. * UIQM-789 update readme, only apply initial values on non-route mode * UIQM-789 added tests for initialValues * UIQM-789 fix sonar issue * UIQM-789 remove comments for already turned off eslint rules
1 parent 840caa9 commit e0417c0

File tree

7 files changed

+120
-5
lines changed

7 files changed

+120
-5
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
* [UIQM-785](https://issues.folio.org/browse/UIQM-785) Default to Name-title browse if the MARC bib field contains a subfield "t".
1111
* [UIQM-783](https://issues.folio.org/browse/UIQM-783) Update label for 38 position of MARC authority "008" field to "Mod Rec".
1212
* [UIQM-788](https://issues.folio.org/browse/UIQM-788) Add new props to quickMARC to make it usable without having to define routes.
13+
* [UIQM-789](https://issues.folio.org/browse/UIQM-789) Add new `initialValues` prop to quickMARC to initialize it with some pre-existing values.
1314

1415
## [10.0.4](https://github.com/folio-org/ui-quick-marc/tree/v10.0.4) (2025-07-14)
1516

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ of the Module Developer's Guide.
3232
| `onSave` | function | Called after saving and closing a record. Called with `externalId` when `marcType` is "bibliographic" or "authority". For `marcType` "holdings" it's called with `instanceId/externalId` | Yes |
3333
| `onCreateAndKeepEditing` | function | Called after creating/deriving a record via "Save and keep editing" button. Called with `externalId` when `marcType` is "bibliographic" or "authority". For `marcType` "holdings" it's called with `instanceId/externalId` | Yes for route-less, No for pre-defined routes |
3434
| `useRoutes` | bool | When `true` - quickMARC will define it's own routes that the consuming application will have to redirect to. When `false` - quickMARC will act like a regular plug-in and simply render a view, and the consuming application will have to define it's own routes and provide some props to quickMARC. | No |
35+
| `initialValues` | object | Values to initialize quickMARC with. Shape should match the response from `records-editor/records` endpoint. Will only be applied when `useRoutes` is `false`. | No |
36+
3537

3638
This is a [Stripes](https://github.com/folio-org/stripes-core/) UI module to edit MARC records.
3739

src/QuickMarc.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ const QuickMarc = ({
2828
isShared,
2929
onClose,
3030
onSave,
31+
initialValues,
3132
onCreateAndKeepEditing = noop,
3233
useRoutes = true,
3334
}) => {
@@ -130,6 +131,7 @@ const QuickMarc = ({
130131
onCheckCentralTenantPerm={checkCentralTenantPermission}
131132
externalId={externalId}
132133
instanceId={instanceId}
134+
initialValues={initialValues}
133135
/>
134136
</QuickMarcProvider>
135137
)}
@@ -149,6 +151,28 @@ QuickMarc.propTypes = {
149151
externalId: PropTypes.string,
150152
isShared: PropTypes.bool,
151153
useRoutes: PropTypes.bool,
154+
initialValues: PropTypes.shape({
155+
leader: PropTypes.string.isRequired,
156+
fields: PropTypes.arrayOf(PropTypes.shape({
157+
tag: PropTypes.string.isRequired,
158+
indicators: PropTypes.arrayOf(PropTypes.string),
159+
content: PropTypes.oneOfType([PropTypes.string, PropTypes.object]).isRequired,
160+
isProtected: PropTypes.bool.isRequired,
161+
})).isRequired,
162+
marcFormat: PropTypes.string.isRequired,
163+
sourceVersion: PropTypes.number.isRequired,
164+
externalId: PropTypes.string.isRequired,
165+
updateInfo: PropTypes.shape({
166+
recordState: PropTypes.string.isRequired,
167+
updatedDate: PropTypes.string.isRequired,
168+
updatedBy: PropTypes.shape({
169+
userId: PropTypes.string.isRequired,
170+
username: PropTypes.string,
171+
lastName: PropTypes.string,
172+
firstName: PropTypes.string,
173+
}).isRequired,
174+
}).isRequired,
175+
}),
152176
};
153177

154178
export default QuickMarc;

src/QuickMarcEditor/QuickMarcEditorContainer.js

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import React, {
55
useMemo,
66
useContext,
77
} from 'react';
8-
import PropTypes from 'prop-types';
8+
import PropTypes, { object } from 'prop-types';
99
import { withRouter } from 'react-router';
1010
import ReactRouterPropTypes from 'react-router-prop-types';
1111
import noop from 'lodash/noop';
@@ -57,6 +57,14 @@ const propTypes = {
5757
externalId: PropTypes.string.isRequired,
5858
instanceId: PropTypes.string.isRequired,
5959
onCheckCentralTenantPerm: PropTypes.func,
60+
initialValues: PropTypes.shape({
61+
leader: PropTypes.string.isRequired,
62+
fields: PropTypes.arrayOf(object).isRequired,
63+
marcFormat: PropTypes.string.isRequired,
64+
sourceVersion: PropTypes.number.isRequired,
65+
externalId: PropTypes.string.isRequired,
66+
updateInfo: PropTypes.object.isRequired,
67+
}),
6068
};
6169

6270
const createRecordDefaults = {
@@ -77,6 +85,7 @@ const QuickMarcEditorContainer = ({
7785
instanceId: instanceIdProp,
7886
onCheckCentralTenantPerm = noop,
7987
match,
88+
initialValues: initialValuesProp,
8089
}) => {
8190
const {
8291
action,
@@ -87,6 +96,7 @@ const QuickMarcEditorContainer = ({
8796
setMarcRecord,
8897
setRelatedRecordVersion,
8998
getIsShared,
99+
isUsingRouter,
90100
} = useContext(QuickMarcContext);
91101
const [locations, setLocations] = useState();
92102
const [isLoading, setIsLoading] = useState(true);
@@ -207,11 +217,33 @@ const QuickMarcEditorContainer = ({
207217
]) => {
208218
let dehydratedMarcRecord;
209219

220+
const isShouldUseInitialValuesProp = initialValuesProp && !isUsingRouter;
221+
210222
if (_action === QUICK_MARC_ACTIONS.CREATE) {
211-
dehydratedMarcRecord = createRecordDefaults[marcType](instanceResponse, fixedFieldSpecResponse);
223+
if (isShouldUseInitialValuesProp) {
224+
dehydratedMarcRecord = dehydrateMarcRecordResponse(
225+
initialValuesProp,
226+
marcType,
227+
fixedFieldSpecResponse,
228+
);
229+
} else {
230+
dehydratedMarcRecord = createRecordDefaults[marcType](instanceResponse, fixedFieldSpecResponse);
231+
}
212232
} else {
233+
const isLoadingDataAfterKeepEditing = Boolean(fieldIds);
234+
235+
// if we just saved a record - then we need to ignore `initialValuesProp` to not initialize with old data
236+
// otherwise if we're just entering Edit mode - initialize with initial values or values from response
237+
let dataToInitializeWith = null;
238+
239+
if (isLoadingDataAfterKeepEditing || !isShouldUseInitialValuesProp) {
240+
dataToInitializeWith = marcRecordResponse;
241+
} else {
242+
dataToInitializeWith = initialValuesProp;
243+
}
244+
213245
dehydratedMarcRecord = dehydrateMarcRecordResponse(
214-
marcRecordResponse,
246+
dataToInitializeWith,
215247
marcType,
216248
fixedFieldSpecResponse,
217249
fieldIds,

src/QuickMarcEditor/QuickMarcEditorContainer.test.js

Lines changed: 55 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import {
55
fireEvent,
66
screen,
77
within,
8+
waitFor,
89
} from '@folio/jest-config-stripes/testing-library/react';
910
import faker from 'faker';
1011

@@ -71,7 +72,10 @@ const record = {
7172
id: faker.random.uuid(),
7273
leader: bibLeaderString,
7374
marcFormat: MARC_TYPES.BIB.toUpperCase(),
74-
fields: [],
75+
fields: [{
76+
tag: '245',
77+
content: '$a value from API',
78+
}],
7579
};
7680

7781
const locations = [];
@@ -86,11 +90,13 @@ const mockOnSave = jest.fn();
8690
const renderQuickMarcEditorContainer = ({
8791
action = QUICK_MARC_ACTIONS.EDIT,
8892
marcType = MARC_TYPES.BIB,
93+
isUsingRouter,
8994
...props
9095
} = {}) => (render(
9196
<Harness
9297
action={action}
9398
marcType={marcType}
99+
isUsingRouter={isUsingRouter}
94100
>
95101
<QuickMarcEditorContainer
96102
externalRecordPath={externalRecordPath}
@@ -597,4 +603,52 @@ describe('Given Quick Marc Editor Container', () => {
597603
});
598604
});
599605
});
606+
607+
describe('when using initialValues prop', () => {
608+
describe('when using routes', () => {
609+
beforeEach(() => {
610+
renderQuickMarcEditorContainer({
611+
mutator,
612+
action: QUICK_MARC_ACTIONS.EDIT,
613+
marcType: MARC_TYPES.BIB,
614+
isUsingRouter: true,
615+
initialValues: {
616+
marcFormat: 'BIBLIOGRAPHIC',
617+
leader: '03109cas\\a2200841\\a\\4500',
618+
fields: [{
619+
tag: '245',
620+
content: '$a value from initial values',
621+
}],
622+
},
623+
});
624+
});
625+
626+
it('should use fetched data to initialize the form', async () => {
627+
await waitFor(() => expect(screen.getByRole('textbox', { name: 'ui-quick-marc.record.subfield' })).toHaveValue('$a value from API'));
628+
});
629+
});
630+
631+
describe('when action is CREATE', () => {
632+
beforeEach(() => {
633+
renderQuickMarcEditorContainer({
634+
mutator,
635+
action: QUICK_MARC_ACTIONS.CREATE,
636+
marcType: MARC_TYPES.BIB,
637+
isUsingRouter: false,
638+
initialValues: {
639+
marcFormat: 'BIBLIOGRAPHIC',
640+
leader: '03109cas\\a2200841\\a\\4500',
641+
fields: [{
642+
tag: '245',
643+
content: '$a value from initial values',
644+
}],
645+
},
646+
});
647+
});
648+
649+
it('should use initialValues', async () => {
650+
await waitFor(() => expect(screen.getByRole('textbox', { name: 'ui-quick-marc.record.subfield' })).toHaveValue('$a value from initial values'));
651+
});
652+
});
653+
});
600654
});

src/QuickMarcEditor/utils.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1179,7 +1179,7 @@ const addLeaderFieldAndIdToRecords = (marcRecordResponse, fieldIds) => {
11791179
};
11801180
};
11811181

1182-
export const dehydrateMarcRecordResponse = (marcRecordResponse, marcType, fixedFieldSpec, fieldIds) => (
1182+
export const dehydrateMarcRecordResponse = (marcRecordResponse, marcType, fixedFieldSpec, fieldIds = []) => (
11831183
flow(
11841184
marcRecord => addLeaderFieldAndIdToRecords(marcRecord, fieldIds),
11851185
marcRecord => autopopulateFixedField(marcRecord, marcType, fixedFieldSpec),

test/jest/helpers/harness.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ const Harness = ({
4848
action,
4949
marcType,
5050
basePath,
51+
isUsingRouter,
5152
}) => {
5253
const QuickMarcProviderComponent = quickMarcContext
5354
? QuickMarcProviderMock
@@ -63,6 +64,7 @@ const Harness = ({
6364
marcType={marcType}
6465
basePath={basePath}
6566
ctxValue={quickMarcContext}
67+
isUsingRouter={isUsingRouter}
6668
>
6769
{children}
6870
</QuickMarcProviderComponent>

0 commit comments

Comments
 (0)