@truedat/core 6.12.1 → 6.12.3

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": "6.12.1",
3
+ "version": "6.12.3",
4
4
  "description": "Truedat Web Core",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -118,5 +118,5 @@
118
118
  "react-dom": ">= 16.8.6 < 17",
119
119
  "semantic-ui-react": ">= 2.0.3 < 2.2"
120
120
  },
121
- "gitHead": "0e64673b5e798d15560f153c6ae0aede669b1dab"
121
+ "gitHead": "2a55116634e90fc77f5317f980b7117e7dbdea31"
122
122
  }
@@ -2,6 +2,7 @@ import _ from "lodash/fp";
2
2
  import React from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { FormattedMessage } from "react-intl";
5
+ import { useLocation } from "react-router-dom";
5
6
  import FilterDropdown from "./FilterDropdown";
6
7
  import FilterMultilevelDropdown from "./FilterMultilevelDropdown";
7
8
  import HierarchyFilterDropdown from "./HierarchyFilterDropdown";
@@ -30,76 +31,85 @@ export const SelectedFilters = ({
30
31
  userFilterScope,
31
32
  searchFiltersPropsMapping,
32
33
  searchFilterDispacher,
33
- }) => (
34
- <>
35
- {_.isEmpty(userFilters) ? null : (
36
- <UserFilters
37
- applyUserFilter={applyUserFilter}
38
- userFilterScope={userFilterScope}
39
- deleteUserFilter={deleteUserFilter}
40
- resetFilters={resetFilters}
41
- selectedUserFilter={selectedUserFilter}
42
- userFilters={userFilters}
43
- disabled={loading}
44
- />
45
- )}
46
- <div className="selectedFilters">
47
- {_.isEmpty(selectedFilters) ? null : (
48
- <>
49
- <div className="appliedFilters">
50
- <FormattedMessage id="search.applied_filters" />
51
- </div>
52
- {selectedFilters.map((filter) => {
53
- const isSelectedFilter = _.isEqual(filter, selectedFilter);
34
+ }) => {
35
+ const { pathname } = useLocation();
36
+ const taxonomyPathRegex = /^\/domains\/(\d+)\/\w+$/;
37
+ const taxonomyPath = pathname.match(taxonomyPathRegex);
38
+ const pathnameSplit = pathname.split("/");
39
+ const domainId = pathnameSplit[2];
54
40
 
55
- const filterType = _.prop(filter)(filterTypes);
56
- const options = isSelectedFilter ? selectedFilterValues : null;
41
+ return (
42
+ <>
43
+ {_.isEmpty(userFilters) ? null : (
44
+ <UserFilters
45
+ applyUserFilter={applyUserFilter}
46
+ userFilterScope={userFilterScope}
47
+ deleteUserFilter={deleteUserFilter}
48
+ domainId={taxonomyPath ? parseInt(domainId) : null}
49
+ resetFilters={resetFilters}
50
+ selectedUserFilter={selectedUserFilter}
51
+ userFilters={userFilters}
52
+ disabled={loading}
53
+ />
54
+ )}
55
+ <div className="selectedFilters">
56
+ {_.isEmpty(selectedFilters) ? null : (
57
+ <>
58
+ <div className="appliedFilters">
59
+ <FormattedMessage id="search.applied_filters" />
60
+ </div>
61
+ {selectedFilters.map((filter) => {
62
+ const isSelectedFilter = _.isEqual(filter, selectedFilter);
57
63
 
58
- const props = {
59
- key: filter,
60
- activeValues,
61
- closeFilter,
62
- filter,
63
- loading,
64
- openFilter,
65
- options,
66
- removeFilter,
67
- toggleFilterValue,
68
- };
64
+ const filterType = _.prop(filter)(filterTypes);
65
+ const options = isSelectedFilter ? selectedFilterValues : null;
69
66
 
70
- switch (filterType) {
71
- case "domain":
72
- return <FilterMultilevelDropdown {...props} />;
73
- case "hierarchy":
74
- return <HierarchyFilterDropdown {...props} />;
75
- case "search":
76
- return (
77
- <SearchFilterDropdown
78
- {...props}
79
- {...searchFiltersPropsMapping[filter]}
80
- open={isSelectedFilter}
81
- searchFilterDispacher={searchFilterDispacher}
82
- />
83
- );
84
- default:
85
- return <FilterDropdown {...props} />;
86
- }
87
- })}
88
- <a className="resetFilters" onClick={() => resetFilters()}>
89
- <FormattedMessage id="search.clear_filters" />
90
- </a>
91
- {saveFilters && (
92
- <ModalSaveFilter
93
- saveFilters={saveFilters}
94
- activeFilters={activeFilters}
95
- scope={userFilterScope}
96
- />
97
- )}
98
- </>
99
- )}
100
- </div>
101
- </>
102
- );
67
+ const props = {
68
+ key: filter,
69
+ activeValues,
70
+ closeFilter,
71
+ filter,
72
+ loading,
73
+ openFilter,
74
+ options,
75
+ removeFilter,
76
+ toggleFilterValue,
77
+ };
78
+
79
+ switch (filterType) {
80
+ case "domain":
81
+ return <FilterMultilevelDropdown {...props} />;
82
+ case "hierarchy":
83
+ return <HierarchyFilterDropdown {...props} />;
84
+ case "search":
85
+ return (
86
+ <SearchFilterDropdown
87
+ {...props}
88
+ {...searchFiltersPropsMapping[filter]}
89
+ open={isSelectedFilter}
90
+ searchFilterDispacher={searchFilterDispacher}
91
+ />
92
+ );
93
+ default:
94
+ return <FilterDropdown {...props} />;
95
+ }
96
+ })}
97
+ <a className="resetFilters" onClick={() => resetFilters()}>
98
+ <FormattedMessage id="search.clear_filters" />
99
+ </a>
100
+ {saveFilters && (
101
+ <ModalSaveFilter
102
+ saveFilters={saveFilters}
103
+ activeFilters={activeFilters}
104
+ scope={userFilterScope}
105
+ />
106
+ )}
107
+ </>
108
+ )}
109
+ </div>
110
+ </>
111
+ );
112
+ };
103
113
 
