@rancher/shell 3.0.5-rc.6 → 3.0.5-rc.8
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/brand/classic/metadata.json +3 -0
- package/assets/styles/app.scss +1 -0
- package/assets/styles/base/_color.scss +16 -0
- package/assets/styles/base/_helpers.scss +10 -0
- package/assets/styles/base/_variables.scss +18 -12
- package/assets/styles/fonts/_icons.scss +1 -32
- package/assets/styles/global/_layout.scss +1 -1
- package/assets/styles/themes/_dark.scss +262 -258
- package/assets/styles/themes/_light.scss +538 -509
- package/assets/styles/themes/_modern.scss +914 -0
- package/assets/translations/en-us.yaml +110 -29
- package/chart/__tests__/S3.test.ts +2 -1
- package/cloud-credential/generic.vue +18 -10
- package/cloud-credential/harvester.vue +1 -9
- package/components/AdvancedSection.vue +8 -0
- package/components/ChartReadme.vue +17 -7
- package/components/CodeMirror.vue +1 -1
- package/components/Drawer/Chrome.vue +0 -1
- package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +27 -28
- package/components/Drawer/ResourceDetailDrawer/composables.ts +4 -24
- package/components/Drawer/ResourceDetailDrawer/index.vue +18 -4
- package/components/InstallHelmCharts.vue +656 -0
- package/components/LazyImage.vue +60 -4
- package/components/Loading.vue +1 -1
- package/components/LocaleSelector.vue +7 -2
- package/components/Markdown.vue +4 -0
- package/components/PaginatedResourceTable.vue +46 -1
- package/components/PromptRestore.vue +22 -44
- package/components/Resource/Detail/Masthead/composable.ts +16 -0
- package/components/Resource/Detail/Masthead/index.vue +37 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +10 -2
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +26 -7
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +8 -1
- package/components/Resource/Detail/Metadata/KeyValue.vue +12 -10
- package/components/Resource/Detail/Metadata/Rectangle.vue +3 -1
- package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +10 -17
- package/components/Resource/Detail/Metadata/composables.ts +9 -7
- package/components/Resource/Detail/Metadata/index.vue +17 -2
- package/components/Resource/Detail/Page.vue +35 -21
- package/components/Resource/Detail/SpacedRow.vue +1 -1
- package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +8 -9
- package/components/Resource/Detail/TitleBar/composables.ts +5 -5
- package/components/Resource/Detail/TitleBar/index.vue +12 -3
- package/components/ResourceDetail/Masthead/legacy.vue +1 -1
- package/components/ResourceDetail/index.vue +569 -72
- package/components/ResourceList/index.vue +1 -0
- package/components/ResourceTable.vue +6 -1
- package/components/ResourceYaml.vue +1 -1
- package/components/RichTranslation.vue +106 -0
- package/components/SlideInPanelManager.vue +13 -10
- package/components/SortableTable/index.vue +5 -5
- package/components/SortableTable/selection.js +0 -1
- package/components/Tabbed/index.vue +35 -4
- package/components/__tests__/LazyImage.spec.ts +121 -0
- package/components/__tests__/PromptRestore.test.ts +1 -65
- package/components/__tests__/RichTranslation.test.ts +115 -0
- package/components/fleet/FleetStatus.vue +4 -0
- package/components/fleet/dashboard/ResourcePanel.vue +2 -1
- package/components/form/ClusterAppearance.vue +5 -0
- package/components/form/FileImageSelector.vue +1 -1
- package/components/form/Members/ClusterPermissionsEditor.vue +1 -1
- package/components/form/NameNsDescription.vue +1 -0
- package/components/form/Networking.vue +24 -19
- package/components/form/ProjectMemberEditor.vue +1 -1
- package/components/form/ResourceLabeledSelect.vue +22 -8
- package/components/form/ResourceTabs/index.vue +20 -0
- package/components/form/SecretSelector.vue +9 -0
- package/components/form/SelectOrCreateAuthSecret.vue +6 -3
- package/components/form/__tests__/Networking.test.ts +116 -0
- package/components/form/labeled-select-utils/labeled-select-pagination.ts +3 -38
- package/components/formatter/FleetApplicationSource.vue +25 -17
- package/components/formatter/PodImages.vue +1 -1
- package/components/formatter/__tests__/LiveDate.test.ts +10 -2
- package/components/google/AccountAccess.vue +44 -46
- package/components/nav/Favorite.vue +4 -0
- package/components/nav/Group.vue +4 -1
- package/components/nav/NotificationCenter/Notification.vue +1 -27
- package/components/nav/WindowManager/index.vue +3 -3
- package/composables/resources.ts +2 -2
- package/config/labels-annotations.js +3 -2
- package/config/pagination-table-headers.js +8 -1
- package/config/product/explorer.js +27 -2
- package/config/product/manager.js +0 -1
- package/config/query-params.js +10 -0
- package/config/router/routes.js +21 -1
- package/config/system-namespaces.js +1 -1
- package/config/table-headers.js +30 -1
- package/config/types.js +1 -1
- package/config/version.js +1 -1
- package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +11 -0
- package/detail/__tests__/workload.test.ts +164 -0
- package/detail/configmap.vue +33 -75
- package/detail/projectsecret.vue +11 -0
- package/detail/provisioning.cattle.io.cluster.vue +351 -369
- package/detail/secret.vue +49 -308
- package/detail/workload/index.vue +38 -21
- package/dialog/InstallExtensionDialog.vue +8 -5
- package/dialog/RotateEncryptionKeyDialog.vue +10 -30
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
- package/edit/auth/ldap/__tests__/config.test.ts +14 -0
- package/edit/auth/ldap/config.vue +24 -0
- package/edit/compliance.cattle.io.clusterscan.vue +1 -1
- package/edit/configmap.vue +4 -1
- package/edit/fleet.cattle.io.gitrepo.vue +5 -6
- package/edit/fleet.cattle.io.helmop.vue +78 -56
- package/edit/logging.banzaicloud.io.output/index.vue +1 -1
- package/edit/logging.banzaicloud.io.output/providers/awsElasticsearch.vue +5 -6
- package/edit/networking.k8s.io.ingress/Certificate.vue +20 -22
- package/edit/networking.k8s.io.ingress/DefaultBackend.vue +8 -3
- package/edit/networking.k8s.io.ingress/Rule.vue +2 -5
- package/edit/networking.k8s.io.ingress/RulePath.vue +17 -11
- package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +165 -0
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +11 -10
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -3
- package/edit/networking.k8s.io.networkpolicy/index.vue +17 -17
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +3 -2
- package/edit/provisioning.cattle.io.cluster/rke2.vue +123 -61
- package/edit/provisioning.cattle.io.cluster/tabs/AgentConfiguration.vue +9 -7
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +22 -13
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +10 -12
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +39 -38
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +41 -19
- package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +16 -3
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +32 -33
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryMirrors.vue +9 -10
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +1 -3
- package/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue +16 -9
- package/edit/secret/basic.vue +1 -0
- package/edit/secret/index.vue +126 -15
- package/edit/workload/index.vue +5 -14
- package/list/projectsecret.vue +345 -0
- package/list/provisioning.cattle.io.cluster.vue +1 -69
- package/list/secret.vue +109 -0
- package/machine-config/__tests__/vmwarevsphere.test.ts +5 -7
- package/machine-config/google.vue +9 -1
- package/machine-config/vmwarevsphere.vue +7 -17
- package/mixins/__tests__/brand.spec.ts +2 -2
- package/mixins/chart.js +0 -2
- package/mixins/create-edit-view/impl.js +10 -1
- package/mixins/resource-fetch-api-pagination.js +11 -12
- package/mixins/resource-fetch.js +3 -1
- package/models/__tests__/chart.test.ts +111 -80
- package/models/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
- package/models/__tests__/node.test.ts +7 -63
- package/models/catalog.cattle.io.app.js +1 -1
- package/models/catalog.cattle.io.operation.js +1 -1
- package/models/chart.js +36 -20
- package/models/cloudcredential.js +2 -163
- package/models/cluster/node.js +7 -7
- package/models/cluster.x-k8s.io.machine.js +3 -3
- package/models/cluster.x-k8s.io.machinedeployment.js +11 -2
- package/models/compliance.cattle.io.clusterscan.js +2 -2
- package/models/configmap.js +4 -0
- package/models/constraints.gatekeeper.sh.constraint.js +1 -1
- package/models/fleet-application.js +0 -17
- package/models/fleet.cattle.io.cluster.js +2 -2
- package/models/fleet.cattle.io.gitrepo.js +15 -1
- package/models/fleet.cattle.io.helmop.js +26 -22
- package/models/management.cattle.io.setting.js +4 -0
- package/models/persistentvolumeclaim.js +1 -1
- package/models/pod.js +2 -2
- package/models/provisioning.cattle.io.cluster.js +39 -67
- package/models/rke.cattle.io.etcdsnapshot.js +1 -1
- package/models/secret.js +161 -2
- package/models/storage.k8s.io.storageclass.js +2 -2
- package/models/workload.js +3 -3
- package/package.json +11 -10
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +1 -0
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +4 -1
- package/pages/c/_cluster/apps/charts/__tests__/AppChartCardFooter.spec.js +41 -0
- package/pages/c/_cluster/apps/charts/chart.vue +422 -174
- package/pages/c/_cluster/apps/charts/index.vue +46 -35
- package/pages/c/_cluster/apps/charts/install.vue +1 -1
- package/pages/c/_cluster/explorer/projectsecret.vue +24 -0
- package/pages/c/_cluster/fleet/__tests__/index.test.ts +608 -314
- package/pages/c/_cluster/fleet/index.vue +103 -45
- package/pages/c/_cluster/manager/cloudCredential/index.vue +2 -59
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +10 -3
- package/pages/c/_cluster/uiplugins/index.vue +36 -25
- package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
- package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
- package/plugins/dashboard-store/actions.js +42 -22
- package/plugins/dashboard-store/normalize.js +29 -17
- package/plugins/dashboard-store/resource-class.js +83 -17
- package/plugins/steve/__tests__/getters.test.ts +1 -1
- package/plugins/steve/__tests__/subscribe.spec.ts +259 -1
- package/plugins/steve/getters.js +8 -2
- package/plugins/steve/resourceWatcher.js +10 -3
- package/plugins/steve/steve-pagination-utils.ts +14 -3
- package/plugins/steve/subscribe.js +192 -19
- package/plugins/steve/worker/web-worker.advanced.js +2 -0
- package/rancher-components/Card/Card.vue +0 -18
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.test.ts +15 -0
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +65 -0
- package/rancher-components/Pill/RcStatusBadge/index.ts +2 -0
- package/rancher-components/Pill/RcStatusBadge/types.ts +5 -0
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.test.ts +33 -0
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +75 -0
- package/rancher-components/Pill/RcStatusIndicator/index.ts +2 -0
- package/rancher-components/Pill/RcStatusIndicator/types.ts +7 -0
- package/rancher-components/Pill/types.ts +2 -0
- package/rancher-components/RcButton/RcButton.vue +1 -1
- package/rancher-components/RcDropdown/RcDropdown.test.ts +98 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +5 -0
- package/rancher-components/RcDropdown/RcDropdownItem.vue +7 -1
- package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +2 -1
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +2 -1
- package/rancher-components/RcDropdown/useDropdownContext.ts +21 -0
- package/rancher-components/RcDropdown/useDropdownItem.ts +30 -1
- package/rancher-components/RcItemCard/RcItemCard.test.ts +20 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +40 -6
- package/store/__tests__/catalog.test.ts +93 -1
- package/store/aws.js +19 -8
- package/store/catalog.js +8 -3
- package/types/kube/kube-api.ts +12 -0
- package/types/resources/settings.d.ts +1 -1
- package/types/shell/index.d.ts +643 -585
- package/types/store/pagination.types.ts +16 -6
- package/types/uiplugins.ts +73 -0
- package/utils/__tests__/back-off.test.ts +354 -0
- package/utils/__tests__/create-yaml.test.ts +235 -0
- package/utils/__tests__/kontainer.test.ts +19 -0
- package/utils/__tests__/uiplugins.test.ts +84 -0
- package/utils/back-off.ts +176 -0
- package/utils/create-yaml.js +103 -9
- package/utils/dynamic-importer.js +8 -0
- package/utils/kontainer.ts +3 -5
- package/utils/pagination-utils.ts +18 -0
- package/utils/style.ts +3 -0
- package/utils/uiplugins.ts +29 -2
- package/utils/validators/__tests__/setting.test.js +92 -0
- package/utils/validators/formRules/__tests__/index.test.ts +88 -7
- package/utils/validators/formRules/index.ts +83 -8
- package/utils/validators/setting.js +17 -0
- package/cloud-credential/__tests__/harvester.test.ts +0 -18
- package/components/ResourceDetail/__tests__/index.test.ts +0 -135
- package/components/ResourceDetail/legacy.vue +0 -562
- package/components/formatter/CloudCredExpired.vue +0 -69
- package/models/etcdbackup.js +0 -45
- package/pages/explorer/resource/detail/configmap.vue +0 -42
- package/pages/explorer/resource/detail/secret.vue +0 -50
- package/utils/aws.js +0 -0
|
@@ -337,7 +337,8 @@ export default {
|
|
|
337
337
|
}
|
|
338
338
|
|
|
339
339
|
&.bg-error {
|
|
340
|
-
background: var(--click-badge-error-bg);
|
|
340
|
+
// background: var(--click-badge-error-bg); TODO revert after dashboard theme colors refactoring
|
|
341
|
+
background: var(--error);
|
|
341
342
|
color: var(--click-badge-error);
|
|
342
343
|
}
|
|
343
344
|
|
|
@@ -75,6 +75,7 @@ export default {
|
|
|
75
75
|
<button
|
|
76
76
|
:disabled="disable"
|
|
77
77
|
@click="customBadgeDialog"
|
|
78
|
+
@keydown.enter.space.prevent="customBadgeDialog"
|
|
78
79
|
>
|
|
79
80
|
<i class="icon icon-brush-icon" />
|
|
80
81
|
<span>
|
|
@@ -118,6 +119,10 @@ export default {
|
|
|
118
119
|
color: var(--link);
|
|
119
120
|
background: transparent;
|
|
120
121
|
|
|
122
|
+
&:focus-visible {
|
|
123
|
+
@include focus-outline;
|
|
124
|
+
}
|
|
125
|
+
|
|
121
126
|
i {
|
|
122
127
|
margin-right: 2px;
|
|
123
128
|
}
|
|
@@ -31,28 +31,23 @@ export default {
|
|
|
31
31
|
const t = this.$store.getters['i18n/t'];
|
|
32
32
|
|
|
33
33
|
return {
|
|
34
|
-
dnsPolicy:
|
|
35
|
-
networkMode:
|
|
36
|
-
|
|
37
|
-
nameservers:
|
|
38
|
-
searches:
|
|
39
|
-
hostname:
|
|
40
|
-
subdomain:
|
|
41
|
-
options:
|
|
34
|
+
dnsPolicy: this.value.dnsPolicy || 'ClusterFirst',
|
|
35
|
+
networkMode: this.value.hostNetwork ? { label: t('workload.networking.networkMode.options.hostNetwork'), value: true } : { label: t('workload.networking.networkMode.options.normal'), value: false },
|
|
36
|
+
tmpHostAliases: [],
|
|
37
|
+
nameservers: null,
|
|
38
|
+
searches: null,
|
|
39
|
+
hostname: null,
|
|
40
|
+
subdomain: null,
|
|
41
|
+
options: null,
|
|
42
42
|
};
|
|
43
43
|
},
|
|
44
44
|
|
|
45
45
|
created() {
|
|
46
|
-
const hostAliases =
|
|
47
|
-
return {
|
|
48
|
-
ip: entry.ip,
|
|
49
|
-
hostnames: entry.hostnames.join(', ')
|
|
50
|
-
};
|
|
51
|
-
});
|
|
46
|
+
const hostAliases = this.value.hostAliases || [];
|
|
52
47
|
const { dnsConfig = {}, hostname, subdomain } = this.value;
|
|
53
48
|
const { nameservers, searches, options } = dnsConfig;
|
|
54
49
|
|
|
55
|
-
this.
|
|
50
|
+
this.tmpHostAliases = hostAliases;
|
|
56
51
|
this.nameservers = nameservers;
|
|
57
52
|
this.searches = searches;
|
|
58
53
|
this.hostname = hostname;
|
|
@@ -89,6 +84,15 @@ export default {
|
|
|
89
84
|
];
|
|
90
85
|
},
|
|
91
86
|
|
|
87
|
+
hostAliases() {
|
|
88
|
+
return (this.value.hostAliases || []).map((entry) => {
|
|
89
|
+
return {
|
|
90
|
+
ip: entry.ip,
|
|
91
|
+
hostnames: entry.hostnames?.join(', ') ?? ''
|
|
92
|
+
};
|
|
93
|
+
});
|
|
94
|
+
},
|
|
95
|
+
|
|
92
96
|
...mapGetters({ t: 'i18n/t' })
|
|
93
97
|
},
|
|
94
98
|
|
|
@@ -121,12 +125,12 @@ export default {
|
|
|
121
125
|
|
|
122
126
|
methods: {
|
|
123
127
|
updateHostAliases(neu) {
|
|
124
|
-
this.
|
|
128
|
+
this.tmpHostAliases = neu.map((entry) => {
|
|
125
129
|
const ip = entry.ip.trim();
|
|
126
130
|
const hostnames = entry.hostnames.trim().split(/[\s,]+/).filter((x) => !!x);
|
|
127
131
|
|
|
128
132
|
return { ip, hostnames };
|
|
129
|
-
})
|
|
133
|
+
});
|
|
130
134
|
this.update();
|
|
131
135
|
},
|
|
132
136
|
|
|
@@ -142,7 +146,7 @@ export default {
|
|
|
142
146
|
dnsConfig,
|
|
143
147
|
dnsPolicy: this.dnsPolicy,
|
|
144
148
|
hostname: this.hostname,
|
|
145
|
-
hostAliases: this.
|
|
149
|
+
hostAliases: this.tmpHostAliases,
|
|
146
150
|
subdomain: this.subdomain,
|
|
147
151
|
hostNetwork: this.networkMode.value
|
|
148
152
|
};
|
|
@@ -256,7 +260,8 @@ export default {
|
|
|
256
260
|
<div class="col span-12">
|
|
257
261
|
<KeyValue
|
|
258
262
|
key="hostAliases"
|
|
259
|
-
|
|
263
|
+
data-test="hostAliases"
|
|
264
|
+
:value="hostAliases"
|
|
260
265
|
:mode="mode"
|
|
261
266
|
:title="t('workload.networking.hostAliases.label')"
|
|
262
267
|
:protip="t('workload.networking.hostAliases.tip')"
|
|
@@ -34,7 +34,7 @@ export default defineComponent({
|
|
|
34
34
|
|
|
35
35
|
inStore: {
|
|
36
36
|
type: String,
|
|
37
|
-
default:
|
|
37
|
+
default: undefined,
|
|
38
38
|
},
|
|
39
39
|
|
|
40
40
|
/**
|
|
@@ -63,7 +63,20 @@ export default defineComponent({
|
|
|
63
63
|
},
|
|
64
64
|
|
|
65
65
|
data() {
|
|
66
|
-
|
|
66
|
+
let validInStore = this.inStore;
|
|
67
|
+
|
|
68
|
+
if (!validInStore && this.resourceType) {
|
|
69
|
+
validInStore = this.$store.getters['currentStore'](this.resourceType);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (!validInStore) {
|
|
73
|
+
validInStore = 'cluster';
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
paginate: false,
|
|
78
|
+
validInStore,
|
|
79
|
+
};
|
|
67
80
|
},
|
|
68
81
|
|
|
69
82
|
async fetch() {
|
|
@@ -72,13 +85,13 @@ export default defineComponent({
|
|
|
72
85
|
this.paginate = false;
|
|
73
86
|
break;
|
|
74
87
|
case RESOURCE_LABEL_SELECT_MODE.DYNAMIC:
|
|
75
|
-
this.paginate = this.$store.getters[`${ this.
|
|
88
|
+
this.paginate = this.$store.getters[`${ this.validInStore }/paginationEnabled`](this.resourceType);
|
|
76
89
|
break;
|
|
77
90
|
}
|
|
78
91
|
|
|
79
92
|
if (!this.paginate) {
|
|
80
93
|
// The resource won't be paginated and component expects everything up front
|
|
81
|
-
await this.$store.dispatch(`${ this.
|
|
94
|
+
await this.$store.dispatch(`${ this.validInStore }/findAll`, { type: this.resourceType });
|
|
82
95
|
}
|
|
83
96
|
},
|
|
84
97
|
|
|
@@ -104,7 +117,7 @@ export default defineComponent({
|
|
|
104
117
|
return [];
|
|
105
118
|
}
|
|
106
119
|
|
|
107
|
-
const all = this.$store.getters[`${ this.
|
|
120
|
+
const all = this.$store.getters[`${ this.validInStore }/all`](this.resourceType);
|
|
108
121
|
|
|
109
122
|
return this.allResourcesSettings?.updateResources ? this.allResourcesSettings.updateResources(all) : all;
|
|
110
123
|
}
|
|
@@ -127,9 +140,10 @@ export default defineComponent({
|
|
|
127
140
|
const defaultOptions: LabelSelectPaginationFunctionOptions = {
|
|
128
141
|
opts,
|
|
129
142
|
filters,
|
|
130
|
-
type:
|
|
131
|
-
ctx:
|
|
132
|
-
sort:
|
|
143
|
+
type: this.resourceType,
|
|
144
|
+
ctx: { getters: this.$store.getters, dispatch: this.$store.dispatch },
|
|
145
|
+
sort: [{ asc: true, field: 'metadata.name' }],
|
|
146
|
+
store: this.validInStore
|
|
133
147
|
};
|
|
134
148
|
const options = this.paginatedResourceSettings?.requestSettings ? this.paginatedResourceSettings.requestSettings(defaultOptions) : defaultOptions;
|
|
135
149
|
const res = await labelSelectPaginationFunction(options);
|
|
@@ -234,6 +234,8 @@ export default {
|
|
|
234
234
|
|
|
235
235
|
<template>
|
|
236
236
|
<Tabbed
|
|
237
|
+
class="resource-tabs"
|
|
238
|
+
:class="{[mode]: true}"
|
|
237
239
|
v-bind="$attrs"
|
|
238
240
|
:default-tab="defaultTab"
|
|
239
241
|
:resource="value"
|
|
@@ -296,3 +298,21 @@ export default {
|
|
|
296
298
|
</Tab>
|
|
297
299
|
</Tabbed>
|
|
298
300
|
</template>
|
|
301
|
+
|
|
302
|
+
<style lang="scss" scoped>
|
|
303
|
+
.resource-tabs {
|
|
304
|
+
// For the time being we're only targeting detail pages for the new styling. Remove this if we want this style to apply to all pages.
|
|
305
|
+
&.view {
|
|
306
|
+
:deep() .tabs.horizontal {
|
|
307
|
+
border: none;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
:deep() .tabs.horizontal + .tab-container {
|
|
311
|
+
border: none;
|
|
312
|
+
border-top: 1px solid var(--border);
|
|
313
|
+
padding: 0;
|
|
314
|
+
padding-top: 24px;
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
</style>
|
|
@@ -138,6 +138,13 @@ export default {
|
|
|
138
138
|
}
|
|
139
139
|
},
|
|
140
140
|
|
|
141
|
+
watch: {
|
|
142
|
+
namespace() {
|
|
143
|
+
// Namespace has changed, reset the selections
|
|
144
|
+
this.$emit('update:value', { [this.mountKey]: { secretKeyRef: { [this.nameKey]: undefined, [this.keyKey]: '' } } });
|
|
145
|
+
}
|
|
146
|
+
},
|
|
147
|
+
|
|
141
148
|
methods: {
|
|
142
149
|
/**
|
|
143
150
|
* Provide a set of options for the LabelSelect ([none, ...{label, value}])
|
|
@@ -208,6 +215,7 @@ export default {
|
|
|
208
215
|
<div class="input-container">
|
|
209
216
|
<!-- key by namespace to ensure label select current page is recreated on ns change -->
|
|
210
217
|
<ResourceLabeledSelect
|
|
218
|
+
:key="namespace"
|
|
211
219
|
v-model:value="name"
|
|
212
220
|
:disabled="!isView && disabled"
|
|
213
221
|
:label="secretNameLabel"
|
|
@@ -219,6 +227,7 @@ export default {
|
|
|
219
227
|
/>
|
|
220
228
|
<LabeledSelect
|
|
221
229
|
v-if="showKeySelector"
|
|
230
|
+
:key="namespace"
|
|
222
231
|
v-model:value="key"
|
|
223
232
|
class="col span-6"
|
|
224
233
|
:disabled="isKeyDisabled"
|
|
@@ -237,7 +237,7 @@ export default {
|
|
|
237
237
|
let filteredSecrets = [];
|
|
238
238
|
|
|
239
239
|
if (this.allSecrets) {
|
|
240
|
-
//
|
|
240
|
+
// Filter secrets given their namespace and required secret type
|
|
241
241
|
filteredSecrets = this.allSecrets
|
|
242
242
|
.filter((x) => this.filterByNamespace ? x.metadata.namespace === this.namespace : true
|
|
243
243
|
)
|
|
@@ -450,6 +450,7 @@ export default {
|
|
|
450
450
|
),
|
|
451
451
|
],
|
|
452
452
|
}),
|
|
453
|
+
watch: this.cacheSecrets,
|
|
453
454
|
};
|
|
454
455
|
|
|
455
456
|
if (this.cacheSecrets) {
|
|
@@ -464,9 +465,11 @@ export default {
|
|
|
464
465
|
null,
|
|
465
466
|
findPageArgs
|
|
466
467
|
);
|
|
467
|
-
|
|
468
|
+
// Strictly speaking this could be any store (request action should be agnostic)
|
|
469
|
+
const res = await this.$store.dispatch(`${ this.inStore }/request`, { url });
|
|
468
470
|
|
|
469
|
-
|
|
471
|
+
// Classify
|
|
472
|
+
return await this.$store.dispatch(`${ this.inStore }/createMany`, res?.data || []);
|
|
470
473
|
},
|
|
471
474
|
|
|
472
475
|
updateKeyVal() {
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
import Networking from '@shell/components/form/Networking.vue';
|
|
3
|
+
import { nextTick } from 'vue';
|
|
4
|
+
|
|
5
|
+
jest.mock('lodash/debounce', () => jest.fn((fn) => fn));
|
|
6
|
+
|
|
7
|
+
describe('component: Networking', () => {
|
|
8
|
+
it.each([
|
|
9
|
+
{
|
|
10
|
+
ip: '10.1.1.1',
|
|
11
|
+
hostnames: ['host1']
|
|
12
|
+
},
|
|
13
|
+
{
|
|
14
|
+
ip: '10.1.1.2',
|
|
15
|
+
hostnames: ['host1', 'host2']
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
ip: '10.1.1.3',
|
|
19
|
+
hostnames: []
|
|
20
|
+
}
|
|
21
|
+
])('should render host aliases form if the value contains host aliases config: [%j]', (hostAliasesConfig) => {
|
|
22
|
+
const wrapper = mount(Networking, {
|
|
23
|
+
props: {
|
|
24
|
+
value: { hostAliases: [hostAliasesConfig] },
|
|
25
|
+
mode: 'create',
|
|
26
|
+
},
|
|
27
|
+
global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
|
|
31
|
+
const keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
|
|
32
|
+
const valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
|
|
33
|
+
|
|
34
|
+
expect(keyInput.element.value).toBe(hostAliasesConfig.ip);
|
|
35
|
+
expect(valueInput.find('[data-testid="value-multiline"]').element.value).toBe(hostAliasesConfig.hostnames.join(', '));
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it('should not render host aliases form, if there is no host aliases configuration', async() => {
|
|
39
|
+
const wrapper = mount(Networking, {
|
|
40
|
+
props: {
|
|
41
|
+
value: {},
|
|
42
|
+
'onUpdate:value': (e) => wrapper.setProps({ value: e }),
|
|
43
|
+
mode: 'create',
|
|
44
|
+
},
|
|
45
|
+
global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
|
|
49
|
+
const keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
|
|
50
|
+
const valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
|
|
51
|
+
|
|
52
|
+
expect(keyInput.exists()).toBe(false);
|
|
53
|
+
expect(valueInput.exists()).toBe(false);
|
|
54
|
+
expect(wrapper.props('value')).toStrictEqual({});
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('should render host aliases form correctly if click add host aliases button', async() => {
|
|
58
|
+
const wrapper = mount(Networking, {
|
|
59
|
+
props: {
|
|
60
|
+
value: {},
|
|
61
|
+
'onUpdate:value': (e) => wrapper.setProps({ value: e }),
|
|
62
|
+
mode: 'create',
|
|
63
|
+
},
|
|
64
|
+
global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
|
|
68
|
+
const addButton = hostAliases.find('[data-testid="add_row_item_button"]');
|
|
69
|
+
|
|
70
|
+
addButton.trigger('click');
|
|
71
|
+
await nextTick();
|
|
72
|
+
|
|
73
|
+
const keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
|
|
74
|
+
const valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
|
|
75
|
+
const v = wrapper.props('value');
|
|
76
|
+
|
|
77
|
+
expect(keyInput.exists()).toBe(true);
|
|
78
|
+
expect(valueInput.exists()).toBe(true);
|
|
79
|
+
expect(v.hostAliases).toHaveLength(1);
|
|
80
|
+
expect(v.hostAliases[0].ip).toBe('');
|
|
81
|
+
expect(v.hostAliases[0].hostnames).toStrictEqual([]);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
it('should render host aliases form correctly if modify the form values', async() => {
|
|
85
|
+
const wrapper = mount(Networking, {
|
|
86
|
+
props: {
|
|
87
|
+
value: {},
|
|
88
|
+
'onUpdate:value': (e) => wrapper.setProps({ value: e }),
|
|
89
|
+
mode: 'create',
|
|
90
|
+
},
|
|
91
|
+
global: { mocks: { $store: { getters: { 'i18n/t': jest.fn() } } } }
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
const hostAliases = wrapper.findComponent('[data-test="hostAliases"]');
|
|
95
|
+
const addButton = hostAliases.find('[data-testid="add_row_item_button"]');
|
|
96
|
+
|
|
97
|
+
addButton.trigger('click');
|
|
98
|
+
await nextTick();
|
|
99
|
+
let v = wrapper.props('value');
|
|
100
|
+
let keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
|
|
101
|
+
let valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
|
|
102
|
+
|
|
103
|
+
keyInput.setValue('10.1.1.1');
|
|
104
|
+
valueInput.find('[data-testid="value-multiline"]').setValue('test1, test2');
|
|
105
|
+
await nextTick();
|
|
106
|
+
v = wrapper.props('value');
|
|
107
|
+
keyInput = hostAliases.find('[data-testid="input-kv-item-key-0"]');
|
|
108
|
+
valueInput = hostAliases.find('[data-testid="kv-item-value-0"]');
|
|
109
|
+
|
|
110
|
+
expect(v.hostAliases).toHaveLength(1);
|
|
111
|
+
expect(v.hostAliases[0].ip).toBe('10.1.1.1');
|
|
112
|
+
expect(v.hostAliases[0].hostnames).toStrictEqual(['test1', 'test2']);
|
|
113
|
+
expect(keyInput.exists()).toBe(true);
|
|
114
|
+
expect(valueInput.exists()).toBe(true);
|
|
115
|
+
});
|
|
116
|
+
});
|
|
@@ -1,46 +1,11 @@
|
|
|
1
1
|
import { debounce } from 'lodash';
|
|
2
2
|
import { PropType, defineComponent } from 'vue';
|
|
3
|
-
import { ComputedOptions, MethodOptions } from 'vue/types/v3-component-options';
|
|
4
3
|
import { LabelSelectPaginateFn, LABEL_SELECT_NOT_OPTION_KINDS, LABEL_SELECT_KINDS } from '@shell/types/components/labeledSelect';
|
|
5
4
|
|
|
6
|
-
interface Props {
|
|
7
|
-
paginate?: LabelSelectPaginateFn
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
interface Data {
|
|
11
|
-
currentPage: number,
|
|
12
|
-
search: string,
|
|
13
|
-
pageSize: number,
|
|
14
|
-
|
|
15
|
-
page: any[],
|
|
16
|
-
pages: number,
|
|
17
|
-
totalResults: number,
|
|
18
|
-
|
|
19
|
-
paginating: boolean,
|
|
20
|
-
|
|
21
|
-
debouncedRequestPagination: Function
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
interface Computed extends ComputedOptions {
|
|
25
|
-
canPaginate: () => boolean,
|
|
26
|
-
|
|
27
|
-
canLoadMore: () => boolean,
|
|
28
|
-
|
|
29
|
-
optionsInPage: () => number,
|
|
30
|
-
|
|
31
|
-
optionCounts: () => string,
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
interface Methods extends MethodOptions {
|
|
35
|
-
loadMore: () => void
|
|
36
|
-
setPaginationFilter: (filter: string) => void
|
|
37
|
-
requestPagination: () => Promise<any>;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
5
|
/**
|
|
41
6
|
* 'mixin' to provide pagination support to LabeledSelect
|
|
42
7
|
*/
|
|
43
|
-
export default defineComponent
|
|
8
|
+
export default defineComponent({
|
|
44
9
|
props: {
|
|
45
10
|
paginate: {
|
|
46
11
|
default: null,
|
|
@@ -61,7 +26,7 @@ export default defineComponent<Props, any, Data, Computed, Methods>({
|
|
|
61
26
|
},
|
|
62
27
|
},
|
|
63
28
|
|
|
64
|
-
data()
|
|
29
|
+
data() {
|
|
65
30
|
return {
|
|
66
31
|
// Internal
|
|
67
32
|
currentPage: 1,
|
|
@@ -72,7 +37,7 @@ export default defineComponent<Props, any, Data, Computed, Methods>({
|
|
|
72
37
|
debouncedRequestPagination: debounce(this.requestPagination, 700),
|
|
73
38
|
|
|
74
39
|
// External
|
|
75
|
-
page: [],
|
|
40
|
+
page: [] as any[],
|
|
76
41
|
totalResults: 0,
|
|
77
42
|
paginating: false,
|
|
78
43
|
};
|
|
@@ -40,32 +40,40 @@ export default {
|
|
|
40
40
|
</script>
|
|
41
41
|
|
|
42
42
|
<template>
|
|
43
|
-
<template v-if="row.source.
|
|
43
|
+
<template v-if="row.source.value">
|
|
44
44
|
<Link
|
|
45
|
+
v-if="row.source.showLink"
|
|
45
46
|
class="source-link"
|
|
46
47
|
label-key="source.display"
|
|
47
48
|
before-icon-key="source.icon"
|
|
48
49
|
url-key="source.value"
|
|
49
50
|
:row="row"
|
|
50
|
-
:value="row.source.value
|
|
51
|
+
:value="row.source.value"
|
|
51
52
|
/>
|
|
52
|
-
<
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
<span v-else>
|
|
54
|
+
{{ row.source.value }}
|
|
55
|
+
</span>
|
|
56
|
+
<div
|
|
57
|
+
v-if="row.sourceSub.value"
|
|
58
|
+
class="text-label"
|
|
59
|
+
>
|
|
60
|
+
<Shortened
|
|
61
|
+
long-value-key="sourceSub.value"
|
|
62
|
+
:row="row"
|
|
63
|
+
:value="row.sourceSub.display"
|
|
64
|
+
/>
|
|
65
|
+
</div>
|
|
61
66
|
</template>
|
|
62
|
-
<
|
|
63
|
-
|
|
64
|
-
|
|
67
|
+
<div
|
|
68
|
+
v-else
|
|
69
|
+
class="text-muted"
|
|
70
|
+
>
|
|
71
|
+
—
|
|
72
|
+
</div>
|
|
65
73
|
</template>
|
|
66
74
|
|
|
67
75
|
<style lang="scss" scoped>
|
|
68
|
-
.source-link {
|
|
69
|
-
|
|
70
|
-
}
|
|
76
|
+
.source-link {
|
|
77
|
+
width: fit-content;
|
|
78
|
+
}
|
|
71
79
|
</style>
|
|
@@ -16,6 +16,15 @@ const defaultMock = {
|
|
|
16
16
|
};
|
|
17
17
|
|
|
18
18
|
describe('component: LiveDate', () => {
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
jest.useFakeTimers();
|
|
21
|
+
jest.setSystemTime(new Date('2025-07-10T10:00:00.000Z'));
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
afterEach(() => {
|
|
25
|
+
jest.useRealTimers();
|
|
26
|
+
});
|
|
27
|
+
|
|
19
28
|
it('should show a dash if no date is provided', () => {
|
|
20
29
|
const wrapper = mount(LiveDate as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>, { global: { mocks: defaultMock } });
|
|
21
30
|
const element = wrapper.find('span');
|
|
@@ -55,8 +64,7 @@ describe('component: LiveDate', () => {
|
|
|
55
64
|
let element = wrapper.find('span');
|
|
56
65
|
|
|
57
66
|
expect(element.text()).toContain('Just now');
|
|
58
|
-
await
|
|
59
|
-
await wrapper.vm.liveUpdate(Date.now());
|
|
67
|
+
await wrapper.vm.liveUpdate(Date.now() + 1000);
|
|
60
68
|
|
|
61
69
|
element = wrapper.find('span');
|
|
62
70
|
expect(element.text()).toContain('1 %unit.sec%');
|