@truedat/dd 8.12.2 → 8.12.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.
Files changed (75) hide show
  1. package/package.json +3 -3
  2. package/src/api/__tests__/queries.spec.js +55 -0
  3. package/src/api/queries.js +31 -0
  4. package/src/components/Grant.js +106 -16
  5. package/src/components/GrantRequest.js +2 -2
  6. package/src/components/GrantRequestBulkApprovalPopup.js +0 -1
  7. package/src/components/GrantsDownloadButton.js +9 -1
  8. package/src/components/GrantsTable.js +4 -1
  9. package/src/components/StructureFields.js +7 -4
  10. package/src/components/StructureGrantCartUserSelector.js +29 -4
  11. package/src/components/StructureGrantDropdown.js +7 -1
  12. package/src/components/StructureGrants.js +4 -1
  13. package/src/components/StructuresUpdateOption.js +2 -2
  14. package/src/components/SystemStructures.js +3 -3
  15. package/src/components/__tests__/CatalogViewConfigForm.spec.js +2 -0
  16. package/src/components/__tests__/EditDomainForm.spec.js +3 -1
  17. package/src/components/__tests__/Grant.spec.js +171 -0
  18. package/src/components/__tests__/GrantApprovalRuleForm.spec.js +2 -0
  19. package/src/components/__tests__/GrantApprovalRuleNew.spec.js +8 -0
  20. package/src/components/__tests__/GrantApprovalRules.spec.js +4 -0
  21. package/src/components/__tests__/GrantRequest.spec.js +4 -4
  22. package/src/components/__tests__/GrantRequestBulkActions.spec.js +1 -4
  23. package/src/components/__tests__/GrantRequestsSearchResults.spec.js +2 -0
  24. package/src/components/__tests__/GrantsDownloadButton.spec.js +58 -2
  25. package/src/components/__tests__/GrantsTable.spec.js +22 -2
  26. package/src/components/__tests__/LineageDefs.spec.js +6 -1
  27. package/src/components/__tests__/LineageForm.spec.js +1 -0
  28. package/src/components/__tests__/LineageGraphToolbar.spec.js +19 -17
  29. package/src/components/__tests__/LineageInspectorPanel.spec.js +17 -9
  30. package/src/components/__tests__/ProfileGroup.spec.js +7 -1
  31. package/src/components/__tests__/ReferenceDatasetForm.spec.js +2 -0
  32. package/src/components/__tests__/ReferenceDatasetRoutes.spec.js +9 -0
  33. package/src/components/__tests__/StructureGrantCartCheckout.spec.js +39 -1
  34. package/src/components/__tests__/StructureGrantCartInformation.spec.js +5 -2
  35. package/src/components/__tests__/StructureGrantCartUserSelector.spec.js +128 -0
  36. package/src/components/__tests__/StructureGrantDropdown.spec.js +92 -0
  37. package/src/components/__tests__/StructureGrantListButton.spec.js +70 -0
  38. package/src/components/__tests__/StructureGrantSummaryButton.spec.js +36 -1
  39. package/src/components/__tests__/StructureGrants.spec.js +12 -0
  40. package/src/components/__tests__/StructureRelationRow.spec.js +72 -4
  41. package/src/components/__tests__/StructureRelations.spec.js +18 -0
  42. package/src/components/__tests__/StructureRoles.spec.js +9 -0
  43. package/src/components/__tests__/StructureRow.spec.js +13 -4
  44. package/src/components/__tests__/StructureSelector.spec.js +2 -0
  45. package/src/components/__tests__/StructureTag.spec.js +2 -0
  46. package/src/components/__tests__/StructureTagForm.spec.js +2 -0
  47. package/src/components/__tests__/StructureType.spec.js +3 -1
  48. package/src/components/__tests__/StructureTypeForm.spec.js +3 -1
  49. package/src/components/__tests__/StructureView.spec.js +17 -1
  50. package/src/components/__tests__/StructuresGrantRequestView.spec.js +2 -0
  51. package/src/components/__tests__/StructuresView.spec.js +2 -1
  52. package/src/components/__tests__/Tag.spec.js +4 -1
  53. package/src/components/__tests__/Tags.spec.js +7 -1
  54. package/src/components/__tests__/__snapshots__/GrantsTable.spec.js.snap +34 -2
  55. package/src/components/__tests__/__snapshots__/LineageDefs.spec.js.snap +32 -30
  56. package/src/components/__tests__/__snapshots__/StructureFields.spec.js.snap +1 -16
  57. package/src/components/__tests__/__snapshots__/StructureRelationRow.spec.js.snap +23 -19
  58. package/src/components/__tests__/__snapshots__/StructureRow.spec.js.snap +28 -24
  59. package/src/components/__tests__/__snapshots__/StructuresUpdateOption.spec.js.snap +7 -3
  60. package/src/messages/en.js +2 -2
  61. package/src/messages/es.js +2 -2
  62. package/src/reducers/__tests__/grantRequestsCart.spec.js +17 -0
  63. package/src/reducers/__tests__/structureRelations.spec.js +28 -0
  64. package/src/reducers/grantRequestsCart.js +3 -0
  65. package/src/selectors/__tests__/__snapshots__/getGrantsColumns.spec.js.snap +1 -9
  66. package/src/selectors/__tests__/getGrantRequestsSearchColumns.spec.js +11 -4
  67. package/src/selectors/__tests__/getGrantsColumns.spec.js +295 -0
  68. package/src/selectors/getBusinessConceptsLinksToStructuresColumnsSelector.js +3 -5
  69. package/src/selectors/getGrantRequestsSearchColumns.js +3 -5
  70. package/src/selectors/getGrantsColumns.js +85 -11
  71. package/src/selectors/getLinkedImplementationsToStructuresColumns.js +3 -7
  72. package/src/selectors/getStructureFieldColumns.js +7 -6
  73. package/src/selectors/getStructureProperties.js +2 -5
  74. package/src/selectors/getStructuresUploadEventColumns.js +2 -7
  75. package/src/selectors/structureColumnsSelector.js +13 -16
