@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
|
@@ -41,22 +41,6 @@ export default class HelmOp extends FleetApplication {
|
|
|
41
41
|
enabled: !!this.links.update && this.spec?.paused === true
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
insertAt(out, 2, {
|
|
45
|
-
action: 'enablePollingAction',
|
|
46
|
-
label: this.t('fleet.helmOp.actions.enablePolling.label'),
|
|
47
|
-
icon: 'icon icon-endpoints_connected',
|
|
48
|
-
bulkable: true,
|
|
49
|
-
enabled: !!this.links.update && !!this.spec?.disablePolling
|
|
50
|
-
});
|
|
51
|
-
|
|
52
|
-
insertAt(out, 3, {
|
|
53
|
-
action: 'disablePollingAction',
|
|
54
|
-
label: this.t('fleet.helmOp.actions.disablePolling.label'),
|
|
55
|
-
icon: 'icon icon-endpoints_disconnected',
|
|
56
|
-
bulkable: true,
|
|
57
|
-
enabled: !!this.links.update && !this.spec?.disablePolling
|
|
58
|
-
});
|
|
59
|
-
|
|
60
44
|
insertAt(out, 5, { divider: true });
|
|
61
45
|
|
|
62
46
|
return out;
|
|
@@ -88,7 +72,7 @@ export default class HelmOp extends FleetApplication {
|
|
|
88
72
|
return false;
|
|
89
73
|
}
|
|
90
74
|
|
|
91
|
-
|
|
75
|
+
sourceDisplay(repo) {
|
|
92
76
|
if (!repo) {
|
|
93
77
|
return null;
|
|
94
78
|
}
|
|
@@ -140,9 +124,14 @@ export default class HelmOp extends FleetApplication {
|
|
|
140
124
|
|
|
141
125
|
switch (this.sourceType) {
|
|
142
126
|
case SOURCE_TYPE.REPO:
|
|
143
|
-
case SOURCE_TYPE.OCI:
|
|
144
127
|
value = this.spec.helm?.repo || '';
|
|
145
128
|
break;
|
|
129
|
+
case SOURCE_TYPE.OCI: {
|
|
130
|
+
const parsed = parse(this.spec.helm?.repo || '');
|
|
131
|
+
|
|
132
|
+
value = parsed?.host ? `oci://${ parsed.host }` : '';
|
|
133
|
+
break;
|
|
134
|
+
}
|
|
146
135
|
case SOURCE_TYPE.TARBALL:
|
|
147
136
|
value = this.spec.helm?.chart || '';
|
|
148
137
|
}
|
|
@@ -158,15 +147,25 @@ export default class HelmOp extends FleetApplication {
|
|
|
158
147
|
|
|
159
148
|
return {
|
|
160
149
|
value,
|
|
161
|
-
display: this.
|
|
150
|
+
display: this.sourceDisplay(value),
|
|
162
151
|
icon: 'icon icon-application',
|
|
163
|
-
showLink: matchHttps || matchSSH
|
|
152
|
+
showLink: !!(matchHttps || matchSSH)
|
|
164
153
|
};
|
|
165
154
|
}
|
|
166
155
|
|
|
167
156
|
get sourceSub() {
|
|
157
|
+
// Version label
|
|
158
|
+
const semanticVersion = this.spec.helm?.version || '';
|
|
159
|
+
const installedVersion = this.status?.version || '';
|
|
160
|
+
|
|
161
|
+
let labelVersion = semanticVersion || installedVersion || '';
|
|
162
|
+
|
|
163
|
+
if (semanticVersion && installedVersion && semanticVersion !== installedVersion) {
|
|
164
|
+
labelVersion = `${ semanticVersion } -> ${ installedVersion }`;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// Chart label
|
|
168
168
|
let chart = '';
|
|
169
|
-
const version = this.spec.helm.version || '';
|
|
170
169
|
|
|
171
170
|
switch (this.sourceType) {
|
|
172
171
|
case SOURCE_TYPE.REPO:
|
|
@@ -180,7 +179,12 @@ export default class HelmOp extends FleetApplication {
|
|
|
180
179
|
}
|
|
181
180
|
}
|
|
182
181
|
|
|
183
|
-
|
|
182
|
+
// Concat chart label and version label
|
|
183
|
+
let value = chart || labelVersion || '';
|
|
184
|
+
|
|
185
|
+
if (chart && labelVersion) {
|
|
186
|
+
value = `${ chart } : ${ labelVersion }`;
|
|
187
|
+
}
|
|
184
188
|
|
|
185
189
|
return {
|
|
186
190
|
value,
|
|
@@ -41,7 +41,7 @@ export default class PVC extends SteveModel {
|
|
|
41
41
|
insertAt(out, 0, {
|
|
42
42
|
action: 'goToEditVolumeSize',
|
|
43
43
|
enabled: this.expandable && this.bound,
|
|
44
|
-
icon: 'icon icon-
|
|
44
|
+
icon: 'icon icon-plus',
|
|
45
45
|
label: this.t('persistentVolumeClaim.expand.label'),
|
|
46
46
|
});
|
|
47
47
|
|
package/models/pod.js
CHANGED
|
@@ -61,7 +61,7 @@ export default class Pod extends WorkloadService {
|
|
|
61
61
|
return {
|
|
62
62
|
action: 'openShell',
|
|
63
63
|
enabled: !!this.links.view && this.isRunning,
|
|
64
|
-
icon: 'icon
|
|
64
|
+
icon: 'icon-chevron-right',
|
|
65
65
|
label: 'Execute Shell',
|
|
66
66
|
total: 1,
|
|
67
67
|
};
|
|
@@ -71,7 +71,7 @@ export default class Pod extends WorkloadService {
|
|
|
71
71
|
return {
|
|
72
72
|
action: 'openLogs',
|
|
73
73
|
enabled: !!this.links.view,
|
|
74
|
-
icon: 'icon icon-
|
|
74
|
+
icon: 'icon icon-chevron-right',
|
|
75
75
|
label: 'View Logs',
|
|
76
76
|
total: 1,
|
|
77
77
|
};
|
|
@@ -13,6 +13,7 @@ import { CAPI as CAPI_ANNOTATIONS, NODE_ARCHITECTURE } from '@shell/config/label
|
|
|
13
13
|
import { KEV1 } from '@shell/models/management.cattle.io.kontainerdriver';
|
|
14
14
|
|
|
15
15
|
const RKE1_ALLOWED_ACTIONS = [
|
|
16
|
+
'promptRemove',
|
|
16
17
|
'openShell',
|
|
17
18
|
'downloadKubeConfig',
|
|
18
19
|
'copyKubeConfig',
|
|
@@ -73,15 +74,17 @@ export default class ProvCluster extends SteveModel {
|
|
|
73
74
|
return super.creationTimestamp;
|
|
74
75
|
}
|
|
75
76
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
77
|
+
get canExplore() {
|
|
78
|
+
return this.mgmt?.isReady && !this.hasError;
|
|
79
|
+
}
|
|
79
80
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
}
|
|
81
|
+
get canEdit() {
|
|
82
|
+
// If the cluster is a KEV1 cluster or Harvester cluster then prevent edit
|
|
83
|
+
if (this.isKev1 || this.isHarvester) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return super.canEdit;
|
|
85
88
|
}
|
|
86
89
|
|
|
87
90
|
get _availableActions() {
|
|
@@ -100,7 +103,7 @@ export default class ProvCluster extends SteveModel {
|
|
|
100
103
|
|
|
101
104
|
const canEditRKE2cluster = this.isRke2 && ready && this.canUpdate;
|
|
102
105
|
|
|
103
|
-
const canSnapshot = ready &&
|
|
106
|
+
const canSnapshot = ready && this.isRke2 && this.canUpdate;
|
|
104
107
|
|
|
105
108
|
const actions = [
|
|
106
109
|
// Note: Actions are not supported in the Steve API, so we check
|
|
@@ -133,7 +136,7 @@ export default class ProvCluster extends SteveModel {
|
|
|
133
136
|
}, {
|
|
134
137
|
action: 'restoreSnapshotAction',
|
|
135
138
|
label: this.$rootGetters['i18n/t']('nav.restoreSnapshot'),
|
|
136
|
-
icon: 'icon icon-
|
|
139
|
+
icon: 'icon icon-backup-restore',
|
|
137
140
|
enabled: canSnapshot,
|
|
138
141
|
}, {
|
|
139
142
|
action: 'rotateCertificates',
|
|
@@ -147,19 +150,6 @@ export default class ProvCluster extends SteveModel {
|
|
|
147
150
|
enabled: canEditRKE2cluster
|
|
148
151
|
}, { divider: true }];
|
|
149
152
|
|
|
150
|
-
// Harvester Cluster 1:1 Harvester Cloud Cred
|
|
151
|
-
if (this.cloudCredential?.canRenew || this.cloudCredential?.canBulkRenew) {
|
|
152
|
-
out.splice(0, 0, { divider: true });
|
|
153
|
-
out.splice(0, 0, {
|
|
154
|
-
action: 'renew',
|
|
155
|
-
enabled: this.cloudCredential?.canRenew,
|
|
156
|
-
bulkable: this.cloudCredential?.canBulkRenew,
|
|
157
|
-
bulkAction: 'renewBulk',
|
|
158
|
-
icon: 'icon icon-fw icon-refresh',
|
|
159
|
-
label: this.$rootGetters['i18n/t']('cluster.cloudCredentials.renew'),
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
|
|
163
153
|
const all = actions.concat(out);
|
|
164
154
|
|
|
165
155
|
// If the cluster is a KEV1 cluster or Harvester cluster then prevent edit
|
|
@@ -822,33 +812,6 @@ export default class ProvCluster extends SteveModel {
|
|
|
822
812
|
return this._stateObj;
|
|
823
813
|
}
|
|
824
814
|
|
|
825
|
-
get rkeTemplate() {
|
|
826
|
-
if (!this.isRke1 || !this.mgmt) {
|
|
827
|
-
// Not an RKE! cluster or no management cluster available
|
|
828
|
-
return false;
|
|
829
|
-
}
|
|
830
|
-
|
|
831
|
-
if (!this.mgmt.spec?.clusterTemplateRevisionName) {
|
|
832
|
-
// Cluster does not use an RKE template
|
|
833
|
-
return false;
|
|
834
|
-
}
|
|
835
|
-
|
|
836
|
-
const clusterTemplateName = this.mgmt.spec.clusterTemplateName.replace(':', '/');
|
|
837
|
-
const clusterTemplateRevisionName = this.mgmt.spec.clusterTemplateRevisionName.replace(':', '/');
|
|
838
|
-
const template = this.$rootGetters['management/all'](MANAGEMENT.RKE_TEMPLATE).find((t) => t.id === clusterTemplateName);
|
|
839
|
-
const revision = this.$rootGetters['management/all'](MANAGEMENT.RKE_TEMPLATE_REVISION).find((t) => t.spec.enabled && t.id === clusterTemplateRevisionName);
|
|
840
|
-
|
|
841
|
-
if (!template || !revision) {
|
|
842
|
-
return false;
|
|
843
|
-
}
|
|
844
|
-
|
|
845
|
-
return {
|
|
846
|
-
displayName: `${ template.spec?.displayName }/${ revision.spec?.displayName }`,
|
|
847
|
-
template,
|
|
848
|
-
revision,
|
|
849
|
-
};
|
|
850
|
-
}
|
|
851
|
-
|
|
852
815
|
get _stateObj() {
|
|
853
816
|
if (!this.isRke2) {
|
|
854
817
|
return this.mgmt?.stateObj || this.metadata?.state;
|
|
@@ -1011,6 +974,28 @@ export default class ProvCluster extends SteveModel {
|
|
|
1011
974
|
return null;
|
|
1012
975
|
}
|
|
1013
976
|
|
|
977
|
+
/**
|
|
978
|
+
* Gets the options for fields that should be commented out in the YAML representation
|
|
979
|
+
* of the model. This is particularly useful for conditionally commenting out certain
|
|
980
|
+
* fields based on the model's configuration.
|
|
981
|
+
*
|
|
982
|
+
* @returns {null | Array.<{path: string, key: string}>}
|
|
983
|
+
* - `path`: A dot-separated string indicating the path to the object containing the key.
|
|
984
|
+
* - `key`: The specific key within the object at the given path that should be commented out.
|
|
985
|
+
*/
|
|
986
|
+
get commentFieldsOptions() {
|
|
987
|
+
if ( this.isRke2 ) {
|
|
988
|
+
return [
|
|
989
|
+
{
|
|
990
|
+
path: 'spec.rkeConfig.machineGlobalConfig',
|
|
991
|
+
key: 'profile'
|
|
992
|
+
}
|
|
993
|
+
];
|
|
994
|
+
}
|
|
995
|
+
|
|
996
|
+
return null;
|
|
997
|
+
}
|
|
998
|
+
|
|
1014
999
|
// JSON Paths that should be folded in the YAML editor by default
|
|
1015
1000
|
get yamlFolding() {
|
|
1016
1001
|
return [
|
|
@@ -1022,24 +1007,11 @@ export default class ProvCluster extends SteveModel {
|
|
|
1022
1007
|
return super.description || this.mgmt?.description;
|
|
1023
1008
|
}
|
|
1024
1009
|
|
|
1025
|
-
|
|
1026
|
-
return this.
|
|
1027
|
-
}
|
|
1028
|
-
|
|
1029
|
-
renewBulk(clusters = []) {
|
|
1030
|
-
// In theory we don't need to filter by cloudCred, but do so for safety
|
|
1031
|
-
const cloudCredentials = clusters.filter((c) => c.cloudCredential).map((c) => c.cloudCredential);
|
|
1032
|
-
|
|
1033
|
-
return this.cloudCredential?.renewBulk(cloudCredentials);
|
|
1010
|
+
get disableResourceDetailDrawerConfigTab() {
|
|
1011
|
+
return !!this.isHarvester;
|
|
1034
1012
|
}
|
|
1035
1013
|
|
|
1036
|
-
get
|
|
1037
|
-
return
|
|
1038
|
-
}
|
|
1039
|
-
|
|
1040
|
-
get cloudCredentialWarning() {
|
|
1041
|
-
const expireData = this.cloudCredential?.expireData;
|
|
1042
|
-
|
|
1043
|
-
return expireData?.expired || expireData?.expiring;
|
|
1014
|
+
get fullDetailPageOverride() {
|
|
1015
|
+
return true;
|
|
1044
1016
|
}
|
|
1045
1017
|
}
|
package/models/secret.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import r from 'jsrsasign';
|
|
2
|
-
import { CERTMANAGER, KUBERNETES } from '@shell/config/labels-annotations';
|
|
2
|
+
import { CERTMANAGER, KUBERNETES, UI_PROJECT_SECRET, UI_PROJECT_SECRET_COPY } from '@shell/config/labels-annotations';
|
|
3
3
|
import { base64Decode, base64Encode } from '@shell/utils/crypto';
|
|
4
4
|
import { removeObjects } from '@shell/utils/array';
|
|
5
|
-
import { SERVICE_ACCOUNT } from '@shell/config/types';
|
|
5
|
+
import { MANAGEMENT, SERVICE_ACCOUNT, VIRTUAL_TYPES } from '@shell/config/types';
|
|
6
6
|
import { set } from '@shell/utils/object';
|
|
7
7
|
import { NAME as MANAGER } from '@shell/config/product/manager';
|
|
8
8
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
@@ -10,6 +10,8 @@ import { colorForState, stateDisplay, STATES_ENUM } from '@shell/plugins/dashboa
|
|
|
10
10
|
import { diffFrom } from '@shell/utils/time';
|
|
11
11
|
import day from 'dayjs';
|
|
12
12
|
import { steveCleanForDownload } from '@shell/plugins/steve/resource-utils';
|
|
13
|
+
import { STORE } from '@shell/store/store-types';
|
|
14
|
+
import { escapeHtml } from '@shell/utils/string';
|
|
13
15
|
|
|
14
16
|
export const TYPES = {
|
|
15
17
|
OPAQUE: 'Opaque',
|
|
@@ -159,6 +161,10 @@ export default class Secret extends SteveModel {
|
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
get canUpdate() {
|
|
164
|
+
if (this.isProjectSecretCopy) {
|
|
165
|
+
return false;
|
|
166
|
+
}
|
|
167
|
+
|
|
162
168
|
if ( !this.hasLink('update') ) {
|
|
163
169
|
return false;
|
|
164
170
|
}
|
|
@@ -170,6 +176,20 @@ export default class Secret extends SteveModel {
|
|
|
170
176
|
return this.$rootGetters['type-map/optionsFor'](this.type).isEditable;
|
|
171
177
|
}
|
|
172
178
|
|
|
179
|
+
get canDelete() {
|
|
180
|
+
// Deleting a copy / synced secret that was created in a namespace in a project that has a project scoped secret
|
|
181
|
+
// will only be temporary (the parent project scoped secret will recreate it)
|
|
182
|
+
return this.isProjectSecretCopy ? false : super.canDelete;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
get canCreate() {
|
|
186
|
+
return this.isProjectSecretCopy ? false : super.canCreate;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
get canEditYaml() {
|
|
190
|
+
return this.isProjectSecretCopy ? false : super.canEditYaml;
|
|
191
|
+
}
|
|
192
|
+
|
|
173
193
|
get keysDisplay() {
|
|
174
194
|
const keys = [
|
|
175
195
|
...Object.keys(this.data || []),
|
|
@@ -470,4 +490,143 @@ export default class Secret extends SteveModel {
|
|
|
470
490
|
|
|
471
491
|
return steveCleanForDownload(yaml, { rootKeys: ['id', 'links', 'actions'] });
|
|
472
492
|
}
|
|
493
|
+
|
|
494
|
+
/**
|
|
495
|
+
* is this a project scoped secret .... or also a cloned project scoped secret
|
|
496
|
+
*/
|
|
497
|
+
get isProjectScopedRelated() {
|
|
498
|
+
return !!this.metadata.labels?.[UI_PROJECT_SECRET];
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
/**
|
|
502
|
+
* is this a project scoped secret
|
|
503
|
+
*/
|
|
504
|
+
get isProjectScoped() {
|
|
505
|
+
return this.isProjectScopedRelated && !this.isProjectSecretCopy && this.$rootGetters['isRancher'];
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
get projectScopedClusterId() {
|
|
509
|
+
if (!this.projectScopedProjectId) {
|
|
510
|
+
return undefined;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
const clusterId = this.metadata.namespace.replace(`-${ this.projectScopedProjectId }`, '');
|
|
514
|
+
|
|
515
|
+
// default and system pss don't follow the patter of <cluster>-<project>, so if they match assume its one of them
|
|
516
|
+
return clusterId === this.metadata.namespace ? 'local' : clusterId;
|
|
517
|
+
}
|
|
518
|
+
|
|
519
|
+
get projectScopedProjectId() {
|
|
520
|
+
return this.metadata.labels?.[UI_PROJECT_SECRET];
|
|
521
|
+
}
|
|
522
|
+
|
|
523
|
+
get isProjectSecretCopy() {
|
|
524
|
+
return this.metadata?.annotations?.[UI_PROJECT_SECRET_COPY] === 'true';
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
get projectCluster() {
|
|
528
|
+
if (!this.isProjectScoped) {
|
|
529
|
+
return undefined;
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
return this.$rootGetters[`${ STORE.MANAGEMENT }/byId`](MANAGEMENT.CLUSTER, this.projectScopedClusterId);
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
/**
|
|
536
|
+
* If this is a project scoped secret, return it
|
|
537
|
+
*/
|
|
538
|
+
get project() {
|
|
539
|
+
if (!this.isProjectScoped ) {
|
|
540
|
+
return undefined;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
return this.$rootGetters[`${ STORE.MANAGEMENT }/byId`](MANAGEMENT.PROJECT, `${ this.projectScopedClusterId }/${ this.projectScopedProjectId }`);
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
get projectScopedSecretCluster() {
|
|
547
|
+
if (!this.isProjectScoped ) {
|
|
548
|
+
return undefined;
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
return this.$rootGetters[`${ STORE.MANAGEMENT }/byId`](MANAGEMENT.PROJECT, `${ this.projectScopedClusterId }/${ this.projectScopedProjectId }`);
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
get clusterAndProjectLabel() {
|
|
555
|
+
if (!this.isProjectScoped) {
|
|
556
|
+
return '';
|
|
557
|
+
}
|
|
558
|
+
const clusterName = this.projectCluster?.nameDisplay;
|
|
559
|
+
// project is going to be empty if upstream and trying to show pss from downstream clusters
|
|
560
|
+
// we only ever have the current clusters projects. if we change this (fetch them in the list)
|
|
561
|
+
// we wipe out the header ns filter projects
|
|
562
|
+
const projectName = this.project?.nameDisplay || this.projectScopedProjectId;
|
|
563
|
+
|
|
564
|
+
if (clusterName && projectName) {
|
|
565
|
+
return `${ projectName } (${ clusterName })`;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
return '';
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
get detailLocation() {
|
|
572
|
+
if (this.isProjectScoped) {
|
|
573
|
+
const id = this.id?.replace(/.*\//, '');
|
|
574
|
+
|
|
575
|
+
return {
|
|
576
|
+
name: `c-cluster-product-${ VIRTUAL_TYPES.PROJECT_SECRETS }-namespace-id`,
|
|
577
|
+
params: {
|
|
578
|
+
product: this.$rootGetters['productId'],
|
|
579
|
+
cluster: this.$rootGetters['clusterId'],
|
|
580
|
+
namespace: this.metadata?.namespace,
|
|
581
|
+
resource: VIRTUAL_TYPES.PROJECT_SECRETS,
|
|
582
|
+
id,
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
}
|
|
586
|
+
|
|
587
|
+
return this._detailLocation;
|
|
588
|
+
}
|
|
589
|
+
|
|
590
|
+
get listLocation() {
|
|
591
|
+
if (!this.isProjectScoped) {
|
|
592
|
+
return super.listLocation;
|
|
593
|
+
}
|
|
594
|
+
|
|
595
|
+
return {
|
|
596
|
+
name: 'c-cluster-product-resource',
|
|
597
|
+
params: {
|
|
598
|
+
product: this.$rootGetters['productId'],
|
|
599
|
+
cluster: this.$rootGetters['clusterId'],
|
|
600
|
+
resource: VIRTUAL_TYPES.PROJECT_SECRETS,
|
|
601
|
+
}
|
|
602
|
+
};
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
get parentNameOverride() {
|
|
606
|
+
if (!this.isProjectScoped) {
|
|
607
|
+
return super.parentNameOverride;
|
|
608
|
+
}
|
|
609
|
+
|
|
610
|
+
return this.$rootGetters['i18n/t'](`typeLabel."${ VIRTUAL_TYPES.PROJECT_SECRETS }"`, { count: 1 })?.trim();
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
get parentLocationOverride() {
|
|
614
|
+
if (!this.isProjectScoped) {
|
|
615
|
+
return super.parentNameOverride;
|
|
616
|
+
}
|
|
617
|
+
|
|
618
|
+
return this.listLocation;
|
|
619
|
+
}
|
|
620
|
+
|
|
621
|
+
get groupByProject() {
|
|
622
|
+
if (!this.isProjectScoped) {
|
|
623
|
+
return undefined;
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
return this.t('resourceTable.groupLabel.project', { name: escapeHtml(this?.project?.nameDisplay || '') }, true);
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
get fullDetailPageOverride() {
|
|
630
|
+
return true;
|
|
631
|
+
}
|
|
473
632
|
}
|
|
@@ -141,14 +141,14 @@ export default class extends SteveModel {
|
|
|
141
141
|
out.unshift({
|
|
142
142
|
action: 'resetDefault',
|
|
143
143
|
enabled: true,
|
|
144
|
-
icon: 'icon icon-
|
|
144
|
+
icon: 'icon icon-checkmark',
|
|
145
145
|
label: this.t('storageClass.actions.resetDefault'),
|
|
146
146
|
});
|
|
147
147
|
} else {
|
|
148
148
|
out.unshift({
|
|
149
149
|
action: 'setDefault',
|
|
150
150
|
enabled: true,
|
|
151
|
-
icon: 'icon icon-
|
|
151
|
+
icon: 'icon icon-checkmark',
|
|
152
152
|
label: this.t('storageClass.actions.setAsDefault'),
|
|
153
153
|
});
|
|
154
154
|
}
|
package/models/workload.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { findBy, insertAt } from '@shell/utils/array';
|
|
2
2
|
import { CATTLE_PUBLIC_ENDPOINTS } from '@shell/config/labels-annotations';
|
|
3
3
|
import { WORKLOAD_TYPES, SERVICE, POD } from '@shell/config/types';
|
|
4
|
-
import {
|
|
4
|
+
import { set } from '@shell/utils/object';
|
|
5
5
|
import day from 'dayjs';
|
|
6
6
|
import { convertSelectorObj, parse } from '@shell/utils/selector';
|
|
7
7
|
import { SEPARATOR } from '@shell/config/workload';
|
|
@@ -76,7 +76,7 @@ export default class Workload extends WorkloadService {
|
|
|
76
76
|
insertAt(out, 0, {
|
|
77
77
|
action: 'openShell',
|
|
78
78
|
enabled: !!this.links.view,
|
|
79
|
-
icon: 'icon icon-
|
|
79
|
+
icon: 'icon icon-chevron-right',
|
|
80
80
|
label: this.t('action.openShell'),
|
|
81
81
|
total: 1,
|
|
82
82
|
});
|
|
@@ -632,7 +632,7 @@ export default class Workload extends WorkloadService {
|
|
|
632
632
|
return undefined;
|
|
633
633
|
}
|
|
634
634
|
|
|
635
|
-
return
|
|
635
|
+
return this.metadata?.relationships?.filter((relationship) => relationship.toType === WORKLOAD_TYPES.JOB) || [];
|
|
636
636
|
}
|
|
637
637
|
|
|
638
638
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rancher/shell",
|
|
3
|
-
"version": "3.0.5-rc.
|
|
3
|
+
"version": "3.0.5-rc.8",
|
|
4
4
|
"description": "Rancher Dashboard Shell",
|
|
5
5
|
"repository": "https://github.com/rancherlabs/dashboard",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -27,17 +27,18 @@
|
|
|
27
27
|
"e2e:dev": "start-server-and-test dev https://localhost:8005 cy:open"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@aws-sdk/client-ec2": "3.
|
|
31
|
-
"@aws-sdk/client-eks": "3.
|
|
32
|
-
"@aws-sdk/client-iam": "3.
|
|
33
|
-
"@aws-sdk/client-kms": "3.
|
|
30
|
+
"@aws-sdk/client-ec2": "3.863.0",
|
|
31
|
+
"@aws-sdk/client-eks": "3.863.0",
|
|
32
|
+
"@aws-sdk/client-iam": "3.863.0",
|
|
33
|
+
"@aws-sdk/client-kms": "3.863.0",
|
|
34
|
+
"@smithy/fetch-http-handler": "5.1.1",
|
|
34
35
|
"@babel/plugin-proposal-optional-chaining": "7.21.0",
|
|
35
36
|
"@babel/plugin-proposal-private-methods": "7.18.6",
|
|
36
37
|
"@babel/plugin-proposal-private-property-in-object": "7.14.5",
|
|
37
38
|
"@babel/preset-typescript": "7.16.7",
|
|
38
39
|
"@novnc/novnc": "1.2.0",
|
|
39
40
|
"@popperjs/core": "2.11.8",
|
|
40
|
-
"@rancher/icons": "2.0.
|
|
41
|
+
"@rancher/icons": "2.0.38",
|
|
41
42
|
"@types/is-url": "1.2.30",
|
|
42
43
|
"@types/node": "20.10.8",
|
|
43
44
|
"@types/semver": "^7.5.8",
|
|
@@ -64,14 +65,14 @@
|
|
|
64
65
|
"cookie-universal": "2.2.2",
|
|
65
66
|
"cookie": "0.7.0",
|
|
66
67
|
"core-js": "3.40.0",
|
|
67
|
-
"cron-validator": "1.
|
|
68
|
+
"cron-validator": "1.4.0",
|
|
68
69
|
"cronstrue": "2.53.0",
|
|
69
70
|
"cross-env": "7.0.3",
|
|
70
71
|
"css-loader": "6.7.3",
|
|
71
72
|
"csv-loader": "3.0.3",
|
|
72
73
|
"custom-event-polyfill": "^1.0.7",
|
|
73
74
|
"cypress": "11.1.0",
|
|
74
|
-
"d3-selection": "
|
|
75
|
+
"d3-selection": "3.0.0",
|
|
75
76
|
"d3": "7.3.0",
|
|
76
77
|
"dayjs": "1.8.29",
|
|
77
78
|
"defu": "5.0.1",
|
|
@@ -108,7 +109,7 @@
|
|
|
108
109
|
"jsdiff": "1.1.1",
|
|
109
110
|
"jsonpath-plus": "10.3.0",
|
|
110
111
|
"jsrsasign": "11.0.0",
|
|
111
|
-
"jszip": "3.
|
|
112
|
+
"jszip": "3.10.1",
|
|
112
113
|
"lodash": "4.17.21",
|
|
113
114
|
"marked": "4.0.17",
|
|
114
115
|
"node-polyfill-webpack-plugin": "3.0.0",
|
|
@@ -117,7 +118,7 @@
|
|
|
117
118
|
"papaparse": "5.3.0",
|
|
118
119
|
"portal-vue": "~3.0.0",
|
|
119
120
|
"sass-loader": "12.6.0",
|
|
120
|
-
"sass": "1.
|
|
121
|
+
"sass": "1.89.2",
|
|
121
122
|
"serve-static": "1.14.1",
|
|
122
123
|
"set-cookie-parser": "2.4.6",
|
|
123
124
|
"shell-quote": "1.7.3",
|
|
@@ -35,6 +35,7 @@ function onClickItem(type: string, label: string) {
|
|
|
35
35
|
<rc-item-card-action
|
|
36
36
|
v-for="(label, j) in footerItem.labels"
|
|
37
37
|
:key="j"
|
|
38
|
+
v-clean-tooltip="footerItem.labelTooltip"
|
|
38
39
|
class="app-chart-card-footer-item-text secondary-text-link"
|
|
39
40
|
data-testid="app-chart-card-footer-item-text"
|
|
40
41
|
tabindex="0"
|
|
@@ -4,6 +4,7 @@ interface SubHeaderItem {
|
|
|
4
4
|
icon: string;
|
|
5
5
|
iconTooltip?: Record<{key?: string, text?: string}>;
|
|
6
6
|
label: string;
|
|
7
|
+
labelTooltip?: string;
|
|
7
8
|
}
|
|
8
9
|
|
|
9
10
|
defineProps<{
|
|
@@ -24,7 +25,9 @@ defineProps<{
|
|
|
24
25
|
v-clean-tooltip="t(subHeaderItem.iconTooltip.key)"
|
|
25
26
|
:class="['icon', 'app-chart-card-sub-header-item-icon', subHeaderItem.icon]"
|
|
26
27
|
/>
|
|
27
|
-
<p
|
|
28
|
+
<p v-clean-tooltip="subHeaderItem.labelTooltip">
|
|
29
|
+
{{ subHeaderItem.label }}
|
|
30
|
+
</p>
|
|
28
31
|
</div>
|
|
29
32
|
</div>
|
|
30
33
|
</template>
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import AppChartCardFooter from '../AppChartCardFooter.vue';
|
|
3
|
+
import { REPO } from '@shell/config/query-params';
|
|
4
|
+
|
|
5
|
+
describe('component: AppChartCardFooter', () => {
|
|
6
|
+
it('should render', () => {
|
|
7
|
+
const wrapper = shallowMount(AppChartCardFooter, {
|
|
8
|
+
propsData: { items: [] },
|
|
9
|
+
stubs: { 'rc-item-card-action': true },
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
expect(wrapper.exists()).toBe(true);
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
it('should apply tooltips to labels', () => {
|
|
16
|
+
const tooltipContent = 'my tooltip';
|
|
17
|
+
const items = [
|
|
18
|
+
{
|
|
19
|
+
type: REPO,
|
|
20
|
+
labels: ['label1', 'label2'],
|
|
21
|
+
labelTooltip: tooltipContent,
|
|
22
|
+
},
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const wrapper = shallowMount(AppChartCardFooter, {
|
|
26
|
+
propsData: { items },
|
|
27
|
+
stubs: { 'rc-item-card-action': true },
|
|
28
|
+
directives: {
|
|
29
|
+
'clean-tooltip': (el, binding) => {
|
|
30
|
+
el.setAttribute('data-tooltip-value', binding.value);
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
const actions = wrapper.findAll('[data-tooltip-value]');
|
|
36
|
+
|
|
37
|
+
expect(actions).toHaveLength(2);
|
|
38
|
+
expect(actions.at(0).attributes('data-tooltip-value')).toBe(tooltipContent);
|
|
39
|
+
expect(actions.at(1).attributes('data-tooltip-value')).toBe(tooltipContent);
|
|
40
|
+
});
|
|
41
|
+
});
|