@uncinc/uncinc-react-kitchen-sink 2.1.5 → 2.1.6
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/dist/components/ApiAutocomplete/index.js +21 -1
- package/dist/components/ApiAutocomplete/stories.js +20 -0
- package/dist/components/Form/Checkbox/index.js +10 -2
- package/dist/components/Form/Checkbox/stories.js +3 -0
- package/dist/components/Form/Select/Input/index.js +4 -4
- package/dist/components/Form/Select/stories.js +8 -1
- package/dist/components/SearchKit/Facets/HierarchicalFilterFacet/index.js +62 -0
- package/dist/components/SearchKit/Facets/HierarchicalMenuFacet/index.js +62 -0
- package/dist/components/SearchKit/Query/index.js +8 -2
- package/dist/components/SearchKit/SearchFacets/index.js +3 -1
- package/dist/components/SearchKit/SearchPage/index.js +47 -1
- package/dist/components/SearchKit/SearchSelectedFilters/index.js +2 -1
- package/dist/components/SearchKit/index.js +5 -2
- package/dist/components/SearchKit/stories.js +15 -0
- package/package.json +1 -1
|
@@ -2,6 +2,19 @@ import React, { useState } from 'react';
|
|
|
2
2
|
import Autosuggest from 'react-autosuggest';
|
|
3
3
|
import './style.scss';
|
|
4
4
|
|
|
5
|
+
function abortableFetch(request, opts) {
|
|
6
|
+
const controller = new AbortController();
|
|
7
|
+
const signal = controller.signal;
|
|
8
|
+
return {
|
|
9
|
+
abort: () => controller.abort(),
|
|
10
|
+
ready: fetch(request, { ...opts,
|
|
11
|
+
signal
|
|
12
|
+
})
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let currentFetch = null;
|
|
17
|
+
|
|
5
18
|
const ApiAutocomplete = ({
|
|
6
19
|
endpoint,
|
|
7
20
|
placeholder,
|
|
@@ -16,7 +29,13 @@ const ApiAutocomplete = ({
|
|
|
16
29
|
|
|
17
30
|
const getSuggestions = query => {
|
|
18
31
|
const url = `${endpoint}?${queryParameter}=${query}`;
|
|
19
|
-
|
|
32
|
+
|
|
33
|
+
if (currentFetch) {
|
|
34
|
+
currentFetch.abort();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
currentFetch = abortableFetch(url);
|
|
38
|
+
currentFetch.ready.then(response => {
|
|
20
39
|
return response.json();
|
|
21
40
|
}).then(response => {
|
|
22
41
|
const ajaxResults = response.map((item, index) => {
|
|
@@ -24,6 +43,7 @@ const ApiAutocomplete = ({
|
|
|
24
43
|
return item;
|
|
25
44
|
});
|
|
26
45
|
setResults(ajaxResults);
|
|
46
|
+
}).catch(e => {// Catch the error so the browser does not output errors.
|
|
27
47
|
});
|
|
28
48
|
};
|
|
29
49
|
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import ApiAutocomplete from './';
|
|
3
|
+
export default {
|
|
4
|
+
title: 'Organisms/Autocomplete'
|
|
5
|
+
};
|
|
6
|
+
export const Default = () => {
|
|
7
|
+
return /*#__PURE__*/React.createElement(ApiAutocomplete, {
|
|
8
|
+
endpoint: "http://nldoet.devinc.eu/autocomplete/json",
|
|
9
|
+
renderItem: item => {
|
|
10
|
+
console.log(item);
|
|
11
|
+
return /*#__PURE__*/React.createElement("div", null, item.name);
|
|
12
|
+
},
|
|
13
|
+
onSelectItem: item => {
|
|
14
|
+
console.log('Selected', item);
|
|
15
|
+
},
|
|
16
|
+
inputProps: {
|
|
17
|
+
label: 'test'
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
};
|
|
@@ -17,7 +17,8 @@ const Checkbox = props => {
|
|
|
17
17
|
touched,
|
|
18
18
|
error,
|
|
19
19
|
value,
|
|
20
|
-
displayRequiredIndicator
|
|
20
|
+
displayRequiredIndicator,
|
|
21
|
+
onChange
|
|
21
22
|
} = props;
|
|
22
23
|
return /*#__PURE__*/React.createElement(GenericFormElement, {
|
|
23
24
|
className: "Checkbox",
|
|
@@ -49,9 +50,16 @@ const Checkbox = props => {
|
|
|
49
50
|
name: fieldName,
|
|
50
51
|
type: "checkbox",
|
|
51
52
|
id: id,
|
|
52
|
-
checked: field.value
|
|
53
|
+
checked: field.value,
|
|
54
|
+
onChange: e => {
|
|
55
|
+
field.onChange(e);
|
|
56
|
+
onChange(!field.value);
|
|
57
|
+
}
|
|
53
58
|
})), title);
|
|
54
59
|
}));
|
|
55
60
|
};
|
|
56
61
|
|
|
62
|
+
Checkbox.defaultProps = {
|
|
63
|
+
onChange: () => {}
|
|
64
|
+
};
|
|
57
65
|
export default withMapping(Checkbox);
|
|
@@ -56,15 +56,15 @@ const SelectInput = props => {
|
|
|
56
56
|
if (e) {
|
|
57
57
|
if (onChange) {
|
|
58
58
|
onChange(e.value);
|
|
59
|
-
} else {
|
|
60
|
-
form.setFieldValue(fieldName, e.value);
|
|
61
59
|
}
|
|
60
|
+
|
|
61
|
+
form.setFieldValue(fieldName, e.value);
|
|
62
62
|
} else {
|
|
63
63
|
if (onChange) {
|
|
64
64
|
onChange('');
|
|
65
|
-
} else {
|
|
66
|
-
form.setFieldValue(fieldName, null);
|
|
67
65
|
}
|
|
66
|
+
|
|
67
|
+
form.setFieldValue(fieldName, null);
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
70
|
options: optionsTransformed,
|
|
@@ -5,7 +5,11 @@ export default {
|
|
|
5
5
|
title: 'Molecules/Form'
|
|
6
6
|
};
|
|
7
7
|
export const Select = () => {
|
|
8
|
-
return /*#__PURE__*/React.createElement(FormikWrapper,
|
|
8
|
+
return /*#__PURE__*/React.createElement(FormikWrapper, {
|
|
9
|
+
initialValues: {
|
|
10
|
+
poison: 'beer'
|
|
11
|
+
}
|
|
12
|
+
}, /*#__PURE__*/React.createElement(FormikSelect, {
|
|
9
13
|
title: "Pick your poison",
|
|
10
14
|
required: true,
|
|
11
15
|
description: "This is a test input.",
|
|
@@ -25,6 +29,9 @@ export const Select = () => {
|
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
return error;
|
|
32
|
+
},
|
|
33
|
+
onChange: e => {
|
|
34
|
+
console.log(e);
|
|
28
35
|
}
|
|
29
36
|
}));
|
|
30
37
|
};
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { Fragment, useRef } from 'react';
|
|
2
|
+
import { EuiFacetGroup, EuiTitle, EuiFacetButton } from '@elastic/eui';
|
|
3
|
+
import { useSearchkit, FilterLink } from '@searchkit/client';
|
|
4
|
+
|
|
5
|
+
const EntriesList = ({
|
|
6
|
+
entries,
|
|
7
|
+
loading,
|
|
8
|
+
facet
|
|
9
|
+
}) => {
|
|
10
|
+
console.log('entries', entries);
|
|
11
|
+
const api = useSearchkit();
|
|
12
|
+
const entriesElements = entries.map(entry => {
|
|
13
|
+
const ref = useRef();
|
|
14
|
+
return /*#__PURE__*/React.createElement(Fragment, {
|
|
15
|
+
key: entry.label
|
|
16
|
+
}, /*#__PURE__*/React.createElement(EuiFacetButton, {
|
|
17
|
+
style: {
|
|
18
|
+
height: '28px',
|
|
19
|
+
marginTop: 0,
|
|
20
|
+
marginBottom: 0
|
|
21
|
+
},
|
|
22
|
+
quantity: entry.count,
|
|
23
|
+
isSelected: api.isFilterSelected({
|
|
24
|
+
identifier: facet.identifier,
|
|
25
|
+
value: entry.label,
|
|
26
|
+
level: entry.level
|
|
27
|
+
}),
|
|
28
|
+
isLoading: loading,
|
|
29
|
+
onClick: e => {
|
|
30
|
+
ref.current.onClick(e);
|
|
31
|
+
}
|
|
32
|
+
}, /*#__PURE__*/React.createElement(FilterLink, {
|
|
33
|
+
ref: ref,
|
|
34
|
+
filter: {
|
|
35
|
+
identifier: facet.identifier,
|
|
36
|
+
value: entry.label,
|
|
37
|
+
level: entry.level
|
|
38
|
+
}
|
|
39
|
+
}, entry.label)), /*#__PURE__*/React.createElement("div", {
|
|
40
|
+
style: {
|
|
41
|
+
marginLeft: '10px'
|
|
42
|
+
}
|
|
43
|
+
}, entry.entries && /*#__PURE__*/React.createElement(EntriesList, {
|
|
44
|
+
entries: entry.entries,
|
|
45
|
+
loading: loading,
|
|
46
|
+
facet: facet
|
|
47
|
+
})));
|
|
48
|
+
});
|
|
49
|
+
return /*#__PURE__*/React.createElement(EuiFacetGroup, null, entriesElements);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const HierarchicalFilterFacet = ({
|
|
53
|
+
facet,
|
|
54
|
+
loading
|
|
55
|
+
}) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EuiTitle, {
|
|
56
|
+
size: "xxs"
|
|
57
|
+
}, /*#__PURE__*/React.createElement("h3", null, facet.label)), /*#__PURE__*/React.createElement(EntriesList, {
|
|
58
|
+
entries: facet.entries,
|
|
59
|
+
facet: facet,
|
|
60
|
+
loading: loading
|
|
61
|
+
}));
|
|
62
|
+
HierarchicalFilterFacet.DISPLAY = 'HierarchicalFilterFacet';
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import React, { Fragment, useRef } from 'react';
|
|
2
|
+
import { EuiFacetGroup, EuiTitle, EuiFacetButton } from '@elastic/eui';
|
|
3
|
+
import { useSearchkit, FilterLink } from '@searchkit/client';
|
|
4
|
+
|
|
5
|
+
const EntriesList = ({
|
|
6
|
+
entries,
|
|
7
|
+
loading,
|
|
8
|
+
facet
|
|
9
|
+
}) => {
|
|
10
|
+
console.log('entries', entries);
|
|
11
|
+
const api = useSearchkit();
|
|
12
|
+
const entriesElements = entries.map(entry => {
|
|
13
|
+
const ref = useRef();
|
|
14
|
+
return /*#__PURE__*/React.createElement(Fragment, {
|
|
15
|
+
key: entry.label
|
|
16
|
+
}, /*#__PURE__*/React.createElement(EuiFacetButton, {
|
|
17
|
+
style: {
|
|
18
|
+
height: '28px',
|
|
19
|
+
marginTop: 0,
|
|
20
|
+
marginBottom: 0
|
|
21
|
+
},
|
|
22
|
+
quantity: entry.count,
|
|
23
|
+
isSelected: api.isFilterSelected({
|
|
24
|
+
identifier: facet.identifier,
|
|
25
|
+
value: entry.label,
|
|
26
|
+
level: entry.level
|
|
27
|
+
}),
|
|
28
|
+
isLoading: loading,
|
|
29
|
+
onClick: e => {
|
|
30
|
+
ref.current.onClick(e);
|
|
31
|
+
}
|
|
32
|
+
}, /*#__PURE__*/React.createElement(FilterLink, {
|
|
33
|
+
ref: ref,
|
|
34
|
+
filter: {
|
|
35
|
+
identifier: facet.identifier,
|
|
36
|
+
value: entry.label,
|
|
37
|
+
level: entry.level
|
|
38
|
+
}
|
|
39
|
+
}, entry.label)), /*#__PURE__*/React.createElement("div", {
|
|
40
|
+
style: {
|
|
41
|
+
marginLeft: '10px'
|
|
42
|
+
}
|
|
43
|
+
}, entry.entries && /*#__PURE__*/React.createElement(EntriesList, {
|
|
44
|
+
entries: entry.entries,
|
|
45
|
+
loading: loading,
|
|
46
|
+
facet: facet
|
|
47
|
+
})));
|
|
48
|
+
});
|
|
49
|
+
return /*#__PURE__*/React.createElement(EuiFacetGroup, null, entriesElements);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
export const HierarchicalMenuFacet = ({
|
|
53
|
+
facet,
|
|
54
|
+
loading
|
|
55
|
+
}) => /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(EuiTitle, {
|
|
56
|
+
size: "xxs"
|
|
57
|
+
}, /*#__PURE__*/React.createElement("h3", null, facet.label)), /*#__PURE__*/React.createElement(EntriesList, {
|
|
58
|
+
entries: facet.entries,
|
|
59
|
+
facet: facet,
|
|
60
|
+
loading: loading
|
|
61
|
+
}));
|
|
62
|
+
HierarchicalMenuFacet.DISPLAY = 'HierarchicalMenuFacet';
|
|
@@ -3,8 +3,9 @@ import { gql, useQuery } from '@apollo/client';
|
|
|
3
3
|
import { useSearchkitVariables } from '@searchkit/client';
|
|
4
4
|
import SearchPage from '../SearchPage';
|
|
5
5
|
|
|
6
|
-
function
|
|
6
|
+
function Query({
|
|
7
7
|
query,
|
|
8
|
+
useRouting,
|
|
8
9
|
children
|
|
9
10
|
}) {
|
|
10
11
|
const graphQuery = useMemo(() => {
|
|
@@ -21,7 +22,12 @@ function App({
|
|
|
21
22
|
} = useQuery(graphQuery, {
|
|
22
23
|
variables
|
|
23
24
|
});
|
|
25
|
+
|
|
26
|
+
if (!useRouting) {
|
|
27
|
+
return /*#__PURE__*/React.createElement("div", null, children(data, loading));
|
|
28
|
+
}
|
|
29
|
+
|
|
24
30
|
return /*#__PURE__*/React.createElement(SearchPage, null, children(data, loading));
|
|
25
31
|
}
|
|
26
32
|
|
|
27
|
-
export default
|
|
33
|
+
export default Query;
|
|
@@ -2,9 +2,11 @@ import React from 'react';
|
|
|
2
2
|
import { SelectFacet } from '../Facets/SelectFacet';
|
|
3
3
|
import { ListFacet } from '../Facets/ListFacet';
|
|
4
4
|
import { ChipFacet } from '../Facets/ChipFacet';
|
|
5
|
+
import { HierarchicalFilterFacet } from '../Facets/HierarchicalFilterFacet';
|
|
6
|
+
import { HierarchicalMenuFacet } from '../Facets/HierarchicalMenuFacet';
|
|
5
7
|
|
|
6
8
|
const FacetList = (components = []) => {
|
|
7
|
-
const FacetsMapper = [SelectFacet, ChipFacet, ListFacet, ...components].reduce((sum, component) => {
|
|
9
|
+
const FacetsMapper = [HierarchicalFilterFacet, HierarchicalMenuFacet, SelectFacet, ChipFacet, ListFacet, ...components].reduce((sum, component) => {
|
|
8
10
|
sum[component.DISPLAY] = component;
|
|
9
11
|
return sum;
|
|
10
12
|
}, {});
|
|
@@ -6,4 +6,50 @@ const SearchPage = ({
|
|
|
6
6
|
children
|
|
7
7
|
}) => /*#__PURE__*/React.createElement(EuiPage, null, children);
|
|
8
8
|
|
|
9
|
-
export
|
|
9
|
+
export const routeToStateFn = routeState => {
|
|
10
|
+
const value = {
|
|
11
|
+
query: routeState.query || '',
|
|
12
|
+
sortBy: routeState.sort || '',
|
|
13
|
+
filters: routeState.filters || [],
|
|
14
|
+
page: {
|
|
15
|
+
size: Number(routeState.size) || 10,
|
|
16
|
+
from: Number(routeState.from) || 0
|
|
17
|
+
}
|
|
18
|
+
}; // Map Number values for min and max filters. By default they
|
|
19
|
+
// are parsed as strings, which does not comply to the schema.
|
|
20
|
+
// The 'qs' package is at fault here.
|
|
21
|
+
// @see https://github.com/ljharb/qs/issues/91
|
|
22
|
+
|
|
23
|
+
value.filters = value.filters.map(item => {
|
|
24
|
+
if (item.min) {
|
|
25
|
+
item.min = Number(item.min);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (item.max) {
|
|
29
|
+
item.max = Number(item.max);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
if (item.boolValue) {
|
|
33
|
+
item.boolValue = !!item.boolValue;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
if (item.geoBoundingBox) {
|
|
37
|
+
item.geoBoundingBox.topLeft.lat = Number(item.geoBoundingBox.topLeft.lat);
|
|
38
|
+
item.geoBoundingBox.topLeft.lon = Number(item.geoBoundingBox.topLeft.lon);
|
|
39
|
+
item.geoBoundingBox.bottomRight.lat = Number(item.geoBoundingBox.bottomRight.lat);
|
|
40
|
+
item.geoBoundingBox.bottomRight.lon = Number(item.geoBoundingBox.bottomRight.lon);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (item.geoRadius) {
|
|
44
|
+
item.geoRadius.radius = Number(item.geoRadius.radius);
|
|
45
|
+
item.geoRadius.center.lat = Number(item.geoRadius.center.lat);
|
|
46
|
+
item.geoRadius.center.lon = Number(item.geoRadius.center.lon);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return item;
|
|
50
|
+
});
|
|
51
|
+
return value;
|
|
52
|
+
};
|
|
53
|
+
export default withSearchkitRouting(SearchPage, {
|
|
54
|
+
routeToState: routeToStateFn
|
|
55
|
+
});
|
|
@@ -24,7 +24,9 @@ const defaultChildren = (data, loading) => /*#__PURE__*/React.createElement(Reac
|
|
|
24
24
|
const SearchKit = ({
|
|
25
25
|
query,
|
|
26
26
|
uri,
|
|
27
|
-
children
|
|
27
|
+
children,
|
|
28
|
+
pageSize = 5,
|
|
29
|
+
useRouting = true
|
|
28
30
|
}) => {
|
|
29
31
|
const client = new ApolloClient({
|
|
30
32
|
uri: uri,
|
|
@@ -36,7 +38,8 @@ const SearchKit = ({
|
|
|
36
38
|
}, /*#__PURE__*/React.createElement(SearchkitProvider, {
|
|
37
39
|
client: skClient
|
|
38
40
|
}, /*#__PURE__*/React.createElement(Query, {
|
|
39
|
-
query: query
|
|
41
|
+
query: query,
|
|
42
|
+
useRouting: useRouting
|
|
40
43
|
}, (data, loading) => children ? children(data, loading) : defaultChildren(data, loading))));
|
|
41
44
|
};
|
|
42
45
|
|
|
@@ -26,6 +26,10 @@ const query = `
|
|
|
26
26
|
identifier
|
|
27
27
|
display
|
|
28
28
|
label
|
|
29
|
+
... on HierarchicalValueSelectedFilter {
|
|
30
|
+
level
|
|
31
|
+
value
|
|
32
|
+
}
|
|
29
33
|
... on DateRangeSelectedFilter {
|
|
30
34
|
dateMin
|
|
31
35
|
dateMax
|
|
@@ -70,6 +74,17 @@ const query = `
|
|
|
70
74
|
entries {
|
|
71
75
|
label
|
|
72
76
|
count
|
|
77
|
+
level
|
|
78
|
+
entries {
|
|
79
|
+
label
|
|
80
|
+
count
|
|
81
|
+
level
|
|
82
|
+
entries {
|
|
83
|
+
label
|
|
84
|
+
count
|
|
85
|
+
level
|
|
86
|
+
}
|
|
87
|
+
}
|
|
73
88
|
}
|
|
74
89
|
}
|
|
75
90
|
}
|