@k-int/stripes-kint-components 1.3.0 → 1.4.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 +9 -1
- package/es/index.js +26 -0
- package/es/lib/NoResultsMessage/NoResultsMessage.js +89 -0
- package/es/lib/NoResultsMessage/index.js +15 -0
- package/es/lib/SASQLookupComponent/SASQLookupComponent.js +17 -0
- package/es/lib/hooks/index.js +8 -0
- package/es/lib/hooks/useHelperApp.js +7 -1
- package/es/lib/hooks/useKiwtSASQuery.js +22 -1
- package/es/lib/hooks/useQIndex.js +75 -0
- package/es/lib/hooks/useRefdata.js +23 -6
- package/es/lib/utils/generateKiwtQuery.js +3 -109
- package/es/lib/utils/generateKiwtQueryParams.js +125 -0
- package/es/lib/utils/index.js +16 -0
- package/package.json +1 -1
- package/src/index.js +7 -1
- package/src/lib/NoResultsMessage/NoResultsMessage.js +78 -0
- package/src/lib/NoResultsMessage/index.js +1 -0
- package/src/lib/SASQLookupComponent/SASQLookupComponent.js +30 -8
- package/src/lib/SASQRoute/README.md +1 -1
- package/src/lib/TypeDown/README.md +1 -115
- package/src/lib/hooks/README.md +34 -0
- package/src/lib/hooks/index.js +2 -0
- package/src/lib/hooks/useHelperApp.js +5 -1
- package/src/lib/hooks/useKiwtSASQuery.js +9 -1
- package/src/lib/hooks/useQIndex.js +41 -0
- package/src/lib/hooks/useRefdata.js +23 -6
- package/src/lib/utils/README.md +39 -1
- package/src/lib/utils/generateKiwtQuery.js +3 -62
- package/src/lib/utils/generateKiwtQueryParams.js +67 -0
- package/src/lib/utils/index.js +3 -0
- package/styles/NoResultsMessage.css +38 -0
- package/translations/stripes-kint-components/en.json +3 -1
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports["default"] = void 0;
|
|
7
|
+
var _excluded = ["searchKey", "filterKeys", "sortKeys", "stats"];
|
|
8
|
+
|
|
9
|
+
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
|
|
10
|
+
|
|
11
|
+
function _iterableToArrayLimit(arr, i) { var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"]; if (_i == null) return; var _arr = []; var _n = true; var _d = false; var _s, _e; try { for (_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; }
|
|
12
|
+
|
|
13
|
+
function _toArray(arr) { return _arrayWithHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableRest(); }
|
|
14
|
+
|
|
15
|
+
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
16
|
+
|
|
17
|
+
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
|
|
18
|
+
|
|
19
|
+
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
|
|
20
|
+
|
|
21
|
+
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
|
|
22
|
+
|
|
23
|
+
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
|
|
24
|
+
|
|
25
|
+
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
|
|
26
|
+
|
|
27
|
+
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
|
|
28
|
+
|
|
29
|
+
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; }
|
|
30
|
+
|
|
31
|
+
function _objectWithoutProperties(source, excluded) { if (source == null) return {}; var target = _objectWithoutPropertiesLoose(source, excluded); var key, i; if (Object.getOwnPropertySymbols) { var sourceSymbolKeys = Object.getOwnPropertySymbols(source); for (i = 0; i < sourceSymbolKeys.length; i++) { key = sourceSymbolKeys[i]; if (excluded.indexOf(key) >= 0) continue; if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue; target[key] = source[key]; } } return target; }
|
|
32
|
+
|
|
33
|
+
function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
|
|
34
|
+
|
|
35
|
+
var generateKiwtQueryParams = function generateKiwtQueryParams(options, nsValues) {
|
|
36
|
+
var qindex = nsValues.qindex,
|
|
37
|
+
query = nsValues.query,
|
|
38
|
+
filters = nsValues.filters,
|
|
39
|
+
sort = nsValues.sort;
|
|
40
|
+
|
|
41
|
+
var _options$searchKey = options.searchKey,
|
|
42
|
+
searchKey = _options$searchKey === void 0 ? '' : _options$searchKey,
|
|
43
|
+
_options$filterKeys = options.filterKeys,
|
|
44
|
+
filterKeys = _options$filterKeys === void 0 ? {} : _options$filterKeys,
|
|
45
|
+
_options$sortKeys = options.sortKeys,
|
|
46
|
+
sortKeys = _options$sortKeys === void 0 ? {} : _options$sortKeys,
|
|
47
|
+
_options$stats = options.stats,
|
|
48
|
+
stats = _options$stats === void 0 ? true : _options$stats,
|
|
49
|
+
rest = _objectWithoutProperties(options, _excluded);
|
|
50
|
+
|
|
51
|
+
var paramsArray = [];
|
|
52
|
+
|
|
53
|
+
if (query) {
|
|
54
|
+
var _split;
|
|
55
|
+
|
|
56
|
+
paramsArray.push.apply(paramsArray, _toConsumableArray((_split = (qindex || searchKey).split(',')) === null || _split === void 0 ? void 0 : _split.map(function (m) {
|
|
57
|
+
return "match=".concat(m);
|
|
58
|
+
})));
|
|
59
|
+
paramsArray.push("term=".concat(query));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (filters) {
|
|
63
|
+
var filterMap = {};
|
|
64
|
+
filters.split(',').forEach(function (filter) {
|
|
65
|
+
var _filter$split = filter.split('.'),
|
|
66
|
+
_filter$split2 = _toArray(_filter$split),
|
|
67
|
+
filterName = _filter$split2[0],
|
|
68
|
+
filterRest = _filter$split2.slice(1);
|
|
69
|
+
|
|
70
|
+
var filterValue = filterRest.join('.');
|
|
71
|
+
if (filterMap[filterName] === undefined) filterMap[filterName] = [];
|
|
72
|
+
filterMap[filterName].push(filterValue);
|
|
73
|
+
}); // We now have a filterMap of shape { status: ['active', 'cancelled'], type: ['local'] }
|
|
74
|
+
|
|
75
|
+
Object.entries(filterMap).forEach(function (_ref) {
|
|
76
|
+
var _ref2 = _slicedToArray(_ref, 2),
|
|
77
|
+
filterName = _ref2[0],
|
|
78
|
+
filterValues = _ref2[1];
|
|
79
|
+
|
|
80
|
+
var filterKey = filterKeys[filterName];
|
|
81
|
+
|
|
82
|
+
if (!filterKey) {
|
|
83
|
+
// These filters have no key mapping so we just pass the values to the backend as-is.
|
|
84
|
+
paramsArray.push.apply(paramsArray, _toConsumableArray(filterValues === null || filterValues === void 0 ? void 0 : filterValues.map(function (f) {
|
|
85
|
+
return "filters=".concat(f);
|
|
86
|
+
})));
|
|
87
|
+
} else {
|
|
88
|
+
var filterString = filterValues.map(function (v) {
|
|
89
|
+
return "".concat(filterKey, "==").concat(v);
|
|
90
|
+
}).join('||');
|
|
91
|
+
paramsArray.push("filters=".concat(filterString));
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (sort) {
|
|
97
|
+
paramsArray.push.apply(paramsArray, _toConsumableArray(sort.split(',').map(function (sortKey) {
|
|
98
|
+
var descending = sortKey.startsWith('-');
|
|
99
|
+
var term = sortKey.replace('-', '');
|
|
100
|
+
|
|
101
|
+
if (term in sortKeys) {
|
|
102
|
+
term = term.replace(term, sortKeys[term]);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
return "sort=".concat(term, ";").concat(descending ? 'desc' : 'asc');
|
|
106
|
+
})));
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if (stats) {
|
|
110
|
+
paramsArray.push('stats=true');
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
for (var _i2 = 0, _Object$entries = Object.entries(rest); _i2 < _Object$entries.length; _i2++) {
|
|
114
|
+
var _Object$entries$_i = _slicedToArray(_Object$entries[_i2], 2),
|
|
115
|
+
key = _Object$entries$_i[0],
|
|
116
|
+
value = _Object$entries$_i[1];
|
|
117
|
+
|
|
118
|
+
paramsArray.push("".concat(key, "=").concat(value));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return paramsArray;
|
|
122
|
+
};
|
|
123
|
+
|
|
124
|
+
var _default = generateKiwtQueryParams;
|
|
125
|
+
exports["default"] = _default;
|
package/es/lib/utils/index.js
CHANGED
|
@@ -15,9 +15,25 @@ Object.defineProperty(exports, "generateKiwtQuery", {
|
|
|
15
15
|
return _generateKiwtQuery["default"];
|
|
16
16
|
}
|
|
17
17
|
});
|
|
18
|
+
Object.defineProperty(exports, "generateKiwtQueryParams", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function get() {
|
|
21
|
+
return _generateKiwtQueryParams["default"];
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "selectorSafe", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function get() {
|
|
27
|
+
return _selectorSafe["default"];
|
|
28
|
+
}
|
|
29
|
+
});
|
|
18
30
|
|
|
19
31
|
var _generateKiwtQuery = _interopRequireDefault(require("./generateKiwtQuery"));
|
|
20
32
|
|
|
33
|
+
var _generateKiwtQueryParams = _interopRequireDefault(require("./generateKiwtQueryParams"));
|
|
34
|
+
|
|
35
|
+
var _selectorSafe = _interopRequireDefault(require("./selectorSafe"));
|
|
36
|
+
|
|
21
37
|
var _buildUrl = _interopRequireDefault(require("./buildUrl"));
|
|
22
38
|
|
|
23
39
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; }
|
package/package.json
CHANGED
package/src/index.js
CHANGED
|
@@ -5,13 +5,16 @@ export {
|
|
|
5
5
|
useKiwtSASQuery,
|
|
6
6
|
useLocalStorageState,
|
|
7
7
|
useMutateRefdataValue,
|
|
8
|
+
useQIndex,
|
|
8
9
|
useRefdata,
|
|
9
10
|
useTemplates,
|
|
10
11
|
} from './lib/hooks';
|
|
11
12
|
|
|
12
13
|
// Useful utility functions
|
|
13
14
|
export {
|
|
14
|
-
generateKiwtQuery
|
|
15
|
+
generateKiwtQuery,
|
|
16
|
+
generateKiwtQueryParams,
|
|
17
|
+
selectorSafe
|
|
15
18
|
} from './lib/utils';
|
|
16
19
|
|
|
17
20
|
// Settings Components
|
|
@@ -58,3 +61,6 @@ export {
|
|
|
58
61
|
export {
|
|
59
62
|
default as SASQViewComponent
|
|
60
63
|
} from './lib/SASQViewComponent';
|
|
64
|
+
|
|
65
|
+
// NoResultsMessage
|
|
66
|
+
export { NoResultsMessage } from './lib/NoResultsMessage';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { FormattedMessage } from 'react-intl';
|
|
4
|
+
import { Button, Icon } from '@folio/stripes/components';
|
|
5
|
+
import css from '../../../styles/NoResultsMessage.css';
|
|
6
|
+
|
|
7
|
+
const NoResultsMessage = ({
|
|
8
|
+
icon: userIcon,
|
|
9
|
+
isLoading,
|
|
10
|
+
isError,
|
|
11
|
+
error,
|
|
12
|
+
filterPaneIsVisible,
|
|
13
|
+
label: userLabel,
|
|
14
|
+
searchTerm,
|
|
15
|
+
toggleFilterPane,
|
|
16
|
+
}) => {
|
|
17
|
+
let icon = 'search';
|
|
18
|
+
let label = <FormattedMessage id="stripes-smart-components.sas.noResults.default" values={{ searchTerm }} />;
|
|
19
|
+
|
|
20
|
+
// No search term but no results
|
|
21
|
+
if (!searchTerm) {
|
|
22
|
+
icon = 'search';
|
|
23
|
+
label = <FormattedMessage id="stripes-smart-components.sas.noResults.noResults" />;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Loading results
|
|
27
|
+
if (isLoading) {
|
|
28
|
+
icon = 'spinner-ellipsis';
|
|
29
|
+
label = <FormattedMessage id="stripes-smart-components.sas.noResults.loading" />;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// Request failure
|
|
33
|
+
if (isError) {
|
|
34
|
+
icon = 'exclamation-circle';
|
|
35
|
+
label = error?.message;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return (
|
|
39
|
+
<div className={css.noResultsMessage}>
|
|
40
|
+
<div className={css.noResultsMessageLabelWrap}>
|
|
41
|
+
{(icon || userIcon) &&
|
|
42
|
+
<Icon
|
|
43
|
+
icon={userIcon ?? icon}
|
|
44
|
+
iconRootClass={css.noResultsMessageIcon}
|
|
45
|
+
/>
|
|
46
|
+
}
|
|
47
|
+
<span className={css.noResultsMessageLabel}>{userLabel ?? label}</span>
|
|
48
|
+
</div>
|
|
49
|
+
{/* If the filter pane is closed we show a button that toggles filter pane */}
|
|
50
|
+
{!filterPaneIsVisible && (
|
|
51
|
+
<Button
|
|
52
|
+
buttonClass={css.noResultsMessageButton}
|
|
53
|
+
marginBottom0
|
|
54
|
+
onClick={toggleFilterPane}
|
|
55
|
+
>
|
|
56
|
+
<FormattedMessage id="stripes-kint-components.noResultsMessage.showFilters" />
|
|
57
|
+
</Button>
|
|
58
|
+
)}
|
|
59
|
+
</div>
|
|
60
|
+
);
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
NoResultsMessage.propTypes = {
|
|
64
|
+
error: PropTypes.object,
|
|
65
|
+
filterPaneIsVisible: PropTypes.bool.isRequired,
|
|
66
|
+
icon: PropTypes.string,
|
|
67
|
+
isLoading: PropTypes.bool,
|
|
68
|
+
isError: PropTypes.bool,
|
|
69
|
+
label: PropTypes.oneOfType(
|
|
70
|
+
PropTypes.string,
|
|
71
|
+
PropTypes.node,
|
|
72
|
+
PropTypes.func
|
|
73
|
+
),
|
|
74
|
+
searchTerm: PropTypes.string.isRequired,
|
|
75
|
+
toggleFilterPane: PropTypes.func.isRequired,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
export default NoResultsMessage;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default as NoResultsMessage } from './NoResultsMessage';
|
|
@@ -20,12 +20,14 @@ import {
|
|
|
20
20
|
MultiColumnList,
|
|
21
21
|
Pane,
|
|
22
22
|
PaneMenu,
|
|
23
|
-
SearchField
|
|
23
|
+
SearchField,
|
|
24
24
|
} from '@folio/stripes/components';
|
|
25
|
+
import { NoResultsMessage } from '../NoResultsMessage';
|
|
25
26
|
|
|
26
27
|
import { generateKiwtQuery } from '../utils';
|
|
27
28
|
import { useKiwtSASQuery, useLocalStorageState } from '../hooks';
|
|
28
29
|
|
|
30
|
+
|
|
29
31
|
const SASQLookupComponent = ({
|
|
30
32
|
children,
|
|
31
33
|
fetchParameters = {},
|
|
@@ -55,7 +57,15 @@ const SASQLookupComponent = ({
|
|
|
55
57
|
};
|
|
56
58
|
|
|
57
59
|
const [filterPaneVisible, setFilterPaneVisible] = useLocalStorageState(filterPaneVisibileKey, true);
|
|
58
|
-
const
|
|
60
|
+
const toggleFilterPane = () => setFilterPaneVisible(!filterPaneVisible);
|
|
61
|
+
|
|
62
|
+
const {
|
|
63
|
+
data: totalData = {},
|
|
64
|
+
error,
|
|
65
|
+
isError,
|
|
66
|
+
isLoading,
|
|
67
|
+
fetchNextPage,
|
|
68
|
+
} = useInfiniteQuery(
|
|
59
69
|
[namespace, id, 'data', query],
|
|
60
70
|
fetchPageData
|
|
61
71
|
);
|
|
@@ -88,13 +98,13 @@ const SASQLookupComponent = ({
|
|
|
88
98
|
fetchNextPage({ pageParam: index });
|
|
89
99
|
};
|
|
90
100
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
101
|
+
// Build the map of column definitions
|
|
102
|
+
const columnMapping = Object.fromEntries(
|
|
103
|
+
resultColumns.map(e => [e.propertyPath, e.label])
|
|
104
|
+
);
|
|
95
105
|
|
|
96
|
-
|
|
97
|
-
|
|
106
|
+
// Build the list of visible columns
|
|
107
|
+
const visibleColumns = resultColumns.map(e => e.propertyPath);
|
|
98
108
|
|
|
99
109
|
return (
|
|
100
110
|
<SearchAndSortQuery
|
|
@@ -126,6 +136,18 @@ const SASQLookupComponent = ({
|
|
|
126
136
|
autosize
|
|
127
137
|
columnMapping={columnMapping}
|
|
128
138
|
contentData={data?.results}
|
|
139
|
+
isEmptyMessage={
|
|
140
|
+
<NoResultsMessage
|
|
141
|
+
{...{
|
|
142
|
+
error,
|
|
143
|
+
isError,
|
|
144
|
+
isLoading,
|
|
145
|
+
filterPaneIsVisible: filterPaneVisible,
|
|
146
|
+
searchTerm: query.query,
|
|
147
|
+
toggleFilterPane
|
|
148
|
+
}}
|
|
149
|
+
/>
|
|
150
|
+
}
|
|
129
151
|
isSelected={({ item }) => item.id === match?.params?.id}
|
|
130
152
|
onHeaderClick={onSort}
|
|
131
153
|
onNeedMoreData={onNeedMoreData}
|
|
@@ -6,7 +6,7 @@ A component designed to speed up the basic 3-pane layout setup process, SASQRout
|
|
|
6
6
|
import React from 'react';
|
|
7
7
|
import { FormattedMessage } from 'react-intl';
|
|
8
8
|
|
|
9
|
-
import SASQRoute from '@k-int/stripes-kint-components
|
|
9
|
+
import { SASQRoute } from '@k-int/stripes-kint-components';
|
|
10
10
|
import ActionItem from '../components/ActionItem';
|
|
11
11
|
|
|
12
12
|
const ActionedRoute = ({ path }) => {
|
|
@@ -1,115 +1 @@
|
|
|
1
|
-
|
|
2
|
-
import React from 'react';
|
|
3
|
-
|
|
4
|
-
import { Button, Col, Pane, Row, TextField } from '@folio/stripes/components';
|
|
5
|
-
import { AppIcon } from '@folio/stripes/core';
|
|
6
|
-
import { generateKiwtQuery, TypeDown } from '@k-int/stripes-kint-components';
|
|
7
|
-
|
|
8
|
-
import { Form, Field, useFormState } from 'react-final-form';
|
|
9
|
-
|
|
10
|
-
const TestField = () => {
|
|
11
|
-
const pathMutator = (input, path) => {
|
|
12
|
-
const query = generateKiwtQuery(
|
|
13
|
-
{
|
|
14
|
-
searchKey: 'name,alternateNames.name',
|
|
15
|
-
stats: false
|
|
16
|
-
}, {
|
|
17
|
-
sort: 'name',
|
|
18
|
-
query: input,
|
|
19
|
-
}
|
|
20
|
-
);
|
|
21
|
-
|
|
22
|
-
return `${path}${query}`;
|
|
23
|
-
};
|
|
24
|
-
|
|
25
|
-
console.log("Current values: %o", useFormState()?.values)
|
|
26
|
-
return (
|
|
27
|
-
<Field
|
|
28
|
-
component={TypeDown}
|
|
29
|
-
name="test"
|
|
30
|
-
path="erm/sas"
|
|
31
|
-
pathMutator={pathMutator}
|
|
32
|
-
renderFooter={() => (
|
|
33
|
-
<>
|
|
34
|
-
<Button
|
|
35
|
-
id="footer button 1"
|
|
36
|
-
marginBottom0
|
|
37
|
-
onClick={() => {
|
|
38
|
-
alert('sup')
|
|
39
|
-
}}
|
|
40
|
-
type="button"
|
|
41
|
-
>
|
|
42
|
-
Hello 1
|
|
43
|
-
</Button>
|
|
44
|
-
<Button
|
|
45
|
-
id="footer button 2"
|
|
46
|
-
marginBottom0
|
|
47
|
-
onClick={() => {
|
|
48
|
-
alert('sup 2')
|
|
49
|
-
}}
|
|
50
|
-
type="button"
|
|
51
|
-
>
|
|
52
|
-
Hello 2
|
|
53
|
-
</Button>
|
|
54
|
-
</>
|
|
55
|
-
)}
|
|
56
|
-
renderListItem={agreement => {
|
|
57
|
-
return (
|
|
58
|
-
<>
|
|
59
|
-
<AppIcon
|
|
60
|
-
app="agreements"
|
|
61
|
-
size="small"
|
|
62
|
-
>
|
|
63
|
-
{agreement.name}
|
|
64
|
-
</AppIcon>
|
|
65
|
-
</>
|
|
66
|
-
);
|
|
67
|
-
}}
|
|
68
|
-
/>
|
|
69
|
-
);
|
|
70
|
-
};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
const TestComponent = () => {
|
|
74
|
-
return (
|
|
75
|
-
<Pane
|
|
76
|
-
defaultWidth="fill"
|
|
77
|
-
dismissible
|
|
78
|
-
id="test-typedown"
|
|
79
|
-
paneTitle={"Test typedown"}
|
|
80
|
-
>
|
|
81
|
-
<Form
|
|
82
|
-
enableReinitialize
|
|
83
|
-
navigationCheck
|
|
84
|
-
onSubmit={(values) => console.log("submitting: %o", values)}
|
|
85
|
-
subscription={{ values: true }}
|
|
86
|
-
>
|
|
87
|
-
{({ handleSubmit }) => {
|
|
88
|
-
return (
|
|
89
|
-
<form onSubmit={handleSubmit}>
|
|
90
|
-
<Row>
|
|
91
|
-
<Col xs={6}>
|
|
92
|
-
<TestField />
|
|
93
|
-
</Col>
|
|
94
|
-
<Col xs={6}>
|
|
95
|
-
<Field
|
|
96
|
-
component={TextField}
|
|
97
|
-
name="test2"
|
|
98
|
-
/>
|
|
99
|
-
</Col>
|
|
100
|
-
</Row>
|
|
101
|
-
<Button
|
|
102
|
-
type="submit"
|
|
103
|
-
>
|
|
104
|
-
submit
|
|
105
|
-
</Button>
|
|
106
|
-
</form>
|
|
107
|
-
);
|
|
108
|
-
}}
|
|
109
|
-
</Form>
|
|
110
|
-
</Pane>
|
|
111
|
-
);
|
|
112
|
-
};
|
|
113
|
-
|
|
114
|
-
export default TestComponent;
|
|
115
|
-
```
|
|
1
|
+
DEPRECATED - DO NOT USE. You probably want Typedown
|
package/src/lib/hooks/README.md
CHANGED
|
@@ -21,6 +21,7 @@ endpoint | string | The endpoint to fetch refdataValues from | | ✓ |
|
|
|
21
21
|
desc | string | The refdataCategory (usually of the form `DomainClass.Field`) | | ✕ |
|
|
22
22
|
queryParams | object | A set of queryParameters to hand to react-query's `useQuery` | | ✕ |
|
|
23
23
|
returnQueryObject | bool | A switch to return the entirety of the queryObject from useQuery. If `false`, the data will be destructured, if `true` the return will be the full object returned by react-query's `useQuery` | false | ✕ |
|
|
24
|
+
options | object | An object of the shape SASQ_MAP (See generateKiwtQuery) to pass to the generateKiwtQuery inside. Any passed desc "d" will be passed as a filter `DescKey.${d}`, with DescKey acting as FilterName, assuming `filterKeys: { DescKey: "desc" }` in options, so `desc==${d}` is passed directly to the backend. | `{filterKeys: {DescKey: "desc" }, stats: false, max: 100}` | ✕ |
|
|
24
25
|
|
|
25
26
|
## useMutateRefdataValue
|
|
26
27
|
A hook for mutations (Create/Delete/Edit) of refdataValues.
|
|
@@ -117,6 +118,8 @@ A hook which takes an object containing various helper components to render, and
|
|
|
117
118
|
When the url contains a query of the form `helper={name}`, this hook will check the helpers object it was handed for a key matching `{name}`, and if there is one it will return the component value for that key.
|
|
118
119
|
|
|
119
120
|
The hook also returns an object `helperToggleFunctions`, which will have the same keys as were handed to the hook, and values corresponding to "toggle" functions for that key. These functions are a simple way to change the helper query in the url.
|
|
121
|
+
|
|
122
|
+
Finally the hook also returns an ease-of-use function `isOpen`, which takes a string input and returns a boolean if the current helper in the URL matches that string or not.
|
|
120
123
|
### Basic usage
|
|
121
124
|
```
|
|
122
125
|
import { useHelperApp } from '@k-int/stripes-kint-components'
|
|
@@ -181,3 +184,34 @@ import { useQuery } from 'react-query';
|
|
|
181
184
|
</SearchAndSortQuery>
|
|
182
185
|
|
|
183
186
|
```
|
|
187
|
+
|
|
188
|
+
## useQIndex
|
|
189
|
+
A hook with a similar API to setState, but instead stores a value in the `qindex` parameter in the URL.
|
|
190
|
+
Returns an array `[qindex, setQindex]`. There is no way to set an initialValue with the hook, as the state is derived from the URL rather than the other way around. This means that multiple `useQIndex` hooks can exist at once.
|
|
191
|
+
|
|
192
|
+
### BasicUsage
|
|
193
|
+
```
|
|
194
|
+
import {
|
|
195
|
+
Button,
|
|
196
|
+
} from '@folio/stripes/components';
|
|
197
|
+
import useQindex from '../../../../stripes-kint-components/src/lib/hooks/useQIndex';
|
|
198
|
+
|
|
199
|
+
const Test() {
|
|
200
|
+
const [qindex, setQindex] = useQindex();
|
|
201
|
+
|
|
202
|
+
return (
|
|
203
|
+
<>
|
|
204
|
+
<Button
|
|
205
|
+
onClick={() => setQindex(qindex + "1")}
|
|
206
|
+
>
|
|
207
|
+
change the qindex
|
|
208
|
+
</Button>
|
|
209
|
+
<div>
|
|
210
|
+
{`The current qindex is: ${qindex}`
|
|
211
|
+
</div>
|
|
212
|
+
</>
|
|
213
|
+
);
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export default Test;
|
|
217
|
+
```
|
package/src/lib/hooks/index.js
CHANGED
|
@@ -5,3 +5,5 @@ export { default as useActiveElement } from './useActiveElement';
|
|
|
5
5
|
export { default as useKiwtSASQuery } from './useKiwtSASQuery';
|
|
6
6
|
export { default as useHelperApp } from './useHelperApp';
|
|
7
7
|
export { default as useLocalStorageState } from './useLocalStorageState';
|
|
8
|
+
export { default as useQIndex } from './useQIndex';
|
|
9
|
+
|
|
@@ -13,6 +13,10 @@ const useHelperApp = (helpers) => {
|
|
|
13
13
|
setCurrentHelper(helper !== currentHelper ? helper : undefined);
|
|
14
14
|
}, [currentHelper]);
|
|
15
15
|
|
|
16
|
+
const isOpen = (hlp) => {
|
|
17
|
+
return currentHelper === hlp;
|
|
18
|
+
};
|
|
19
|
+
|
|
16
20
|
useEffect(() => {
|
|
17
21
|
if (currentHelper !== query?.helper) {
|
|
18
22
|
const newQuery = {
|
|
@@ -56,7 +60,7 @@ const useHelperApp = (helpers) => {
|
|
|
56
60
|
helperToggleFunctions[h] = () => handleToggleHelper(h);
|
|
57
61
|
});
|
|
58
62
|
|
|
59
|
-
return { HelperComponent, helperToggleFunctions };
|
|
63
|
+
return { HelperComponent, helperToggleFunctions, isOpen };
|
|
60
64
|
};
|
|
61
65
|
|
|
62
66
|
export default useHelperApp;
|
|
@@ -2,6 +2,7 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import { useLocation, useHistory } from 'react-router-dom';
|
|
3
3
|
|
|
4
4
|
import buildUrl from '../utils/buildUrl';
|
|
5
|
+
import useQindex from './useQIndex';
|
|
5
6
|
|
|
6
7
|
const locationQuerySetter = ({ location, history, nsValues }) => {
|
|
7
8
|
const url = buildUrl(location, nsValues);
|
|
@@ -13,8 +14,15 @@ const useKiwtSASQuery = () => {
|
|
|
13
14
|
const location = useLocation();
|
|
14
15
|
const [query, setQuery] = useState({});
|
|
15
16
|
const queryGetter = () => query;
|
|
17
|
+
|
|
18
|
+
const [qindex] = useQindex();
|
|
19
|
+
// Ensure we update the query along with the querySetter
|
|
20
|
+
if (query.qindex !== qindex) {
|
|
21
|
+
setQuery({ ...query, qindex });
|
|
22
|
+
}
|
|
23
|
+
|
|
16
24
|
const querySetter = ({ nsValues }) => {
|
|
17
|
-
setQuery(nsValues);
|
|
25
|
+
setQuery({ ...query, ...nsValues, qindex });
|
|
18
26
|
locationQuerySetter({ location, history, nsValues });
|
|
19
27
|
};
|
|
20
28
|
return { query, queryGetter, querySetter };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import React, { useEffect, useState } from 'react';
|
|
2
|
+
import { useHistory, useLocation } from 'react-router-dom';
|
|
3
|
+
import queryString from 'query-string';
|
|
4
|
+
|
|
5
|
+
const useQIndex = () => {
|
|
6
|
+
const history = useHistory();
|
|
7
|
+
const location = useLocation();
|
|
8
|
+
|
|
9
|
+
const query = queryString.parse(location.search);
|
|
10
|
+
const [currentQindex, setCurrentQindex] = useState(query?.qindex);
|
|
11
|
+
|
|
12
|
+
const handleQindexChange = (newQindex) => {
|
|
13
|
+
setCurrentQindex(newQindex);
|
|
14
|
+
if (newQindex !== query?.qindex) {
|
|
15
|
+
const newQuery = {
|
|
16
|
+
...query,
|
|
17
|
+
qindex: newQindex
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
history.push({
|
|
21
|
+
pathname: location.pathname,
|
|
22
|
+
search: `?${queryString.stringify(newQuery)}`
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (currentQindex !== query?.qindex) {
|
|
29
|
+
setCurrentQindex(query?.qindex);
|
|
30
|
+
}
|
|
31
|
+
}, [
|
|
32
|
+
currentQindex,
|
|
33
|
+
history,
|
|
34
|
+
location,
|
|
35
|
+
query
|
|
36
|
+
]);
|
|
37
|
+
|
|
38
|
+
return [currentQindex, handleQindexChange];
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
export default useQIndex;
|
|
@@ -4,25 +4,42 @@ import PropTypes from 'prop-types';
|
|
|
4
4
|
import { useQuery } from 'react-query';
|
|
5
5
|
import { useOkapiKy } from '@folio/stripes/core';
|
|
6
6
|
|
|
7
|
+
import { generateKiwtQuery } from '../utils';
|
|
8
|
+
|
|
7
9
|
const useRefdata = ({
|
|
8
10
|
endpoint,
|
|
9
11
|
desc,
|
|
10
12
|
queryParams,
|
|
11
|
-
returnQueryObject = false
|
|
13
|
+
returnQueryObject = false,
|
|
14
|
+
options = {
|
|
15
|
+
filterKeys: {
|
|
16
|
+
DescKey: 'desc'
|
|
17
|
+
},
|
|
18
|
+
stats: false,
|
|
19
|
+
max: 100
|
|
20
|
+
}
|
|
12
21
|
}) => {
|
|
13
22
|
const ky = useOkapiKy();
|
|
14
|
-
|
|
23
|
+
|
|
24
|
+
const nsValues = {};
|
|
25
|
+
|
|
26
|
+
/* Desc will tend to contain a '.', which will throw off generateKiwtQuery.
|
|
27
|
+
* To combat this we can insert another Desc. at the beginning to act as the filtername, so
|
|
28
|
+
* Funder.Name => Desc.desc=Funder.Name. This way "Desc" acts as the filterName, and without a filterKey
|
|
29
|
+
* "desc=Funder.Name" is passed wholesale to the query.
|
|
30
|
+
*/
|
|
15
31
|
|
|
16
32
|
if (Array.isArray(desc)) {
|
|
17
33
|
// If we have an array, append a desc filter for each desc given
|
|
18
|
-
desc.
|
|
19
|
-
path += `${index === 0 ? '?filters=' : '%7C%7C'}desc=${d}`;
|
|
20
|
-
});
|
|
34
|
+
nsValues.filters = desc.map(d => `DescKey.${d}`).join(',');
|
|
21
35
|
} else if (desc) {
|
|
22
36
|
// If we just have a string, append a single desc filter
|
|
23
|
-
|
|
37
|
+
nsValues.filters = `DescKey.${desc}`;
|
|
24
38
|
}
|
|
25
39
|
|
|
40
|
+
const query = generateKiwtQuery(options, nsValues);
|
|
41
|
+
const path = `${endpoint}${query}`;
|
|
42
|
+
|
|
26
43
|
const queryObject = useQuery(
|
|
27
44
|
['stripes-kint-components', 'useRefdata', 'refdata', desc ?? ''],
|
|
28
45
|
() => ky(path).json(),
|