@truedat/dd 7.14.0 → 7.14.2
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/StructureTabPane.js +0 -1
- package/src/components/StructureTabs.js +2 -2
- package/src/components/StructuresRoutes.js +1 -8
- package/src/components/__tests__/StructureTabs.spec.js +54 -0
- package/src/components/__tests__/__snapshots__/StructureTabs.spec.js.snap +82 -0
- package/src/selectors/__tests__/getActiveTab.spec.js +144 -0
- package/src/selectors/getActiveTab.js +28 -6
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@truedat/dd",
|
|
3
|
-
"version": "7.14.
|
|
3
|
+
"version": "7.14.2",
|
|
4
4
|
"description": "Truedat Web Data Dictionary",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"module": "src/index.js",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@testing-library/jest-dom": "^6.6.3",
|
|
49
49
|
"@testing-library/react": "^16.3.0",
|
|
50
50
|
"@testing-library/user-event": "^14.6.1",
|
|
51
|
-
"@truedat/test": "7.14.
|
|
51
|
+
"@truedat/test": "7.14.2",
|
|
52
52
|
"identity-obj-proxy": "^3.0.0",
|
|
53
53
|
"jest": "^29.7.0",
|
|
54
54
|
"redux-saga-test-plan": "^4.0.6"
|
|
@@ -83,5 +83,5 @@
|
|
|
83
83
|
"svg-pan-zoom": "^3.6.2",
|
|
84
84
|
"swr": "^2.3.3"
|
|
85
85
|
},
|
|
86
|
-
"gitHead": "
|
|
86
|
+
"gitHead": "819dbd2c48ef3339194608f79a58d502fe6c01a6"
|
|
87
87
|
}
|
|
@@ -184,7 +184,7 @@ export const StructureTabs = ({ path }) => {
|
|
|
184
184
|
])
|
|
185
185
|
: null;
|
|
186
186
|
|
|
187
|
-
structureTabsOrder
|
|
187
|
+
const sortedItems = items && structureTabsOrder
|
|
188
188
|
? items.sort((a, b) => {
|
|
189
189
|
const aIndex = _.indexOf(a.key)(structureTabsOrder);
|
|
190
190
|
const bIndex = _.indexOf(b.key)(structureTabsOrder);
|
|
@@ -208,7 +208,7 @@ export const StructureTabs = ({ path }) => {
|
|
|
208
208
|
secondary
|
|
209
209
|
pointing
|
|
210
210
|
tabular
|
|
211
|
-
items={
|
|
211
|
+
items={sortedItems}
|
|
212
212
|
className="tab-overflow"
|
|
213
213
|
/>
|
|
214
214
|
<Divider hidden />
|
|
@@ -2,14 +2,7 @@ import _ from "lodash/fp";
|
|
|
2
2
|
import React from "react";
|
|
3
3
|
import { useIntl } from "react-intl";
|
|
4
4
|
import { Routes, Route, useParams } from "react-router";
|
|
5
|
-
|
|
6
|
-
STRUCTURE,
|
|
7
|
-
STRUCTURES,
|
|
8
|
-
STRUCTURES_BULK_UPDATE,
|
|
9
|
-
STRUCTURE_EVENTS,
|
|
10
|
-
STRUCTURE_VERSION,
|
|
11
|
-
STRUCTURE_MEMBERS_NEW,
|
|
12
|
-
} from "@truedat/core/routes";
|
|
5
|
+
|
|
13
6
|
import { useSelector } from "react-redux";
|
|
14
7
|
import AddStructureMember from "./AddStructureMember";
|
|
15
8
|
import StructureCrumbs from "./StructureCrumbs";
|
|
@@ -35,4 +35,58 @@ describe("<StructureTabs />", () => {
|
|
|
35
35
|
await waitForLoad(rendered);
|
|
36
36
|
expect(rendered.container).toMatchSnapshot();
|
|
37
37
|
});
|
|
38
|
+
|
|
39
|
+
it("should render correctly with structureTabsOrder", async () => {
|
|
40
|
+
jest.spyOn(getTabVisibilityModule, "getTabVisibility").mockReturnValue(tabVisibility);
|
|
41
|
+
|
|
42
|
+
const structureTabsOrder = ["links", "notes", "fields", "profile"];
|
|
43
|
+
const props = { path: "/structures/:id" };
|
|
44
|
+
const rendered = render(<StructureTabs {...props} />, {
|
|
45
|
+
state: { structure, structureVersion: version, structureTabsOrder },
|
|
46
|
+
});
|
|
47
|
+
await waitForLoad(rendered);
|
|
48
|
+
|
|
49
|
+
const menuItems = rendered.container.querySelectorAll(".item");
|
|
50
|
+
expect(menuItems.length).toBeGreaterThan(0);
|
|
51
|
+
expect(rendered.container).toMatchSnapshot();
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should use default order when structureTabsOrder is empty", async () => {
|
|
55
|
+
jest.spyOn(getTabVisibilityModule, "getTabVisibility").mockReturnValue(tabVisibility);
|
|
56
|
+
|
|
57
|
+
const props = { path: "/structures/:id" };
|
|
58
|
+
const rendered = render(<StructureTabs {...props} />, {
|
|
59
|
+
state: { structure, structureVersion: version, structureTabsOrder: [] },
|
|
60
|
+
});
|
|
61
|
+
await waitForLoad(rendered);
|
|
62
|
+
|
|
63
|
+
const menuItems = rendered.container.querySelectorAll(".item");
|
|
64
|
+
expect(menuItems.length).toBeGreaterThan(0);
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
it("should handle structureTabsOrder with tabs not in items", async () => {
|
|
68
|
+
jest.spyOn(getTabVisibilityModule, "getTabVisibility").mockReturnValue(tabVisibility);
|
|
69
|
+
|
|
70
|
+
const structureTabsOrder = ["nonexistent", "fields", "notes"];
|
|
71
|
+
const props = { path: "/structures/:id" };
|
|
72
|
+
const rendered = render(<StructureTabs {...props} />, {
|
|
73
|
+
state: { structure, structureVersion: version, structureTabsOrder },
|
|
74
|
+
});
|
|
75
|
+
await waitForLoad(rendered);
|
|
76
|
+
|
|
77
|
+
const menuItems = rendered.container.querySelectorAll(".item");
|
|
78
|
+
expect(menuItems.length).toBeGreaterThan(0);
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should not crash when structure is empty", async () => {
|
|
82
|
+
jest.spyOn(getTabVisibilityModule, "getTabVisibility").mockReturnValue(tabVisibility);
|
|
83
|
+
|
|
84
|
+
const props = { path: "/structures/:id" };
|
|
85
|
+
const rendered = render(<StructureTabs {...props} />, {
|
|
86
|
+
state: { structure: null, structureVersion: version, structureTabsOrder: [] },
|
|
87
|
+
});
|
|
88
|
+
await waitForLoad(rendered);
|
|
89
|
+
|
|
90
|
+
expect(rendered.container).toBeTruthy();
|
|
91
|
+
});
|
|
38
92
|
});
|
|
@@ -81,3 +81,85 @@ exports[`<StructureTabs /> matches the latest snapshot: metadata 1`] = `
|
|
|
81
81
|
/>
|
|
82
82
|
</div>
|
|
83
83
|
`;
|
|
84
|
+
|
|
85
|
+
exports[`<StructureTabs /> should render correctly with structureTabsOrder 1`] = `
|
|
86
|
+
<div>
|
|
87
|
+
<div
|
|
88
|
+
class="ui pointing secondary top attached tabular tab-overflow menu"
|
|
89
|
+
>
|
|
90
|
+
<a
|
|
91
|
+
class="active item"
|
|
92
|
+
data-discover="true"
|
|
93
|
+
href="/structures/123/links"
|
|
94
|
+
>
|
|
95
|
+
tabs.dd.links
|
|
96
|
+
</a>
|
|
97
|
+
<a
|
|
98
|
+
class="item"
|
|
99
|
+
data-discover="true"
|
|
100
|
+
href="/structures/123/notes"
|
|
101
|
+
>
|
|
102
|
+
tabs.dd.notes
|
|
103
|
+
</a>
|
|
104
|
+
<a
|
|
105
|
+
class="item"
|
|
106
|
+
data-discover="true"
|
|
107
|
+
href="/structures/123/versions/1/fields"
|
|
108
|
+
>
|
|
109
|
+
tabs.dd.fields
|
|
110
|
+
</a>
|
|
111
|
+
<a
|
|
112
|
+
class="item"
|
|
113
|
+
data-discover="true"
|
|
114
|
+
href="/structures/123/profile"
|
|
115
|
+
>
|
|
116
|
+
tabs.dd.profile
|
|
117
|
+
</a>
|
|
118
|
+
<a
|
|
119
|
+
class="item"
|
|
120
|
+
data-discover="true"
|
|
121
|
+
href="/structures/123/grants"
|
|
122
|
+
>
|
|
123
|
+
tabs.dd.grants
|
|
124
|
+
</a>
|
|
125
|
+
<a
|
|
126
|
+
class="item"
|
|
127
|
+
data-discover="true"
|
|
128
|
+
href="/structures/123/metadata"
|
|
129
|
+
>
|
|
130
|
+
tabs.dd.metadata
|
|
131
|
+
</a>
|
|
132
|
+
<a
|
|
133
|
+
class="item"
|
|
134
|
+
data-discover="true"
|
|
135
|
+
href="/structures/123/rules"
|
|
136
|
+
>
|
|
137
|
+
tabs.dd.rules
|
|
138
|
+
</a>
|
|
139
|
+
<a
|
|
140
|
+
class="item"
|
|
141
|
+
data-discover="true"
|
|
142
|
+
href="/structures/123/versions/1/versions"
|
|
143
|
+
>
|
|
144
|
+
tabs.dd.versions
|
|
145
|
+
</a>
|
|
146
|
+
<a
|
|
147
|
+
class="item"
|
|
148
|
+
data-discover="true"
|
|
149
|
+
href="/structures/123/events"
|
|
150
|
+
>
|
|
151
|
+
tabs.dd.audit
|
|
152
|
+
</a>
|
|
153
|
+
<a
|
|
154
|
+
class="item"
|
|
155
|
+
data-discover="true"
|
|
156
|
+
href="/structures/123/members"
|
|
157
|
+
>
|
|
158
|
+
tabs.dd.roles
|
|
159
|
+
</a>
|
|
160
|
+
</div>
|
|
161
|
+
<div
|
|
162
|
+
class="ui hidden divider"
|
|
163
|
+
/>
|
|
164
|
+
</div>
|
|
165
|
+
`;
|
|
@@ -75,6 +75,68 @@ describe("selectors: defaultTab", () => {
|
|
|
75
75
|
expect(defaultTab({ fields }, tabsOrder)).toBe("fields");
|
|
76
76
|
expect(defaultTab({}, tabsOrder)).toBe(undefined);
|
|
77
77
|
});
|
|
78
|
+
|
|
79
|
+
it("should return the first visible tab according to custom order when all tabs are visible", () => {
|
|
80
|
+
const tabsOrder = ["links", "fields", "notes", "metadata"];
|
|
81
|
+
const tabVisibility = {
|
|
82
|
+
links: true,
|
|
83
|
+
fields: true,
|
|
84
|
+
notes: true,
|
|
85
|
+
metadata: true,
|
|
86
|
+
children: true,
|
|
87
|
+
grants: true,
|
|
88
|
+
};
|
|
89
|
+
expect(defaultTab(tabVisibility, tabsOrder)).toBe("links");
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
it("should return the first visible tab in custom order, skipping invisible ones", () => {
|
|
93
|
+
const tabsOrder = ["links", "fields", "notes", "metadata"];
|
|
94
|
+
const tabVisibility = {
|
|
95
|
+
links: false,
|
|
96
|
+
fields: true,
|
|
97
|
+
notes: true,
|
|
98
|
+
metadata: true,
|
|
99
|
+
};
|
|
100
|
+
expect(defaultTab(tabVisibility, tabsOrder)).toBe("fields");
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should include custom tabs in the order when provided", () => {
|
|
104
|
+
const tabsOrder = ["links", "fields"];
|
|
105
|
+
const customTabs = [{ name: "custom1" }, { name: "custom2" }];
|
|
106
|
+
const tabVisibility = {
|
|
107
|
+
links: false,
|
|
108
|
+
fields: false,
|
|
109
|
+
};
|
|
110
|
+
expect(defaultTab(tabVisibility, tabsOrder, customTabs)).toBe("custom1");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should place custom tabs after tabsOrder when tabsOrder is provided", () => {
|
|
114
|
+
const tabsOrder = ["links", "fields"];
|
|
115
|
+
const customTabs = [{ name: "custom1" }, { name: "custom2" }];
|
|
116
|
+
const tabVisibility = {
|
|
117
|
+
links: true,
|
|
118
|
+
fields: true,
|
|
119
|
+
};
|
|
120
|
+
expect(defaultTab(tabVisibility, tabsOrder, customTabs)).toBe("links");
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("should place custom tabs at the end when no tabsOrder is provided", () => {
|
|
124
|
+
const customTabs = [{ name: "custom1" }, { name: "custom2" }];
|
|
125
|
+
const tabVisibility = {
|
|
126
|
+
fields: true,
|
|
127
|
+
};
|
|
128
|
+
expect(defaultTab(tabVisibility, [], customTabs)).toBe("fields");
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it("should return custom tab as first when it is first in tabsOrder", () => {
|
|
132
|
+
const tabsOrder = ["custom", "links", "fields"];
|
|
133
|
+
const customTabs = [{ name: "custom", route: "/structures/:id/custom" }];
|
|
134
|
+
const tabVisibility = {
|
|
135
|
+
links: true,
|
|
136
|
+
fields: true,
|
|
137
|
+
};
|
|
138
|
+
expect(defaultTab(tabVisibility, tabsOrder, customTabs)).toBe("custom");
|
|
139
|
+
});
|
|
78
140
|
});
|
|
79
141
|
|
|
80
142
|
describe("selectors: getActiveTab", () => {
|
|
@@ -103,4 +165,86 @@ describe("selectors: getActiveTab", () => {
|
|
|
103
165
|
expect(getActiveTab({ tabVisibility, path: "foo" })).toBe(undefined);
|
|
104
166
|
expect(getActiveTab({ tabVisibility, path: customPath, customTabs: [{ name: "custom", route: customPath }] })).toBe("custom");
|
|
105
167
|
});
|
|
168
|
+
|
|
169
|
+
it("should return the first visible tab according to structureTabsOrder when path is STRUCTURE", () => {
|
|
170
|
+
const structureTabsOrder = ["links", "fields", "notes"];
|
|
171
|
+
const tabVisibility = {
|
|
172
|
+
links: true,
|
|
173
|
+
fields: true,
|
|
174
|
+
notes: true,
|
|
175
|
+
};
|
|
176
|
+
expect(getActiveTab({ tabVisibility, path: STRUCTURE, structureTabsOrder })).toBe("links");
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
it("should return the first visible tab according to structureTabsOrder when path is STRUCTURE_VERSION", () => {
|
|
180
|
+
const structureTabsOrder = ["notes", "fields", "links"];
|
|
181
|
+
const tabVisibility = {
|
|
182
|
+
notes: true,
|
|
183
|
+
fields: true,
|
|
184
|
+
links: true,
|
|
185
|
+
};
|
|
186
|
+
expect(getActiveTab({ tabVisibility, path: STRUCTURE_VERSION, structureTabsOrder })).toBe("notes");
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
it("should skip invisible tabs in structureTabsOrder and return the first visible one", () => {
|
|
190
|
+
const structureTabsOrder = ["links", "fields", "notes"];
|
|
191
|
+
const tabVisibility = {
|
|
192
|
+
links: false,
|
|
193
|
+
fields: true,
|
|
194
|
+
notes: true,
|
|
195
|
+
};
|
|
196
|
+
expect(getActiveTab({ tabVisibility, path: STRUCTURE, structureTabsOrder })).toBe("fields");
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
it("should return first visible tab from default order when all tabs in structureTabsOrder are invisible", () => {
|
|
200
|
+
const structureTabsOrder = ["links", "versions"];
|
|
201
|
+
const tabVisibility = {
|
|
202
|
+
links: false,
|
|
203
|
+
versions: false,
|
|
204
|
+
fields: true,
|
|
205
|
+
notes: true,
|
|
206
|
+
};
|
|
207
|
+
expect(getActiveTab({ tabVisibility, path: STRUCTURE, structureTabsOrder })).toBe("fields");
|
|
208
|
+
});
|
|
209
|
+
|
|
210
|
+
it("should handle tabs in structureTabsOrder that are not in tabVisibility", () => {
|
|
211
|
+
const structureTabsOrder = ["nonexistent", "fields", "notes"];
|
|
212
|
+
const tabVisibility = {
|
|
213
|
+
fields: true,
|
|
214
|
+
notes: true,
|
|
215
|
+
};
|
|
216
|
+
expect(getActiveTab({ tabVisibility, path: STRUCTURE, structureTabsOrder })).toBe("fields");
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
it("should handle structureLinks, lineage, and impact tabs in custom order", () => {
|
|
220
|
+
const structureTabsOrder = ["lineage", "structureLinks", "impact", "fields"];
|
|
221
|
+
const tabVisibility = {
|
|
222
|
+
lineage: true,
|
|
223
|
+
structureLinks: true,
|
|
224
|
+
impact: true,
|
|
225
|
+
fields: true,
|
|
226
|
+
};
|
|
227
|
+
expect(getActiveTab({ tabVisibility, path: STRUCTURE, structureTabsOrder })).toBe("lineage");
|
|
228
|
+
});
|
|
229
|
+
|
|
230
|
+
it("should return custom tab as first when it is first in structureTabsOrder", () => {
|
|
231
|
+
const structureTabsOrder = ["custom", "links", "fields", "notes"];
|
|
232
|
+
const customTabs = [{ name: "custom", route: "/structures/:id/custom" }];
|
|
233
|
+
const tabVisibility = {
|
|
234
|
+
links: true,
|
|
235
|
+
fields: true,
|
|
236
|
+
notes: true,
|
|
237
|
+
};
|
|
238
|
+
expect(getActiveTab({ tabVisibility, path: STRUCTURE, structureTabsOrder, customTabs })).toBe("custom");
|
|
239
|
+
});
|
|
240
|
+
|
|
241
|
+
it("should skip custom tab if it is not in customTabs array even if in structureTabsOrder", () => {
|
|
242
|
+
const structureTabsOrder = ["custom", "links", "fields"];
|
|
243
|
+
const customTabs = [];
|
|
244
|
+
const tabVisibility = {
|
|
245
|
+
links: true,
|
|
246
|
+
fields: true,
|
|
247
|
+
};
|
|
248
|
+
expect(getActiveTab({ tabVisibility, path: STRUCTURE, structureTabsOrder, customTabs })).toBe("links");
|
|
249
|
+
});
|
|
106
250
|
});
|
|
@@ -36,19 +36,41 @@ export const defaultTab = (tabVisibility, tabsOrder = [], customTabs = []) => {
|
|
|
36
36
|
"rules",
|
|
37
37
|
"roles",
|
|
38
38
|
"links",
|
|
39
|
+
"structureLinks",
|
|
40
|
+
"lineage",
|
|
41
|
+
"impact",
|
|
39
42
|
"versions",
|
|
40
|
-
|
|
43
|
+
"events",
|
|
41
44
|
];
|
|
42
45
|
|
|
43
|
-
|
|
46
|
+
const customTabsNames = _.map((tab) => tab.name)(customTabs);
|
|
47
|
+
const customTabsNamesSet = new Set(customTabsNames);
|
|
48
|
+
|
|
49
|
+
const isTabVisible = (tab) => {
|
|
50
|
+
if (customTabsNamesSet.has(tab)) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
return tabVisibility[tab] === true;
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
if (_.isArray(tabsOrder) && _.size(tabsOrder) > 0) {
|
|
57
|
+
for (const tab of tabsOrder) {
|
|
58
|
+
if (isTabVisible(tab)) {
|
|
59
|
+
return tab;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const order = [...defaultOrder, ...customTabsNames];
|
|
65
|
+
return _.find((tab) => isTabVisible(tab))(order);
|
|
44
66
|
};
|
|
45
67
|
|
|
46
|
-
const getCustomTabs = (customTabs) => _.map((tab) => [_.eq(tab.route), _.constant(tab.name)])(customTabs)
|
|
68
|
+
const getCustomTabs = (customTabs) => _.map((tab) => [_.eq(tab.route), _.constant(tab.name)])(customTabs);
|
|
47
69
|
|
|
48
|
-
export const getActiveTab = ({ tabVisibility, path,
|
|
70
|
+
export const getActiveTab = ({ tabVisibility, path, structureTabsOrder, customTabs }) => {
|
|
49
71
|
return _.cond([
|
|
50
|
-
[_.eq(STRUCTURE), _.constant(defaultTab(tabVisibility,
|
|
51
|
-
[_.eq(STRUCTURE_VERSION), _.constant(defaultTab(tabVisibility,
|
|
72
|
+
[_.eq(STRUCTURE), _.constant(defaultTab(tabVisibility, structureTabsOrder, customTabs))],
|
|
73
|
+
[_.eq(STRUCTURE_VERSION), _.constant(defaultTab(tabVisibility, structureTabsOrder, customTabs))],
|
|
52
74
|
[_.eq(STRUCTURE_VERSION_FIELDS), _.constant("fields")],
|
|
53
75
|
[_.eq(STRUCTURE_FIELDS), _.constant("fields")],
|
|
54
76
|
[_.eq(STRUCTURE_CHILDREN), _.constant("children")],
|