@truedat/dd 8.10.2 → 8.10.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 +3 -3
- package/src/components/Graphs.js +109 -0
- package/src/components/LineageDomainSelectorSkeleton.js +8 -0
- package/src/components/LineageDownloadButton.js +29 -6
- package/src/components/LineageEventsPanel.js +206 -0
- package/src/components/LineageForm.js +265 -144
- package/src/components/LineageGraph.js +0 -1
- package/src/components/LineageHeader.js +33 -0
- package/src/components/LineageResourceToggle.js +56 -0
- package/src/components/LineageRoutes.js +2 -31
- package/src/components/LineageSelectionPanel.js +165 -0
- package/src/components/__tests__/LineageForm.spec.js +343 -3
- package/src/components/__tests__/LineageRoutes.spec.js +62 -76
- package/src/components/__tests__/__snapshots__/LineageForm.spec.js.snap +291 -250
- package/src/components/__tests__/__snapshots__/LineageRoutes.spec.js.snap +19 -43
- package/src/components/index.js +12 -0
- package/src/components/lineageDomainCache.js +101 -0
- package/src/components/lineageEventHelpers.js +195 -0
- package/src/styles/lineageGraph.less +1213 -47
- package/src/components/Lineage.js +0 -20
- package/src/components/LineageSample.js +0 -20
- package/src/components/__tests__/Lineage.spec.js +0 -16
- package/src/components/__tests__/__snapshots__/Lineage.spec.js.snap +0 -163
|
@@ -1,17 +1,11 @@
|
|
|
1
1
|
import _ from "lodash/fp";
|
|
2
|
-
import { useEffect, useState } from "react";
|
|
2
|
+
import { useCallback, useEffect, useRef, useState } from "react";
|
|
3
3
|
import PropTypes from "prop-types";
|
|
4
4
|
import { connect } from "react-redux";
|
|
5
5
|
import { FormattedMessage, useIntl } from "react-intl";
|
|
6
|
-
import {
|
|
7
|
-
Accordion,
|
|
8
|
-
Form,
|
|
9
|
-
Icon,
|
|
10
|
-
Segment,
|
|
11
|
-
Header,
|
|
12
|
-
Button,
|
|
13
|
-
} from "semantic-ui-react";
|
|
6
|
+
import { Accordion, Form, Icon, Header, Button } from "semantic-ui-react";
|
|
14
7
|
import { DomainSelector } from "@truedat/core/components";
|
|
8
|
+
import { DOMAINS_QUERY } from "@truedat/core/api/queries";
|
|
15
9
|
import {
|
|
16
10
|
clearNodes,
|
|
17
11
|
selectGroup,
|
|
@@ -26,53 +20,95 @@ import {
|
|
|
26
20
|
lineageLevels,
|
|
27
21
|
} from "../selectors";
|
|
28
22
|
import LineageDownloadButton from "./LineageDownloadButton";
|
|
23
|
+
import { LineageResourceToggle } from "./LineageResourceToggle";
|
|
24
|
+
import LineageDomainSelectorSkeleton from "./LineageDomainSelectorSkeleton";
|
|
25
|
+
import {
|
|
26
|
+
LINEAGE_DOMAIN_CACHE_KEY,
|
|
27
|
+
LINEAGE_DOMAIN_CACHE_TTL,
|
|
28
|
+
checkDomainsLineage,
|
|
29
|
+
readDomainAvailabilityCache,
|
|
30
|
+
writeDomainAvailabilityCache,
|
|
31
|
+
} from "./lineageDomainCache";
|
|
32
|
+
|
|
33
|
+
const singleOptionValue = (options = []) =>
|
|
34
|
+
options.length === 1 ? options[0]?.value : undefined;
|
|
29
35
|
|
|
30
36
|
export const LineageForm = ({
|
|
37
|
+
autoCollapse = true,
|
|
38
|
+
collapsible = true,
|
|
31
39
|
createGraph,
|
|
32
40
|
clearNodes,
|
|
41
|
+
domainAvailabilityChecker = checkDomainsLineage,
|
|
33
42
|
fetchNodes,
|
|
34
43
|
graph,
|
|
35
44
|
graphLoading,
|
|
36
|
-
groupOptions,
|
|
45
|
+
groupOptions = [],
|
|
37
46
|
levelsSelection,
|
|
38
47
|
lineageLevels,
|
|
39
48
|
loading,
|
|
40
|
-
|
|
49
|
+
onGraphSubmit,
|
|
50
|
+
resourceOptions = [],
|
|
41
51
|
selectGroup,
|
|
42
52
|
selectResources,
|
|
43
|
-
selectedGroups,
|
|
44
|
-
selectedResources,
|
|
53
|
+
selectedGroups = [],
|
|
54
|
+
selectedResources = [],
|
|
55
|
+
showDownloadButton = true,
|
|
45
56
|
}) => {
|
|
46
57
|
const [domainId, setDomainId] = useState(null);
|
|
47
58
|
const [open, setOpen] = useState(true);
|
|
48
59
|
const [selectLevels, setSelectLevels] = useState(levelsSelection);
|
|
60
|
+
const [unavailableDomainIds, setUnavailableDomainIds] = useState([]);
|
|
49
61
|
const [levels, setLevels] = useState(lineageLevels);
|
|
62
|
+
const availabilityRequestId = useRef(0);
|
|
63
|
+
const resourceValues = _.map("value")(resourceOptions);
|
|
64
|
+
const allResourcesSelected =
|
|
65
|
+
!_.isEmpty(resourceValues) &&
|
|
66
|
+
_.isEmpty(_.difference(resourceValues, selectedResources || []));
|
|
50
67
|
const handleSubmit = (type) => () => {
|
|
51
|
-
_.isNil(levels)
|
|
52
|
-
?
|
|
68
|
+
const graphParams = _.isNil(levels)
|
|
69
|
+
? {
|
|
53
70
|
ids: selectedResources,
|
|
54
71
|
type,
|
|
55
72
|
isRedirected: true,
|
|
56
|
-
}
|
|
57
|
-
:
|
|
73
|
+
}
|
|
74
|
+
: {
|
|
58
75
|
ids: selectedResources,
|
|
59
76
|
type,
|
|
60
77
|
levels,
|
|
61
78
|
isRedirected: true,
|
|
62
|
-
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
createGraph(graphParams);
|
|
82
|
+
setOpen(false);
|
|
83
|
+
onGraphSubmit && onGraphSubmit();
|
|
63
84
|
};
|
|
64
85
|
const disabled = _.isEmpty(selectedResources);
|
|
65
86
|
useEffect(() => {
|
|
66
|
-
setOpen(!graphLoading && _.isEmpty(graph));
|
|
67
|
-
}, [graph, graphLoading]);
|
|
87
|
+
if (autoCollapse) setOpen(!graphLoading && _.isEmpty(graph));
|
|
88
|
+
}, [autoCollapse, graph, graphLoading]);
|
|
68
89
|
useEffect(() => {
|
|
69
90
|
selectLevels === "all" && setLevels();
|
|
70
91
|
}, [selectLevels]);
|
|
71
92
|
useEffect(() => {
|
|
72
|
-
domainId &&
|
|
73
|
-
}, [domainId, fetchNodes
|
|
93
|
+
domainId && fetchNodes({ domain_id: domainId });
|
|
94
|
+
}, [domainId, fetchNodes]);
|
|
95
|
+
useEffect(() => {
|
|
96
|
+
const nextGroupLevel = groupOptions.findIndex((options, level) => {
|
|
97
|
+
const selectedGroup = _.nth(level, selectedGroups);
|
|
98
|
+
const optionValues = _.map("value")(options);
|
|
99
|
+
|
|
100
|
+
return !_.includes(selectedGroup)(optionValues);
|
|
101
|
+
});
|
|
102
|
+
const value = singleOptionValue(groupOptions[nextGroupLevel]);
|
|
103
|
+
|
|
104
|
+
if (value !== undefined) {
|
|
105
|
+
selectGroup({ id: value, domain_id: domainId });
|
|
106
|
+
}
|
|
107
|
+
}, [domainId, groupOptions, selectGroup, selectedGroups]);
|
|
108
|
+
|
|
74
109
|
useEffect(() => {
|
|
75
110
|
return () => {
|
|
111
|
+
availabilityRequestId.current += 1;
|
|
76
112
|
clearNodes();
|
|
77
113
|
};
|
|
78
114
|
}, [clearNodes]);
|
|
@@ -94,7 +130,6 @@ export const LineageForm = ({
|
|
|
94
130
|
clearNodes();
|
|
95
131
|
} else {
|
|
96
132
|
setDomainId(value);
|
|
97
|
-
fetchNodes({ domain_id: value });
|
|
98
133
|
}
|
|
99
134
|
};
|
|
100
135
|
|
|
@@ -104,56 +139,99 @@ export const LineageForm = ({
|
|
|
104
139
|
}
|
|
105
140
|
};
|
|
106
141
|
|
|
107
|
-
const handleDomainsLoaded = (
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
142
|
+
const handleDomainsLoaded = useCallback(
|
|
143
|
+
async ({ domains = [] }) => {
|
|
144
|
+
const requestId = availabilityRequestId.current + 1;
|
|
145
|
+
|
|
146
|
+
availabilityRequestId.current = requestId;
|
|
147
|
+
|
|
148
|
+
const cachedChecks = readDomainAvailabilityCache(domains);
|
|
149
|
+
const checks = cachedChecks || (await domainAvailabilityChecker(domains));
|
|
150
|
+
if (availabilityRequestId.current !== requestId) return;
|
|
151
|
+
|
|
152
|
+
if (!cachedChecks) writeDomainAvailabilityCache(domains, checks);
|
|
153
|
+
|
|
154
|
+
const availableDomainIds = checks
|
|
155
|
+
.filter(([, available]) => available)
|
|
156
|
+
.map(([id]) => id);
|
|
157
|
+
const unavailableDomainIds = checks
|
|
158
|
+
.filter(([, available]) => !available)
|
|
159
|
+
.map(([id]) => id);
|
|
160
|
+
const availableDomains = domains.filter(({ id }) =>
|
|
161
|
+
availableDomainIds.includes(`${id}`),
|
|
162
|
+
);
|
|
163
|
+
|
|
164
|
+
setUnavailableDomainIds(unavailableDomainIds);
|
|
165
|
+
|
|
166
|
+
if (availableDomains.length === 1) {
|
|
167
|
+
setDomainId(availableDomains[0].id);
|
|
168
|
+
}
|
|
169
|
+
},
|
|
170
|
+
[domainAvailabilityChecker],
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
const isLineageDomainDisabled = ({ id }) =>
|
|
174
|
+
unavailableDomainIds.includes(`${id}`);
|
|
175
|
+
|
|
176
|
+
const toggleAllResources = (e) => {
|
|
177
|
+
e && e.preventDefault();
|
|
178
|
+
selectResources(allResourcesSelected ? [] : resourceValues);
|
|
111
179
|
};
|
|
112
180
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
181
|
+
const clearSelection = () => {
|
|
182
|
+
setDomainId(null);
|
|
183
|
+
setSelectLevels(levelsSelection);
|
|
184
|
+
setLevels(lineageLevels);
|
|
185
|
+
selectResources([]);
|
|
186
|
+
clearNodes();
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
const form = (
|
|
190
|
+
<Form loading={loading} size="small" className="lineage-toolbar__form">
|
|
191
|
+
<div className="lineage-toolbar__fields">
|
|
192
|
+
<div className="lineage-selection-column">
|
|
193
|
+
<DomainSelector
|
|
194
|
+
action="viewLineage"
|
|
195
|
+
cacheKey={LINEAGE_DOMAIN_CACHE_KEY}
|
|
196
|
+
cacheTtl={LINEAGE_DOMAIN_CACHE_TTL}
|
|
197
|
+
className="lineage-domain-selector"
|
|
198
|
+
closeOnSelect
|
|
199
|
+
labels
|
|
200
|
+
loadingComponent={<LineageDomainSelectorSkeleton />}
|
|
201
|
+
onChange={handleDomainChange}
|
|
202
|
+
onLoad={handleDomainsLoaded}
|
|
203
|
+
optionDisabled={isLineageDomainDisabled}
|
|
204
|
+
query={DOMAINS_QUERY}
|
|
205
|
+
value={domainId}
|
|
206
|
+
/>
|
|
207
|
+
</div>
|
|
208
|
+
{_.map.convert({ cap: false })((options, level) => (
|
|
209
|
+
<div className="lineage-selection-column" key={level}>
|
|
210
|
+
<Form.Dropdown
|
|
211
|
+
className="lineage-column-dropdown"
|
|
212
|
+
placeholder={formatMessage({
|
|
213
|
+
id:
|
|
214
|
+
level == 0
|
|
215
|
+
? "lineage.group.placeholder"
|
|
216
|
+
: "lineage.subgroup.placeholder",
|
|
217
|
+
})}
|
|
218
|
+
fluid
|
|
219
|
+
search
|
|
220
|
+
selection
|
|
221
|
+
options={options}
|
|
222
|
+
loading={loading}
|
|
223
|
+
value={_.nth(level, selectedGroups) || null}
|
|
224
|
+
onChange={(_e, { value: id }) =>
|
|
225
|
+
selectGroup({ id, domain_id: domainId })
|
|
226
|
+
}
|
|
134
227
|
/>
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
level == 0
|
|
141
|
-
? "lineage.group.placeholder"
|
|
142
|
-
: "lineage.subgroup.placeholder",
|
|
143
|
-
})}
|
|
144
|
-
fluid
|
|
145
|
-
search
|
|
146
|
-
selection
|
|
147
|
-
options={options}
|
|
148
|
-
loading={loading}
|
|
149
|
-
value={_.nth(level, selectedGroups) || null}
|
|
150
|
-
onChange={(_e, { value: id }) =>
|
|
151
|
-
selectGroup({ id, domain_id: domainId })
|
|
152
|
-
}
|
|
153
|
-
/>
|
|
154
|
-
))(groupOptions)}
|
|
155
|
-
{_.isEmpty(resourceOptions) ? null : (
|
|
228
|
+
</div>
|
|
229
|
+
))(groupOptions)}
|
|
230
|
+
{_.isEmpty(resourceOptions) ? null : (
|
|
231
|
+
<div className="lineage-selection-column lineage-selection-column--resource">
|
|
232
|
+
<div className="lineage-resource-field">
|
|
156
233
|
<Form.Dropdown
|
|
234
|
+
className="lineage-column-dropdown lineage-resource-selector"
|
|
157
235
|
placeholder={formatMessage({
|
|
158
236
|
id: "lineage.resources.placeholder",
|
|
159
237
|
})}
|
|
@@ -165,90 +243,131 @@ export const LineageForm = ({
|
|
|
165
243
|
value={selectedResources}
|
|
166
244
|
onChange={(_e, { value }) => selectResources(value)}
|
|
167
245
|
/>
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
checked={selectLevels === "select"}
|
|
190
|
-
value="select"
|
|
191
|
-
onChange={(e, { value }) => setSelectLevels(value)}
|
|
192
|
-
label={formatMessage({
|
|
193
|
-
id: "lineage.form.levels.select.label",
|
|
194
|
-
})}
|
|
195
|
-
/>
|
|
196
|
-
</Form.Field>
|
|
197
|
-
</Form.Group>
|
|
198
|
-
<Form.Field disabled={selectLevels === "all" || disabled}>
|
|
199
|
-
<Form.Input
|
|
200
|
-
type="number"
|
|
201
|
-
onKeyDown={handleKeyDown}
|
|
202
|
-
control="input"
|
|
203
|
-
placeholder={formatMessage({
|
|
204
|
-
id: "lineage.form.levels.select.input",
|
|
246
|
+
<LineageResourceToggle
|
|
247
|
+
allResourcesSelected={allResourcesSelected}
|
|
248
|
+
disabled={_.isEmpty(resourceValues)}
|
|
249
|
+
onClick={toggleAllResources}
|
|
250
|
+
/>
|
|
251
|
+
</div>
|
|
252
|
+
</div>
|
|
253
|
+
)}
|
|
254
|
+
</div>
|
|
255
|
+
<div className="lineage-toolbar__controls">
|
|
256
|
+
<div className="lineage-toolbar__levels">
|
|
257
|
+
<Header as="h5">
|
|
258
|
+
<FormattedMessage id="lineage.form.levels.header" />
|
|
259
|
+
</Header>
|
|
260
|
+
<Form.Group inline className="lineage-toolbar__level-options">
|
|
261
|
+
<Form.Field className="lineage-toolbar__level-option">
|
|
262
|
+
<Form.Radio
|
|
263
|
+
disabled={disabled}
|
|
264
|
+
name="allLevels"
|
|
265
|
+
label={formatMessage({
|
|
266
|
+
id: "lineage.form.levels.all.label",
|
|
205
267
|
})}
|
|
206
|
-
value=
|
|
207
|
-
|
|
208
|
-
onChange={(e) =>
|
|
209
|
-
min="1"
|
|
268
|
+
value="all"
|
|
269
|
+
checked={selectLevels === "all"}
|
|
270
|
+
onChange={(e, { value }) => setSelectLevels(value)}
|
|
210
271
|
/>
|
|
211
272
|
</Form.Field>
|
|
212
|
-
<
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
<
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
273
|
+
<div className="field lineage-toolbar__level-depth">
|
|
274
|
+
<Form.Radio
|
|
275
|
+
disabled={disabled}
|
|
276
|
+
name="selectLevels"
|
|
277
|
+
checked={selectLevels === "select"}
|
|
278
|
+
value="select"
|
|
279
|
+
onChange={(e, { value }) => setSelectLevels(value)}
|
|
280
|
+
label={formatMessage({
|
|
281
|
+
id: "lineage.form.levels.select.label",
|
|
282
|
+
})}
|
|
283
|
+
/>
|
|
284
|
+
<Form.Field
|
|
285
|
+
className="lineage-toolbar__level-input"
|
|
286
|
+
disabled={selectLevels === "all" || disabled}
|
|
287
|
+
>
|
|
288
|
+
<Form.Input
|
|
289
|
+
type="number"
|
|
290
|
+
onKeyDown={handleKeyDown}
|
|
291
|
+
control="input"
|
|
292
|
+
value={levels || ""}
|
|
293
|
+
autoComplete="off"
|
|
294
|
+
onChange={(e) => changeLevels(e)}
|
|
295
|
+
min="1"
|
|
296
|
+
/>
|
|
297
|
+
</Form.Field>
|
|
298
|
+
</div>
|
|
299
|
+
</Form.Group>
|
|
300
|
+
</div>
|
|
301
|
+
<div className="lineage-toolbar__actions">
|
|
302
|
+
<Button
|
|
303
|
+
secondary
|
|
304
|
+
size="small"
|
|
305
|
+
disabled={_.isEmpty(selectedGroups)}
|
|
306
|
+
onClick={clearSelection}
|
|
307
|
+
>
|
|
308
|
+
<FormattedMessage id="navigation.lineage.clean" />
|
|
309
|
+
</Button>
|
|
310
|
+
<Button
|
|
311
|
+
primary
|
|
312
|
+
size="small"
|
|
313
|
+
disabled={disabled}
|
|
314
|
+
onClick={handleSubmit("impact")}
|
|
315
|
+
>
|
|
316
|
+
<FormattedMessage id="navigation.lineage.impact" />
|
|
317
|
+
</Button>
|
|
318
|
+
<Button
|
|
319
|
+
primary
|
|
320
|
+
size="small"
|
|
321
|
+
disabled={disabled}
|
|
322
|
+
onClick={handleSubmit("lineage")}
|
|
323
|
+
>
|
|
324
|
+
<FormattedMessage id="navigation.lineage.lineage" />
|
|
325
|
+
</Button>
|
|
326
|
+
{showDownloadButton ? <LineageDownloadButton /> : null}
|
|
327
|
+
</div>
|
|
328
|
+
</div>
|
|
329
|
+
</Form>
|
|
330
|
+
);
|
|
331
|
+
|
|
332
|
+
if (!collapsible) {
|
|
333
|
+
return (
|
|
334
|
+
<div className="lineage-toolbar lineage-toolbar--panel">
|
|
335
|
+
<div className="lineage-events-panel">
|
|
336
|
+
<div className="lineage-events-panel__header">
|
|
337
|
+
<span>
|
|
338
|
+
<FormattedMessage id="lineage.form.panel.header" />
|
|
339
|
+
</span>
|
|
340
|
+
<Icon name="sitemap" />
|
|
341
|
+
</div>
|
|
342
|
+
{form}
|
|
343
|
+
</div>
|
|
344
|
+
</div>
|
|
345
|
+
);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
return (
|
|
349
|
+
<Accordion className="lineage-toolbar">
|
|
350
|
+
<Accordion.Title
|
|
351
|
+
active={open}
|
|
352
|
+
onClick={() => setOpen(!open)}
|
|
353
|
+
className="noselect lineage-toolbar__title"
|
|
354
|
+
>
|
|
355
|
+
<Header as="h4">
|
|
356
|
+
<Icon name="dropdown" />
|
|
357
|
+
<FormattedMessage id="lineage.form.header" />
|
|
358
|
+
</Header>
|
|
359
|
+
</Accordion.Title>
|
|
360
|
+
<Accordion.Content active={open}>{form}</Accordion.Content>
|
|
361
|
+
</Accordion>
|
|
246
362
|
);
|
|
247
363
|
};
|
|
248
364
|
|
|
249
365
|
LineageForm.propTypes = {
|
|
366
|
+
autoCollapse: PropTypes.bool,
|
|
367
|
+
collapsible: PropTypes.bool,
|
|
250
368
|
clearNodes: PropTypes.func.isRequired,
|
|
251
369
|
createGraph: PropTypes.func.isRequired,
|
|
370
|
+
domainAvailabilityChecker: PropTypes.func,
|
|
252
371
|
fetchNodes: PropTypes.func,
|
|
253
372
|
graph: PropTypes.object,
|
|
254
373
|
graphLoading: PropTypes.bool,
|
|
@@ -256,11 +375,13 @@ LineageForm.propTypes = {
|
|
|
256
375
|
levelsSelection: PropTypes.string,
|
|
257
376
|
lineageLevels: PropTypes.number,
|
|
258
377
|
loading: PropTypes.bool,
|
|
378
|
+
onGraphSubmit: PropTypes.func,
|
|
259
379
|
resourceOptions: PropTypes.array,
|
|
260
380
|
selectGroup: PropTypes.func.isRequired,
|
|
261
381
|
selectResources: PropTypes.func.isRequired,
|
|
262
382
|
selectedGroups: PropTypes.array,
|
|
263
383
|
selectedResources: PropTypes.array,
|
|
384
|
+
showDownloadButton: PropTypes.bool,
|
|
264
385
|
};
|
|
265
386
|
|
|
266
387
|
const mapStateToProps = (state) => ({
|
|
@@ -253,7 +253,6 @@ export const LineageGraph = ({
|
|
|
253
253
|
onPointerDown={onPointerDown}
|
|
254
254
|
onPointerUp={onPointerUp}
|
|
255
255
|
onPointerCancel={onPointerUp}
|
|
256
|
-
style={{ border: "1px solid #d4d4d5", borderRadius: "5px" }}
|
|
257
256
|
>
|
|
258
257
|
<LineageDefs />
|
|
259
258
|
<g className="svg-pan-zoom_viewport">
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { useIntl, FormattedMessage } from "react-intl";
|
|
2
|
+
import { Icon } from "semantic-ui-react";
|
|
3
|
+
|
|
4
|
+
const LineageHeader = () => {
|
|
5
|
+
const { formatMessage } = useIntl();
|
|
6
|
+
|
|
7
|
+
return (
|
|
8
|
+
<div className="lineage-view__header">
|
|
9
|
+
<div className="lineage-view__header-main">
|
|
10
|
+
<div className="lineage-view__header-icon" aria-hidden="true">
|
|
11
|
+
<Icon
|
|
12
|
+
name={formatMessage({
|
|
13
|
+
id: "lineage.header.icon",
|
|
14
|
+
defaultMessage: "sitemap",
|
|
15
|
+
})}
|
|
16
|
+
/>
|
|
17
|
+
</div>
|
|
18
|
+
<div className="lineage-view__header-copy">
|
|
19
|
+
<div className="lineage-view__header-title-row">
|
|
20
|
+
<h2>
|
|
21
|
+
<FormattedMessage id="navigation.lineage" />
|
|
22
|
+
</h2>
|
|
23
|
+
</div>
|
|
24
|
+
<p>
|
|
25
|
+
<FormattedMessage id="lineage.header.description" />
|
|
26
|
+
</p>
|
|
27
|
+
</div>
|
|
28
|
+
</div>
|
|
29
|
+
</div>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export default LineageHeader;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import PropTypes from "prop-types";
|
|
2
|
+
import { useIntl } from "react-intl";
|
|
3
|
+
import { Icon } from "semantic-ui-react";
|
|
4
|
+
|
|
5
|
+
export const LineageResourceToggle = ({
|
|
6
|
+
allResourcesSelected,
|
|
7
|
+
disabled,
|
|
8
|
+
onClick,
|
|
9
|
+
}) => {
|
|
10
|
+
const { formatMessage } = useIntl();
|
|
11
|
+
const state = allResourcesSelected ? "on" : "off";
|
|
12
|
+
|
|
13
|
+
const icon = formatMessage({
|
|
14
|
+
id: `lineage.resources.toggle.${state}.icon`,
|
|
15
|
+
defaultMessage: allResourcesSelected ? "minus" : "plus",
|
|
16
|
+
}).replace("none", "");
|
|
17
|
+
|
|
18
|
+
const label = formatMessage({
|
|
19
|
+
id: `lineage.resources.toggle.${state}.label`,
|
|
20
|
+
defaultMessage: allResourcesSelected ? "remove all" : "add all",
|
|
21
|
+
}).replace("none", "");
|
|
22
|
+
|
|
23
|
+
const hoverText = formatMessage({
|
|
24
|
+
id: `lineage.resources.toggle.${state}.hover`,
|
|
25
|
+
defaultMessage: allResourcesSelected ? "remove all" : "add all",
|
|
26
|
+
}).replace("none", "");
|
|
27
|
+
|
|
28
|
+
const ariaLabel = formatMessage({
|
|
29
|
+
id: allResourcesSelected
|
|
30
|
+
? "lineage.resources.remove_all"
|
|
31
|
+
: "lineage.resources.add_all",
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (!icon && !label) return null;
|
|
35
|
+
|
|
36
|
+
return (
|
|
37
|
+
<button
|
|
38
|
+
type="button"
|
|
39
|
+
aria-label={ariaLabel}
|
|
40
|
+
className={`lineage-resource-toggle${state === "off" ? " lineage-resource-toggle--add" : ""}`}
|
|
41
|
+
disabled={disabled}
|
|
42
|
+
onClick={onClick}
|
|
43
|
+
>
|
|
44
|
+
<span title={hoverText} className="lineage-resource-toggle-content">
|
|
45
|
+
{icon ? <Icon name={icon} /> : null}
|
|
46
|
+
{label ? <span>{label}</span> : null}
|
|
47
|
+
</span>
|
|
48
|
+
</button>
|
|
49
|
+
);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
LineageResourceToggle.propTypes = {
|
|
53
|
+
allResourcesSelected: PropTypes.bool,
|
|
54
|
+
disabled: PropTypes.bool,
|
|
55
|
+
onClick: PropTypes.func,
|
|
56
|
+
};
|
|
@@ -1,22 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Routes, Route } from "react-router";
|
|
3
3
|
import { ProtectedRoute } from "@truedat/core/router";
|
|
4
|
-
import {
|
|
5
|
-
import LineageEvents from "./LineageEvents";
|
|
6
|
-
import LineageGraph from "./LineageGraph";
|
|
7
|
-
import LineageSample from "./LineageSample";
|
|
8
|
-
import LineageForm from "./LineageForm";
|
|
4
|
+
import { GRAPHS } from "@truedat/core/routes";
|
|
9
5
|
import GraphLoader from "./GraphLoader";
|
|
10
|
-
import
|
|
11
|
-
|
|
12
|
-
const Graphs = () => (
|
|
13
|
-
<>
|
|
14
|
-
<LineageForm />
|
|
15
|
-
<GraphRedirector />
|
|
16
|
-
{/* Load LineageGraph here so that its <Loader> is already available when clicking the LinageForm */}
|
|
17
|
-
<LineageGraph />
|
|
18
|
-
</>
|
|
19
|
-
);
|
|
6
|
+
import Graphs from "./Graphs";
|
|
20
7
|
|
|
21
8
|
export const LineageRoutes = () => {
|
|
22
9
|
return (
|
|
@@ -33,22 +20,6 @@ export const LineageRoutes = () => {
|
|
|
33
20
|
}
|
|
34
21
|
/>
|
|
35
22
|
</Route>
|
|
36
|
-
<Route
|
|
37
|
-
path={LINEAGE_EVENTS}
|
|
38
|
-
element={
|
|
39
|
-
<ProtectedRoute authorization="lineage">
|
|
40
|
-
<LineageEvents />
|
|
41
|
-
</ProtectedRoute>
|
|
42
|
-
}
|
|
43
|
-
/>
|
|
44
|
-
<Route
|
|
45
|
-
path={SAMPLE}
|
|
46
|
-
element={
|
|
47
|
-
<ProtectedRoute authorization="lineage">
|
|
48
|
-
<LineageSample />
|
|
49
|
-
</ProtectedRoute>
|
|
50
|
-
}
|
|
51
|
-
/>
|
|
52
23
|
<Route path="*" element={null} />
|
|
53
24
|
</Routes>
|
|
54
25
|
);
|