@@ -149,3 +149,298 @@ describe("EndDateDecorator", () => {
149
149
  expect(container).toMatchSnapshot();
150
150
  });
151
151
  });
152
+
153
+ describe("user or group column", () => {
154
+ const authentication = { user_name: "baz" };
155
+
156
+ const userColumn = () =>
157
+ _.find({ name: "user" })(getGrantsTableColumns({ authentication }));
158
+
159
+ const deletedMessages = {
160
+ en: {
161
+ "deleted.user": "Deleted user",
162
+ "deleted.group": "Deleted group",
163
+ },
164
+ };
165
+
166
+ it("shows user group alias when grant is for a group", () => {
167
+ const column = userColumn();
168
+ const grant = {
169
+ user: null,
170
+ user_group: { id: 10, name: "foo", alias: "bar" },
171
+ };
172
+ const FieldDecorator = column.fieldDecorator;
173
+ const rendered = render(
174
+ <FieldDecorator {...column.fieldSelector(grant)} />,
175
+ );
176
+ expect(rendered.getByText(/^bar$/i)).toBeInTheDocument();
177
+ });
178
+
179
+ it("shows user group name when alias is empty", () => {
180
+ const column = userColumn();
181
+ const grant = {
182
+ user: null,
183
+ user_group: { id: 10, name: "foo", alias: "" },
184
+ };
185
+ const FieldDecorator = column.fieldDecorator;
186
+ const rendered = render(
187
+ <FieldDecorator {...column.fieldSelector(grant)} />,
188
+ );
189
+ expect(rendered.getByText(/^foo$/i)).toBeInTheDocument();
190
+ });
191
+
192
+ it("shows Deleted group when grant has user_group_id and no user_group", () => {
193
+ const column = userColumn();
194
+ const grant = {
195
+ user: null,
196
+ user_group_id: 10,
197
+ user_group: null,
198
+ };
199
+ const FieldDecorator = column.fieldDecorator;
200
+ const rendered = render(
201
+ <FieldDecorator {...column.fieldSelector(grant)} />,
202
+ { messages: deletedMessages },
203
+ );
204
+ expect(rendered.getByText(/^deleted group$/i)).toBeInTheDocument();
205
+ expect(rendered.queryByText(/^deleted user$/i)).not.toBeInTheDocument();
206
+ });
207
+
208
+ it("shows user full name when grant is for a user", () => {
209
+ const column = userColumn();
210
+ const grant = {
211
+ user: {
212
+ full_name: "foo user",
213
+ email: "foo@ext",
214
+ user_name: "foo",
215
+ },
216
+ };
217
+ const FieldDecorator = column.fieldDecorator;
218
+ const rendered = render(
219
+ <FieldDecorator {...column.fieldSelector(grant)} />,
220
+ { messages: deletedMessages },
221
+ );
222
+ expect(rendered.getByText(/foo user/i)).toBeInTheDocument();
223
+ expect(rendered.queryByText(/^deleted group$/i)).not.toBeInTheDocument();
224
+ });
225
+
226
+ it("shows Deleted user when grant has user_id and no usable user", () => {
227
+ const column = userColumn();
228
+ const grant = {
229
+ user_id: 7,
230
+ user: null,
231
+ };
232
+ const FieldDecorator = column.fieldDecorator;
233
+ const rendered = render(
234
+ <FieldDecorator {...column.fieldSelector(grant)} />,
235
+ { messages: deletedMessages },
236
+ );
237
+ expect(rendered.getByText(/^deleted user$/i)).toBeInTheDocument();
238
+ expect(rendered.queryByText(/^deleted group$/i)).not.toBeInTheDocument();
239
+ });
240
+
241
+ it("shows source_group_name when grant has only origin group", () => {
242
+ const column = userColumn();
243
+ const grant = {
244
+ user: null,
245
+ source_group_name: "baz",
246
+ };
247
+ const FieldDecorator = column.fieldDecorator;
248
+ const rendered = render(
249
+ <FieldDecorator {...column.fieldSelector(grant)} />,
250
+ );
251
+ expect(rendered.getByText(/^baz$/i)).toBeInTheDocument();
252
+ });
253
+
254
+ it("sorts the user column by user_or_group.raw", () => {
255
+ const column = _.find({ name: "user" })(defaultGrantsTableColumns);
256
+ expect(column.sort.name).toBe("user_or_group.raw");
257
+ });
258
+ });
259
+
260
+ describe("structure grants user or group column", () => {
261
+ const authentication = { user_name: "baz" };
262
+ const structure = { id: 1, name: "foo" };
263
+
264
+ const userColumn = () =>
265
+ _.find({ name: "user" })(getGrantsColumns({ authentication, structure }));
266
+
267
+ const deletedMessages = {
268
+ en: {
269
+ "deleted.user": "Deleted user",
270
+ "deleted.group": "Deleted group",
271
+ },
272
+ };
273
+
274
+ it("shows user group alias when structure grant is for a group", () => {
275
+ const column = userColumn();
276
+ const grant = {
277
+ user: null,
278
+ user_group: { id: 10, name: "foo", alias: "bar" },
279
+ };
280
+ const FieldDecorator = column.fieldDecorator;
281
+ const rendered = render(
282
+ <FieldDecorator {...column.fieldSelector(grant)} />,
283
+ );
284
+ expect(rendered.getByText(/^bar$/i)).toBeInTheDocument();
285
+ });
286
+
287
+ it("shows Deleted group when structure grant has user_group_id and no user_group", () => {
288
+ const column = userColumn();
289
+ const grant = {
290
+ user: null,
291
+ user_group_id: 10,
292
+ user_group: null,
293
+ };
294
+ const FieldDecorator = column.fieldDecorator;
295
+ const rendered = render(
296
+ <FieldDecorator {...column.fieldSelector(grant)} />,
297
+ { messages: deletedMessages },
298
+ );
299
+ expect(rendered.getByText(/^deleted group$/i)).toBeInTheDocument();
300
+ });
301
+
302
+ it("shows user full name when structure grant is for a user", () => {
303
+ const column = userColumn();
304
+ const grant = {
305
+ user: {
306
+ full_name: "foo user",
307
+ email: "foo@ext",
308
+ user_name: "foo",
309
+ },
310
+ };
311
+ const FieldDecorator = column.fieldDecorator;
312
+ const rendered = render(
313
+ <FieldDecorator {...column.fieldSelector(grant)} />,
314
+ { messages: deletedMessages },
315
+ );
316
+ expect(rendered.getByText(/foo user/i)).toBeInTheDocument();
317
+ });
318
+ });
319
+
320
+ describe("my grants user or group column", () => {
321
+ const authentication = { user_name: "baz" };
322
+
323
+ it("includes the user column when onlyMyGrants is true", () => {
324
+ const columns = getGrantsTableColumns({
325
+ authentication,
326
+ onlyMyGrants: true,
327
+ });
328
+ expect(_.map("name")(columns)).toContain("user");
329
+ });
330
+
331
+ it("shows user group alias when my grants hit is for a group", () => {
332
+ const column = _.find({ name: "user" })(
333
+ getGrantsTableColumns({ authentication, onlyMyGrants: true }),
334
+ );
335
+ const grant = {
336
+ user: null,
337
+ user_group: { id: 10, name: "foo", alias: "bar" },
338
+ };
339
+ const FieldDecorator = column.fieldDecorator;
340
+ const rendered = render(
341
+ <FieldDecorator {...column.fieldSelector(grant)} />,
342
+ );
343
+ expect(rendered.getByText(/^bar$/i)).toBeInTheDocument();
344
+ });
345
+
346
+ it("does not show same_user label for a group grant in my grants", () => {
347
+ const column = _.find({ name: "user" })(
348
+ getGrantsTableColumns({ authentication, onlyMyGrants: true }),
349
+ );
350
+ const grant = {
351
+ user: null,
352
+ user_group: { id: 10, name: "foo", alias: "bar" },
353
+ };
354
+ const FieldDecorator = column.fieldDecorator;
355
+ const rendered = render(
356
+ <FieldDecorator {...column.fieldSelector(grant)} />,
357
+ {
358
+ messages: {
359
+ en: {
360
+ "grant.cell.end_date.same_user": "Same",
361
+ },
362
+ },
363
+ },
364
+ );
365
+ expect(rendered.getByText(/^bar$/i)).toBeInTheDocument();
366
+ expect(rendered.queryByText(/^same$/i)).not.toBeInTheDocument();
367
+ });
368
+ });
369
+
370
+ describe("structure grants group member label", () => {
371
+ const authentication = { user_name: "baz" };
372
+ const structure = { id: 1, name: "foo" };
373
+
374
+ const messages = {
375
+ en: {
376
+ "grant.cell.group_member": "Group member",
377
+ "grant.cell.end_date.same_user": "Same",
378
+ },
379
+ };
380
+
381
+ const userColumn = () =>
382
+ _.find({ name: "user" })(getGrantsColumns({ authentication, structure }));
383
+
384
+ const groupGrant = {
385
+ user: null,
386
+ user_group: { id: 10, name: "foo", alias: "bar" },
387
+ user_group_id: 10,
388
+ };
389
+
390
+ it("shows group member label when the logged user belongs to the grant group", () => {
391
+ const column = userColumn();
392
+ const grant = { ...groupGrant, current_user_group_member: true };
393
+ const FieldDecorator = column.fieldDecorator;
394
+ const rendered = render(
395
+ <FieldDecorator {...column.fieldSelector(grant)} />,
396
+ { messages },
397
+ );
398
+ expect(rendered.getByText(/^bar$/i)).toBeInTheDocument();
399
+ expect(rendered.getByText(/^group member$/i)).toBeInTheDocument();
400
+ });
401
+
402
+ it("does not show group member label when the logged user does not belong to the grant group", () => {
403
+ const column = userColumn();
404
+ const grant = { ...groupGrant, current_user_group_member: false };
405
+ const FieldDecorator = column.fieldDecorator;
406
+ const rendered = render(
407
+ <FieldDecorator {...column.fieldSelector(grant)} />,
408
+ { messages },
409
+ );
410
+ expect(rendered.getByText(/^bar$/i)).toBeInTheDocument();
411
+ expect(rendered.queryByText(/^group member$/i)).not.toBeInTheDocument();
412
+ });
413
+
414
+ it("shows same user label for a personal grant and not the group member label", () => {
415
+ const column = userColumn();
416
+ const grant = {
417
+ user: {
418
+ full_name: "foo user",
419
+ email: "foo@ext",
420
+ user_name: "baz",
421
+ },
422
+ };
423
+ const FieldDecorator = column.fieldDecorator;
424
+ const rendered = render(
425
+ <FieldDecorator {...column.fieldSelector(grant)} />,
426
+ { messages },
427
+ );
428
+ expect(rendered.getByText(/foo user/i)).toBeInTheDocument();
429
+ expect(rendered.getByText(/^same$/i)).toBeInTheDocument();
430
+ expect(rendered.queryByText(/^group member$/i)).not.toBeInTheDocument();
431
+ });
432
+
433
+ it("does not show group member label in my grants", () => {
434
+ const column = _.find({ name: "user" })(
435
+ getGrantsTableColumns({ authentication, onlyMyGrants: true }),
436
+ );
437
+ const grant = { ...groupGrant, current_user_group_member: true };
438
+ const FieldDecorator = column.fieldDecorator;
439
+ const rendered = render(
440
+ <FieldDecorator {...column.fieldSelector(grant)} />,
441
+ { messages },
442
+ );
443
+ expect(rendered.getByText(/^bar$/i)).toBeInTheDocument();
444
+ expect(rendered.queryByText(/^group member$/i)).not.toBeInTheDocument();
445
+ });
446
+ });
@@ -1,6 +1,5 @@
1
1
  import _ from "lodash/fp";
