@k-int/stripes-kint-components 1.7.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.
Files changed (136) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/es/index.js +43 -8
  3. package/es/lib/ActionList/ActionList.js +48 -28
  4. package/es/lib/ActionList/ActionListFieldArray.js +52 -16
  5. package/es/lib/CustomProperties/Config/CustomPropertiesLookup.js +198 -0
  6. package/es/lib/CustomProperties/Config/CustomPropertiesSettings.js +321 -0
  7. package/es/lib/CustomProperties/Config/CustomPropertiesView.js +166 -0
  8. package/es/lib/CustomProperties/Config/CustomPropertyForm.js +357 -0
  9. package/es/lib/CustomProperties/Config/index.js +41 -0
  10. package/es/lib/FormModal/FormModal.js +126 -0
  11. package/es/lib/{TypeDown → FormModal}/index.js +2 -2
  12. package/es/lib/NoResultsMessage/NoResultsMessage.js +1 -1
  13. package/es/lib/Typedown/Typedown.js +44 -13
  14. package/es/lib/constants/customProperties.js +60 -0
  15. package/es/lib/hooks/index.js +16 -0
  16. package/es/lib/hooks/useCustomProperties.js +112 -0
  17. package/es/lib/hooks/useMutateCustomProperties.js +143 -0
  18. package/package.json +4 -2
  19. package/src/index.js +11 -4
  20. package/src/lib/ActionList/ActionList.js +30 -23
  21. package/src/lib/ActionList/ActionListFieldArray.js +36 -2
  22. package/src/lib/ActionList/README.md +4 -1
  23. package/src/lib/CustomProperties/Config/CustomPropertiesLookup.js +111 -0
  24. package/src/lib/CustomProperties/Config/CustomPropertiesSettings.js +237 -0
  25. package/src/lib/CustomProperties/Config/CustomPropertiesView.js +150 -0
  26. package/src/lib/CustomProperties/Config/CustomPropertyForm.js +295 -0
  27. package/src/lib/CustomProperties/Config/index.js +4 -0
  28. package/src/lib/FormModal/FormModal.js +71 -0
  29. package/src/lib/FormModal/index.js +1 -0
  30. package/src/lib/NoResultsMessage/NoResultsMessage.js +2 -2
  31. package/src/lib/Typedown/Typedown.js +50 -8
  32. package/src/lib/constants/customProperties.js +9 -0
  33. package/src/lib/hooks/index.js +2 -0
  34. package/src/lib/hooks/useCustomProperties.js +73 -0
  35. package/src/lib/hooks/useMutateCustomProperties.js +62 -0
  36. package/translations/stripes-kint-components/en.json +47 -1
  37. package/yarn-error.log +14118 -0
  38. package/es/artifacts/coverage-jest/lcov-report/block-navigation.js +0 -109
  39. package/es/artifacts/coverage-jest/lcov-report/prettify.js +0 -998
  40. package/es/artifacts/coverage-jest/lcov-report/sorter.js +0 -238
  41. package/es/lib/TypeDown/TypeDown.js +0 -251
  42. package/junit.xml +0 -79
  43. package/src/artifacts/coverage-jest/lcov-report/ActionList/ActionList.js.html +0 -256
  44. package/src/artifacts/coverage-jest/lcov-report/ActionList/ActionListFieldArray.js.html +0 -799
  45. package/src/artifacts/coverage-jest/lcov-report/ActionList/index.html +0 -146
  46. package/src/artifacts/coverage-jest/lcov-report/ActionList/index.js.html +0 -88
  47. package/src/artifacts/coverage-jest/lcov-report/EditableRefdataList/EditableRefdataList.js.html +0 -376
  48. package/src/artifacts/coverage-jest/lcov-report/EditableRefdataList/index.html +0 -131
  49. package/src/artifacts/coverage-jest/lcov-report/EditableRefdataList/index.js.html +0 -88
  50. package/src/artifacts/coverage-jest/lcov-report/EditableSettingsList/EditableSettingsList.js.html +0 -223
  51. package/src/artifacts/coverage-jest/lcov-report/EditableSettingsList/EditableSettingsListFieldArray.js.html +0 -211
  52. package/src/artifacts/coverage-jest/lcov-report/EditableSettingsList/SettingField/EditSettingValue.js.html +0 -376
  53. package/src/artifacts/coverage-jest/lcov-report/EditableSettingsList/SettingField/RenderSettingValue.js.html +0 -262
  54. package/src/artifacts/coverage-jest/lcov-report/EditableSettingsList/SettingField/SettingField.js.html +0 -436
  55. package/src/artifacts/coverage-jest/lcov-report/EditableSettingsList/SettingField/index.html +0 -161
  56. package/src/artifacts/coverage-jest/lcov-report/EditableSettingsList/SettingField/index.js.html +0 -94
  57. package/src/artifacts/coverage-jest/lcov-report/EditableSettingsList/index.html +0 -146
  58. package/src/artifacts/coverage-jest/lcov-report/EditableSettingsList/index.js.html +0 -94
  59. package/src/artifacts/coverage-jest/lcov-report/NoResultsMessage/NoResultsMessage.js.html +0 -319
  60. package/src/artifacts/coverage-jest/lcov-report/NoResultsMessage/index.html +0 -131
  61. package/src/artifacts/coverage-jest/lcov-report/NoResultsMessage/index.js.html +0 -88
  62. package/src/artifacts/coverage-jest/lcov-report/QueryTypedown/QueryTypedown.js.html +0 -184
  63. package/src/artifacts/coverage-jest/lcov-report/QueryTypedown/index.html +0 -131
  64. package/src/artifacts/coverage-jest/lcov-report/QueryTypedown/index.js.html +0 -88
  65. package/src/artifacts/coverage-jest/lcov-report/RefdataButtons/RefdataButtons.js.html +0 -370
  66. package/src/artifacts/coverage-jest/lcov-report/RefdataButtons/index.html +0 -131
  67. package/src/artifacts/coverage-jest/lcov-report/RefdataButtons/index.js.html +0 -88
  68. package/src/artifacts/coverage-jest/lcov-report/SASQLookupComponent/SASQLookupComponent.js.html +0 -949
  69. package/src/artifacts/coverage-jest/lcov-report/SASQLookupComponent/index.html +0 -131
  70. package/src/artifacts/coverage-jest/lcov-report/SASQLookupComponent/index.js.html +0 -88
  71. package/src/artifacts/coverage-jest/lcov-report/SASQRoute/SASQRoute.js.html +0 -274
  72. package/src/artifacts/coverage-jest/lcov-report/SASQRoute/index.html +0 -131
  73. package/src/artifacts/coverage-jest/lcov-report/SASQRoute/index.js.html +0 -88
  74. package/src/artifacts/coverage-jest/lcov-report/SASQViewComponent/SASQViewComponent.js.html +0 -250
  75. package/src/artifacts/coverage-jest/lcov-report/SASQViewComponent/index.html +0 -131
  76. package/src/artifacts/coverage-jest/lcov-report/SASQViewComponent/index.js.html +0 -88
  77. package/src/artifacts/coverage-jest/lcov-report/SearchField/SearchField.js.html +0 -214
  78. package/src/artifacts/coverage-jest/lcov-report/SearchField/index.html +0 -131
  79. package/src/artifacts/coverage-jest/lcov-report/SearchField/index.js.html +0 -88
  80. package/src/artifacts/coverage-jest/lcov-report/SettingPage/SettingPage.js.html +0 -211
  81. package/src/artifacts/coverage-jest/lcov-report/SettingPage/SettingPagePane.js.html +0 -178
  82. package/src/artifacts/coverage-jest/lcov-report/SettingPage/index.html +0 -146
  83. package/src/artifacts/coverage-jest/lcov-report/SettingPage/index.js.html +0 -91
  84. package/src/artifacts/coverage-jest/lcov-report/TypeDown/TypeDown.js.html +0 -769
  85. package/src/artifacts/coverage-jest/lcov-report/TypeDown/index.html +0 -131
  86. package/src/artifacts/coverage-jest/lcov-report/TypeDown/index.js.html +0 -88
  87. package/src/artifacts/coverage-jest/lcov-report/Typedown/Typedown.js.html +0 -790
  88. package/src/artifacts/coverage-jest/lcov-report/Typedown/index.html +0 -131
  89. package/src/artifacts/coverage-jest/lcov-report/Typedown/index.js.html +0 -88
  90. package/src/artifacts/coverage-jest/lcov-report/base.css +0 -224
  91. package/src/artifacts/coverage-jest/lcov-report/block-navigation.js +0 -87
  92. package/src/artifacts/coverage-jest/lcov-report/constants/eventCodes.js.html +0 -94
  93. package/src/artifacts/coverage-jest/lcov-report/constants/index.html +0 -116
  94. package/src/artifacts/coverage-jest/lcov-report/contexts/SettingsContext.js.html +0 -97
  95. package/src/artifacts/coverage-jest/lcov-report/contexts/index.html +0 -131
  96. package/src/artifacts/coverage-jest/lcov-report/contexts/index.js.html +0 -91
  97. package/src/artifacts/coverage-jest/lcov-report/favicon.png +0 -0
  98. package/src/artifacts/coverage-jest/lcov-report/hooks/index.html +0 -251
  99. package/src/artifacts/coverage-jest/lcov-report/hooks/index.js.html +0 -115
  100. package/src/artifacts/coverage-jest/lcov-report/hooks/settingsHooks/index.html +0 -146
  101. package/src/artifacts/coverage-jest/lcov-report/hooks/settingsHooks/index.js.html +0 -91
  102. package/src/artifacts/coverage-jest/lcov-report/hooks/settingsHooks/useSettingSection.js.html +0 -163
  103. package/src/artifacts/coverage-jest/lcov-report/hooks/settingsHooks/useSettings.js.html +0 -403
  104. package/src/artifacts/coverage-jest/lcov-report/hooks/typedownHooks/index.html +0 -161
  105. package/src/artifacts/coverage-jest/lcov-report/hooks/typedownHooks/index.js.html +0 -94
  106. package/src/artifacts/coverage-jest/lcov-report/hooks/typedownHooks/useTypedown.js.html +0 -520
  107. package/src/artifacts/coverage-jest/lcov-report/hooks/typedownHooks/useTypedownData.js.html +0 -163
  108. package/src/artifacts/coverage-jest/lcov-report/hooks/typedownHooks/useTypedownToggle.js.html +0 -163
  109. package/src/artifacts/coverage-jest/lcov-report/hooks/useActiveElement.js.html +0 -157
  110. package/src/artifacts/coverage-jest/lcov-report/hooks/useHelperApp.js.html +0 -283
  111. package/src/artifacts/coverage-jest/lcov-report/hooks/useKiwtFieldArray.js.html +0 -274
  112. package/src/artifacts/coverage-jest/lcov-report/hooks/useKiwtSASQuery.js.html +0 -178
  113. package/src/artifacts/coverage-jest/lcov-report/hooks/useLocalStorageState.js.html +0 -136
  114. package/src/artifacts/coverage-jest/lcov-report/hooks/useMutateRefdataValue.js.html +0 -301
  115. package/src/artifacts/coverage-jest/lcov-report/hooks/useQIndex.js.html +0 -208
  116. package/src/artifacts/coverage-jest/lcov-report/hooks/useRefdata.js.html +0 -268
  117. package/src/artifacts/coverage-jest/lcov-report/hooks/useTemplates.js.html +0 -166
  118. package/src/artifacts/coverage-jest/lcov-report/index.html +0 -401
  119. package/src/artifacts/coverage-jest/lcov-report/prettify.css +0 -1
  120. package/src/artifacts/coverage-jest/lcov-report/prettify.js +0 -2
  121. package/src/artifacts/coverage-jest/lcov-report/sort-arrow-sprite.png +0 -0
  122. package/src/artifacts/coverage-jest/lcov-report/sorter.js +0 -196
  123. package/src/artifacts/coverage-jest/lcov-report/utils/buildUrl.js.html +0 -193
  124. package/src/artifacts/coverage-jest/lcov-report/utils/generateKiwtQuery.js.html +0 -109
  125. package/src/artifacts/coverage-jest/lcov-report/utils/generateKiwtQueryParams.js.html +0 -286
  126. package/src/artifacts/coverage-jest/lcov-report/utils/index.html +0 -236
  127. package/src/artifacts/coverage-jest/lcov-report/utils/index.js.html +0 -121
  128. package/src/artifacts/coverage-jest/lcov-report/utils/refdataOptions.js.html +0 -106
  129. package/src/artifacts/coverage-jest/lcov-report/utils/renderHelpText.js.html +0 -166
  130. package/src/artifacts/coverage-jest/lcov-report/utils/selectorSafe.js.html +0 -103
  131. package/src/artifacts/coverage-jest/lcov-report/utils/sortByLabel.js.html +0 -130
  132. package/src/artifacts/coverage-jest/lcov-report/utils/toCamelCase.js.html +0 -127
  133. package/src/artifacts/coverage-jest/lcov.info +0 -1999
  134. package/src/lib/TypeDown/README.md +0 -1
  135. package/src/lib/TypeDown/TypeDown.js +0 -228
  136. package/src/lib/TypeDown/index.js +0 -1
