@truedat/dq 6.8.5 → 6.8.8

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/dq",
3
- "version": "6.8.5",
3
+ "version": "6.8.8",
4
4
  "description": "Truedat Web Data Quality Module",
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": "6.8.5",
37
+ "@truedat/test": "6.8.6",
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",
@@ -92,8 +92,8 @@
92
92
  },
93
93
  "dependencies": {
94
94
  "@apollo/client": "^3.7.1",
95
- "@truedat/core": "6.8.5",
96
- "@truedat/df": "6.8.5",
95
+ "@truedat/core": "6.8.6",
96
+ "@truedat/df": "6.8.6",
97
97
  "decode-uri-component": "^0.2.2",
98
98
  "graphql": "^15.5.3",
99
99
  "moment": "^2.29.4",
@@ -118,5 +118,5 @@
118
118
  "react-dom": ">= 16.8.6 < 17",
119
119
  "semantic-ui-react": ">= 2.0.3 < 2.2"
120
120
  },
121
- "gitHead": "b1c501fc90a7999f24fadacffafff294d8f9a15a"
121
+ "gitHead": "8b5f95c2dd85e395d3f8e9e38249875702ee7a10"
122
122
  }
@@ -0,0 +1,36 @@
1
+ import _ from "lodash/fp";
2
+ import React from "react";
3
+ import PropTypes from "prop-types";
4
+ import { connect } from "react-redux";
5
+ import { Button } from "semantic-ui-react";
6
+ import { Link } from "react-router-dom";
7
+ import { FormattedMessage } from "react-intl";
8
+ import { linkTo } from "@truedat/core/routes";
9
+
10
+ export const ImplementationStructureLinksActions = ({
11
+ implementation_id,
12
+ canCreateLink,
13
+ }) =>
14
+ implementation_id && canCreateLink ? (
15
+ <Button
16
+ floated="right"
17
+ primary
18
+ as={Link}
19
+ to={linkTo.IMPLEMENTATION_STRUCTURES_NEW({
20
+ implementation_id,
21
+ })}
22
+ content={<FormattedMessage id="links.actions.create" />}
23
+ />
24
+ ) : null;
25
+
26
+ ImplementationStructureLinksActions.propTypes = {
27
+ implementation_id: PropTypes.number,
28
+ canCreateLink: PropTypes.bool,
29
+ };
30
+
31
+ const mapStateToProps = (state) => ({
32
+ implementation_id: _.prop("id")(state.ruleImplementation),
33
+ canCreateLink: _.propOr(false, "link_structure")(state.implementationActions),
34
+ });
35
+
36
+ export default connect(mapStateToProps)(ImplementationStructureLinksActions);
@@ -1,163 +1,29 @@
1
- import _ from "lodash/fp";
2
1
  import React from "react";
3
2
  import PropTypes from "prop-types";
4
3
  import { connect } from "react-redux";
