@k-int/stripes-kint-components 2.2.0 → 2.3.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 (109) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/es/index.js +124 -4
  3. package/es/lib/ActionList/ActionList.js +7 -2
  4. package/es/lib/ActionList/ActionListFieldArray.js +49 -10
  5. package/es/lib/CustomProperties/Config/CustomPropertiesSettings.js +2 -2
  6. package/es/lib/CustomProperties/Config/{CustomPropertiesView.js → CustomPropertyView.js} +5 -5
  7. package/es/lib/CustomProperties/Config/index.js +6 -4
  8. package/es/lib/CustomProperties/Edit/CustomPropertiesEdit.js +72 -0
  9. package/es/lib/CustomProperties/Edit/CustomPropertiesEditCtx.js +133 -0
  10. package/es/lib/CustomProperties/Edit/CustomPropertiesListField.js +279 -0
  11. package/es/lib/CustomProperties/Edit/CustomPropertyField.js +370 -0
  12. package/es/lib/CustomProperties/Edit/CustomPropertyFormCard.js +156 -0
  13. package/es/lib/CustomProperties/Edit/index.js +51 -0
  14. package/es/lib/CustomProperties/Filter/CustomPropertiesFilter.js +216 -0
  15. package/es/lib/CustomProperties/Filter/CustomPropertiesFilterField.js +236 -0
  16. package/es/lib/CustomProperties/Filter/CustomPropertiesFilterFieldArray.js +159 -0
  17. package/es/lib/CustomProperties/Filter/CustomPropertiesFilterForm.js +119 -0
  18. package/es/lib/CustomProperties/Filter/CustomPropertiesRule.js +173 -0
  19. package/es/lib/CustomProperties/Filter/index.js +59 -0
  20. package/es/lib/CustomProperties/Filter/useOperators.js +138 -0
  21. package/es/lib/CustomProperties/Filter/useParseActiveFilterStrings.js +97 -0
  22. package/es/lib/CustomProperties/Filter/useValueProps.js +101 -0
  23. package/es/lib/CustomProperties/View/CustomPropertiesView.js +73 -0
  24. package/es/lib/CustomProperties/View/CustomPropertiesViewCtx.js +187 -0
  25. package/es/lib/CustomProperties/View/CustomPropertyCard.js +204 -0
  26. package/es/lib/CustomProperties/View/index.js +35 -0
  27. package/es/lib/CustomProperties/index.js +125 -0
  28. package/es/lib/EditableRefdataList/EditableRefdataList.js +12 -16
  29. package/es/lib/FormModal/FormModal.js +18 -4
  30. package/es/lib/QueryTypedown/QueryTypedown.js +9 -4
  31. package/es/lib/constants/customProperties.js +4 -1
  32. package/es/lib/hooks/index.js +16 -0
  33. package/es/lib/hooks/typedownHooks/useTypedownData.js +9 -2
  34. package/es/lib/hooks/useAvailableCustomProperties.js +106 -0
  35. package/es/lib/hooks/useInvalidateRefdata.js +53 -0
  36. package/es/lib/hooks/useMutateRefdataValue.js +11 -6
  37. package/es/lib/hooks/useRefdata.js +1 -3
  38. package/es/lib/utils/groupCustomPropertiesByCtx.js +69 -0
  39. package/es/lib/utils/index.js +24 -0
  40. package/es/lib/utils/refdataQueryKey.js +48 -0
  41. package/es/lib/utils/typedownQueryKey.js +48 -0
  42. package/es/lib/utils/validators.js +60 -1
  43. package/git_translate.sh +8 -0
  44. package/package.json +1 -1
  45. package/src/index.js +27 -3
  46. package/src/lib/ActionList/ActionList.js +5 -2
  47. package/src/lib/ActionList/ActionListFieldArray.js +31 -8
  48. package/src/lib/ActionList/README.md +23 -20
  49. package/src/lib/CustomProperties/Config/CustomPropertiesSettings.js +2 -2
  50. package/src/lib/CustomProperties/Config/{CustomPropertiesView.js → CustomPropertyView.js} +3 -3
  51. package/src/lib/CustomProperties/Config/index.js +1 -1
  52. package/src/lib/CustomProperties/Edit/CustomPropertiesEdit.js +35 -0
  53. package/src/lib/CustomProperties/Edit/CustomPropertiesEditCtx.js +85 -0
  54. package/src/lib/CustomProperties/Edit/CustomPropertiesListField.js +194 -0
  55. package/src/lib/CustomProperties/Edit/CustomPropertyField.js +299 -0
  56. package/src/lib/CustomProperties/Edit/CustomPropertyFormCard.js +131 -0
  57. package/src/lib/CustomProperties/Edit/index.js +5 -0
  58. package/src/lib/CustomProperties/Filter/CustomPropertiesFilter.js +125 -0
  59. package/src/lib/CustomProperties/Filter/CustomPropertiesFilterField.js +148 -0
  60. package/src/lib/CustomProperties/Filter/CustomPropertiesFilterFieldArray.js +113 -0
  61. package/src/lib/CustomProperties/Filter/CustomPropertiesFilterForm.js +74 -0
  62. package/src/lib/CustomProperties/Filter/CustomPropertiesRule.js +122 -0
  63. package/src/lib/CustomProperties/Filter/index.js +6 -0
  64. package/src/lib/CustomProperties/Filter/useOperators.js +55 -0
  65. package/src/lib/CustomProperties/Filter/useParseActiveFilterStrings.js +35 -0
  66. package/src/lib/CustomProperties/Filter/useValueProps.js +45 -0
  67. package/src/lib/CustomProperties/View/CustomPropertiesView.js +36 -0
  68. package/src/lib/CustomProperties/View/CustomPropertiesViewCtx.js +112 -0
  69. package/src/lib/CustomProperties/View/CustomPropertyCard.js +177 -0
  70. package/src/lib/CustomProperties/View/index.js +3 -0
  71. package/src/lib/CustomProperties/index.js +30 -0
  72. package/src/lib/EditableRefdataList/EditableRefdataList.js +13 -10
  73. package/src/lib/FormModal/FormModal.js +37 -17
  74. package/src/lib/QueryTypedown/QueryTypedown.js +3 -1
  75. package/src/lib/constants/customProperties.js +1 -0
  76. package/src/lib/hooks/index.js +2 -0
  77. package/src/lib/hooks/typedownHooks/useTypedownData.js +9 -3
  78. package/src/lib/hooks/useAvailableCustomProperties.js +40 -0
  79. package/src/lib/hooks/useInvalidateRefdata.js +11 -0
  80. package/src/lib/hooks/useMutateRefdataValue.js +7 -3
  81. package/src/lib/hooks/useRefdata.js +2 -3
  82. package/src/lib/utils/groupCustomPropertiesByCtx.js +13 -0
  83. package/src/lib/utils/index.js +5 -0
  84. package/src/lib/utils/refdataQueryKey.js +9 -0
  85. package/src/lib/utils/typedownQueryKey.js +9 -0
  86. package/src/lib/utils/validators.js +40 -0
  87. package/translate.sh +63 -0
  88. package/translations/stripes-kint-components/ar.json +105 -0
  89. package/translations/stripes-kint-components/ca.json +1 -0
  90. package/translations/stripes-kint-components/cs_CZ.json +105 -0
  91. package/translations/stripes-kint-components/da.json +1 -0
  92. package/translations/stripes-kint-components/de.json +105 -0
  93. package/translations/stripes-kint-components/en.json +54 -2
  94. package/translations/stripes-kint-components/es.json +105 -0
  95. package/translations/stripes-kint-components/fr.json +105 -0
  96. package/translations/stripes-kint-components/he.json +1 -0
  97. package/translations/stripes-kint-components/hi_IN.json +105 -0
  98. package/translations/stripes-kint-components/hu.json +105 -0
  99. package/translations/stripes-kint-components/it_IT.json +105 -0
  100. package/translations/stripes-kint-components/ja.json +105 -0
  101. package/translations/stripes-kint-components/ko.json +105 -0
  102. package/translations/stripes-kint-components/nb.json +1 -0
  103. package/translations/stripes-kint-components/nn.json +1 -0
  104. package/translations/stripes-kint-components/pl.json +105 -0
  105. package/translations/stripes-kint-components/pt_PT.json +105 -0
  106. package/translations/stripes-kint-components/ru.json +105 -0
  107. package/translations/stripes-kint-components/sv.json +105 -0
  108. package/translations/stripes-kint-components/ur.json +1 -0
  109. package/translations/stripes-kint-components/zh_CN.json +105 -0
