@truedat/bg 5.13.2 → 5.13.4

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/bg",
3
- "version": "5.13.2",
3
+ "version": "5.13.4",
4
4
  "description": "Truedat Web Business Glossary",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -86,9 +86,9 @@
86
86
  ]
87
87
  },
88
88
  "dependencies": {
89
- "@truedat/core": "5.13.2",
90
- "@truedat/df": "5.13.2",
91
- "@truedat/lm": "5.13.2",
89
+ "@truedat/core": "5.13.4",
90
+ "@truedat/df": "5.13.4",
91
+ "@truedat/lm": "5.13.4",
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": "f702ebedee85733e60b46b26fd468a18e93b8c20"
114
+ "gitHead": "53fddebbe61698097cb6830cbcc2d9ee47c3690f"
115
115
  }
@@ -2,16 +2,27 @@ import _ from "lodash/fp";
2
2
  import React, { useEffect, useState } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
- import { Button, Segment, Grid, Icon, Table } from "semantic-ui-react";
5
+ import {
6
+ Button,
7
+ Dropdown,
8
+ Segment,
9
+ Grid,
10
+ Icon,
11
+ Popup,
12
+ Table,
13
+ } from "semantic-ui-react";
6
14
  import { FormattedMessage, useIntl } from "react-intl";
7
15
  import { useHistory, useLocation } from "react-router-dom";
8
16
 
9
17
  import { RelationGraph } from "@truedat/lm/components";
10
18
  import { linkTo } from "@truedat/core/routes";
11
19
  import {
12
- selectMaxDepth,
13
- selectLimitedGraph,
14
- } from "@truedat/lm/selectors/relationGraphTraversal";
20
+ anyTraversalTags,
21
+ findMaxDepth,
22
+ pruneGraph,
23
+ graphDistinctTags,
24
+ EMPTY,
25
+ } from "@truedat/lm/services/relationGraphTraversal";
15
26
  import { RelationGraphDepth } from "@truedat/lm/components";
16
27
  import { getConceptToConceptRelations } from "../selectors/getConceptRelations";
17
28
 