@@ -0,0 +1,295 @@
1
+ import { useState } from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { FormattedMessage, useIntl } from 'react-intl';
4
+ import { Field, useFormState, useForm } from 'react-final-form';
5
+
6
+ import {
7
+ Col,
8
+ InfoPopover,
9
+ MultiSelection,
10
+ Row,
11
+ Select,
12
+ TextArea,
13
+ TextField
14
+ } from '@folio/stripes/components';
15
+ import { requiredValidator } from '@folio/stripes-erm-components';
16
+
17
+ const CustomPropertyForm = ({
18
+ contextFilterOptions,
19
+ helpPopovers,
20
+ labelOverrides,
21
+ refdata
22
+ }) => {
23
+ const { values } = useFormState();
24
+ const { change } = useForm();
25
+ const intl = useIntl();
26
+
27
+ const booleanToString = booleanValue => booleanValue?.toString();
28
+ const stringToBoolean = stringValue => stringValue === 'true';
29
+
30
+ const [contextOptions, setContextOptions] = useState(contextFilterOptions?.filter(ctx => ctx.value !== '' && ctx?.value !== 'isNull'));
31
+
32
+ const addCtx = ({ _r, _e, filterText }) => {
33
+ const newOption = { value: filterText, label: filterText };
34
+ setContextOptions([newOption, ...contextOptions]);
35
+ change('ctx', [newOption]);
36
+ };
37
+
38
+ const renderAddCtx = ({ filterValue, exactMatch }) => {
39
+ if (!filterValue || exactMatch) {
40
+ return null;
41
+ } else {
42
+ return <FormattedMessage id="stripes-kint-components.customProperties.ctx.addContext" values={{ value: filterValue }} />;
43
+ }
44
+ };
45
+
46
+ return (
47
+ <>
48
+ <Row>
49
+ <Col xs={6}>
50
+ <Field
51
+ component={TextField}
52
+ label={labelOverrides?.label ??
53
+ <FormattedMessage id="stripes-kint-components.customProperties.label" />
54
+ }
55
+ name="label"
56
+ required
57
+ startControl={helpPopovers?.label ?
58
+ <InfoPopover
59
+ content={helpPopovers?.label}
60
+ /> : null
61
+ }
62
+ validate={requiredValidator}
63
+ />
64
+ </Col>
65
+ <Col xs={6}>
66
+ <Field
67
+ component={TextField}
68
+ label={labelOverrides?.name ??
69
+ <FormattedMessage id="stripes-kint-components.customProperties.name" />
70
+ }
71
+ name="name"
72
+ required
73
+ startControl={helpPopovers?.name ?
74
+ <InfoPopover
75
+ content={helpPopovers?.name}
76
+ /> : null
77
+ }
78
+ validate={v => {
79
+ if (v && v.length) {
80
+ return /^[a-z][a-z0-9]*$/i.test(v) ? (
81
+ undefined
82
+ ) : (
83
+ <FormattedMessage id="stripes-kint-components.errors.hasNonAlphaName" />
84
+ );
85
+ }
86
+
87
+ return requiredValidator(v);
88
+ }}
89
+ />
90
+ </Col>
91
+ </Row>
92
+ <Row>
93
+ <Col xs={12}>
94
+ <Field
95
+ component={TextArea}
96
+ label={labelOverrides?.description ??
97
+ <FormattedMessage id="stripes-kint-components.customProperties.description" />
98
+ }
99
+ name="description"
100
+ required
101
+ startControl={helpPopovers?.description ?
102
+ <InfoPopover
103
+ content={helpPopovers?.description}
104
+ /> : null
105
+ }
106
+ validate={requiredValidator}
107
+ />
108
+ </Col>
109
+ </Row>
110
+ <Row>
111
+ <Col xs={3}>
112
+ <Field
113
+ component={TextField}
114
+ label={labelOverrides?.weight ??
115
+ <FormattedMessage id="stripes-kint-components.customProperties.weight" />
116
+ }
117
+ name="weight"
118
+ required
119
+ startControl={helpPopovers?.weight ?
120
+ <InfoPopover
121
+ content={helpPopovers?.weight}
122
+ /> : null
123
+ }
124
+ type="number"
125
+ validate={requiredValidator}
126
+ />
127
+ </Col>
128
+ <Col xs={3}>
129
+ <Field
130
+ component={Select}
131
+ dataOptions={[
132
+ {
133
+ label: intl.formatMessage({
134
+ id: 'stripes-kint-components.yes',
135
+ }),
136
+ value: 'true',
137
+ },
138
+ {
139
+ label: intl.formatMessage({
140
+ id: 'stripes-kint-components.no',
141
+ }),
142
+ value: 'false',
143
+ },
144
+ ]}
145
+ format={booleanToString}
146
+ label={labelOverrides?.primary ??
147
+ <FormattedMessage
148
+ id="stripes-kint-components.customProperties.primary"
149
+ />
150
+ }
151
+ name="primary"
152
+ parse={stringToBoolean}
153
+ required
154
+ startControl={helpPopovers?.primary ?
155
+ <InfoPopover
156
+ content={helpPopovers?.primary}
157
+ /> : null
158
+ }
159
+ validate={requiredValidator}
160
+ />
161
+ </Col>
162
+ <Col xs={3}>
163
+ <Field
164
+ component={Select}
165
+ dataOptions={[
166
+ {
167
+ label: intl.formatMessage({
168
+ id:
169
+ 'stripes-kint-components.customProperties.internalTrue',
170
+ }),
171
+ value: 'true',
172
+ },
173
+ {
174
+ label: intl.formatMessage({
175
+ id:
176
+ 'stripes-kint-components.customProperties.internalFalse',
177
+ }),
178
+ value: 'false',
179
+ },
180
+ ]}
181
+ format={booleanToString}
182
+ label={labelOverrides?.defaultVisibility ??
183
+ <FormattedMessage id="stripes-kint-components.customProperties.defaultVisibility" />
184
+ }
185
+ name="defaultInternal"
186
+ parse={stringToBoolean}
187
+ required
188
+ startControl={helpPopovers?.defaultVisibility ?
189
+ <InfoPopover
190
+ content={helpPopovers?.defaultVisibility}
191
+ /> : null
192
+ }
193
+ validate={requiredValidator}
194
+ />
195
+ </Col>
196
+ <Col xs={3}>
197
+ <Field
198
+ actions={[{ onSelect: addCtx, render: renderAddCtx }]}
199
+ component={MultiSelection}
200
+ dataOptions={contextOptions}
201
+ label={labelOverrides?.ctx ??
202
+ <FormattedMessage id="stripes-kint-components.customProperties.ctx" />
203
+ }
204
+ name="ctx"
205
+ onChange={(selectedItems) => {
206
+ if (selectedItems.length) {
207
+ change('ctx', [selectedItems?.[selectedItems?.length - 1]]);
208
+ } else {
209
+ change('ctx', undefined);
210
+ }
211
+ }}
212
+ validate={value => (value?.length > 1 ? <FormattedMessage id="stripes-kint-components.customProperties.ctx.error.moreThanOne" /> : null)}
213
+ />
214
+ </Col>
215
+ </Row>
216
+ {/* Users can only configure the type of a custom property when creating it, not when editing it */}
217
+ {!values?.id && (
218
+ <Row>
219
+ <Col xs={6}>
220
+ <Field
221
+ component={Select}
222
+ dataOptions={[
223
+ { label: '', value: '' },
224
+ {
225
+ label: intl.formatMessage({
226
+ id: 'stripes-kint-components.customProperties.type.com.k_int.web.toolkit.custprops.types.CustomPropertyDecimal',
227
+ }),
228
+ value: 'Decimal',
229
+ },
230
+ {
231
+ label: intl.formatMessage({
232
+ id: 'stripes-kint-components.customProperties.type.com.k_int.web.toolkit.custprops.types.CustomPropertyInteger',
233
+ }),
234
+ value: 'Integer',
235
+ },
236
+ {
237
+ label: intl.formatMessage({
238
+ id: 'stripes-kint-components.customProperties.type.com.k_int.web.toolkit.custprops.types.CustomPropertyText',
239
+ }),
240
+ value: 'Text',
241
+ },
242
+ {
243
+ label: intl.formatMessage({
244
+ id: 'stripes-kint-components.customProperties.type.com.k_int.web.toolkit.custprops.types.CustomPropertyRefdata',
245
+ }),
246
+ value: 'Refdata',
247
+ },
248
+ ]
249
+ }
250
+ label={labelOverrides?.type ??
251
+ <FormattedMessage id="stripes-kint-components.customProperties.type" />
252
+ }
253
+ name="type"
254
+ required
255
+ startControl={helpPopovers?.type ?
256
+ <InfoPopover
257
+ content={helpPopovers?.type}
258
+ /> : null
259
+ }
260
+ validate={requiredValidator}
261
+ />
262
+ </Col>
263
+ <Col xs={6}>
264
+ {values?.type === 'Refdata' && (
265
+ <Field
266
+ component={Select}
267
+ dataOptions={[{ label: '', value: '' }, ...refdata]}
268
+ label={labelOverrides?.category ??
269
+ <FormattedMessage id="stripes-kint-components.customProperties.category" />
270
+ }
271
+ name="category"
272
+ required
273
+ startControl={helpPopovers?.category ?
274
+ <InfoPopover
275
+ content={helpPopovers?.category}
276
+ /> : null
277
+ }
278
+ validate={requiredValidator}
279
+ />
280
+ )}
281
+ </Col>
282
+ </Row>
283
+ )}
284
+ </>
285
+ );
286
+ };
287
+
288
+ CustomPropertyForm.propTypes = {
289
+ contextFilterOptions: PropTypes.arrayOf(PropTypes.string),
290
+ helpPopovers: PropTypes.object,
291
+ labelOverrides: PropTypes.object,
292
+ refdata: PropTypes.arrayOf(PropTypes.object)
293
+ };
294
+
295
+ export default CustomPropertyForm;
@@ -0,0 +1,4 @@
1
+ export { default as CustomPropertiesLookup } from './CustomPropertiesLookup';
2
+ export { default as CustomPropertiesView } from './CustomPropertiesLookup';
3
+ export { default as CustomPropertiesSettings } from './CustomPropertiesSettings';
4
+ export { default as CustomPropertyForm } from './CustomPropertyForm';
@@ -0,0 +1,71 @@
1
+ import PropTypes from 'prop-types';
2
+
3
+ import { Form } from 'react-final-form';
4
+ import { FormattedMessage } from 'react-intl';
5
+ import { Button, Modal, ModalFooter } from '@folio/stripes/components';
6
+
7
+ const FormModal = ({ children, modalProps: { onClose, ...modalProps }, onSubmit, ...formProps }) => {
8
+ return (
9
+ <Form
10
+ onSubmit={onSubmit}
11
+ {...formProps}
12
+ >
13
+ {({ handleSubmit, form: { restart } }) => {
14
+ const handleClose = (e) => {
15
+ onClose(e);
16
+ restart();
17
+ };
18
+
19
+ const handleSubmitAndClear = () => {
20
+ handleSubmit();
21
+ restart();
22
+ };
23
+
24
+ const renderFooter = () => (
25
+ <ModalFooter>
26
+ <Button
27
+ buttonStyle="primary"
28
+ onClick={handleSubmitAndClear}
29
+ >
30
+ <FormattedMessage id="stripes-kint-components.save" />
31
+ </Button>
32
+ <Button
33
+ onClick={handleClose}
34
+ >
35
+ <FormattedMessage id="stripes-kint-components.cancel" />
36
+ </Button>
37
+ </ModalFooter>
38
+ );
39
+
40
+ return (
41
+ <form
42
+ onSubmit={handleSubmitAndClear}
43
+ >
44
+ <Modal
45
+ enforceFocus={false}
46
+ footer={renderFooter()}
47
+ onClose={handleClose}
48
+ {...modalProps}
49
+ >
50
+ {children}
51
+ </Modal>
52
+ </form>
53
+ );
54
+ }}
55
+ </Form>
56
+ );
57
+ };
58
+
59
+ FormModal.propTypes = {
60
+ children: PropTypes.oneOfType([
61
+ PropTypes.arrayOf(PropTypes.node),
62
+ PropTypes.node,
63
+ PropTypes.func,
64
+ ]),
65
+ modalProps: PropTypes.shape({
66
+ onClose: PropTypes.func
67
+ }),
68
+ onSubmit: PropTypes.func
69
+ };
70
+
71
+ export default FormModal;
@@ -0,0 +1 @@
1
+ export { default } from './FormModal';
@@ -66,11 +66,11 @@ NoResultsMessage.propTypes = {
66
66
  icon: PropTypes.string,
67
67
  isLoading: PropTypes.bool,
68
68
  isError: PropTypes.bool,
69
- label: PropTypes.oneOfType(
69
+ label: PropTypes.oneOfType([
70
70
  PropTypes.string,
71
71
  PropTypes.node,
72
72
  PropTypes.func
73
- ),
73
+ ]),
74
74
  searchTerm: PropTypes.string.isRequired,
75
75
  toggleFilterPane: PropTypes.func.isRequired,
76
76
  };
