@truedat/dd 5.3.0 → 5.3.1

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.
@@ -1,22 +1,27 @@
1
1
  import React from "react";
2
2
  import { render } from "@truedat/test/render";
3
3
  import { waitFor } from "@testing-library/react";
4
- import { useParams } from "react-router-dom";
4
+ import userEvent from "@testing-library/user-event";
5
5
  import { STRUCTURE_STRUCTURE_LINKS_QUERY } from "../../api/queries";
6
+ import { deleteStructureStructureLink } from "../../routines";
6
7
  import StructureStructureLinks from "../StructureStructureLinks";
7
8
 
8
9
  jest.mock("react-router-dom", () => ({
9
10
  ...jest.requireActual("react-router-dom"),
10
- useParams: jest.fn(),
11
+ useParams: () => ({ id: 60217 }),
11
12
  }));
12
13
 
13
14
  const dataStructureWithLinks = {
14
15
  currentVersion: {
15
16
  id: "212416",
16
- name: "CMESANO",
17
+ name: "STRUCTURE_1",
17
18
  },
18
19
  dataStructureLinks: [
19
20
  {
21
+ _actions: {
22
+ delete_struct_to_struct_link: true,
23
+ },
24
+ id: "1",
20
25
  labels: [
21
26
  {
22
27
  name: "copy",
@@ -24,54 +29,58 @@ const dataStructureWithLinks = {
24
29
  ],
25
30
  source: {
26
31
  currentVersion: {
27
- name: "CMESANO",
32
+ name: "STRUCTURE_1",
28
33
  pathWithIds: [
29
34
  {
30
35
  data_structure_id: "114207",
31
- name: "SRV_DS2P.PRO.SANTALUCIA.ES",
36
+ name: "UNO",
32
37
  },
33
38
  {
34
39
  data_structure_id: "58050",
35
- name: "SIISDS2",
40
+ name: "DOS",
36
41
  },
37
42
  {
38
43
  data_structure_id: "58045",
39
- name: "INPAHEM_SINIEPAGO",
44
+ name: "TRES",
40
45
  },
41
46
  ],
42
47
  },
43
48
  id: "60217",
44
49
  system: {
45
50
  id: "2",
46
- name: "Oracle producción solvencia",
51
+ name: "SYSTEM_1",
47
52
  },
48
53
  },
49
54
  target: {
50
55
  currentVersion: {
51
- name: "NIDSINIE",
56
+ name: "STRUCTURE_2",
52
57
  pathWithIds: [
53
58
  {
54
59
  data_structure_id: "114207",
55
- name: "SRV_DS2P.PRO.SANTALUCIA.ES",
60
+ name: "UNO",
56
61
  },
57
62
  {
58
63
  data_structure_id: "58050",
59
- name: "SIISDS2",
64
+ name: "DOS",
60
65
  },
61
66
  {
62
67
  data_structure_id: "58045",
63
- name: "INPAHEM_SINIEPAGO",
68
+ name: "TRES",
64
69
  },
65
70
  ],
66
71
  },
67
72
  id: "60218",
68
73
  system: {
69
74
  id: "2",
70
- name: "Oracle producción solvencia",
75
+ name: "SYSTEM_1",
71
76
  },
72
77
  },
73
78
  },
74
79
  {
80
+ _actions: {
81
+ delete_struct_to_struct_link: true,
82
+ },
83
+ id: "2",
75
84
  labels: [
76
85
  {
77
86
  name: "label_1_1",
@@ -82,46 +91,46 @@ const dataStructureWithLinks = {
82
91
  ],
83
92
  source: {
84
93
  currentVersion: {
85
- name: "ivalindm",
94
+ name: "STRUCTURE_3",
86
95
  pathWithIds: [
87
96
  {
88
97
  data_structure_id: "147587",
89
- name: "bdrs",
98
+ name: "UNO",
90
99
  },
91
100
  {
92
101
  data_structure_id: "151648",
93
- name: "inpahem_siniepago",
102
+ name: "DOS",
94
103
  },
95
104
  ],
96
105
  },
97
106
  id: "151674",
98
107
  system: {
99
108
  id: "11",
100
- name: "Azure Databricks",
109
+ name: "SYSTEM_2",
101
110
  },
102
111
  },
103
112
  target: {
104
113
  currentVersion: {
105
- name: "CMESANO",
114
+ name: "STRUCTURE_1",
106
115
  pathWithIds: [
107
116
  {
108
117
  data_structure_id: "114207",
109
- name: "SRV_DS2P.PRO.SANTALUCIA.ES",
118
+ name: "UNO",
110
119
  },
111
120
  {
112
121
  data_structure_id: "58050",
113
- name: "SIISDS2",
122
+ name: "DOS",
114
123
  },
115
124
  {
116
125
  data_structure_id: "58045",
117
- name: "INPAHEM_SINIEPAGO",
126
+ name: "TRES",
118
127
  },
119
128
  ],
120
129
  },
121
130
  id: "60217",
122
131
  system: {
123
132
  id: "2",
124
- name: "Oracle producción solvencia",
133
+ name: "SYSTEM_1",
125
134
  },
126
135
  },
127
136
  },
@@ -138,24 +147,89 @@ const linksMock = {
138
147
  };
139
148
 
140
149
  describe("<StructureStructureLinks />", () => {
141
- const props = { dataStructureWithLinks };
150
+ const props = {
151
+ dataStructureWithLinks,
152
+ };
153
+
154
+ const structureActions = {
155
+ create_struct_to_struct_link: {
156
+ href: "/some/url",
157
+ method: "POST",
158
+ },
159
+ };
160
+
161
+ const renderOpts = {
162
+ routes: ["/structures/60217/structureLinks"],
163
+ mocks: [linksMock],
164
+ };
165
+
166
+ it("shows structure to structure links", async () => {
167
+ const { getByRole } = render(<StructureStructureLinks {...props} />, {
168
+ ...renderOpts,
169
+ state: { structureActions },
170
+ });
171
+ await waitFor(() => {
172
+ expect(getByRole("link", { name: /STRUCTURE_2/i })).toBeInTheDocument();
173
+ expect(getByRole("link", { name: /STRUCTURE_3/i })).toBeInTheDocument();
174
+ });
175
+ await waitFor(() => {
176
+ expect(getByRole("button", { name: /Add link/i })).toBeInTheDocument();
177
+ });
178
+ expect(
179
+ document.getElementById("delete-link-60217-60218")
180
+ ).toBeInTheDocument();
181
+ expect(
182
+ document.getElementById("delete-link-151674-60217")
183
+ ).toBeInTheDocument();
184
+ });
142
185
 
143
- it("matches the latest snapshot", async () => {
144
- const renderOpts = {
145
- routes: ["/structures/60217/structureLinks"],
146
- mocks: [linksMock],
147
- };
148
- useParams.mockImplementation(() => ({
149
- id: 60217,
150
- }));
151
- const { container, findByText, getByRole, queryByText, debug } = render(
186
+ it("hides the 'add link' and delete link buttons if there are no permissions", async () => {
187
+ const { getByRole, queryByRole } = render(
152
188
  <StructureStructureLinks {...props} />,
153
189
  renderOpts
154
190
  );
155
191
  await waitFor(() => {
156
- expect(getByRole("link", { name: /NIDSINIE/i })).toBeInTheDocument();
157
- expect(getByRole("link", { name: /ivalindm/i })).toBeInTheDocument();
192
+ expect(getByRole("link", { name: /STRUCTURE_2/i })).toBeInTheDocument();
193
+ expect(getByRole("link", { name: /STRUCTURE_3/i })).toBeInTheDocument();
194
+ });
195
+ expect(
196
+ queryByRole("button", { name: /Add link/i })
197
+ ).not.toBeInTheDocument();
198
+ expect(document.getElementById("delete-link-60217-60218")).toBeNull();
199
+ expect(document.getElementById("delete-link-151674-60217")).toBeNull();
200
+ });
201
+
202
+ it("deletes link", async () => {
203
+ const dispatch = jest.fn();
204
+ const { getByText, getByRole } = render(
205
+ <StructureStructureLinks {...props} />,
206
+ {
207
+ ...renderOpts,
208
+ state: { structureActions },
209
+ dispatch,
210
+ }
211
+ );
212
+ await waitFor(() => {
213
+ expect(getByRole("link", { name: /STRUCTURE_2/i })).toBeInTheDocument();
214
+ expect(getByRole("link", { name: /STRUCTURE_3/i })).toBeInTheDocument();
215
+ });
216
+ await waitFor(() => {
217
+ expect(getByRole("button", { name: /Add link/i })).toBeInTheDocument();
218
+ });
219
+
220
+ const deleteButton = document.getElementById("delete-link-60217-60218");
221
+ userEvent.click(deleteButton);
222
+ expect(getByText("Delete link")).toBeInTheDocument();
223
+ const yesButton = getByRole("button", { name: /Yes/i });
224
+ userEvent.click(yesButton);
225
+
226
+ expect(dispatch).toHaveBeenCalledWith({
227
+ ...deleteStructureStructureLink(),
228
+ payload: {
229
+ dataStructureLinkId: "1",
230
+ sourceStructureId: "60217",
231
+ targetStructureId: "60218",
232
+ },
158
233
  });
159
- expect(container).toMatchSnapshot();
160
234
  });
161
235
  });
@@ -424,6 +424,8 @@ export default {
424
424
  "structureLink.currentStructure": "Current structure",
425
425
  "structureLink.label": "Relation label",
426
426
  "structureLink.relatedStructure": "Related structure",
427
+ "structureLink.selector.label": "Relation label",
428
+ "structureLink.selector.placeholder": "Select a relation label...",
427
429
  "structureSelector.union.criteria": "Union criteria",
428
430
  "structureSelector.union.type": "Union type",
429
431
  "structureTag.comment": "Comments",
@@ -433,6 +433,9 @@ export default {
433
433
  "structureLink.currentStructure": "Estructura actual",
434
434
  "structureLink.label": "Etiqueta de relación",
435
435
  "structureLink.relatedStructure": "Estructura relacionada",
436
+ "structureLink.selector.label": "Etiqueta de relación",
437
+ "structureLink.selector.placeholder":
438
+ "Seleccione una etiqueta de relación...",
436
439
  "structureSelector.union.criteria": "Criterio de unión",
437
440
  "structureSelector.union.type": "Tipo de unión",
438
441
  "structureTag.comment": "Comentario",
@@ -8,6 +8,7 @@ import {
8
8
  STRUCTURE_TAGS,
9
9
  STRUCTURE_TYPES,
10
10
  STRUCTURES,
11
+ STRUCTURE_STRUCTURE_LINKS,
11
12
  linkTo,
12
13
  } from "@truedat/core/routes";
13
14
  import {
@@ -24,6 +25,7 @@ import {
24
25
  deleteStructure,
25
26
  deleteTag,
26
27
  doStructureNoteAction,
28
+ linkStructureToStructure,
27
29
  updateGrantApprovalRule,
28
30
  updateReferenceDataset,
29
31
  updateStructure,
@@ -50,6 +52,10 @@ export const structureRedirect = (
50
52
  const id = _.path("data.id")(payload);
51
53
  return linkTo.SYSTEM_STRUCTURES({ id });
52
54
  }
55
+ case linkStructureToStructure.SUCCESS:
56
+ return linkTo.STRUCTURE_STRUCTURE_LINKS({
57
+ id: payload.sourceStructureId,
58
+ });
53
59
  case updateSystem.SUCCESS: {
54
60
  const id = _.path("data.id")(payload);
55
61
  return linkTo.SYSTEM_STRUCTURES({ id });
package/src/routines.js CHANGED
@@ -51,6 +51,7 @@ export const deleteGrantApprovalRule = createRoutine("DELETE_GRANT_APPROVAL_RULE
51
51
  export const deleteReferenceDataset = createRoutine("DELETE_REFERENCE_DATASET");
52
52
  export const deleteStructureTag = createRoutine("DELETE_STRUCTURE_TAG");
53
53
  export const deleteStructure = createRoutine("DELETE_STRUCTURE");
54
+ export const deleteStructureStructureLink = createRoutine("DELETE_STRUCTURE_STRUCTURE_LINK");
54
55
  export const deleteTag = createRoutine("DELETE_TAG");
55
56
  export const deleteUserSearchFilter = createRoutine("DELETE_USER_SEARCH_FILTER");
56
57
  export const doStructureNoteAction = createRoutine("DO_STRUCTURE_NOTE_ACTION");
@@ -86,7 +87,7 @@ export const fetchUserSearchFilters = createRoutine("FETCH_USER_SEARCH_FILTERS")
86
87
  export const filterStructures = createRoutine("FILTER_STRUCTURES");
87
88
  export const hoverNode = createRoutine("HOVER_NODE");
88
89
  export const initSvg = createRoutine("INIT_SVG");
89
- export const tagStructure = createRoutine("TAG_STRUCTURE");
90
+ export const linkStructureToStructure = createRoutine("LINK_STRUCTURE_TO_STRUCTURE");
90
91
  export const loadLineageEvents = createRoutine("LOAD_LINEAGE_EVENTS");
91
92
  export const openGrantFilter = createRoutine("OPEN_GRANT_FILTER");
92
93
  export const openStructureFilter = createRoutine("OPEN_STRUCTURE_FILTER");
@@ -113,6 +114,7 @@ export const setGrantChangeRequestCart = createRoutine("SET_GRANT_CHANGE_REQUEST
113
114
  export const setGrantRequestsQuery = createRoutine("SET_GRANT_REQUESTS_QUERY");
114
115
  export const sortGrants = createRoutine("SORT_GRANTS");
115
116
  export const sortStructures = createRoutine("SORT_STRUCTURES");
117
+ export const tagStructure = createRoutine("TAG_STRUCTURE");
116
118
  export const toggleGrantDateFilter = createRoutine("TOGGLE_GRANT_DATE_FILTER");
117
119
  export const toggleGrantFilterValue = createRoutine("TOGGLE_GRANT_FILTER_VALUE");
118
120
  export const toggleStructureDateFilter = createRoutine("TOGGLE_STRUCTURE_DATE_FILTER");
@@ -0,0 +1,101 @@
1
+ import _ from "lodash/fp";
2
+ import { compile } from "path-to-regexp";
3
+ import { testSaga } from "redux-saga-test-plan";
4
+ import { apiJsonDelete, JSON_OPTS } from "@truedat/core/services/api";
5
+ import {
6
+ deleteStructureStructureLinkSaga,
7
+ deleteStructureStructureLinkRequestSaga,
8
+ } from "../deleteStructureStructureLink";
9
+ import { deleteStructureStructureLink } from "../../routines";
10
+ import { API_STRUCTURE_TO_STRUCTURE_LINK } from "../../api";
11
+
12
+ describe("sagas: deleteStructureStructureRequestSaga", () => {
13
+ it("should invoke deleteStructureStructureSaga on deleteStructureStructureLink.TRIGGER", () => {
14
+ expect(() => {
15
+ testSaga(deleteStructureStructureLinkRequestSaga)
16
+ .next()
17
+ .takeLatest(
18
+ deleteStructureStructureLink.TRIGGER,
19
+ deleteStructureStructureLinkSaga
20
+ )
21
+ .finish()
22
+ .isDone();
23
+ }).not.toThrow();
24
+ });
25
+
26
+ it("should throw exception if an unhandled action is received", () => {
27
+ expect(() => {
28
+ testSaga(deleteStructureStructureLinkRequestSaga)
29
+ .next()
30
+ .takeLatest("FOO", deleteStructureStructureLinkSaga);
31
+ }).toThrow();
32
+ });
33
+ });
34
+
35
+ describe("sagas: deleteStructureStructureLinkSaga", () => {
36
+ const sourceStructureId = 1;
37
+ const targetStructureId = 2;
38
+ const dataStructureLinkId = 1;
39
+ const receivedPayload = {
40
+ sourceStructureId,
41
+ targetStructureId,
42
+ dataStructureLinkId,
43
+ };
44
+
45
+ const deletePayload = {
46
+ sourceStructureId,
47
+ targetStructureId,
48
+ };
49
+
50
+ const url = compile(API_STRUCTURE_TO_STRUCTURE_LINK)({
51
+ sourceStructureId,
52
+ targetStructureId,
53
+ });
54
+
55
+ const client = {
56
+ cache: {
57
+ identify: jest.fn(),
58
+ evict: jest.fn(),
59
+ gc: jest.fn(),
60
+ },
61
+ };
62
+
63
+ it("should put a success action when a response is returned", () => {
64
+ expect(() => {
65
+ testSaga(deleteStructureStructureLinkSaga, { payload: receivedPayload })
66
+ .next()
67
+ .getContext("client")
68
+ .next(client)
69
+ .put(deleteStructureStructureLink.request(deletePayload))
70
+ .next(client)
71
+ .call(apiJsonDelete, url, JSON_OPTS)
72
+ .next({ data: deletePayload })
73
+ .put(deleteStructureStructureLink.success(deletePayload))
74
+ .next()
75
+ .put(deleteStructureStructureLink.fulfill())
76
+ .next()
77
+ .isDone();
78
+ }).not.toThrow();
79
+ });
80
+
81
+ it("should put a failure action when a call returns an error", () => {
82
+ const message = "Request failed";
83
+ const error = { message };
84
+
85
+ expect(() => {
86
+ testSaga(deleteStructureStructureLinkSaga, { payload: receivedPayload })
87
+ .next()
88
+ .getContext("client")
89
+ .next(client)
90
+ .put(deleteStructureStructureLink.request(deletePayload))
91
+ .next(client)
92
+ .call(apiJsonDelete, url, JSON_OPTS)
93
+ .throw(error)
94
+ .put(deleteStructureStructureLink.failure(message))
95
+ .next()
96
+ .put(deleteStructureStructureLink.fulfill())
97
+ .next()
98
+ .isDone();
99
+ }).not.toThrow();
100
+ });
101
+ });
@@ -0,0 +1,45 @@
1
+ import { compile } from "path-to-regexp";
2
+ import { call, put, takeLatest, getContext } from "redux-saga/effects";
3
+ import { apiJsonDelete, JSON_OPTS } from "@truedat/core/services/api";
4
+ import { API_STRUCTURE_TO_STRUCTURE_LINK } from "../api";
5
+ import { deleteStructureStructureLink } from "../routines";
6
+
7
+ export const evictDataStructureLink = (cache, dataStructureLinkId) => {
8
+ const cachedDataStructureLink = cache.identify({
9
+ __typename: "DataStructureLink",
10
+ id: dataStructureLinkId,
11
+ });
12
+ cache.evict(cachedDataStructureLink);
13
+ cache.gc();
14
+ };
15
+
16
+ export function* deleteStructureStructureLinkSaga({
17
+ payload: { sourceStructureId, targetStructureId, dataStructureLinkId },
18
+ }) {
19
+ const client = yield getContext("client");
20
+ const cache = client.cache;
21
+ try {
22
+ const payload = { sourceStructureId, targetStructureId };
23
+ const url = compile(API_STRUCTURE_TO_STRUCTURE_LINK)(payload);
24
+ yield put(deleteStructureStructureLink.request(payload));
25
+ yield call(apiJsonDelete, url, JSON_OPTS);
26
+ evictDataStructureLink(cache, dataStructureLinkId);
27
+ yield put(deleteStructureStructureLink.success(payload));
28
+ } catch (error) {
29
+ if (error.response) {
30
+ const { status, data } = error.response;
31
+ yield put(deleteStructureStructureLink.failure({ status, data }));
32
+ } else {
33
+ yield put(deleteStructureStructureLink.failure(error.message));
34
+ }
35
+ } finally {
36
+ yield put(deleteStructureStructureLink.fulfill());
37
+ }
38
+ }
39
+
40
+ export function* deleteStructureStructureLinkRequestSaga() {
41
+ yield takeLatest(
42
+ deleteStructureStructureLink.TRIGGER,
43
+ deleteStructureStructureLinkSaga
44
+ );
45
+ }
@@ -12,6 +12,7 @@ import { deleteGrantApprovalRuleRequestSaga } from "./deleteGrantApprovalRule";
12
12
  import { deleteStructureTagRequestSaga } from "./deleteStructureTag";
13
13
  import { deleteReferenceDatasetRequestSaga } from "./deleteReferenceDataset";
14
14
  import { deleteStructureRequestSaga } from "./deleteStructure";
15
+ import { deleteStructureStructureLinkRequestSaga } from "./deleteStructureStructureLink";
15
16
  import { deleteTagRequestSaga } from "./deleteTag";
16
17
  import { deleteUserSearchFilterRequestSaga } from "./deleteUserSearchFilter";
17
18
  import { doStructureNoteActionRequestSaga } from "./doStructureNoteAction";
@@ -41,6 +42,7 @@ import { fetchSystemRequestSaga } from "./fetchSystem";
41
42
  import { fetchSystemStructuresRequestSaga } from "./fetchSystemStructures";
42
43
  import { fetchSystemsRequestSaga } from "./fetchSystems";
43
44
  import { fetchUserSearchFiltersRequestSaga } from "./fetchUserSearchFilters";
45
+ import { linkStructureToStructureRequestSaga } from "./linkStructureToStructure";
44
46
  import { tagStructureRequestSaga } from "./tagStructure";
45
47
  import { operateGrantRequestToCartRequestSaga } from "./operateGrantRequestCart";
46
48
  import { requestGrantRemovalRequestSaga } from "./requestGrantRemoval";
@@ -69,6 +71,7 @@ export {
69
71
  deleteStructureTagRequestSaga,
70
72
  deleteReferenceDatasetRequestSaga,
71
73
  deleteStructureRequestSaga,
74
+ deleteStructureStructureLinkRequestSaga,
72
75
  deleteTagRequestSaga,
73
76
  deleteUserSearchFilterRequestSaga,
74
77
  doStructureNoteActionRequestSaga,
@@ -98,6 +101,7 @@ export {
98
101
  fetchSystemStructuresRequestSaga,
99
102
  fetchSystemsRequestSaga,
100
103
  fetchUserSearchFiltersRequestSaga,
104
+ linkStructureToStructureRequestSaga,
101
105
  tagStructureRequestSaga,
102
106
  operateGrantRequestToCartRequestSaga,
103
107
  requestGrantRemovalRequestSaga,
@@ -127,6 +131,7 @@ export default [
127
131
  deleteStructureTagRequestSaga(),
128
132
  deleteReferenceDatasetRequestSaga(),
129
133
  deleteStructureRequestSaga(),
134
+ deleteStructureStructureLinkRequestSaga(),
130
135
  deleteTagRequestSaga(),
131
136
  deleteUserSearchFilterRequestSaga(),
132
137
  doStructureNoteActionRequestSaga(),
@@ -156,6 +161,7 @@ export default [
156
161
  fetchSystemStructuresRequestSaga(),
157
162
  fetchSystemsRequestSaga(),
158
163
  fetchUserSearchFiltersRequestSaga(),
164
+ linkStructureToStructureRequestSaga(),
159
165
  tagStructureRequestSaga(),
160
166
  operateGrantRequestToCartRequestSaga(),
161
167
  requestGrantRemovalRequestSaga(),
@@ -0,0 +1,46 @@
1
+ import _ from "lodash/fp";
2
+ import { call, put, takeLatest } from "redux-saga/effects";
3
+ import { apiJsonPost, JSON_OPTS } from "@truedat/core/services/api";
4
+ import { linkStructureToStructure } from "../routines";
5
+ import { API_STRUCTURE_TO_STRUCTURE_LINKS } from "../api";
6
+
7
+ export function* linkStructureToStructureSaga({ payload }) {
8
+ try {
9
+ const {
10
+ sourceStructureId: source_id,
11
+ targetStructureId: target_id,
12
+ labelIds: label_ids,
13
+ } = payload;
14
+
15
+ const payloadSnakeCase = {
16
+ source_id,
17
+ target_id,
18
+ label_ids,
19
+ };
20
+
21
+ yield put(linkStructureToStructure.request(payloadSnakeCase));
22
+ const { data } = yield call(
23
+ apiJsonPost,
24
+ API_STRUCTURE_TO_STRUCTURE_LINKS,
25
+ { data_structure_link: payloadSnakeCase },
26
+ JSON_OPTS
27
+ );
28
+ yield put(linkStructureToStructure.success({ ...data, ...payload }));
29
+ } catch (error) {
30
+ if (error.response) {
31
+ const { status, data } = error.response;
32
+ yield put(linkStructureToStructure.failure({ status, data }));
33
+ } else {
34
+ yield put(linkStructureToStructure.failure(error.message));
35
+ }
36
+ } finally {
37
+ yield put(linkStructureToStructure.fulfill());
38
+ }
39
+ }
40
+
41
+ export function* linkStructureToStructureRequestSaga() {
42
+ yield takeLatest(
43
+ linkStructureToStructure.TRIGGER,
44
+ linkStructureToStructureSaga
45
+ );
46
+ }
@@ -12,7 +12,7 @@ describe("selectors: getStructuresFields", () => {
12
12
  external_id: null,
13
13
  inserted_at: "2019-10-22T10:37:54Z",
14
14
  links: [],
15
- name: "CMESANO",
15
+ name: "STRUCTURE_1",
16
16
  nullable: true,
17
17
  precision: "8.0",
18
18
  type: "num",
@@ -73,7 +73,7 @@ describe("selectors: getStructuresFields", () => {
73
73
  external_id: null,
74
74
  inserted_at: "2019-10-22T10:37:54Z",
75
75
  links: [],
76
- name: "CMESANO",
76
+ name: "STRUCTURE_1",
77
77
  nullable: true,
78
78
  precision: "8.0",
79
79
  type: "num",
@@ -8,7 +8,7 @@ import {
8
8
  STRUCTURE_NOTES_EDIT,
9
9
  STRUCTURE_PARENTS,
10
10
  STRUCTURE_PROFILE,
11
- STRUCTURE_LINKED_STRUCTURES,
11
+ STRUCTURE_STRUCTURE_LINKS,
12
12
  STRUCTURE_RULES,
13
13
  STRUCTURE_LINKS,
14
14
  STRUCTURE_LINKS_NEW,
@@ -44,7 +44,7 @@ export const getActiveTab = (tabVisibility, path) => {
44
44
  [_.eq(STRUCTURE_METADATA), _.constant("metadata")],
45
45
  [_.eq(STRUCTURE_PARENTS), _.constant("parents")],
46
46
  [_.eq(STRUCTURE_PROFILE), _.constant("profile")],
47
- [_.eq(STRUCTURE_LINKED_STRUCTURES), _.constant("structureLinks")],
47
+ [_.eq(STRUCTURE_STRUCTURE_LINKS), _.constant("structureLinks")],
48
48
  [_.eq(STRUCTURE_RULES), _.constant("rules")],
49
49
  [_.eq(STRUCTURE_LINKS), _.constant("links")],
50
50
  [_.eq(STRUCTURE_LINKS_NEW), _.constant("links")],
@@ -37,6 +37,7 @@ const notesTabVisible = ({ templatesLoading, templates, structure }) =>
37
37
 
38
38
  const versionsTabVisible = notEmptyPath("structureVersions");
39
39
  const structureLinksTabVisible = (state) =>
40
+ _.has("manage_structure_to_structure_link", state?.structureActions) ||
40
41
  state?.structure?.data_structure_link_count > 0;
41
42
  const rulesTabVisible = (state) => state?.structure?.implementation_count > 0;
42
43
  const lineageTabVisible = _.anyPass([_.path("structure.degree.in")]);