@k-int/stripes-kint-components 1.5.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -1
- package/es/index.js +80 -25
- package/es/lib/ActionList/ActionList.js +92 -33
- package/es/lib/ActionList/ActionListFieldArray.js +202 -104
- package/es/lib/ActionList/index.js +7 -3
- package/es/lib/CustomProperties/Config/CustomPropertiesLookup.js +198 -0
- package/es/lib/CustomProperties/Config/CustomPropertiesSettings.js +321 -0
- package/es/lib/CustomProperties/Config/CustomPropertiesView.js +166 -0
- package/es/lib/CustomProperties/Config/CustomPropertyForm.js +357 -0
- package/es/lib/CustomProperties/Config/index.js +41 -0
- package/es/lib/EditableRefdataList/EditableRefdataList.js +69 -24
- package/es/lib/EditableRefdataList/index.js +7 -3
- package/es/lib/EditableSettingsList/EditableSettingsList.js +90 -0
- package/es/lib/EditableSettingsList/EditableSettingsListFieldArray.js +90 -0
- package/es/lib/EditableSettingsList/EditableSettingsListFieldArray.test.js +181 -0
- package/es/lib/{Settings → EditableSettingsList/SettingField}/EditSettingValue.js +72 -9
- package/es/lib/EditableSettingsList/SettingField/EditSettingValue.test.js +447 -0
- package/es/lib/{Settings → EditableSettingsList/SettingField}/RenderSettingValue.js +45 -7
- package/es/lib/EditableSettingsList/SettingField/RenderSettingValue.test.js +495 -0
- package/es/lib/EditableSettingsList/SettingField/SettingField.js +187 -0
- package/es/lib/EditableSettingsList/SettingField/SettingField.test.js +180 -0
- package/es/lib/EditableSettingsList/SettingField/index.js +35 -0
- package/es/lib/EditableSettingsList/index.js +35 -0
- package/es/lib/FormModal/FormModal.js +126 -0
- package/es/lib/FormModal/index.js +19 -0
- package/es/lib/NoResultsMessage/NoResultsMessage.js +65 -32
- package/es/lib/NoResultsMessage/index.js +7 -3
- package/es/lib/QueryTypedown/QueryTypedown.js +48 -9
- package/es/lib/QueryTypedown/index.js +6 -2
- package/es/lib/RefdataButtons/RefdataButtons.js +143 -0
- package/es/lib/RefdataButtons/index.js +19 -0
- package/es/lib/SASQLookupComponent/SASQLookupComponent.js +194 -140
- package/es/lib/SASQLookupComponent/index.js +6 -2
- package/es/lib/SASQRoute/SASQRoute.js +55 -18
- package/es/lib/SASQRoute/index.js +6 -2
- package/es/lib/SASQViewComponent/SASQViewComponent.js +50 -11
- package/es/lib/SASQViewComponent/index.js +6 -2
- package/es/lib/SearchField/SearchField.js +48 -13
- package/es/lib/SearchField/index.js +6 -2
- package/es/lib/SettingPage/SettingPage.js +99 -0
- package/es/lib/SettingPage/SettingPagePane.js +83 -0
- package/es/lib/SettingPage/index.js +27 -0
- package/es/lib/Typedown/Typedown.js +174 -99
- package/es/lib/Typedown/index.js +6 -2
- package/es/lib/constants/customProperties.js +60 -0
- package/es/lib/constants/eventCodes.js +31 -1
- package/es/lib/contexts/SettingsContext.js +41 -0
- package/es/lib/contexts/index.js +19 -0
- package/es/lib/hooks/index.js +44 -10
- package/es/lib/hooks/settingsHooks/index.js +27 -0
- package/es/lib/hooks/settingsHooks/useSettingSection.js +74 -0
- package/es/lib/hooks/settingsHooks/useSettings.js +175 -0
- package/es/lib/hooks/typedownHooks/index.js +8 -28
- package/es/lib/hooks/typedownHooks/useTypedown.js +129 -12
- package/es/lib/hooks/typedownHooks/useTypedownData.js +35 -2
- package/es/lib/hooks/typedownHooks/useTypedownToggle.js +39 -6
- package/es/lib/hooks/useActiveElement.js +33 -2
- package/es/lib/hooks/useCustomProperties.js +112 -0
- package/es/lib/hooks/useHelperApp.js +44 -11
- package/es/lib/hooks/useKiwtFieldArray.js +37 -4
- package/es/lib/hooks/useKiwtSASQuery.js +43 -9
- package/es/lib/hooks/useLocalStorageState.js +37 -4
- package/es/lib/hooks/useMutateCustomProperties.js +143 -0
- package/es/lib/hooks/useMutateRefdataValue.js +42 -9
- package/es/lib/hooks/useQIndex.js +42 -9
- package/es/lib/hooks/useRefdata.js +43 -16
- package/es/lib/hooks/useTemplates.js +36 -3
- package/es/lib/utils/buildUrl.js +43 -10
- package/es/lib/utils/generateKiwtQuery.js +33 -4
- package/es/lib/utils/generateKiwtQueryParams.js +31 -2
- package/es/lib/utils/index.js +41 -5
- package/es/lib/utils/refdataOptions.js +43 -0
- package/es/lib/utils/renderHelpText.js +109 -0
- package/es/lib/utils/selectorSafe.js +31 -2
- package/es/lib/utils/sortByLabel.js +55 -0
- package/es/lib/utils/toCamelCase.js +48 -0
- package/jest.config.js +15 -1
- package/package.json +19 -10
- package/src/index.js +25 -10
- package/src/lib/ActionList/ActionList.js +32 -22
- package/src/lib/ActionList/ActionListFieldArray.js +56 -10
- package/src/lib/ActionList/README.md +5 -1
- package/src/lib/ActionList/index.js +1 -1
- package/src/lib/CustomProperties/Config/CustomPropertiesLookup.js +111 -0
- package/src/lib/CustomProperties/Config/CustomPropertiesSettings.js +237 -0
- package/src/lib/CustomProperties/Config/CustomPropertiesView.js +150 -0
- package/src/lib/CustomProperties/Config/CustomPropertyForm.js +295 -0
- package/src/lib/CustomProperties/Config/index.js +4 -0
- package/src/lib/EditableRefdataList/EditableRefdataList.js +10 -5
- package/src/lib/EditableRefdataList/index.js +1 -1
- package/src/lib/{Settings → EditableSettingsList}/EditableSettingsList.js +0 -0
- package/src/lib/{Settings → EditableSettingsList}/EditableSettingsListFieldArray.js +2 -2
- package/src/lib/EditableSettingsList/EditableSettingsListFieldArray.test.js +111 -0
- package/src/lib/{Settings → EditableSettingsList/SettingField}/EditSettingValue.js +24 -1
- package/src/lib/EditableSettingsList/SettingField/EditSettingValue.test.js +379 -0
- package/src/lib/{Settings → EditableSettingsList/SettingField}/RenderSettingValue.js +2 -1
- package/src/lib/EditableSettingsList/SettingField/RenderSettingValue.test.js +368 -0
- package/src/lib/{Settings → EditableSettingsList/SettingField}/SettingField.js +7 -7
- package/src/lib/EditableSettingsList/SettingField/SettingField.test.js +80 -0
- package/src/lib/EditableSettingsList/SettingField/index.js +3 -0
- package/src/lib/EditableSettingsList/index.js +3 -0
- package/src/lib/FormModal/FormModal.js +71 -0
- package/src/lib/FormModal/index.js +1 -0
- package/src/lib/NoResultsMessage/NoResultsMessage.js +2 -2
- package/src/lib/NoResultsMessage/index.js +1 -1
- package/src/lib/{Settings → RefdataButtons}/RefdataButtons.js +1 -1
- package/src/lib/RefdataButtons/index.js +1 -0
- package/src/lib/SASQLookupComponent/SASQLookupComponent.js +7 -1
- package/src/lib/{Settings → SettingPage}/SettingPage.js +5 -5
- package/src/lib/{Settings → SettingPage}/SettingPagePane.js +12 -2
- package/src/lib/SettingPage/index.js +2 -0
- package/src/lib/Typedown/Typedown.js +52 -9
- package/src/lib/constants/customProperties.js +9 -0
- package/src/lib/{Settings → contexts}/SettingsContext.js +1 -1
- package/src/lib/contexts/index.js +2 -0
- package/src/lib/hooks/index.js +3 -0
- package/src/lib/hooks/settingsHooks/index.js +2 -0
- package/src/lib/{Settings → hooks/settingsHooks}/useSettingSection.js +0 -0
- package/src/lib/{Settings → hooks/settingsHooks}/useSettings.js +14 -6
- package/src/lib/hooks/typedownHooks/index.js +0 -3
- package/src/lib/hooks/typedownHooks/useTypedown.js +93 -11
- package/src/lib/hooks/useCustomProperties.js +73 -0
- package/src/lib/hooks/useMutateCustomProperties.js +62 -0
- package/src/lib/hooks/useRefdata.js +2 -8
- package/src/lib/utils/index.js +7 -0
- package/src/lib/utils/refdataOptions.js +7 -0
- package/src/lib/{Settings/utils → utils}/renderHelpText.js +1 -1
- package/src/lib/{Settings/utils → utils}/sortByLabel.js +1 -1
- package/src/lib/{Settings/utils → utils}/toCamelCase.js +0 -0
- package/test/helpers/index.js +1 -0
- package/test/helpers/translationsProperties.js +40 -0
- package/test/jest/helpers/KintHarness.js +36 -0
- package/test/jest/helpers/index.js +2 -0
- package/test/jest/helpers/renderWithKintHarness.js +15 -0
- package/test/jest/jest-transformer.js +4 -0
- package/test/jest/setupTests.js +1 -0
- package/translations/stripes-kint-components/en.json +48 -1
- package/yarn-error.log +14118 -0
- package/babelOptions.js +0 -30
- package/es/lib/Settings/EditableSettingsList.js +0 -57
- package/es/lib/Settings/EditableSettingsListFieldArray.js +0 -59
- package/es/lib/Settings/RefdataButtons.js +0 -100
- package/es/lib/Settings/SettingField.js +0 -144
- package/es/lib/Settings/SettingPage.js +0 -64
- package/es/lib/Settings/SettingPagePane.js +0 -43
- package/es/lib/Settings/SettingsContext.js +0 -18
- package/es/lib/Settings/index.js +0 -71
- package/es/lib/Settings/useSettingSection.js +0 -41
- package/es/lib/Settings/useSettings.js +0 -126
- package/es/lib/Settings/utils/index.js +0 -31
- package/es/lib/Settings/utils/renderHelpText.js +0 -57
- package/es/lib/Settings/utils/sortByLabel.js +0 -26
- package/es/lib/Settings/utils/toCamelCase.js +0 -19
- package/es/lib/TypeDown/TypeDown.js +0 -209
- package/es/lib/TypeDown/index.js +0 -15
- package/es/lib/hooks/typedownHooks/useTypedownFooter.js +0 -47
- package/es/lib/hooks/typedownHooks/useTypedownList.js +0 -45
- package/es/lib/hooks/typedownHooks/useTypedownSearchField.js +0 -47
- package/es/lib/utils/getFocusableElements.js +0 -132
- package/src/lib/Settings/index.js +0 -8
- package/src/lib/Settings/utils/index.js +0 -3
- package/src/lib/TypeDown/README.md +0 -1
- package/src/lib/TypeDown/TypeDown.js +0 -226
- package/src/lib/TypeDown/index.js +0 -1
- package/src/lib/hooks/typedownHooks/useTypedownFooter.js +0 -43
- package/src/lib/hooks/typedownHooks/useTypedownList.js +0 -36
- package/src/lib/hooks/typedownHooks/useTypedownSearchField.js +0 -39
- package/src/lib/utils/getFocusableElements.js +0 -99
|
@@ -15,8 +15,11 @@ const propTypes = {
|
|
|
15
15
|
actionAssigner: PropTypes.func,
|
|
16
16
|
actionCalls: PropTypes.object,
|
|
17
17
|
columnMapping: PropTypes.object,
|
|
18
|
+
creatableFields: PropTypes.object,
|
|
18
19
|
editableFields: PropTypes.object,
|
|
19
20
|
fields: PropTypes.object,
|
|
21
|
+
fieldComponents: PropTypes.object,
|
|
22
|
+
formatter: PropTypes.object,
|
|
20
23
|
visibleFields: PropTypes.arrayOf(PropTypes.string)
|
|
21
24
|
};
|
|
22
25
|
|
|
@@ -24,9 +27,12 @@ const ActionListFieldArray = ({
|
|
|
24
27
|
actionAssigner,
|
|
25
28
|
actionCalls,
|
|
26
29
|
columnMapping,
|
|
30
|
+
creatableFields,
|
|
27
31
|
editableFields,
|
|
28
32
|
fields,
|
|
29
|
-
|
|
33
|
+
fieldComponents,
|
|
34
|
+
visibleFields,
|
|
35
|
+
...mclProps // Assume anything left over is to directly apply to the MCL
|
|
30
36
|
}) => {
|
|
31
37
|
// Grab finalForm functions/values from form hooks
|
|
32
38
|
const { change } = useForm();
|
|
@@ -54,7 +60,7 @@ const ActionListFieldArray = ({
|
|
|
54
60
|
};
|
|
55
61
|
|
|
56
62
|
const handleCreate = (index) => {
|
|
57
|
-
const rowData = fields.value[index];
|
|
63
|
+
const { actionListActions: _a, ...rowData } = fields.value[index];
|
|
58
64
|
actionCalls.create(rowData);
|
|
59
65
|
};
|
|
60
66
|
|
|
@@ -105,8 +111,13 @@ const ActionListFieldArray = ({
|
|
|
105
111
|
key={`cancel[${data.rowIndex}]`}
|
|
106
112
|
data-type-button="cancel"
|
|
107
113
|
onClick={() => {
|
|
108
|
-
|
|
109
|
-
|
|
114
|
+
if (!data.id && editing === 'NEW_ROW') {
|
|
115
|
+
fields.remove(data.rowIndex);
|
|
116
|
+
toggleEditing('NEW_ROW');
|
|
117
|
+
} else {
|
|
118
|
+
change(fieldName, get(initialValues, fieldName));
|
|
119
|
+
toggleEditing(data.id);
|
|
120
|
+
}
|
|
110
121
|
}}
|
|
111
122
|
>
|
|
112
123
|
<FormattedMessage id="stripes-kint-components.actionList.cancel" />
|
|
@@ -153,7 +164,7 @@ const ActionListFieldArray = ({
|
|
|
153
164
|
|
|
154
165
|
const formatContent = () => {
|
|
155
166
|
return (
|
|
156
|
-
fields.map(fieldName => {
|
|
167
|
+
fields.map((fieldName, fieldIndex) => {
|
|
157
168
|
// Fetch the content from the field Values
|
|
158
169
|
const cd = get(values, fieldName);
|
|
159
170
|
cd.actionListActions = actionAssigner(cd);
|
|
@@ -170,19 +181,30 @@ const ActionListFieldArray = ({
|
|
|
170
181
|
*/
|
|
171
182
|
for (const key of visibleFields) {
|
|
172
183
|
const editFunction = editableFields[key] ?? (() => true);
|
|
184
|
+
const createFunction = creatableFields[key] ?? (() => true);
|
|
173
185
|
/*
|
|
174
|
-
Next check if this is a new row, if so we should
|
|
175
|
-
If it
|
|
176
|
-
|
|
186
|
+
Next check if this is a new row, if so we should run the createableField function with the data.
|
|
187
|
+
If it is not a new row, then we run the editableField function with the data,
|
|
188
|
+
and it should return true/false
|
|
189
|
+
|
|
190
|
+
For both checks
|
|
191
|
+
true => Field, false => display value
|
|
177
192
|
*/
|
|
178
193
|
if (
|
|
179
|
-
!cd.id ||
|
|
194
|
+
(!cd.id && createFunction(cd)) ||
|
|
180
195
|
(editFunction(cd))
|
|
181
196
|
) {
|
|
182
197
|
returnObj[key] =
|
|
198
|
+
fieldComponents[key] ?
|
|
199
|
+
fieldComponents[key]({
|
|
200
|
+
name: `${fieldName}.${key}`
|
|
201
|
+
}) :
|
|
183
202
|
<Field
|
|
203
|
+
autofocus={fieldIndex === 0}
|
|
184
204
|
component={TextField}
|
|
205
|
+
marginBottom0
|
|
185
206
|
name={`${fieldName}.${key}`}
|
|
207
|
+
parse={v => v}
|
|
186
208
|
/>;
|
|
187
209
|
}
|
|
188
210
|
}
|
|
@@ -192,6 +214,28 @@ const ActionListFieldArray = ({
|
|
|
192
214
|
);
|
|
193
215
|
};
|
|
194
216
|
|
|
217
|
+
const { formatter, ...restOfMclProps } = mclProps; // Destructure formatter part of mclProps
|
|
218
|
+
const fieldAwareFormatter = () => {
|
|
219
|
+
const returnObj = {};
|
|
220
|
+
// For each visible field, if it's being edited then ignore passed formatters, else use them
|
|
221
|
+
visibleFields.forEach(key => {
|
|
222
|
+
returnObj[key] = cd => {
|
|
223
|
+
// Row is being edited if it has no id, or its id is in the editing string
|
|
224
|
+
const editingRow = cd.id === editing || !cd.id;
|
|
225
|
+
// If not editing, use the passed formatter values
|
|
226
|
+
|
|
227
|
+
let returnValue = cd[key];
|
|
228
|
+
|
|
229
|
+
if (!editingRow && formatter[key]) {
|
|
230
|
+
returnValue = formatter[key](cd);
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
return returnValue;
|
|
234
|
+
};
|
|
235
|
+
});
|
|
236
|
+
return returnObj;
|
|
237
|
+
};
|
|
238
|
+
|
|
195
239
|
return (
|
|
196
240
|
<>
|
|
197
241
|
<Button
|
|
@@ -212,10 +256,12 @@ const ActionListFieldArray = ({
|
|
|
212
256
|
columnWidths={getColumnWidths()}
|
|
213
257
|
contentData={formatContent()}
|
|
214
258
|
formatter={{
|
|
215
|
-
actionListActions: renderActionButtons
|
|
259
|
+
actionListActions: renderActionButtons,
|
|
260
|
+
...fieldAwareFormatter()
|
|
216
261
|
}}
|
|
217
262
|
interactive={false}
|
|
218
263
|
visibleColumns={[...visibleFields, 'actionListActions']}
|
|
264
|
+
{...restOfMclProps}
|
|
219
265
|
/>
|
|
220
266
|
</>
|
|
221
267
|
);
|
|
@@ -61,5 +61,9 @@ actionAssigner | function | A function which will be passed the entire row objec
|
|
|
61
61
|
actionCalls | object<function> | An object with keys matching any "actions" the `actionAssigner` may have assigned (In addition to special case `create`, if relevant), and values which are functions. These functions will be handed the row as a parameter. | {} | ✕ |
|
|
62
62
|
columnMapping | object | An object which will act on the rendered MultiColumnList headers to map the labels for each `visibleField` | | ✕ |
|
|
63
63
|
contentData | array | An array of objects to render along with their actions | | ✓ |
|
|
64
|
-
|
|
64
|
+
creatableFields | object<function> | An object with keys from the `visibleFields` array, and values of functions which take the entire row object and return a boolean indicating whether that field is fillable on create or not. | | ✕ |
|
|
65
|
+
editableFields | object<function> | An object with keys from the `visibleFields` array, and values of functions which take the entire row object and return a boolean indicating whether that field is editable or not. No key for a given field will be interpreted as () => true, so a field is editable by default. | | ✕ |
|
|
66
|
+
fieldComponents | object<function> | An object with keys from the `visibleFields` array, and values of functions which take some `fieldProps` (currently only the name of the field `name`), and returns a Field component to be used in "edit mode" for the visible field specified. | | ✕ |
|
|
67
|
+
formatter | object<function> | A "formatter" object that takes the same shape as an MCL formatter, and is used in the same way whilst a row is NOT being edited. While editing a given row, this formatter entry is ignored. | | ✕ |
|
|
65
68
|
visibleFields | array<String> | An array of strings corresponding to those fields to be displayed in the rendered MultiColumnList | | ✓ |
|
|
69
|
+
...mclProps | any | Any other props supplied to ActionList will be applied to the MCL directly. *WARNING* Some MCL props may override important functionality within ActionList | | ✕ |
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { default
|
|
1
|
+
export { default } from './ActionList';
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import { FormattedMessage } from 'react-intl';
|
|
5
|
+
|
|
6
|
+
import debounce from 'lodash/debounce';
|
|
7
|
+
|
|
8
|
+
import { Col, MultiColumnList, Row, Spinner, Select } from '@folio/stripes/components';
|
|
9
|
+
|
|
10
|
+
import SearchField from '../../SearchField';
|
|
11
|
+
import { useCustomProperties } from '../../hooks';
|
|
12
|
+
|
|
13
|
+
const DEBOUNCE_TIME = 500;
|
|
14
|
+
|
|
15
|
+
const CustomPropertiesLookup = ({
|
|
16
|
+
contextFilterOptions, // expects an array of the form [{value: "OpenAccess", label: "Open Access"}, {value: false, label: "None"}]
|
|
17
|
+
customPropertiesEndpoint: endpoint,
|
|
18
|
+
labelOverrides,
|
|
19
|
+
mclProps,
|
|
20
|
+
onSelectCustomProperty,
|
|
21
|
+
queryParams
|
|
22
|
+
}) => {
|
|
23
|
+
const [nsValues, setNsValues] = useState({
|
|
24
|
+
sort: 'id'
|
|
25
|
+
});
|
|
26
|
+
const [selectedContext, setSelectedContext] = useState();
|
|
27
|
+
|
|
28
|
+
const { data: custprops, isLoading } = useCustomProperties({
|
|
29
|
+
endpoint,
|
|
30
|
+
nsValues,
|
|
31
|
+
queryParams,
|
|
32
|
+
returnQueryObject: true,
|
|
33
|
+
ctx: selectedContext
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
const handleSearch = debounce((query) => {
|
|
37
|
+
setNsValues({
|
|
38
|
+
...nsValues,
|
|
39
|
+
query,
|
|
40
|
+
});
|
|
41
|
+
}, DEBOUNCE_TIME);
|
|
42
|
+
|
|
43
|
+
return (
|
|
44
|
+
<>
|
|
45
|
+
<SearchField fullWidth onChange={e => handleSearch(e.target.value)} />
|
|
46
|
+
<Row>
|
|
47
|
+
<Col xs={6}>
|
|
48
|
+
<Select
|
|
49
|
+
dataOptions={contextFilterOptions}
|
|
50
|
+
onChange={(e) => {
|
|
51
|
+
setSelectedContext(e.target.value);
|
|
52
|
+
}}
|
|
53
|
+
value={selectedContext}
|
|
54
|
+
/>
|
|
55
|
+
</Col>
|
|
56
|
+
</Row>
|
|
57
|
+
{isLoading ?
|
|
58
|
+
<Spinner /> :
|
|
59
|
+
<MultiColumnList
|
|
60
|
+
columnMapping={{
|
|
61
|
+
'label': labelOverrides?.label ?? <FormattedMessage id="stripes-kint-components.customProperties.label" />,
|
|
62
|
+
'primary': labelOverrides?.primary ?? <FormattedMessage id="stripes-kint-components.customProperties.primary" />,
|
|
63
|
+
'ctx': labelOverrides?.ctx ?? <FormattedMessage id="stripes-kint-components.customProperties.ctx" />,
|
|
64
|
+
'weight': labelOverrides?.weight ?? <FormattedMessage id="stripes-kint-components.customProperties.weight" />,
|
|
65
|
+
'type': labelOverrides?.type ?? <FormattedMessage id="stripes-kint-components.customProperties.type" />,
|
|
66
|
+
'category': labelOverrides?.category ?? <FormattedMessage id="stripes-kint-components.customProperties.category" />
|
|
67
|
+
}}
|
|
68
|
+
contentData={custprops}
|
|
69
|
+
formatter={{
|
|
70
|
+
primary: data => {
|
|
71
|
+
if (data?.primary) {
|
|
72
|
+
return (
|
|
73
|
+
<FormattedMessage id="stripes-kint-components.yes" />
|
|
74
|
+
);
|
|
75
|
+
} else {
|
|
76
|
+
return (
|
|
77
|
+
<FormattedMessage id="stripes-kint-components.no" />
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
type: data => (
|
|
82
|
+
<FormattedMessage id={`stripes-kint-components.customProperties.type.${data?.type}`} />
|
|
83
|
+
),
|
|
84
|
+
category: data => data?.category?.desc
|
|
85
|
+
}}
|
|
86
|
+
onRowClick={onSelectCustomProperty}
|
|
87
|
+
visibleColumns={['label', 'primary', 'ctx', 'weight', 'type', 'category']}
|
|
88
|
+
{...mclProps}
|
|
89
|
+
/>
|
|
90
|
+
}
|
|
91
|
+
</>
|
|
92
|
+
);
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
CustomPropertiesLookup.propTypes = {
|
|
96
|
+
contextFilterOptions: PropTypes.arrayOf(PropTypes.shape({
|
|
97
|
+
value: PropTypes.string,
|
|
98
|
+
label: PropTypes.oneOfType([
|
|
99
|
+
PropTypes.element,
|
|
100
|
+
PropTypes.string
|
|
101
|
+
])
|
|
102
|
+
})),
|
|
103
|
+
customPropertiesEndpoint: PropTypes.string,
|
|
104
|
+
labelOverrides: PropTypes.object,
|
|
105
|
+
mclProps: PropTypes.object,
|
|
106
|
+
onSelectCustomProperty: PropTypes.func,
|
|
107
|
+
queryParams: PropTypes.object,
|
|
108
|
+
refdataEndpoint: PropTypes.string,
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export default CustomPropertiesLookup;
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import compose from 'compose-function';
|
|
5
|
+
|
|
6
|
+
import { FormattedMessage, useIntl } from 'react-intl';
|
|
7
|
+
|
|
8
|
+
import { useQueryClient } from 'react-query';
|
|
9
|
+
|
|
10
|
+
import SafeHTMLMessage from '@folio/react-intl-safe-html';
|
|
11
|
+
|
|
12
|
+
import { Button, ConfirmationModal, Pane } from '@folio/stripes/components';
|
|
13
|
+
|
|
14
|
+
import FormModal from '../../FormModal/FormModal';
|
|
15
|
+
|
|
16
|
+
import CustomPropertiesLookup from './CustomPropertiesLookup';
|
|
17
|
+
import CustomPropertiesView from './CustomPropertiesView';
|
|
18
|
+
import CustomPropertiesForm from './CustomPropertyForm';
|
|
19
|
+
import { useMutateCustomProperties, useRefdata } from '../../hooks';
|
|
20
|
+
|
|
21
|
+
const EDITING = 'edit';
|
|
22
|
+
const CREATING = 'create';
|
|
23
|
+
const VIEWING = 'view';
|
|
24
|
+
|
|
25
|
+
// A default option for setting up panes manually
|
|
26
|
+
const CustomPropertiesSettings = ({
|
|
27
|
+
afterQueryCalls,
|
|
28
|
+
contextFilterOptions,
|
|
29
|
+
customPropertiesEndpoint,
|
|
30
|
+
helpPopovers,
|
|
31
|
+
labelOverrides,
|
|
32
|
+
refdataEndpoint,
|
|
33
|
+
}) => {
|
|
34
|
+
const queryClient = useQueryClient();
|
|
35
|
+
|
|
36
|
+
const intl = useIntl();
|
|
37
|
+
const [customProperty, setCustomProperty] = useState();
|
|
38
|
+
const [deleteModal, setDeleteModal] = useState(false);
|
|
39
|
+
|
|
40
|
+
const refdata = useRefdata({
|
|
41
|
+
endpoint: refdataEndpoint,
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
const [mode, setMode] = useState(VIEWING);
|
|
45
|
+
|
|
46
|
+
// Default props that need hooks are hard
|
|
47
|
+
let renderContextFilterOptions = contextFilterOptions;
|
|
48
|
+
if (!contextFilterOptions) {
|
|
49
|
+
/*
|
|
50
|
+
Default is {value: '', label: 'All'}, empty string will map to ALL contexts
|
|
51
|
+
If null context is needed, use
|
|
52
|
+
{value: 'isNull', label: ...}
|
|
53
|
+
*/
|
|
54
|
+
renderContextFilterOptions = [
|
|
55
|
+
{
|
|
56
|
+
value: '', // empty string is all custoprop contexts
|
|
57
|
+
label: intl.formatMessage({ id: 'stripes-kint-components.customProperties.all' })
|
|
58
|
+
}
|
|
59
|
+
];
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
let renderViewPaneTitle = labelOverrides?.viewPaneTitle;
|
|
63
|
+
if (renderViewPaneTitle instanceof Function) {
|
|
64
|
+
renderViewPaneTitle = renderViewPaneTitle(customProperty);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Defaulting is hard
|
|
68
|
+
const afterQueryCallsSafe = {
|
|
69
|
+
put: () => null,
|
|
70
|
+
post: () => null,
|
|
71
|
+
delete: () => null,
|
|
72
|
+
...afterQueryCalls
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
const {
|
|
76
|
+
post: createCustprop,
|
|
77
|
+
put: editCustProp,
|
|
78
|
+
delete: deleteCustProp
|
|
79
|
+
} = useMutateCustomProperties({
|
|
80
|
+
afterQueryCalls: {
|
|
81
|
+
put: () => {
|
|
82
|
+
setMode(VIEWING);
|
|
83
|
+
queryClient.invalidateQueries(['stripes-kint-components', 'useCustomProperties', 'custprops']);
|
|
84
|
+
afterQueryCallsSafe.put();
|
|
85
|
+
},
|
|
86
|
+
post: () => {
|
|
87
|
+
setMode(VIEWING);
|
|
88
|
+
queryClient.invalidateQueries(['stripes-kint-components', 'useCustomProperties', 'custprops']);
|
|
89
|
+
afterQueryCallsSafe.post();
|
|
90
|
+
},
|
|
91
|
+
delete: () => {
|
|
92
|
+
setMode(VIEWING);
|
|
93
|
+
queryClient.invalidateQueries(['stripes-kint-components', 'useCustomProperties', 'custprops']);
|
|
94
|
+
afterQueryCallsSafe.delete();
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
endpoint: customPropertiesEndpoint,
|
|
98
|
+
id: customProperty?.id
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
const handeContextSubmit = (submitData) => {
|
|
102
|
+
return {
|
|
103
|
+
...submitData,
|
|
104
|
+
ctx: submitData?.ctx?.[0]?.value
|
|
105
|
+
};
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
return (
|
|
109
|
+
<>
|
|
110
|
+
<Pane
|
|
111
|
+
defaultWidth="fill"
|
|
112
|
+
id="settings-customProperties.lookupPane"
|
|
113
|
+
lastMenu={
|
|
114
|
+
<Button
|
|
115
|
+
marginBottom0
|
|
116
|
+
onClick={() => setMode(CREATING)} // TODO do we need to clear form here too?
|
|
117
|
+
>
|
|
118
|
+
<FormattedMessage id="stripes-kint-components.create" />
|
|
119
|
+
</Button>
|
|
120
|
+
}
|
|
121
|
+
paneTitle={labelOverrides.paneTitle ??
|
|
122
|
+
<FormattedMessage id="stripes-kint-components.customProperties" /> // This should be configurable?
|
|
123
|
+
}
|
|
124
|
+
>
|
|
125
|
+
<CustomPropertiesLookup
|
|
126
|
+
contextFilterOptions={renderContextFilterOptions}
|
|
127
|
+
customPropertiesEndpoint={customPropertiesEndpoint}
|
|
128
|
+
labelOverrides={labelOverrides}
|
|
129
|
+
onSelectCustomProperty={(_e, cp) => setCustomProperty(cp)}
|
|
130
|
+
/>
|
|
131
|
+
</Pane>
|
|
132
|
+
{customProperty &&
|
|
133
|
+
<Pane
|
|
134
|
+
actionMenu={({ onToggle }) => (
|
|
135
|
+
[
|
|
136
|
+
<Button
|
|
137
|
+
buttonStyle="dropdownItem"
|
|
138
|
+
marginBottom0
|
|
139
|
+
onClick={() => setMode(EDITING)}
|
|
140
|
+
>
|
|
141
|
+
<FormattedMessage id="stripes-kint-components.edit" />
|
|
142
|
+
</Button>,
|
|
143
|
+
<Button
|
|
144
|
+
buttonStyle="dropdownItem"
|
|
145
|
+
marginBottom0
|
|
146
|
+
onClick={() => {
|
|
147
|
+
setDeleteModal(true);
|
|
148
|
+
onToggle();
|
|
149
|
+
}}
|
|
150
|
+
>
|
|
151
|
+
<FormattedMessage id="stripes-kint-components.delete" />
|
|
152
|
+
</Button>
|
|
153
|
+
]
|
|
154
|
+
)}
|
|
155
|
+
defaultWidth="fill"
|
|
156
|
+
dismissible
|
|
157
|
+
id="settings-customProperties-viewPane"
|
|
158
|
+
onClose={() => setCustomProperty()}
|
|
159
|
+
paneTitle={
|
|
160
|
+
renderViewPaneTitle ?? customProperty?.label ?? customProperty?.name
|
|
161
|
+
}
|
|
162
|
+
>
|
|
163
|
+
<CustomPropertiesView
|
|
164
|
+
customProperty={customProperty}
|
|
165
|
+
labelOverrides={labelOverrides}
|
|
166
|
+
/>
|
|
167
|
+
</Pane>
|
|
168
|
+
}
|
|
169
|
+
<FormModal
|
|
170
|
+
initialValues={mode === CREATING ?
|
|
171
|
+
{
|
|
172
|
+
weight: 0,
|
|
173
|
+
primary: true,
|
|
174
|
+
defaultInternal: true
|
|
175
|
+
} :
|
|
176
|
+
customProperty
|
|
177
|
+
}
|
|
178
|
+
modalProps={{
|
|
179
|
+
dismissible: true,
|
|
180
|
+
onClose: () => setMode(VIEWING),
|
|
181
|
+
open: (mode === CREATING || mode === EDITING)
|
|
182
|
+
}}
|
|
183
|
+
onSubmit={mode === CREATING ?
|
|
184
|
+
compose(createCustprop, handeContextSubmit) :
|
|
185
|
+
compose(editCustProp, handeContextSubmit)
|
|
186
|
+
}
|
|
187
|
+
>
|
|
188
|
+
<CustomPropertiesForm
|
|
189
|
+
contextFilterOptions={renderContextFilterOptions}
|
|
190
|
+
helpPopovers={helpPopovers}
|
|
191
|
+
labelOverrides={labelOverrides}
|
|
192
|
+
refdata={refdata.map(rdc => ({ label: rdc.desc, value: rdc.id }))}
|
|
193
|
+
/>
|
|
194
|
+
</FormModal>
|
|
195
|
+
<ConfirmationModal
|
|
196
|
+
buttonStyle="danger"
|
|
197
|
+
confirmLabel={
|
|
198
|
+
labelOverrides?.confirmLabel ??
|
|
199
|
+
<FormattedMessage id="stripes-kint-components.customProperties.delete.confirmLabel" />
|
|
200
|
+
}
|
|
201
|
+
heading={
|
|
202
|
+
labelOverrides?.confirmHeading ??
|
|
203
|
+
<FormattedMessage id="stripes-kint-components.customProperties.delete.confirmHeading" />
|
|
204
|
+
}
|
|
205
|
+
id="delete-job-confirmation"
|
|
206
|
+
message={
|
|
207
|
+
labelOverrides?.confirmMessage ??
|
|
208
|
+
<SafeHTMLMessage id="stripes-kint-components.customProperties.delete.confirmMessage" values={{ name: customProperty?.name }} />
|
|
209
|
+
}
|
|
210
|
+
onCancel={() => setDeleteModal(false)}
|
|
211
|
+
onConfirm={() => {
|
|
212
|
+
deleteCustProp();
|
|
213
|
+
setCustomProperty();
|
|
214
|
+
setDeleteModal(false);
|
|
215
|
+
}}
|
|
216
|
+
open={deleteModal}
|
|
217
|
+
/>
|
|
218
|
+
</>
|
|
219
|
+
);
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
CustomPropertiesSettings.propTypes = {
|
|
223
|
+
afterQueryCalls: PropTypes.object,
|
|
224
|
+
contextFilterOptions: PropTypes.arrayOf(PropTypes.shape({
|
|
225
|
+
value: PropTypes.string,
|
|
226
|
+
label: PropTypes.oneOfType([
|
|
227
|
+
PropTypes.element,
|
|
228
|
+
PropTypes.string
|
|
229
|
+
])
|
|
230
|
+
})),
|
|
231
|
+
customPropertiesEndpoint: PropTypes.string,
|
|
232
|
+
helpPopovers: PropTypes.object,
|
|
233
|
+
labelOverrides: PropTypes.object,
|
|
234
|
+
refdataEndpoint: PropTypes.string,
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
export default CustomPropertiesSettings;
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
import PropTypes from 'prop-types';
|
|
2
|
+
import { FormattedMessage } from 'react-intl';
|
|
3
|
+
import { Col, KeyValue, NoValue, Row } from '@folio/stripes/components';
|
|
4
|
+
|
|
5
|
+
import { REFDATA_CLASS_NAME } from '../../constants/customProperties';
|
|
6
|
+
|
|
7
|
+
// A default option for CustProp view pane, with the ability to override labels for fields
|
|
8
|
+
const CustomPropertiesView = ({
|
|
9
|
+
customProperty,
|
|
10
|
+
labelOverrides
|
|
11
|
+
}) => {
|
|
12
|
+
return (
|
|
13
|
+
<>
|
|
14
|
+
<Row>
|
|
15
|
+
<Col xs={6}>
|
|
16
|
+
<KeyValue
|
|
17
|
+
label={
|
|
18
|
+
labelOverrides?.label ??
|
|
19
|
+
<FormattedMessage id="stripes-kint-components.customProperties.label" />
|
|
20
|
+
}
|
|
21
|
+
value={customProperty?.label}
|
|
22
|
+
/>
|
|
23
|
+
</Col>
|
|
24
|
+
<Col xs={6}>
|
|
25
|
+
<KeyValue
|
|
26
|
+
label={
|
|
27
|
+
labelOverrides?.name ??
|
|
28
|
+
<FormattedMessage id="stripes-kint-components.customProperties.name" />
|
|
29
|
+
}
|
|
30
|
+
value={customProperty?.name}
|
|
31
|
+
/>
|
|
32
|
+
</Col>
|
|
33
|
+
</Row>
|
|
34
|
+
<Row>
|
|
35
|
+
<Col xs={12}>
|
|
36
|
+
<KeyValue
|
|
37
|
+
label={
|
|
38
|
+
labelOverrides?.description ??
|
|
39
|
+
<FormattedMessage id="stripes-kint-components.customProperties.description" />
|
|
40
|
+
}
|
|
41
|
+
value={customProperty?.description}
|
|
42
|
+
/>
|
|
43
|
+
</Col>
|
|
44
|
+
</Row>
|
|
45
|
+
<Row>
|
|
46
|
+
<Col xs={6}>
|
|
47
|
+
<KeyValue
|
|
48
|
+
label={
|
|
49
|
+
labelOverrides?.weight ??
|
|
50
|
+
<FormattedMessage id="stripes-kint-components.customProperties.weight" />
|
|
51
|
+
}
|
|
52
|
+
value={customProperty?.weight}
|
|
53
|
+
/>
|
|
54
|
+
</Col>
|
|
55
|
+
<Col xs={6}>
|
|
56
|
+
<KeyValue
|
|
57
|
+
label={
|
|
58
|
+
labelOverrides?.primary ??
|
|
59
|
+
<FormattedMessage
|
|
60
|
+
id="stripes-kint-components.customProperties.primary"
|
|
61
|
+
/>
|
|
62
|
+
}
|
|
63
|
+
value={
|
|
64
|
+
<FormattedMessage
|
|
65
|
+
id={
|
|
66
|
+
customProperty?.primary
|
|
67
|
+
? 'stripes-kint-components.yes'
|
|
68
|
+
: 'stripes-kint-components.no'
|
|
69
|
+
}
|
|
70
|
+
/>
|
|
71
|
+
}
|
|
72
|
+
/>
|
|
73
|
+
</Col>
|
|
74
|
+
</Row>
|
|
75
|
+
<Row>
|
|
76
|
+
<Col xs={6}>
|
|
77
|
+
<KeyValue
|
|
78
|
+
label={
|
|
79
|
+
labelOverrides?.defaultVisibility ??
|
|
80
|
+
<FormattedMessage id="stripes-kint-components.customProperties.defaultVisibility" />
|
|
81
|
+
}
|
|
82
|
+
value={
|
|
83
|
+
<FormattedMessage
|
|
84
|
+
id={
|
|
85
|
+
customProperty?.defaultInternal
|
|
86
|
+
? 'stripes-kint-components.customProperties.internalTrue'
|
|
87
|
+
: 'stripes-kint-components.customProperties.internalFalse'
|
|
88
|
+
}
|
|
89
|
+
/>
|
|
90
|
+
}
|
|
91
|
+
/>
|
|
92
|
+
</Col>
|
|
93
|
+
<Col xs={6}>
|
|
94
|
+
<KeyValue
|
|
95
|
+
label={
|
|
96
|
+
labelOverrides?.ctx ??
|
|
97
|
+
<FormattedMessage id="stripes-kint-components.customProperties.ctx" />
|
|
98
|
+
}
|
|
99
|
+
value={customProperty?.ctx ?? <NoValue />}
|
|
100
|
+
/>
|
|
101
|
+
</Col>
|
|
102
|
+
</Row>
|
|
103
|
+
<Row>
|
|
104
|
+
<Col xs={6}>
|
|
105
|
+
{customProperty?.type && (
|
|
106
|
+
<KeyValue
|
|
107
|
+
label={
|
|
108
|
+
labelOverrides?.type ??
|
|
109
|
+
<FormattedMessage id="stripes-kint-components.customProperties.type" />
|
|
110
|
+
}
|
|
111
|
+
value={<FormattedMessage id={`stripes-kint-components.customProperties.type.${customProperty?.type}`} />}
|
|
112
|
+
/>
|
|
113
|
+
)}
|
|
114
|
+
</Col>
|
|
115
|
+
<Col xs={6}>
|
|
116
|
+
{customProperty?.type === REFDATA_CLASS_NAME && (
|
|
117
|
+
<KeyValue
|
|
118
|
+
label={
|
|
119
|
+
labelOverrides?.category ??
|
|
120
|
+
<FormattedMessage id="stripes-kint-components.customProperties.category" />
|
|
121
|
+
}
|
|
122
|
+
value={customProperty?.category?.desc ?? <NoValue />}
|
|
123
|
+
/>
|
|
124
|
+
)}
|
|
125
|
+
</Col>
|
|
126
|
+
</Row>
|
|
127
|
+
</>
|
|
128
|
+
);
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
CustomPropertiesView.propTypes = {
|
|
132
|
+
customProperty: PropTypes.shape({
|
|
133
|
+
id: PropTypes.string,
|
|
134
|
+
label: PropTypes.string,
|
|
135
|
+
name: PropTypes.string,
|
|
136
|
+
description: PropTypes.string,
|
|
137
|
+
weight: PropTypes.number,
|
|
138
|
+
primary: PropTypes.bool,
|
|
139
|
+
defaultInternal: PropTypes.bool,
|
|
140
|
+
ctx: PropTypes.string,
|
|
141
|
+
type: PropTypes.string,
|
|
142
|
+
category: PropTypes.shape({
|
|
143
|
+
desc: PropTypes.string
|
|
144
|
+
})
|
|
145
|
+
|
|
146
|
+
}),
|
|
147
|
+
labelOverrides: PropTypes.object
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
export default CustomPropertiesView;
|