@k-int/stripes-kint-components 1.2.3 → 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 +15 -5
- package/es/index.js +72 -0
- package/es/lib/NoResultsMessage/NoResultsMessage.js +89 -0
- package/es/lib/NoResultsMessage/index.js +15 -0
- package/es/lib/QueryTypedown/QueryTypedown.js +71 -0
- package/es/lib/QueryTypedown/index.js +15 -0
- package/es/lib/SASQLookupComponent/SASQLookupComponent.js +295 -0
- package/es/lib/SASQLookupComponent/index.js +15 -0
- package/es/lib/SASQRoute/SASQRoute.js +70 -0
- package/es/lib/SASQRoute/index.js +15 -0
- package/es/lib/SASQViewComponent/SASQViewComponent.js +71 -0
- package/es/lib/SASQViewComponent/index.js +15 -0
- package/es/lib/TypeDown/TypeDown.js +24 -6
- package/es/lib/Typedown/Typedown.js +225 -0
- package/es/lib/Typedown/index.js +15 -0
- package/es/lib/hooks/index.js +16 -0
- package/es/lib/hooks/typedownHooks/useTypedown.js +5 -1
- package/es/lib/hooks/useHelperApp.js +7 -1
- package/es/lib/hooks/useKiwtSASQuery.js +22 -1
- package/es/lib/hooks/useLocalStorageState.js +49 -0
- package/es/lib/hooks/useQIndex.js +75 -0
- package/es/lib/hooks/useRefdata.js +23 -6
- package/es/lib/utils/generateKiwtQuery.js +3 -93
- package/es/lib/utils/generateKiwtQueryParams.js +125 -0
- package/es/lib/utils/index.js +16 -0
- package/es/lib/utils/selectorSafe.js +1 -1
- package/package.json +1 -1
- package/src/index.js +31 -1
- package/src/lib/EditableRefdataList/README.md +1 -1
- package/src/lib/NoResultsMessage/NoResultsMessage.js +78 -0
- package/src/lib/NoResultsMessage/index.js +1 -0
- package/src/lib/QueryTypedown/QueryTypedown.js +33 -0
- package/src/lib/QueryTypedown/index.js +1 -0
- package/src/lib/SASQLookupComponent/SASQLookupComponent.js +282 -0
- package/src/lib/SASQLookupComponent/index.js +1 -0
- package/src/lib/SASQRoute/README.md +55 -0
- package/src/lib/SASQRoute/SASQRoute.js +63 -0
- package/src/lib/SASQRoute/index.js +1 -0
- package/src/lib/SASQViewComponent/SASQViewComponent.js +55 -0
- package/src/lib/SASQViewComponent/index.js +1 -0
- package/src/lib/TypeDown/README.md +1 -0
- package/src/lib/TypeDown/TypeDown.js +23 -4
- package/src/lib/Typedown/README.md +115 -0
- package/src/lib/Typedown/Typedown.js +234 -0
- package/src/lib/Typedown/index.js +1 -0
- package/src/lib/hooks/README.md +35 -1
- package/src/lib/hooks/index.js +3 -0
- package/src/lib/hooks/typedownHooks/useTypedown.js +3 -1
- package/src/lib/hooks/useHelperApp.js +5 -1
- package/src/lib/hooks/useKiwtSASQuery.js +9 -1
- package/src/lib/hooks/useLocalStorageState.js +17 -0
- 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 -57
- package/src/lib/utils/generateKiwtQueryParams.js +67 -0
- package/src/lib/utils/index.js +3 -0
- package/src/lib/utils/selectorSafe.js +1 -1
- package/styles/NoResultsMessage.css +38 -0
- package/translations/stripes-kint-components/en.json +5 -1
|
@@ -0,0 +1,282 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
import { FormattedMessage } from 'react-intl';
|
|
4
|
+
import { useInfiniteQuery } from 'react-query';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
useNamespace,
|
|
8
|
+
useOkapiKy
|
|
9
|
+
} from '@folio/stripes/core';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
SearchAndSortQuery,
|
|
13
|
+
PersistedPaneset,
|
|
14
|
+
} from '@folio/stripes/smart-components';
|
|
15
|
+
|
|
16
|
+
import {
|
|
17
|
+
Button,
|
|
18
|
+
IconButton,
|
|
19
|
+
Icon,
|
|
20
|
+
MultiColumnList,
|
|
21
|
+
Pane,
|
|
22
|
+
PaneMenu,
|
|
23
|
+
SearchField,
|
|
24
|
+
} from '@folio/stripes/components';
|
|
25
|
+
import { NoResultsMessage } from '../NoResultsMessage';
|
|
26
|
+
|
|
27
|
+
import { generateKiwtQuery } from '../utils';
|
|
28
|
+
import { useKiwtSASQuery, useLocalStorageState } from '../hooks';
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
const SASQLookupComponent = ({
|
|
32
|
+
children,
|
|
33
|
+
fetchParameters = {},
|
|
34
|
+
FilterComponent = () => null,
|
|
35
|
+
history,
|
|
36
|
+
id,
|
|
37
|
+
location,
|
|
38
|
+
mainPaneProps,
|
|
39
|
+
match,
|
|
40
|
+
mclProps,
|
|
41
|
+
noSearchField,
|
|
42
|
+
path,
|
|
43
|
+
resultColumns = [],
|
|
44
|
+
RenderBody,
|
|
45
|
+
sasqProps,
|
|
46
|
+
}) => {
|
|
47
|
+
const { query, queryGetter, querySetter } = useKiwtSASQuery();
|
|
48
|
+
const { 0: namespace } = useNamespace();
|
|
49
|
+
const ky = useOkapiKy();
|
|
50
|
+
|
|
51
|
+
const filterPaneVisibileKey = `${namespace}-${id}-filterPaneVisibility`;
|
|
52
|
+
|
|
53
|
+
const fetchPageData = ({ pageParam = 0 }) => {
|
|
54
|
+
const queryMap = fetchParameters.SASQ_MAP;
|
|
55
|
+
queryMap.offset = pageParam;
|
|
56
|
+
return ky(`${fetchParameters.endpoint}${generateKiwtQuery(queryMap, query)}`).json();
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const [filterPaneVisible, setFilterPaneVisible] = useLocalStorageState(filterPaneVisibileKey, true);
|
|
60
|
+
const toggleFilterPane = () => setFilterPaneVisible(!filterPaneVisible);
|
|
61
|
+
|
|
62
|
+
const {
|
|
63
|
+
data: totalData = {},
|
|
64
|
+
error,
|
|
65
|
+
isError,
|
|
66
|
+
isLoading,
|
|
67
|
+
fetchNextPage,
|
|
68
|
+
} = useInfiniteQuery(
|
|
69
|
+
[namespace, id, 'data', query],
|
|
70
|
+
fetchPageData
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const data = totalData.pages?.reduce(
|
|
74
|
+
(acc, curr) => {
|
|
75
|
+
const newAcc = { ...acc };
|
|
76
|
+
for (const [key, value] of Object.entries(curr)) {
|
|
77
|
+
if (
|
|
78
|
+
key !== 'page' &&
|
|
79
|
+
key !== 'result' &&
|
|
80
|
+
acc[key] !== value
|
|
81
|
+
) {
|
|
82
|
+
newAcc[key] = value;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
const newResults = [...(acc.results ?? [])];
|
|
87
|
+
newResults.push(...(curr.results ?? []));
|
|
88
|
+
newAcc.results = newResults;
|
|
89
|
+
|
|
90
|
+
return newAcc;
|
|
91
|
+
},
|
|
92
|
+
{}
|
|
93
|
+
) ?? {};
|
|
94
|
+
|
|
95
|
+
// TODO focus handling to stop redraw movin to top
|
|
96
|
+
|
|
97
|
+
const onNeedMoreData = (_askAmount, index) => {
|
|
98
|
+
fetchNextPage({ pageParam: index });
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
// Build the map of column definitions
|
|
102
|
+
const columnMapping = Object.fromEntries(
|
|
103
|
+
resultColumns.map(e => [e.propertyPath, e.label])
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
// Build the list of visible columns
|
|
107
|
+
const visibleColumns = resultColumns.map(e => e.propertyPath);
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<SearchAndSortQuery
|
|
111
|
+
initialSearchState={{ query: '' }}
|
|
112
|
+
queryGetter={queryGetter}
|
|
113
|
+
querySetter={querySetter}
|
|
114
|
+
{...sasqProps}
|
|
115
|
+
>
|
|
116
|
+
{
|
|
117
|
+
({
|
|
118
|
+
activeFilters,
|
|
119
|
+
filterChanged,
|
|
120
|
+
getFilterHandlers,
|
|
121
|
+
getSearchHandlers,
|
|
122
|
+
onSort,
|
|
123
|
+
onSubmitSearch,
|
|
124
|
+
resetAll,
|
|
125
|
+
searchChanged,
|
|
126
|
+
searchValue
|
|
127
|
+
}) => {
|
|
128
|
+
const searchHandlers = getSearchHandlers();
|
|
129
|
+
const sortOrder = query.sort ?? '';
|
|
130
|
+
const disableReset = !filterChanged && !searchChanged;
|
|
131
|
+
|
|
132
|
+
const filterCount = activeFilters.string ? activeFilters.string.split(',').length : 0;
|
|
133
|
+
|
|
134
|
+
const TableBody = () => (
|
|
135
|
+
<MultiColumnList
|
|
136
|
+
autosize
|
|
137
|
+
columnMapping={columnMapping}
|
|
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
|
+
}
|
|
151
|
+
isSelected={({ item }) => item.id === match?.params?.id}
|
|
152
|
+
onHeaderClick={onSort}
|
|
153
|
+
onNeedMoreData={onNeedMoreData}
|
|
154
|
+
onRowClick={(_e, rowData) => {
|
|
155
|
+
history.push(`${path}/${rowData?.id}${location?.search}`);
|
|
156
|
+
}}
|
|
157
|
+
pagingType="click"
|
|
158
|
+
sortDirection={sortOrder.startsWith('-') ? 'descending' : 'ascending'}
|
|
159
|
+
sortOrder={sortOrder.replace(/^-/, '').replace(/,.*/, '')}
|
|
160
|
+
totalCount={data.totalRecords}
|
|
161
|
+
virtualize
|
|
162
|
+
visibleColumns={visibleColumns}
|
|
163
|
+
{...mclProps}
|
|
164
|
+
/>
|
|
165
|
+
);
|
|
166
|
+
|
|
167
|
+
const Body = RenderBody ?? TableBody;
|
|
168
|
+
|
|
169
|
+
return (
|
|
170
|
+
<PersistedPaneset
|
|
171
|
+
appId={namespace}
|
|
172
|
+
id={`${id}-paneset`}
|
|
173
|
+
>
|
|
174
|
+
{filterPaneVisible &&
|
|
175
|
+
<Pane
|
|
176
|
+
defaultWidth="20%"
|
|
177
|
+
lastMenu={
|
|
178
|
+
<PaneMenu>
|
|
179
|
+
<IconButton
|
|
180
|
+
icon="caret-left"
|
|
181
|
+
onClick={() => setFilterPaneVisible(false)}
|
|
182
|
+
/>
|
|
183
|
+
</PaneMenu>
|
|
184
|
+
}
|
|
185
|
+
paneTitle={<FormattedMessage id="stripes-smart-components.searchAndFilter" />}
|
|
186
|
+
>
|
|
187
|
+
<form onSubmit={onSubmitSearch}>
|
|
188
|
+
{!noSearchField &&
|
|
189
|
+
<>
|
|
190
|
+
<SearchField
|
|
191
|
+
autoFocus
|
|
192
|
+
name="query"
|
|
193
|
+
onChange={searchHandlers.query}
|
|
194
|
+
onClear={searchHandlers.reset}
|
|
195
|
+
value={searchValue.query}
|
|
196
|
+
/>
|
|
197
|
+
<Button
|
|
198
|
+
buttonStyle="primary"
|
|
199
|
+
disabled={!searchValue.query}
|
|
200
|
+
fullWidth
|
|
201
|
+
type="submit"
|
|
202
|
+
>
|
|
203
|
+
<FormattedMessage id="stripes-smart-components.search" />
|
|
204
|
+
</Button>
|
|
205
|
+
<Button
|
|
206
|
+
buttonStyle="none"
|
|
207
|
+
disabled={disableReset}
|
|
208
|
+
id="clickable-reset-all"
|
|
209
|
+
onClick={resetAll}
|
|
210
|
+
>
|
|
211
|
+
<Icon icon="times-circle-solid">
|
|
212
|
+
<FormattedMessage id="stripes-smart-components.resetAll" />
|
|
213
|
+
</Icon>
|
|
214
|
+
</Button>
|
|
215
|
+
</>
|
|
216
|
+
}
|
|
217
|
+
<FilterComponent
|
|
218
|
+
activeFilters={activeFilters.state}
|
|
219
|
+
filterChanged={filterChanged}
|
|
220
|
+
filterHandlers={getFilterHandlers()}
|
|
221
|
+
resetAll={resetAll}
|
|
222
|
+
searchChanged={searchChanged}
|
|
223
|
+
searchHandlers={getSearchHandlers()}
|
|
224
|
+
searchValue={searchValue}
|
|
225
|
+
/>
|
|
226
|
+
</form>
|
|
227
|
+
</Pane>
|
|
228
|
+
}
|
|
229
|
+
<Pane
|
|
230
|
+
defaultWidth="fill"
|
|
231
|
+
firstMenu={!filterPaneVisible ?
|
|
232
|
+
<PaneMenu>
|
|
233
|
+
<IconButton
|
|
234
|
+
badgeCount={filterCount}
|
|
235
|
+
icon="caret-right"
|
|
236
|
+
onClick={() => setFilterPaneVisible(true)}
|
|
237
|
+
/>
|
|
238
|
+
</PaneMenu>
|
|
239
|
+
:
|
|
240
|
+
null}
|
|
241
|
+
paneSub={<FormattedMessage id="stripes-kint-components.sasqLookupComponent.mainPane.found" values={{ total: data?.total }} />}
|
|
242
|
+
{...mainPaneProps}
|
|
243
|
+
>
|
|
244
|
+
<Body data={data} />
|
|
245
|
+
</Pane>
|
|
246
|
+
{children}
|
|
247
|
+
</PersistedPaneset>
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
</SearchAndSortQuery>
|
|
252
|
+
);
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
SASQLookupComponent.propTypes = {
|
|
256
|
+
children: PropTypes.oneOfType([
|
|
257
|
+
PropTypes.func,
|
|
258
|
+
PropTypes.node
|
|
259
|
+
]),
|
|
260
|
+
fetchParameters: PropTypes.object,
|
|
261
|
+
FilterComponent: PropTypes.oneOfType([
|
|
262
|
+
PropTypes.func,
|
|
263
|
+
PropTypes.node
|
|
264
|
+
]),
|
|
265
|
+
history: PropTypes.object,
|
|
266
|
+
id: PropTypes.string.isRequired,
|
|
267
|
+
location: PropTypes.object,
|
|
268
|
+
mainPaneProps: PropTypes.object,
|
|
269
|
+
match: PropTypes.object,
|
|
270
|
+
mclProps: PropTypes.object,
|
|
271
|
+
noSearchField: PropTypes.bool,
|
|
272
|
+
path: PropTypes.string.isRequired,
|
|
273
|
+
RenderBody: PropTypes.oneOfType([
|
|
274
|
+
PropTypes.func,
|
|
275
|
+
PropTypes.node
|
|
276
|
+
]),
|
|
277
|
+
resource: PropTypes.object,
|
|
278
|
+
resultColumns: PropTypes.arrayOf(PropTypes.object),
|
|
279
|
+
sasqProps: PropTypes.object
|
|
280
|
+
};
|
|
281
|
+
|
|
282
|
+
export default SASQLookupComponent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './SASQLookupComponent';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# SASQRoute
|
|
2
|
+
A component designed to speed up the basic 3-pane layout setup process, SASQRoute is an all in one Routing, SASQ and MCL setup
|
|
3
|
+
|
|
4
|
+
## Basic Usage
|
|
5
|
+
```
|
|
6
|
+
import React from 'react';
|
|
7
|
+
import { FormattedMessage } from 'react-intl';
|
|
8
|
+
|
|
9
|
+
import { SASQRoute } from '@k-int/stripes-kint-components';
|
|
10
|
+
import ActionItem from '../components/ActionItem';
|
|
11
|
+
|
|
12
|
+
const ActionedRoute = ({ path }) => {
|
|
13
|
+
|
|
14
|
+
const fetchParameters = {
|
|
15
|
+
endpoint: "remote-sync/feedback/done",
|
|
16
|
+
itemEndpoint: "remote-sync/feedback",
|
|
17
|
+
SASQ_MAP: {
|
|
18
|
+
searchKey: 'description',
|
|
19
|
+
filterKeys: {
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
const resultColumns = [
|
|
25
|
+
{ propertyPath: "selected", label: " " },
|
|
26
|
+
{ propertyPath:"description", label: <FormattedMessage id="ui-remote-sync.prop.feedback.description" /> },
|
|
27
|
+
{ propertyPath:"status", label: <FormattedMessage id="ui-remote-sync.prop.feedback.status" /> },
|
|
28
|
+
{ propertyPath:"correlationId", label: <FormattedMessage id="ui-remote-sync.prop.feedback.correlationId" /> },
|
|
29
|
+
{ propertyPath:"caseIndicator", label: <FormattedMessage id="ui-remote-sync.prop.feedback.caseIndicator" /> }
|
|
30
|
+
];
|
|
31
|
+
|
|
32
|
+
return (
|
|
33
|
+
<SASQRoute
|
|
34
|
+
fetchParameters={fetchParameters}
|
|
35
|
+
id="actioned"
|
|
36
|
+
resultColumns={resultColumns}
|
|
37
|
+
path={path}
|
|
38
|
+
ViewComponent={ActionItem}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
NOTE - The following prop list is incomplete
|
|
45
|
+
## Props
|
|
46
|
+
|
|
47
|
+
Name | Type | Description | default | required
|
|
48
|
+
--- | --- | --- | --- | ---
|
|
49
|
+
fetchParameters | object | An object containing the parameters needed to make the fetches necessary for both the table and the view components. `endpoint` contains the main fetch endpoint, which regularly will be used for both fetching all data, and also for fetching an individual item (It is assumed that this endpoint will have `/{id}` appended to it.) If `itemEndpoint` is provided that will be used instead (this will also have `/{:id}` appended to it). `SASQ_MAP` is an object of the shape taken by `generateKiwtQuery` | | ✓ |
|
|
50
|
+
id | string | A unique identifier for this route. IMPORTANT that this is unique, as it drives paneset logic | | ✓ |
|
|
51
|
+
path | string | The main path for this route. In the above example the path is `remote-sync/actioned`. This component will set up the main 3 pane layout under this path, and also the view pane route under `remote-sync/actioned/:id` | | ✓ |
|
|
52
|
+
resultColumns | array | An array containing objects with a `propertyPath` and `label`. These will be used to drive the MCL columns. | | ✓ |
|
|
53
|
+
ViewComponent | Element | The component to render on clicking a row entry. | | ✓ |
|
|
54
|
+
|
|
55
|
+
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
Route
|
|
6
|
+
} from 'react-router-dom';
|
|
7
|
+
|
|
8
|
+
import SASQLookupComponent from '../SASQLookupComponent';
|
|
9
|
+
import SASQViewComponent from '../SASQViewComponent';
|
|
10
|
+
|
|
11
|
+
const SASQRoute = ({ path, fetchParameters, ...props }) => {
|
|
12
|
+
// Grab the SASQ_MAP and tweak it
|
|
13
|
+
const { SASQ_MAP = {} } = fetchParameters;
|
|
14
|
+
|
|
15
|
+
if (!SASQ_MAP.perPage) {
|
|
16
|
+
SASQ_MAP.perPage = 25;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
SASQ_MAP.stats = true;
|
|
20
|
+
|
|
21
|
+
// Reinsert the SASQ_MAP
|
|
22
|
+
fetchParameters.SASQ_MAP = SASQ_MAP;
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<Route
|
|
26
|
+
path={`${path}/:id?`}
|
|
27
|
+
render={routeProps => {
|
|
28
|
+
return (
|
|
29
|
+
<SASQLookupComponent
|
|
30
|
+
{...routeProps}
|
|
31
|
+
fetchParameters={fetchParameters}
|
|
32
|
+
path={path}
|
|
33
|
+
{...props}
|
|
34
|
+
>
|
|
35
|
+
<Route
|
|
36
|
+
path={`${path}/:id`}
|
|
37
|
+
render={innerProps => (
|
|
38
|
+
<SASQViewComponent
|
|
39
|
+
{...innerProps}
|
|
40
|
+
fetchParameters={fetchParameters}
|
|
41
|
+
path={path}
|
|
42
|
+
ViewComponent={props.ViewComponent}
|
|
43
|
+
{...props}
|
|
44
|
+
/>
|
|
45
|
+
)}
|
|
46
|
+
/>
|
|
47
|
+
</SASQLookupComponent>
|
|
48
|
+
);
|
|
49
|
+
}}
|
|
50
|
+
/>
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
SASQRoute.propTypes = {
|
|
55
|
+
fetchParameters: PropTypes.object,
|
|
56
|
+
path: PropTypes.string,
|
|
57
|
+
ViewComponent: PropTypes.oneOfType([
|
|
58
|
+
PropTypes.func,
|
|
59
|
+
PropTypes.node
|
|
60
|
+
])
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
export default SASQRoute;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './SASQRoute';
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import PropTypes from 'prop-types';
|
|
3
|
+
|
|
4
|
+
import { useQuery } from 'react-query';
|
|
5
|
+
|
|
6
|
+
import {
|
|
7
|
+
useNamespace,
|
|
8
|
+
useOkapiKy
|
|
9
|
+
} from '@folio/stripes/core';
|
|
10
|
+
|
|
11
|
+
const SASQViewComponent = ({
|
|
12
|
+
fetchParameters,
|
|
13
|
+
history,
|
|
14
|
+
location,
|
|
15
|
+
match,
|
|
16
|
+
path,
|
|
17
|
+
ViewComponent,
|
|
18
|
+
...props
|
|
19
|
+
}) => {
|
|
20
|
+
const { 0: namespace } = useNamespace();
|
|
21
|
+
|
|
22
|
+
// If itemEndpoint is available, use that, otherwise use standard endpoint
|
|
23
|
+
const endpoint = fetchParameters?.itemEndpoint ?? fetchParameters?.endpoint;
|
|
24
|
+
|
|
25
|
+
const ky = useOkapiKy();
|
|
26
|
+
const { data = {} } = useQuery(
|
|
27
|
+
[namespace, 'data', 'view', match?.params?.id],
|
|
28
|
+
() => ky(`${endpoint}/${match?.params?.id}`).json(),
|
|
29
|
+
{
|
|
30
|
+
enabled: !!match?.params?.id
|
|
31
|
+
}
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
return (
|
|
35
|
+
<ViewComponent
|
|
36
|
+
onClose={() => history.push(`${path}${location.search}`)}
|
|
37
|
+
resource={data}
|
|
38
|
+
{...props}
|
|
39
|
+
/>
|
|
40
|
+
);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
SASQViewComponent.propTypes = {
|
|
44
|
+
fetchParameters: PropTypes.object,
|
|
45
|
+
history: PropTypes.object,
|
|
46
|
+
location: PropTypes.object,
|
|
47
|
+
match: PropTypes.object,
|
|
48
|
+
path: PropTypes.string.isRequired,
|
|
49
|
+
ViewComponent: PropTypes.oneOfType([
|
|
50
|
+
PropTypes.func,
|
|
51
|
+
PropTypes.node
|
|
52
|
+
]),
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default SASQViewComponent;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { default } from './SASQViewComponent';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
DEPRECATED - DO NOT USE. You probably want Typedown
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, { useCallback, useState } from 'react';
|
|
1
|
+
import React, { useCallback, useEffect, useState } from 'react';
|
|
2
2
|
import PropTypes from 'prop-types';
|
|
3
3
|
import classnames from 'classnames';
|
|
4
4
|
|
|
@@ -15,15 +15,25 @@ import css from '../../../styles/TypeDown.css';
|
|
|
15
15
|
import { useTypedown, useTypedownData } from '../hooks/typedownHooks';
|
|
16
16
|
import selectorSafe from '../utils/selectorSafe';
|
|
17
17
|
|
|
18
|
+
/* @deprecated
|
|
19
|
+
* Replaced by Typedown and QueryTypedown.
|
|
20
|
+
*/
|
|
18
21
|
const TypeDown = ({
|
|
19
22
|
input,
|
|
20
23
|
meta,
|
|
24
|
+
onChange,
|
|
21
25
|
path,
|
|
22
26
|
pathMutator,
|
|
23
27
|
renderFooter = null,
|
|
24
28
|
renderListItem = null,
|
|
25
29
|
uniqueIdentificationPath = 'id'
|
|
26
30
|
}) => {
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
if (process.env.NODE_ENV === 'development') {
|
|
33
|
+
console.warn('TypeDown component is deprecated, you likely want either Typedown or QueryTypedown');
|
|
34
|
+
}
|
|
35
|
+
}, []);
|
|
36
|
+
|
|
27
37
|
const selectedUniqueId = get(input.value, uniqueIdentificationPath);
|
|
28
38
|
|
|
29
39
|
const [callPath, setCallPath] = useState(pathMutator(null, path));
|
|
@@ -61,6 +71,14 @@ const TypeDown = ({
|
|
|
61
71
|
</div>
|
|
62
72
|
), [renderListItem, uniqueIdentificationPath]);
|
|
63
73
|
|
|
74
|
+
const handleChange = value => {
|
|
75
|
+
input.onChange(value);
|
|
76
|
+
|
|
77
|
+
if (typeof onChange === 'function') {
|
|
78
|
+
onChange(value);
|
|
79
|
+
}
|
|
80
|
+
};
|
|
81
|
+
|
|
64
82
|
const dropDown = useCallback(() => {
|
|
65
83
|
return (
|
|
66
84
|
<div
|
|
@@ -86,7 +104,7 @@ const TypeDown = ({
|
|
|
86
104
|
data-selected={isSelected}
|
|
87
105
|
id={`typedown-button-[${index}]`}
|
|
88
106
|
onClick={() => {
|
|
89
|
-
|
|
107
|
+
handleChange(d);
|
|
90
108
|
handleNextFocus();
|
|
91
109
|
}}
|
|
92
110
|
onKeyDown={listKeyDownHandler}
|
|
@@ -132,9 +150,9 @@ const TypeDown = ({
|
|
|
132
150
|
>
|
|
133
151
|
<SearchField
|
|
134
152
|
// Pass meta through so correct styling gets applied to the TextField
|
|
135
|
-
{...meta}
|
|
136
153
|
id="typedown-searchField"
|
|
137
154
|
marginBottom0
|
|
155
|
+
meta={meta}
|
|
138
156
|
onChange={e => {
|
|
139
157
|
setCallPath(pathMutator(e.target.value, path));
|
|
140
158
|
}}
|
|
@@ -186,7 +204,7 @@ const TypeDown = ({
|
|
|
186
204
|
<IconButton
|
|
187
205
|
className={css.clearItem}
|
|
188
206
|
icon="times-circle-solid"
|
|
189
|
-
onClick={() =>
|
|
207
|
+
onClick={() => handleChange()}
|
|
190
208
|
/>
|
|
191
209
|
</div>
|
|
192
210
|
}
|
|
@@ -197,6 +215,7 @@ const TypeDown = ({
|
|
|
197
215
|
TypeDown.propTypes = {
|
|
198
216
|
input: PropTypes.object,
|
|
199
217
|
meta: PropTypes.object,
|
|
218
|
+
onChange: PropTypes.func,
|
|
200
219
|
path: PropTypes.string,
|
|
201
220
|
pathMutator: PropTypes.func,
|
|
202
221
|
renderFooter: PropTypes.func,
|
|
@@ -0,0 +1,115 @@
|
|
|
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
|
+
```
|