@@ -41,34 +52,6 @@ export const ConceptRelations = ({
41
52
  relationsGraph,
42
53
  initialDepth,
43
54
  }) => {
44
- const [depth, setDepth] = useState(initialDepth || Infinity);
45
- const [maxDepth, setMaxDepth] = useState();
46
- const [currentId, setCurrentId] = useState();
47
- const [limitedRelationGraph, setLimitedRelationGraph] =
48
- useState(relationsGraph);
49
-
50
- useEffect(() => {
51
- !_.isEmpty(concept) &&
52
- setCurrentId(`business_concept:${concept.business_concept_id}`);
53
- }, [concept]);
54
-
55
- useEffect(() => {
56
- if (!_.isEmpty(relationsGraph) && currentId) {
57
- const useEffectMaxDepth = selectMaxDepth({ relationsGraph }, currentId);
58
-
59
- setMaxDepth(useEffectMaxDepth);
60
- if (depth === Infinity) {
61
- setDepth(useEffectMaxDepth);
62
- }
63
- }
64
- }, [relationsGraph, currentId]);
65
-
66
- useEffect(() => {
67
- setLimitedRelationGraph(
68
- selectLimitedGraph({ relationsGraph }, currentId, depth)
69
- );
70
- }, [relationsGraph, currentId, depth]);
71
-
72
55
  const { formatMessage } = useIntl();
73
56
  const history = useHistory();
74
57
  const location = useLocation();
@@ -87,79 +70,177 @@ export const ConceptRelations = ({
87
70
  );
88
71
  };
89
72
 
73
+ const onTraversalTagsChange = (event, { value }) => {
74
+ setAllowedTags(value);
75
+ };
76
+
77
+ const [depth, setDepth] = useState(initialDepth || Infinity);
78
+ const [maxDepth, setMaxDepth] = useState(0);
79
+ const [currentId, setCurrentId] = useState();
80
+ const [tagOptions, setTagsOptions] = useState([]);
81
+ const [limitedRelationGraph, setLimitedRelationGraph] =
82
+ useState(relationsGraph);
83
+ const [traversalTags, setAllowedTags] = useState([]);
84
+
85
+ const nonDefaultOptions = (ids, depth, maxDepth) => {
86
+ return !_.isEmpty(ids) || depth !== maxDepth;
87
+ };
88
+
89
+ useEffect(() => {
90
+ !_.isEmpty(concept) &&
91
+ setCurrentId(`business_concept:${concept.business_concept_id}`);
92
+ }, [concept]);
93
+
94
+ useEffect(() => {
95
+ if (!_.isEmpty(relationsGraph) && currentId) {
96
+ const newMaxDepth = findMaxDepth(
97
+ relationsGraph,
98
+ currentId,
99
+ traversalTags
100
+ );
101
+
102
+ setMaxDepth(newMaxDepth);
103
+ setDepth(newMaxDepth);
104
+ }
105
+ }, [relationsGraph, currentId, traversalTags]);
106
+
107
+ useEffect(() => {
108
+ /* just a little optimization to avoid generating a graph if no limitations
109
+ * (tags, depth) are set
110
+ */
111
+ if (nonDefaultOptions(traversalTags, depth, maxDepth)) {
112
+ const limitedGraph = pruneGraph(
113
+ relationsGraph,
114
+ currentId,
115
+ depth,
116
+ traversalTags
117
+ );
118
+
119
+ setLimitedRelationGraph(limitedGraph);
120
+ } else setLimitedRelationGraph(relationsGraph);
121
+ }, [relationsGraph, currentId, depth, traversalTags, maxDepth]);
122
+
123
+ useEffect(() => {
124
+ const tagsToOptions = (tags) =>
125
+ _.map(
126
+ ({ id, value }) => ({
127
+ text: formatMessage({
128
+ id: `source.${value.type}`,
129
+ defaultMessage: value.type,
130
+ }),
131
+ value: id,
132
+ }),
133
+ [
134
+ {
135
+ id: EMPTY,
136
+ value: { target_type: "business_concept", type: "_empty" },
137
+ },
138
+ ...tags,
139
+ ]
140
+ );
141
+
142
+ // eslint-disable-next-line prettier/prettier
143
+ _.flow(
144
+ graphDistinctTags,
145
+ tagsToOptions,
146
+ setTagsOptions
147
+ )(relationsGraph);
148
+ }, [relationsGraph]);
149
+
90
150
  return (
91
151
  <Segment attached="bottom">
92
- <Grid>
152
+ <div className="traversal-tags-container">
153
+ <div>
154
+ <b>
155
+ <label>
156
+ {formatMessage({
157
+ id: "relations.tags.label",
158
+ })}
159
+ </label>
160
+ </b>
161
+ </div>
162
+ <div>
163
+ <Dropdown
164
+ className="traversal-tags"
165
+ placeholder={formatMessage({
166
+ id: `relations.tags.placeholder`,
167
+ })}
168
+ multiple
169
+ search
170
+ selection
171
+ options={tagOptions}
172
+ onChange={onTraversalTagsChange}
173
+ clearable
174
+ />
175
+ </div>
176
+ </div>
177
+ <div className="implementation-actions">
178
+ {_.negate(_.isEmpty)(conceptRelations) ? (
179
+ <Button.Group>
180
+ <Button
181
+ active={graphRender}
182
+ icon
183
+ data-tooltip={formatMessage({
184
+ id: "relations.actions.maps.tooltip",
185
+ })}
186
+ onClick={() => setGraphRender(true)}
187
+ >
188
+ <Icon name="sitemap" />
189
+ </Button>
190
+ <Button
191
+ active={!graphRender}
192
+ icon
193
+ data-tooltip={formatMessage({
194
+ id: "relations.actions.list.tooltip",
195
+ })}
196
+ onClick={() => setGraphRender(false)}
197
+ >
198
+ <Icon name="list ul" />
199
+ </Button>
200
+ </Button.Group>
201
+ ) : null}
202
+ <ConceptRelationActions />
203
+ </div>
204
+
205
+ {conceptRelations ? (
206
+ <>
207
+ {graphRender && !_.isEmpty(currentId) ? (
208
+ <>
209
+ <RelationGraphDepth
210
+ onClick={(_e) => setDepth(maxDepth)}
211
+ onChange={(newDepth) => setDepth(parseInt(newDepth))}
212
+ depth={depth}
213
+ maxDepth={maxDepth}
214
+ />
215
+ <RelationGraph
216
+ navigate={navigate}
217
+ currentId={currentId}
218
+ relationsGraph={limitedRelationGraph}
219
+ />
220
+ </>
221
+ ) : (
222
+ <Table selectable>
223
+ <Table.Body>
224
+ {_.flow(
225
+ _.filter(({ tags }) => anyTraversalTags(traversalTags, tags)),
226
+ _.map((relation) => (
227
+ <ConceptRelationRow
228
+ key={relation.id}
229
+ relationContext={relation.context}
230
+ {...relation}
231
+ />
232
+ ))
233
+ )(conceptRelations)}
234
+ </Table.Body>
235
+ </Table>
236
+ )}
237
+ </>
238
+ ) : null}
239
+ {_.isEmpty(conceptRelations) ? (
93
240
  <Grid.Row>
94
- <Grid.Column>
95
- <div className="implementation-actions">
96
- {_.negate(_.isEmpty)(conceptRelations) && (
97
- <Button.Group>
98
- <Button
99
- active={graphRender}
100
- icon
101
- data-tooltip={formatMessage({
102
- id: "relations.actions.maps.tooltip",
103
- })}
104
- onClick={() => setGraphRender(true)}
105
- >
106
- <Icon name="sitemap" />
107
- </Button>
108
- <Button
109
- active={!graphRender}
110
- icon
111
- data-tooltip={formatMessage({
112
- id: "relations.actions.list.tooltip",
113
- })}
114
- onClick={() => setGraphRender(false)}
115
- >
116
- <Icon name="list ul" />
117
- </Button>
118
- </Button.Group>
119
- )}
120
- <ConceptRelationActions />
121
- </div>
122
- </Grid.Column>
241
+ <FormattedMessage id="conceptRelations.empty" />
123
242
  </Grid.Row>
124
- {conceptRelations && (
125
- <Grid.Row>
126
- <Grid.Column>
127
- {graphRender && !_.isEmpty(currentId) ? (
128
- <>
129
- <RelationGraphDepth
130
- onClick={(_e) => setDepth(maxDepth)}
131
- onChange={(newDepth) => setDepth(parseInt(newDepth))}
132
- depth={depth}
133
- maxDepth={maxDepth}
134
- />
135
- <RelationGraph
136
- navigate={navigate}
137
- currentId={currentId}
138
- relationsGraph={limitedRelationGraph}
139
- />
140
- </>
141
- ) : (
142
- <Table selectable>
143
- <Table.Body>
144
- {conceptRelations.map((relation, index) => (
145
- <ConceptRelationRow
146
- key={`${relation.id}.${index}`}
147
- relationContext={relation.context}
148
- {...relation}
149
- />
150
- ))}
151
- </Table.Body>
152
- </Table>
153
- )}
154
- </Grid.Column>
155
- </Grid.Row>
156
- )}
157
- {_.isEmpty(conceptRelations) && (
158
- <Grid.Row>
159
- <FormattedMessage id="conceptRelations.empty" />
160
- </Grid.Row>
161
- )}
162
- </Grid>
243
+ ) : null}
163
244
  </Segment>
164
245
  );
165
246
  };