@@ -4,7 +4,7 @@ import classnames from 'classnames';
4
4
 
5
5
  import get from 'lodash/get';
6
6
 
7
- import { EndOfList, IconButton, Popper } from '@folio/stripes/components';
7
+ import { EndOfList, IconButton, Label, Popper } from '@folio/stripes/components';
8
8
 
9
9
  // eslint-disable-next-line import/no-extraneous-dependencies
10
10
  import { interactionStyles } from '@folio/stripes-components/lib/sharedStyles/interactionStyles.css';
@@ -17,19 +17,29 @@ import selectorSafe from '../utils/selectorSafe';
17
17
 
18
18
  const Typedown = ({
19
19
  dataOptions,
20
+ endOfList,
21
+ id,
20
22
  input,
23
+ isSelected,
21
24
  filterPath,
25
+ label,
22
26
  meta,
23
27
  onChange,
24
28
  onType,
25
29
  renderFooter = null,
26
30
  renderListItem = null,
31
+ required,
27
32
  uniqueIdentificationPath = 'id'
28
33
  }) => {
29
34
  const selectedUniqueId = get(input.value, uniqueIdentificationPath);
30
35
 
31
36
  // Display data needs to be in line with data options but also able to react to default handleType
32
37
  const [displayData, setDisplayData] = useState(dataOptions);
38
+
39
+ // keep track of what we've typed and whether we've typed an exact match or not
40
+ const [currentlyTyped, setCurrentlyTyped] = useState('');
41
+ const [exactMatch, setExactMatch] = useState(false);
42
+
33
43
  useEffect(() => {
34
44
  setDisplayData(dataOptions);
35
45
  }, [dataOptions]);
@@ -46,6 +56,14 @@ const Typedown = ({
46
56
  } else {
47
57
  setDisplayData(dataOptions);
48
58
  }
59
+
60
+ setCurrentlyTyped(e.target.value);
61
+
62
+ if (displayData.length === 1 && get(displayData[0], filterPath) === e.target.value) {
63
+ setExactMatch(true);
64
+ } else {
65
+ setExactMatch(false);
66
+ }
49
67
  };
50
68
 
51
69
  // Hook to set up all the essentials
@@ -74,11 +92,11 @@ const Typedown = ({
74
92
  className={css.listItem}
75
93
  >
76
94
  {renderListItem ?
77
- renderListItem(option) :
95
+ renderListItem(option, currentlyTyped, exactMatch) :
78
96
  get(option, uniqueIdentificationPath)
79
97
  }
80
98
  </div>
81
- ), [renderListItem, uniqueIdentificationPath]);
99
+ ), [currentlyTyped, exactMatch, renderListItem, uniqueIdentificationPath]);
82
100
 
