@truedat/core 5.16.4 → 5.17.1
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/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/core",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.17.1",
|
|
4
4
|
"description": "Truedat Web Core",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -117,5 +117,5 @@
|
|
|
117
117
|
"react-dom": ">= 16.8.6 < 17",
|
|
118
118
|
"semantic-ui-react": ">= 2.0.3 < 2.2"
|
|
119
119
|
},
|
|
120
|
-
"gitHead": "
|
|
120
|
+
"gitHead": "6e0fe4ca06e36b5625ab3c20aaf940dba237d34f"
|
|
121
121
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
|
-
import React from "react";
|
|
2
|
+
import React, { Fragment } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { Dropdown } from "semantic-ui-react";
|
|
5
5
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
@@ -7,14 +7,41 @@ import { i18nOrder } from "../services/sort";
|
|
|
7
7
|
|
|
8
8
|
const removePrefix = _.replace(/^.*\./, "");
|
|
9
9
|
|
|
10
|
+
const makeFiltersGroup = (filters, groups) =>
|
|
11
|
+
_.groupBy((filter) =>
|
|
12
|
+
_.flow(
|
|
13
|
+
_.find(([_group, fields]) => _.contains(filter)(fields)),
|
|
14
|
+
_.prop("[0]")
|
|
15
|
+
)(groups)
|
|
16
|
+
)(filters);
|
|
17
|
+
|
|
10
18
|
export const AvailableFilters = ({
|
|
11
19
|
addFilter,
|
|
12
20
|
disabled,
|
|
13
21
|
filters,
|
|
14
22
|
loading,
|
|
15
23
|
resetFilters,
|
|
24
|
+
filtersGroup = [],
|
|
16
25
|
}) => {
|
|
17
26
|
const { formatMessage } = useIntl();
|
|
27
|
+
const filtersByGroup = makeFiltersGroup(filters, filtersGroup);
|
|
28
|
+
|
|
29
|
+
const groupWithoutFilters = (groups) =>
|
|
30
|
+
_.flow(
|
|
31
|
+
_.prop("[0]"),
|
|
32
|
+
(groupName) => _.prop(groupName)(filtersByGroup),
|
|
33
|
+
_.isEmpty
|
|
34
|
+
)(groups);
|
|
35
|
+
|
|
36
|
+
const groups = _.flow(
|
|
37
|
+
(groups) => _.concat(groups, [[undefined, []]]),
|
|
38
|
+
_.reject(groupWithoutFilters),
|
|
39
|
+
_.map(([groupName, _filters]) => [
|
|
40
|
+
groupName,
|
|
41
|
+
_.prop(groupName)(filtersByGroup),
|
|
42
|
+
])
|
|
43
|
+
)(filtersGroup);
|
|
44
|
+
|
|
18
45
|
return (
|
|
19
46
|
<Dropdown
|
|
20
47
|
button
|
|
@@ -37,20 +64,36 @@ export const AvailableFilters = ({
|
|
|
37
64
|
/>
|
|
38
65
|
</em>
|
|
39
66
|
</Dropdown.Item>
|
|
40
|
-
{_.
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
67
|
+
{_.map.convert({ cap: false })(([groupName, filters], idx) => (
|
|
68
|
+
<Fragment key={idx}>
|
|
69
|
+
{idx == 0 ? null : <Dropdown.Divider />}
|
|
70
|
+
{groupName ? (
|
|
71
|
+
<Dropdown.Header key={groupName}>
|
|
72
|
+
<b>
|
|
73
|
+
<FormattedMessage
|
|
74
|
+
id={`filters.group.header.${groupName}`}
|
|
75
|
+
defaultMessage={groupName}
|
|
76
|
+
/>
|
|
77
|
+
</b>
|
|
78
|
+
</Dropdown.Header>
|
|
79
|
+
) : null}
|
|
80
|
+
|
|
81
|
+
{_.flow(
|
|
82
|
+
_.defaultTo([]),
|
|
83
|
+
_.sortBy(i18nOrder(formatMessage, "filters")),
|
|
84
|
+
_.map((filter) => (
|
|
85
|
+
<Dropdown.Item
|
|
86
|
+
key={filter}
|
|
87
|
+
text={formatMessage({
|
|
88
|
+
id: `filters.${filter}`,
|
|
89
|
+
defaultMessage: removePrefix(filter),
|
|
90
|
+
})}
|
|
91
|
+
onClick={() => addFilter({ filter })}
|
|
92
|
+
/>
|
|
93
|
+
))
|
|
94
|
+
)(filters)}
|
|
95
|
+
</Fragment>
|
|
96
|
+
))(groups)}
|
|
54
97
|
</Dropdown.Menu>
|
|
55
98
|
</Dropdown>
|
|
56
99
|
);
|
|
@@ -62,6 +105,7 @@ AvailableFilters.propTypes = {
|
|
|
62
105
|
filters: PropTypes.array,
|
|
63
106
|
resetFilters: PropTypes.func,
|
|
64
107
|
loading: PropTypes.bool,
|
|
108
|
+
filtersGroup: PropTypes.array,
|
|
65
109
|
};
|
|
66
110
|
|
|
67
111
|
export default AvailableFilters;
|
|
@@ -1,45 +1,59 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import React from "react";
|
|
3
|
-
import {
|
|
4
|
-
import
|
|
5
|
-
import {
|
|
3
|
+
import { render } from "@truedat/test/render";
|
|
4
|
+
import userEvent from "@testing-library/user-event";
|
|
5
|
+
import { waitFor } from "@testing-library/react";
|
|
6
6
|
import { AvailableFilters } from "../AvailableFilters";
|
|
7
7
|
|
|
8
|
-
// workaround for enzyme issue with React.useContext
|
|
9
|
-
// see https://github.com/airbnb/enzyme/issues/2176#issuecomment-532361526
|
|
10
|
-
jest.spyOn(React, "useContext").mockImplementation(() => intl);
|
|
11
|
-
|
|
12
8
|
describe("<AvailableFilters/>", () => {
|
|
9
|
+
const resetFilters = jest.fn();
|
|
10
|
+
const addFilter = jest.fn();
|
|
11
|
+
|
|
13
12
|
const getProps = () => ({
|
|
14
|
-
addFilter
|
|
15
|
-
resetFilters
|
|
16
|
-
filters: ["foo"],
|
|
13
|
+
addFilter,
|
|
14
|
+
resetFilters,
|
|
15
|
+
filters: ["foo", "bar", "xyz"],
|
|
17
16
|
});
|
|
18
17
|
|
|
19
18
|
it("matches the latest snapshot", () => {
|
|
20
19
|
const props = getProps();
|
|
21
|
-
const
|
|
22
|
-
expect(
|
|
20
|
+
const { container } = render(<AvailableFilters {...props} />);
|
|
21
|
+
expect(container).toMatchSnapshot();
|
|
23
22
|
});
|
|
24
23
|
|
|
25
|
-
it("dispatches resetFilters when first item is clicked", () => {
|
|
24
|
+
it("dispatches resetFilters when first item is clicked", async () => {
|
|
26
25
|
const props = getProps();
|
|
27
|
-
const
|
|
26
|
+
const { queryByText } = render(<AvailableFilters {...props} />);
|
|
28
27
|
|
|
29
|
-
expect(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
expect(props.resetFilters.mock.calls.length).toBe(1);
|
|
28
|
+
expect(queryByText(/reset all filters/i)).toBeInTheDocument();
|
|
29
|
+
expect(resetFilters.mock.calls.length).toBe(0);
|
|
30
|
+
userEvent.click(await queryByText(/reset all filters/i));
|
|
31
|
+
await waitFor(() => expect(resetFilters.mock.calls.length).toBe(1));
|
|
34
32
|
});
|
|
35
33
|
|
|
36
|
-
it("dispatches addFilter when last item is clicked", () => {
|
|
34
|
+
it("dispatches addFilter when last item is clicked", async () => {
|
|
37
35
|
const props = getProps();
|
|
38
|
-
const
|
|
36
|
+
const { queryByText } = render(<AvailableFilters {...props} />);
|
|
39
37
|
|
|
40
38
|
expect(props.addFilter.mock.calls.length).toBe(0);
|
|
41
|
-
|
|
42
|
-
items.last().simulate("click");
|
|
39
|
+
userEvent.click(await queryByText(/foo/i));
|
|
43
40
|
expect(props.addFilter.mock.calls.length).toBe(1);
|
|
44
41
|
});
|
|
42
|
+
|
|
43
|
+
it("group by filters", async () => {
|
|
44
|
+
const filtersGroup = [
|
|
45
|
+
["important", ["xyz"]],
|
|
46
|
+
["grupNan", ["inexist_filter"]],
|
|
47
|
+
];
|
|
48
|
+
|
|
49
|
+
const props = {
|
|
50
|
+
addFilter,
|
|
51
|
+
resetFilters,
|
|
52
|
+
filters: ["foo", "bar", "xyz"],
|
|
53
|
+
filtersGroup,
|
|
54
|
+
};
|
|
55
|
+
const { queryByText } = render(<AvailableFilters {...props} />);
|
|
56
|
+
expect(queryByText(/important/i)).toBeInTheDocument();
|
|
57
|
+
expect(queryByText(/grupNan/i)).not.toBeInTheDocument();
|
|
58
|
+
});
|
|
45
59
|
});
|
|
@@ -1,45 +1,67 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`<AvailableFilters/> matches the latest snapshot 1`] = `
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
noResultsMessage="No results found."
|
|
17
|
-
openOnFocus={true}
|
|
18
|
-
renderLabel={[Function]}
|
|
19
|
-
scrolling={true}
|
|
20
|
-
searchInput="text"
|
|
21
|
-
selectOnBlur={true}
|
|
22
|
-
selectOnNavigation={true}
|
|
23
|
-
text="filters"
|
|
24
|
-
upward={false}
|
|
25
|
-
wrapSelection={true}
|
|
26
|
-
>
|
|
27
|
-
<DropdownMenu>
|
|
28
|
-
<DropdownItem
|
|
29
|
-
onClick={[MockFunction]}
|
|
4
|
+
<div>
|
|
5
|
+
<div
|
|
6
|
+
aria-expanded="false"
|
|
7
|
+
class="ui button floating labeled scrolling dropdown icon"
|
|
8
|
+
role="listbox"
|
|
9
|
+
tabindex="0"
|
|
10
|
+
>
|
|
11
|
+
<div
|
|
12
|
+
aria-atomic="true"
|
|
13
|
+
aria-live="polite"
|
|
14
|
+
class="divider text"
|
|
15
|
+
role="alert"
|
|
30
16
|
>
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
</em>
|
|
37
|
-
</DropdownItem>
|
|
38
|
-
<DropdownItem
|
|
39
|
-
key="foo"
|
|
40
|
-
onClick={[Function]}
|
|
41
|
-
text="foo"
|
|
17
|
+
Filters
|
|
18
|
+
</div>
|
|
19
|
+
<i
|
|
20
|
+
aria-hidden="true"
|
|
21
|
+
class="filter icon"
|
|
42
22
|
/>
|
|
43
|
-
|
|
44
|
-
|
|
23
|
+
<div
|
|
24
|
+
class="menu transition"
|
|
25
|
+
>
|
|
26
|
+
<div
|
|
27
|
+
class="item"
|
|
28
|
+
role="option"
|
|
29
|
+
>
|
|
30
|
+
<em>
|
|
31
|
+
(reset all filters)
|
|
32
|
+
</em>
|
|
33
|
+
</div>
|
|
34
|
+
<div
|
|
35
|
+
class="item"
|
|
36
|
+
role="option"
|
|
37
|
+
>
|
|
38
|
+
<span
|
|
39
|
+
class="text"
|
|
40
|
+
>
|
|
41
|
+
bar
|
|
42
|
+
</span>
|
|
43
|
+
</div>
|
|
44
|
+
<div
|
|
45
|
+
class="item"
|
|
46
|
+
role="option"
|
|
47
|
+
>
|
|
48
|
+
<span
|
|
49
|
+
class="text"
|
|
50
|
+
>
|
|
51
|
+
foo
|
|
52
|
+
</span>
|
|
53
|
+
</div>
|
|
54
|
+
<div
|
|
55
|
+
class="item"
|
|
56
|
+
role="option"
|
|
57
|
+
>
|
|
58
|
+
<span
|
|
59
|
+
class="text"
|
|
60
|
+
>
|
|
61
|
+
xyz
|
|
62
|
+
</span>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
45
67
|
`;
|