@@ -4,33 +4,60 @@ exports[`<ConceptRelations /> matches the latest snapshot 1`] = `
4
4
  <Segment
5
5
  attached="bottom"
6
6
  >
7
- <Grid>
8
- <GridRow>
9
- <GridColumn>
10
- <div
11
- className="implementation-actions"
12
- >
13
- <Connect(ConceptRelationActions) />
14
- </div>
15
- </GridColumn>
16
- </GridRow>
17
- <GridRow>
18
- <GridColumn>
19
- <Table
20
- as="table"
21
- selectable={true}
22
- >
23
- <TableBody
24
- as="tbody"
25
- />
26
- </Table>
27
- </GridColumn>
28
- </GridRow>
29
- <GridRow>
30
- <MemoizedFormattedMessage
31
- id="conceptRelations.empty"
7
+ <div
8
+ className="traversal-tags-container"
9
+ >
10
+ <div>
11
+ <b>
12
+ <label>
13
+ relations.tags.label
14
+ </label>
15
+ </b>
16
+ </div>
17
+ <div>
18
+ <Dropdown
19
+ additionLabel="Add "
20
+ additionPosition="top"
21
+ className="traversal-tags"
22
+ clearable={true}
23
+ closeOnBlur={true}
24
+ closeOnEscape={true}
25
+ deburr={false}
26
+ icon="dropdown"
27
+ minCharacters={1}
28
+ multiple={true}
29
+ noResultsMessage="No results found."
30
+ onChange={[Function]}
31
+ openOnFocus={true}
32
+ options={[]}
33
+ placeholder="relations.tags.placeholder"
34
+ renderLabel={[Function]}
35
+ search={true}
36
+ searchInput="text"
37
+ selectOnBlur={true}
38
+ selectOnNavigation={true}
39
+ selection={true}
40
+ wrapSelection={true}
32
41
  />
33
- </GridRow>
34
- </Grid>
42
+ </div>
43
+ </div>
44
+ <div
45
+ className="implementation-actions"
46
+ >
47
+ <Connect(ConceptRelationActions) />
48
+ </div>
49
+ <Table
50
+ as="table"
51
+ selectable={true}
52
+ >
53
+ <TableBody
54
+ as="tbody"
55
+ />
56
+ </Table>
57
+ <GridRow>
58
+ <MemoizedFormattedMessage
59
+ id="conceptRelations.empty"
60
+ />
61
+ </GridRow>
35
62
  </Segment>
36
63
  `;