2
2
  import { Link } from "react-router";
3
- import { createSelector } from "reselect";
4
3
  import { FormattedMessage } from "react-intl";
5
4
  import Moment from "react-moment";
6
5
  import { Icon, Label } from "semantic-ui-react";
@@ -73,7 +72,6 @@ export const defaultBusinessConceptsLinksToStructuresColumns = [
73
72
  },
74
73
  ];
75
74
 
76
- export const getBusinessConceptsLinksToStructuresColumns = createSelector(
77
- _.prop("businessConceptsLinksToStructuresColumns"),
78
- _.defaultTo(defaultBusinessConceptsLinksToStructuresColumns),
79
- );
75
+ export const getBusinessConceptsLinksToStructuresColumns = (state) =>
76
+ state.businessConceptsLinksToStructuresColumns ??
77
+ defaultBusinessConceptsLinksToStructuresColumns;
@@ -27,7 +27,7 @@ export const UserDecorator = ({ user, user_group, user_id, user_group_id }) => {
27
27
  return (
28
28
  <Header as="h4">
29
29
  <Header.Content>
30
- {formatMessage({ id: "grantRequest.deleted.group" })}
30
+ {formatMessage({ id: "deleted.group" })}
31
31
  </Header.Content>
32
32
  </Header>
33
33
  );
@@ -44,9 +44,7 @@ export const UserDecorator = ({ user, user_group, user_id, user_group_id }) => {
44
44
  if (user_id || user) {
45
45
  return (
46
46
  <Header as="h4">
47
- <Header.Content>
48
- {formatMessage({ id: "grantRequest.deleted.user" })}
49
- </Header.Content>
47
+ <Header.Content>{formatMessage({ id: "deleted.user" })}</Header.Content>
50
48
  </Header>
51
49
  );
52
50
  }
@@ -139,7 +137,7 @@ StatusDecorator.propTypes = {
139
137
  export const defaultGrantRequestsSearchTableColumns = [
140
138
  {
141
139
  name: "user",
142
- sort: { name: "user.user_name" },
140
+ sort: { name: "user_or_group.raw" },
143
141
  fieldSelector: (grantRequest) => ({
144
142
  user: grantRequest?.user,
145
143
  user_group: grantRequest?.user_group,
@@ -7,11 +7,58 @@ import { useIntl } from "react-intl";
7
7
  import Moment from "react-moment";
8
8
  import PropTypes from "prop-types";
9
9
 
10
- export const GrantUserDecorator = ({ authentication, user }) => {
10
+ export const GrantUserDecorator = ({
11
+ authentication,
12
+ user,
13
+ user_group,
14
+ user_id,
15
+ user_group_id,
16
+ source_group_name,
17
+ current_user_group_member,
18
+ }) => {
11
19
  const { formatMessage } = useIntl();
12
- const sameUser = user?.user_name === authentication?.user_name;
13
- return (
14
- user && (
20
+ const userGroupText = user_group
21
+ ? _.isEmpty(user_group.alias)
22
+ ? user_group.name
23
+ : user_group.alias
24
+ : undefined;
25
+
26
+ if (userGroupText) {
27
+ return (
28
+ <Header as="h4">
29
+ <Header.Content>
30
+ {userGroupText}{" "}
31
+ {current_user_group_member && (
32
+ <Label color="teal" size="small">
33
+ {formatMessage({ id: "grant.cell.group_member" })}
34
+ </Label>
35
+ )}
36
+ </Header.Content>
37
+ </Header>
38
+ );
39
+ }
40
+
41
+ if (user_group_id) {
42
+ return (
43
+ <Header as="h4">
44
+ <Header.Content>
45
+ {formatMessage({ id: "deleted.group" })}
46
+ </Header.Content>
47
+ </Header>
48
+ );
49
+ }
50
+
51
+ if (source_group_name) {
52
+ return (
53
+ <Header as="h4">
54
+ <Header.Content>{source_group_name}</Header.Content>
55
+ </Header>
56
+ );
57
+ }
58
+
59
+ if (!_.isEmpty(user?.full_name)) {
60
+ const sameUser = user?.user_name === authentication?.user_name;
61
+ return (
15
62
  <Header as="h4">
16
63
  <Header.Content>
17
64
  {user.full_name}{" "}
@@ -23,13 +70,28 @@ export const GrantUserDecorator = ({ authentication, user }) => {
23
70
  <Header.Subheader>{user.email}</Header.Subheader>
24
71
  </Header.Content>
25
72
  </Header>
26
- )
27
- );
73
+ );
74
+ }
75
+
76
+ if (user_id || user) {
77
+ return (
78
+ <Header as="h4">
79
+ <Header.Content>{formatMessage({ id: "deleted.user" })}</Header.Content>
80
+ </Header>
81
+ );
82
+ }
83
+
84
+ return null;
28
85
  };
29
86
 
30
87
  GrantUserDecorator.propTypes = {
31
88
  authentication: PropTypes.object,
32
89
  user: PropTypes.object,
90
+ user_group: PropTypes.object,
91
+ user_id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
92
+ user_group_id: PropTypes.oneOfType([PropTypes.number, PropTypes.string]),
93
+ source_group_name: PropTypes.string,
94
+ current_user_group_member: PropTypes.bool,
33
95
  };
34
96
 
35
97
  export const userDecorator = (authentication) => (props) =>
@@ -160,7 +222,14 @@ EndDateDecorator.propTypes = {
160
222
  export const defaultGrantsColumns = [
161
223
  {
162
224
  name: "user",
163
- fieldSelector: _.pick(["user"]),
225
+ fieldSelector: _.pick([
226
+ "user",
227
+ "user_group",
228
+ "user_id",
229
+ "user_group_id",
230
+ "source_group_name",
231
+ "current_user_group_member",
232
+ ]),
164
233
  fieldDecorator: userDecorator,
165
234
  },
166
235
  {
@@ -198,8 +267,14 @@ export const getGrantsColumns = createSelector(
198
267
  export const defaultGrantsTableColumns = [
199
268
  {
200
269
  name: "user",
201
- sort: { name: "user.full_name.raw" },
202
- fieldSelector: _.pick(["user"]),
270
+ sort: { name: "user_or_group.raw" },
271
+ fieldSelector: _.pick([
272
+ "user",
273
+ "user_group",
274
+ "user_id",
275
+ "user_group_id",
276
+ "source_group_name",
277
+ ]),
203
278
  fieldDecorator: userDecorator,
204
279
  },
205
280
  {
@@ -228,10 +303,9 @@ export const getGrantsTableColumns = createSelector(
228
303
  _.prop("authentication"),
229
304
  _.prop("onlyMyGrants"),
230
305
  ],
231
- (grantsColumns, authentication, onlyMyGrants) => {
306
+ (grantsColumns, authentication) => {
232
307
  return _.flow(
233
308
  _.defaultTo(defaultGrantsTableColumns),
234
- _.reject((c) => (onlyMyGrants ? c.name === "user" : false)),
235
309
  _.map((c) => {
236
310
  return c.name === "user"
237
311
  ? { ...c, fieldDecorator: c.fieldDecorator(authentication) }
@@ -1,5 +1,4 @@
1
1
  import _ from "lodash/fp";
2
- import { createSelector } from "reselect";
3
2
  import { FormattedMessage } from "react-intl";
4
3
  import DateTime from "@truedat/core/components/DateTime";
5
4
  import { formatNumber } from "@truedat/core/services/format";
@@ -86,9 +85,6 @@ export const defaultImplementationToStructuresColumns = [
86
85
  },
87
86
  ];
88
87
 
89
- const getColumns = (state) => state.ruleImplementationToStructuresColumns;
90
-
91
- export const getLinkedImplementationsToStructuresColumns = createSelector(
92
- [getColumns],
93
- _.defaultTo(defaultImplementationToStructuresColumns),
94
- );
88
+ export const getLinkedImplementationsToStructuresColumns = (state) =>
89
+ state.ruleImplementationToStructuresColumns ??
90
+ defaultImplementationToStructuresColumns;
@@ -1,7 +1,6 @@
1
1
  import _ from "lodash/fp";
2
2
  import { Icon, List } from "semantic-ui-react";
3
3
  import { FormattedMessage } from "react-intl";
4
- import { createSelector } from "reselect";
5
4
  import { Link } from "react-router";
6
5
  import { linkTo } from "@truedat/core/routes";
7
6
  import { accentInsensitivePathOrder } from "@truedat/core/services/sort";
@@ -49,7 +48,11 @@ const lineageLinkDecorator = ({ degree, data_structure_id: id }) =>
49
48
  ) : null;
50
49
 
51
50
  export const linksDecorator = (links) => {
52
- const sortedLinks = _.sortBy(accentInsensitivePathOrder("name"))(links);
51
+ const sortedLinks = _.flow(
52
+ _.defaultTo([]),
53
+ _.filter((resource) => resource?.resource_id && resource?.name),
54
+ _.sortBy(accentInsensitivePathOrder("name")),
55
+ )(links);
53
56
  return _.isEmpty(sortedLinks) ? null : (
54
57
  <List>
55
58
  {sortedLinks.map((resource, i) => (
@@ -95,7 +98,5 @@ export const defaultStructureFieldColumns = [
95
98
  },
96
99
  ];
97
100
 
98
- export const getStructureFieldColumns = createSelector(
99
- _.prop("structureFieldsColumns"),
100
- _.defaultTo(defaultStructureFieldColumns),
101
- );
101
+ export const getStructureFieldColumns = (state) =>
102
+ state.structureFieldsColumns ?? defaultStructureFieldColumns;
@@ -1,6 +1,5 @@
1
1
  import _ from "lodash/fp";
2
2
  import { useState } from "react";
3
- import { createSelector } from "reselect";
4
3
  import { FormattedMessage, useIntl } from "react-intl";
5
4
  import { Button, Label, Popup } from "semantic-ui-react";
6
5
  import { useDomainPath } from "@truedat/bg/taxonomy/components/DomainPath";
@@ -81,7 +80,5 @@ export const defaultStructureProperties = [
81
80
  { name: "group", width: 8 },
82
81
  ];
83
82
 
84
- export const getStructureProperties = createSelector(
85
- _.prop("structureProperties"),
86
- _.defaultTo(defaultStructureProperties),
87
- );
83
+ export const getStructureProperties = (state) =>
84
+ state.structureProperties ?? defaultStructureProperties;
@@ -1,5 +1,4 @@
1
1
  import _ from "lodash/fp";
2
- import { createSelector } from "reselect";
3
2
  import { FormattedMessage } from "react-intl";
4
3
  import Moment from "react-moment";
5
4
  import { AlertExporter } from "@truedat/core/components/AlertExporter";
@@ -65,9 +64,5 @@ export const defaultStructuresUploadEventColumns = [
65
64
  },
66
65
  ];
67
66
 
68
- const getColumns = (state) => state.structuresUploadEventColumns;
69
-
70
- export const getStructuresUploadEventColumns = createSelector(
71
- [getColumns],
72
- (columns) => _.defaultTo(defaultStructuresUploadEventColumns)(columns),
73
- );
67
+ export const getStructuresUploadEventColumns = (state) =>
68
+ state.structuresUploadEventColumns ?? defaultStructuresUploadEventColumns;
@@ -64,23 +64,20 @@ export const defaultStructureColumns = [
64
64
  },
65
65
  ];
66
66
 
67
- // If default filters include "system.name.raw", exclude the "system" column
68
- const filterExcludes = { "system.name.raw": "system" };
69
-
70
- const columnsToExclude = (defaultFilters) =>
71
- _.flow(_.pick(_.keys(defaultFilters)), _.values)(filterExcludes);
67
+ const filteredStructureColumns = createSelector(
68
+ (state) => state.structuresColumns ?? defaultStructureColumns,
69
+ _.reject(({ name }) => name === "system"),
70
+ );
72
71
 
73
- export const structureColumnsSelector = (state, defaultFilters, ownColumns) =>
74
- createSelector(_.prop("structuresColumns"), (columns) => {
75
- const excludes = columnsToExclude(defaultFilters);
76
- const res = ownColumns
77
- ? ownColumns
78
- : _.flow(
79
- _.defaultTo(defaultStructureColumns),
80
- _.reject(({ name }) => _.includes(name)(excludes)),
81
- )(columns);
82
- return res;
83
- })(state);
72
+ export const structureColumnsSelector = (state, defaultFilters, ownColumns) => {
73
+ if (ownColumns) return ownColumns;
74
+ return Object.prototype.hasOwnProperty.call(
75
+ defaultFilters || {},
76
+ "system.name.raw",
77
+ )
78
+ ? filteredStructureColumns(state)
79
+ : (state.structuresColumns ?? defaultStructureColumns);
80
+ };
84
81
 
85
82
  const rawName = {
86
83
  name: "name",