@@ -0,0 +1,45 @@
1
+ import { Datepicker, Select, TextField } from '@folio/stripes/components';
2
+ import * as CUSTPROP_TYPES from '../../constants/customProperties';
3
+ import { invalidNumber as invalidNumberValidator, required as requiredValidator } from '../../utils/validators';
4
+
5
+ const {
6
+ REFDATA_CLASS_NAME: REFDATA,
7
+ DECIMAL_CLASS_NAME: DECIMAL,
8
+ INTEGER_CLASS_NAME: INTEGER,
9
+ DATE_CLASS_NAME: DATE,
10
+ TEXT_CLASS_NAME: TEXT,
11
+ } = CUSTPROP_TYPES;
12
+
13
+ const useValueProps = (custPropDefinition) => {
14
+ const props = {
15
+ validate: requiredValidator
16
+ };
17
+
18
+ switch (custPropDefinition.type) {
19
+ case INTEGER:
20
+ case DECIMAL:
21
+ props.component = TextField;
22
+ props.type = 'number';
23
+ props.validate = invalidNumberValidator;
24
+ break;
25
+ case REFDATA:
26
+ props.component = Select;
27
+ props.dataOptions = custPropDefinition.category.values.map(rdv => ({ label: rdv.label, value: rdv.id }));
28
+ props.placeholder = ' ';
29
+ break;
30
+ case DATE:
31
+ props.component = Datepicker;
32
+ props.backendDateStandard = 'YYYY-MM-DD';
33
+ props.timeZone = 'UTC';
34
+ props.usePortal = true;
35
+ break;
36
+ case TEXT:
37
+ default:
38
+ props.component = TextField;
39
+ break;
40
+ }
41
+
42
+ return props;
43
+ };
44
+
45
+ export default useValueProps;
@@ -0,0 +1,36 @@
1
+ import PropTypes from 'prop-types';
2
+ import CustomPropertiesViewCtx from './CustomPropertiesViewCtx';
3
+
4
+ const CustomPropertiesView = ({
5
+ contexts = [],
6
+ customProperties,
7
+ customPropertiesEndpoint,
8
+ id,
9
+ labelOverrides = {},
10
+ }) => {
11
+ return (
12
+ contexts.map(ctx => (
13
+ <CustomPropertiesViewCtx
14
+ key={`customPropertiesView-${ctx}`}
15
+ {...{
16
+ ctx,
17
+ customProperties,
18
+ customPropertiesEndpoint,
19
+ id,
20
+ labelOverrides
21
+ }}
22
+ />
23
+ ))
24
+ );
25
+ };
26
+
27
+ CustomPropertiesView.propTypes = {
28
+ contexts: PropTypes.arrayOf(PropTypes.string),
29
+ customProperties: PropTypes.object,
30
+ customPropertiesEndpoint: PropTypes.string,
31
+ id: PropTypes.string,
32
+ labelOverrides: PropTypes.object,
33
+ nameOverride: PropTypes.string
34
+ };
35
+
36
+ export default CustomPropertiesView;
@@ -0,0 +1,112 @@
1
+ import PropTypes from 'prop-types';
2
+ import { FormattedMessage } from 'react-intl';
3
+ import { Accordion, Badge, Spinner } from '@folio/stripes/components';
4
+
5
+ import { useCustomProperties } from '../../hooks';
6
+
7
+ import CustomPropertyCard from './CustomPropertyCard';
8
+
9
+ const CustomPropertiesViewCtx = ({
10
+ ctx,
11
+ customProperties,
12
+ customPropertiesEndpoint,
13
+ id,
14
+ labelOverrides
15
+ }) => {
16
+ // Deal with all the possible label override options
17
+ const getAccordionLabel = () => {
18
+ // Special case for null context
19
+ if (ctx === 'isNull') {
20
+ return (
21
+ labelOverrides.noContext ??
22
+ <FormattedMessage id="stripes-kint-components.customProperties" />
23
+ );
24
+ }
25
+
26
+ // Label overrides for specific contexts
27
+ if (labelOverrides[ctx]) {
28
+ return labelOverrides[ctx];
29
+ }
30
+
31
+ // Label override for default title, taking ctx into account
32
+ if (labelOverrides.defaultTitle && typeof labelOverrides.defaultTitle === 'function') {
33
+ return (
34
+ labelOverrides.defaultTitle(ctx)
35
+ );
36
+ }
37
+
38
+ // Label override for default title or finally built in default
39
+ return (
40
+ labelOverrides.defaultTitle ??
41
+ <FormattedMessage id="stripes-kint-components.customProperties.ctx.title" values={{ ctx }} />
42
+ );
43
+ };
44
+
45
+ const { data: custprops, isLoading } = useCustomProperties({
46
+ ctx,
47
+ endpoint: customPropertiesEndpoint,
48
+ returnQueryObject: true,
49
+ options: {
50
+ sort: [
51
+ { path: 'retired' }, // Place retired custprops at the end
52
+ { path: 'primary', direction: 'desc' }, // Primary properties should display before optional
53
+ { path: 'label' } // Within those groups, sort by label
54
+ ]
55
+ }
56
+ });
57
+
58
+ if (isLoading) {
59
+ return (
60
+ <Accordion
61
+ closedByDefault
62
+ displayWhenClosed={<Spinner />}
63
+ displayWhenOpen={<Spinner />}
64
+ id={`${id}-accordion-${ctx}`}
65
+ label={getAccordionLabel()}
66
+ >
67
+ <Spinner />
68
+ </Accordion>
69
+ );
70
+ }
71
+
72
+ // We need to display any set properties, along with any non-set primary properties
73
+ const primaryCount = custprops?.filter(cp => cp.primary === true)?.length ?? 0;
74
+ const optionalCount = Object.entries(customProperties)?.filter(
75
+ ([_key, cp]) => (
76
+ (cp[0]?.type?.ctx === ctx || (ctx === 'isNull' && !cp[0]?.type?.ctx)) && // Either the ctx string matches, or isNull matches blank
77
+ cp[0]?.type?.primary === false // Only count non-primary set custprops
78
+ )
79
+ )?.length ?? 0;
80
+
81
+ return (
82
+ (primaryCount + optionalCount) > 0 &&
83
+ <Accordion
84
+ closedByDefault
85
+ displayWhenClosed={<Badge>{primaryCount + optionalCount}</Badge>}
86
+ displayWhenOpen={<Badge>{primaryCount + optionalCount}</Badge>}
87
+ id={`${id}-accordion-${ctx}`}
88
+ label={getAccordionLabel()}
89
+ >
90
+ {custprops.map((cp, index) => (
91
+ <CustomPropertyCard
92
+ key={`custom-property-card-${ctx}[${index}]`}
93
+ ctx={ctx}
94
+ customProperty={customProperties?.[cp.name]?.[0]}
95
+ customPropertyDefinition={cp}
96
+ index={index}
97
+ labelOverrides={labelOverrides}
98
+ />
99
+ ))}
100
+ </Accordion>
101
+ );
102
+ };
103
+
104
+ CustomPropertiesViewCtx.propTypes = {
105
+ ctx: PropTypes.string,
106
+ customProperties: PropTypes.object,
107
+ customPropertiesEndpoint: PropTypes.string,
108
+ id: PropTypes.string,
109
+ labelOverrides: PropTypes.object,
110
+ };
111
+
112
+ export default CustomPropertiesViewCtx;
@@ -0,0 +1,177 @@
1
+ import PropTypes from 'prop-types';
2
+ import { FormattedMessage, FormattedNumber } from 'react-intl';
3
+
4
+ import {
5
+ Card,
6
+ Col,
7
+ FormattedUTCDate,
8
+ InfoPopover,
9
+ KeyValue,
10
+ NoValue,
11
+ Row,
12
+ } from '@folio/stripes/components';
13
+
14
+ import * as CUSTPROP_TYPES from '../../constants/customProperties';
15
+
16
+ const CustomPropertyCard = ({
17
+ ctx,
18
+ customProperty,
19
+ customPropertyDefinition,
20
+ index,
21
+ labelOverrides
22
+ }) => {
23
+ // We only need to display primary and set properties
24
+ const toDisplay = !!(customPropertyDefinition.primary || customProperty);
25
+
26
+ if (!toDisplay) {
27
+ return null;
28
+ }
29
+
30
+ const internalFalse = customProperty?.internal === false ||
31
+ (customProperty?.internal === undefined && customPropertyDefinition.defaultInternal === false);
32
+
33
+ // Deal with all the possible label override options
34
+ const getRetiredCardTitle = () => {
35
+ // Label override for default card title,
36
+ if (labelOverrides.retiredName && typeof labelOverrides.retiredName === 'function') {
37
+ return (
38
+ labelOverrides.retiredName(customPropertyDefinition)
39
+ );
40
+ }
41
+
42
+ // Label override for default title or finally built in default
43
+ return (
44
+ labelOverrides.retiredName ??
45
+ <FormattedMessage id="stripes-kint-components.customProperty.retiredName" values={{ name: customPropertyDefinition.label }} />
46
+ );
47
+ };
48
+
49
+ const getInternalLabel = () => {
50
+ if (internalFalse) {
51
+ return (
52
+ labelOverrides.internalFalse ??
53
+ <FormattedMessage id="stripes-kint-components.customProperty.internalFalse" />
54
+ );
55
+ }
56
+
57
+ return (
58
+ labelOverrides.internalTrue ??
59
+ <FormattedMessage id="stripes-kint-components.customProperty.internalTrue" />
60
+ );
61
+ };
62
+
63
+ const renderValue = () => {
64
+ if (!customProperty) {
65
+ return (
66
+ labelOverrides.notSet ??
67
+ <FormattedMessage id="stripes-kint-components.customProperty.notSet" />
68
+ );
69
+ }
70
+
71
+ switch (customPropertyDefinition.type) {
72
+ case CUSTPROP_TYPES.REFDATA_CLASS_NAME:
73
+ return customProperty.value?.label ?? customProperty.value?.value;
74
+ case CUSTPROP_TYPES.DECIMAL_CLASS_NAME:
75
+ case CUSTPROP_TYPES.INTEGER_CLASS_NAME:
76
+ return <FormattedNumber value={customProperty.value} />;
77
+ case CUSTPROP_TYPES.DATE_CLASS_NAME:
78
+ return <FormattedUTCDate value={customProperty.value} />;
79
+ case CUSTPROP_TYPES.TEXT_CLASS_NAME:
80
+ default:
81
+ return customProperty.value;
82
+ }
83
+ };
84
+
85
+ return (
86
+ <Card
87
+ key={`customPropertyCard-${ctx}[${index}]`}
88
+ headerStart={
89
+ <>
90
+ <strong>
91
+ {customPropertyDefinition.retired ?
92
+ getRetiredCardTitle() :
93
+ customPropertyDefinition.label
94
+ }
95
+ </strong>
96
+ {customPropertyDefinition.description ? (
97
+ <InfoPopover
98
+ content={customPropertyDefinition.description}
99
+ />
100
+ ) : null}
101
+ </>
102
+ }
103
+ id={`customproperty-card-${index}`}
104
+ >
105
+ <Row>
106
+ <Col xs={6}>
107
+ <KeyValue
108
+ label={
109
+ labelOverrides.value ??
110
+ <FormattedMessage id="stripes-kint-components.customProperty.value" />
111
+ }
112
+ >
113
+ {renderValue()}
114
+ </KeyValue>
115
+ </Col>
116
+ {customProperty?.internalNote ? (
117
+ <Col xs={6}>
118
+ <KeyValue
119
+ label={
120
+ labelOverrides.internalNote ??
121
+ <FormattedMessage id="stripes-kint-components.customProperty.internalNote" />
122
+ }
123
+ >
124
+ <span
125
+ style={{ whiteSpace: 'pre-wrap' }}
126
+ >
127
+ {customProperty.internalNote}
128
+ </span>
129
+ </KeyValue>
130
+ </Col>
131
+ ) : null}
132
+ </Row>
133
+ <Row>
134
+ <Col xs={6}>
135
+ <KeyValue
136
+ label={
137
+ labelOverrides.visibility ??
138
+ <FormattedMessage id="stripes-kint-components.customProperty.visibility" />
139
+ }
140
+ >
141
+ {getInternalLabel()}
142
+ </KeyValue>
143
+ </Col>
144
+ {internalFalse &&
145
+ <Col xs={6}>
146
+ <KeyValue
147
+ label={
148
+ labelOverrides.publicNote ??
149
+ <FormattedMessage id="stripes-kint-components.customProperty.publicNote" />
150
+ }
151
+ >
152
+ {customProperty?.publicNote ? (
153
+ <span
154
+ style={{ whiteSpace: 'pre-wrap' }}
155
+ >
156
+ {customProperty.publicNote}
157
+ </span>
158
+ ) : (
159
+ <NoValue />
160
+ )}
161
+ </KeyValue>
162
+ </Col>
163
+ }
164
+ </Row>
165
+ </Card>
166
+ );
167
+ };
168
+
169
+ CustomPropertyCard.propTypes = {
170
+ ctx: PropTypes.string,
171
+ customProperty: PropTypes.object,
172
+ customPropertyDefinition: PropTypes.object,
173
+ index: PropTypes.number,
174
+ labelOverrides: PropTypes.object,
175
+ };
176
+
177
+ export default CustomPropertyCard;
@@ -0,0 +1,3 @@
1
+ export { default as CustomPropertiesView } from './CustomPropertiesView';
2
+ export { default as CustomPropertiesViewCtx } from './CustomPropertiesViewCtx';
3
+ export { default as CustomPropertyCard } from './CustomPropertyCard';
@@ -0,0 +1,30 @@
1
+ export {
2
+ CustomPropertiesLookup,
3
+ CustomPropertyView,
4
+ CustomPropertiesSettings,
5
+ CustomPropertyForm
6
+ } from './Config';
7
+
8
+ export {
9
+ CustomPropertiesEdit,
10
+ CustomPropertiesEditCtx,
11
+ CustomPropertiesListField,
12
+ CustomPropertyFormCard,
13
+ CustomPropertyField
14
+ } from './Edit';
15
+
16
+
17
+ export {
18
+ CustomPropertiesView,
19
+ CustomPropertiesViewCtx,
20
+ CustomPropertyCard
21
+ } from './View';
22
+
23
+ export {
24
+ CustomPropertiesFilter,
25
+ CustomPropertiesFilterForm,
26
+ CustomPropertiesFilterField,
27
+ CustomPropertiesFilterFieldArray,
28
+ useOperators,
29
+ useParseActiveFilterStrings,
30
+ } from './Filter';
@@ -55,25 +55,28 @@ const EditableRefdataList = ({ desc, refdataEndpoint }) => {
55
55
  // This is the function which will take a row in the table and assign the relevant actions to it
56
56
  const actionAssigner = () => {
57
57
  const actionArray = [
58
- { name: 'edit', label: <FormattedMessage id="stripes-kint-components.editableRefdataList.edit" />, icon: 'edit' },
58
+ {
59
+ name: 'edit',
60
+ label: <FormattedMessage id="stripes-kint-components.editableRefdataList.edit" />,
61
+ icon: 'edit',
62
+ callback: (data) => editRefdataValue(data)
63
+ }
59
64
  ];
60
65
 
61
66
  if (!refdata?.internal) {
62
- actionArray.push({ name: 'delete', label: <FormattedMessage id="stripes-kint-components.editableRefdataList.delete" />, icon: 'trash' });
67
+ actionArray.push({
68
+ name: 'delete',
69
+ label: <FormattedMessage id="stripes-kint-components.editableRefdataList.delete" />,
70
+ icon: 'trash',
71
+ callback: (data) => deleteRefdataValue(data.id)
72
+ });
63
73
  }
64
74
  return actionArray;
65
75
  };
66
76
 
67
- const actionCalls = {
68
- create: refdata?.internal ? null : (data) => editRefdataValue(data),
69
- edit: (data) => editRefdataValue(data),
70
- delete: (data) => deleteRefdataValue(data.id)
71
- };
72
-
73
77
  return (
74
78
  <ActionList
75
79
  actionAssigner={actionAssigner}
76
- actionCalls={actionCalls}
77
80
  columnMapping={{
78
81
  label: <FormattedMessage id="stripes-kint-components.editableRefdataList.label" />,
79
82
  value: <FormattedMessage id="stripes-kint-components.editableRefdataList.value" />
@@ -82,11 +85,11 @@ const EditableRefdataList = ({ desc, refdataEndpoint }) => {
82
85
  creatableFields={{
83
86
  value: () => false
84
87
  }}
88
+ createCallback={refdata?.internal ? null : (data) => editRefdataValue(data)}
85
89
  editableFields={{
86
90
  value: () => false
87
91
  }}
88
92
  visibleFields={['label', 'value']}
89
- // TODO add a field validator/fieldType as options?
90
93
  />
91
94
  );
92
95
  };
@@ -4,7 +4,13 @@ import { Form } from 'react-final-form';
4
4
  import { FormattedMessage } from 'react-intl';
5
5
  import { Button, Modal, ModalFooter } from '@folio/stripes/components';
6
6
 
7
- const FormModal = ({ children, modalProps: { onClose, ...modalProps }, onSubmit, ...formProps }) => {
7
+ const FormModal = ({
8
+ children,
9
+ labelOverrides = {},
10
+ modalProps: { footer, onClose, ...modalProps },
11
+ onSubmit,
12
+ ...formProps
13
+ }) => {
8
14
  return (
9
15
  <Form
10
16
  onSubmit={onSubmit}
@@ -16,21 +22,33 @@ const FormModal = ({ children, modalProps: { onClose, ...modalProps }, onSubmit,
16
22
  restart();
17
23
  };
18
24
 
19
- const renderFooter = () => (
20
- <ModalFooter>
21
- <Button
22
- buttonStyle="primary"
23
- onClick={handleSubmit}
24
- >
25
- <FormattedMessage id="stripes-kint-components.save" />
26
- </Button>
27
- <Button
28
- onClick={handleClose}
29
- >
30
- <FormattedMessage id="stripes-kint-components.cancel" />
31
- </Button>
32
- </ModalFooter>
33
- );
25
+ const renderFooter = () => {
26
+ if (footer) {
27
+ return footer({ handleSubmit, handleClose });
28
+ }
29
+
30
+ return (
31
+ <ModalFooter>
32
+ <Button
33
+ buttonStyle="primary"
34
+ onClick={handleSubmit}
35
+ >
36
+ {
37
+ labelOverrides.save ??
38
+ <FormattedMessage id="stripes-kint-components.save" />
39
+ }
40
+ </Button>
41
+ <Button
42
+ onClick={handleClose}
43
+ >
44
+ {
45
+ labelOverrides.cancel ??
46
+ <FormattedMessage id="stripes-kint-components.cancel" />
47
+ }
48
+ </Button>
49
+ </ModalFooter>
50
+ );
51
+ };
34
52
 
35
53
  return (
36
54
  <form
@@ -57,8 +75,10 @@ FormModal.propTypes = {
57
75
  PropTypes.node,
58
76
  PropTypes.func,
59
77
  ]),
78
+ labelOverrides: PropTypes.object,
60
79
  modalProps: PropTypes.shape({
61
- onClose: PropTypes.func
80
+ footer: PropTypes.func,
81
+ onClose: PropTypes.func,
62
82
  }),
63
83
  onSubmit: PropTypes.func
64
84
  };
@@ -5,12 +5,13 @@ import Typedown from '../Typedown';
5
5
  import { useTypedownData } from '../hooks/typedownHooks';
6
6
 
7
7
  const QueryTypedown = ({
8
+ dataFormatter = d => d,
8
9
  path,
9
10
  pathMutator,
10
11
  ...rest
11
12
  }) => {
12
13
  const [callPath, setCallPath] = useState(pathMutator(null, path));
13
- const data = useTypedownData(callPath);
14
+ const data = dataFormatter(useTypedownData(path, callPath));
14
15
 
15
16
  const onType = e => {
16
17
  setCallPath(pathMutator(e.target.value, path));
@@ -26,6 +27,7 @@ const QueryTypedown = ({
26
27
  };
27
28
 
28
29
  QueryTypedown.propTypes = {
30
+ dataFormatter: PropTypes.func,
29
31
  path: PropTypes.string,
30
32
  pathMutator: PropTypes.func
31
33
  };
@@ -7,3 +7,4 @@ export const INTEGER_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomP
7
7
  export const REFDATA_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyRefdata';
8
8
  export const REFDATA_DEFINITION_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyRefdataDefinition';
9
9
  export const TEXT_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyText';
10
+ export const DATE_CLASS_NAME = 'com.k_int.web.toolkit.custprops.types.CustomPropertyLocalDate';
@@ -10,3 +10,5 @@ export { useSettings, useSettingSection } from './settingsHooks';
10
10
  export { default as useKiwtFieldArray } from './useKiwtFieldArray';
11
11
  export { default as useCustomProperties } from './useCustomProperties';
12
12
  export { default as useMutateCustomProperties } from './useMutateCustomProperties';
13
+ export { default as useAvailableCustomProperties } from './useAvailableCustomProperties';
14
+ export { default as useInvalidateRefdata } from './useInvalidateRefdata';
@@ -2,16 +2,22 @@ import { useEffect, useState } from 'react';
2
2
  import { useQuery } from 'react-query';
3
3
  import { useOkapiKy } from '@folio/stripes/core';
4
4
 
5
- const useTypedownData = (callPath) => {
5
+ import { typedownQueryKey } from '../../utils';
6
+
7
+ const useTypedownData = (path, callPath) => {
6
8
  const ky = useOkapiKy();
7
9
 
10
+ const queryKey = typedownQueryKey(path);
11
+ if (callPath) {
12
+ queryKey.push(callPath);
13
+ }
14
+
8
15
  const { data, isLoading } = useQuery(
9
16
  // Ensure when multiple apps are using this function that each one gets memoized individually
10
- ['stripes-kint-components', 'typedown', callPath],
17
+ queryKey,
11
18
  () => ky(callPath).json()
12
19
  );
13
20
 
14
-
15
21
  // Smooth out transitions while data changes by only displaying once call has been loaded.
16
22
  const [contentData, setContentData] = useState();
17
23
  useEffect(() => {
@@ -0,0 +1,40 @@
1
+ import { useEffect, useState } from 'react';
2
+ import { useIntl } from 'react-intl';
3
+
4
+ const useAvailableCustomProperties = (customProperties = []) => {
5
+ const intl = useIntl();
6
+ const [custProps, setCustProps] = useState([]);
7
+
8
+ useEffect(() => {
9
+ if (customProperties.length !== custProps.length) {
10
+ setCustProps(customProperties.map(customProperty => {
11
+ let options = customProperty?.category?.values;
12
+ if (options) {
13
+ options = [
14
+ {
15
+ label: intl.formatMessage({
16
+ id: 'stripes-kint-components.notSet',
17
+ }),
18
+ value: '',
19
+ },
20
+ ...options,
21
+ ];
22
+ }
23
+
24
+ return {
25
+ description: customProperty.description,
26
+ label: customProperty.label,
27
+ primary: customProperty.primary,
28
+ type: customProperty.type,
29
+ options,
30
+ value: customProperty.name,
31
+ defaultInternal: customProperty.defaultInternal,
32
+ };
33
+ }));
34
+ }
35
+ }, [custProps, customProperties, intl]);
36
+
37
+ return custProps;
38
+ };
39
+
40
+ export default useAvailableCustomProperties;
@@ -0,0 +1,11 @@
1
+ import { useQueryClient } from 'react-query';
2
+
3
+ import { refdataQueryKey } from '../utils';
4
+
5
+ const useInvalidateRefdata = (desc) => {
6
+ const queryClient = useQueryClient();
7
+
8
+ return () => queryClient.invalidateQueries(refdataQueryKey(desc));
9
+ };
10
+
11
+ export default useInvalidateRefdata;
@@ -1,8 +1,9 @@
1
- import React from 'react';
2
1
  import { useMutation } from 'react-query';
3
2
 
4
3
  import { useOkapiKy } from '@folio/stripes/core';
5
4
 
5
+ import useInvalidateRefdata from './useInvalidateRefdata';
6
+
6
7
  const useMutateRefdataValue = ({
7
8
  afterQueryCalls,
8
9
  endpoint,
@@ -16,6 +17,7 @@ const useMutateRefdataValue = ({
16
17
  const returnObj = {};
17
18
 
18
19
  const ky = useOkapiKy();
20
+ const invalidateRefdata = useInvalidateRefdata();
19
21
 
20
22
  const deleteQueryObject = useMutation(
21
23
  ['stripes-kint-components', 'useMutateRefdataValue', 'delete', id],
@@ -33,7 +35,8 @@ const useMutateRefdataValue = ({
33
35
  }
34
36
  }
35
37
  ).json()
36
- .then(afterQueryCalls?.delete),
38
+ .then(afterQueryCalls?.delete)
39
+ .then(() => invalidateRefdata()),
37
40
  queryParams?.delete
38
41
  );
39
42
 
@@ -50,7 +53,8 @@ const useMutateRefdataValue = ({
50
53
  }
51
54
  }
52
55
  ).json()
53
- .then(afterQueryCalls?.put),
56
+ .then(afterQueryCalls?.put)
57
+ .then(() => invalidateRefdata()),
54
58
  queryParams?.put
55
59
  );
56
60