5
- import {
6
- Button,
7
- Grid,
8
- Header,
9
- Icon,
10
- List,
11
- Segment,
12
- Table,
13
- } from "semantic-ui-react";
14
- import { FormattedMessage } from "react-intl";
15
- import { Link } from "react-router-dom";
16
- import { linkTo } from "@truedat/core/routes";
17
- import { columnDecorator } from "@truedat/core/services";
18
- import ImplementationStructureDelete from "./ImplementationStructureDelete";
19
- import ImplementationStructureLink from "./ImplementationStructureLink";
20
-
21
- const ImplementationStructureDeleteDecorator = ({ id, implementation_id }) => (
22
- <ImplementationStructureDelete id={id} implementationId={implementation_id} />
23
- );
24
- ImplementationStructureDeleteDecorator.propTypes = {
25
- id: PropTypes.number,
26
- implementation_id: PropTypes.number,
27
- };
28
-
29
- const DomainDecorator = (domains) => (
30
- <List>
31
- {domains.map(({ name, parents }, i) => (
32
- <List.Item key={i}>
33
- {_.flow(_.map("name"), _.union([name]), _.join(" > "))(parents)}
34
- </List.Item>
35
- ))}
36
- </List>
37
- );
38
-
39
- DomainDecorator.propTypes = {
40
- domains: PropTypes.array,
41
- };
42
-
43
- const PathDecorator = (path) => (
44
- <span title={_.join(" › ")(path)}>
45
- {_.flow(_.join(" › "), _.truncate({ length: 90 }))(path)}
46
- </span>
47
- );
48
- PathDecorator.propTypes = {
49
- path: PropTypes.string,
50
- };
51
-
52
- const ImplementationStructureTypeDecorator = (type) => (
53
- <FormattedMessage id={`implementationsStructures.type.${type}`} />
54
- );
55
- ImplementationStructureTypeDecorator.propTypes = {
56
- type: PropTypes.string,
57
- };
58
-
59
- export const ImplementationStructures = ({ implementation, canCreateLink }) => {
60
- const deleteColumn = canCreateLink
61
- ? [
62
- {
63
- fieldSelector: _.identity,
64
- fieldDecorator: ImplementationStructureDeleteDecorator,
65
- },
66
- ]
67
- : [];
68
-
69
- const columns = [
70
- {
71
- header: "structure.name",
72
- fieldSelector: _.path("data_structure"),
73
- fieldDecorator: ImplementationStructureLink,
74
- },
75
- {
76
- header: "structure.domain",
77
- fieldSelector: _.path("data_structure.domains"),
78
- fieldDecorator: DomainDecorator,
79
- },
80
- {
81
- header: "structure.system",
82
- fieldSelector: _.path("data_structure.system.name"),
83
- },
84
- {
85
- header: "structure.path",
86
- fieldSelector: _.path("data_structure.current_version.path"),
87
- fieldDecorator: PathDecorator,
88
- },
89
- {
90
- header: "implementationsStructures.type",
91
- fieldSelector: _.path("type"),
92
- fieldDecorator: ImplementationStructureTypeDecorator,
93
- },
94
- ...deleteColumn,
95
- ];
96
-
97
- const headerRow = columns.map(({ header }, key) => (
98
- <Table.HeaderCell
99
- key={key}
100
- content={header ? <FormattedMessage id={header} /> : null}
4
+ import { Segment } from "semantic-ui-react";
5
+ import { getImplementationStructureLinksColumns } from "../selectors";
6
+ import ImplementationStructureLinksActions from "./ImplementationStructureLinksActions";
7
+
8
+ const LinksPane = React.lazy(() => import("@truedat/lm/components/LinksPane"));
9
+
10
+ export const ImplementationStructures = ({ groups }) => (
11
+ <Segment attached="bottom">
12
+ <LinksPane
13
+ groups={groups}
14
+ sourceType="implementations"
15
+ targetType="structure"
16
+ linksActions={<ImplementationStructureLinksActions />}
101
17
  />
102
- ));
103
-
104
- const implementation_id = _.prop("id")(implementation);
105
-
106
- return (
107
- <Segment attached="bottom">
108
- <Grid>
109
- {implementation_id && canCreateLink && (
110
- <Grid.Column width={16}>
111
- <Button
112
- floated="right"
113
- primary
114
- as={Link}
115
- to={linkTo.IMPLEMENTATION_STRUCTURES_NEW({
116
- implementation_id,
117
- })}
118
- content={<FormattedMessage id="links.actions.create" />}
119
- />
120
- </Grid.Column>
121
- )}
122
- {!_.isEmpty(implementation?.data_structures) ? (
123
- <Grid.Column width={16}>
124
- <Table
125
- headerRow={headerRow}
126
- renderBodyRow={(link, i) => (
127
- <Table.Row key={i}>
128
- {columns.map((column, ci) => (
129
- <Table.Cell
130
- key={ci}
131
- textAlign={_.prop("textAlign")(column)}
132
- content={columnDecorator(column)(link)}
133
- />
134
- ))}
135
- </Table.Row>
136
- )}
137
- tableData={implementation?.data_structures}
138
- />
139
- </Grid.Column>
140
- ) : (
141
- <Header as="h4">
142
- <Icon name="search" />
143
- <Header.Content>
144
- <FormattedMessage id="implementationStructures.empty" />
145
- </Header.Content>
146
- </Header>
147
- )}
148
- </Grid>
149
- </Segment>
150
- );
151
- };
18
+ </Segment>
19
+ );
152
20
 
