@truedat/dd 4.42.4 → 4.43.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 CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ## [4.43.0] 2022-04-26
4
+
5
+ ### Added
6
+
7
+ - [TD-3186] DataStructure view shows related implementations
8
+
9
+ ## [4.42.6] 2022-04-25
10
+
11
+ ### Added
12
+
13
+ - [TD-2026] Fix `linage graph` empty metada condition
14
+
15
+ ## [4.42.5] 2022-04-22
16
+
17
+ ### Added
18
+
19
+ - [TD-2026] Add metadata to `linage graph`
20
+
3
21
  ## [4.41.2] 2022-03-30
4
22
 
5
23
  ### Fixed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@truedat/dd",
3
- "version": "4.42.4",
3
+ "version": "4.43.0",
4
4
  "description": "Truedat Web Data Dictionary",
5
5
  "sideEffects": false,
6
6
  "jsnext:main": "src/index.js",
@@ -34,7 +34,7 @@
34
34
  "@testing-library/jest-dom": "^5.14.1",
35
35
  "@testing-library/react": "^12.0.0",
36
36
  "@testing-library/user-event": "^13.2.1",
37
- "@truedat/test": "4.42.4",
37
+ "@truedat/test": "4.43.0",
38
38
  "babel-jest": "^27.0.6",
39
39
  "babel-plugin-dynamic-import-node": "^2.3.3",
40
40
  "babel-plugin-lodash": "^3.3.4",
@@ -84,9 +84,9 @@
84
84
  ]
85
85
  },
86
86
  "dependencies": {
87
- "@truedat/auth": "4.42.4",
88
- "@truedat/core": "4.42.4",
89
- "@truedat/df": "4.42.4",
87
+ "@truedat/auth": "4.43.0",
88
+ "@truedat/core": "4.43.0",
89
+ "@truedat/df": "4.43.0",
90
90
  "lodash": "^4.17.21",
91
91
  "path-to-regexp": "^1.7.0",
92
92
  "prop-types": "^15.7.2",
@@ -107,5 +107,5 @@
107
107
  "react-dom": ">= 16.8.6 < 17",
108
108
  "semantic-ui-react": ">= 0.88.2 < 2.1"
109
109
  },
110
- "gitHead": "3130f82b417611c76542fc29a6885b4bf85cdd30"
110
+ "gitHead": "ad0f63f2d98ae377883743b839858d9d671d2431"
111
111
  }
@@ -1,10 +1,19 @@
1
1
  import _ from "lodash/fp";
2
- import React, { useRef, useEffect, useReducer } from "react";
2
+ import React, { useRef, useEffect, useReducer, useState } from "react";
3
3
  import PropTypes from "prop-types";
4
4
  import { connect } from "react-redux";
5
- import { Dimmer, Loader } from "semantic-ui-react";
5
+ import {
6
+ Dimmer,
7
+ Loader,
8
+ Segment,
9
+ Header,
10
+ Button,
11
+ Grid,
12
+ Divider,
13
+ } from "semantic-ui-react";
6
14
  import svgPanZoom from "svg-pan-zoom";
7
15
  import { FormattedMessage, useIntl } from "react-intl";