104
114
  SelectedFilters.propTypes = {
105
115
  activeFilters: PropTypes.object,
@@ -10,16 +10,35 @@ export const UserFilters = ({
10
10
  applyUserFilter,
11
11
  deleteUserFilter,
12
12
  disabled,
13
+ domainId,
13
14
  resetFilters,
14
15
  selectedUserFilter,
15
16
  userFilters,
16
17
  userFilterScope,
17
18
  }) => {
18
19
  const authorized = useAuthorized();
19
- const sortedUserFilters = _.orderBy(
20
- ["is_global", "id"],
21
- ["desc", "asc"]
20
+ const showDomainFilter = (filters) => {
21
+ if (_.flow(_.keys, (k) => !_.includes("taxonomy")(k))(filters)) return true;
22
+
23
+ if (_.flow(_.keys, _.equals(["taxonomy"]))(filters)) return false;
24
+
25
+ if (_.flow(_.get("taxonomy"), _.size, (s) => s > 1)(filters)) return false;
26
+
27
+ if (
28
+ _.flow(_.get("taxonomy"), _.head, (t) => !_.equals(domainId)(t))(filters)
29
+ )
30
+ return false;
31
+
32
+ return true;
33
+ };
34
+
35
+ const sortedUserFilters = _.flow(
36
+ _.filter(({ filters }) =>
37
+ _.isNull(domainId) ? true : showDomainFilter(filters)
38
+ ),
39
+ _.orderBy(["is_global", "id"], ["desc", "asc"])
22
40
  )(userFilters);
41
+
23
42
  return _.isEmpty(userFilters) ? null : (
24
43
  <div className="selectedFilters">
25
44
  {sortedUserFilters.map((userFilter, key) => {
@@ -89,6 +108,7 @@ export const UserFilters = ({
89
108
  UserFilters.propTypes = {
90
109
  applyUserFilter: PropTypes.func,
91
110
  deleteUserFilter: PropTypes.func,
111
+ domainId: PropTypes.number,
92
112
  resetFilters: PropTypes.func,
93
113
  selectedUserFilter: PropTypes.string,
94
114
  userFilters: PropTypes.array,
@@ -7,6 +7,13 @@ import { Icon, Dropdown, Segment } from "semantic-ui-react";
7
7
 
8
8
  import { SelectedFilters } from "../SelectedFilters";
9
9
 
10
+ jest.mock("react-router-dom", () => ({
11
+ ...jest.requireActual("react-router-dom"),
12
+ useLocation: () => ({
13
+ pathname: "/domains/123/structures",
14
+ }),
15
+ }));
16
+
10
17
  const DummyLoader = () => <div></div>;
11
18
  const DummyFilerItem = ({ active, toggleFilterValue, option }) => (
12
19
  <Dropdown.Item onClick={() => toggleFilterValue(option)} active={active}>
@@ -144,3 +151,77 @@ describe("<SelectedFilters/>", () => {
144
151
  ).not.toBeNull();
145
152
  });
146
153
  });
154
+
155
+ describe("<SelectedFilters/> taxonomy screens", () => {
156
+ const props = {
157
+ resetFilters: jest.fn(),
158
+ filterTypes: {
159
+ foo: "fooType",
160
+ },
161
+ openFilter: jest.fn(),
162
+ closeFilter: jest.fn(),
163
+ selectedFilter: "foo",
164
+ selectedFilters: ["foo", "bar"],
165
+ selectedFilterActiveValues: ["value2"],
166
+ selectedFilterValues: ["value1", "value2"],
167
+ selectedUserFilter: null,
168
+ userFilters: [
169
+ {
170
+ id: 1,
171
+ name: "Hide Domain Filter",
172
+ scope: "data_structure",
173
+ filters: { taxonomy: [123] },
174
+ user_id: 1,
175
+ is_global: true,
176
+ },
177
+ {
178
+ id: 2,
179
+ name: "Show Status Filter",
180
+ scope: "data_structure",
181
+ filters: { status: ["pending"] },
182
+ user_id: 1,
183
+ is_global: true,
184
+ },
185
+ {
186
+ id: 3,
187
+ name: "Hide Multiple Domain Filter",
188
+ scope: "data_structure",
189
+ filters: { status: ["pending"], taxonomy: [123, 321] },
190
+ user_id: 1,
191
+ is_global: true,
192
+ },
193
+ {
194
+ id: 4,
195
+ name: "Hide Other Domain Filter",
196
+ scope: "data_structure",
197
+ filters: { status: ["pending"], taxonomy: [321] },
198
+ user_id: 1,
199
+ is_global: true,
200
+ },
201
+ {
202
+ id: 5,
203
+ name: "Show Status and Domain Filter",
204
+ scope: "data_structure",
205
+ filters: { status: ["pending"], taxonomy: [123] },
206
+ user_id: 1,
207
+ is_global: true,
208
+ },
209
+ ],
210
+ searchFiltersPropsMapping: {},
211
+ searchFilterDispacher: jest.fn(),
212
+ };
213
+
214
+ it("matches the latest snapshot", () => {
215
+ const { container } = render(<SelectedFilters {...props} />);
216
+ expect(container).toMatchSnapshot();
217
+ });
218
+
219
+ it("render only Show filters", () => {
220
+ const { queryByText } = render(<SelectedFilters {...props} />);
221
+ expect(queryByText("Hide Domain Filter")).toBeNull();
222
+ expect(queryByText("Show Status Filter")).toBeInTheDocument();
223
+ expect(queryByText("Hide Multiple Domain Filter")).toBeNull();
224
+ expect(queryByText("Hide Other Domain Filter")).toBeNull();
225
+ expect(queryByText("Show Status and Domain Filter")).toBeInTheDocument();
226
+ });
227
+ });
@@ -112,3 +112,74 @@ describe("<UserFilters /> not admin", () => {
112
112
  expect(container).toMatchSnapshot();
113
113
  });
114
114
  });
115
+
116
+ describe("<UserFilters /> for taxonomy screens", () => {
117
+ jest.mock("../../hooks", () => ({
118
+ ...jest.requireActual("../../hooks"),
119
+ useAuthorized: jest.fn(() => true),
120
+ }));
121
+
122
+ const props = {
123
+ applyUserFilter,
124
+ deleteUserFilter,
125
+ resetFilters,
126
+ domainId: 123,
127
+ selectedUserFilter,
128
+ userFilters: [
129
+ {
130
+ id: 1,
131
+ name: "Hide Domain Filter",
132
+ scope: "data_structure",
133
+ filters: { taxonomy: [123] },
134
+ user_id: 1,
135
+ is_global: true,
136
+ },
137
+ {
138
+ id: 2,
139
+ name: "Show Status Filter",
140
+ scope: "data_structure",
141
+ filters: { status: ["pending"] },
142
+ user_id: 1,
143
+ is_global: true,
144
+ },
145
+ {
146
+ id: 3,
147
+ name: "Hide Multiple Domain Filter",
148
+ scope: "data_structure",
149
+ filters: { status: ["pending"], taxonomy: [123, 321] },
150
+ user_id: 1,
151
+ is_global: true,
152
+ },
153
+ {
154
+ id: 4,
155
+ name: "Hide Other Domain Filter",
156
+ scope: "data_structure",
157
+ filters: { status: ["pending"], taxonomy: [321] },
158
+ user_id: 1,
159
+ is_global: true,
160
+ },
161
+ {
162
+ id: 5,
163
+ name: "Show Status and Domain Filter",
164
+ scope: "data_structure",
165
+ filters: { status: ["pending"], taxonomy: [123] },
166
+ user_id: 1,
167
+ is_global: true,
168
+ },
169
+ ],
170
+ };
171
+
172
+ it("matches the latest snapshot", () => {
173
+ const { container } = render(<UserFilters {...props} />, renderOpts);
174
+ expect(container).toMatchSnapshot();
175
+ });
176
+
177
+ it("render only Show filters", () => {
178
+ const { queryByText } = render(<UserFilters {...props} />, renderOpts);
179
+ expect(queryByText("Hide Domain Filter")).toBeNull();
180
+ expect(queryByText("Show Status Filter")).toBeInTheDocument();
181
+ expect(queryByText("Hide Multiple Domain Filter")).toBeNull();
182
+ expect(queryByText("Hide Other Domain Filter")).toBeNull();
183
+ expect(queryByText("Show Status and Domain Filter")).toBeInTheDocument();
184
+ });
185
+ });
@@ -109,3 +109,109 @@ exports[`<SelectedFilters/> matches the latest snapshot 1`] = `
109
109
  </div>
110
110
  </div>
111
111
  `;
112
+
113
+ exports[`<SelectedFilters/> taxonomy screens matches the latest snapshot 1`] = `
114
+ <div>
115
+ <div
116
+ class="selectedFilters"
117
+ >
118
+ <div
119
+ class="ui basic circular label global"
120
+ >
121
+ <span
122
+ class="userFilter"
123
+ >
124
+ Show Status Filter
125
+ </span>
126
+ </div>
127
+ <div
128
+ class="ui basic circular label global"
129
+ >
130
+ <span
131
+ class="userFilter"
132
+ >
133
+ Show Status and Domain Filter
134
+ </span>
135
+ </div>
136
+ </div>
137
+ <div
138
+ class="selectedFilters"
139
+ >
140
+ <div
141
+ class="appliedFilters"
142
+ >
143
+ Filters:
144
+ </div>
145
+ <div
146
+ aria-expanded="true"
147
+ class="ui active visible floating item scrolling dropdown"
148
+ role="listbox"
149
+ tabindex="0"
150
+ >
151
+ <div
152
+ class="ui label"
153
+ >
154
+ foo
155
+ <i
156
+ aria-hidden="true"
157
+ class="delete icon"
158
+ />
159
+ </div>
160
+ <div
161
+ class="menu transition dimmable visible"
162
+ >
163
+ <div
164
+ aria-checked="false"
165
+ class="item"
166
+ role="option"
167
+ >
168
+ <i
169
+ aria-hidden="true"
170
+ class="square outline icon"
171
+ />
172
+ <i>
173
+ Empty
174
+ </i>
175
+ </div>
176
+ <div
177
+ aria-checked="false"
178
+ class="item"
179
+ role="option"
180
+ >
181
+ <i
182
+ aria-hidden="true"
183
+ class="square outline icon"
184
+ />
185
+ <i>
186
+ Empty
187
+ </i>
188
+ </div>
189
+ </div>
190
+ </div>
191
+ <div
192
+ aria-expanded="false"
193
+ class="ui floating item scrolling dropdown"
194
+ role="listbox"
195
+ tabindex="0"
196
+ >
197
+ <div
198
+ class="ui label"
199
+ >
200
+ bar
201
+ <i
202
+ aria-hidden="true"
203
+ class="delete icon"
204
+ />
205
+ </div>
206
+ <div
207
+ class="menu transition dimmable"
208
+ />
209
+ </div>
210
+ <a
211
+ class="resetFilters"
212
+ >
213
+ Clear filters
214
+ </a>
215
+ </div>
216
+ </div>
217
+ `;
@@ -79,6 +79,33 @@ exports[`<UserFilters /> admin matches the latest snapshot with global filters 1
79
79
  </div>
80
80
  `;
81
81
 
82
+ exports[`<UserFilters /> for taxonomy screens matches the latest snapshot 1`] = `
83
+ <div>
84
+ <div
85
+ class="selectedFilters"
86
+ >
87
+ <div
88
+ class="ui basic circular label global"
89
+ >
90
+ <span
91
+ class="userFilter"
92
+ >
93
+ Show Status Filter
94
+ </span>
95
+ </div>
96
+ <div
97
+ class="ui basic circular label global"
98
+ >
99
+ <span
100
+ class="userFilter"
101
+ >
102
+ Show Status and Domain Filter
103
+ </span>
104
+ </div>
105
+ </div>
106
+ </div>
107
+ `;
108
+
82
109
  exports[`<UserFilters /> not admin matches the latest snapshot 1`] = `
83
110
  <div>
84
111
  <div
@@ -1,6 +1,7 @@
1
1
  import _ from "lodash/fp";
2
2
  import React, { useState } from "react";
3
3
  import { FormattedMessage } from "react-intl";
4
+ import { useLocation } from "react-router-dom";
4
5
  import ModalSaveFilter from "./ModalSaveFilter";
5
6
  import UserFilters from "./UserFilters";
6
7
  import FilterDropdown from "./FilterDropdown";
@@ -22,11 +23,17 @@ export default function SearchSelectedFilters() {
22
23
  userFiltersType,
23
24
  } = context;
24
25
  const [selectedUserFilter, setSelectedUserFilter] = useState();
26
+ const { pathname } = useLocation();
27
+ const taxonomyPathRegex = /^\/domains\/(\d+)\/\w+$/;
28
+ const taxonomyPath = pathname.match(taxonomyPathRegex);
29
+ const pathnameSplit = pathname.split("/");
30
+ const domainId = pathnameSplit[2];
25
31
 
26
32
  return (
27
33
  <>
28
34
  {userFiltersType ? (
29
35
  <UserFilters
36
+ domainId={taxonomyPath ? parseInt(domainId) : null}
30
37
  setSelectedUserFilter={setSelectedUserFilter}
31
38
  selectedUserFilter={selectedUserFilter}
32
39
  />
@@ -57,7 +57,11 @@ DeleteModal.propTypes = {
57
57
  mutate: PropTypes.func,
58
58
  };
59
59
 
60
- export const UserFilters = ({ setSelectedUserFilter, selectedUserFilter }) => {
60
+ export const UserFilters = ({
61
+ domainId,
62
+ setSelectedUserFilter,
63
+ selectedUserFilter,
64
+ }) => {
61
65
  const authorized = useAuthorized();
62
66
  const {
63
67
  userFiltersType,
@@ -72,9 +76,26 @@ export const UserFilters = ({ setSelectedUserFilter, selectedUserFilter }) => {
72
76
  mutate,
73
77
  } = useUserFilters(userFiltersType, userFilterScope);
74
78
 
75
- const sortedUserFilters = _.orderBy(
76
- ["is_global", "id"],
77
- ["desc", "asc"]
79
+ const showDomainFilter = (filters) => {
80
+ if (_.flow(_.keys, (k) => !_.includes("taxonomy")(k))(filters)) return true;
81
+
82
+ if (_.flow(_.keys, _.equals(["taxonomy"]))(filters)) return false;
83
+
84
+ if (_.flow(_.get("taxonomy"), _.size, (s) => s > 1)(filters)) return false;
85
+
86
+ if (
87
+ _.flow(_.get("taxonomy"), _.head, (t) => !_.equals(domainId)(t))(filters)
88
+ )
89
+ return false;
90
+
91
+ return true;
92
+ };
93
+
94
+ const sortedUserFilters = _.flow(
95
+ _.filter(({ filters }) =>
96
+ _.isNull(domainId) ? true : showDomainFilter(filters)
97
+ ),
98
+ _.orderBy(["is_global", "id"], ["desc", "asc"])
78
99
  )(userFilters);
79
100
 
80
101
  return _.isEmpty(userFilters) ? null : (
@@ -127,6 +148,7 @@ export const UserFilters = ({ setSelectedUserFilter, selectedUserFilter }) => {
127
148
  };
128
149
 
129
150
  UserFilters.propTypes = {
151
+ domainId: PropTypes.number,
130
152
  selectedUserFilter: PropTypes.string,
131
153
  setSelectedUserFilter: PropTypes.func,
132
154
  };