153
21
  ImplementationStructures.propTypes = {
154
- implementation: PropTypes.object,
155
- canCreateLink: PropTypes.bool,
22
+ groups: PropTypes.array,
156
23
  };
157
24
 
158
25
  const mapStateToProps = (state) => ({
159
- implementation: state.ruleImplementation,
160
- canCreateLink: _.propOr(false, "link_structure")(state.implementationActions),
26
+ groups: getImplementationStructureLinksColumns(state),
161
27
  });
162
28
 
163
29
  export default connect(mapStateToProps)(ImplementationStructures);
@@ -1,91 +1,120 @@
1
- import React from "react";
1
+ import React, { Suspense } from "react";
2
+ import { waitFor } from "@testing-library/react";
2
3
  import { render } from "@truedat/test/render";
3
4
  import { ImplementationStructures } from "../ImplementationStructures";
5
+ import { defaultImplementationStructureLinksColumns } from "../../selectors";
6
+
7
+ const columns = defaultImplementationStructureLinksColumns;
8
+
9
+ const groups = [
10
+ [
11
+ columns,
12
+ [
13
+ "undefined",
14
+ [
15
+ {
16
+ data_structure: {
17
+ current_version: {
18
+ deleted_at: null,
19
+ name: "AGENCIA RECIBO",
20
+ },
21
+ id: 10397859,
22
+ },
23
+ data_structure_id: 10397859,
24
+ id: 21844,
25
+ implementation_id: 11932,
26
+ type: "population",
27
+ },
28
+ ],
29
+ ],
30
+ ],
31
+ [
32
+ columns,
33
+ [
34
+ "deleted",
35
+ [
36
+ {
37
+ data_structure: {
38
+ current_version: {
39
+ deleted_at: "2023-07-12T08:11:23.000000Z",
40
+ name: "/BEV1/RBKP",
41
+ },
42
+ id: 12579384,
43
+ },
44
+ data_structure_id: 12579384,
45
+ id: 21800,
46
+ implementation_id: 11932,
47
+ type: "dataset",
48
+ },
49
+ ],
50
+ ],
51
+ ],
52
+ ];
4
53
 