16
+
8
17
  import {
9
18
  clearNode,
10
19
  selectNode,
@@ -64,6 +73,9 @@ export const LineageGraph = ({
64
73
  const [state, dispatch] = useReducer(reducer, initialState);
65
74
  const { selectedNode, hover, svg } = state;
66
75
 
76
+ const [metadata, setMetadata] = useState(null);
77
+ const [selectedLink, selectLink] = useState(null);
78
+
67
79
  useEffect(() => {
68
80
  // Anything in here is fired on component mount.
69
81
  return () => cancelPoll();
@@ -84,78 +96,110 @@ export const LineageGraph = ({
84
96
  const { formatMessage } = useIntl();
85
97
 
86
98
  return (
87
- <>
88
- <Dimmer.Dimmable dimmed={loading} className="dl">
89
- <Dimmer active={loading} inverted>
90
- <Loader size="large">
91
- <FormattedMessage
92
- id="lineage.graph.loading"
93
- defaultMessage={"Analyzing..."}
94
- />
95
- {loadingInfo?.data?.graph_hash && loadingInfo?.data?.status && (
96
- <p>
97
- {formatMessage({
98
- id:
99
- _.toLower(loadingInfo?.data?.status) === "already_started"
100
- ? "lineage.graph.loading.background.existing"
101
- : _.toLower(loadingInfo?.data?.status) ===
102
- "just_started" &&
103
- "lineage.graph.loading.background.launched",
104
- })}
105
- </p>
106
- )}
107
- {loadingInfo?.data?.graph_hash && (
108
- <p>
109
- Graph hash:{" "}
110
- <span className="graph-hash">
111
- {loadingInfo?.data?.graph_hash}
112
- </span>
113
- </p>
114
- )}
115
- <p>
116
- {loadingInfo?.data?.retry &&
117
- formatMessage(
118
- { id: "lineage.graph.loading.polling" },
119
- { retry: loadingInfo?.data?.retry }
120
- )}
121
- </p>
122
- </Loader>
123
- </Dimmer>
124
- <svg
125
- width="100%"
126
- height={height}
127
- ref={ref}
128
- onClick={() => dispatch(selectNode.trigger(null))}
99
+ <Grid>
100
+ <Grid.Row columns={2}>
101
+ <Grid.Column
102
+ width={_.isNull(metadata) || _.isEmpty(metadata) ? 16 : 12}
103
+ style={
104
+ _.isNull(metadata) || _.isEmpty(metadata) ? {} : { paddingRight: 0 }
105
+ }
129
106
  >
130
- <LineageDefs />
131
- <g className="svg-pan-zoom_viewport">
132
- {_.map.convert({ cap: false })((g, i) => (
133
- <LineageGroup
134
- key={i}
135
- active={hover === g.id}
136
- onHover={onHover(g.id)}
137
- onClick={onSelect(g)}
138
- selected={selectedNode === g}
139
- {...g}
140
- />
141
- ))(groups)}
142
- {_.map.convert({ cap: false })((g, i) => (
143
- <LineageResource
144
- key={i}
145
- active={hover === g.id}
146
- onHover={onHover(g.id)}
147
- onClick={onSelect(g)}
148
- selected={selectedNode === g}
149
- {...g}
150
- />
151
- ))(resources)}
152
- {_.map.convert({ cap: false })((p, i) => (
153
- <LineageLink key={i} active path={p.path} />
154
- ))(paths)}
155
- </g>
156
- </svg>
157
- </Dimmer.Dimmable>
158
- </>
107
+ <Dimmer.Dimmable dimmed={loading} className="dl">
108
+ <Dimmer active={loading} inverted>
109
+ <Loader size="large">
110
+ <FormattedMessage
111
+ id="lineage.graph.loading"
112
+ defaultMessage={"Analyzing..."}
113
+ />
114
+ {loadingInfo?.data?.graph_hash && loadingInfo?.data?.status && (
115
+ <p>
116
+ {formatMessage({
117
+ id:
118
+ _.toLower(loadingInfo?.data?.status) ===
119
+ "already_started"
120
+ ? "lineage.graph.loading.background.existing"
121
+ : _.toLower(loadingInfo?.data?.status) ===
122
+ "just_started" &&
123
+ "lineage.graph.loading.background.launched",
124
+ })}
125
+ </p>
126
+ )}
127
+ {loadingInfo?.data?.graph_hash && (
128
+ <p>
129
+ Graph hash:{" "}
130
+ <span className="graph-hash">
131
+ {loadingInfo?.data?.graph_hash}
132
+ </span>
133
+ </p>
134
+ )}
135
+ <p>
136
+ {loadingInfo?.data?.retry &&
137
+ formatMessage(
138
+ { id: "lineage.graph.loading.polling" },
139
+ { retry: loadingInfo?.data?.retry }
140
+ )}
141
+ </p>
142
+ </Loader>
143
+ </Dimmer>
144
+ <svg
145
+ width="100%"
146
+ height={height}
147
+ ref={ref}
148
+ onClick={() => dispatch(selectNode.trigger(null))}
149
+ style={{ border: "1px solid #d4d4d5", borderRadius: "5px" }}
150
+ >
151
+ <LineageDefs />
152
+ <g className="svg-pan-zoom_viewport">
153
+ {_.map.convert({ cap: false })((g, i) => (
154
+ <LineageGroup
155
+ key={i}
156
+ active={hover === g.id}
157
+ onHover={onHover(g.id)}
158
+ onClick={onSelect(g)}
159
+ selected={selectedNode === g}
160
+ {...g}
161
+ />
162
+ ))(groups)}
163
+ {_.map.convert({ cap: false })((g, i) => (
164
+ <LineageResource
165
+ key={i}
166
+ active={hover === g.id}
167
+ onHover={onHover(g.id)}
168
+ onClick={onSelect(g)}
169
+ selected={selectedNode === g}
170
+ {...g}
171
+ />
172
+ ))(resources)}
173
+ {_.map.convert({ cap: false })((p, i) => (
174
+ <LineageLink
175
+ key={i}
176
+ active
177
+ selected={selectedLink === i}
178
+ path={p.path}
179
+ metadata={p.metadata}
180
+ onClick={(metadata) => {
181
+ setMetadata(metadata);
182
+ selectLink(i);
183
+ }}
184
+ />
185
+ ))(paths)}
186
+ </g>
187
+ </svg>
188
+ </Dimmer.Dimmable>
189
+ </Grid.Column>
190
+ {_.isNull(metadata) || _.isEmpty(metadata) ? null : (
191
+ <Grid.Column width={4} style={{ maxHeight: 300 }}>
192
+ <LinageMetadata
193
+ metadata={metadata}
194
+ onClose={() => {
195
+ setMetadata(null);
196
+ selectLink(null);
197
+ }}
198
+ />
199
+ </Grid.Column>
200
+ )}
201
+ </Grid.Row>
202
+ </Grid>
159
203
  );
160
204
  };
161
205
 
@@ -186,3 +230,35 @@ const mapStateToProps = (
186
230
  export default connect(mapStateToProps, { clearNode, cancelPoll })(
187
231
  LineageGraph
188
232
  );
233
+
234
+ export const LinageMetadata = ({ metadata, onClose }) => {
235
+ const { formatMessage } = useIntl();
236
+ const content = _.flow(
237
+ _.toPairs,
238
+ _.map(([key, value]) => (
239
+ <div key={key}>
240
+ <b>{key}:</b>
241
+ <p>{value}</p>
242
+ <Divider fitted />
243
+ </div>
244
+ ))
245
+ )(metadata);
246
+
247
+ return (
248
+ <Segment secondary>
249
+ <Header>
250
+ {" "}
251
+ {formatMessage({ id: "lineage.graph.metadata.header" })}{" "}
252
+ </Header>
253
+ <div style={{ maxHeight: "400px", overflowY: "auto" }}>{content}</div>
254
+ <Button
255
+ onClick={onClose}
256
+ content={formatMessage({ id: "lineage.graph.metadata.close.button" })}
257
+ />
258
+ </Segment>
259
+ );
260
+ };
261
+ LinageMetadata.propTypes = {
262
+ metadata: PropTypes.object,
263
+ onClose: PropTypes.func,
264
+ };
@@ -1,13 +1,31 @@
1
+ import _ from "lodash/fp";
1
2
  import React from "react";
2
3
  import PropTypes from "prop-types";
3
4
 
4
- export const LineageLink = ({ active = false, path }) => (
5
- <path className={active ? "active link" : "link"} d={path} />
6
- );
5
+ export const LineageLink = ({
6
+ active = false,
7
+ path,
8
+ metadata,
9
+ onClick,
10
+ selected,
11
+ }) => {
12
+ return _.isNull(metadata) || _.isEmpty(metadata) ? (
13
+ <path className={active ? "active link" : "link"} d={path} />
14
+ ) : (
15
+ <path
16
+ className={
17
+ active ? (selected ? "active link metadata" : "link metadata") : "link"
18
+ }
19
+ d={path}
20
+ onClick={() => onClick(metadata)}
21
+ />
22
+ );
23
+ };
7
24
 
8
25
  LineageLink.propTypes = {
9
26
  active: PropTypes.bool,
10
- path: PropTypes.string.isRequired
27
+ path: PropTypes.string.isRequired,
28
+ onClick: PropTypes.func,
11
29
  };
12
30
 
13
31
  export default LineageLink;
@@ -129,6 +129,8 @@ export default {
129
129
  "lineage.graph.status.just_started": "Just started",
130
130
  "lineage.graph.status.started": "Started",
131
131
  "lineage.graph.status.timed_out": "Timed out",
132
+ "lineage.graph.metadata.header": "Information",
133
+ "lineage.graph.metadata.close.button": "Close",
132
134
  "lineage.group.placeholder": "Select Top Level Structure",
133
135
  "lineage.resources.placeholder": "Select Child Structures",
134
136
  "lineage.subgroup.placeholder": "Select Child Structure",
@@ -132,6 +132,8 @@ export default {
132
132
  "lineage.graph.status.just_started": "Acaba de iniciarse",
133
133
  "lineage.graph.status.started": "Iniciado",
134
134
  "lineage.graph.status.timed_out": "Tiempo de espera máximo sobrepasado",
135
+ "lineage.graph.metadata.header": "Información",
136
+ "lineage.graph.metadata.close.button": "Cerrar",
135
137
  "lineage.group.placeholder": "Seleccionar Estructura Padre",
136
138
  "lineage.resources.placeholder": "Seleccionar Estructuras Hijos",
137
139
  "lineage.subgroup.placeholder": "Seleccionar Estructura Hijo",
@@ -26,6 +26,7 @@ const structureVersionFields = _.pick([
26
26
  "deleted_at",
27
27
  "description",
28
28
  "group",
29
+ "implementations",
29
30
  "metadata",
30
31
  "name",
31
32
  "source",
@@ -138,12 +138,16 @@ describe("selectors: getTabVisibility", () => {
138
138
  });
139
139
  });
140
140
 
141
- it("should include rules iff ruleImplementations is not empty", () => {
141
+ it("should include rules iff structure.implementations is not empty", () => {
142
142
  expect(getTabVisibility({})).toMatchObject({ rules: false });
143
- expect(getTabVisibility({ ruleImplementations: [] })).toMatchObject({
143
+ expect(
144
+ getTabVisibility({ structure: { implementations: [] } })
145
+ ).toMatchObject({
144
146
  rules: false,
145
147
  });
146
- expect(getTabVisibility({ ruleImplementations: [{}] })).toMatchObject({
148
+ expect(
149
+ getTabVisibility({ structure: { implementations: [{}] } })
150
+ ).toMatchObject({
147
151
  rules: true,
148
152
  });
149
153
  });
@@ -36,7 +36,7 @@ const notesTabVisible = ({ templatesLoading, templates, structure }) =>
36
36
  )(templates);
37
37
 
38
38
  const versionsTabVisible = notEmptyPath("structureVersions");
39
- const rulesTabVisible = notEmptyPath("ruleImplementations");
39
+ const rulesTabVisible = notEmptyPath("structure.implementations");
40
40
  const lineageTabVisible = _.anyPass([_.path("structure.degree.in")]);
41
41
  const impactTabVisible = _.anyPass([_.path("structure.degree.out")]);
42
42
  const parentsTabVisible = _.conformsTo({ parentRelations: notEmpty });