83
101
  const handleChange = useCallback(value => {
84
102
  input.onChange(value);
@@ -101,7 +119,7 @@ const Typedown = ({
101
119
  id="typedown-list"
102
120
  >
103
121
  {displayData?.length ? displayData?.map((d, index) => {
104
- const isSelected = get(input.value, uniqueIdentificationPath) === get(d, uniqueIdentificationPath);
122
+ const isSelectedEval = isSelected ? isSelected(input.value, d) : get(input.value, uniqueIdentificationPath) === get(d, uniqueIdentificationPath);
105
123
  return (
106
124
  <button
107
125
  key={`typedown-button-[${index}]`}
@@ -110,7 +128,7 @@ const Typedown = ({
110
128
  css.fullWidth,
111
129
  css.menuButton
112
130
  )}
113
- data-selected={isSelected}
131
+ data-selected={isSelectedEval}
114
132
  id={`typedown-button-[${index}]`}
115
133
  onClick={() => {
116
134
  handleChange(d);
@@ -123,8 +141,7 @@ const Typedown = ({
123
141
  </button>
124
142
  );
125
143
  }) :
126
- // TODO test this
127
- <EndOfList />
144
+ endOfList || <EndOfList />
128
145
  }
129
146
  </div>
130
147
  {renderFooter &&
@@ -133,17 +150,21 @@ const Typedown = ({
133
150
  className={css.footer}
134
151
  id={`typedown-footer-${selectorSafe(input.name)}`}
135
152
  >
136
- {renderFooter()}
153
+ {renderFooter(displayData, currentlyTyped, exactMatch)}
137
154
  </div>
138
155
  }
139
156
  </div>
140
157
  );
141
158
  }, [
159
+ currentlyTyped,
142
160
  displayData,
161
+ endOfList,
162
+ exactMatch,
143
163
  footerRef,
144
164
  handleChange,
145
165
  handleNextFocus,
146
166
  input,
167
+ isSelected,
147
168
  listKeyDownHandler,
148
169
  listRef,
149
170
  renderFooter,
@@ -174,6 +195,15 @@ const Typedown = ({
174
195
  <div
175
196
  ref={resizeRef}
176
197
  >
198
+ {label &&
199
+ <Label
200
+ htmlFor={id}
201
+ id={`${id}-label`}
202
+ required={required}
203
+ >
204
+ {label}
205
+ </Label>
206
+ }
177
207
  {renderSearchField()}
178
208
  <Popper
179
209
  key="typedown-menu-toggle"
@@ -222,13 +252,25 @@ const Typedown = ({
222
252
 
223
253
  Typedown.propTypes = {
224
254
  dataOptions: PropTypes.arrayOf(PropTypes.object),
255
+ endOfList: PropTypes.oneOfType([
256
+ PropTypes.func,
257
+ PropTypes.node,
258
+ PropTypes.element
259
+ ]),
225
260
  filterPath: PropTypes.string,
261
+ id: PropTypes.string,
226
262
  input: PropTypes.object,
263
+ isSelected: PropTypes.func,
264
+ label: PropTypes.oneOfType([
265
+ PropTypes.string,
266
+ PropTypes.element
267
+ ]),
227
268
  meta: PropTypes.object,
228
269
  onChange: PropTypes.func,
229
270
  onType: PropTypes.func,
230
271
  renderFooter: PropTypes.func,
231
272
  renderListItem: PropTypes.func,
273
+ required: PropTypes.bool,
232
274
  uniqueIdentificationPath: PropTypes.string
233
275
  };
234
276
 
@@ -0,0 +1,9 @@
1
+ export const TYPE_CLASS_PREFIX = 'com.k_int.web.toolkit.custprops.types.CustomProperty';
2
+ export const BLOB_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyBlob';
3
+ export const BOOLEAN_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyBoolean';
4
+ export const CONTAINER_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyContainer';
5
+ export const DECIMAL_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyDecimal';
6
+ export const INTEGER_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyInteger';
7
+ export const REFDATA_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyRefdata';
8
+ export const REFDATA_DEFINITION_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyRefdataDefinition';
9
+ export const TEXT_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyText';
@@ -8,3 +8,5 @@ export { default as useLocalStorageState } from './useLocalStorageState';
8
8
  export { default as useQIndex } from './useQIndex';
9
9
  export { useSettings, useSettingSection } from './settingsHooks';
10
10
  export { default as useKiwtFieldArray } from './useKiwtFieldArray';
11
+ export { default as useCustomProperties } from './useCustomProperties';
12
+ export { default as useMutateCustomProperties } from './useMutateCustomProperties';
@@ -0,0 +1,73 @@
1
+ import PropTypes from 'prop-types';
2
+
3
+ import { useQuery } from 'react-query';
4
+ import { useOkapiKy } from '@folio/stripes/core';
5
+
6
+ import { generateKiwtQuery } from '../utils';
7
+
8
+ const useCustomProperties = ({
9
+ endpoint,
10
+ ctx,
11
+ nsValues = {
12
+ sort: 'id'
13
+ },
14
+ options = {
15
+ searchKey: 'label,name,description',
16
+ filterKeys: {
17
+ ContextKey: 'ctx'
18
+ },
19
+ stats: false,
20
+ max: 100
21
+ },
22
+ queryParams,
23
+ returnQueryObject = false,
24
+ }) => {
25
+ const ky = useOkapiKy();
26
+
27
+ // Allow passing of 'false' for isNull
28
+ if (Array.isArray(ctx)) {
29
+ // If we have an array, append a context filter for each ctx given
30
+ nsValues.filters = ctx.map(c => {
31
+ if (c === 'isNull') {
32
+ return 'ContextWithoutKey.ctx isNull';
33
+ } else {
34
+ return `ContextKey.${c}`;
35
+ }
36
+ }).join(',');
37
+ } else if (ctx === 'isNull') { // isNull is a special case
38
+ nsValues.filters = 'ContextWithoutKey.ctx isNull';
39
+ } else if (ctx) {
40
+ // If we just have a string, append a single ctx filter
41
+ nsValues.filters = `ContextKey.${ctx}`;
42
+ } else {
43
+ nsValues.filters = null;
44
+ }
45
+
46
+ const query = generateKiwtQuery(options, nsValues);
47
+ const path = `${endpoint}${query}`;
48
+
49
+ const queryObject = useQuery(
50
+ ['stripes-kint-components', 'useCustomProperties', 'custprops', ctx, path],
51
+ () => ky(path).json(),
52
+ queryParams
53
+ );
54
+
55
+ if (returnQueryObject) {
56
+ return queryObject || {};
57
+ }
58
+
59
+ const { data: custprops } = queryObject;
60
+ return custprops || [];
61
+ };
62
+
63
+ useCustomProperties.propTypes = {
64
+ endpoint: PropTypes.string,
65
+ ctx: PropTypes.oneOfType([
66
+ PropTypes.string,
67
+ PropTypes.arrayOf(PropTypes.string)
68
+ ]),
69
+ queryParams: PropTypes.object,
70
+ returnQueryObject: PropTypes.bool
71
+ };
72
+
73
+ export default useCustomProperties;
@@ -0,0 +1,62 @@
1
+ import { useMutation } from 'react-query';
2
+
3
+ import { useOkapiKy } from '@folio/stripes/core';
4
+
5
+ const useMutateCustomProperties = ({
6
+ afterQueryCalls,
7
+ endpoint,
8
+ id,
9
+ queryParams,
10
+ returnQueryObject = {
11
+ post: false,
12
+ put: false,
13
+ delete: false
14
+ }
15
+ }) => {
16
+ const returnObj = {};
17
+
18
+ const ky = useOkapiKy();
19
+
20
+ const deleteQueryObject = useMutation(
21
+ ['stripes-kint-components', 'useMutateCustomProperties', 'delete', id],
22
+ async () => ky.delete(`${endpoint}/${id}`).json()
23
+ .then(afterQueryCalls?.delete),
24
+ queryParams?.delete
25
+ );
26
+
27
+ const putQueryObject = useMutation(
28
+ ['stripes-kint-components', 'useMutateCustomProperties', 'put', id],
29
+ async (data) => ky.put(`${endpoint}/${id}`, { json: data }).json()
30
+ .then(afterQueryCalls?.put),
31
+ queryParams?.put
32
+ );
33
+
34
+ const postQueryObject = useMutation(
35
+ ['stripes-kint-components', 'useMutateCustomProperties', 'post'],
36
+ async (data) => ky.post(`${endpoint}`, { json: data }).json()
37
+ .then(afterQueryCalls?.post),
38
+ queryParams?.post
39
+ );
40
+
41
+ if (returnQueryObject?.delete) {
42
+ returnObj.delete = deleteQueryObject;
43
+ } else {
44
+ returnObj.delete = deleteQueryObject.mutateAsync;
45
+ }
46
+
47
+ if (returnQueryObject?.put) {
48
+ returnObj.put = putQueryObject;
49
+ } else {
50
+ returnObj.put = putQueryObject.mutateAsync;
51
+ }
52
+
53
+ if (returnQueryObject?.post) {
54
+ returnObj.post = postQueryObject;
55
+ } else {
56
+ returnObj.post = postQueryObject.mutateAsync;
57
+ }
58
+
59
+ return returnObj;
60
+ };
61
+
62
+ export default useMutateCustomProperties;