@@ -284,7 +284,10 @@ export default {
284
284
  "relations.actions.implementation.delete.confirmation.content":
285
285
  "Link between implementation and concept will be deleted. Are you sure?",
286
286
  "relations.actions.implementation.delete.confirmation.header": "Delete link",
287
+ "relations.tags.label": "Filter by relation types",
288
+ "relations.tags.placeholder": "Relation types",
287
289
  "ruleImplementations.props.business_concepts": "Concepts",
290
+ "source._empty": "Empty",
288
291
  "source.bc_caculo": "Calculated from",
289
292
  "source.bc_padre": "Children",
290
293
  "source.bc_parent": "Children",
@@ -288,8 +288,11 @@ export default {
288
288
  "Se eliminará la vinculación entre la implementación y el concepto. ¿Estás seguro?",
289
289
  "relations.actions.implementation.delete.confirmation.header":
290
290
  "Borrar vínculación",
291
+ "relations.tags.label": "Filtrar por tipos de relación",
292
+ "relations.tags.placeholder": "Tipos de relación",
291
293
  "ruleImplementations.props.business_concepts": "Conceptos",
292
294
  "saveConceptFilters.error.name.unique": "Nombre duplicado",
295
+ "source._empty": "Vacío",
293
296
  "source.bc_caculo": "Cálculado en base a",
294
297
  "source.bc_padre": "Hijos",
295
298
  "source.bc_parent": "Hijos",
@@ -115,7 +115,7 @@ exports[`<DomainStructures /> matches the latest snapshot 1`] = `
115
115
  class="selectedFilters"
116
116
  />
117
117
  <div
118
- class="dimmable"
118
+ class="dimmable structure-table-overflow"
119
119
  >
120
120
  <div
121
121
  class="ui inverted dimmer"