@truedat/core 4.43.4 → 4.44.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 +12 -0
- package/package.json +3 -3
- package/src/api/queries.js +11 -0
- package/src/components/Alert.js +11 -1
- package/src/components/CatalogMenu.js +2 -2
- package/src/components/DomainSelector.js +42 -0
- package/src/components/DropdownMenuItem.js +1 -1
- package/src/components/TreeSelector.js +161 -0
- package/src/components/__tests__/Alert.spec.js +1 -1
- package/src/components/__tests__/CatalogMenu.spec.js +10 -4
- package/src/components/__tests__/DomainSelector.spec.js +59 -0
- package/src/components/__tests__/TreeSelector.spec.js +38 -0
- package/src/components/__tests__/__snapshots__/Alert.spec.js.snap +7 -1
- package/src/components/__tests__/__snapshots__/CatalogMenu.spec.js.snap +97 -39
- package/src/components/__tests__/__snapshots__/DomainSelector.spec.js.snap +3 -0
- package/src/components/__tests__/__snapshots__/TreeSelector.spec.js.snap +59 -0
- package/src/components/index.js +5 -1
- package/src/messages/en.js +2 -2
- package/src/messages/es.js +2 -2
- package/src/routes.js +89 -79
- package/src/services/__tests__/tree.spec.js +68 -0
- package/src/services/tree.js +44 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [4.44.0] 2022-05-10
|
|
4
|
+
|
|
5
|
+
### Added
|
|
6
|
+
|
|
7
|
+
- [TD-4723] New `DomainSelector` which loads domains using GraphQL query
|
|
8
|
+
|
|
9
|
+
## [4.43.6] 2022-05-05
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- [TD-4586] Simplify accepted CSV message and include link to 'my loads'.
|
|
14
|
+
|
|
3
15
|
## [4.43.4] 2022-05-05
|
|
4
16
|
|
|
5
17
|
### Added
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/core",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.44.0",
|
|
4
4
|
"description": "Truedat Web Core",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"@babel/plugin-transform-modules-commonjs": "^7.15.0",
|
|
33
33
|
"@babel/preset-env": "^7.15.0",
|
|
34
34
|
"@babel/preset-react": "^7.14.5",
|
|
35
|
-
"@truedat/test": "4.
|
|
35
|
+
"@truedat/test": "4.44.0",
|
|
36
36
|
"babel-jest": "^27.0.6",
|
|
37
37
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
38
38
|
"babel-plugin-lodash": "^3.3.4",
|
|
@@ -106,5 +106,5 @@
|
|
|
106
106
|
"react-dom": ">= 16.8.6 < 17",
|
|
107
107
|
"semantic-ui-react": ">= 0.88.2 < 2.1"
|
|
108
108
|
},
|
|
109
|
-
"gitHead": "
|
|
109
|
+
"gitHead": "55fd4a8be70ca0d1bd4f3cb7b5eaf073b0350029"
|
|
110
110
|
}
|
package/src/components/Alert.js
CHANGED
|
@@ -45,6 +45,7 @@ export const Alert = ({
|
|
|
45
45
|
messages,
|
|
46
46
|
downloadable = false,
|
|
47
47
|
initialMaxListItems = Infinity,
|
|
48
|
+
anchor,
|
|
48
49
|
},
|
|
49
50
|
dismissAlert,
|
|
50
51
|
}) => {
|
|
@@ -81,7 +82,16 @@ export const Alert = ({
|
|
|
81
82
|
<Message
|
|
82
83
|
error={error}
|
|
83
84
|
header={formatMessage({ id: header, defaultMessage: header }, fields)}
|
|
84
|
-
content={
|
|
85
|
+
content={
|
|
86
|
+
<>
|
|
87
|
+
<p>{message_content}</p>
|
|
88
|
+
{!anchor ? null : (
|
|
89
|
+
<a href={anchor.reference}>
|
|
90
|
+
{formatMessage({ id: "sidemenu.structures_upload_events" })}
|
|
91
|
+
</a>
|
|
92
|
+
)}
|
|
93
|
+
</>
|
|
94
|
+
}
|
|
85
95
|
list={list.length >= maxListItems ? list.slice(0, maxListItems) : list}
|
|
86
96
|
icon={icon}
|
|
87
97
|
color={color}
|
|
@@ -14,8 +14,8 @@ import Submenu from "./Submenu";
|
|
|
14
14
|
const items = [{ name: "structures", routes: [STRUCTURES, SYSTEMS] }];
|
|
15
15
|
|
|
16
16
|
const adminItems = [
|
|
17
|
-
{ name: "
|
|
18
|
-
{ name: "
|
|
17
|
+
{ name: "structureTypes", routes: [STRUCTURE_TYPES] },
|
|
18
|
+
{ name: "structureTags", routes: [STRUCTURE_TAGS] },
|
|
19
19
|
];
|
|
20
20
|
|
|
21
21
|
const structureNoteItems = [
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { useIntl } from "react-intl";
|
|
5
|
+
import { useQuery } from "@apollo/client";
|
|
6
|
+
import { accentInsensitivePathOrder } from "../services/sort";
|
|
7
|
+
import { stratify, flatten } from "../services/tree";
|
|
8
|
+
import { DOMAINS_QUERY } from "../api/queries";
|
|
9
|
+
import TreeSelector from "./TreeSelector";
|
|
10
|
+
|
|
11
|
+
export const DomainSelector = ({ action, onLoad, value, ...props }) => {
|
|
12
|
+
const { formatMessage } = useIntl();
|
|
13
|
+
const { loading, error, data } = useQuery(DOMAINS_QUERY, {
|
|
14
|
+
variables: { action },
|
|
15
|
+
onCompleted: onLoad,
|
|
16
|
+
});
|
|
17
|
+
if (error) return null;
|
|
18
|
+
if (loading) return null;
|
|
19
|
+
const options = _.flow(
|
|
20
|
+
_.propOr([], "domains"),
|
|
21
|
+
_.sortBy(accentInsensitivePathOrder("name")),
|
|
22
|
+
stratify({}),
|
|
23
|
+
flatten
|
|
24
|
+
)(data);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<TreeSelector
|
|
28
|
+
options={options}
|
|
29
|
+
placeholder={formatMessage({ id: "domain.multiple.placeholder" })}
|
|
30
|
+
value={_.map(_.toString)(value)}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
DomainSelector.propTypes = {
|
|
37
|
+
action: PropTypes.string,
|
|
38
|
+
onLoad: PropTypes.func,
|
|
39
|
+
value: PropTypes.array,
|
|
40
|
+
};
|
|
41
|
+
|
|
42
|
+
export default DomainSelector;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React, { useState, useEffect } from "react";
|
|
3
|
+
import { Dropdown, Form, Icon, Input, Label } from "semantic-ui-react";
|
|
4
|
+
import PropTypes from "prop-types";
|
|
5
|
+
import { lowerDeburr } from "../services/sort";
|
|
6
|
+
import { recursiveMatch, descendents, childIds } from "../services/tree";
|
|
7
|
+
import DropdownMenuItem from "./DropdownMenuItem";
|
|
8
|
+
|
|
9
|
+
export const match =
|
|
10
|
+
(query) =>
|
|
11
|
+
({ name }) =>
|
|
12
|
+
_.contains(query)(lowerDeburr(name));
|
|
13
|
+
export const matchAny = recursiveMatch(match);
|
|
14
|
+
|
|
15
|
+
export const TreeSelector = ({
|
|
16
|
+
options,
|
|
17
|
+
error,
|
|
18
|
+
label,
|
|
19
|
+
name,
|
|
20
|
+
onBlur,
|
|
21
|
+
onChange,
|
|
22
|
+
required = false,
|
|
23
|
+
placeholder,
|
|
24
|
+
value: initialValue = [],
|
|
25
|
+
}) => {
|
|
26
|
+
const [value, setValue] = useState(initialValue);
|
|
27
|
+
const [query, setQuery] = useState();
|
|
28
|
+
const [open, setOpen] = useState([]);
|
|
29
|
+
const [displayed, setDisplayed] = useState([]);
|
|
30
|
+
|
|
31
|
+
useEffect(() => {
|
|
32
|
+
const ids = childIds(open)(options);
|
|
33
|
+
setDisplayed((displayed) => _.union(displayed)(ids));
|
|
34
|
+
}, [options, open, value]);
|
|
35
|
+
|
|
36
|
+
const handleOpen = (id) => {
|
|
37
|
+
const option = _.find({ id })(options);
|
|
38
|
+
const isOpen = _.contains(id)(open);
|
|
39
|
+
const childIds = _.map("id")(option.children);
|
|
40
|
+
const descendentIds = descendents(option);
|
|
41
|
+
|
|
42
|
+
if (isOpen) {
|
|
43
|
+
setOpen(_.without([id, ...descendentIds])(open));
|
|
44
|
+
setDisplayed(_.without(descendentIds)(displayed));
|
|
45
|
+
} else {
|
|
46
|
+
setOpen(_.union([id])(open));
|
|
47
|
+
setDisplayed(_.union(childIds)(displayed));
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
const displayAll = () => {
|
|
52
|
+
const ids = _.map("id")(options);
|
|
53
|
+
setOpen(ids);
|
|
54
|
+
setDisplayed(ids);
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
const handleSearch = (e, { value }) => {
|
|
58
|
+
e.preventDefault();
|
|
59
|
+
setQuery(lowerDeburr(value));
|
|
60
|
+
if (!_.isEmpty(value)) {
|
|
61
|
+
displayAll();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const handleClick = (e, id) => {
|
|
66
|
+
const ids = _.includes(id)(value)
|
|
67
|
+
? _.without([id])(value)
|
|
68
|
+
: _.union([id])(value);
|
|
69
|
+
setValue(ids);
|
|
70
|
+
onChange && onChange(e, { value: ids });
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
const filterSearch = query ? _.filter(matchAny(query)) : _.identity;
|
|
74
|
+
|
|
75
|
+
const filterDisplayed = _.filter(
|
|
76
|
+
({ id, level }) => level === 0 || _.includes(id)(displayed)
|
|
77
|
+
);
|
|
78
|
+
|
|
79
|
+
const trigger = _.isEmpty(value) ? (
|
|
80
|
+
<label>{placeholder}</label>
|
|
81
|
+
) : (
|
|
82
|
+
_.map((id) => (
|
|
83
|
+
<Label key={id}>
|
|
84
|
+
{_.flow(_.find({ id }), _.prop("name"))(options)}
|
|
85
|
+
<Icon
|
|
86
|
+
name="delete"
|
|
87
|
+
onClick={(e) => {
|
|
88
|
+
e.preventDefault();
|
|
89
|
+
e.stopPropagation();
|
|
90
|
+
handleClick(e, id);
|
|
91
|
+
}}
|
|
92
|
+
/>
|
|
93
|
+
</Label>
|
|
94
|
+
))(value)
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
const items = _.flow(
|
|
98
|
+
filterSearch,
|
|
99
|
+
filterDisplayed,
|
|
100
|
+
_.map((option) => (
|
|
101
|
+
<DropdownMenuItem
|
|
102
|
+
key={option?.id}
|
|
103
|
+
check={false}
|
|
104
|
+
handleOpen={handleOpen}
|
|
105
|
+
handleClick={handleClick}
|
|
106
|
+
open={_.contains(option.id)(open)}
|
|
107
|
+
canOpen={!_.isEmpty(option.children)}
|
|
108
|
+
selected={_.contains(option.id)(value)}
|
|
109
|
+
{...option}
|
|
110
|
+
/>
|
|
111
|
+
))
|
|
112
|
+
)(options);
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<Form.Dropdown
|
|
116
|
+
error={error}
|
|
117
|
+
floating
|
|
118
|
+
label={label}
|
|
119
|
+
name={name}
|
|
120
|
+
onBlur={onBlur}
|
|
121
|
+
upward={false}
|
|
122
|
+
required={required}
|
|
123
|
+
trigger={trigger}
|
|
124
|
+
multiple
|
|
125
|
+
value={value}
|
|
126
|
+
>
|
|
127
|
+
<Dropdown.Menu>
|
|
128
|
+
<Input
|
|
129
|
+
icon="search"
|
|
130
|
+
iconPosition="left"
|
|
131
|
+
className="search"
|
|
132
|
+
onKeyDown={(e) => {
|
|
133
|
+
if (e.key === " ") {
|
|
134
|
+
e.stopPropagation();
|
|
135
|
+
}
|
|
136
|
+
}}
|
|
137
|
+
onChange={handleSearch}
|
|
138
|
+
onClick={(e) => {
|
|
139
|
+
e.preventDefault();
|
|
140
|
+
e.stopPropagation();
|
|
141
|
+
}}
|
|
142
|
+
/>
|
|
143
|
+
<Dropdown.Menu scrolling>{items}</Dropdown.Menu>
|
|
144
|
+
</Dropdown.Menu>
|
|
145
|
+
</Form.Dropdown>
|
|
146
|
+
);
|
|
147
|
+
};
|
|
148
|
+
|
|
149
|
+
TreeSelector.propTypes = {
|
|
150
|
+
error: PropTypes.bool,
|
|
151
|
+
label: PropTypes.string,
|
|
152
|
+
name: PropTypes.string,
|
|
153
|
+
onBlur: PropTypes.func,
|
|
154
|
+
onChange: PropTypes.func,
|
|
155
|
+
options: PropTypes.array,
|
|
156
|
+
placeholder: PropTypes.string,
|
|
157
|
+
required: PropTypes.bool,
|
|
158
|
+
value: PropTypes.array,
|
|
159
|
+
};
|
|
160
|
+
|
|
161
|
+
export default TreeSelector;
|
|
@@ -27,7 +27,7 @@ describe("<Alert />", () => {
|
|
|
27
27
|
const wrapper = shallow(<Alert {...props} />);
|
|
28
28
|
const message = wrapper.find("Message");
|
|
29
29
|
expect(message).toHaveLength(1);
|
|
30
|
-
expect(message.prop("content"))
|
|
30
|
+
expect(wrapper.text().includes(message.prop("content")));
|
|
31
31
|
expect(message.prop("header")).toEqual("header.message.id");
|
|
32
32
|
});
|
|
33
33
|
|
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
2
|
+
import { render } from "@truedat/test/render";
|
|
3
3
|
import { CatalogMenu } from "../CatalogMenu";
|
|
4
4
|
|
|
5
5
|
jest.mock("../../hooks", () => ({
|
|
6
|
-
|
|
6
|
+
...jest.requireActual("../../hooks"),
|
|
7
7
|
useAuthorized: jest.fn(() => true),
|
|
8
8
|
}));
|
|
9
9
|
|
|
10
|
+
const renderOpts = {
|
|
11
|
+
messages: {
|
|
12
|
+
en: {},
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
10
16
|
describe("<CatalogMenu />", () => {
|
|
11
17
|
it("matches the latest snapshot", () => {
|
|
12
|
-
const
|
|
13
|
-
expect(
|
|
18
|
+
const { container } = render(<CatalogMenu />, renderOpts);
|
|
19
|
+
expect(container).toMatchSnapshot();
|
|
14
20
|
});
|
|
15
21
|
});
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { waitFor } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import { render } from "@truedat/test/render";
|
|
5
|
+
import { DOMAINS_QUERY } from "../../api/queries";
|
|
6
|
+
import DomainSelector from "../DomainSelector";
|
|
7
|
+
|
|
8
|
+
const action = "manageStructureTags";
|
|
9
|
+
|
|
10
|
+
const domainsMock = {
|
|
11
|
+
request: { query: DOMAINS_QUERY, variables: { action } },
|
|
12
|
+
result: {
|
|
13
|
+
data: {
|
|
14
|
+
domains: [
|
|
15
|
+
{ __typename: "Domain", id: "1", name: "foo", parentId: null },
|
|
16
|
+
{ __typename: "Domain", id: "2", name: "bar", parentId: "1" },
|
|
17
|
+
{ __typename: "Domain", id: "3", name: "baz", parentId: "2" },
|
|
18
|
+
{ __typename: "Domain", id: "4", name: "xyzzy", parentId: "99" },
|
|
19
|
+
],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
};
|
|
23
|
+
const messages = {
|
|
24
|
+
en: {
|
|
25
|
+
"domain.multiple.placeholder": "Select domains",
|
|
26
|
+
},
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
const renderOpts = { mocks: [domainsMock], messages };
|
|
30
|
+
|
|
31
|
+
describe("<DomainSelector />", () => {
|
|
32
|
+
it("matches latest snapshot", () => {
|
|
33
|
+
const props = { action, onChange: jest.fn() };
|
|
34
|
+
const { container } = render(<DomainSelector {...props} />, renderOpts);
|
|
35
|
+
expect(container).toMatchSnapshot();
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("calls onChange with selected values", async () => {
|
|
39
|
+
const props = { action, onChange: jest.fn() };
|
|
40
|
+
const { getByText, getByRole } = render(
|
|
41
|
+
<DomainSelector {...props} />,
|
|
42
|
+
renderOpts
|
|
43
|
+
);
|
|
44
|
+
|
|
45
|
+
await waitFor(() => {
|
|
46
|
+
expect(getByText("Select domains")).toBeTruthy();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
userEvent.click(getByText("Select domains"));
|
|
50
|
+
|
|
51
|
+
await waitFor(() => {
|
|
52
|
+
expect(getByRole("option", { name: /foo/i })).toBeTruthy();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
userEvent.click(getByRole("option", { name: /foo/i }));
|
|
56
|
+
expect(props.onChange.mock.calls.length).toBe(1);
|
|
57
|
+
expect(props.onChange.mock.calls[0][1]).toEqual({ value: ["1"] });
|
|
58
|
+
});
|
|
59
|
+
});
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { waitFor } from "@testing-library/react";
|
|
3
|
+
import userEvent from "@testing-library/user-event";
|
|
4
|
+
import { render } from "@truedat/test/render";
|
|
5
|
+
import TreeSelector from "../TreeSelector";
|
|
6
|
+
|
|
7
|
+
const baz = { id: "3", level: 2, name: "baz", children: [] };
|
|
8
|
+
const bar = { id: "2", level: 1, name: "bar", children: [baz] };
|
|
9
|
+
const foo = { id: "1", level: 0, name: "foo", children: [bar] };
|
|
10
|
+
const options = [foo, bar, baz];
|
|
11
|
+
|
|
12
|
+
const renderOpts = {};
|
|
13
|
+
const onChange = jest.fn();
|
|
14
|
+
const props = { options, placeholder: "Select a domain", onChange };
|
|
15
|
+
|
|
16
|
+
describe("<TreeSelector />", () => {
|
|
17
|
+
it("matches latest snapshot", () => {
|
|
18
|
+
const { container } = render(<TreeSelector {...props} />, renderOpts);
|
|
19
|
+
expect(container).toMatchSnapshot();
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
it("calls onChange with selected values", async () => {
|
|
23
|
+
const { getByText, getByRole } = render(
|
|
24
|
+
<TreeSelector {...props} />,
|
|
25
|
+
renderOpts
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
userEvent.click(getByText("Select a domain"));
|
|
29
|
+
|
|
30
|
+
await waitFor(() => {
|
|
31
|
+
expect(getByRole("option", { name: /foo/i })).toBeTruthy();
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
userEvent.click(getByRole("option", { name: /foo/i }));
|
|
35
|
+
expect(onChange.mock.calls.length).toBe(1);
|
|
36
|
+
expect(onChange.mock.calls[0][1]).toEqual({ value: ["1"] });
|
|
37
|
+
});
|
|
38
|
+
});
|
|
@@ -3,7 +3,13 @@
|
|
|
3
3
|
exports[`<Alert /> matches the latest snapshot 1`] = `
|
|
4
4
|
<Fragment>
|
|
5
5
|
<Message
|
|
6
|
-
content=
|
|
6
|
+
content={
|
|
7
|
+
<React.Fragment>
|
|
8
|
+
<p>
|
|
9
|
+
content.message.id
|
|
10
|
+
</p>
|
|
11
|
+
</React.Fragment>
|
|
12
|
+
}
|
|
7
13
|
error={true}
|
|
8
14
|
header="header.message.id"
|
|
9
15
|
icon="warning"
|
|
@@ -1,43 +1,101 @@
|
|
|
1
1
|
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
2
|
|
|
3
3
|
exports[`<CatalogMenu /> matches the latest snapshot 1`] = `
|
|
4
|
-
<
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
"
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
"
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
"
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
4
|
+
<div>
|
|
5
|
+
<div>
|
|
6
|
+
<div
|
|
7
|
+
aria-expanded="false"
|
|
8
|
+
class="ui item dropdown"
|
|
9
|
+
role="listbox"
|
|
10
|
+
tabindex="0"
|
|
11
|
+
>
|
|
12
|
+
<a
|
|
13
|
+
class="ui"
|
|
14
|
+
href="/structures"
|
|
15
|
+
>
|
|
16
|
+
<i
|
|
17
|
+
aria-hidden="true"
|
|
18
|
+
class="block layout large icon"
|
|
19
|
+
/>
|
|
20
|
+
</a>
|
|
21
|
+
<div
|
|
22
|
+
class="menu transition"
|
|
23
|
+
>
|
|
24
|
+
<div
|
|
25
|
+
class="header selectable"
|
|
26
|
+
>
|
|
27
|
+
catalog
|
|
28
|
+
</div>
|
|
29
|
+
<div
|
|
30
|
+
class="divider"
|
|
31
|
+
/>
|
|
32
|
+
<a
|
|
33
|
+
aria-checked="false"
|
|
34
|
+
class="item"
|
|
35
|
+
href="/structures"
|
|
36
|
+
name="structures"
|
|
37
|
+
role="option"
|
|
38
|
+
>
|
|
39
|
+
<span
|
|
40
|
+
class="text"
|
|
41
|
+
>
|
|
42
|
+
structures
|
|
43
|
+
</span>
|
|
44
|
+
</a>
|
|
45
|
+
<a
|
|
46
|
+
aria-checked="false"
|
|
47
|
+
class="item"
|
|
48
|
+
href="/structureTypes"
|
|
49
|
+
name="structureTypes"
|
|
50
|
+
role="option"
|
|
51
|
+
>
|
|
52
|
+
<span
|
|
53
|
+
class="text"
|
|
54
|
+
>
|
|
55
|
+
structureTypes
|
|
56
|
+
</span>
|
|
57
|
+
</a>
|
|
58
|
+
<a
|
|
59
|
+
aria-checked="false"
|
|
60
|
+
class="item"
|
|
61
|
+
href="/structureTags"
|
|
62
|
+
name="structureTags"
|
|
63
|
+
role="option"
|
|
64
|
+
>
|
|
65
|
+
<span
|
|
66
|
+
class="text"
|
|
67
|
+
>
|
|
68
|
+
structureTags
|
|
69
|
+
</span>
|
|
70
|
+
</a>
|
|
71
|
+
<a
|
|
72
|
+
aria-checked="false"
|
|
73
|
+
class="item"
|
|
74
|
+
href="/structureNotes"
|
|
75
|
+
name="pending_structure_notes"
|
|
76
|
+
role="option"
|
|
77
|
+
>
|
|
78
|
+
<span
|
|
79
|
+
class="text"
|
|
80
|
+
>
|
|
81
|
+
pending_structure_notes
|
|
82
|
+
</span>
|
|
83
|
+
</a>
|
|
84
|
+
<a
|
|
85
|
+
aria-checked="false"
|
|
86
|
+
class="item"
|
|
87
|
+
href="/bulk_update_template_content_events"
|
|
88
|
+
name="structures_upload_events"
|
|
89
|
+
role="option"
|
|
90
|
+
>
|
|
91
|
+
<span
|
|
92
|
+
class="text"
|
|
93
|
+
>
|
|
94
|
+
structures_upload_events
|
|
95
|
+
</span>
|
|
96
|
+
</a>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
43
101
|
`;
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
|
2
|
+
|
|
3
|
+
exports[`<TreeSelector /> matches latest snapshot 1`] = `
|
|
4
|
+
<div>
|
|
5
|
+
<div
|
|
6
|
+
class="field"
|
|
7
|
+
>
|
|
8
|
+
<div
|
|
9
|
+
aria-expanded="false"
|
|
10
|
+
aria-multiselectable="true"
|
|
11
|
+
class="ui floating multiple dropdown"
|
|
12
|
+
role="listbox"
|
|
13
|
+
tabindex="0"
|
|
14
|
+
>
|
|
15
|
+
<label>
|
|
16
|
+
Select a domain
|
|
17
|
+
</label>
|
|
18
|
+
<i
|
|
19
|
+
aria-hidden="true"
|
|
20
|
+
class="dropdown icon"
|
|
21
|
+
/>
|
|
22
|
+
<div
|
|
23
|
+
class="menu transition"
|
|
24
|
+
>
|
|
25
|
+
<div
|
|
26
|
+
class="ui left icon input search"
|
|
27
|
+
>
|
|
28
|
+
<input
|
|
29
|
+
type="text"
|
|
30
|
+
/>
|
|
31
|
+
<i
|
|
32
|
+
aria-hidden="true"
|
|
33
|
+
class="search icon"
|
|
34
|
+
/>
|
|
35
|
+
</div>
|
|
36
|
+
<div
|
|
37
|
+
class="scrolling menu transition"
|
|
38
|
+
>
|
|
39
|
+
<div
|
|
40
|
+
aria-selected="false"
|
|
41
|
+
class="item"
|
|
42
|
+
role="option"
|
|
43
|
+
>
|
|
44
|
+
<div
|
|
45
|
+
style="margin-left: 0px;"
|
|
46
|
+
>
|
|
47
|
+
<i
|
|
48
|
+
aria-hidden="true"
|
|
49
|
+
class="plus icon"
|
|
50
|
+
/>
|
|
51
|
+
foo
|
|
52
|
+
</div>
|
|
53
|
+
</div>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</div>
|
|
58
|
+
</div>
|
|
59
|
+
`;
|
package/src/components/index.js
CHANGED
|
@@ -12,6 +12,7 @@ import DashboardMenu from "./DashboardMenu";
|
|
|
12
12
|
import DateFilter from "./DateFilter";
|
|
13
13
|
import DateRangeFilter from "./DateRangeFilter";
|
|
14
14
|
import DateTime from "./DateTime";
|
|
15
|
+
import DomainSelector from "./DomainSelector";
|
|
15
16
|
import DropdownMenuItem from "./DropdownMenuItem";
|
|
16
17
|
import ErrorBoundary from "./ErrorBoundary";
|
|
17
18
|
import FiltersLoader from "./FiltersLoader";
|
|
@@ -36,6 +37,7 @@ import SidebarToggle from "./SidebarToggle";
|
|
|
36
37
|
import SideMenu from "./SideMenu";
|
|
37
38
|
import Submenu from "./Submenu";
|
|
38
39
|
import TaxonomyMenu from "./TaxonomyMenu";
|
|
40
|
+
import TreeSelector from "./TreeSelector";
|
|
39
41
|
import Unauthorized from "./Unauthorized";
|
|
40
42
|
import UploadModal from "./UploadModal";
|
|
41
43
|
|
|
@@ -54,6 +56,7 @@ export {
|
|
|
54
56
|
DateFilter,
|
|
55
57
|
DateRangeFilter,
|
|
56
58
|
DateTime,
|
|
59
|
+
DomainSelector,
|
|
57
60
|
DropdownMenuItem,
|
|
58
61
|
ErrorBoundary,
|
|
59
62
|
FiltersLoader,
|
|
@@ -78,6 +81,7 @@ export {
|
|
|
78
81
|
SideMenu,
|
|
79
82
|
Submenu,
|
|
80
83
|
TaxonomyMenu,
|
|
84
|
+
TreeSelector,
|
|
81
85
|
Unauthorized,
|
|
82
|
-
UploadModal
|
|
86
|
+
UploadModal,
|
|
83
87
|
};
|
package/src/messages/en.js
CHANGED
|
@@ -92,8 +92,8 @@ export default {
|
|
|
92
92
|
"sidemenu.rules": "Quality Rules",
|
|
93
93
|
"sidemenu.search": "Search",
|
|
94
94
|
"sidemenu.sources": "Sources",
|
|
95
|
-
"sidemenu.
|
|
96
|
-
"sidemenu.
|
|
95
|
+
"sidemenu.structureTags": "Structure Tags",
|
|
96
|
+
"sidemenu.structureTypes": "Structure Types",
|
|
97
97
|
"sidemenu.structures": "Structures",
|
|
98
98
|
"sidemenu.structures_upload_events": "My loads",
|
|
99
99
|
"sidemenu.subscriptions": "Subscriptions",
|
package/src/messages/es.js
CHANGED
|
@@ -95,8 +95,8 @@ export default {
|
|
|
95
95
|
"sidemenu.rules": "Reglas",
|
|
96
96
|
"sidemenu.search": "Búsqueda",
|
|
97
97
|
"sidemenu.sources": "Orígenes",
|
|
98
|
-
"sidemenu.
|
|
99
|
-
"sidemenu.
|
|
98
|
+
"sidemenu.structureTags": "Etiquetas de estructura",
|
|
99
|
+
"sidemenu.structureTypes": "Tipos de estructura",
|
|
100
100
|
"sidemenu.structures": "Estructuras",
|
|
101
101
|
"sidemenu.structures_upload_events": "Mis cargas",
|
|
102
102
|
"sidemenu.subscriptions": "Suscripciones",
|
package/src/routes.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
2
|
import { compile } from "path-to-regexp";
|
|
3
3
|
|
|
4
|
-
export const GRANT_REQUEST_APPROVALS = "/grant_request_approvals";
|
|
5
4
|
export const CALLBACK = "/callback";
|
|
6
|
-
export const CONCEPT_VERSION = "/concepts/:business_concept_id/versions/:id";
|
|
7
5
|
export const CONCEPTS = "/concepts";
|
|
8
6
|
export const CONCEPTS_BULK_UPDATE = "/concepts/bulk_update";
|
|
9
7
|
export const CONCEPTS_NEW = "/concepts/new";
|
|
@@ -17,17 +15,17 @@ export const CONCEPT_LINKS_CONCEPTS =
|
|
|
17
15
|
"/concepts/:business_concept_id/versions/:id/links/concepts";
|
|
18
16
|
export const CONCEPT_LINKS_CONCEPTS_NEW =
|
|
19
17
|
"/concepts/:business_concept_id/versions/:id/links/concepts/new";
|
|
18
|
+
export const CONCEPT_LINKS_IMPLEMENTATIONS =
|
|
19
|
+
"/concepts/:business_concept_id/versions/:id/links/implementations";
|
|
20
20
|
export const CONCEPT_LINKS_STRUCTURES =
|
|
21
21
|
"/concepts/:business_concept_id/versions/:id/links/structures";
|
|
22
22
|
export const CONCEPT_LINKS_STRUCTURES_NEW =
|
|
23
23
|
"/concepts/:business_concept_id/versions/:id/links/structures/new";
|
|
24
|
-
|
|
25
|
-
export const CONCEPT_LINKS_IMPLEMENTATIONS =
|
|
26
|
-
"/concepts/:business_concept_id/versions/:id/links/implementations";
|
|
27
24
|
export const CONCEPT_RULES =
|
|
28
25
|
"/concepts/:business_concept_id/versions/:id/rules";
|
|
29
26
|
export const CONCEPT_RULES_NEW =
|
|
30
27
|
"/concepts/:business_concept_id/versions/:id/rules/new";
|
|
28
|
+
export const CONCEPT_VERSION = "/concepts/:business_concept_id/versions/:id";
|
|
31
29
|
export const CONFIGURATION = "/configurations/:external_id";
|
|
32
30
|
export const CONFIGURATIONS = "/configurations";
|
|
33
31
|
export const CONFIGURATION_CREATE = "/configurations/new";
|
|
@@ -44,11 +42,11 @@ export const DOMAIN_MEMBERS = "/domains/:id/members";
|
|
|
44
42
|
export const DOMAIN_MEMBERS_NEW = "/domains/:id/members/new";
|
|
45
43
|
export const DOMAIN_NEW = "/domains/:id/new";
|
|
46
44
|
export const EXECUTION_GROUP = "/executionGroups/:id";
|
|
47
|
-
export const GRANT_REQUESTS = "/grant_requests";
|
|
48
|
-
export const GRANT_REQUEST = "/grant_requests/:id";
|
|
49
|
-
|
|
50
45
|
export const GRANTS = "/grants";
|
|
51
46
|
export const GRANTS_REQUESTS_CHECKOUT = "/grants_requests/checkout";
|
|
47
|
+
export const GRANT_REQUEST = "/grant_requests/:id";
|
|
48
|
+
export const GRANT_REQUESTS = "/grant_requests";
|
|
49
|
+
export const GRANT_REQUEST_APPROVALS = "/grant_request_approvals";
|
|
52
50
|
export const GRAPH = "/graphs/:id";
|
|
53
51
|
export const GRAPHS = "/graphs";
|
|
54
52
|
export const GROUP = "/groups/:id";
|
|
@@ -83,20 +81,19 @@ export const JOB = "/jobs/:id";
|
|
|
83
81
|
export const JOBS = "/jobs";
|
|
84
82
|
export const LINEAGE_EVENTS = "/lineage_events";
|
|
85
83
|
export const LOGIN = "/login";
|
|
86
|
-
export const MY_GRANT_REQUESTS = "/my_grant_requests";
|
|
87
84
|
export const MY_GRANTS = "/my_grants";
|
|
85
|
+
export const MY_GRANT_REQUESTS = "/my_grant_requests";
|
|
88
86
|
export const PASSWORD = "/password";
|
|
89
|
-
export const PENDING_STRUCTURE_NOTES = "/
|
|
87
|
+
export const PENDING_STRUCTURE_NOTES = "/structureNotes";
|
|
90
88
|
export const PROFILE_EXECUTION =
|
|
91
89
|
"/profileGroups/:group_id/profileExecutions/:id";
|
|
92
90
|
export const PROFILE_GROUP = "/profileGroups/:id";
|
|
93
91
|
export const QUALITY_DASHBOARD = "/quality_dashboard";
|
|
94
|
-
|
|
95
|
-
export const REMEDIATION_PLAN = "/rule_results/:rule_result_id/remediation";
|
|
96
92
|
export const REMEDIATION_EDIT =
|
|
97
|
-
"/rules/:id/implementations/:implementation_id/
|
|
93
|
+
"/rules/:id/implementations/:implementation_id/results/:rule_result_id/remediation/edit";
|
|
98
94
|
export const REMEDIATION_NEW =
|
|
99
|
-
"/rules/:id/implementations/:implementation_id/
|
|
95
|
+
"/rules/:id/implementations/:implementation_id/results/:rule_result_id/remediation/new";
|
|
96
|
+
export const REMEDIATION_PLAN = "/rule_results/:rule_result_id/remediation";
|
|
100
97
|
export const ROLE = "/roles/:id";
|
|
101
98
|
export const ROLES = "/roles";
|
|
102
99
|
export const ROLES_NEW = "/roles/new";
|
|
@@ -107,20 +104,22 @@ export const RULE_EVENTS = "/rules/:id/events";
|
|
|
107
104
|
export const RULE_IMPLEMENTATION =
|
|
108
105
|
"/rules/:id/implementations/:implementation_id(\\d+)";
|
|
109
106
|
export const RULE_IMPLEMENTATIONS = "/rules/:id/implementations";
|
|
110
|
-
export const RULE_IMPLEMENTATION_EVENTS =
|
|
111
|
-
"/rules/:id/implementations/:implementation_id/events";
|
|
112
|
-
export const RULE_IMPLEMENTATION_NEW = "/rules/:id/implementations/new";
|
|
113
|
-
export const RULE_IMPLEMENTATION_EDIT =
|
|
114
|
-
"/rules/:id/implementations/:implementation_id/edit";
|
|
115
107
|
export const RULE_IMPLEMENTATION_CLONE =
|
|
116
108
|
"/rules/:id/implementations/:implementation_id/clone";
|
|
109
|
+
export const RULE_IMPLEMENTATION_EDIT =
|
|
110
|
+
"/rules/:id/implementations/:implementation_id/edit";
|
|
111
|
+
export const RULE_IMPLEMENTATION_EVENTS =
|
|
112
|
+
"/rules/:id/implementations/:implementation_id/events";
|
|
117
113
|
export const RULE_IMPLEMENTATION_MOVE =
|
|
118
114
|
"/rules/:id/implementations/:implementation_id/move";
|
|
115
|
+
export const RULE_IMPLEMENTATION_NEW = "/rules/:id/implementations/new";
|
|
119
116
|
export const RULE_IMPLEMENTATION_RESULT_DETAILS =
|
|
120
117
|
"/rules/:id/implementations/:implementation_id/results/:rule_result_id";
|
|
118
|
+
export const RULE_IMPLEMENTATION_RESULT_DETAILS_REMEDIATION_PLAN =
|
|
119
|
+
"/rules/:id/implementations/:implementation_id/results/:rule_result_id/remediation_plan";
|
|
121
120
|
export const RULE_IMPLEMENTATION_RESULT_SEGMENTS_RESULTS =
|
|
122
121
|
"/rules/:id/implementations/:implementation_id/results/:rule_result_id/segment_results";
|
|
123
|
-
export const
|
|
122
|
+
export const RULE_IMPLEMENTATION_RESULT_REMEDIATION_PLAN =
|
|
124
123
|
"/rules/:id/implementations/:implementation_id/results/:rule_result_id/remediation_plan";
|
|
125
124
|
export const RULE_IMPLEMENTATION_RESULTS =
|
|
126
125
|
"/rules/:id/implementations/:implementation_id/results";
|
|
@@ -157,11 +156,11 @@ export const STRUCTURE_PARENTS = "/structures/:id/parents";
|
|
|
157
156
|
export const STRUCTURE_PROFILE = "/structures/:id/profile";
|
|
158
157
|
export const STRUCTURE_RULES_IMPLEMENTATIONS =
|
|
159
158
|
"/structures/:id/rules_implementations";
|
|
160
|
-
export const STRUCTURE_TAGS = "/
|
|
161
|
-
export const
|
|
162
|
-
export const
|
|
163
|
-
export const STRUCTURE_TYPES = "/
|
|
164
|
-
export const STRUCTURE_TYPES_EDIT = "/
|
|
159
|
+
export const STRUCTURE_TAGS = "/structureTags";
|
|
160
|
+
export const STRUCTURE_TAGS_EDIT = "/structureTags/:id/edit";
|
|
161
|
+
export const STRUCTURE_TAGS_NEW = "/structureTags/new";
|
|
162
|
+
export const STRUCTURE_TYPES = "/structureTypes";
|
|
163
|
+
export const STRUCTURE_TYPES_EDIT = "/structureTypes/:id/edit";
|
|
165
164
|
export const STRUCTURE_VERSION = "/structures/:id/versions/:version";
|
|
166
165
|
export const STRUCTURE_VERSIONS = "/structures/:id/versions";
|
|
167
166
|
export const STRUCTURE_VERSION_VERSIONS =
|
|
@@ -169,8 +168,8 @@ export const STRUCTURE_VERSION_VERSIONS =
|
|
|
169
168
|
export const STRUCTURES_UPLOAD_EVENTS = "/bulk_update_template_content_events";
|
|
170
169
|
export const SUBSCRIPTION = "/subscriptions/:id";
|
|
171
170
|
export const SUBSCRIPTIONS = "/subscriptions";
|
|
172
|
-
export const SUBSCRIPTION_NEW = "/subscriptions/new";
|
|
173
171
|
export const SUBSCRIPTION_EDIT = "/subscriptions/:id/edit";
|
|
172
|
+
export const SUBSCRIPTION_NEW = "/subscriptions/new";
|
|
174
173
|
export const SYSTEMS = "/systems";
|
|
175
174
|
export const SYSTEM_EDIT = "/systems/:id/edit";
|
|
176
175
|
export const SYSTEM_NEW = "/systems/new";
|
|
@@ -190,133 +189,142 @@ export const USER_EDIT = "/users/:id/edit";
|
|
|
190
189
|
export const USER_EDIT_PASSWORD = "/users/:id/password";
|
|
191
190
|
|
|
192
191
|
const routes = {
|
|
193
|
-
GRANT_REQUEST_APPROVALS,
|
|
194
192
|
CALLBACK,
|
|
193
|
+
CONCEPTS,
|
|
194
|
+
CONCEPTS_BULK_UPDATE,
|
|
195
|
+
CONCEPTS_NEW,
|
|
196
|
+
CONCEPTS_PENDING,
|
|
195
197
|
CONCEPT_ARCHIVE,
|
|
196
198
|
CONCEPT_EDIT,
|
|
197
199
|
CONCEPT_EVENTS,
|
|
198
|
-
CONCEPT_LINKS_CONCEPTS_NEW,
|
|
199
200
|
CONCEPT_LINKS_CONCEPTS,
|
|
200
|
-
|
|
201
|
-
CONCEPT_LINKS_STRUCTURES,
|
|
201
|
+
CONCEPT_LINKS_CONCEPTS_NEW,
|
|
202
202
|
CONCEPT_LINKS_IMPLEMENTATIONS,
|
|
203
|
-
|
|
203
|
+
CONCEPT_LINKS_STRUCTURES,
|
|
204
|
+
CONCEPT_LINKS_STRUCTURES_NEW,
|
|
204
205
|
CONCEPT_RULES,
|
|
206
|
+
CONCEPT_RULES_NEW,
|
|
205
207
|
CONCEPT_VERSION,
|
|
206
|
-
CONCEPTS_BULK_UPDATE,
|
|
207
|
-
CONCEPTS_NEW,
|
|
208
|
-
CONCEPTS_PENDING,
|
|
209
|
-
CONCEPTS,
|
|
210
|
-
CONFIGURATION_EDIT,
|
|
211
208
|
CONFIGURATION,
|
|
209
|
+
CONFIGURATION_EDIT,
|
|
212
210
|
DASHBOARD,
|
|
213
|
-
DOMAIN_ACTION,
|
|
214
|
-
DOMAIN_EDIT,
|
|
215
|
-
DOMAIN_MEMBERS_NEW,
|
|
216
|
-
DOMAIN_MEMBERS,
|
|
217
|
-
DOMAIN_NEW,
|
|
218
211
|
DOMAIN,
|
|
212
|
+
DOMAINS,
|
|
219
213
|
DOMAINS_ACTIONS,
|
|
220
214
|
DOMAINS_NEW,
|
|
221
215
|
DOMAINS_SEARCH,
|
|
222
|
-
|
|
216
|
+
DOMAIN_ACTION,
|
|
217
|
+
DOMAIN_EDIT,
|
|
218
|
+
DOMAIN_MEMBERS,
|
|
219
|
+
DOMAIN_MEMBERS_NEW,
|
|
220
|
+
DOMAIN_NEW,
|
|
223
221
|
EXECUTION_GROUP,
|
|
224
|
-
GRANT_REQUEST,
|
|
225
|
-
GRANT_REQUESTS,
|
|
226
222
|
GRANTS,
|
|
227
223
|
GRANTS_REQUESTS_CHECKOUT,
|
|
224
|
+
GRANT_REQUEST,
|
|
225
|
+
GRANT_REQUESTS,
|
|
226
|
+
GRANT_REQUEST_APPROVALS,
|
|
228
227
|
GRAPH,
|
|
229
228
|
GRAPHS,
|
|
230
|
-
GROUP_CREATE,
|
|
231
|
-
GROUP_EDIT,
|
|
232
229
|
GROUP,
|
|
233
230
|
GROUPS,
|
|
231
|
+
GROUP_CREATE,
|
|
232
|
+
GROUP_EDIT,
|
|
234
233
|
IMPLEMENTATIONS,
|
|
234
|
+
IMPLEMENTATION_CONCEPT_LINKS,
|
|
235
|
+
IMPLEMENTATION_CONCEPT_LINKS_NEW,
|
|
236
|
+
IMPLEMENTATION_STRUCTURES,
|
|
237
|
+
IMPLEMENTATION_STRUCTURES_NEW,
|
|
238
|
+
INGEST,
|
|
239
|
+
INGESTS,
|
|
240
|
+
INGESTS_NEW,
|
|
241
|
+
INGESTS_PENDING,
|
|
235
242
|
INGEST_ARCHIVE,
|
|
236
243
|
INGEST_DUPLICATE,
|
|
237
244
|
INGEST_EDIT,
|
|
238
245
|
INGEST_EVENTS,
|
|
239
246
|
INGEST_EXECUTIONS,
|
|
240
|
-
INGEST_RELATIONS_INGESTS_NEW,
|
|
241
247
|
INGEST_RELATIONS_INGESTS,
|
|
242
|
-
|
|
248
|
+
INGEST_RELATIONS_INGESTS_NEW,
|
|
243
249
|
INGEST_RELATIONS_STRUCTURES,
|
|
244
|
-
|
|
245
|
-
INGESTS_NEW,
|
|
246
|
-
INGESTS_PENDING,
|
|
247
|
-
INGESTS,
|
|
250
|
+
INGEST_RELATIONS_STRUCTURES_NEW,
|
|
248
251
|
JOB,
|
|
249
252
|
JOBS,
|
|
250
253
|
LINEAGE_EVENTS,
|
|
251
254
|
LOGIN,
|
|
252
|
-
MY_GRANT_REQUESTS,
|
|
253
255
|
MY_GRANTS,
|
|
256
|
+
MY_GRANT_REQUESTS,
|
|
254
257
|
PASSWORD,
|
|
255
258
|
PENDING_STRUCTURE_NOTES,
|
|
256
259
|
PROFILE_EXECUTION,
|
|
257
260
|
PROFILE_GROUP,
|
|
258
261
|
QUALITY_DASHBOARD,
|
|
259
|
-
REMEDIATION_PLAN,
|
|
260
262
|
REMEDIATION_EDIT,
|
|
261
263
|
REMEDIATION_NEW,
|
|
264
|
+
REMEDIATION_PLAN,
|
|
262
265
|
ROLE,
|
|
263
|
-
ROLES_NEW,
|
|
264
266
|
ROLES,
|
|
267
|
+
ROLES_NEW,
|
|
268
|
+
RULE,
|
|
269
|
+
RULES,
|
|
265
270
|
RULE_EDIT,
|
|
266
271
|
RULE_EVENTS,
|
|
272
|
+
RULE_IMPLEMENTATION,
|
|
273
|
+
RULE_IMPLEMENTATIONS,
|
|
267
274
|
RULE_IMPLEMENTATION_CLONE,
|
|
268
275
|
RULE_IMPLEMENTATION_EDIT,
|
|
269
276
|
RULE_IMPLEMENTATION_EVENTS,
|
|
270
|
-
IMPLEMENTATION_CONCEPT_LINKS,
|
|
271
|
-
IMPLEMENTATION_CONCEPT_LINKS_NEW,
|
|
272
|
-
IMPLEMENTATION_STRUCTURES,
|
|
273
|
-
IMPLEMENTATION_STRUCTURES_NEW,
|
|
274
277
|
RULE_IMPLEMENTATION_MOVE,
|
|
275
278
|
RULE_IMPLEMENTATION_NEW,
|
|
279
|
+
RULE_IMPLEMENTATION_RESULTS,
|
|
280
|
+
RULE_IMPLEMENTATION_RESULTS_DETAILS,
|
|
276
281
|
RULE_IMPLEMENTATION_RESULT_DETAILS,
|
|
277
|
-
RULE_IMPLEMENTATION_RESULT_SEGMENTS_RESULTS,
|
|
278
282
|
RULE_IMPLEMENTATION_RESULT_DETAILS_REMEDIATION_PLAN,
|
|
283
|
+
RULE_IMPLEMENTATION_RESULT_SEGMENTS_RESULTS,
|
|
284
|
+
RULE_IMPLEMENTATION_RESULT_SEGMENTS_RESULTS,
|
|
285
|
+
RULE_IMPLEMENTATION_RESULT_REMEDIATION_PLAN,
|
|
279
286
|
RULE_IMPLEMENTATION_RESULTS_DETAILS,
|
|
280
287
|
RULE_IMPLEMENTATION_RESULTS,
|
|
281
288
|
RULE_IMPLEMENTATION,
|
|
282
289
|
RULE_IMPLEMENTATIONS,
|
|
283
290
|
RULE_NEW,
|
|
284
|
-
RULE,
|
|
285
|
-
RULES,
|
|
286
291
|
SAMPLE,
|
|
292
|
+
SEARCH,
|
|
287
293
|
SEARCH_CONCEPTS,
|
|
288
294
|
SEARCH_INGESTS,
|
|
289
295
|
SEARCH_RESULTS,
|
|
290
296
|
SEARCH_STRUCTURES,
|
|
291
|
-
|
|
297
|
+
SOURCE,
|
|
298
|
+
SOURCES,
|
|
292
299
|
SOURCES_NEW,
|
|
293
300
|
SOURCE_EDIT,
|
|
294
301
|
SOURCE_JOB,
|
|
295
|
-
SOURCE_JOBS_NEW,
|
|
296
302
|
SOURCE_JOBS,
|
|
297
|
-
|
|
298
|
-
|
|
303
|
+
SOURCE_JOBS_NEW,
|
|
304
|
+
STRUCTURE,
|
|
305
|
+
STRUCTURES,
|
|
306
|
+
STRUCTURES_BULK_UPDATE,
|
|
299
307
|
STRUCTURE_CHILDREN,
|
|
300
308
|
STRUCTURE_EVENTS,
|
|
301
309
|
STRUCTURE_GRANTS,
|
|
302
310
|
STRUCTURE_IMPACT,
|
|
303
311
|
STRUCTURE_LINEAGE,
|
|
304
|
-
STRUCTURE_LINKS_NEW,
|
|
305
312
|
STRUCTURE_LINKS,
|
|
313
|
+
STRUCTURE_LINKS_NEW,
|
|
306
314
|
STRUCTURE_METADATA,
|
|
307
|
-
STRUCTURE_NOTES_EDIT,
|
|
308
315
|
STRUCTURE_NOTES,
|
|
316
|
+
STRUCTURE_NOTES_EDIT,
|
|
309
317
|
STRUCTURE_PARENTS,
|
|
310
318
|
STRUCTURE_PROFILE,
|
|
311
319
|
STRUCTURE_RULES_IMPLEMENTATIONS,
|
|
320
|
+
STRUCTURE_TAGS,
|
|
312
321
|
STRUCTURE_TAGS_EDIT,
|
|
313
322
|
STRUCTURE_TAGS_NEW,
|
|
314
|
-
STRUCTURE_TAGS,
|
|
315
|
-
STRUCTURE_TYPES_EDIT,
|
|
316
323
|
STRUCTURE_TYPES,
|
|
317
|
-
|
|
324
|
+
STRUCTURE_TYPES_EDIT,
|
|
318
325
|
STRUCTURE_VERSION,
|
|
319
326
|
STRUCTURE_VERSIONS,
|
|
327
|
+
STRUCTURE_VERSION_VERSIONS,
|
|
320
328
|
STRUCTURE,
|
|
321
329
|
STRUCTURES_BULK_UPDATE,
|
|
322
330
|
STRUCTURES,
|
|
@@ -325,23 +333,25 @@ const routes = {
|
|
|
325
333
|
SUBSCRIPTION_NEW,
|
|
326
334
|
SUBSCRIPTION,
|
|
327
335
|
SUBSCRIPTIONS,
|
|
336
|
+
SUBSCRIPTION_EDIT,
|
|
337
|
+
SUBSCRIPTION_NEW,
|
|
338
|
+
SYSTEMS,
|
|
328
339
|
SYSTEM_EDIT,
|
|
329
340
|
SYSTEM_NEW,
|
|
330
341
|
SYSTEM_STRUCTURES,
|
|
331
|
-
SYSTEMS,
|
|
332
|
-
TAGS_NEW,
|
|
333
342
|
TAGS,
|
|
334
|
-
|
|
335
|
-
TEMPLATE_SCOPE,
|
|
343
|
+
TAGS_NEW,
|
|
336
344
|
TEMPLATE,
|
|
337
|
-
TEMPLATES_NEW,
|
|
338
345
|
TEMPLATES,
|
|
346
|
+
TEMPLATES_NEW,
|
|
347
|
+
TEMPLATE_EDIT,
|
|
348
|
+
TEMPLATE_SCOPE,
|
|
339
349
|
UNAUTHORIZED,
|
|
340
|
-
USER_EDIT_PASSWORD,
|
|
341
|
-
USER_EDIT,
|
|
342
350
|
USER,
|
|
343
|
-
USERS_NEW,
|
|
344
351
|
USERS,
|
|
352
|
+
USERS_NEW,
|
|
353
|
+
USER_EDIT,
|
|
354
|
+
USER_EDIT_PASSWORD,
|
|
345
355
|
};
|
|
346
356
|
|
|
347
357
|
export const linkTo = _.mapValues(compile)(routes);
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import {
|
|
3
|
+
flatten,
|
|
4
|
+
childIds,
|
|
5
|
+
descendents,
|
|
6
|
+
recursiveMatch,
|
|
7
|
+
stratify,
|
|
8
|
+
} from "../tree";
|
|
9
|
+
|
|
10
|
+
const baz = { id: "3", name: "baz", children: [] };
|
|
11
|
+
const bar = { id: "2", name: "bar", children: [baz] };
|
|
12
|
+
const foo = { id: "1", name: "foo", children: [bar] };
|
|
13
|
+
const options = [foo];
|
|
14
|
+
|
|
15
|
+
describe("stratify", () => {
|
|
16
|
+
it("stratifies options", () => {
|
|
17
|
+
const foo = { id: 1, name: "foo" };
|
|
18
|
+
const bar = { id: 2, name: "bar", parentId: 1 };
|
|
19
|
+
const baz = { id: 3, name: "baz", parentId: 2 };
|
|
20
|
+
const xyzzy = { id: 4, name: "xyzzy", parentId: 99 };
|
|
21
|
+
const options = [foo, bar, baz, xyzzy];
|
|
22
|
+
const res = stratify({})(options);
|
|
23
|
+
expect(res).toEqual([
|
|
24
|
+
{
|
|
25
|
+
...foo,
|
|
26
|
+
level: 0,
|
|
27
|
+
children: [{ ...bar, children: [{ ...baz, children: [] }] }],
|
|
28
|
+
},
|
|
29
|
+
{ ...xyzzy, level: 0, children: [] },
|
|
30
|
+
]);
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
describe("flatten", () => {
|
|
35
|
+
it("flattens stratified options and assigns level", () => {
|
|
36
|
+
const res = flatten(options);
|
|
37
|
+
expect(res).toEqual([
|
|
38
|
+
{ ...foo, level: 0 },
|
|
39
|
+
{ ...bar, level: 1 },
|
|
40
|
+
{ ...baz, level: 2 },
|
|
41
|
+
]);
|
|
42
|
+
});
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
describe("childIds", () => {
|
|
46
|
+
it("returns ids of children", () => {
|
|
47
|
+
const res = childIds("1")(options);
|
|
48
|
+
expect(res).toEqual(["2"]);
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
describe("descendents", () => {
|
|
53
|
+
it("returns descendent ids", () => {
|
|
54
|
+
const res = _.flatMap(descendents)(options);
|
|
55
|
+
expect(res).toEqual(["1", "2", "3"]);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("recursiveMatch", () => {
|
|
60
|
+
it("matches recursively", () => {
|
|
61
|
+
const match =
|
|
62
|
+
(query) =>
|
|
63
|
+
({ name }) =>
|
|
64
|
+
_.contains(query)(name);
|
|
65
|
+
const res = _.filter(recursiveMatch(match)("baz"))(options);
|
|
66
|
+
expect(res).toEqual([foo]);
|
|
67
|
+
});
|
|
68
|
+
});
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
|
|
3
|
+
const idFn = (d) => d.id;
|
|
4
|
+
const parentFn = (d) => d.parentId;
|
|
5
|
+
const nodeFn = ({ id, name, ...props }) => ({
|
|
6
|
+
id,
|
|
7
|
+
name,
|
|
8
|
+
children: [],
|
|
9
|
+
...props,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
export const stratify = (options) => (data) => {
|
|
13
|
+
const { node = nodeFn, id = idFn, parent = parentFn } = options || {};
|
|
14
|
+
const root = { children: [] };
|
|
15
|
+
const nodes = data.reduce((acc, d) => ({ ...acc, [id(d)]: node(d) }), {
|
|
16
|
+
root,
|
|
17
|
+
});
|
|
18
|
+
for (const d of data) {
|
|
19
|
+
const n = nodes[id(d)];
|
|
20
|
+
const p = nodes[parent(d)] || root;
|
|
21
|
+
p.children.push(n);
|
|
22
|
+
}
|
|
23
|
+
return root.children.map((c) => ({ ...c, level: 0 }));
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export const flatten = (data, level = 0) =>
|
|
27
|
+
data.flatMap((d) =>
|
|
28
|
+
d.children?.length
|
|
29
|
+
? [{ ...d, level }, ...flatten(d.children, level + 1)]
|
|
30
|
+
: [{ ...d, level }]
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
export const recursiveMatch = (match) => (query) => (d) =>
|
|
34
|
+
match(query)(d) || _.some(recursiveMatch(match)(query))(d?.children);
|
|
35
|
+
|
|
36
|
+
export const descendents = ({ id, children }) =>
|
|
37
|
+
_.isArray(children) ? [id, ...children.flatMap(descendents)] : [id];
|
|
38
|
+
|
|
39
|
+
export const childIds = (ids) =>
|
|
40
|
+
_.flow(
|
|
41
|
+
_.filter(({ id }) => _.contains(id)(ids)),
|
|
42
|
+
_.flatMap("children"),
|
|
43
|
+
_.map("id")
|
|
44
|
+
);
|