@rancher/shell 0.3.9 → 0.3.10
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/translations/en-us.yaml +19 -24
- package/assets/translations/zh-hans.yaml +82 -16
- package/chart/istio.vue +11 -11
- package/chart/rancher-backup/S3.vue +1 -1
- package/components/AsyncButton.vue +2 -2
- package/components/ButtonGroup.vue +1 -1
- package/components/CompoundStatusBadge.vue +1 -1
- package/components/CopyCode.vue +1 -1
- package/components/DetailTop.vue +1 -1
- package/components/ExplorerProjectsNamespaces.vue +3 -3
- package/components/GlobalRoleBindings.vue +1 -1
- package/components/HarvesterServiceAddOnConfig.vue +2 -117
- package/components/ResourceDetail/Masthead.vue +1 -1
- package/components/ResourceList/Masthead.vue +0 -6
- package/components/ResourceList/ResourceLoadingIndicator.vue +1 -9
- package/components/ResourceList/index.vue +7 -6
- package/components/ResourceTable.vue +13 -3
- package/components/SortableTable/THead.vue +3 -3
- package/components/SortableTable/index.vue +3 -3
- package/components/Tabbed/Tab.vue +1 -1
- package/components/Tabbed/index.vue +1 -1
- package/components/Wizard.vue +9 -6
- package/components/__tests__/NamespaceFilter.test.ts +26 -7
- package/components/auth/RoleDetailEdit.vue +1 -1
- package/components/auth/SelectPrincipal.vue +1 -1
- package/components/fleet/FleetRepos.vue +1 -1
- package/components/form/ArrayList.vue +1 -1
- package/components/form/KeyValue.vue +3 -2
- package/components/form/Labels.vue +34 -14
- package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
- package/components/form/NameNsDescription.vue +1 -1
- package/components/form/PlusMinus.vue +2 -2
- package/components/form/Probe.vue +1 -1
- package/components/form/ProjectMemberEditor.vue +8 -4
- package/components/form/ResourceQuota/NamespaceRow.vue +1 -1
- package/components/form/ServicePorts.vue +2 -2
- package/components/form/Tolerations.vue +30 -3
- package/components/form/WorkloadPorts.vue +2 -1
- package/components/form/__tests__/KeyValue.test.ts +17 -0
- package/components/formatter/ClusterLink.vue +3 -3
- package/components/formatter/LiveDate.vue +1 -1
- package/components/formatter/PodImages.vue +1 -1
- package/components/formatter/RKETemplateName.vue +1 -1
- package/components/formatter/Shortened.vue +1 -1
- package/components/nav/Header.vue +7 -7
- package/components/nav/NamespaceFilter.vue +103 -54
- package/config/labels-annotations.js +8 -5
- package/config/settings.ts +2 -5
- package/config/types.js +6 -4
- package/core/plugin-routes.ts +26 -7
- package/core/plugins-loader.js +2 -0
- package/detail/provisioning.cattle.io.cluster.vue +4 -4
- package/edit/cis.cattle.io.clusterscan.vue +1 -1
- package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +19 -149
- package/edit/logging-flow/index.vue +2 -2
- package/edit/logging.banzaicloud.io.output/providers/elasticsearch.vue +12 -0
- package/edit/logging.banzaicloud.io.output/providers/opensearch.vue +12 -0
- package/edit/management.cattle.io.project.vue +7 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/routeConfig.vue +2 -2
- package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +11 -8
- package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +2 -2
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +12 -4
- package/edit/networking.k8s.io.networkpolicy/__tests__/PolicyRuleTarget.spec.ts +140 -0
- package/edit/networking.k8s.io.networkpolicy/__tests__/utils/mock.json +158 -0
- package/edit/networking.k8s.io.networkpolicy/__tests__/utils/selectors.ts +45 -0
- package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/AgentConfiguration.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/MachinePool.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -1
- package/edit/provisioning.cattle.io.cluster/RegistryMirrors.vue +2 -2
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +143 -169
- package/edit/provisioning.cattle.io.cluster/rke2.vue +15 -6
- package/edit/resources.cattle.io.restore.vue +2 -2
- package/edit/service.vue +22 -3
- package/edit/storage.k8s.io.storageclass/index.vue +1 -1
- package/edit/workload/Job.vue +2 -2
- package/edit/workload/index.vue +1 -1
- package/edit/workload/mixins/workload.js +7 -1
- package/edit/workload/storage/__tests__/Storage.test.ts +84 -5
- package/initialize/index.js +1 -0
- package/layouts/default.vue +1 -1
- package/mixins/resource-fetch-namespaced.js +19 -27
- package/mixins/resource-fetch.js +0 -5
- package/models/__tests__/namespace.test.ts +125 -0
- package/models/management.cattle.io.project.js +6 -1
- package/models/persistentvolume.js +1 -1
- package/models/workload.service.js +22 -7
- package/package.json +17 -5
- package/pages/auth/login.vue +46 -49
- package/pages/c/_cluster/apps/charts/chart.vue +1 -1
- package/pages/c/_cluster/apps/charts/install.vue +42 -51
- package/pages/c/_cluster/explorer/index.vue +1 -1
- package/pages/c/_cluster/monitoring/index.vue +1 -1
- package/pages/c/_cluster/settings/performance.vue +53 -18
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -1
- package/pages/c/_cluster/uiplugins/index.vue +16 -5
- package/pages/home.vue +1 -1
- package/pkg/vue.config.js +1 -0
- package/plugins/clean-html-directive.js +1 -1
- package/plugins/clean-tooltip-directive.js +33 -0
- package/plugins/dashboard-store/actions.js +4 -2
- package/plugins/dashboard-store/getters.js +6 -0
- package/plugins/dashboard-store/mutations.js +2 -2
- package/plugins/plugin.js +6 -1
- package/plugins/steve/actions.js +1 -1
- package/plugins/steve/getters.js +14 -3
- package/plugins/steve/resourceWatcher.js +36 -62
- package/plugins/steve/subscribe.js +137 -21
- package/plugins/steve/worker/index.js +7 -1
- package/plugins/steve/worker/web-worker.advanced.js +26 -8
- package/plugins/steve/worker/web-worker.basic.js +23 -4
- package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -2
- package/rancher-components/components/Form/Radio/RadioGroup.vue +2 -2
- package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +1 -1
- package/store/index.js +16 -61
- package/store/store-types.js +5 -0
- package/store/type-map.js +1 -1
- package/types/shell/index.d.ts +23 -7
- package/utils/__tests__/create-yaml.test.ts +63 -0
- package/utils/array.ts +4 -0
- package/utils/create-yaml.js +5 -5
- package/utils/namespace-filter.js +17 -5
- package/utils/projectAndNamespaceFiltering.utils.ts +62 -0
- package/utils/selector.js +6 -5
- package/utils/settings.ts +5 -7
- package/models/k8s.cni.cncf.io.networkattachmentdefinition.js +0 -93
|
@@ -50,6 +50,8 @@ export default {
|
|
|
50
50
|
row._showHost = true;
|
|
51
51
|
}
|
|
52
52
|
|
|
53
|
+
row._ipam = '';
|
|
54
|
+
|
|
53
55
|
return row;
|
|
54
56
|
});
|
|
55
57
|
|
|
@@ -387,7 +389,6 @@ export default {
|
|
|
387
389
|
:mode="mode"
|
|
388
390
|
:options="ipamOptions"
|
|
389
391
|
:label="t('servicesPage.harvester.ipam.label')"
|
|
390
|
-
:disabled="mode === 'edit'"
|
|
391
392
|
@input="queueUpdate"
|
|
392
393
|
/>
|
|
393
394
|
</div>
|
|
@@ -15,4 +15,21 @@ describe('component: KeyValue', () => {
|
|
|
15
15
|
|
|
16
16
|
expect(inputValue.value).toBe(value);
|
|
17
17
|
});
|
|
18
|
+
|
|
19
|
+
it('should display a markdown-multiline field with new lines visible', () => {
|
|
20
|
+
const wrapper = mount(KeyValue, {
|
|
21
|
+
propsData: {
|
|
22
|
+
value: 'test',
|
|
23
|
+
valueMarkdownMultiline: true,
|
|
24
|
+
},
|
|
25
|
+
mocks: { $store: { getters: { 'i18n/t': jest.fn() } } },
|
|
26
|
+
directives: { t }
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
const inputFieldTextArea = wrapper.find('textarea').element;
|
|
30
|
+
const inputFieldMultiline = wrapper.find('[data-testid="code-mirror-multiline-field"]').element;
|
|
31
|
+
|
|
32
|
+
expect(inputFieldTextArea).toBeUndefined();
|
|
33
|
+
expect(inputFieldMultiline).toBeDefined();
|
|
34
|
+
});
|
|
18
35
|
});
|
|
@@ -64,17 +64,17 @@ export default {
|
|
|
64
64
|
<span v-else>{{ value }}</span>
|
|
65
65
|
<i
|
|
66
66
|
v-if="row.unavailableMachines"
|
|
67
|
-
v-tooltip="row.unavailableMachines"
|
|
67
|
+
v-clean-tooltip="row.unavailableMachines"
|
|
68
68
|
class="conditions-alert-icon icon-alert icon"
|
|
69
69
|
/>
|
|
70
70
|
<i
|
|
71
71
|
v-if="row.rkeTemplateUpgrade"
|
|
72
|
-
v-tooltip="t('cluster.rkeTemplateUpgrade', { name: row.rkeTemplateUpgrade })"
|
|
72
|
+
v-clean-tooltip="t('cluster.rkeTemplateUpgrade', { name: row.rkeTemplateUpgrade })"
|
|
73
73
|
class="template-upgrade-icon icon-alert icon"
|
|
74
74
|
/>
|
|
75
75
|
<i
|
|
76
76
|
v-if="row.hasError"
|
|
77
|
-
v-tooltip="{ content: `<div>${formattedConditions}</div>`, html: true }"
|
|
77
|
+
v-clean-tooltip="{ content: `<div>${formattedConditions}</div>`, html: true }"
|
|
78
78
|
class="conditions-alert-icon icon-error icon-lg"
|
|
79
79
|
/>
|
|
80
80
|
</span>
|
|
@@ -14,7 +14,7 @@ export default {
|
|
|
14
14
|
<span>{{ value.displayName }}</span>
|
|
15
15
|
<i
|
|
16
16
|
v-if="value.upgrade"
|
|
17
|
-
v-tooltip="t('cluster.rkeTemplateUpgrade', { name: value.upgrade })"
|
|
17
|
+
v-clean-tooltip="t('cluster.rkeTemplateUpgrade', { name: value.upgrade })"
|
|
18
18
|
class="template-upgrade-icon icon-alert icon"
|
|
19
19
|
/>
|
|
20
20
|
</div>
|
|
@@ -360,7 +360,7 @@ export default {
|
|
|
360
360
|
>
|
|
361
361
|
<div
|
|
362
362
|
v-if="currentProduct && currentProduct.showClusterSwitcher"
|
|
363
|
-
v-tooltip="nameTooltip"
|
|
363
|
+
v-clean-tooltip="nameTooltip"
|
|
364
364
|
class="cluster cluster-clipped"
|
|
365
365
|
>
|
|
366
366
|
<div
|
|
@@ -455,7 +455,7 @@ export default {
|
|
|
455
455
|
<template v-if="currentProduct && currentProduct.showClusterSwitcher">
|
|
456
456
|
<button
|
|
457
457
|
v-if="showImportYaml"
|
|
458
|
-
v-tooltip="t('nav.import')"
|
|
458
|
+
v-clean-tooltip="t('nav.import')"
|
|
459
459
|
:disabled="!importEnabled"
|
|
460
460
|
type="button"
|
|
461
461
|
class="btn header-btn role-tertiary"
|
|
@@ -478,7 +478,7 @@ export default {
|
|
|
478
478
|
|
|
479
479
|
<button
|
|
480
480
|
v-if="showKubeShell"
|
|
481
|
-
v-tooltip="t('nav.shellShortcut', {key: shellShortcut})"
|
|
481
|
+
v-clean-tooltip="t('nav.shellShortcut', {key: shellShortcut})"
|
|
482
482
|
v-shortkey="{windows: ['ctrl', '`'], mac: ['meta', '`']}"
|
|
483
483
|
:disabled="!shellEnabled"
|
|
484
484
|
type="button"
|
|
@@ -491,7 +491,7 @@ export default {
|
|
|
491
491
|
|
|
492
492
|
<button
|
|
493
493
|
v-if="showKubeConfig"
|
|
494
|
-
v-tooltip="t('nav.kubeconfig.download')"
|
|
494
|
+
v-clean-tooltip="t('nav.kubeconfig.download')"
|
|
495
495
|
:disabled="!kubeConfigEnabled"
|
|
496
496
|
type="button"
|
|
497
497
|
class="btn header-btn role-tertiary"
|
|
@@ -502,7 +502,7 @@ export default {
|
|
|
502
502
|
|
|
503
503
|
<button
|
|
504
504
|
v-if="showCopyConfig"
|
|
505
|
-
v-tooltip="t('nav.kubeconfig.copy')"
|
|
505
|
+
v-clean-tooltip="t('nav.kubeconfig.copy')"
|
|
506
506
|
:disabled="!kubeConfigEnabled"
|
|
507
507
|
type="button"
|
|
508
508
|
class="btn header-btn role-tertiary"
|
|
@@ -521,7 +521,7 @@ export default {
|
|
|
521
521
|
|
|
522
522
|
<button
|
|
523
523
|
v-if="showSearch"
|
|
524
|
-
v-tooltip="t('nav.resourceSearch.toolTip', {key: searchShortcut})"
|
|
524
|
+
v-clean-tooltip="t('nav.resourceSearch.toolTip', {key: searchShortcut})"
|
|
525
525
|
v-shortkey="{windows: ['ctrl', 'k'], mac: ['meta', 'k']}"
|
|
526
526
|
type="button"
|
|
527
527
|
class="btn header-btn role-tertiary"
|
|
@@ -549,7 +549,7 @@ export default {
|
|
|
549
549
|
<button
|
|
550
550
|
v-for="action, i in extensionHeaderActions"
|
|
551
551
|
:key="`${action.label}${i}`"
|
|
552
|
-
v-tooltip="handleExtensionTooltip(action)"
|
|
552
|
+
v-clean-tooltip="handleExtensionTooltip(action)"
|
|
553
553
|
v-shortkey="action.shortcutKey"
|
|
554
554
|
:disabled="action.enabled ? !action.enabled(ctx) : false"
|
|
555
555
|
type="button"
|
|
@@ -5,7 +5,6 @@ import { NAMESPACE, MANAGEMENT } from '@shell/config/types';
|
|
|
5
5
|
import { sortBy } from '@shell/utils/sort';
|
|
6
6
|
import { isArray, addObjects, findBy, filterBy } from '@shell/utils/array';
|
|
7
7
|
import {
|
|
8
|
-
NAMESPACE_FILTER_SPECIAL as SPECIAL,
|
|
9
8
|
NAMESPACE_FILTER_ALL_USER as ALL_USER,
|
|
10
9
|
NAMESPACE_FILTER_ALL as ALL,
|
|
11
10
|
NAMESPACE_FILTER_ALL_SYSTEM as ALL_SYSTEM,
|
|
@@ -13,23 +12,42 @@ import {
|
|
|
13
12
|
NAMESPACE_FILTER_NAMESPACED_YES as NAMESPACED_YES,
|
|
14
13
|
NAMESPACE_FILTER_NAMESPACED_NO as NAMESPACED_NO,
|
|
15
14
|
createNamespaceFilterKey,
|
|
15
|
+
NAMESPACE_FILTER_KINDS,
|
|
16
|
+
NAMESPACE_FILTER_NS_FULL_PREFIX,
|
|
17
|
+
NAMESPACE_FILTER_P_FULL_PREFIX,
|
|
16
18
|
} from '@shell/utils/namespace-filter';
|
|
17
19
|
import { KEY } from '@shell/utils/platform';
|
|
20
|
+
import pAndNFiltering from '@shell/utils/projectAndNamespaceFiltering.utils';
|
|
21
|
+
import { SETTING } from '@shell/config/settings';
|
|
22
|
+
|
|
23
|
+
const forcedNamespaceValidTypes = [NAMESPACE_FILTER_KINDS.DIVIDER, NAMESPACE_FILTER_KINDS.PROJECT, NAMESPACE_FILTER_KINDS.NAMESPACE];
|
|
18
24
|
|
|
19
25
|
export default {
|
|
26
|
+
|
|
20
27
|
data() {
|
|
21
28
|
return {
|
|
22
|
-
isOpen:
|
|
23
|
-
filter:
|
|
24
|
-
hidden:
|
|
25
|
-
total:
|
|
26
|
-
activeElement:
|
|
27
|
-
cachedFiltered:
|
|
29
|
+
isOpen: false,
|
|
30
|
+
filter: '',
|
|
31
|
+
hidden: 0,
|
|
32
|
+
total: 0,
|
|
33
|
+
activeElement: null,
|
|
34
|
+
cachedFiltered: [],
|
|
35
|
+
NAMESPACE_FILTER_KINDS,
|
|
36
|
+
namespaceFilterMode: undefined,
|
|
28
37
|
};
|
|
29
38
|
},
|
|
30
39
|
|
|
40
|
+
async fetch() {
|
|
41
|
+
// Determine if filtering by specific namespaces/projects is required
|
|
42
|
+
// This is done once and up front
|
|
43
|
+
// - it doesn't need to be re-active
|
|
44
|
+
// - added it as a computed caused massive amounts of churn around the `filtered` watcher
|
|
45
|
+
await this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.UI_PERFORMANCE });
|
|
46
|
+
this.namespaceFilterMode = this.calcNamespaceFilterMode();
|
|
47
|
+
},
|
|
48
|
+
|
|
31
49
|
computed: {
|
|
32
|
-
...mapGetters(['currentProduct'
|
|
50
|
+
...mapGetters(['currentProduct']),
|
|
33
51
|
|
|
34
52
|
hasFilter() {
|
|
35
53
|
return this.filter.length > 0;
|
|
@@ -40,23 +58,27 @@ export default {
|
|
|
40
58
|
|
|
41
59
|
out = out.filter((item) => {
|
|
42
60
|
// Filter out anything not applicable to singleton selection
|
|
43
|
-
if (this.namespaceFilterMode) {
|
|
61
|
+
if (this.namespaceFilterMode?.length) {
|
|
44
62
|
// We always show dividers, projects and namespaces
|
|
45
|
-
if (!
|
|
46
|
-
|
|
47
|
-
|
|
63
|
+
if (!forcedNamespaceValidTypes.includes(item.kind)) {
|
|
64
|
+
const validCustomType = this.namespaceFilterMode.find(prefix => item.kind.startsWith(prefix));
|
|
65
|
+
|
|
66
|
+
if (!validCustomType) {
|
|
67
|
+
// Hide any invalid option that's not selected
|
|
68
|
+
return this.value.findIndex(v => v.id === item.id) >= 0;
|
|
69
|
+
}
|
|
48
70
|
}
|
|
49
71
|
}
|
|
50
72
|
|
|
51
73
|
// Filter by the current filter
|
|
52
74
|
if (this.hasFilter) {
|
|
53
|
-
return item.kind !== SPECIAL && item.label.toLowerCase().includes(this.filter.toLowerCase());
|
|
75
|
+
return item.kind !== NAMESPACE_FILTER_KINDS.SPECIAL && item.label.toLowerCase().includes(this.filter.toLowerCase());
|
|
54
76
|
}
|
|
55
77
|
|
|
56
78
|
return true;
|
|
57
79
|
});
|
|
58
80
|
|
|
59
|
-
if (out?.[0]?.kind ===
|
|
81
|
+
if (out?.[0]?.kind === NAMESPACE_FILTER_KINDS.DIVIDER) {
|
|
60
82
|
out.splice(0, 1);
|
|
61
83
|
}
|
|
62
84
|
|
|
@@ -70,8 +92,15 @@ export default {
|
|
|
70
92
|
out.forEach((i) => {
|
|
71
93
|
i.selected = !!mapped[i.id] || (i.id === ALL && this.value && this.value.length === 0);
|
|
72
94
|
i.elementId = (i.id || '').replace('://', '_');
|
|
73
|
-
|
|
74
|
-
|
|
95
|
+
i.enabled = true;
|
|
96
|
+
// Are we in restricted resource type mode, if so is this an allowed type?
|
|
97
|
+
if (this.namespaceFilterMode?.length) {
|
|
98
|
+
const isLastSelected = i.selected && (i.id === ALL || this.value.length === 1);
|
|
99
|
+
const kindAllowed = this.namespaceFilterMode.find(f => f === i.kind);
|
|
100
|
+
const isNotInProjectGroup = i.id === ALL_ORPHANS;
|
|
101
|
+
|
|
102
|
+
i.enabled = (!isLastSelected && kindAllowed) && !isNotInProjectGroup;
|
|
103
|
+
}
|
|
75
104
|
});
|
|
76
105
|
|
|
77
106
|
return out;
|
|
@@ -134,27 +163,27 @@ export default {
|
|
|
134
163
|
out = [
|
|
135
164
|
{
|
|
136
165
|
id: ALL,
|
|
137
|
-
kind: SPECIAL,
|
|
166
|
+
kind: NAMESPACE_FILTER_KINDS.SPECIAL,
|
|
138
167
|
label: t('nav.ns.all'),
|
|
139
168
|
},
|
|
140
169
|
{
|
|
141
170
|
id: ALL_USER,
|
|
142
|
-
kind: SPECIAL,
|
|
171
|
+
kind: NAMESPACE_FILTER_KINDS.SPECIAL,
|
|
143
172
|
label: t('nav.ns.user'),
|
|
144
173
|
},
|
|
145
174
|
{
|
|
146
175
|
id: ALL_SYSTEM,
|
|
147
|
-
kind: SPECIAL,
|
|
176
|
+
kind: NAMESPACE_FILTER_KINDS.SPECIAL,
|
|
148
177
|
label: t('nav.ns.system'),
|
|
149
178
|
},
|
|
150
179
|
{
|
|
151
180
|
id: NAMESPACED_YES,
|
|
152
|
-
kind: SPECIAL,
|
|
181
|
+
kind: NAMESPACE_FILTER_KINDS.SPECIAL,
|
|
153
182
|
label: t('nav.ns.namespaced'),
|
|
154
183
|
},
|
|
155
184
|
{
|
|
156
185
|
id: NAMESPACED_NO,
|
|
157
|
-
kind: SPECIAL,
|
|
186
|
+
kind: NAMESPACE_FILTER_KINDS.SPECIAL,
|
|
158
187
|
label: t('nav.ns.clusterLevel'),
|
|
159
188
|
},
|
|
160
189
|
];
|
|
@@ -224,8 +253,8 @@ export default {
|
|
|
224
253
|
}
|
|
225
254
|
|
|
226
255
|
out.push({
|
|
227
|
-
id:
|
|
228
|
-
kind:
|
|
256
|
+
id: `${ NAMESPACE_FILTER_P_FULL_PREFIX }${ id }`,
|
|
257
|
+
kind: NAMESPACE_FILTER_KINDS.PROJECT,
|
|
229
258
|
label: t('nav.ns.project', { name: project.nameDisplay }),
|
|
230
259
|
});
|
|
231
260
|
|
|
@@ -243,7 +272,7 @@ export default {
|
|
|
243
272
|
|
|
244
273
|
out.push({
|
|
245
274
|
id: ALL_ORPHANS,
|
|
246
|
-
kind:
|
|
275
|
+
kind: NAMESPACE_FILTER_KINDS.PROJECT,
|
|
247
276
|
label: t('nav.ns.orphan'),
|
|
248
277
|
disabled: true,
|
|
249
278
|
});
|
|
@@ -265,8 +294,8 @@ export default {
|
|
|
265
294
|
out,
|
|
266
295
|
namespaces.map((namespace) => {
|
|
267
296
|
return {
|
|
268
|
-
id:
|
|
269
|
-
kind:
|
|
297
|
+
id: `${ NAMESPACE_FILTER_NS_FULL_PREFIX }${ namespace.id }`,
|
|
298
|
+
kind: NAMESPACE_FILTER_KINDS.NAMESPACE,
|
|
270
299
|
label: t('nav.ns.namespace', { name: namespace.nameDisplay }),
|
|
271
300
|
};
|
|
272
301
|
})
|
|
@@ -275,7 +304,7 @@ export default {
|
|
|
275
304
|
|
|
276
305
|
function divider(out) {
|
|
277
306
|
out.push({
|
|
278
|
-
kind:
|
|
307
|
+
kind: NAMESPACE_FILTER_KINDS.DIVIDER,
|
|
279
308
|
label: `Divider ${ out.length }`,
|
|
280
309
|
disabled: true,
|
|
281
310
|
});
|
|
@@ -283,16 +312,14 @@ export default {
|
|
|
283
312
|
},
|
|
284
313
|
|
|
285
314
|
isSingleSpecial() {
|
|
286
|
-
return this.value && this.value.length === 1 && this.value[0].kind ===
|
|
315
|
+
return this.value && this.value.length === 1 && this.value[0].kind === NAMESPACE_FILTER_KINDS.SPECIAL;
|
|
287
316
|
},
|
|
288
317
|
|
|
289
318
|
value: {
|
|
290
319
|
get() {
|
|
291
320
|
// Use last picked filter from user preferences
|
|
292
321
|
const prefs = this.$store.getters['prefs/get'](NAMESPACE_FILTERS);
|
|
293
|
-
|
|
294
|
-
const prefDefault = this.currentProduct?.customNamespaceFilter ? [] : [ALL_USER];
|
|
295
|
-
const values = prefs && prefs[this.key] ? prefs[this.key] : prefDefault;
|
|
322
|
+
const values = prefs && prefs[this.key] ? prefs[this.key] : this.defaultOption();
|
|
296
323
|
const options = this.options;
|
|
297
324
|
|
|
298
325
|
// Remove values that are not valid options
|
|
@@ -311,7 +338,7 @@ export default {
|
|
|
311
338
|
neu = neu.filter(x => !!x.id);
|
|
312
339
|
|
|
313
340
|
const last = neu[neu.length - 1];
|
|
314
|
-
const lastIsSpecial = last?.kind === SPECIAL;
|
|
341
|
+
const lastIsSpecial = last?.kind === NAMESPACE_FILTER_KINDS.SPECIAL;
|
|
315
342
|
const hadUser = !!old.find(x => x.id === ALL_USER);
|
|
316
343
|
const hadAll = !!old.find(x => x.id === ALL);
|
|
317
344
|
|
|
@@ -320,7 +347,7 @@ export default {
|
|
|
320
347
|
}
|
|
321
348
|
|
|
322
349
|
if (neu.length > 1) {
|
|
323
|
-
neu = neu.filter(x => x.kind !== SPECIAL);
|
|
350
|
+
neu = neu.filter(x => x.kind !== NAMESPACE_FILTER_KINDS.SPECIAL);
|
|
324
351
|
}
|
|
325
352
|
|
|
326
353
|
if (neu.find(x => x.id === 'all')) {
|
|
@@ -332,7 +359,7 @@ export default {
|
|
|
332
359
|
// If there was something selected and you remove it, go back to user by default
|
|
333
360
|
// Unless it was user or all
|
|
334
361
|
if (neu.length === 0 && !hadUser && !hadAll) {
|
|
335
|
-
ids = this.
|
|
362
|
+
ids = this.defaultOption();
|
|
336
363
|
} else {
|
|
337
364
|
ids = neu.map(x => x.id);
|
|
338
365
|
}
|
|
@@ -579,28 +606,27 @@ export default {
|
|
|
579
606
|
},
|
|
580
607
|
selectOption(option) {
|
|
581
608
|
// Ignore click for a divider
|
|
582
|
-
if (option.kind ===
|
|
609
|
+
if (option.kind === NAMESPACE_FILTER_KINDS.DIVIDER) {
|
|
583
610
|
return;
|
|
584
611
|
}
|
|
585
612
|
|
|
586
613
|
const current = this.value;
|
|
587
|
-
const exists = current.findIndex(v => v.id === option.id);
|
|
588
|
-
const optionIsSelected = exists !== -1;
|
|
589
614
|
|
|
590
|
-
//
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
615
|
+
// Remove invalid
|
|
616
|
+
if (!!this.namespaceFilterMode?.length) {
|
|
617
|
+
this.value.forEach((v) => {
|
|
618
|
+
if (!this.namespaceFilterMode.find(f => f === v.kind)) {
|
|
619
|
+
const index = current.findIndex(c => c.id === v.id);
|
|
620
|
+
|
|
621
|
+
current.splice(index, 1);
|
|
622
|
+
}
|
|
623
|
+
});
|
|
598
624
|
}
|
|
599
625
|
|
|
600
|
-
const
|
|
626
|
+
const exists = current.findIndex(v => v.id === option.id);
|
|
601
627
|
|
|
602
628
|
// Remove if it exists (or always add if in singleton mode - we've reset the list above)
|
|
603
|
-
if (
|
|
629
|
+
if (exists !== -1) {
|
|
604
630
|
current.splice(exists, 1);
|
|
605
631
|
} else {
|
|
606
632
|
current.push(option);
|
|
@@ -624,13 +650,35 @@ export default {
|
|
|
624
650
|
this.selectOption(ns);
|
|
625
651
|
event.preventDefault();
|
|
626
652
|
event.stopPropagation();
|
|
627
|
-
}
|
|
653
|
+
},
|
|
654
|
+
|
|
655
|
+
defaultOption() {
|
|
656
|
+
// Note - This is one place where a default ns/project filter value is provided (ALL_USER)
|
|
657
|
+
// There's also..
|
|
658
|
+
// - dashboard root store `loadCluster` --> when `updateNamespaces` is dispatched
|
|
659
|
+
// - harvester root store `loadCluster` --> when `updateNamespaces` is dispatched (can be discarded)
|
|
660
|
+
// Due to this, we can't really set a nicer default when forced ns/project filtering is on (ALL_USER is invalid)
|
|
661
|
+
if (this.currentProduct?.customNamespaceFilter) {
|
|
662
|
+
return [];
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
return [ALL_USER];
|
|
666
|
+
},
|
|
667
|
+
|
|
668
|
+
calcNamespaceFilterMode() {
|
|
669
|
+
if (pAndNFiltering.isEnabled(this.$store.getters)) {
|
|
670
|
+
return [NAMESPACE_FILTER_KINDS.NAMESPACE, NAMESPACE_FILTER_KINDS.PROJECT];
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
return null;
|
|
674
|
+
},
|
|
628
675
|
}
|
|
629
676
|
};
|
|
630
677
|
</script>
|
|
631
678
|
|
|
632
679
|
<template>
|
|
633
680
|
<div
|
|
681
|
+
v-if="!$fetchState.pending"
|
|
634
682
|
class="ns-filter"
|
|
635
683
|
data-testid="namespaces-filter"
|
|
636
684
|
tabindex="0"
|
|
@@ -674,7 +722,7 @@ export default {
|
|
|
674
722
|
<div
|
|
675
723
|
v-else
|
|
676
724
|
ref="values"
|
|
677
|
-
v-tooltip="tooltip"
|
|
725
|
+
v-clean-tooltip="tooltip"
|
|
678
726
|
data-testid="namespaces-values"
|
|
679
727
|
class="ns-values"
|
|
680
728
|
>
|
|
@@ -694,8 +742,9 @@ export default {
|
|
|
694
742
|
class="ns-value"
|
|
695
743
|
>
|
|
696
744
|
<div>{{ ns.label }}</div>
|
|
745
|
+
<!-- block user from removing the last selection if ns forced filtering is on -->
|
|
697
746
|
<i
|
|
698
|
-
v-if="!namespaceFilterMode"
|
|
747
|
+
v-if="!namespaceFilterMode || value.length > 1"
|
|
699
748
|
class="icon icon-close"
|
|
700
749
|
:data-testid="`namespaces-values-close-${j}`"
|
|
701
750
|
@click="removeOption(ns, $event)"
|
|
@@ -708,7 +757,7 @@ export default {
|
|
|
708
757
|
<div
|
|
709
758
|
v-if="hidden > 0"
|
|
710
759
|
ref="more"
|
|
711
|
-
v-tooltip="tooltip"
|
|
760
|
+
v-clean-tooltip="tooltip"
|
|
712
761
|
class="ns-more"
|
|
713
762
|
>
|
|
714
763
|
{{ t('namespaceFilter.more', { more: hidden }) }}
|
|
@@ -754,7 +803,7 @@ export default {
|
|
|
754
803
|
class="ns-singleton-info"
|
|
755
804
|
>
|
|
756
805
|
<i
|
|
757
|
-
v-tooltip="t('resourceList.nsFilterToolTip'
|
|
806
|
+
v-clean-tooltip="t('resourceList.nsFilterToolTip')"
|
|
758
807
|
class="icon icon-info"
|
|
759
808
|
/>
|
|
760
809
|
</div>
|
|
@@ -791,7 +840,7 @@ export default {
|
|
|
791
840
|
@keydown="itemKeyHandler($event, opt)"
|
|
792
841
|
>
|
|
793
842
|
<div
|
|
794
|
-
v-if="opt.kind ===
|
|
843
|
+
v-if="opt.kind === NAMESPACE_FILTER_KINDS.DIVIDER"
|
|
795
844
|
class="ns-divider"
|
|
796
845
|
/>
|
|
797
846
|
<div
|
|
@@ -799,7 +848,7 @@ export default {
|
|
|
799
848
|
class="ns-item"
|
|
800
849
|
>
|
|
801
850
|
<i
|
|
802
|
-
v-if="opt.kind ===
|
|
851
|
+
v-if="opt.kind === NAMESPACE_FILTER_KINDS.NAMESPACE"
|
|
803
852
|
class="icon icon-folder"
|
|
804
853
|
/>
|
|
805
854
|
<div>{{ opt.label }}</div>
|
|
@@ -130,11 +130,14 @@ export const ANNOTATIONS_TO_FOLD = [
|
|
|
130
130
|
];
|
|
131
131
|
|
|
132
132
|
export const HCI = {
|
|
133
|
-
CLOUD_INIT:
|
|
134
|
-
CLOUD_PROVIDER_IPAM:
|
|
135
|
-
NETWORK_ROUTE:
|
|
136
|
-
IMAGE_NAME:
|
|
137
|
-
NETWORK_TYPE:
|
|
133
|
+
CLOUD_INIT: 'harvesterhci.io/cloud-init-template',
|
|
134
|
+
CLOUD_PROVIDER_IPAM: 'cloudprovider.harvesterhci.io/ipam',
|
|
135
|
+
NETWORK_ROUTE: 'network.harvesterhci.io/route',
|
|
136
|
+
IMAGE_NAME: 'harvesterhci.io/image-name',
|
|
137
|
+
NETWORK_TYPE: 'network.harvesterhci.io/type',
|
|
138
|
+
CLOUD_PROVIDER_NAMESPACE: 'cloudprovider.harvesterhci.io/namespace',
|
|
139
|
+
CLOUD_PROVIDER_NETWORK: 'cloudprovider.harvesterhci.io/network',
|
|
140
|
+
CLOUD_PROVIDER_PROJECT: 'cloudprovider.harvesterhci.io/project',
|
|
138
141
|
};
|
|
139
142
|
|
|
140
143
|
// Annotations that can be on management.cattle.io.cluster to configure a custom badge
|
package/config/settings.ts
CHANGED
|
@@ -159,9 +159,6 @@ export const DEFAULT_PERF_SETTING = {
|
|
|
159
159
|
},
|
|
160
160
|
disableWebsocketNotification: true,
|
|
161
161
|
garbageCollection: GC_DEFAULTS,
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
threshold: 1500,
|
|
165
|
-
},
|
|
166
|
-
advancedWorker: { enabled: false },
|
|
162
|
+
forceNsFilterV2: { enabled: false },
|
|
163
|
+
advancedWorker: { enabled: false },
|
|
167
164
|
};
|
package/config/types.js
CHANGED
|
@@ -182,6 +182,7 @@ export const MANAGEMENT = {
|
|
|
182
182
|
GLOBAL_ROLE: 'management.cattle.io.globalrole',
|
|
183
183
|
GLOBAL_ROLE_BINDING: 'management.cattle.io.globalrolebinding',
|
|
184
184
|
POD_SECURITY_POLICY_TEMPLATE: 'management.cattle.io.podsecuritypolicytemplate',
|
|
185
|
+
PSP_TEMPLATE_BINDING: 'management.cattle.io.podsecuritypolicytemplateprojectbinding',
|
|
185
186
|
PSA: 'management.cattle.io.podsecurityadmissionconfigurationtemplate',
|
|
186
187
|
MANAGED_CHART: 'management.cattle.io.managedchart',
|
|
187
188
|
USER_NOTIFICATION: 'management.cattle.io.rancherusernotification',
|
|
@@ -285,10 +286,11 @@ export const VIRTUAL_TYPES = {
|
|
|
285
286
|
|
|
286
287
|
// harvester
|
|
287
288
|
export const HCI = {
|
|
288
|
-
CLUSTER:
|
|
289
|
-
DASHBOARD:
|
|
290
|
-
IMAGE:
|
|
291
|
-
SETTING:
|
|
289
|
+
CLUSTER: 'harvesterhci.io.management.cluster',
|
|
290
|
+
DASHBOARD: 'harvesterhci.io.dashboard',
|
|
291
|
+
IMAGE: 'harvesterhci.io.virtualmachineimage',
|
|
292
|
+
SETTING: 'harvesterhci.io.setting',
|
|
293
|
+
HARVESTER_CONFIG: 'rke-machine-config.cattle.io.harvesterconfig',
|
|
292
294
|
};
|
|
293
295
|
|
|
294
296
|
export const VIRTUAL_HARVESTER_PROVIDER = 'harvester';
|
package/core/plugin-routes.ts
CHANGED
|
@@ -153,20 +153,39 @@ export class PluginRoutes {
|
|
|
153
153
|
// Using the existing router and adding routes to it will force nuxt middleware (specifically authenticated on default layout) to
|
|
154
154
|
// execute many times (nuxt middleware boils down to router.beforeEach). This issue was seen refreshing in a harvester cluster with a
|
|
155
155
|
// dynamically loaded cluster
|
|
156
|
-
const newRouter: Router = new Router({
|
|
157
|
-
mode: 'history',
|
|
158
|
-
routes: allRoutes
|
|
159
|
-
});
|
|
160
156
|
|
|
157
|
+
const pluginRoutesWithParents: any[] = [];
|
|
158
|
+
const orderedPluginRoutes: any[] = [];
|
|
159
|
+
|
|
160
|
+
// separate plugin routes that have parent and not
|
|
161
161
|
newRoutes.forEach((r: any) => {
|
|
162
|
+
let foundParentRoute;
|
|
163
|
+
|
|
162
164
|
if (r.parent) {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
165
|
+
foundParentRoute = allRoutes.find(route => route.name === r.parent);
|
|
166
|
+
|
|
167
|
+
if (foundParentRoute) {
|
|
168
|
+
pluginRoutesWithParents.push(r);
|
|
169
|
+
}
|
|
166
170
|
}
|
|
171
|
+
|
|
172
|
+
if (!foundParentRoute) {
|
|
173
|
+
orderedPluginRoutes.push(r.route);
|
|
174
|
+
}
|
|
175
|
+
|
|
167
176
|
this.pluginRoutes.push(r.route);
|
|
168
177
|
});
|
|
169
178
|
|
|
179
|
+
const newRouter: Router = new Router({
|
|
180
|
+
mode: 'history',
|
|
181
|
+
routes: [...orderedPluginRoutes, ...allRoutes]
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
// handle plugin routes with parent
|
|
185
|
+
pluginRoutesWithParents.forEach((r: any) => {
|
|
186
|
+
newRouter.addRoute(r.parent, r.route);
|
|
187
|
+
});
|
|
188
|
+
|
|
170
189
|
// Typing is incorrect
|
|
171
190
|
(this.router as any).matcher = (newRouter as any).matcher;
|
|
172
191
|
}
|
package/core/plugins-loader.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import Vue from 'vue';
|
|
2
|
+
import $ from 'jquery';
|
|
2
3
|
import JSZip from 'jszip';
|
|
3
4
|
import jsyaml from 'js-yaml';
|
|
4
5
|
|
|
@@ -25,6 +26,7 @@ export default function({
|
|
|
25
26
|
window.Vue = Vue;
|
|
26
27
|
|
|
27
28
|
// Global libraries - allows us to externalise these to reduce package bundle size
|
|
29
|
+
window.$ = $;
|
|
28
30
|
window.__jszip = JSZip;
|
|
29
31
|
window.__jsyaml = jsyaml;
|
|
30
32
|
}
|