@rancher/shell 3.0.11 → 3.0.12-rc.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/assets/images/providers/entraid-black.svg +4 -0
- package/assets/images/providers/entraid.svg +9 -0
- package/assets/images/vendor/entraid.svg +9 -0
- package/assets/styles/app.scss +0 -1
- package/assets/styles/base/_mixins.scss +31 -0
- package/assets/styles/base/_variables.scss +2 -0
- package/assets/styles/themes/_modern.scss +6 -5
- package/assets/translations/en-us.yaml +24 -21
- package/assets/translations/zh-hans.yaml +4 -11
- package/chart/__tests__/S3.test.ts +10 -3
- package/components/CountBox.vue +20 -0
- package/components/CreateDriver.vue +0 -12
- package/components/DetailText.vue +12 -3
- package/components/EmptyProductPage.vue +76 -0
- package/components/Resource/Detail/CopyToClipboard.vue +1 -2
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +9 -3
- package/components/Resource/Detail/TitleBar/__tests__/__snapshots__/index.test.ts.snap +31 -0
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +45 -1
- package/components/Resource/Detail/TitleBar/index.vue +1 -1
- package/components/Resource/Detail/ViewOptions/__tests__/__snapshots__/index.test.ts.snap +9 -0
- package/components/Resource/Detail/ViewOptions/__tests__/index.test.ts +62 -0
- package/components/Resource/Detail/ViewOptions/index.vue +2 -1
- package/components/ResourceList/Masthead.vue +25 -2
- package/components/SelectIconGrid.vue +5 -0
- package/components/SideNav.vue +13 -0
- package/components/__tests__/CountBox.test.ts +72 -0
- package/components/__tests__/DetailText.test.ts +113 -0
- package/components/__tests__/PromptModal.test.ts +2 -0
- package/components/fleet/FleetClusterTargets/index.vue +18 -1
- package/components/fleet/FleetClusters.vue +1 -0
- package/components/fleet/__tests__/FleetClusters.test.ts +71 -0
- package/components/form/InputWithSelect.vue +18 -10
- package/components/form/KeyValue.vue +17 -1
- package/components/form/LabeledSelect.vue +82 -24
- package/components/form/NodeScheduling.vue +17 -3
- package/components/form/PrivateRegistry.vue +69 -0
- package/components/form/Select.vue +73 -56
- package/components/form/ServiceNameSelect.vue +13 -11
- package/components/form/__tests__/KeyValue.test.ts +66 -0
- package/components/form/__tests__/NodeScheduling.test.ts +9 -0
- package/components/form/__tests__/PrivateRegistry.test.ts +133 -0
- package/components/form/labeled-select-utils/useLabeledSelectPagination.ts +138 -0
- package/components/formatter/WorkloadHealthScale.vue +3 -1
- package/components/nav/Group.vue +33 -9
- package/components/nav/Header.vue +56 -10
- package/components/nav/NotificationCenter/Notification.vue +4 -1
- package/components/nav/NotificationCenter/NotificationHeader.vue +20 -8
- package/components/nav/NotificationCenter/__tests__/NotificationHeader.test.ts +80 -0
- package/components/nav/TopLevelMenu.vue +15 -1
- package/components/nav/Type.vue +8 -7
- package/components/nav/WindowManager/index.vue +2 -1
- package/components/nav/WorkspaceSwitcher.vue +13 -0
- package/components/nav/__tests__/Group.test.ts +67 -0
- package/components/nav/__tests__/Header.test.ts +235 -0
- package/components/nav/__tests__/Type.test.ts +20 -3
- package/components/templates/default.vue +34 -4
- package/components/templates/home.vue +12 -25
- package/components/templates/plain.vue +13 -26
- package/composables/useLabeledFormElement.ts +10 -2
- package/composables/useLabeledSelect.ts +60 -0
- package/composables/useUserRetentionValidation.ts +1 -49
- package/config/cookies.js +0 -1
- package/config/labels-annotations.js +1 -0
- package/config/pagination-table-headers.js +8 -1
- package/config/product/apps.js +2 -1
- package/config/product/auth.js +1 -0
- package/config/product/backup.js +1 -0
- package/config/product/compliance.js +1 -1
- package/config/product/explorer.js +25 -6
- package/config/product/fleet.js +1 -0
- package/config/product/gatekeeper.js +1 -0
- package/config/product/istio.js +1 -0
- package/config/product/logging.js +1 -0
- package/config/product/longhorn.js +2 -1
- package/config/product/manager.js +1 -0
- package/config/product/monitoring.js +1 -0
- package/config/product/navlinks.js +1 -0
- package/config/product/neuvector.js +2 -1
- package/config/product/settings.js +1 -0
- package/config/product/uiplugins.js +1 -0
- package/config/query-params.js +1 -0
- package/config/router/routes.js +0 -8
- package/core/__tests__/plugin-products-helpers.test.ts +454 -0
- package/core/__tests__/plugin-products.test.ts +3810 -0
- package/core/extension-manager-impl.js +30 -1
- package/core/plugin-products-base.ts +392 -0
- package/core/plugin-products-extending.ts +44 -0
- package/core/plugin-products-helpers.ts +263 -0
- package/core/plugin-products-top-level.ts +66 -0
- package/core/plugin-products-type-guards.ts +33 -0
- package/core/plugin-products.ts +50 -0
- package/core/plugin-types.ts +237 -0
- package/core/plugin.ts +45 -10
- package/core/productDebugger.js +48 -0
- package/core/types.ts +97 -11
- package/detail/__tests__/__snapshots__/fleet.cattle.io.bundle.test.ts.snap +52 -0
- package/detail/__tests__/fleet.cattle.io.bundle.test.ts +171 -0
- package/detail/__tests__/management.cattle.io.fleetworkspace.test.ts +128 -0
- package/detail/fleet.cattle.io.bundle.vue +21 -34
- package/detail/management.cattle.io.fleetworkspace.vue +49 -0
- package/dialog/ExtensionCatalogInstallDialog.vue +1 -1
- package/dialog/InstallExtensionDialog.vue +6 -27
- package/dialog/UninstallExistingExtensionDialog.vue +141 -0
- package/dialog/UninstallExtensionDialog.vue +4 -26
- package/dialog/__tests__/UninstallExistingExtensionDialog.test.ts +114 -0
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +9 -0
- package/edit/__tests__/kontainerDriver.test.ts +0 -13
- package/edit/__tests__/nodeDriver.test.ts +5 -11
- package/edit/__tests__/resources.cattle.io.restore.test.ts +9 -0
- package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
- package/edit/auth/__tests__/oidc.test.ts +54 -0
- package/edit/auth/azuread.vue +1 -1
- package/edit/auth/oidc.vue +8 -0
- package/edit/kontainerDriver.vue +1 -2
- package/edit/nodeDriver.vue +0 -2
- package/edit/provisioning.cattle.io.cluster/AgentEnv.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/AgentEnv.test.ts +25 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Ingress.test.ts +176 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +70 -99
- package/edit/provisioning.cattle.io.cluster/rke2.vue +4 -1
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +6 -0
- package/edit/provisioning.cattle.io.cluster/tabs/Ingress.vue +7 -2
- package/initialize/App.vue +29 -2
- package/initialize/install-plugins.js +0 -2
- package/list/__tests__/management.cattle.io.feature.test.ts +105 -0
- package/list/catalog.cattle.io.app.vue +25 -5
- package/list/management.cattle.io.feature.vue +1 -1
- package/list/management.cattle.io.fleetworkspace.vue +8 -0
- package/list/provisioning.cattle.io.cluster.vue +0 -1
- package/list/workload.vue +11 -4
- package/machine-config/amazonec2.vue +1 -0
- package/mixins/chart.js +40 -9
- package/mixins/resource-fetch.js +12 -3
- package/models/__tests__/catalog.cattle.io.app.test.ts +15 -1
- package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +84 -0
- package/models/__tests__/chart.test.ts +99 -6
- package/models/__tests__/management.cattle.io.feature.test.ts +131 -0
- package/models/__tests__/monitoring.coreos.com.alertmanagerconfig.test.ts +98 -0
- package/models/catalog.cattle.io.app.js +21 -17
- package/models/catalog.cattle.io.clusterrepo.js +39 -11
- package/models/chart.js +33 -19
- package/models/fleet-application.js +1 -1
- package/models/fleet.cattle.io.bundle.js +1 -1
- package/models/kontainerdriver.js +11 -0
- package/models/management.cattle.io.authconfig.js +5 -1
- package/models/management.cattle.io.cluster.js +0 -53
- package/models/management.cattle.io.feature.js +3 -3
- package/models/management.cattle.io.kontainerdriver.js +1 -26
- package/models/monitoring.coreos.com.alertmanagerconfig.js +31 -17
- package/models/nodedriver.js +7 -0
- package/models/pod.js +18 -0
- package/models/workload.js +20 -2
- package/package.json +13 -13
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +0 -1
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +189 -0
- package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +55 -0
- package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +53 -0
- package/pages/c/_cluster/apps/charts/chart.vue +217 -33
- package/pages/c/_cluster/apps/charts/index.vue +2 -2
- package/pages/c/_cluster/apps/charts/install.vue +8 -3
- package/pages/c/_cluster/auth/user.retention/index.vue +55 -22
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -7
- package/pages/c/_cluster/settings/brand.vue +4 -4
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +39 -2
- package/pages/c/_cluster/uiplugins/__tests__/PluginInfoPanel.test.ts +61 -0
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +246 -23
- package/pages/c/_cluster/uiplugins/index.vue +166 -62
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +1 -0
- package/plugins/dashboard-store/actions.js +3 -2
- package/plugins/dashboard-store/resource-class.js +62 -6
- package/plugins/plugin.js +16 -0
- package/plugins/steve/steve-pagination-utils.ts +7 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +205 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +82 -4
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +1 -1
- package/scripts/test-plugins-build.sh +5 -2
- package/scripts/typegen.sh +13 -1
- package/server/server-middleware.js +2 -2
- package/static/humans.txt +1 -0
- package/static/robots.txt +34 -0
- package/static/welcome-cow.svg +18 -0
- package/store/__tests__/catalog.test.ts +161 -11
- package/store/__tests__/type-map.test.ts +84 -24
- package/store/auth.js +0 -3
- package/store/catalog.js +60 -8
- package/store/type-map.js +42 -3
- package/tsconfig.paths.json +1 -0
- package/types/resources/pod.ts +18 -0
- package/types/shell/index.d.ts +8539 -2938
- package/types/store/dashboard-store.types.ts +5 -0
- package/types/store/pagination.types.ts +6 -0
- package/utils/__tests__/git.test.ts +270 -0
- package/utils/__tests__/inactivity.test.ts +316 -0
- package/utils/__tests__/object.test.ts +77 -0
- package/utils/__tests__/time.test.ts +14 -1
- package/utils/__tests__/url.test.ts +246 -0
- package/utils/axios.js +1 -4
- package/utils/dynamic-importer.js +3 -2
- package/utils/object.js +33 -2
- package/utils/pagination-utils.ts +1 -1
- package/utils/time.ts +5 -0
- package/utils/uiplugins.ts +12 -16
- package/utils/validators/__tests__/private-registry.test.ts +76 -0
- package/utils/validators/private-registry.ts +28 -0
- package/vue.config.js +0 -9
- package/assets/images/providers/azuread-black.svg +0 -22
- package/assets/images/providers/azuread.svg +0 -25
- package/assets/images/vendor/azuread.svg +0 -18
- package/assets/styles/fonts/_dots.scss +0 -18
- package/components/EmberPage.vue +0 -622
- package/components/EmberPageView.vue +0 -39
- package/components/form/labeled-select-utils/labeled-select-pagination.ts +0 -116
- package/mixins/labeled-form-element.ts +0 -225
- package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -28
- package/pages/c/_cluster/manager/pages/_page.vue +0 -22
- package/pages/c/_cluster/mcapps/pages/_page.vue +0 -22
- package/plugins/ember-cookie.js +0 -17
- package/utils/ember-page.js +0 -30
|
@@ -1,30 +1,54 @@
|
|
|
1
1
|
import { CATALOG } from '@shell/config/types';
|
|
2
|
+
import { CATALOG as CATALOG_ANNOTATIONS } from '@shell/config/labels-annotations';
|
|
2
3
|
import {
|
|
3
4
|
state, getters, actions, mutations, filterAndArrangeCharts
|
|
4
5
|
} from '../catalog';
|
|
5
6
|
import { createStore } from 'vuex';
|
|
6
7
|
|
|
7
8
|
const clusterRepo = { _key: 'testClusterRepo' };
|
|
8
|
-
const repoChartName = '
|
|
9
|
+
const repoChartName = 'regular-chart';
|
|
9
10
|
const repoChart = {
|
|
10
11
|
name: repoChartName,
|
|
11
12
|
type: 'namespaced',
|
|
12
13
|
version: 1,
|
|
13
14
|
metadata: { name: repoChartName }
|
|
14
15
|
};
|
|
15
|
-
const
|
|
16
|
+
const deprecatedByFieldChartName = 'deprecated-by-field-chart';
|
|
17
|
+
const deprecatedByFieldChart = {
|
|
18
|
+
name: deprecatedByFieldChartName,
|
|
19
|
+
type: 'namespaced',
|
|
20
|
+
version: 1,
|
|
21
|
+
deprecated: true,
|
|
22
|
+
metadata: { name: deprecatedByFieldChartName }
|
|
23
|
+
};
|
|
24
|
+
const deprecatedByAnnotationChartName = 'deprecated-by-annotation-chart';
|
|
25
|
+
const deprecatedByAnnotationChart = {
|
|
26
|
+
name: deprecatedByAnnotationChartName,
|
|
27
|
+
type: 'namespaced',
|
|
28
|
+
version: 1,
|
|
29
|
+
annotations: { [CATALOG_ANNOTATIONS.DEPRECATED]: 'true' },
|
|
30
|
+
metadata: { name: deprecatedByAnnotationChartName }
|
|
31
|
+
};
|
|
16
32
|
const repo = {
|
|
17
33
|
metadata: { name: 'testRepo' },
|
|
18
34
|
_key: 'testRepo',
|
|
19
35
|
links: { index: 'fetchindex' },
|
|
20
36
|
canLoad: true,
|
|
21
|
-
followLink: () => ({
|
|
37
|
+
followLink: () => ({
|
|
38
|
+
entries: {
|
|
39
|
+
[repoChartName]: [repoChart],
|
|
40
|
+
[deprecatedByFieldChartName]: [deprecatedByFieldChart],
|
|
41
|
+
[deprecatedByAnnotationChartName]: [deprecatedByAnnotationChart]
|
|
42
|
+
}
|
|
43
|
+
})
|
|
22
44
|
};
|
|
23
45
|
|
|
24
46
|
const catalogStoreName = 'catalog';
|
|
25
47
|
const clusterStore = 'cluster';
|
|
26
48
|
|
|
27
49
|
const expectedChartKey = `namespace/${ repo._key }/${ repoChartName }`;
|
|
50
|
+
const expectedDeprecatedByFieldChartKey = `namespace/${ repo._key }/${ deprecatedByFieldChartName }`;
|
|
51
|
+
const expectedDeprecatedByAnnotationChartKey = `namespace/${ repo._key }/${ deprecatedByAnnotationChartName }`;
|
|
28
52
|
const initialVersionInfo = { junk: true };
|
|
29
53
|
const initialRawChartName = 'cde';
|
|
30
54
|
const initialRawChart = {
|
|
@@ -160,10 +184,20 @@ describe('catalog', () => {
|
|
|
160
184
|
expect(rawCharts[expectedChartKey]).toBeDefined();
|
|
161
185
|
expect(rawCharts[expectedChartKey].id).toBe(expectedChartKey);
|
|
162
186
|
expect(rawCharts[expectedChartKey].versions[0].version).toBe(repoChart.version);
|
|
163
|
-
|
|
164
|
-
expect(
|
|
165
|
-
expect(
|
|
166
|
-
expect(
|
|
187
|
+
|
|
188
|
+
expect(rawCharts[expectedDeprecatedByFieldChartKey]).toBeDefined();
|
|
189
|
+
expect(rawCharts[expectedDeprecatedByFieldChartKey].id).toBe(expectedDeprecatedByFieldChartKey);
|
|
190
|
+
expect(rawCharts[expectedDeprecatedByFieldChartKey].deprecated).toBe(true);
|
|
191
|
+
|
|
192
|
+
expect(rawCharts[expectedDeprecatedByAnnotationChartKey]).toBeDefined();
|
|
193
|
+
expect(rawCharts[expectedDeprecatedByAnnotationChartKey].id).toBe(expectedDeprecatedByAnnotationChartKey);
|
|
194
|
+
expect(rawCharts[expectedDeprecatedByAnnotationChartKey].deprecated).toBe(true);
|
|
195
|
+
|
|
196
|
+
expect(charts).toHaveLength(4);
|
|
197
|
+
expect(charts.find((c: any) => c.id === initialRawChart.id)).toBeDefined();
|
|
198
|
+
expect(charts.find((c: any) => c.id === expectedChartKey)).toBeDefined();
|
|
199
|
+
expect(charts.find((c: any) => c.id === expectedDeprecatedByFieldChartKey)).toBeDefined();
|
|
200
|
+
expect(charts.find((c: any) => c.id === expectedDeprecatedByAnnotationChartKey)).toBeDefined();
|
|
167
201
|
|
|
168
202
|
// Version info should be unchanged
|
|
169
203
|
expect(store.state[catalogStoreName].versionInfos).toStrictEqual(initialVersionInfo);
|
|
@@ -197,14 +231,130 @@ describe('catalog', () => {
|
|
|
197
231
|
expect(rawCharts[expectedChartKey].id).toBe(expectedChartKey);
|
|
198
232
|
expect(rawCharts[expectedChartKey].versions[0].version).toBe(repoChart.version);
|
|
199
233
|
|
|
200
|
-
expect(
|
|
201
|
-
expect(
|
|
202
|
-
expect(
|
|
203
|
-
|
|
234
|
+
expect(rawCharts[expectedDeprecatedByFieldChartKey]).toBeDefined();
|
|
235
|
+
expect(rawCharts[expectedDeprecatedByFieldChartKey].id).toBe(expectedDeprecatedByFieldChartKey);
|
|
236
|
+
expect(rawCharts[expectedDeprecatedByFieldChartKey].deprecated).toBe(true);
|
|
237
|
+
|
|
238
|
+
expect(rawCharts[expectedDeprecatedByAnnotationChartKey]).toBeDefined();
|
|
239
|
+
expect(rawCharts[expectedDeprecatedByAnnotationChartKey].id).toBe(expectedDeprecatedByAnnotationChartKey);
|
|
240
|
+
expect(rawCharts[expectedDeprecatedByAnnotationChartKey].deprecated).toBe(true);
|
|
241
|
+
|
|
242
|
+
expect(charts).toHaveLength(3);
|
|
243
|
+
expect(charts.find((c: any) => c.id === expectedChartKey)).toBeDefined();
|
|
244
|
+
expect(charts.find((c: any) => c.id === expectedDeprecatedByFieldChartKey)).toBeDefined();
|
|
245
|
+
expect(charts.find((c: any) => c.id === expectedDeprecatedByAnnotationChartKey)).toBeDefined();
|
|
204
246
|
|
|
205
247
|
// Version info should be changed (it's now empty given reset)
|
|
206
248
|
expect(store.state[catalogStoreName].versionInfos).toStrictEqual({ });
|
|
207
249
|
});
|
|
250
|
+
|
|
251
|
+
it('repoKeys provided', async() => {
|
|
252
|
+
const store = createStore(constructStore());
|
|
253
|
+
|
|
254
|
+
// Validate initial state of store
|
|
255
|
+
expect(store.getters[`${ catalogStoreName }/rawCharts`]).toStrictEqual(initialRawCharts);
|
|
256
|
+
expect(store.getters[`${ catalogStoreName }/charts`]).toStrictEqual([]);
|
|
257
|
+
|
|
258
|
+
// Make the request targeting specific repo (we provide repo._key)
|
|
259
|
+
await store.dispatch(`${ catalogStoreName }/load`, {
|
|
260
|
+
force: true,
|
|
261
|
+
repoKeys: [repo._key]
|
|
262
|
+
});
|
|
263
|
+
|
|
264
|
+
const rawCharts = store.getters[`${ catalogStoreName }/rawCharts`];
|
|
265
|
+
const charts = store.getters[`${ catalogStoreName }/charts`];
|
|
266
|
+
|
|
267
|
+
// We expect the old chart belonging to this repo to be wiped out
|
|
268
|
+
// and replaced entirely by the newly fetched chart.
|
|
269
|
+
expect(rawCharts[initialRawChart.id]).not.toBeDefined();
|
|
270
|
+
expect(rawCharts[expectedChartKey]).toBeDefined();
|
|
271
|
+
expect(rawCharts[expectedChartKey].id).toBe(expectedChartKey);
|
|
272
|
+
expect(rawCharts[expectedChartKey].versions[0].version).toBe(repoChart.version);
|
|
273
|
+
|
|
274
|
+
expect(rawCharts[expectedDeprecatedByFieldChartKey]).toBeDefined();
|
|
275
|
+
expect(rawCharts[expectedDeprecatedByFieldChartKey].id).toBe(expectedDeprecatedByFieldChartKey);
|
|
276
|
+
expect(rawCharts[expectedDeprecatedByFieldChartKey].deprecated).toBe(true);
|
|
277
|
+
|
|
278
|
+
expect(rawCharts[expectedDeprecatedByAnnotationChartKey]).toBeDefined();
|
|
279
|
+
expect(rawCharts[expectedDeprecatedByAnnotationChartKey].id).toBe(expectedDeprecatedByAnnotationChartKey);
|
|
280
|
+
expect(rawCharts[expectedDeprecatedByAnnotationChartKey].deprecated).toBe(true);
|
|
281
|
+
|
|
282
|
+
expect(charts).toHaveLength(3);
|
|
283
|
+
expect(charts.find((c: any) => c.id === expectedChartKey)).toBeDefined();
|
|
284
|
+
expect(charts.find((c: any) => c.id === expectedDeprecatedByFieldChartKey)).toBeDefined();
|
|
285
|
+
expect(charts.find((c: any) => c.id === expectedDeprecatedByAnnotationChartKey)).toBeDefined();
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
it('repoKeys provided, ignoring unrelated charts and versions', async() => {
|
|
289
|
+
// We will manually inject an unrelated chart to prove it isn't wiped out
|
|
290
|
+
const store = createStore(constructStore());
|
|
291
|
+
const unrelatedChart = {
|
|
292
|
+
id: `namespace/unrelatedRepo/unrelatedChart`,
|
|
293
|
+
repoKey: 'unrelatedRepo',
|
|
294
|
+
type: 'namespaced',
|
|
295
|
+
name: 'unrelatedChart',
|
|
296
|
+
version: 1,
|
|
297
|
+
metadata: { name: 'unrelatedChart' }
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
const targetedVersionKey = `namespace/testRepo/myChart/1.0.0`;
|
|
301
|
+
const unrelatedVersionKey = `namespace/unrelatedRepo/unrelatedChart/1.0.0`;
|
|
302
|
+
|
|
303
|
+
store.state[catalogStoreName].charts = {
|
|
304
|
+
...initialRawCharts,
|
|
305
|
+
[unrelatedChart.id]: unrelatedChart
|
|
306
|
+
};
|
|
307
|
+
|
|
308
|
+
store.state[catalogStoreName].versionInfos = {
|
|
309
|
+
[targetedVersionKey]: { data: 'old-data' },
|
|
310
|
+
[unrelatedVersionKey]: { data: 'keep-me' }
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
// Make the request targeting specific repo
|
|
314
|
+
await store.dispatch(`${ catalogStoreName }/load`, {
|
|
315
|
+
force: true,
|
|
316
|
+
repoKeys: [repo._key]
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
const rawCharts = store.getters[`${ catalogStoreName }/rawCharts`];
|
|
320
|
+
const versionInfos = store.state[catalogStoreName].versionInfos;
|
|
321
|
+
|
|
322
|
+
// The unrelated chart should NOT be wiped
|
|
323
|
+
expect(rawCharts[unrelatedChart.id]).toBeDefined();
|
|
324
|
+
expect(rawCharts[unrelatedChart.id].repoKey).toBe('unrelatedRepo');
|
|
325
|
+
|
|
326
|
+
// The old initialRawChart (with repoKey: repo._key) SHOULD be wiped and replaced
|
|
327
|
+
expect(rawCharts[initialRawChart.id]).not.toBeDefined();
|
|
328
|
+
expect(rawCharts[expectedChartKey]).toBeDefined();
|
|
329
|
+
|
|
330
|
+
expect(rawCharts[expectedDeprecatedByFieldChartKey]).toBeDefined();
|
|
331
|
+
expect(rawCharts[expectedDeprecatedByAnnotationChartKey]).toBeDefined();
|
|
332
|
+
|
|
333
|
+
// The targeted version info SHOULD be wiped
|
|
334
|
+
expect(versionInfos[targetedVersionKey]).not.toBeDefined();
|
|
335
|
+
// The unrelated version info should NOT be wiped
|
|
336
|
+
expect(versionInfos[unrelatedVersionKey]).toBeDefined();
|
|
337
|
+
expect(versionInfos[unrelatedVersionKey].data).toBe('keep-me');
|
|
338
|
+
});
|
|
339
|
+
});
|
|
340
|
+
|
|
341
|
+
describe('refresh', () => {
|
|
342
|
+
it('calls refresh(false) on all repos and then dispatches a reset load', async() => {
|
|
343
|
+
const mockRepo1 = { refresh: jest.fn().mockResolvedValue(true) };
|
|
344
|
+
const mockRepo2 = { refresh: jest.fn().mockResolvedValue(true) };
|
|
345
|
+
|
|
346
|
+
const getters = { repos: [mockRepo1, mockRepo2] };
|
|
347
|
+
const dispatch = jest.fn().mockResolvedValue(true);
|
|
348
|
+
const commit = jest.fn();
|
|
349
|
+
|
|
350
|
+
await actions.refresh({
|
|
351
|
+
getters, commit, dispatch
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
expect(mockRepo1.refresh).toHaveBeenCalledWith(false);
|
|
355
|
+
expect(mockRepo2.refresh).toHaveBeenCalledWith(false);
|
|
356
|
+
expect(dispatch).toHaveBeenCalledWith('load', { force: true, reset: true });
|
|
357
|
+
});
|
|
208
358
|
});
|
|
209
359
|
|
|
210
360
|
describe('filterAndArrangeCharts', () => {
|
|
@@ -7,6 +7,17 @@ import {
|
|
|
7
7
|
SCHEMA,
|
|
8
8
|
} from '@shell/config/types';
|
|
9
9
|
|
|
10
|
+
// Type definitions for test data
|
|
11
|
+
interface TestSchema {
|
|
12
|
+
id: string;
|
|
13
|
+
type: string;
|
|
14
|
+
attributes?: { kind: string };
|
|
15
|
+
_group?: string;
|
|
16
|
+
_id?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type SchemaOrType = TestSchema | string;
|
|
20
|
+
|
|
10
21
|
/**
|
|
11
22
|
* types in the store
|
|
12
23
|
*/
|
|
@@ -115,9 +126,9 @@ describe('type-map', () => {
|
|
|
115
126
|
/**
|
|
116
127
|
* Stick in the required mode param to the expected menu items
|
|
117
128
|
*/
|
|
118
|
-
const setTypeMode = (modes, resourcesById) => {
|
|
119
|
-
return modes.reduce((res, mode) => {
|
|
120
|
-
const newResource = { };
|
|
129
|
+
const setTypeMode = (modes: string[], resourcesById: Record<string, any>) => {
|
|
130
|
+
return modes.reduce((res: Record<string, any>, mode: string) => {
|
|
131
|
+
const newResource: Record<string, any> = { };
|
|
121
132
|
|
|
122
133
|
Object.entries(resourcesById).forEach(([id, resource]: [string, any]) => {
|
|
123
134
|
newResource[id] = {
|
|
@@ -146,17 +157,17 @@ describe('type-map', () => {
|
|
|
146
157
|
spoofedTypes: { [productName]: [] }
|
|
147
158
|
},
|
|
148
159
|
typeMapGetters: {
|
|
149
|
-
labelFor: (schema, count) => '',
|
|
150
|
-
optionsFor: (schema) => {},
|
|
160
|
+
labelFor: (schema: SchemaOrType, count: number) => '',
|
|
161
|
+
optionsFor: (schema: SchemaOrType) => ({}),
|
|
151
162
|
groupForBasicType: () => {},
|
|
152
|
-
typeWeightFor: (label, isBasic) => 1
|
|
163
|
+
typeWeightFor: (label: string, isBasic: boolean) => 1
|
|
153
164
|
},
|
|
154
165
|
rootState: {},
|
|
155
166
|
rootGetters: {
|
|
156
167
|
[`${ productStore }/all`]: (schema: string) => {
|
|
157
168
|
return [];
|
|
158
169
|
},
|
|
159
|
-
'prefs/get': (pref) => {},
|
|
170
|
+
'prefs/get': (pref: string) => {},
|
|
160
171
|
|
|
161
172
|
},
|
|
162
173
|
|
|
@@ -201,9 +212,9 @@ describe('type-map', () => {
|
|
|
201
212
|
|
|
202
213
|
const testTypeMapGetters = {
|
|
203
214
|
...typeMapGetters,
|
|
204
|
-
labelFor: (schema, count) => 'Pod',
|
|
215
|
+
labelFor: (schema: SchemaOrType, count: number) => 'Pod',
|
|
205
216
|
groupForBasicType: () => true,
|
|
206
|
-
optionsFor: (schema) => ({
|
|
217
|
+
optionsFor: (schema: SchemaOrType) => ({
|
|
207
218
|
namespaced: true,
|
|
208
219
|
customRoute: 'cde'
|
|
209
220
|
}),
|
|
@@ -320,7 +331,7 @@ describe('type-map', () => {
|
|
|
320
331
|
|
|
321
332
|
const testTypeMapGetters = {
|
|
322
333
|
...typeMapGetters,
|
|
323
|
-
groupForBasicType: (product, id) => false
|
|
334
|
+
groupForBasicType: (product: string, id: string) => false
|
|
324
335
|
};
|
|
325
336
|
|
|
326
337
|
const groups = getters.allTypes(state, testTypeMapGetters, rootState, rootGetters)(productName, modes);
|
|
@@ -473,7 +484,7 @@ describe('type-map', () => {
|
|
|
473
484
|
|
|
474
485
|
const testTypeMapGetters = {
|
|
475
486
|
...typeMapGetters,
|
|
476
|
-
optionsFor: (schema) => ({
|
|
487
|
+
optionsFor: (schema: SchemaOrType) => ({
|
|
477
488
|
namespaced: true,
|
|
478
489
|
customRoute: 'cde',
|
|
479
490
|
ifRancherCluster: true
|
|
@@ -497,7 +508,7 @@ describe('type-map', () => {
|
|
|
497
508
|
|
|
498
509
|
const testTypeMapGetters = {
|
|
499
510
|
...typeMapGetters,
|
|
500
|
-
optionsFor: (schema) => ({
|
|
511
|
+
optionsFor: (schema: SchemaOrType) => ({
|
|
501
512
|
namespaced: true,
|
|
502
513
|
customRoute: 'cde',
|
|
503
514
|
ifRancherCluster: false
|
|
@@ -521,7 +532,7 @@ describe('type-map', () => {
|
|
|
521
532
|
|
|
522
533
|
const testTypeMapGetters = {
|
|
523
534
|
...typeMapGetters,
|
|
524
|
-
optionsFor: (schema) => ({
|
|
535
|
+
optionsFor: (schema: SchemaOrType) => ({
|
|
525
536
|
namespaced: true,
|
|
526
537
|
customRoute: 'cde',
|
|
527
538
|
ifRancherCluster: true
|
|
@@ -545,7 +556,7 @@ describe('type-map', () => {
|
|
|
545
556
|
|
|
546
557
|
const testTypeMapGetters = {
|
|
547
558
|
...typeMapGetters,
|
|
548
|
-
optionsFor: (schema) => ({
|
|
559
|
+
optionsFor: (schema: SchemaOrType) => ({
|
|
549
560
|
namespaced: true,
|
|
550
561
|
customRoute: 'cde',
|
|
551
562
|
localOnly: true
|
|
@@ -569,7 +580,7 @@ describe('type-map', () => {
|
|
|
569
580
|
|
|
570
581
|
const testTypeMapGetters = {
|
|
571
582
|
...typeMapGetters,
|
|
572
|
-
optionsFor: (schema) => ({
|
|
583
|
+
optionsFor: (schema: SchemaOrType) => ({
|
|
573
584
|
namespaced: true,
|
|
574
585
|
customRoute: 'cde',
|
|
575
586
|
localOnly: true
|
|
@@ -630,9 +641,9 @@ describe('type-map', () => {
|
|
|
630
641
|
|
|
631
642
|
const testTypeMapGetters = {
|
|
632
643
|
...typeMapGetters,
|
|
633
|
-
labelFor: (schema, count) => 'Secret',
|
|
644
|
+
labelFor: (schema: SchemaOrType, count: number) => 'Secret',
|
|
634
645
|
groupForBasicType: () => true,
|
|
635
|
-
optionsFor: (schema) => ({
|
|
646
|
+
optionsFor: (schema: SchemaOrType) => ({
|
|
636
647
|
namespaced: true,
|
|
637
648
|
customRoute: 'cde'
|
|
638
649
|
}),
|
|
@@ -882,8 +893,10 @@ describe('type-map', () => {
|
|
|
882
893
|
|
|
883
894
|
const testTypeMapGetters = {
|
|
884
895
|
...typeMapGetters,
|
|
885
|
-
labelFor: (schema, count) => {
|
|
886
|
-
|
|
896
|
+
labelFor: (schema: SchemaOrType, count: number) => {
|
|
897
|
+
const schemaId = typeof schema === 'object' ? schema.id : schema;
|
|
898
|
+
|
|
899
|
+
switch (schemaId) {
|
|
887
900
|
case 'secret':
|
|
888
901
|
return 'Secret';
|
|
889
902
|
default:
|
|
@@ -891,11 +904,11 @@ describe('type-map', () => {
|
|
|
891
904
|
}
|
|
892
905
|
},
|
|
893
906
|
groupForBasicType: () => true,
|
|
894
|
-
optionsFor: (schema) => ({
|
|
907
|
+
optionsFor: (schema: SchemaOrType) => ({
|
|
895
908
|
namespaced: true,
|
|
896
909
|
customRoute: 'cde'
|
|
897
910
|
}),
|
|
898
|
-
isFavorite: (id) => id === 'secret',
|
|
911
|
+
isFavorite: (id: string) => id === 'secret',
|
|
899
912
|
};
|
|
900
913
|
|
|
901
914
|
return {
|
|
@@ -1134,14 +1147,14 @@ describe('type-map', () => {
|
|
|
1134
1147
|
},
|
|
1135
1148
|
};
|
|
1136
1149
|
|
|
1137
|
-
const createProductState = (products) => ({
|
|
1150
|
+
const createProductState = (products: any) => ({
|
|
1138
1151
|
products,
|
|
1139
1152
|
schemaGeneration: 1,
|
|
1140
1153
|
});
|
|
1141
1154
|
|
|
1142
|
-
const createProductRootGetters = (moduleSchemas = [], moduleName = 'cluster') => ({
|
|
1155
|
+
const createProductRootGetters = (moduleSchemas: any[] = [], moduleName = 'cluster') => ({
|
|
1143
1156
|
'prefs/get': () => false,
|
|
1144
|
-
[`${ moduleName }/all`]: (resource) => {
|
|
1157
|
+
[`${ moduleName }/all`]: (resource: any) => {
|
|
1145
1158
|
if (resource === SCHEMA) {
|
|
1146
1159
|
return moduleSchemas;
|
|
1147
1160
|
}
|
|
@@ -1281,4 +1294,51 @@ describe('type-map', () => {
|
|
|
1281
1294
|
});
|
|
1282
1295
|
});
|
|
1283
1296
|
});
|
|
1297
|
+
|
|
1298
|
+
describe('groupLabel', () => {
|
|
1299
|
+
it('should return groupLabel when it exists in state', () => {
|
|
1300
|
+
const state = { groupLabels: { mygroup: { label: 'My Group Label', labelKey: undefined } } };
|
|
1301
|
+
|
|
1302
|
+
const result = getters.groupLabel(state)('mygroup');
|
|
1303
|
+
|
|
1304
|
+
expect(result).toStrictEqual({ label: 'My Group Label', labelKey: undefined });
|
|
1305
|
+
});
|
|
1306
|
+
|
|
1307
|
+
it('should return groupLabel with labelKey when set', () => {
|
|
1308
|
+
const state = { groupLabels: { anothergroup: { label: undefined, labelKey: 'typeLabel.myKey' } } };
|
|
1309
|
+
|
|
1310
|
+
const result = getters.groupLabel(state)('anothergroup');
|
|
1311
|
+
|
|
1312
|
+
expect(result).toStrictEqual({ label: undefined, labelKey: 'typeLabel.myKey' });
|
|
1313
|
+
});
|
|
1314
|
+
|
|
1315
|
+
it('should handle case-insensitive group names', () => {
|
|
1316
|
+
const state = { groupLabels: { mygroup: { label: 'My Group', labelKey: undefined } } };
|
|
1317
|
+
|
|
1318
|
+
const result = getters.groupLabel(state)('MyGroup');
|
|
1319
|
+
|
|
1320
|
+
expect(result).toStrictEqual({ label: 'My Group', labelKey: undefined });
|
|
1321
|
+
});
|
|
1322
|
+
|
|
1323
|
+
it('should return undefined when group label does not exist', () => {
|
|
1324
|
+
const state = { groupLabels: {} };
|
|
1325
|
+
|
|
1326
|
+
const result = getters.groupLabel(state)('nonexistent');
|
|
1327
|
+
|
|
1328
|
+
expect(result).toBeUndefined();
|
|
1329
|
+
});
|
|
1330
|
+
|
|
1331
|
+
it('should return undefined for empty, null, undefined, or non-existent group name', () => {
|
|
1332
|
+
const state = { groupLabels: { mygroup: { label: 'My Group', labelKey: undefined } } };
|
|
1333
|
+
|
|
1334
|
+
// Empty string fails the groupName check and returns undefined
|
|
1335
|
+
expect(getters.groupLabel(state)('')).toBeUndefined();
|
|
1336
|
+
// null returns undefined
|
|
1337
|
+
expect(getters.groupLabel(state)(null)).toBeUndefined();
|
|
1338
|
+
// undefined returns undefined
|
|
1339
|
+
expect(getters.groupLabel(state)(undefined)).toBeUndefined();
|
|
1340
|
+
// Non-existent group returns undefined
|
|
1341
|
+
expect(getters.groupLabel(state)('nonexistent')).toBeUndefined();
|
|
1342
|
+
});
|
|
1343
|
+
});
|
|
1284
1344
|
});
|
package/store/auth.js
CHANGED
|
@@ -3,7 +3,6 @@ import { MANAGEMENT, EXT } from '@shell/config/types';
|
|
|
3
3
|
import { addObjects, findBy, joinStringList } from '@shell/utils/array';
|
|
4
4
|
import { openAuthPopup, returnTo } from '@shell/utils/auth';
|
|
5
5
|
import { base64Encode } from '@shell/utils/crypto';
|
|
6
|
-
import { removeEmberPage } from '@shell/utils/ember-page';
|
|
7
6
|
import { randomStr } from '@shell/utils/string';
|
|
8
7
|
import { addParams, parse as parseUrl, removeParam } from '@shell/utils/url';
|
|
9
8
|
|
|
@@ -429,8 +428,6 @@ export const actions = {
|
|
|
429
428
|
},
|
|
430
429
|
|
|
431
430
|
uiLogout({ commit, dispatch }, options = {}) {
|
|
432
|
-
removeEmberPage();
|
|
433
|
-
|
|
434
431
|
commit('loggedOut');
|
|
435
432
|
dispatch('onLogout', options, { root: true });
|
|
436
433
|
|
package/store/catalog.js
CHANGED
|
@@ -325,8 +325,12 @@ export const actions = {
|
|
|
325
325
|
* force: Always refresh catalog's helm repo by re-fetching index.yaml
|
|
326
326
|
*
|
|
327
327
|
* reset: clear existing charts and version cache
|
|
328
|
+
*
|
|
329
|
+
* repoKeys: Optional array of specific repo keys (IDs) to refresh. When provided, only these specific
|
|
330
|
+
* repos will be fetched, and only their existing charts will be cleared from the cache to avoid
|
|
331
|
+
* duplicate chart entries or wiping out unrelated chart data.
|
|
328
332
|
*/
|
|
329
|
-
async load(ctx, { force, reset } = {}) {
|
|
333
|
+
async load(ctx, { force, reset, repoKeys = [] } = {}) {
|
|
330
334
|
const {
|
|
331
335
|
state, getters, rootGetters, commit, dispatch
|
|
332
336
|
} = ctx;
|
|
@@ -360,14 +364,34 @@ export const actions = {
|
|
|
360
364
|
promises = {};
|
|
361
365
|
|
|
362
366
|
for ( const repo of repos ) {
|
|
363
|
-
|
|
367
|
+
let shouldLoad = false;
|
|
368
|
+
|
|
369
|
+
if (repoKeys.length) {
|
|
370
|
+
// If repoKeys are explicitly provided (e.g. refreshing a single repo from the UI),
|
|
371
|
+
// we ONLY want to load the repos in that array. We intentionally ignore `!getters.isLoaded(repo)`
|
|
372
|
+
// here so we don't accidentally fetch other unrelated repos just because they haven't loaded yet.
|
|
373
|
+
shouldLoad = repoKeys.includes(repo._key);
|
|
374
|
+
} else {
|
|
375
|
+
// Default behavior: load if explicitly forced, OR if the repo hasn't been loaded into state yet.
|
|
376
|
+
shouldLoad = force === true || !getters.isLoaded(repo);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
if ( shouldLoad && repo.canLoad ) {
|
|
364
380
|
console.info('Loading index for repo', repo.name, `(${ repo._key })`); // eslint-disable-line no-console
|
|
365
381
|
promises[repo._key] = repo.followLink('index');
|
|
366
382
|
}
|
|
367
383
|
}
|
|
368
384
|
|
|
369
385
|
const res = await allHashSettled(promises);
|
|
370
|
-
const charts = reset ? {} : state.charts;
|
|
386
|
+
const charts = reset ? {} : { ...state.charts };
|
|
387
|
+
let versionInfos = null;
|
|
388
|
+
|
|
389
|
+
if (reset) {
|
|
390
|
+
versionInfos = {};
|
|
391
|
+
} else if (repoKeys.length) {
|
|
392
|
+
versionInfos = { ...state.versionInfos };
|
|
393
|
+
}
|
|
394
|
+
|
|
371
395
|
const errors = [];
|
|
372
396
|
|
|
373
397
|
for ( const key of Object.keys(res) ) {
|
|
@@ -379,6 +403,28 @@ export const actions = {
|
|
|
379
403
|
continue;
|
|
380
404
|
}
|
|
381
405
|
|
|
406
|
+
// We are targeting specific repos. To prevent duplicate chart versions from appearing,
|
|
407
|
+
// we must remove the old charts for this specific repo before appending the newly fetched ones,
|
|
408
|
+
// but ONLY if the fetch was successful.
|
|
409
|
+
if (repoKeys.length && repoKeys.includes(key)) {
|
|
410
|
+
for (const chartKey in charts) {
|
|
411
|
+
if (charts[chartKey].repoKey === key) {
|
|
412
|
+
delete charts[chartKey];
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
// Also clear out cached version info for this repo so we don't display stale READMEs/values
|
|
417
|
+
const repoType = repo.type === CATALOG.CLUSTER_REPO ? 'cluster' : 'namespace';
|
|
418
|
+
const repoName = repo.metadata.name;
|
|
419
|
+
const versionPrefix = `${ repoType }/${ repoName }/`;
|
|
420
|
+
|
|
421
|
+
for (const versionKey in versionInfos) {
|
|
422
|
+
if (versionKey.startsWith(versionPrefix)) {
|
|
423
|
+
delete versionInfos[versionKey];
|
|
424
|
+
}
|
|
425
|
+
}
|
|
426
|
+
}
|
|
427
|
+
|
|
382
428
|
for ( const k in obj.value.entries ) {
|
|
383
429
|
for ( const entry of obj.value.entries[k] ) {
|
|
384
430
|
addChart(ctx, charts, entry, repo);
|
|
@@ -394,13 +440,17 @@ export const actions = {
|
|
|
394
440
|
loaded,
|
|
395
441
|
});
|
|
396
442
|
|
|
397
|
-
if (
|
|
398
|
-
commit('setVersions',
|
|
443
|
+
if (versionInfos) {
|
|
444
|
+
commit('setVersions', versionInfos);
|
|
399
445
|
}
|
|
400
446
|
},
|
|
401
447
|
|
|
448
|
+
/**
|
|
449
|
+
* Globally refreshes all loaded repositories by triggering their refresh actions concurrently,
|
|
450
|
+
* bypassing individual catalog loads, and then performs a single, global catalog/load.
|
|
451
|
+
*/
|
|
402
452
|
async refresh({ getters, commit, dispatch }) {
|
|
403
|
-
const promises = getters.repos.map((x) => x.refresh());
|
|
453
|
+
const promises = getters.repos.map((x) => x.refresh(false));
|
|
404
454
|
|
|
405
455
|
// @TODO wait for repo state to indicate they're done once the API has that
|
|
406
456
|
|
|
@@ -488,7 +538,9 @@ function addChart(ctx, map, chart, repo) {
|
|
|
488
538
|
certified = CATALOG_ANNOTATIONS._OTHER;
|
|
489
539
|
}
|
|
490
540
|
|
|
491
|
-
|
|
541
|
+
const isDeprecated = !!chart.deprecated || chart.annotations?.[CATALOG_ANNOTATIONS.DEPRECATED] === 'true';
|
|
542
|
+
|
|
543
|
+
if ( isDeprecated ) {
|
|
492
544
|
sideLabel = DEPRECATED;
|
|
493
545
|
} else if ( chart.annotations?.[CATALOG_ANNOTATIONS.EXPERIMENTAL] ) {
|
|
494
546
|
sideLabel = EXPERIMENTAL;
|
|
@@ -546,7 +598,7 @@ function addChart(ctx, map, chart, repo) {
|
|
|
546
598
|
versions: [],
|
|
547
599
|
keywords: chart.keywords || [],
|
|
548
600
|
categories: filterCategories(chart.keywords),
|
|
549
|
-
deprecated:
|
|
601
|
+
deprecated: isDeprecated,
|
|
550
602
|
primeOnly,
|
|
551
603
|
experimental,
|
|
552
604
|
hidden: !!chart.annotations?.[CATALOG_ANNOTATIONS.HIDDEN],
|
package/store/type-map.js
CHANGED
|
@@ -317,6 +317,12 @@ export function DSL(store, product, module = 'type-map') {
|
|
|
317
317
|
}
|
|
318
318
|
},
|
|
319
319
|
|
|
320
|
+
labelGroup(group, label, labelKey) {
|
|
321
|
+
store.commit(`${ module }/labelGroup`, {
|
|
322
|
+
group, label, labelKey
|
|
323
|
+
});
|
|
324
|
+
},
|
|
325
|
+
|
|
320
326
|
setGroupDefaultType(input, defaultType) {
|
|
321
327
|
if ( isArray(input) ) {
|
|
322
328
|
store.commit(`${ module }/setGroupDefaultType`, { groups: input, defaultType });
|
|
@@ -397,6 +403,7 @@ export const state = function() {
|
|
|
397
403
|
groupIgnore: [],
|
|
398
404
|
groupWeights: {},
|
|
399
405
|
groupDefaultTypes: {},
|
|
406
|
+
groupLabels: {},
|
|
400
407
|
basicGroupWeights: { [ROOT]: 1000 },
|
|
401
408
|
groupMappings: [],
|
|
402
409
|
typeIgnore: [],
|
|
@@ -499,6 +506,23 @@ export const getters = {
|
|
|
499
506
|
};
|
|
500
507
|
},
|
|
501
508
|
|
|
509
|
+
groupLabel(state) {
|
|
510
|
+
return (group) => {
|
|
511
|
+
// Handle null/undefined
|
|
512
|
+
if (!group) {
|
|
513
|
+
return;
|
|
514
|
+
}
|
|
515
|
+
|
|
516
|
+
// commit is done with lowercase group names, so lowercase here to match
|
|
517
|
+
const groupName = group.toLowerCase();
|
|
518
|
+
|
|
519
|
+
// If this has been explicitly set, use that
|
|
520
|
+
if (groupName) {
|
|
521
|
+
return state.groupLabels[groupName];
|
|
522
|
+
}
|
|
523
|
+
};
|
|
524
|
+
},
|
|
525
|
+
|
|
502
526
|
groupForBasicType(state) {
|
|
503
527
|
return (product, schemaId) => {
|
|
504
528
|
return state.basicTypes?.[product]?.[schemaId];
|
|
@@ -740,10 +764,21 @@ export const getters = {
|
|
|
740
764
|
|
|
741
765
|
// Translate if an entry exists
|
|
742
766
|
let label = name;
|
|
743
|
-
|
|
744
|
-
|
|
767
|
+
let key;
|
|
768
|
+
|
|
769
|
+
// See if we have a configured label for this group
|
|
770
|
+
const groupLabel = getters['groupLabel'](name);
|
|
771
|
+
|
|
772
|
+
if (groupLabel?.label) {
|
|
773
|
+
label = groupLabel.label;
|
|
774
|
+
} else if (groupLabel?.labelKey) {
|
|
775
|
+
key = groupLabel.labelKey;
|
|
776
|
+
} else {
|
|
777
|
+
// i18n-uses nav.group.*
|
|
778
|
+
key = `nav.group."${ name }"`;
|
|
779
|
+
}
|
|
745
780
|
|
|
746
|
-
if ( rootGetters['i18n/exists'](key) ) {
|
|
781
|
+
if (key && rootGetters['i18n/exists'](key) ) {
|
|
747
782
|
label = rootGetters['i18n/t'](key);
|
|
748
783
|
}
|
|
749
784
|
|
|
@@ -1680,6 +1715,10 @@ export const mutations = {
|
|
|
1680
1715
|
}
|
|
1681
1716
|
},
|
|
1682
1717
|
|
|
1718
|
+
labelGroup(state, { group, label, labelKey }) {
|
|
1719
|
+
state.groupLabels[group.toLowerCase()] = { label, labelKey };
|
|
1720
|
+
},
|
|
1721
|
+
|
|
1683
1722
|
// setGroupDefaultType({group: 'core', defaultType: 'name'});
|
|
1684
1723
|
// By default when a group is clicked, the first item is selected - this allows
|
|
1685
1724
|
// this behaviour to be changed and a named child type can be chosen
|