@truedat/bg 5.8.1 → 5.8.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 +6 -6
- package/src/concepts/components/ConceptLinksDropdownSelector.js +55 -0
- package/src/concepts/components/ConceptsLinksManagement.js +201 -97
- package/src/concepts/components/__tests__/ConceptLinksManagement.spec.js +0 -1
- package/src/concepts/components/__tests__/__snapshots__/ConceptLinksManagement.spec.js.snap +65 -1
- package/src/concepts/relations/components/ConceptRelationForm.js +55 -91
- package/src/concepts/relations/components/ConceptSelector.js +28 -1
- package/src/concepts/relations/components/__tests__/ConceptRelationForm.spec.js +103 -64
- package/src/concepts/relations/components/__tests__/__snapshots__/ConceptRelationForm.spec.js.snap +189 -51
- package/src/messages/en.js +6 -3
- package/src/messages/es.js +6 -3
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/bg",
|
|
3
|
-
"version": "5.8.
|
|
3
|
+
"version": "5.8.3",
|
|
4
4
|
"description": "Truedat Web Business Glossary",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"jsnext:main": "src/index.js",
|
|
@@ -34,7 +34,7 @@
|
|
|
34
34
|
"@testing-library/jest-dom": "^5.16.5",
|
|
35
35
|
"@testing-library/react": "^12.0.0",
|
|
36
36
|
"@testing-library/user-event": "^13.2.1",
|
|
37
|
-
"@truedat/test": "5.8.
|
|
37
|
+
"@truedat/test": "5.8.3",
|
|
38
38
|
"babel-jest": "^28.1.0",
|
|
39
39
|
"babel-plugin-dynamic-import-node": "^2.3.3",
|
|
40
40
|
"babel-plugin-lodash": "^3.3.4",
|
|
@@ -86,9 +86,9 @@
|
|
|
86
86
|
]
|
|
87
87
|
},
|
|
88
88
|
"dependencies": {
|
|
89
|
-
"@truedat/core": "5.8.
|
|
90
|
-
"@truedat/df": "5.8.
|
|
91
|
-
"@truedat/lm": "5.8.
|
|
89
|
+
"@truedat/core": "5.8.3",
|
|
90
|
+
"@truedat/df": "5.8.3",
|
|
91
|
+
"@truedat/lm": "5.8.3",
|
|
92
92
|
"decode-uri-component": "^0.2.2",
|
|
93
93
|
"file-saver": "^2.0.5",
|
|
94
94
|
"moment": "^2.29.4",
|
|
@@ -111,5 +111,5 @@
|
|
|
111
111
|
"react-dom": ">= 16.8.6 < 17",
|
|
112
112
|
"semantic-ui-react": ">= 2.0.3 < 2.2"
|
|
113
113
|
},
|
|
114
|
-
"gitHead": "
|
|
114
|
+
"gitHead": "36771348dbfbdb680f5694454d7549bca927cbaa"
|
|
115
115
|
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import _ from "lodash/fp";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import PropTypes from "prop-types";
|
|
4
|
+
import { Form, Dropdown } from "semantic-ui-react";
|
|
5
|
+
import { FormattedMessage, useIntl } from "react-intl";
|
|
6
|
+
|
|
7
|
+
const formatOption = (formatMessage) => (options) =>
|
|
8
|
+
_.flow(
|
|
9
|
+
_.map(({ value, text }) =>
|
|
10
|
+
_.isNil(text) || text == ""
|
|
11
|
+
? { value, text }
|
|
12
|
+
: {
|
|
13
|
+
value,
|
|
14
|
+
text: formatMessage({
|
|
15
|
+
id: `conceptRelations.${text}`,
|
|
16
|
+
defaultMessage: formatMessage({ id: text, defaultMessage: text }),
|
|
17
|
+
}),
|
|
18
|
+
}
|
|
19
|
+
)
|
|
20
|
+
)(options);
|
|
21
|
+
|
|
22
|
+
export const ConceptLinksDropdownSelector = ({
|
|
23
|
+
defaultOption,
|
|
24
|
+
options,
|
|
25
|
+
handleChange,
|
|
26
|
+
}) => {
|
|
27
|
+
const { formatMessage } = useIntl();
|
|
28
|
+
|
|
29
|
+
return (
|
|
30
|
+
<Form.Field>
|
|
31
|
+
<label>
|
|
32
|
+
<b>
|
|
33
|
+
<FormattedMessage id="conceptRelations.linkType" />
|
|
34
|
+
</b>
|
|
35
|
+
</label>
|
|
36
|
+
<div>
|
|
37
|
+
<Dropdown
|
|
38
|
+
className="concept-link-dropdown"
|
|
39
|
+
value={defaultOption}
|
|
40
|
+
selection
|
|
41
|
+
options={formatOption(formatMessage)(options)}
|
|
42
|
+
onChange={(_e, { value }) => handleChange(value)}
|
|
43
|
+
/>
|
|
44
|
+
</div>
|
|
45
|
+
</Form.Field>
|
|
46
|
+
);
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
ConceptLinksDropdownSelector.propTypes = {
|
|
50
|
+
setSelectedLinkType: PropTypes.func,
|
|
51
|
+
options: PropTypes.array,
|
|
52
|
+
defaultOption: PropTypes.string,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
export default ConceptLinksDropdownSelector;
|
|
@@ -18,6 +18,12 @@ import {
|
|
|
18
18
|
import { createRelation, deleteRelation } from "@truedat/core/routines";
|
|
19
19
|
import ConceptSelector from "../relations/components/ConceptSelector";
|
|
20
20
|
import { fetchConcepts } from "../routines";
|
|
21
|
+
import { pickConceptAttrs } from "../relations/components/ConceptRelationForm";
|
|
22
|
+
import ConceptLinksDropdownSelector from "./ConceptLinksDropdownSelector";
|
|
23
|
+
import ConceptUserFiltersLoader from "./ConceptUserFiltersLoader";
|
|
24
|
+
const RelationsLoader = React.lazy(() =>
|
|
25
|
+
import("@truedat/lm/components/RelationsLoader")
|
|
26
|
+
);
|
|
21
27
|
|
|
22
28
|
const TagTypeDropdownSelector = React.lazy(() =>
|
|
23
29
|
import("@truedat/lm/components/TagTypeDropdownSelector")
|
|
@@ -32,12 +38,19 @@ const linksDefaultFilters = {
|
|
|
32
38
|
status: ["pending_approval", "draft", "rejected", "published"],
|
|
33
39
|
};
|
|
34
40
|
|
|
41
|
+
const linkOptions = [
|
|
42
|
+
{ value: "structures", text: "structures" },
|
|
43
|
+
{ value: "concepts", text: "concepts" },
|
|
44
|
+
];
|
|
45
|
+
|
|
35
46
|
const STATUS_PENDING = "pending";
|
|
36
47
|
const STATUS_CREATED = "created";
|
|
37
48
|
const STATUS_DELETED = "deleted";
|
|
38
49
|
|
|
39
50
|
const LinkedMessage = ({
|
|
40
|
-
|
|
51
|
+
selectedSourceConcept,
|
|
52
|
+
selectedTargetConcept,
|
|
53
|
+
selectedLinkType,
|
|
41
54
|
selectedStructure,
|
|
42
55
|
selectedTag,
|
|
43
56
|
status,
|
|
@@ -54,27 +67,41 @@ const LinkedMessage = ({
|
|
|
54
67
|
<Message success={status !== STATUS_PENDING} floating>
|
|
55
68
|
<Message.Header>{messagesMap[status]}</Message.Header>
|
|
56
69
|
<Message.List>
|
|
57
|
-
{
|
|
70
|
+
{selectedSourceConcept ? (
|
|
58
71
|
<Message.Item>
|
|
59
|
-
{formatMessage({ id: "conceptRelations.
|
|
60
|
-
{": "} {
|
|
72
|
+
{formatMessage({ id: "conceptRelations.from" })}
|
|
73
|
+
{": "} {selectedSourceConcept.name}
|
|
61
74
|
</Message.Item>
|
|
62
75
|
) : null}
|
|
63
76
|
{selectedStructure ? (
|
|
64
77
|
<Message.Item>
|
|
65
|
-
{formatMessage({ id: "conceptRelations.
|
|
78
|
+
{formatMessage({ id: "conceptRelations.to" })}
|
|
66
79
|
{": "}
|
|
67
80
|
{selectedStructure.name}
|
|
68
81
|
</Message.Item>
|
|
82
|
+
) : selectedTargetConcept ? (
|
|
83
|
+
<Message.Item>
|
|
84
|
+
{formatMessage({ id: "conceptRelations.to" })}
|
|
85
|
+
{": "}
|
|
86
|
+
{selectedTargetConcept.name}
|
|
87
|
+
</Message.Item>
|
|
69
88
|
) : null}
|
|
70
89
|
{selectedTag ? (
|
|
71
90
|
<Message.Item>
|
|
72
91
|
{formatMessage({ id: "conceptRelations.tag" })}
|
|
73
92
|
{": "}
|
|
74
|
-
{
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
93
|
+
{selectedLinkType === "structures"
|
|
94
|
+
? formatMessage({
|
|
95
|
+
id: selectedTag.text,
|
|
96
|
+
defaultMessage: selectedTag.text,
|
|
97
|
+
})
|
|
98
|
+
: formatMessage({
|
|
99
|
+
id: `source.${selectedTag.text}`,
|
|
100
|
+
defaultMessage: formatMessage({
|
|
101
|
+
id: selectedTag.text,
|
|
102
|
+
defaultMessage: selectedTag.text,
|
|
103
|
+
}),
|
|
104
|
+
})}
|
|
78
105
|
</Message.Item>
|
|
79
106
|
) : null}
|
|
80
107
|
</Message.List>
|
|
@@ -83,8 +110,10 @@ const LinkedMessage = ({
|
|
|
83
110
|
};
|
|
84
111
|
|
|
85
112
|
LinkedMessage.propTypes = {
|
|
86
|
-
|
|
113
|
+
selectedSourceConcept: PropTypes.object,
|
|
87
114
|
selectedStructure: PropTypes.object,
|
|
115
|
+
selectedTargetConcept: PropTypes.object,
|
|
116
|
+
selectedLinkType: PropTypes.string,
|
|
88
117
|
selectedTag: PropTypes.object,
|
|
89
118
|
status: PropTypes.string,
|
|
90
119
|
};
|
|
@@ -95,11 +124,11 @@ export const ConceptsLinksManagement = ({
|
|
|
95
124
|
icon,
|
|
96
125
|
createRelation,
|
|
97
126
|
deleteRelation,
|
|
98
|
-
|
|
99
|
-
|
|
127
|
+
conceptLinks,
|
|
128
|
+
tagStructureOptions,
|
|
129
|
+
tagConceptOptions,
|
|
100
130
|
fetchConcepts,
|
|
101
131
|
conceptPayload,
|
|
102
|
-
tagOptions,
|
|
103
132
|
selectedRelationTags,
|
|
104
133
|
clearStructures,
|
|
105
134
|
clearStructureFilters,
|
|
@@ -109,97 +138,128 @@ export const ConceptsLinksManagement = ({
|
|
|
109
138
|
structurePayload,
|
|
110
139
|
}) => {
|
|
111
140
|
const { formatMessage } = useIntl();
|
|
112
|
-
const [
|
|
141
|
+
const [selectedLinkType, setSelectedLinkType] = useState("structures");
|
|
142
|
+
const [selectedSourceConcept, setSelectedSourceConcept] = useState(null);
|
|
143
|
+
const [selectedTargetConcept, setSelectedTargetConcept] = useState(null);
|
|
113
144
|
const [selectedStructure, setSelectedStructure] = useState(null);
|
|
114
145
|
|
|
146
|
+
const [tagOptions, setTagOptions] = useState(tagStructureOptions);
|
|
115
147
|
const [selectedTag, setselectedTag] = useState(null);
|
|
148
|
+
|
|
116
149
|
const [status, setStatus] = useState(STATUS_PENDING);
|
|
117
|
-
const [links, setLinks] = useState(
|
|
150
|
+
const [links, setLinks] = useState(null);
|
|
151
|
+
|
|
152
|
+
useEffect(() => {
|
|
153
|
+
if (selectedLinkType == "concepts") {
|
|
154
|
+
setTagOptions(tagConceptOptions);
|
|
155
|
+
setSelectedStructure(null);
|
|
156
|
+
} else if (selectedLinkType == "structures") {
|
|
157
|
+
setSelectedTargetConcept(null);
|
|
158
|
+
const filters = conceptPayload.filters;
|
|
159
|
+
const payload = {
|
|
160
|
+
...conceptPayload,
|
|
161
|
+
filters: { ...filters, ...linksDefaultFilters },
|
|
162
|
+
size: 7,
|
|
163
|
+
};
|
|
164
|
+
fetchConcepts(payload);
|
|
165
|
+
setTagOptions(tagStructureOptions);
|
|
166
|
+
}
|
|
167
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
168
|
+
}, [selectedLinkType, tagStructureOptions]);
|
|
118
169
|
|
|
119
|
-
|
|
170
|
+
useEffect(() => {
|
|
171
|
+
if (status !== STATUS_PENDING) setSelectedStructure(null);
|
|
172
|
+
|
|
173
|
+
setStatus(STATUS_PENDING);
|
|
174
|
+
if (selectedRelationTags) {
|
|
175
|
+
const [id] = selectedRelationTags;
|
|
176
|
+
const tag = _.find(_.propEq("value", id))(tagOptions);
|
|
177
|
+
setselectedTag(tag);
|
|
178
|
+
}
|
|
179
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
180
|
+
}, [selectedRelationTags]);
|
|
181
|
+
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
setLinks(conceptLinks);
|
|
184
|
+
}, [conceptLinks]);
|
|
185
|
+
|
|
186
|
+
const isLinked = (conceptLinks, id, targetType) => {
|
|
120
187
|
return _.find(
|
|
121
188
|
(link) =>
|
|
122
|
-
_.propEq("
|
|
123
|
-
_.propEq("
|
|
124
|
-
)(
|
|
189
|
+
_.propEq("target_id", id)(link) &&
|
|
190
|
+
_.propEq("target_type", targetType)(link)
|
|
191
|
+
)(conceptLinks);
|
|
125
192
|
};
|
|
126
193
|
|
|
127
|
-
const
|
|
194
|
+
const handleSourceConceptSelected = (selectedSourceConcept) => {
|
|
128
195
|
setStatus(STATUS_PENDING);
|
|
129
|
-
|
|
196
|
+
setSelectedSourceConcept(selectedSourceConcept);
|
|
130
197
|
setSelectedStructure(null);
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
...
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
198
|
+
setSelectedTargetConcept(null);
|
|
199
|
+
|
|
200
|
+
if (selectedLinkType == "structures") {
|
|
201
|
+
clearStructures();
|
|
202
|
+
clearStructureFilters();
|
|
203
|
+
fetchStructureFilters();
|
|
204
|
+
resetStructureFilters();
|
|
205
|
+
fetchStructures({ ...structurePayload, size: 7, page: 0 });
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
|
|
209
|
+
const handleTargetConceptSelected = (concept) => {
|
|
210
|
+
setSelectedTargetConcept(concept);
|
|
211
|
+
if (selectedSourceConcept && concept) {
|
|
212
|
+
const isConceptLinked = isLinked(
|
|
213
|
+
conceptLinks,
|
|
214
|
+
concept.business_concept_id,
|
|
215
|
+
"business_concept"
|
|
216
|
+
);
|
|
217
|
+
if (isConceptLinked) {
|
|
218
|
+
setStatus(STATUS_DELETED);
|
|
219
|
+
deleteRelation({ id: isConceptLinked.id });
|
|
220
|
+
} else {
|
|
221
|
+
const conceptLink = {
|
|
222
|
+
source_id: selectedSourceConcept.business_concept_id,
|
|
223
|
+
source_type: "business_concept",
|
|
224
|
+
target_id: concept.business_concept_id,
|
|
225
|
+
target_type: "business_concept",
|
|
226
|
+
tag_ids: selectedRelationTags ? selectedRelationTags : [],
|
|
227
|
+
context: {
|
|
228
|
+
target: pickConceptAttrs(concept),
|
|
229
|
+
source: pickConceptAttrs(selectedSourceConcept),
|
|
230
|
+
},
|
|
231
|
+
};
|
|
232
|
+
setStatus(STATUS_CREATED);
|
|
233
|
+
createRelation(conceptLink);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
142
236
|
};
|
|
143
237
|
|
|
144
238
|
const handleStructureSelected = (structure) => {
|
|
145
239
|
setSelectedStructure(structure);
|
|
146
|
-
if (
|
|
147
|
-
const
|
|
148
|
-
|
|
149
|
-
|
|
240
|
+
if (selectedSourceConcept && structure) {
|
|
241
|
+
const isStructureLinked = isLinked(
|
|
242
|
+
conceptLinks,
|
|
243
|
+
structure.id,
|
|
244
|
+
"data_structure"
|
|
245
|
+
);
|
|
246
|
+
if (isStructureLinked) {
|
|
247
|
+
setStatus(STATUS_DELETED);
|
|
248
|
+
deleteRelation({ id: isStructureLinked.id });
|
|
150
249
|
} else {
|
|
151
250
|
const structureLink = {
|
|
152
|
-
source_id:
|
|
251
|
+
source_id: selectedSourceConcept.business_concept_id,
|
|
153
252
|
source_type: "business_concept",
|
|
154
253
|
target_id: structure.id,
|
|
155
254
|
target_type: "data_structure",
|
|
156
255
|
tag_ids: selectedRelationTags ? selectedRelationTags : [],
|
|
157
256
|
};
|
|
257
|
+
setStatus(STATUS_CREATED);
|
|
158
258
|
createRelation(structureLink);
|
|
159
259
|
}
|
|
160
|
-
fetchConcepts({
|
|
161
|
-
...conceptPayload,
|
|
162
|
-
filters: { ...conceptPayload.filters, ...linksDefaultFilters },
|
|
163
|
-
size: 7,
|
|
164
|
-
});
|
|
165
260
|
}
|
|
166
261
|
};
|
|
167
262
|
|
|
168
|
-
useEffect(() => {
|
|
169
|
-
if (status !== STATUS_PENDING) setSelectedStructure(null);
|
|
170
|
-
|
|
171
|
-
setStatus(STATUS_PENDING);
|
|
172
|
-
if (selectedRelationTags) {
|
|
173
|
-
const [id] = selectedRelationTags;
|
|
174
|
-
const tag = _.find(_.propEq("value", id))(tagOptions);
|
|
175
|
-
setselectedTag(tag);
|
|
176
|
-
}
|
|
177
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
178
|
-
}, [selectedRelationTags]);
|
|
179
|
-
|
|
180
|
-
useEffect(() => {
|
|
181
|
-
if (deletingRelation?.id) {
|
|
182
|
-
setLinks(_.filter(_.negate(_.propEq("id", deletingRelation.id)))(links));
|
|
183
|
-
setStatus(STATUS_DELETED);
|
|
184
|
-
}
|
|
185
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
186
|
-
}, [deletingRelation]);
|
|
187
|
-
|
|
188
|
-
useEffect(() => {
|
|
189
|
-
if (creatingRelation) {
|
|
190
|
-
setLinks([
|
|
191
|
-
...links,
|
|
192
|
-
{
|
|
193
|
-
id: creatingRelation.id.toString(),
|
|
194
|
-
resource_id: creatingRelation.target_id.toString(),
|
|
195
|
-
resource_type: "data_structure",
|
|
196
|
-
},
|
|
197
|
-
]);
|
|
198
|
-
setStatus(STATUS_CREATED);
|
|
199
|
-
}
|
|
200
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
201
|
-
}, [creatingRelation]);
|
|
202
|
-
|
|
203
263
|
return (
|
|
204
264
|
<>
|
|
205
265
|
<Segment>
|
|
@@ -213,16 +273,28 @@ export const ConceptsLinksManagement = ({
|
|
|
213
273
|
<Segment attached="bottom">
|
|
214
274
|
<Grid>
|
|
215
275
|
<Grid.Row>
|
|
216
|
-
<Grid.Column width={
|
|
276
|
+
<Grid.Column width={4}>
|
|
277
|
+
{
|
|
278
|
+
<ConceptLinksDropdownSelector
|
|
279
|
+
handleChange={setSelectedLinkType}
|
|
280
|
+
defaultOption={selectedLinkType}
|
|
281
|
+
options={linkOptions}
|
|
282
|
+
/>
|
|
283
|
+
}
|
|
284
|
+
</Grid.Column>
|
|
285
|
+
<Grid.Column width={4}>
|
|
217
286
|
{!_.isEmpty(tagOptions) && (
|
|
218
287
|
<TagTypeDropdownSelector options={tagOptions} />
|
|
219
288
|
)}
|
|
220
289
|
</Grid.Column>
|
|
290
|
+
|
|
221
291
|
<Grid.Column width={8}>
|
|
222
|
-
{
|
|
292
|
+
{selectedSourceConcept || selectedTag ? (
|
|
223
293
|
<LinkedMessage
|
|
224
294
|
selectedStructure={selectedStructure}
|
|
225
|
-
|
|
295
|
+
selectedTargetConcept={selectedTargetConcept}
|
|
296
|
+
selectedLinkType={selectedLinkType}
|
|
297
|
+
selectedSourceConcept={selectedSourceConcept}
|
|
226
298
|
selectedTag={selectedTag}
|
|
227
299
|
status={status}
|
|
228
300
|
/>
|
|
@@ -240,8 +312,8 @@ export const ConceptsLinksManagement = ({
|
|
|
240
312
|
</Header>
|
|
241
313
|
<ConceptSelector
|
|
242
314
|
showTitle={false}
|
|
243
|
-
selectedConcept={
|
|
244
|
-
handleConceptSelected={
|
|
315
|
+
selectedConcept={selectedSourceConcept}
|
|
316
|
+
handleConceptSelected={handleSourceConceptSelected}
|
|
245
317
|
tagOptions={tagOptions}
|
|
246
318
|
/>
|
|
247
319
|
</Segment>
|
|
@@ -250,16 +322,47 @@ export const ConceptsLinksManagement = ({
|
|
|
250
322
|
<Segment>
|
|
251
323
|
<Header as="h4">
|
|
252
324
|
<Header.Content>
|
|
253
|
-
{formatMessage({
|
|
325
|
+
{formatMessage({
|
|
326
|
+
id:
|
|
327
|
+
selectedLinkType == "structures"
|
|
328
|
+
? "conceptRelations.structures"
|
|
329
|
+
: "conceptRelations.concepts",
|
|
330
|
+
})}
|
|
254
331
|
</Header.Content>
|
|
255
332
|
</Header>
|
|
256
|
-
{
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
333
|
+
{selectedSourceConcept && selectedLinkType == "structures" ? (
|
|
334
|
+
<>
|
|
335
|
+
<ConceptUserFiltersLoader />
|
|
336
|
+
<RelationsLoader
|
|
337
|
+
resource_id={selectedSourceConcept.business_concept_id}
|
|
338
|
+
resource_type="business_concept"
|
|
339
|
+
target_type="data_structure"
|
|
340
|
+
/>
|
|
341
|
+
<StructureSelector
|
|
342
|
+
selectedStructure={selectedStructure}
|
|
343
|
+
onSelect={handleStructureSelected}
|
|
344
|
+
links={conceptLinks}
|
|
345
|
+
placeToTop={false}
|
|
346
|
+
/>
|
|
347
|
+
</>
|
|
348
|
+
) : selectedSourceConcept &&
|
|
349
|
+
selectedLinkType == "concepts" ? (
|
|
350
|
+
<>
|
|
351
|
+
<RelationsLoader
|
|
352
|
+
resource_id={selectedSourceConcept.business_concept_id}
|
|
353
|
+
resource_type="business_concept"
|
|
354
|
+
target_type="business_concept"
|
|
355
|
+
/>
|
|
356
|
+
<ConceptSelector
|
|
357
|
+
selectedConcept={selectedTargetConcept}
|
|
358
|
+
handleConceptSelected={handleTargetConceptSelected}
|
|
359
|
+
businessConceptId={
|
|
360
|
+
selectedSourceConcept.business_concept_id
|
|
361
|
+
}
|
|
362
|
+
links={links}
|
|
363
|
+
showTitle={false}
|
|
364
|
+
/>
|
|
365
|
+
</>
|
|
263
366
|
) : null}
|
|
264
367
|
</Segment>
|
|
265
368
|
</Grid.Column>
|
|
@@ -286,17 +389,18 @@ ConceptsLinksManagement.propTypes = {
|
|
|
286
389
|
createRelation: PropTypes.func,
|
|
287
390
|
deleteRelation: PropTypes.func,
|
|
288
391
|
selectedRelationTags: PropTypes.array,
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
392
|
+
tagStructureOptions: PropTypes.array,
|
|
393
|
+
tagConceptOptions: PropTypes.array,
|
|
394
|
+
conceptLinks: PropTypes.object,
|
|
292
395
|
};
|
|
293
396
|
|
|
294
397
|
const makeMapStateToProps = () => {
|
|
295
|
-
const
|
|
398
|
+
const getTagStructureOptions = makeTagOptionsSelector("data_field");
|
|
296
399
|
const searchQuerySelector = makeSearchQuerySelector(
|
|
297
400
|
"conceptQuery",
|
|
298
401
|
"conceptActiveFilters"
|
|
299
402
|
);
|
|
403
|
+
const getTagConceptOptions = makeTagOptionsSelector("business_concept");
|
|
300
404
|
const structureSearchQuerySelector = makeSearchQuerySelector(
|
|
301
405
|
"structureQuery",
|
|
302
406
|
"structureActiveFilters",
|
|
@@ -306,9 +410,9 @@ const makeMapStateToProps = () => {
|
|
|
306
410
|
conceptPayload: searchQuerySelector(state, props),
|
|
307
411
|
selectedRelationTags: state.selectedRelationTags,
|
|
308
412
|
structurePayload: structureSearchQuerySelector(state, props),
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
413
|
+
tagStructureOptions: getTagStructureOptions(state),
|
|
414
|
+
tagConceptOptions: getTagConceptOptions(state),
|
|
415
|
+
conceptLinks: state.relations,
|
|
312
416
|
});
|
|
313
417
|
|
|
314
418
|
return mapStateToProps;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import React, { Suspense } from "react";
|
|
2
2
|
import { render } from "@truedat/test/render";
|
|
3
|
-
import { waitFor } from "@testing-library/react";
|
|
4
3
|
import userEvent from "@testing-library/user-event";
|
|
5
4
|
import ConceptsLinksManagement from "../ConceptsLinksManagement";
|
|
6
5
|
import en from "../../../messages/en";
|
|
@@ -33,7 +33,71 @@ exports[`<ConceptsLinksManagement /> matches the latest snapshot 1`] = `
|
|
|
33
33
|
class="row"
|
|
34
34
|
>
|
|
35
35
|
<div
|
|
36
|
-
class="
|
|
36
|
+
class="four wide column"
|
|
37
|
+
>
|
|
38
|
+
<div
|
|
39
|
+
class="field"
|
|
40
|
+
>
|
|
41
|
+
<label>
|
|
42
|
+
<b>
|
|
43
|
+
Link type
|
|
44
|
+
</b>
|
|
45
|
+
</label>
|
|
46
|
+
<div>
|
|
47
|
+
<div
|
|
48
|
+
aria-expanded="false"
|
|
49
|
+
class="ui selection dropdown concept-link-dropdown"
|
|
50
|
+
role="listbox"
|
|
51
|
+
tabindex="0"
|
|
52
|
+
>
|
|
53
|
+
<div
|
|
54
|
+
aria-atomic="true"
|
|
55
|
+
aria-live="polite"
|
|
56
|
+
class="divider text"
|
|
57
|
+
role="alert"
|
|
58
|
+
>
|
|
59
|
+
Structures
|
|
60
|
+
</div>
|
|
61
|
+
<i
|
|
62
|
+
aria-hidden="true"
|
|
63
|
+
class="dropdown icon"
|
|
64
|
+
/>
|
|
65
|
+
<div
|
|
66
|
+
class="menu transition"
|
|
67
|
+
>
|
|
68
|
+
<div
|
|
69
|
+
aria-checked="true"
|
|
70
|
+
aria-selected="true"
|
|
71
|
+
class="active selected item"
|
|
72
|
+
role="option"
|
|
73
|
+
style="pointer-events: all;"
|
|
74
|
+
>
|
|
75
|
+
<span
|
|
76
|
+
class="text"
|
|
77
|
+
>
|
|
78
|
+
Structures
|
|
79
|
+
</span>
|
|
80
|
+
</div>
|
|
81
|
+
<div
|
|
82
|
+
aria-checked="false"
|
|
83
|
+
aria-selected="false"
|
|
84
|
+
class="item"
|
|
85
|
+
role="option"
|
|
86
|
+
style="pointer-events: all;"
|
|
87
|
+
>
|
|
88
|
+
<span
|
|
89
|
+
class="text"
|
|
90
|
+
>
|
|
91
|
+
Concepts
|
|
92
|
+
</span>
|
|
93
|
+
</div>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
</div>
|
|
97
|
+
</div>
|
|
98
|
+
</div>
|
|
99
|
+
<div
|
|
100
|
+
class="four wide column"
|
|
37
101
|
/>
|
|
38
102
|
<div
|
|
39
103
|
class="eight wide column"
|