@rancher/shell 3.0.12-rc.1 → 3.0.12-rc.3
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/apis/impl/apis.ts +6 -0
- package/apis/index.ts +26 -0
- package/apis/intf/resources-api/cluster-api.ts +18 -0
- package/apis/intf/resources-api/mgmt-api.ts +15 -0
- package/apis/intf/resources-api/resource-base.ts +107 -0
- package/apis/intf/resources-api/resource-constants.ts +147 -0
- package/apis/intf/resources-api/resources-api.ts +143 -0
- package/apis/intf/resources.ts +49 -0
- package/apis/intf/{modal.ts → shell-api/modal.ts} +21 -26
- package/apis/intf/shell-api/proxy.ts +216 -0
- package/apis/intf/{slide-in.ts → shell-api/slide-in.ts} +4 -3
- package/apis/intf/{system.ts → shell-api/system.ts} +4 -1
- package/apis/intf/shell.ts +12 -6
- package/apis/resources/__tests__/resources-api-class.test.ts +550 -0
- package/apis/resources/index.ts +22 -0
- package/apis/resources/resources-api-class.ts +187 -0
- package/apis/shell/__tests__/proxy.test.ts +369 -0
- package/apis/shell/index.ts +8 -1
- package/apis/shell/modal.ts +4 -1
- package/apis/shell/notifications.ts +9 -6
- package/apis/shell/proxy.ts +256 -0
- package/apis/shell/slide-in.ts +4 -1
- package/apis/vue-shim.d.ts +2 -1
- package/assets/data/aws-regions.json +4 -0
- package/assets/fonts/lato/LatoLatin-Black.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Black.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-BlackItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-BlackItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Bold.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Bold.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-BoldItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-BoldItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Heavy.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Heavy.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-HeavyItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-HeavyItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Italic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Italic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Light.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Light.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-LightItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-LightItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Medium.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Medium.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-MediumItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-MediumItalic.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Regular.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Regular.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-Semibold.woff +0 -0
- package/assets/fonts/lato/LatoLatin-Semibold.woff2 +0 -0
- package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff +0 -0
- package/assets/fonts/lato/LatoLatin-SemiboldItalic.woff2 +0 -0
- package/assets/images/providers/entraid-black.svg +4 -0
- package/assets/images/providers/entraid.svg +9 -0
- package/assets/images/vendor/entraid.svg +9 -0
- package/assets/styles/app.scss +0 -1
- package/assets/styles/base/_variables.scss +2 -0
- package/assets/styles/fonts/_fontstack.scss +132 -8
- package/assets/translations/en-us.yaml +41 -22
- package/assets/translations/zh-hans.yaml +4 -8
- package/chart/__tests__/S3.test.ts +10 -3
- package/chart/monitoring/index.vue +10 -1
- package/components/ActionDropdownShell.vue +2 -1
- package/components/CountBox.vue +20 -0
- package/components/CreateDriver.vue +0 -12
- package/components/CruResourceFooter.vue +9 -5
- package/components/DetailText.vue +12 -3
- package/components/ExplorerProjectsNamespaces.vue +1 -1
- package/components/InstallHelmCharts.vue +2 -2
- package/components/LandingPagePreference.vue +14 -5
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +15 -1
- package/components/Resource/Detail/Metadata/index.vue +6 -0
- package/components/Resource/Detail/ResourcePopover/index.vue +12 -1
- package/components/Resource/Detail/SpacedRow.vue +3 -1
- package/components/Resource/Detail/TitleBar/index.vue +10 -11
- package/components/ResourceList/Masthead.vue +12 -8
- package/components/SelectIconGrid.vue +5 -10
- package/components/SingleClusterInfo.vue +1 -0
- package/components/SortableTable/__tests__/sorting.test.ts +126 -0
- package/components/SortableTable/index.vue +6 -9
- package/components/SortableTable/selection.js +23 -5
- package/components/SortableTable/sorting.js +6 -3
- package/components/Wizard.vue +14 -13
- package/components/__tests__/CountBox.test.ts +72 -0
- package/components/__tests__/DetailText.test.ts +113 -0
- package/components/fleet/FleetBundles.vue +100 -12
- package/components/fleet/FleetClusterTargets/index.vue +54 -15
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +149 -115
- package/components/fleet/__tests__/FleetClusters.test.ts +12 -12
- package/components/form/InputWithSelect.vue +18 -10
- package/components/form/KeyValue.vue +17 -1
- package/components/form/LabeledSelect.vue +101 -26
- package/components/form/NameNsDescription.vue +11 -0
- package/components/form/Security.vue +6 -2
- package/components/form/Select.vue +73 -56
- package/components/form/ServiceNameSelect.vue +13 -11
- package/components/form/WorkloadPorts.vue +2 -7
- package/components/form/__tests__/KeyValue.test.ts +66 -0
- package/components/form/__tests__/NodeScheduling.test.ts +9 -0
- package/components/form/__tests__/Security.test.ts +76 -0
- package/components/form/labeled-select-utils/useLabeledSelectPagination.ts +138 -0
- package/components/formatter/Autoscaler.vue +4 -4
- package/components/formatter/ClusterKubeVersion.vue +27 -0
- package/components/formatter/ClusterLink.vue +1 -7
- package/components/formatter/ClusterProvider.vue +6 -10
- package/components/formatter/FleetSummaryGraph.vue +0 -3
- package/components/formatter/MachineSummaryGraph.vue +1 -1
- package/components/formatter/PodsUsage.vue +2 -2
- package/components/formatter/__tests__/Autoscaler.test.ts +19 -22
- package/components/formatter/__tests__/FleetSummaryGraph.test.ts +216 -0
- package/components/formatter/__tests__/PodsUsage.test.ts +6 -10
- package/components/nav/Group.vue +7 -6
- package/components/nav/Header.vue +24 -3
- package/components/nav/NamespaceFilter.vue +2 -2
- package/components/nav/NotificationCenter/Notification.vue +4 -1
- package/components/nav/NotificationCenter/NotificationHeader.vue +20 -8
- package/components/nav/NotificationCenter/__tests__/NotificationHeader.test.ts +80 -0
- package/components/nav/TopLevelMenu.helper.ts +15 -3
- package/components/nav/TopLevelMenu.vue +16 -5
- package/components/nav/Type.vue +8 -7
- package/components/nav/WindowManager/index.vue +2 -1
- package/components/nav/WorkspaceSwitcher.vue +13 -0
- package/components/nav/__tests__/Group.test.ts +67 -0
- package/components/nav/__tests__/Header.test.ts +235 -0
- package/components/nav/__tests__/TopLevelMenu.test.ts +145 -21
- package/components/nav/__tests__/Type.test.ts +20 -3
- package/components/templates/default.vue +34 -4
- package/components/templates/home.vue +30 -25
- package/components/templates/plain.vue +31 -26
- package/components/templates/standalone.vue +17 -0
- package/composables/useFormValidation.ts +93 -0
- package/composables/useLabeledFormElement.ts +10 -2
- package/composables/useLabeledSelect.ts +60 -0
- package/composables/useUserRetentionValidation.ts +1 -49
- package/composables/useVeeValidateField.test.ts +159 -0
- package/composables/useVeeValidateField.ts +67 -0
- package/config/cookies.js +0 -1
- package/config/labels-annotations.js +1 -0
- package/config/pagination-table-headers.js +18 -1
- package/config/product/manager.js +82 -21
- package/config/query-params.js +1 -0
- package/config/router/routes.js +6 -8
- package/config/table-headers.js +20 -1
- package/config/types.js +2 -1
- package/core/__tests__/plugin-products.test.ts +1505 -30
- package/core/plugin-products-base.ts +137 -20
- package/core/plugin-products-helpers.ts +5 -4
- package/core/plugin-products.ts +4 -0
- package/core/plugin-types.ts +129 -4
- package/core/plugin.ts +15 -7
- package/core/productDebugger.js +9 -4
- package/core/types-provisioning.ts +43 -30
- package/core/types.ts +58 -19
- package/detail/__tests__/management.cattle.io.fleetworkspace.test.ts +128 -0
- package/detail/__tests__/pod.test.ts +41 -0
- package/detail/harvesterhci.io.management.cluster.vue +6 -2
- package/detail/management.cattle.io.fleetworkspace.vue +49 -0
- package/detail/pod.vue +1 -1
- package/detail/provisioning.cattle.io.cluster.vue +4 -10
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +9 -0
- package/edit/__tests__/kontainerDriver.test.ts +0 -13
- package/edit/__tests__/nodeDriver.test.ts +5 -11
- package/edit/__tests__/resources.cattle.io.restore.test.ts +9 -0
- package/edit/auditlog.cattle.io.auditpolicy/__tests__/__snapshots__/General.test.ts.snap +6 -0
- package/edit/auth/__tests__/azuread.test.ts +217 -34
- package/edit/auth/__tests__/oidc.test.ts +54 -0
- package/edit/auth/azuread.vue +123 -15
- package/edit/auth/oidc.vue +10 -2
- package/edit/kontainerDriver.vue +1 -2
- package/edit/networking.k8s.io.ingress/DefaultBackend.vue +13 -4
- package/edit/networking.k8s.io.ingress/RulePath.vue +8 -4
- package/edit/networking.k8s.io.ingress/index.vue +75 -20
- package/edit/nodeDriver.vue +0 -2
- package/edit/provisioning.cattle.io.cluster/AgentEnv.vue +1 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/AgentEnv.test.ts +25 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/MachinePool.test.ts +104 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +81 -106
- package/edit/provisioning.cattle.io.cluster/rke2.vue +8 -4
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +11 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +37 -4
- package/edit/provisioning.cattle.io.cluster/tabs/registries/__tests__/RegistryConfigs.test.ts +132 -7
- package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -1
- package/edit/secret/__tests__/ssh.test.ts +5 -6
- package/edit/secret/basic.vue +31 -0
- package/edit/secret/index.vue +68 -17
- package/edit/secret/registry.vue +38 -0
- package/edit/secret/ssh.vue +29 -0
- package/edit/secret/tls.vue +30 -0
- package/edit/service.vue +4 -4
- package/edit/workload/Upgrading.vue +3 -3
- package/edit/workload/__tests__/Upgrading.test.ts +6 -9
- package/edit/workload/mixins/workload.js +2 -1
- package/initialize/App.vue +29 -2
- package/initialize/install-plugins.js +0 -2
- package/list/__tests__/management.cattle.io.feature.test.ts +105 -0
- package/list/catalog.cattle.io.app.vue +25 -5
- package/list/fleet.cattle.io.bundle.vue +7 -104
- package/list/fleet.cattle.io.clusterregistrationtoken.vue +20 -0
- package/list/management.cattle.io.feature.vue +1 -1
- package/list/management.cattle.io.fleetworkspace.vue +8 -0
- package/list/provisioning.cattle.io.cluster.vue +262 -180
- package/list/utils/management.cattle.io.cluster.utils.ts +128 -0
- package/machine-config/amazonec2.vue +1 -0
- package/mixins/__tests__/chart.test.ts +112 -0
- package/mixins/brand.js +2 -1
- package/mixins/chart.js +50 -15
- package/mixins/resource-fetch-api-pagination.js +41 -5
- package/models/__tests__/catalog.cattle.io.app.test.ts +15 -1
- package/models/__tests__/catalog.cattle.io.clusterrepo.test.ts +84 -0
- package/models/__tests__/chart.test.ts +99 -6
- package/models/__tests__/ext.cattle.io.kubeconfig.test.ts +67 -67
- package/models/__tests__/management.cattle.io.cluster.test.ts +1 -1
- package/models/__tests__/management.cattle.io.feature.test.ts +131 -0
- package/models/__tests__/management.cattle.io.node.ts +6 -5
- package/models/__tests__/management.cattle.io.nodepool.ts +5 -4
- package/models/__tests__/monitoring.coreos.com.alertmanagerconfig.test.ts +98 -0
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +32 -11
- package/models/base-cluster.x-k8s.io.js +26 -0
- package/models/catalog.cattle.io.app.js +21 -17
- package/models/catalog.cattle.io.clusterrepo.js +39 -11
- package/models/chart.js +33 -19
- package/models/cluster.js +1 -1
- package/models/cluster.x-k8s.io.machine.js +4 -22
- package/models/cluster.x-k8s.io.machinedeployment.js +2 -20
- package/models/cluster.x-k8s.io.machineset.js +2 -20
- package/models/compliance.cattle.io.clusterscan.js +130 -2
- package/models/ext.cattle.io.kubeconfig.ts +4 -7
- package/models/fleet-application.js +4 -2
- package/models/fleet.cattle.io.bundle.js +1 -1
- package/models/kontainerdriver.js +11 -0
- package/models/management.cattle.io.authconfig.js +5 -1
- package/models/management.cattle.io.cluster.js +402 -78
- package/models/management.cattle.io.feature.js +3 -3
- package/models/management.cattle.io.kontainerdriver.js +1 -26
- package/models/management.cattle.io.node.js +6 -4
- package/models/management.cattle.io.nodepool.js +1 -1
- package/models/monitoring.coreos.com.alertmanagerconfig.js +31 -17
- package/models/networking.k8s.io.ingress.js +12 -4
- package/models/nodedriver.js +7 -0
- package/models/provisioning.cattle.io.cluster.js +47 -330
- package/models/rke.cattle.io.etcdsnapshot.js +1 -2
- package/package.json +20 -37
- package/pages/__tests__/readme.test.ts +49 -0
- package/pages/auth/setup.vue +2 -3
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +265 -0
- package/pages/c/_cluster/apps/charts/__tests__/index.test.ts +55 -0
- package/pages/c/_cluster/apps/charts/__tests__/install.test.ts +53 -0
- package/pages/c/_cluster/apps/charts/chart.vue +275 -39
- package/pages/c/_cluster/apps/charts/index.vue +2 -2
- package/pages/c/_cluster/apps/charts/install.vue +18 -10
- package/pages/c/_cluster/auth/user.retention/index.vue +55 -22
- package/pages/c/_cluster/explorer/__tests__/index.test.ts +23 -25
- package/pages/c/_cluster/explorer/index.vue +5 -49
- package/pages/c/_cluster/istio/__tests__/istio.index.test.ts +194 -0
- package/pages/c/_cluster/istio/index.vue +21 -6
- package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +5 -7
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +40 -2
- package/pages/c/_cluster/uiplugins/__tests__/PluginInfoPanel.test.ts +61 -0
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +735 -13
- package/pages/c/_cluster/uiplugins/index.vue +226 -222
- package/pages/diagnostic.vue +13 -17
- package/pages/fail-whale.vue +18 -0
- package/pages/home.vue +77 -260
- package/pages/readme.vue +88 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +88 -0
- package/plugins/dashboard-store/actions.js +40 -18
- package/plugins/dashboard-store/resource-class.js +5 -2
- package/plugins/steve/__tests__/subscribe.spec.ts +6 -3
- package/plugins/steve/steve-pagination-utils.ts +11 -3
- package/plugins/steve/subscribe.js +35 -5
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +211 -1
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +37 -4
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +1 -1
- package/rancher-components/RcButton/RcButton.test.ts +37 -1
- package/rancher-components/RcButton/RcButton.vue +38 -8
- package/rancher-components/RcDropdown/RcDropdownTrigger.vue +10 -8
- package/scripts/test-plugins-build.sh +5 -2
- package/server/server-middleware.js +2 -2
- package/static/humans.txt +1 -0
- package/static/robots.txt +34 -0
- package/static/welcome-cow.svg +18 -0
- package/store/__tests__/catalog.test.ts +276 -12
- package/store/__tests__/type-map.test.ts +556 -1
- package/store/action-menu.js +8 -3
- package/store/auth.js +1 -4
- package/store/aws.js +27 -16
- package/store/catalog.js +87 -11
- package/store/digitalocean.js +20 -38
- package/store/index.js +2 -0
- package/store/linode.js +25 -40
- package/store/pnap.js +1 -0
- package/store/type-map.js +111 -29
- package/tsconfig.paths.json +8 -8
- package/types/kube/kube-api.ts +14 -1
- package/types/rancher/steve.api.ts +12 -12
- package/types/resources/settings.d.ts +2 -1
- package/types/shell/index.d.ts +128 -24
- package/types/store/dashboard-store.types.ts +108 -11
- package/types/store/pagination.types.ts +6 -3
- package/utils/__tests__/alertmanagerconfig.test.ts +117 -0
- package/utils/__tests__/async.test.ts +87 -0
- package/utils/__tests__/aws.test.ts +140 -0
- package/utils/__tests__/banners.test.ts +176 -0
- package/utils/__tests__/chart.test.ts +64 -1
- package/utils/__tests__/color.test.ts +226 -0
- package/utils/__tests__/duration.test.ts +140 -0
- package/utils/__tests__/fleet.test.ts +340 -0
- package/utils/__tests__/git.test.ts +270 -0
- package/utils/__tests__/inactivity.test.ts +316 -0
- package/utils/__tests__/ingress.test.ts +553 -0
- package/utils/__tests__/kube.test.ts +68 -0
- package/utils/__tests__/namespace-filter.test.ts +109 -0
- package/utils/__tests__/object.test.ts +77 -0
- package/utils/__tests__/pagination-utils.test.ts +361 -0
- package/utils/__tests__/parse-externalid.test.ts +137 -0
- package/utils/__tests__/perf-setting.utils.test.ts +98 -0
- package/utils/__tests__/poller-sequential.test.ts +177 -0
- package/utils/__tests__/poller.test.ts +170 -0
- package/utils/__tests__/promise.test.ts +346 -0
- package/utils/__tests__/settings.test.ts +140 -0
- package/utils/__tests__/sort-utils.test.ts +301 -0
- package/utils/__tests__/string-utils.test.ts +798 -0
- package/utils/__tests__/string.test.ts +23 -1
- package/utils/__tests__/style.test.ts +154 -0
- package/utils/__tests__/svg-filter.test.ts +184 -0
- package/utils/__tests__/time.test.ts +14 -1
- package/utils/__tests__/units.test.ts +417 -0
- package/utils/__tests__/url.test.ts +246 -0
- package/utils/__tests__/versions.test.ts +128 -0
- package/utils/__tests__/xccdf.test.ts +391 -0
- package/utils/chart.js +36 -0
- package/utils/fleet.ts +13 -3
- package/utils/gatekeeper/__tests__/util.test.ts +174 -0
- package/utils/gc/__tests__/gc-interval.test.ts +119 -0
- package/utils/gc/__tests__/gc-root-store.test.ts +225 -0
- package/utils/gc/__tests__/gc-route-changed.test.ts +96 -0
- package/utils/gc/__tests__/gc.test.ts +487 -0
- package/utils/ingress.ts +9 -1
- package/utils/object.js +33 -2
- package/utils/pagination-utils.ts +2 -1
- package/utils/string.js +25 -2
- package/utils/time.ts +5 -0
- package/utils/uiplugins.ts +5 -5
- package/utils/validators/__tests__/cluster-name.test.ts +110 -0
- package/utils/validators/__tests__/cron-schedule.test.ts +79 -0
- package/utils/validators/__tests__/index.test.ts +481 -0
- package/utils/validators/__tests__/kubernetes-name.test.ts +163 -0
- package/utils/validators/__tests__/misc-validators.test.ts +246 -0
- package/utils/validators/__tests__/pod-affinity.test.ts +382 -0
- package/utils/validators/__tests__/prometheusrule.test.ts +211 -0
- package/utils/validators/__tests__/role-template.test.ts +149 -0
- package/utils/validators/__tests__/service.test.ts +283 -0
- package/utils/validators/__tests__/setting.test.js +32 -0
- package/utils/validators/formRules/__tests__/index.test.ts +50 -0
- package/utils/validators/formRules/index.ts +5 -5
- package/utils/validators/machine-pool.ts +1 -1
- package/utils/validators/setting.js +18 -3
- package/utils/xccdf.ts +418 -0
- package/vue.config.js +0 -9
- package/assets/fonts/lato/lato-v17-latin-700.woff +0 -0
- package/assets/fonts/lato/lato-v17-latin-700.woff2 +0 -0
- package/assets/fonts/lato/lato-v17-latin-regular.woff +0 -0
- package/assets/fonts/lato/lato-v17-latin-regular.woff2 +0 -0
- package/assets/images/providers/azuread-black.svg +0 -22
- package/assets/images/providers/azuread.svg +0 -25
- package/assets/images/vendor/azuread.svg +0 -18
- package/assets/styles/fonts/_dots.scss +0 -18
- package/components/EmberPage.vue +0 -622
- package/components/EmberPageView.vue +0 -39
- package/components/form/labeled-select-utils/labeled-select-pagination.ts +0 -116
- package/mixins/labeled-form-element.ts +0 -225
- package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -28
- package/pages/c/_cluster/manager/pages/_page.vue +0 -22
- package/pages/c/_cluster/mcapps/pages/_page.vue +0 -22
- package/plugins/ember-cookie.js +0 -17
- package/utils/ember-page.js +0 -30
|
@@ -159,23 +159,20 @@ const showAdditionalActionButtons = computed(() => isArray(additionalActions));
|
|
|
159
159
|
|
|
160
160
|
<style lang="scss" scoped>
|
|
161
161
|
.title-bar {
|
|
162
|
-
min-width:
|
|
162
|
+
min-width: $resource-detail-min-width;
|
|
163
163
|
|
|
164
164
|
.badge-state {
|
|
165
165
|
font-size: 16px;
|
|
166
166
|
margin-left: 12px;
|
|
167
167
|
position: relative;
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
.icon-document {
|
|
171
|
-
width: 15px;
|
|
172
|
-
font-size: 16px;
|
|
173
|
-
margin-right: 10px;
|
|
168
|
+
flex: 0 0 auto;
|
|
174
169
|
}
|
|
175
170
|
|
|
176
171
|
.actions {
|
|
177
172
|
display: flex;
|
|
178
173
|
align-items: center;
|
|
174
|
+
flex: 0 0 auto;
|
|
175
|
+
margin-left: 16px;
|
|
179
176
|
}
|
|
180
177
|
|
|
181
178
|
.show-configuration, &:deep() .actions > button {
|
|
@@ -198,15 +195,17 @@ const showAdditionalActionButtons = computed(() => isArray(additionalActions));
|
|
|
198
195
|
max-width: 60%;
|
|
199
196
|
}
|
|
200
197
|
|
|
201
|
-
//
|
|
198
|
+
// Title takes the remaining row space; min-width: 0 lets its children
|
|
199
|
+
// (resource-name) shrink so the action buttons stay visible on narrow viewports.
|
|
202
200
|
.title {
|
|
203
|
-
|
|
201
|
+
flex: 1 1 auto;
|
|
202
|
+
min-width: 0;
|
|
204
203
|
}
|
|
205
204
|
|
|
206
|
-
// We want the resource name to be what collaspes wh
|
|
207
205
|
.resource-name {
|
|
208
206
|
display: inline-block;
|
|
209
|
-
flex: 1;
|
|
207
|
+
flex: 0 1 auto;
|
|
208
|
+
min-width: 0;
|
|
210
209
|
white-space: nowrap;
|
|
211
210
|
overflow-x: hidden;
|
|
212
211
|
overflow-y: clip;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { mapGetters } from 'vuex';
|
|
3
3
|
import Favorite from '@shell/components/nav/Favorite';
|
|
4
4
|
import TypeDescription from '@shell/components/TypeDescription';
|
|
5
|
+
import { RcButton } from '@components/RcButton';
|
|
5
6
|
import { get } from '@shell/utils/object';
|
|
6
7
|
import { AS, _YAML } from '@shell/config/query-params';
|
|
7
8
|
import ResourceLoadingIndicator from './ResourceLoadingIndicator';
|
|
@@ -16,6 +17,7 @@ export default {
|
|
|
16
17
|
|
|
17
18
|
components: {
|
|
18
19
|
Favorite,
|
|
20
|
+
RcButton,
|
|
19
21
|
TypeDescription,
|
|
20
22
|
ResourceLoadingIndicator,
|
|
21
23
|
TabTitle
|
|
@@ -221,22 +223,24 @@ export default {
|
|
|
221
223
|
<slot name="extraActions" />
|
|
222
224
|
|
|
223
225
|
<slot name="createButton">
|
|
224
|
-
<
|
|
226
|
+
<RcButton
|
|
225
227
|
v-if="hasEditComponent && _isCreatable"
|
|
226
|
-
|
|
227
|
-
|
|
228
|
+
variant="primary"
|
|
229
|
+
size="large"
|
|
228
230
|
:data-testid="componentTestid+'-create'"
|
|
231
|
+
:to="_createLocation"
|
|
229
232
|
>
|
|
230
233
|
{{ _createButtonlabel }}
|
|
231
|
-
</
|
|
232
|
-
<
|
|
234
|
+
</RcButton>
|
|
235
|
+
<RcButton
|
|
233
236
|
v-else-if="_isYamlCreatable"
|
|
234
|
-
|
|
235
|
-
|
|
237
|
+
variant="primary"
|
|
238
|
+
size="large"
|
|
236
239
|
:data-testid="componentTestid+'-create-yaml'"
|
|
240
|
+
:to="_yamlCreateLocation"
|
|
237
241
|
>
|
|
238
242
|
{{ t("resourceList.head.createFromYaml") }}
|
|
239
|
-
</
|
|
243
|
+
</RcButton>
|
|
240
244
|
</slot>
|
|
241
245
|
</div>
|
|
242
246
|
</slot>
|
|
@@ -38,6 +38,10 @@ export default {
|
|
|
38
38
|
type: String,
|
|
39
39
|
default: 'disabled',
|
|
40
40
|
},
|
|
41
|
+
tooltipField: {
|
|
42
|
+
type: String,
|
|
43
|
+
default: 'tooltip',
|
|
44
|
+
},
|
|
41
45
|
|
|
42
46
|
asLink: {
|
|
43
47
|
type: Boolean,
|
|
@@ -104,6 +108,7 @@ export default {
|
|
|
104
108
|
:is="asLink ? 'a' : 'div'"
|
|
105
109
|
v-for="(r, idx) in rows"
|
|
106
110
|
:key="get(r, keyField)"
|
|
111
|
+
v-clean-tooltip="get(r, tooltipField) || null"
|
|
107
112
|
:role="asLink ? 'link' : null"
|
|
108
113
|
:aria-disabled="asLink && get(r, disabledField) === true ? true : null"
|
|
109
114
|
:aria-label="get(r, nameField)"
|
|
@@ -126,16 +131,6 @@ export default {
|
|
|
126
131
|
class="side-label"
|
|
127
132
|
:class="{'indicator': true }"
|
|
128
133
|
/>
|
|
129
|
-
<div v-if="r.deploysOnWindows">
|
|
130
|
-
<label class="deploys-os-label">
|
|
131
|
-
{{ t('catalog.charts.deploysOnWindows') }}
|
|
132
|
-
</label>
|
|
133
|
-
</div>
|
|
134
|
-
<div v-if="r.windowsIncompatible">
|
|
135
|
-
<label class="os-incompatible-label">
|
|
136
|
-
{{ t('catalog.charts.windowsIncompatible') }}
|
|
137
|
-
</label>
|
|
138
|
-
</div>
|
|
139
134
|
<div
|
|
140
135
|
v-if="get(r, sideLabelField)"
|
|
141
136
|
class="side-label"
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import sorting from '@shell/components/SortableTable/sorting';
|
|
2
|
+
|
|
3
|
+
const { arrangedRows } = sorting.computed;
|
|
4
|
+
|
|
5
|
+
describe('sorting mixin', () => {
|
|
6
|
+
describe('arrangedRows', () => {
|
|
7
|
+
function createContext({
|
|
8
|
+
rows = [] as any[],
|
|
9
|
+
sortFields = ['id'],
|
|
10
|
+
descending = false,
|
|
11
|
+
sortGeneration = undefined as string | undefined,
|
|
12
|
+
sortGenerationFn = (() => 'gen1') as (() => string) | undefined,
|
|
13
|
+
externalPaginationEnabled = false,
|
|
14
|
+
cacheKey = null as string | null,
|
|
15
|
+
cachedRows = null as any[] | null,
|
|
16
|
+
cachedRowsRef = null as any[] | null,
|
|
17
|
+
} = {}) {
|
|
18
|
+
return {
|
|
19
|
+
rows,
|
|
20
|
+
sortFields,
|
|
21
|
+
descending,
|
|
22
|
+
sortGeneration,
|
|
23
|
+
sortGenerationFn,
|
|
24
|
+
externalPaginationEnabled,
|
|
25
|
+
cacheKey,
|
|
26
|
+
cachedRows,
|
|
27
|
+
cachedRowsRef,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
it('should return undefined when externalPaginationEnabled is true', () => {
|
|
32
|
+
const ctx = createContext({ externalPaginationEnabled: true });
|
|
33
|
+
|
|
34
|
+
expect(arrangedRows.call(ctx)).toBeUndefined();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should sort rows by the given sort fields', () => {
|
|
38
|
+
const rows = [{ id: 'b' }, { id: 'a' }, { id: 'c' }];
|
|
39
|
+
const ctx = createContext({ rows, sortGenerationFn: undefined });
|
|
40
|
+
|
|
41
|
+
const result = arrangedRows.call(ctx);
|
|
42
|
+
|
|
43
|
+
expect(result.map((r: any) => r.id)).toStrictEqual(['a', 'b', 'c']);
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should cache results when sortGenerationFn is provided', () => {
|
|
47
|
+
const rows = [{ id: 'b' }, { id: 'a' }];
|
|
48
|
+
const ctx = createContext({ rows });
|
|
49
|
+
|
|
50
|
+
const result1 = arrangedRows.call(ctx);
|
|
51
|
+
|
|
52
|
+
expect(ctx.cacheKey).not.toBeNull();
|
|
53
|
+
expect(ctx.cachedRows).toStrictEqual(result1);
|
|
54
|
+
|
|
55
|
+
const result2 = arrangedRows.call(ctx);
|
|
56
|
+
|
|
57
|
+
expect(result2).toBe(ctx.cachedRows);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it('should invalidate cache when rows change to different items with the same count', () => {
|
|
61
|
+
const rowsA = [{ id: 'alpha' }];
|
|
62
|
+
const rowsB = [{ id: 'beta' }];
|
|
63
|
+
const ctx = createContext({ rows: rowsA });
|
|
64
|
+
|
|
65
|
+
const resultA = arrangedRows.call(ctx);
|
|
66
|
+
|
|
67
|
+
expect(resultA.map((r: any) => r.id)).toStrictEqual(['alpha']);
|
|
68
|
+
|
|
69
|
+
ctx.rows = rowsB;
|
|
70
|
+
const resultB = arrangedRows.call(ctx);
|
|
71
|
+
|
|
72
|
+
expect(resultB.map((r: any) => r.id)).toStrictEqual(['beta']);
|
|
73
|
+
});
|
|
74
|
+
|
|
75
|
+
it('should return cached rows when same rows are passed again', () => {
|
|
76
|
+
const rows = [{ id: 'x' }, { id: 'y' }];
|
|
77
|
+
const ctx = createContext({ rows });
|
|
78
|
+
|
|
79
|
+
arrangedRows.call(ctx);
|
|
80
|
+
const cached = ctx.cachedRows;
|
|
81
|
+
|
|
82
|
+
const result = arrangedRows.call(ctx);
|
|
83
|
+
|
|
84
|
+
expect(result).toBe(cached);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should invalidate cache when descending changes', () => {
|
|
88
|
+
const rows = [{ id: 'a' }, { id: 'b' }];
|
|
89
|
+
const ctx = createContext({ rows });
|
|
90
|
+
|
|
91
|
+
arrangedRows.call(ctx);
|
|
92
|
+
|
|
93
|
+
ctx.descending = true;
|
|
94
|
+
const result = arrangedRows.call(ctx);
|
|
95
|
+
|
|
96
|
+
expect(result.map((r: any) => r.id)).toStrictEqual(['b', 'a']);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
it('should not cache when there is no sortGenerationFn or sortGeneration', () => {
|
|
100
|
+
const rows = [{ id: 'a' }];
|
|
101
|
+
const ctx = createContext({ rows });
|
|
102
|
+
|
|
103
|
+
ctx.sortGenerationFn = undefined;
|
|
104
|
+
ctx.sortGeneration = undefined;
|
|
105
|
+
|
|
106
|
+
arrangedRows.call(ctx);
|
|
107
|
+
|
|
108
|
+
expect(ctx.cacheKey).toBeNull();
|
|
109
|
+
expect(ctx.cachedRows).toBeNull();
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it('should use sortGeneration over sortGenerationFn when provided', () => {
|
|
113
|
+
const rows = [{ id: 'a' }];
|
|
114
|
+
const ctx = createContext({
|
|
115
|
+
rows,
|
|
116
|
+
sortGeneration: 'custom-gen',
|
|
117
|
+
sortGenerationFn: () => 'fn-gen',
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
arrangedRows.call(ctx);
|
|
121
|
+
|
|
122
|
+
expect(ctx.cacheKey).toContain('custom-gen');
|
|
123
|
+
expect(ctx.cacheKey).not.toContain('fn-gen');
|
|
124
|
+
});
|
|
125
|
+
});
|
|
126
|
+
});
|
|
@@ -26,6 +26,7 @@ import ButtonMultiAction from '@shell/components/ButtonMultiAction.vue';
|
|
|
26
26
|
import ActionMenu from '@shell/components/ActionMenuShell.vue';
|
|
27
27
|
import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
|
|
28
28
|
import ActionDropdownShell from '@shell/components/ActionDropdownShell.vue';
|
|
29
|
+
import { RcButton } from '@components/RcButton';
|
|
29
30
|
import { useTabCountUpdater } from '@shell/components/form/ResourceTabs/composable';
|
|
30
31
|
|
|
31
32
|
// Uncomment for table performance debugging
|
|
@@ -65,6 +66,7 @@ export default {
|
|
|
65
66
|
ButtonMultiAction,
|
|
66
67
|
ActionMenu,
|
|
67
68
|
ActionDropdownShell,
|
|
69
|
+
RcButton,
|
|
68
70
|
},
|
|
69
71
|
|
|
70
72
|
mixins: [
|
|
@@ -1116,17 +1118,17 @@ export default {
|
|
|
1116
1118
|
>
|
|
1117
1119
|
<slot name="header-left">
|
|
1118
1120
|
<template v-if="tableActions">
|
|
1119
|
-
<
|
|
1121
|
+
<RcButton
|
|
1120
1122
|
v-for="(act) in availableActions"
|
|
1121
1123
|
:id="act.action"
|
|
1122
1124
|
:key="act.action"
|
|
1123
1125
|
v-clean-tooltip="actionTooltip"
|
|
1124
1126
|
type="button"
|
|
1125
|
-
|
|
1127
|
+
variant="primary"
|
|
1128
|
+
size="large"
|
|
1126
1129
|
:class="{[bulkActionClass]:true}"
|
|
1127
1130
|
:disabled="!act.enabled"
|
|
1128
1131
|
:data-testid="componentTestid + '-' + act.action"
|
|
1129
|
-
role="button"
|
|
1130
1132
|
:aria-label="act.label"
|
|
1131
1133
|
@click="applyTableAction(act, null, $event)"
|
|
1132
1134
|
@keydown.enter.stop
|
|
@@ -1138,7 +1140,7 @@ export default {
|
|
|
1138
1140
|
:class="act.icon"
|
|
1139
1141
|
/>
|
|
1140
1142
|
<span v-clean-html="act.label" />
|
|
1141
|
-
</
|
|
1143
|
+
</RcButton>
|
|
1142
1144
|
<template v-if="featureDropdownMenu">
|
|
1143
1145
|
<ActionDropdownShell
|
|
1144
1146
|
:disabled="!selectedRows.length"
|
|
@@ -2154,11 +2156,6 @@ export default {
|
|
|
2154
2156
|
}
|
|
2155
2157
|
}
|
|
2156
2158
|
|
|
2157
|
-
.bulk-action {
|
|
2158
|
-
.icon {
|
|
2159
|
-
vertical-align: -10%;
|
|
2160
|
-
}
|
|
2161
|
-
}
|
|
2162
2159
|
}
|
|
2163
2160
|
|
|
2164
2161
|
.middle {
|
|
@@ -626,27 +626,45 @@ function _execute(resources, action, args, opts = {}, ctx) {
|
|
|
626
626
|
return action.invoke.apply(ctx, [actionOpts, resources || [], args]);
|
|
627
627
|
}
|
|
628
628
|
|
|
629
|
+
/**
|
|
630
|
+
* for the given resource find it's action matching the target action. if that target action has an alt resource return it
|
|
631
|
+
*/
|
|
632
|
+
const findResourceFromAction = (r) => {
|
|
633
|
+
const actualAction = r.availableActions.find((aa) => aa.action === action.action);
|
|
634
|
+
|
|
635
|
+
return actualAction?.altResource || r;
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
// if there there are multiple resources and a bulk action, use it and pass in the resources
|
|
639
|
+
// for example cluster management cluster list Download KubeConfig
|
|
629
640
|
if ( resources.length > 1 && action.bulkAction && !opts.alt ) {
|
|
630
|
-
const
|
|
641
|
+
const applyResource = findResourceFromAction(resources[0]);
|
|
642
|
+
const fn = applyResource[action.bulkAction];
|
|
631
643
|
|
|
632
644
|
if ( fn ) {
|
|
633
|
-
|
|
645
|
+
const applyResources = resources.map(findResourceFromAction);
|
|
646
|
+
|
|
647
|
+
return fn.call(applyResource, applyResources, ...args);
|
|
634
648
|
}
|
|
635
649
|
}
|
|
636
650
|
|
|
637
651
|
const promises = [];
|
|
638
652
|
|
|
653
|
+
// if there is a single resource or no bulk action, for each resource execute it's action
|
|
654
|
+
// for example delete when only one row is selected
|
|
639
655
|
for ( const resource of resources ) {
|
|
640
656
|
let fn;
|
|
641
657
|
|
|
658
|
+
const applyResource = findResourceFromAction(resource);
|
|
659
|
+
|
|
642
660
|
if (opts.alt && action.altAction) {
|
|
643
|
-
fn =
|
|
661
|
+
fn = applyResource[action.altAction];
|
|
644
662
|
} else {
|
|
645
|
-
fn =
|
|
663
|
+
fn = applyResource[action.action];
|
|
646
664
|
}
|
|
647
665
|
|
|
648
666
|
if ( fn ) {
|
|
649
|
-
promises.push(fn.apply(
|
|
667
|
+
promises.push(fn.apply(applyResource, args));
|
|
650
668
|
}
|
|
651
669
|
}
|
|
652
670
|
|
|
@@ -50,7 +50,8 @@ export default {
|
|
|
50
50
|
|
|
51
51
|
if ( sortGenerationKey) {
|
|
52
52
|
key = `${ sortGenerationKey }/${ this.rows.length }/${ this.descending }/${ this.sortFields.join(',') }`;
|
|
53
|
-
|
|
53
|
+
|
|
54
|
+
if ( this.cacheKey === key && this.cachedRowsRef === this.rows ) {
|
|
54
55
|
return this.cachedRows;
|
|
55
56
|
}
|
|
56
57
|
}
|
|
@@ -60,6 +61,7 @@ export default {
|
|
|
60
61
|
if ( key ) {
|
|
61
62
|
this.cacheKey = key;
|
|
62
63
|
this.cachedRows = out;
|
|
64
|
+
this.cachedRowsRef = this.rows;
|
|
63
65
|
}
|
|
64
66
|
|
|
65
67
|
return out;
|
|
@@ -104,8 +106,9 @@ export default {
|
|
|
104
106
|
return {
|
|
105
107
|
sortBy,
|
|
106
108
|
descending,
|
|
107
|
-
cachedRows:
|
|
108
|
-
|
|
109
|
+
cachedRows: null,
|
|
110
|
+
cachedRowsRef: null,
|
|
111
|
+
cacheKey: null,
|
|
109
112
|
};
|
|
110
113
|
},
|
|
111
114
|
|
package/components/Wizard.vue
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
import { _CREATE, _VIEW } from '@shell/config/query-params';
|
|
3
3
|
import AsyncButton from '@shell/components/AsyncButton';
|
|
4
4
|
import { Banner } from '@components/Banner';
|
|
5
|
+
import { RcButton } from '@components/RcButton';
|
|
5
6
|
import Loading from '@shell/components/Loading';
|
|
6
7
|
import { stringify } from '@shell/utils/error';
|
|
7
8
|
import LazyImage from '@shell/components/LazyImage';
|
|
@@ -28,6 +29,7 @@ export default {
|
|
|
28
29
|
components: {
|
|
29
30
|
AsyncButton,
|
|
30
31
|
Banner,
|
|
32
|
+
RcButton,
|
|
31
33
|
Loading,
|
|
32
34
|
LazyImage,
|
|
33
35
|
},
|
|
@@ -44,7 +46,6 @@ export default {
|
|
|
44
46
|
loading: Wizard will block until all steps are not loading
|
|
45
47
|
nextButton?: {
|
|
46
48
|
labelKey?: default to `wizard.next`
|
|
47
|
-
style?: defaults to `btn role-primary`
|
|
48
49
|
},
|
|
49
50
|
previousButton: {
|
|
50
51
|
disable: defaults to false
|
|
@@ -185,9 +186,6 @@ export default {
|
|
|
185
186
|
return this.steps.filter((step) => !step.hidden);
|
|
186
187
|
},
|
|
187
188
|
|
|
188
|
-
nextButtonStyle() {
|
|
189
|
-
return this.activeStep.nextButton?.style || `btn role-primary`;
|
|
190
|
-
},
|
|
191
189
|
nextButtonLabel() {
|
|
192
190
|
return this.activeStep.nextButton?.labelKey || `wizard.next`;
|
|
193
191
|
}
|
|
@@ -444,13 +442,14 @@ export default {
|
|
|
444
442
|
name="cancel"
|
|
445
443
|
:cancel="cancel"
|
|
446
444
|
>
|
|
447
|
-
<
|
|
445
|
+
<RcButton
|
|
448
446
|
type="button"
|
|
449
|
-
|
|
447
|
+
variant="secondary"
|
|
448
|
+
size="large"
|
|
450
449
|
@click="cancel"
|
|
451
450
|
>
|
|
452
451
|
<t k="generic.cancel" />
|
|
453
|
-
</
|
|
452
|
+
</RcButton>
|
|
454
453
|
</slot>
|
|
455
454
|
<div class="controls-steps">
|
|
456
455
|
<slot
|
|
@@ -458,14 +457,15 @@ export default {
|
|
|
458
457
|
name="back"
|
|
459
458
|
:back="back"
|
|
460
459
|
>
|
|
461
|
-
<
|
|
460
|
+
<RcButton
|
|
462
461
|
:disabled="!canPrevious || (!editFirstStep && activeStepIndex===1)"
|
|
463
462
|
type="button"
|
|
464
|
-
|
|
463
|
+
variant="secondary"
|
|
464
|
+
size="large"
|
|
465
465
|
@click="back()"
|
|
466
466
|
>
|
|
467
467
|
<t k="wizard.previous" />
|
|
468
|
-
</
|
|
468
|
+
</RcButton>
|
|
469
469
|
</slot>
|
|
470
470
|
<slot
|
|
471
471
|
v-if="activeStepIndex === visibleSteps.length-1"
|
|
@@ -484,14 +484,15 @@ export default {
|
|
|
484
484
|
name="next"
|
|
485
485
|
:next="next"
|
|
486
486
|
>
|
|
487
|
-
<
|
|
487
|
+
<RcButton
|
|
488
488
|
:disabled="!canNext"
|
|
489
489
|
type="button"
|
|
490
|
-
|
|
490
|
+
variant="primary"
|
|
491
|
+
size="large"
|
|
491
492
|
@click="next()"
|
|
492
493
|
>
|
|
493
494
|
<t :k="nextButtonLabel" />
|
|
494
|
-
</
|
|
495
|
+
</RcButton>
|
|
495
496
|
</slot>
|
|
496
497
|
</div>
|
|
497
498
|
</div>
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import CountBox from '@shell/components/CountBox.vue';
|
|
3
|
+
|
|
4
|
+
describe('component: CountBox', () => {
|
|
5
|
+
const defaultProps = {
|
|
6
|
+
name: 'Test',
|
|
7
|
+
count: 5,
|
|
8
|
+
primaryColorVar: '--sizzle-1',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
describe('when clickable is false', () => {
|
|
12
|
+
it('should render as a div', () => {
|
|
13
|
+
const wrapper = shallowMount(CountBox, { props: defaultProps });
|
|
14
|
+
|
|
15
|
+
expect(wrapper.element.tagName).toBe('DIV');
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
it('should not have the clickable class', () => {
|
|
19
|
+
const wrapper = shallowMount(CountBox, { props: defaultProps });
|
|
20
|
+
|
|
21
|
+
expect(wrapper.classes()).not.toContain('clickable');
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
it('should not emit click event when clicked', async() => {
|
|
25
|
+
const wrapper = shallowMount(CountBox, { props: defaultProps });
|
|
26
|
+
|
|
27
|
+
await wrapper.trigger('click');
|
|
28
|
+
|
|
29
|
+
expect(wrapper.emitted('click')).toBeUndefined();
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
describe('when clickable is true', () => {
|
|
34
|
+
it('should have the clickable class', () => {
|
|
35
|
+
const wrapper = shallowMount(CountBox, {
|
|
36
|
+
props: {
|
|
37
|
+
...defaultProps,
|
|
38
|
+
clickable: true,
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
expect(wrapper.classes()).toContain('clickable');
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
it('should emit click event when clicked', async() => {
|
|
46
|
+
const wrapper = shallowMount(CountBox, {
|
|
47
|
+
props: {
|
|
48
|
+
...defaultProps,
|
|
49
|
+
clickable: true,
|
|
50
|
+
},
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
await wrapper.trigger('click');
|
|
54
|
+
|
|
55
|
+
expect(wrapper.emitted('click')).toHaveLength(1);
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe('display', () => {
|
|
60
|
+
it('should display the count', () => {
|
|
61
|
+
const wrapper = shallowMount(CountBox, { props: defaultProps });
|
|
62
|
+
|
|
63
|
+
expect(wrapper.find('h1').text()).toBe('5');
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
it('should display the name', () => {
|
|
67
|
+
const wrapper = shallowMount(CountBox, { props: defaultProps });
|
|
68
|
+
|
|
69
|
+
expect(wrapper.find('label').text()).toBe('Test');
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
});
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { mount } from '@vue/test-utils';
|
|
2
|
+
|
|
3
|
+
import DetailText from '@shell/components/DetailText.vue';
|
|
4
|
+
|
|
5
|
+
jest.mock('@shell/utils/clipboard', () => ({ copyTextToClipboard: jest.fn() }));
|
|
6
|
+
|
|
7
|
+
describe('component: DetailText', () => {
|
|
8
|
+
const defaultMocks = {
|
|
9
|
+
$store: {
|
|
10
|
+
getters: {
|
|
11
|
+
'i18n/t': jest.fn((key: string) => `%${ key }%`),
|
|
12
|
+
'prefs/get': jest.fn(() => true),
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
describe('concealment', () => {
|
|
18
|
+
it('should not render the actual secret value in the content area when concealed', () => {
|
|
19
|
+
const secretValue = 'super-secret-password-xyz';
|
|
20
|
+
const wrapper = mount(DetailText, {
|
|
21
|
+
props: {
|
|
22
|
+
value: secretValue,
|
|
23
|
+
conceal: true,
|
|
24
|
+
label: 'Password',
|
|
25
|
+
},
|
|
26
|
+
|
|
27
|
+
global: {
|
|
28
|
+
mocks: defaultMocks,
|
|
29
|
+
directives: {
|
|
30
|
+
'clean-html': () => {},
|
|
31
|
+
'clean-tooltip': () => {},
|
|
32
|
+
t: () => {},
|
|
33
|
+
},
|
|
34
|
+
stubs: {
|
|
35
|
+
CopyToClipboard: true,
|
|
36
|
+
CodeMirror: true,
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
const concealedSpan = wrapper.find('[data-testid="detail-top_html"]');
|
|
42
|
+
|
|
43
|
+
expect(concealedSpan.exists()).toBe(true);
|
|
44
|
+
expect(concealedSpan.classes()).toContain('conceal');
|
|
45
|
+
expect(concealedSpan.text()).not.toContain(secretValue);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should render the actual value when not concealed', () => {
|
|
49
|
+
const visibleValue = 'visible-value-123';
|
|
50
|
+
const wrapper = mount(DetailText, {
|
|
51
|
+
props: {
|
|
52
|
+
value: visibleValue,
|
|
53
|
+
conceal: false,
|
|
54
|
+
label: 'Data',
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
global: {
|
|
58
|
+
mocks: defaultMocks,
|
|
59
|
+
directives: {
|
|
60
|
+
'clean-html': (el: HTMLElement, binding: { value: string }) => {
|
|
61
|
+
el.innerHTML = binding.value;
|
|
62
|
+
},
|
|
63
|
+
'clean-tooltip': () => {},
|
|
64
|
+
t: () => {},
|
|
65
|
+
},
|
|
66
|
+
stubs: {
|
|
67
|
+
CopyToClipboard: true,
|
|
68
|
+
CodeMirror: true,
|
|
69
|
+
},
|
|
70
|
+
},
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
const contentSpan = wrapper.find('[data-testid="detail-top_html"]');
|
|
74
|
+
|
|
75
|
+
expect(contentSpan.exists()).toBe(true);
|
|
76
|
+
expect(contentSpan.classes()).not.toContain('conceal');
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
it('should not render JSON secret values in CodeMirror when concealed', () => {
|
|
80
|
+
const jsonSecret = '{"api_key": "secret-key-123"}';
|
|
81
|
+
const wrapper = mount(DetailText, {
|
|
82
|
+
props: {
|
|
83
|
+
value: jsonSecret,
|
|
84
|
+
conceal: true,
|
|
85
|
+
label: 'Config',
|
|
86
|
+
},
|
|
87
|
+
|
|
88
|
+
global: {
|
|
89
|
+
mocks: defaultMocks,
|
|
90
|
+
directives: {
|
|
91
|
+
'clean-html': () => {},
|
|
92
|
+
'clean-tooltip': () => {},
|
|
93
|
+
t: () => {},
|
|
94
|
+
},
|
|
95
|
+
stubs: {
|
|
96
|
+
CopyToClipboard: true,
|
|
97
|
+
CodeMirror: true,
|
|
98
|
+
},
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
const codeMirror = wrapper.findComponent({ name: 'CodeMirror' });
|
|
103
|
+
|
|
104
|
+
expect(codeMirror.exists()).toBe(false);
|
|
105
|
+
|
|
106
|
+
const concealedSpan = wrapper.find('[data-testid="detail-top_html"]');
|
|
107
|
+
|
|
108
|
+
expect(concealedSpan.exists()).toBe(true);
|
|
109
|
+
expect(concealedSpan.classes()).toContain('conceal');
|
|
110
|
+
expect(concealedSpan.text()).not.toContain('secret-key-123');
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
});
|