5
54
  describe("<ImplementationStructures />", () => {
6
55
  const renderOpts = {
56
+ fallback: "lazy",
7
57
  messages: {
8
58
  en: {
9
- "structure.domain": "domain",
10
- "structure.name": "name",
11
- "structure.system": "system",
12
- "structure.path": "path",
13
- "implementationsStructures.type": "type",
14
- "links.actions.create": "create",
15
- "implementationStructures.empty": "empty",
59
+ "implementationsRelation.master.table.title": "Links to Structures",
60
+ "implementationsDeletedRelation.table.title": "Deleted Structures",
61
+ "links.actions.create": "Create",
16
62
  "implementationsStructures.type.dataset": "dataset",
63
+ "implementationsStructures.type.population": "population",
17
64
  },
18
65
  },
19
66
  };
20
67
 
21
- it("matches the latest snapshot", () => {
22
- const props = {
23
- implementation: {
24
- data_structures: [
25
- {
26
- data_structure: {
27
- id: 1,
28
- name: "foo",
29
- system: { name: "bar" },
30
- domains: [{ name: "foo_domain", parents: [{ name: "bar" }] }],
31
- current_version: {
32
- name: "qux",
33
- path: ["baz"],
34
- },
35
- },
36
- type: "dataset",
37
- },
38
- ],
39
- },
40
- canCreateLink: true,
41
- };
42
- const { container } = render(
43
- <ImplementationStructures {...props} />,
68
+ it("matches the latest snapshot", async () => {
69
+ const props = { groups };
70
+ const { container, queryByText } = render(
71
+ <Suspense fallback={null}>
72
+ <ImplementationStructures {...props} />
73
+ </Suspense>,
44
74
  renderOpts
45
75
  );
76
+
77
+ await waitFor(() =>
78
+ expect(queryByText(/AGENCIA RECIBO/i)).toBeInTheDocument()
79
+ );
80
+
46
81
  expect(container).toMatchSnapshot();
47
82
  });
48
83
 
49
- it("matches the latest snapshot without create permission", () => {
50
- const props = {
51
- implementation: {
52
- data_structures: [
53
- {
54
- data_structure: {
55
- id: 1,
56
- name: "foo",
57
- domains: [{ name: "foo_domain", parents: [{ name: "bar" }] }],
58
- system: { name: "bar" },
59
- path: ["baz"],
60
- current_version: {
61
- name: "qux",
62
- path: ["baz"],
63
- },
64
- },
65
- type: "dataset",
66
- },
67
- ],
68
- },
69
- canCreateLink: false,
84
+ it("matches the latest snapshot without create permission", async () => {
85
+ const props = { groups };
86
+ const state = {
87
+ ruleImplementation: { id: 1 },
88
+ implementationActions: { link_structure: {} },
70
89
  };
71
- const { container } = render(
72
- <ImplementationStructures {...props} />,
73
- renderOpts
90
+ const { getByRole } = render(
91
+ <Suspense fallback={null}>
92
+ <ImplementationStructures {...props} />
93
+ </Suspense>,
94
+ { ...renderOpts, state }
95
+ );
96
+ await waitFor(() =>
97
+ expect(getByRole("button", { name: /create/i })).toBeEnabled()
74
98
  );
75
- expect(container).toMatchSnapshot();
76
99
  });
77
100
 
78
- it("matches the latest snapshot without data_structures", () => {
79
- const props = {
80
- implementation: {
81
- data_structures: [],
82
- },
83
- canCreateLink: true,
101
+ it("matches the latest snapshot without data_structures", async () => {
102
+ const state = {
103
+ ruleImplementation: { id: 1 },
104
+ implementationActions: { link_structure: {} },
84
105
  };
85
- const { container } = render(
86
- <ImplementationStructures {...props} />,
87
- renderOpts
106
+ const props = [];
107
+ const { container, getByRole } = render(
108
+ <Suspense fallback={null}>
109
+ <ImplementationStructures {...props} />
110
+ </Suspense>,
111
+ { ...renderOpts, state }
88
112
  );
113
+
114
+ await waitFor(() =>
115
+ expect(getByRole("button", { name: /create/i })).toBeEnabled()
116
+ );
117
+
89
118
  expect(container).toMatchSnapshot();
90
119
  });
91
120
  });
@@ -4,217 +4,131 @@ exports[`<ImplementationStructures /> matches the latest snapshot 1`] = `
4
4
  <div>
5
5
  <div
6
6
  class="ui bottom attached segment"
7
+ style=""
7
8
  >
8
9
  <div
9
10
  class="ui grid"
10
11
  >
11
12
  <div
12
- class="sixteen wide column"
13
+ class="row"
13
14
  >
14
- <table
15
- class="ui table"
15
+ <div
16
+ class="column"
17
+ />
18
+ </div>
19
+ <div
20
+ class="row"
21
+ >
22
+ <div
23
+ class="column"
16
24
  >
17
- <thead
18
- class=""
25
+ <h3
26
+ class="ui header"
19
27
  >
20
- <tr
21
- class=""
22
- >
23
- <th
24
- class=""
25
- >
26
- name
27
- </th>
28
- <th
29
- class=""
30
- >
31
- domain
32
- </th>
33
- <th
34
- class=""
35
- >
36
- system
37
- </th>
38
- <th
39
- class=""
40
- >
41
- path
42
- </th>
43
- <th
44
- class=""
45
- >
46
- type
47
- </th>
48
- <th
49
- class=""
50
- />
51
- </tr>
52
- </thead>
53
- <tbody
54
- class=""
28
+ Links to Structures
29
+ </h3>
30
+ <table
31
+ class="ui table"
55
32
  >
56
- <tr
33
+ <thead
57
34
  class=""
58
35
  >
59
- <td
36
+ <tr
60
37
  class=""
61
38
  >
62
- <a
63
- href="/structures/1"
39
+ <th
40
+ class=""
41
+ >
42
+ name
43
+ </th>
44
+ <th
45
+ class=""
64
46
  >
65
- qux
66
- </a>
67
- </td>
68
- <td
47
+ type
48
+ </th>
49
+ </tr>
50
+ </thead>
51
+ <tbody
52
+ class=""
53
+ >
54
+ <tr
69
55
  class=""
70
56
  >
71
- <div
72
- class="ui list"
73
- role="list"
57
+ <td
58
+ class=""
74
59
  >
75
- <div
76
- class="item"
77
- role="listitem"
60
+ <a
61
+ href="/structures/10397859"
78
62
  >
79
- bar &gt; foo_domain
80
- </div>
81
- </div>
82
- </td>
83
- <td
84
- class=""
85
- >
86
- bar
87
- </td>
88
- <td
89
- class=""
90
- >
91
- <span
92
- title="baz"
63
+ AGENCIA RECIBO
64
+ </a>
65
+ </td>
66
+ <td
67
+ class=""
93
68
  >
94
- baz
95
- </span>
96
- </td>
97
- <td
98
- class=""
99
- >
100
- dataset
101
- </td>
102
- <td
103
- class=""
104
- >
105
- <i
106
- aria-hidden="true"
107
- class="red trash alternate outline icon"
108
- />
109
- </td>
110
- </tr>
111
- </tbody>
112
- </table>
69
+ population
70
+ </td>
71
+ </tr>
72
+ </tbody>
73
+ </table>
74
+ </div>
113
75
  </div>
114
- </div>
115
- </div>
116
- </div>
117
- `;
118
-
119
- exports[`<ImplementationStructures /> matches the latest snapshot without create permission 1`] = `
120
- <div>
121
- <div
122
- class="ui bottom attached segment"
123
- >
124
- <div
125
- class="ui grid"
126
- >
127
76
  <div
128
- class="sixteen wide column"
77
+ class="row"
129
78
  >
130
- <table
131
- class="ui table"
79
+ <div
80
+ class="column"
132
81
  >
133
- <thead
134
- class=""
82
+ <h3
83
+ class="ui header"
135
84
  >
136
- <tr
137
- class=""
138
- >
139
- <th
140
- class=""
141
- >
142
- name
143
- </th>
144
- <th
145
- class=""
146
- >
147
- domain
148
- </th>
149
- <th
150
- class=""
151
- >
152
- system
153
- </th>
154
- <th
155
- class=""
156
- >
157
- path
158
- </th>
159
- <th
160
- class=""
161
- >
162
- type
163
- </th>
164
- </tr>
165
- </thead>
166
- <tbody
167
- class=""
85
+ Deleted Structures
86
+ </h3>
87
+ <table
88
+ class="ui table"
168
89
  >
169
- <tr
90
+ <thead
170
91
  class=""
171
92
  >
172
- <td
93
+ <tr
173
94
  class=""
174
95
  >
175
- <a
176
- href="/structures/1"
96
+ <th
97
+ class=""
177
98
  >
178
- qux
179
- </a>
180
- </td>
181
- <td
99
+ name
100
+ </th>
101
+ <th
102
+ class=""
103
+ >
104
+ type
105
+ </th>
106
+ </tr>
107
+ </thead>
108
+ <tbody
109
+ class=""
110
+ >
111
+ <tr
182
112
  class=""
183
113
  >
184
- <div
185
- class="ui list"
186
- role="list"
114
+ <td
115
+ class=""
187
116
  >
188
- <div
189
- class="item"
190
- role="listitem"
117
+ <a
118
+ href="/structures/12579384"
191
119
  >
192
- bar &gt; foo_domain
193
- </div>
194
- </div>
195
- </td>
196
- <td
197
- class=""
198
- >
199
- bar
200
- </td>
201
- <td
202
- class=""
203
- >
204
- <span
205
- title="baz"
120
+ /BEV1/RBKP
121
+ </a>
122
+ </td>
123
+ <td
124
+ class=""
206
125
  >
207
- baz
208
- </span>
209
- </td>
210
- <td
211
- class=""
212
- >
213
- dataset
214
- </td>
215
- </tr>
216
- </tbody>
217
- </table>
126
+ dataset
127
+ </td>
128
+ </tr>
129
+ </tbody>
130
+ </table>
131
+ </div>
218
132
  </div>
219
133
  </div>
220
134
  </div>
@@ -229,19 +143,21 @@ exports[`<ImplementationStructures /> matches the latest snapshot without data_s
229
143
  <div
230
144
  class="ui grid"
231
145
  >
232
- <h4
233
- class="ui header"
146
+ <div
147
+ class="row"
234
148
  >
235
- <i
236
- aria-hidden="true"
237
- class="search icon"
238
- />
239
149
  <div
240
- class="content"
150
+ class="column"
241
151
  >
242
- empty
152
+ <a
153
+ class="ui primary right floated button"
154
+ href="/implementations/1/structures/new"
155
+ role="button"
156
+ >
157
+ Create
158
+ </a>
243
159
  </div>
244
- </h4>
160
+ </div>
245
161
  </div>
246
162
  </div>
247
163
  </div>
@@ -0,0 +1,56 @@
1
+ import _ from "lodash/fp";
2
+ import { getImplementationStructureLinksColumns } from "..";
3
+ // import { defaultImplementationStructureLinksColumns } from "../../selectors";
4
+
5
+ const foo = {
6
+ data_structure: {
7
+ current_version: {
8
+ deleted_at: "2023-07-12T08:11:23.000000Z",
9
+ name: "/BEV1/RBKP",
10
+ },
11
+ id: 12579384,
12
+ },
13
+ data_structure_id: 12579384,
14
+ id: 21800,
15
+ implementation_id: 11932,
16
+ type: "dataset",
17
+ };
18
+
19
+ const bar = {
20
+ data_structure: {
21
+ current_version: {
22
+ deleted_at: null,
23
+ name: "AGENCIA RECIBO",
24
+ },
25
+ id: 10397859,
26
+ },
27
+ data_structure_id: 10397859,
28
+ id: 21844,
29
+ implementation_id: 11932,
30
+ type: "population",
31
+ };
32
+
33
+ const data_structures = [foo, bar];
34
+
35
+ // const columns = defaultImplementationStructureLinksColumns
36
+
37
+ describe("selectors: getImplementationStructureLinksColumns", () => {
38
+ const state = {
39
+ ruleImplementation: {
40
+ id: 1,
41
+ data_structures,
42
+ },
43
+ implementationActions: { link_structure: {} },
44
+ };
45
+
46
+ it("should return all links", () => {
47
+ const links = _.flow(
48
+ getImplementationStructureLinksColumns,
49
+ _.map(_.last)
50
+ )(state);
51
+ expect(links).toEqual([
52
+ ["undefined", [bar]],
53
+ ["deleted", [foo]],
54
+ ]);
55
+ });
56
+ });
@@ -0,0 +1,184 @@
1
+ import _ from "lodash/fp";
2
+ import React from "react";
3
+ import PropTypes from "prop-types";
4
+ import { Icon, Label, List } from "semantic-ui-react";
5
+ import { createSelector } from "reselect";
6
+ import { FormattedMessage } from "react-intl";
7
+ import Moment from "react-moment";
8
+ import { accentInsensitivePathOrder } from "@truedat/core/services/sort";
9
+ import ImplementationStructureDelete from "../components/ImplementationStructureDelete";
10
+ import ImplementationStructureLink from "../components/ImplementationStructureLink";
11
+
12
+ const ImplementationStructureDeleteDecorator = ({ id, implementation_id }) => (
13
+ <ImplementationStructureDelete id={id} implementationId={implementation_id} />
14
+ );
15
+ ImplementationStructureDeleteDecorator.propTypes = {
16
+ id: PropTypes.number,
17
+ implementation_id: PropTypes.number,
18
+ };
19
+
20
+ const deletedDateDecorator = (date) => (
21
+ <Label className="alert warning">
22
+ <Icon name="warning circle" color="red" />
23
+ <Moment locale="es" date={date} format="YYYY-MM-DD HH:mm" />
24
+ </Label>
25
+ );
26
+
27
+ const dateDecorator = (date) => (
28
+ <Moment locale="es" date={date} format="YYYY-MM-DD HH:mm" />
29
+ );
30
+
31
+ const DomainDecorator = (domains) => (
32
+ <List>
33
+ {domains.map(({ name, parents }, i) => (
34
+ <List.Item key={i}>
35
+ {_.flow(_.map("name"), _.union([name]), _.join(" > "))(parents)}
36
+ </List.Item>
37
+ ))}
38
+ </List>
39
+ );
40
+
41
+ DomainDecorator.propTypes = {
42
+ domains: PropTypes.array,
43
+ };
44
+
45
+ const PathDecorator = (path) => (
46
+ <span title={_.join(" › ")(path)}>
47
+ {_.flow(_.join(" › "), _.truncate({ length: 90 }))(path)}
48
+ </span>
49
+ );
50
+ PathDecorator.propTypes = {
51
+ path: PropTypes.string,
52
+ };
53
+
54
+ const ImplementationStructureTypeDecorator = (type) => (
55
+ <FormattedMessage id={`implementationsStructures.type.${type}`} />
56
+ );
57
+ ImplementationStructureTypeDecorator.propTypes = {
58
+ type: PropTypes.string,
59
+ };
60
+
61
+ export const defaultImplementationStructureLinksColumns = [
62
+ {
63
+ name: "name",
64
+ fieldSelector: _.path("data_structure"),
65
+ fieldDecorator: ImplementationStructureLink,
66
+ },
67
+ {
68
+ name: "domain",
69
+ fieldSelector: _.path("data_structure.domains"),
70
+ fieldDecorator: DomainDecorator,
71
+ },
72
+ {
73
+ name: "system",
74
+ fieldSelector: _.path("data_structure.system.name"),
75
+ },
76
+ {
77
+ name: "path",
78
+ fieldSelector: _.path("data_structure.current_version.path"),
79
+ fieldDecorator: PathDecorator,
80
+ },
81
+ {
82
+ name: "updated_at",
83
+ fieldSelector: _.path("data_structure.updated_at"),
84
+ fieldDecorator: dateDecorator,
85
+ },
86
+ {
87
+ name: "type",
88
+ fieldSelector: _.path("type"),
89
+ fieldDecorator: ImplementationStructureTypeDecorator,
90
+ },
91
+ ];
92
+
93
+ const getStructureLinks = ({ ruleImplementation }) =>
94
+ ruleImplementation?.data_structures;
95
+
96
+ const getAction = (state) =>
97
+ !!_.prop("link_structure")(state.implementationActions);
98
+
99
+ const getColumns = (state) =>
100
+ _.defaultTo(defaultImplementationStructureLinksColumns)(
101
+ state.implementationStructureLinksColumns
102
+ );
103
+ const orderedLinks = (links) =>
104
+ _.sortBy(accentInsensitivePathOrder("current_version.name"))(links);
105
+
106
+ const withActions = (columns, canCreateLink) => {
107
+ const deleteColumn = canCreateLink
108
+ ? [
109
+ {
110
+ name: "_actions",
111
+ fieldSelector: _.identity,
112
+ fieldDecorator: ImplementationStructureDeleteDecorator,
113
+ },
114
+ ]
115
+ : [];
116
+ const result = [...columns, ...deleteColumn];
117
+
118
+ return result;
119
+ };
120
+
121
+ const withDeletedAttribute = (columns, tag) =>
122
+ tag == "deleted"
123
+ ? _.map((c) =>
124
+ _.propEq("name", "updated_at")(c)
125
+ ? {
126
+ name: "deleted_at",
127
+ fieldSelector: _.path(
128
+ "data_structure.current_version.deleted_at"
129
+ ),
130
+ fieldDecorator: deletedDateDecorator,
131
+ }
132
+ : c
133
+ )(columns)
134
+ : columns;
135
+
136
+ const mapColumns = (tag, columns, canCreateLink) =>
137
+ _.flow(
138
+ (cols) => withActions(cols, canCreateLink),
139
+ (cols) => withDeletedAttribute(cols, tag)
140
+ )(columns);
141
+
142
+ const withHeaders = (pair, columns, canCreateLink) => [
143
+ mapColumns(_.first(pair), columns, canCreateLink),
144
+ pair,
145
+ ];
146
+
147
+ const implementationStructureDeletedLinks = (links, columns, canCreateLink) => {
148
+ const deleted = _.flow(
149
+ orderedLinks,
150
+ _.filter(
151
+ ({ data_structure }) =>
152
+ !_.isEmpty(_.get("current_version.deleted_at", data_structure))
153
+ )
154
+ )(links);
155
+ return _.isEmpty(deleted)
156
+ ? []
157
+ : [withHeaders(["deleted", deleted], columns, canCreateLink)];
158
+ };
159
+
160
+ const implementationStructureLinks = (links, columns, canCreateLink) =>
161
+ _.flow(
162
+ orderedLinks,
163
+ _.filter(({ data_structure }) =>
164
+ _.isEmpty(_.get("current_version.deleted_at", data_structure))
165
+ ),
166
+ _.groupBy("\uffee"),
167
+ _.toPairs,
168
+ _.sortBy(([k]) => k),
169
+ _.map((pair) => withHeaders(pair, columns, canCreateLink))
170
+ )(links);
171
+
172
+ export const getImplementationStructureLinksColumns = createSelector(
173
+ [getStructureLinks, getColumns, getAction],
174
+ (structureLinks, columns, canCreateLink) => {
175
+ return [
176
+ ...implementationStructureLinks(structureLinks, columns, canCreateLink),
177
+ ...implementationStructureDeletedLinks(
178
+ structureLinks,
179
+ columns,
180
+ canCreateLink
181
+ ),
182
+ ];
183
+ }
184
+ );
@@ -1,5 +1,9 @@
1
1
  export { datasetDefaultFiltersSelector } from "./datasetDefaultFiltersSelector";
2
2
  export { getImplementationsExecution } from "./getImplementationsExecution";
3
+ export {
4
+ getImplementationStructureLinksColumns,
5
+ defaultImplementationStructureLinksColumns,
6
+ } from "./getImplementationStructureLinksColumns";
3
7
  export { getRuleAvailableFilters } from "./getRuleAvailableFilters";
4
8
  export { getRuleFilterTypes } from "./getRuleFilterTypes";
5
9
  export { getRuleSelectedFilters } from "./getRuleSelectedFilters";