@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
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { shallowMount } from '@vue/test-utils';
|
|
2
|
+
import FleetSummaryGraph from '@shell/components/formatter/FleetSummaryGraph.vue';
|
|
3
|
+
import { FLEET } from '@shell/config/types';
|
|
4
|
+
import { ExtendedVue, Vue } from 'vue/types/vue';
|
|
5
|
+
import { DefaultProps } from 'vue/types/options';
|
|
6
|
+
|
|
7
|
+
const FleetSummaryGraphComponent = FleetSummaryGraph as unknown as ExtendedVue<Vue, {}, {}, {}, DefaultProps>;
|
|
8
|
+
|
|
9
|
+
function makeRow({
|
|
10
|
+
type = FLEET.GIT_REPO,
|
|
11
|
+
resourceCounts = {},
|
|
12
|
+
targetClusters = [],
|
|
13
|
+
statusResourceCountsForCluster = undefined,
|
|
14
|
+
}: {
|
|
15
|
+
type?: string;
|
|
16
|
+
resourceCounts?: Record<string, number>;
|
|
17
|
+
targetClusters?: any[];
|
|
18
|
+
statusResourceCountsForCluster?: any;
|
|
19
|
+
} = {}) {
|
|
20
|
+
const row: Record<string, any> = {
|
|
21
|
+
id: 'test-ns/test-row',
|
|
22
|
+
type,
|
|
23
|
+
status: { resourceCounts },
|
|
24
|
+
targetClusters,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
if (statusResourceCountsForCluster !== undefined) {
|
|
28
|
+
row.statusResourceCountsForCluster = statusResourceCountsForCluster;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return row;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
describe('component: FleetSummaryGraph', () => {
|
|
35
|
+
describe('summary', () => {
|
|
36
|
+
it('returns status.resourceCounts for GitRepo rows', () => {
|
|
37
|
+
const resourceCounts = {
|
|
38
|
+
desiredReady: 7,
|
|
39
|
+
ready: 7,
|
|
40
|
+
};
|
|
41
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, {
|
|
42
|
+
propsData: {
|
|
43
|
+
row: makeRow({
|
|
44
|
+
resourceCounts,
|
|
45
|
+
targetClusters: [{ id: 'cluster-1' }],
|
|
46
|
+
}),
|
|
47
|
+
},
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
expect((wrapper.vm as any).summary).toStrictEqual(resourceCounts);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
it('returns status.resourceCounts for HelmOp rows', () => {
|
|
54
|
+
const resourceCounts = {
|
|
55
|
+
desiredReady: 3,
|
|
56
|
+
ready: 2,
|
|
57
|
+
modified: 1,
|
|
58
|
+
};
|
|
59
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, {
|
|
60
|
+
propsData: {
|
|
61
|
+
row: makeRow({
|
|
62
|
+
type: FLEET.HELM_OP,
|
|
63
|
+
resourceCounts,
|
|
64
|
+
targetClusters: [{ id: 'cluster-1' }],
|
|
65
|
+
}),
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
expect((wrapper.vm as any).summary).toStrictEqual(resourceCounts);
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
it('does not return function when row has statusResourceCountsForCluster as a method', () => {
|
|
73
|
+
const resourceCounts = {
|
|
74
|
+
desiredReady: 5,
|
|
75
|
+
ready: 5,
|
|
76
|
+
};
|
|
77
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, {
|
|
78
|
+
propsData: {
|
|
79
|
+
row: makeRow({
|
|
80
|
+
resourceCounts,
|
|
81
|
+
targetClusters: [{ id: 'cluster-1' }],
|
|
82
|
+
// Simulate a class method — the bug was that a truthy function
|
|
83
|
+
// caused summary to return the function itself instead of resourceCounts
|
|
84
|
+
statusResourceCountsForCluster: (clusterId: string) => ({ desiredReady: 0 }),
|
|
85
|
+
}),
|
|
86
|
+
},
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
const summary = (wrapper.vm as any).summary;
|
|
90
|
+
|
|
91
|
+
expect(typeof summary).not.toBe('function');
|
|
92
|
+
expect(summary).toStrictEqual(resourceCounts);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
it('calls statusResourceCountsForCluster with clusterId when clusterId prop is set', () => {
|
|
96
|
+
const perClusterData = {
|
|
97
|
+
desiredReady: 2,
|
|
98
|
+
ready: 1,
|
|
99
|
+
};
|
|
100
|
+
const mockFn = jest.fn().mockReturnValue(perClusterData);
|
|
101
|
+
|
|
102
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, {
|
|
103
|
+
propsData: {
|
|
104
|
+
row: makeRow({ statusResourceCountsForCluster: mockFn }),
|
|
105
|
+
clusterId: 'cluster-1',
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
expect((wrapper.vm as any).summary).toStrictEqual(perClusterData);
|
|
110
|
+
expect(mockFn).toHaveBeenCalledWith('cluster-1');
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it('returns empty object when status.resourceCounts is undefined', () => {
|
|
114
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, { propsData: { row: makeRow() } });
|
|
115
|
+
|
|
116
|
+
expect((wrapper.vm as any).summary).toStrictEqual({});
|
|
117
|
+
});
|
|
118
|
+
});
|
|
119
|
+
|
|
120
|
+
describe('show', () => {
|
|
121
|
+
it('returns true when stateParts exist and row has targetClusters', () => {
|
|
122
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, {
|
|
123
|
+
propsData: {
|
|
124
|
+
row: makeRow({
|
|
125
|
+
resourceCounts: {
|
|
126
|
+
desiredReady: 5,
|
|
127
|
+
ready: 5,
|
|
128
|
+
},
|
|
129
|
+
targetClusters: [{ id: 'cluster-1' }],
|
|
130
|
+
}),
|
|
131
|
+
},
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
expect((wrapper.vm as any).show).toBeTruthy();
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
it('returns false when stateParts exist but targetClusters is empty', () => {
|
|
138
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, {
|
|
139
|
+
propsData: {
|
|
140
|
+
row: makeRow({
|
|
141
|
+
resourceCounts: {
|
|
142
|
+
desiredReady: 5,
|
|
143
|
+
ready: 5,
|
|
144
|
+
},
|
|
145
|
+
targetClusters: [],
|
|
146
|
+
}),
|
|
147
|
+
},
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
expect((wrapper.vm as any).show).toBeFalsy();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('returns true for FLEET.CLUSTER type even without targetClusters', () => {
|
|
154
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, {
|
|
155
|
+
propsData: {
|
|
156
|
+
row: makeRow({
|
|
157
|
+
type: FLEET.CLUSTER,
|
|
158
|
+
resourceCounts: {
|
|
159
|
+
desiredReady: 3,
|
|
160
|
+
ready: 3,
|
|
161
|
+
},
|
|
162
|
+
}),
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
expect((wrapper.vm as any).show).toBeTruthy();
|
|
167
|
+
});
|
|
168
|
+
|
|
169
|
+
it('returns false when resourceCounts is empty', () => {
|
|
170
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, { propsData: { row: makeRow({ targetClusters: [{ id: 'cluster-1' }] }) } });
|
|
171
|
+
|
|
172
|
+
expect((wrapper.vm as any).show).toBeFalsy();
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
describe('stateParts', () => {
|
|
177
|
+
it('filters out keys starting with "desired"', () => {
|
|
178
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, {
|
|
179
|
+
propsData: {
|
|
180
|
+
row: makeRow({
|
|
181
|
+
resourceCounts: {
|
|
182
|
+
desiredReady: 5,
|
|
183
|
+
ready: 5,
|
|
184
|
+
},
|
|
185
|
+
targetClusters: [{ id: 'cluster-1' }],
|
|
186
|
+
}),
|
|
187
|
+
},
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
const parts = (wrapper.vm as any).stateParts;
|
|
191
|
+
|
|
192
|
+
expect(parts.every((p: any) => !p.label.startsWith('Desired'))).toBe(true);
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
it('filters out entries with value 0', () => {
|
|
196
|
+
const wrapper = shallowMount(FleetSummaryGraphComponent, {
|
|
197
|
+
propsData: {
|
|
198
|
+
row: makeRow({
|
|
199
|
+
resourceCounts: {
|
|
200
|
+
desiredReady: 5,
|
|
201
|
+
ready: 5,
|
|
202
|
+
notReady: 0,
|
|
203
|
+
},
|
|
204
|
+
targetClusters: [{ id: 'cluster-1' }],
|
|
205
|
+
}),
|
|
206
|
+
},
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
const parts = (wrapper.vm as any).stateParts;
|
|
210
|
+
const labels = parts.map((p: any) => p.label);
|
|
211
|
+
|
|
212
|
+
expect(labels).toContain('Ready');
|
|
213
|
+
expect(labels).not.toContain('NotReady');
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
});
|
|
@@ -7,11 +7,9 @@ describe('component: PodsUsage', () => {
|
|
|
7
7
|
props: {
|
|
8
8
|
row: {
|
|
9
9
|
isReady: true,
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
allocatable: { pods: 20 }
|
|
14
|
-
}
|
|
10
|
+
status: {
|
|
11
|
+
requested: { pods: 10 },
|
|
12
|
+
allocatable: { pods: 20 }
|
|
15
13
|
}
|
|
16
14
|
}
|
|
17
15
|
},
|
|
@@ -28,11 +26,9 @@ describe('component: PodsUsage', () => {
|
|
|
28
26
|
props: {
|
|
29
27
|
row: {
|
|
30
28
|
isReady: true,
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
allocatable: { pods: 0 }
|
|
35
|
-
}
|
|
29
|
+
status: {
|
|
30
|
+
requested: { pods: 10 },
|
|
31
|
+
allocatable: { pods: 0 }
|
|
36
32
|
}
|
|
37
33
|
}
|
|
38
34
|
},
|
package/components/nav/Group.vue
CHANGED
|
@@ -82,7 +82,8 @@ export default {
|
|
|
82
82
|
const validRoute = filterLocationValidParams(this.$router, overviewRoute || {});
|
|
83
83
|
const route = this.$router.resolve(validRoute);
|
|
84
84
|
|
|
85
|
-
|
|
85
|
+
// Use .path instead of .fullPath to ignore query parameters and hashes when comparing routes
|
|
86
|
+
return this.$route.path === route?.path;
|
|
86
87
|
}
|
|
87
88
|
}
|
|
88
89
|
|
|
@@ -204,14 +205,14 @@ export default {
|
|
|
204
205
|
} else if (item.route) {
|
|
205
206
|
const navLevels = ['cluster', 'product', 'resource'];
|
|
206
207
|
const matchesNavLevel = navLevels.filter((param) => !this.$route.params[param] || this.$route.params[param] !== item.route.params[param]).length === 0;
|
|
207
|
-
const withoutHash = this.$route.hash ? this.$route.fullPath.slice(0, this.$route.fullPath.indexOf(this.$route.hash)) : this.$route.fullPath;
|
|
208
|
-
const withoutQuery = withoutHash.split('?')[0];
|
|
209
208
|
const validItemRoute = filterLocationValidParams(this.$router, item.route);
|
|
210
|
-
const itemFullPath = this.$router.resolve(validItemRoute).fullPath;
|
|
211
209
|
|
|
212
|
-
|
|
210
|
+
// Use .path instead of .fullPath to ignore query parameters and hashes when comparing routes
|
|
211
|
+
const itemPath = this.$router.resolve(validItemRoute).path;
|
|
212
|
+
|
|
213
|
+
if (matchesNavLevel || itemPath === this.$route.path) {
|
|
213
214
|
return true;
|
|
214
|
-
} else if (parentPath &&
|
|
215
|
+
} else if (parentPath && itemPath === parentPath) {
|
|
215
216
|
return true;
|
|
216
217
|
}
|
|
217
218
|
}
|
|
@@ -189,12 +189,30 @@ export default {
|
|
|
189
189
|
(this.currentProduct && this.currentProduct.showWorkspaceSwitcher);
|
|
190
190
|
// Don't show if the header is in 'simple' mode
|
|
191
191
|
const notSimple = !this.simple;
|
|
192
|
-
// One of these must be enabled, otherwise
|
|
193
|
-
const validFilterSettings = this.currentProduct?.showNamespaceFilter || this.
|
|
192
|
+
// One of these must be enabled, otherwise there's no component to show
|
|
193
|
+
const validFilterSettings = this.currentProduct?.showNamespaceFilter || this.showWorkspaceSwitcher;
|
|
194
194
|
|
|
195
195
|
return validClusterOrProduct && notSimple && validFilterSettings;
|
|
196
196
|
},
|
|
197
197
|
|
|
198
|
+
/**
|
|
199
|
+
* The workspace switcher should be disabled on detail, edit and create pages.
|
|
200
|
+
* Only list pages should allow changing the workspace.
|
|
201
|
+
*/
|
|
202
|
+
disableWorkspaceSwitcher() {
|
|
203
|
+
// Disable on detail/edit pages (route has an id param)
|
|
204
|
+
if (this.$route?.params?.id) {
|
|
205
|
+
return true;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
// Disable on create pages (route names end with '-create')
|
|
209
|
+
if (this.$route?.name?.endsWith('-create')) {
|
|
210
|
+
return true;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
return false;
|
|
214
|
+
},
|
|
215
|
+
|
|
198
216
|
featureRancherDesktop() {
|
|
199
217
|
return this.$config.rancherEnv === 'desktop';
|
|
200
218
|
},
|
|
@@ -581,7 +599,10 @@ export default {
|
|
|
581
599
|
class="top"
|
|
582
600
|
>
|
|
583
601
|
<NamespaceFilter v-if="clusterReady && currentProduct && (currentProduct.showNamespaceFilter || isExplorer)" />
|
|
584
|
-
<WorkspaceSwitcher
|
|
602
|
+
<WorkspaceSwitcher
|
|
603
|
+
v-else-if="clusterReady && showWorkspaceSwitcher"
|
|
604
|
+
:disabled="disableWorkspaceSwitcher"
|
|
605
|
+
/>
|
|
585
606
|
</div>
|
|
586
607
|
<div
|
|
587
608
|
v-if="currentCluster && !simple"
|
|
@@ -246,7 +246,10 @@ const findNewIndex = (shouldAdvance: boolean, activeIndex: number, itemsArr: Ele
|
|
|
246
246
|
:class="clz"
|
|
247
247
|
/>
|
|
248
248
|
</div>
|
|
249
|
-
<div
|
|
249
|
+
<div
|
|
250
|
+
v-clean-tooltip="item.title"
|
|
251
|
+
class="item-title"
|
|
252
|
+
>
|
|
250
253
|
{{ item.title }}
|
|
251
254
|
</div>
|
|
252
255
|
<button
|
|
@@ -2,17 +2,19 @@
|
|
|
2
2
|
import { useStore } from 'vuex';
|
|
3
3
|
import { computed, inject, ref } from 'vue';
|
|
4
4
|
import { DropdownContext, defaultContext } from '@components/RcDropdown/types';
|
|
5
|
+
import RcButton from '@components/RcButton/RcButton.vue';
|
|
6
|
+
import { RcButtonType } from '@components/RcButton/types';
|
|
5
7
|
|
|
6
8
|
const { dropdownItems } = inject<DropdownContext>('dropdownContext') || defaultContext;
|
|
7
9
|
const store = useStore();
|
|
8
10
|
const unreadCount = computed<number>(() => store.getters['notifications/unreadCount']);
|
|
9
|
-
const markAllReadButton = ref<
|
|
11
|
+
const markAllReadButton = ref<RcButtonType | null>(null);
|
|
10
12
|
|
|
11
13
|
const markAllRead = (keyboard: boolean) => {
|
|
12
14
|
store.dispatch('notifications/markAllRead');
|
|
13
15
|
|
|
14
|
-
// If
|
|
15
|
-
if (keyboard
|
|
16
|
+
// If activated via keyboard, move focus to the next dropdown item
|
|
17
|
+
if (keyboard) {
|
|
16
18
|
moveFocus(true);
|
|
17
19
|
}
|
|
18
20
|
};
|
|
@@ -65,18 +67,19 @@ const gotFocus = (e: Event) => {
|
|
|
65
67
|
{{ t('notificationCenter.title') }}
|
|
66
68
|
</div>
|
|
67
69
|
<div v-if="unreadCount !== 0">
|
|
68
|
-
<
|
|
70
|
+
<RcButton
|
|
69
71
|
ref="markAllReadButton"
|
|
70
|
-
|
|
72
|
+
variant="ghost"
|
|
73
|
+
size="small"
|
|
71
74
|
tabindex="-1"
|
|
72
|
-
|
|
75
|
+
class="mark-all-read"
|
|
73
76
|
data-testid="notifications-center-markall-read"
|
|
74
77
|
@keydown.up.down.stop.prevent="handleKeydown"
|
|
75
78
|
@keydown.enter.space.stop="markAllRead(true)"
|
|
76
79
|
@click="markAllRead(false)"
|
|
77
80
|
>
|
|
78
81
|
{{ t('notificationCenter.markAllRead') }}
|
|
79
|
-
</
|
|
82
|
+
</RcButton>
|
|
80
83
|
</div>
|
|
81
84
|
</div>
|
|
82
85
|
<div class="notification-border" />
|
|
@@ -104,8 +107,17 @@ const gotFocus = (e: Event) => {
|
|
|
104
107
|
flex: 1;
|
|
105
108
|
}
|
|
106
109
|
|
|
107
|
-
|
|
110
|
+
.mark-all-read {
|
|
111
|
+
padding: 0;
|
|
112
|
+
min-height: auto;
|
|
113
|
+
font-size: inherit;
|
|
114
|
+
line-height: inherit;
|
|
108
115
|
color: var(--link);
|
|
116
|
+
|
|
117
|
+
&:hover {
|
|
118
|
+
color: var(--body-text);
|
|
119
|
+
text-decoration: underline;
|
|
120
|
+
}
|
|
109
121
|
}
|
|
110
122
|
}
|
|
111
123
|
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { ref } from 'vue';
|
|
2
|
+
import { mount, shallowMount } from '@vue/test-utils';
|
|
3
|
+
import NotificationHeader from '@shell/components/nav/NotificationCenter/NotificationHeader.vue';
|
|
4
|
+
import { defaultContext } from '@components/RcDropdown/types';
|
|
5
|
+
|
|
6
|
+
const buildStore = (unreadCount = 1) => {
|
|
7
|
+
const dispatch = jest.fn();
|
|
8
|
+
const store = {
|
|
9
|
+
dispatch,
|
|
10
|
+
getters: { 'notifications/unreadCount': unreadCount },
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
return { store, dispatch };
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
const buildGlobal = (store: any) => ({
|
|
17
|
+
provide: {
|
|
18
|
+
store,
|
|
19
|
+
dropdownContext: { ...defaultContext, dropdownItems: ref<HTMLElement[]>([]) },
|
|
20
|
+
},
|
|
21
|
+
mocks: { $store: store },
|
|
22
|
+
});
|
|
23
|
+
|
|
24
|
+
jest.mock('vuex', () => ({ useStore: () => (globalThis as any).__testStore }));
|
|
25
|
+
|
|
26
|
+
describe('component: NotificationHeader', () => {
|
|
27
|
+
afterEach(() => {
|
|
28
|
+
(globalThis as any).__testStore = undefined;
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
it('renders the mark all read action when there are unread notifications', () => {
|
|
32
|
+
const { store } = buildStore(3);
|
|
33
|
+
|
|
34
|
+
(globalThis as any).__testStore = store;
|
|
35
|
+
|
|
36
|
+
const wrapper = shallowMount(NotificationHeader, { global: buildGlobal(store) });
|
|
37
|
+
|
|
38
|
+
expect(wrapper.find('[data-testid="notifications-center-markall-read"]').exists()).toBe(true);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('hides the mark all read action when there are no unread notifications', () => {
|
|
42
|
+
const { store } = buildStore(0);
|
|
43
|
+
|
|
44
|
+
(globalThis as any).__testStore = store;
|
|
45
|
+
|
|
46
|
+
const wrapper = shallowMount(NotificationHeader, { global: buildGlobal(store) });
|
|
47
|
+
|
|
48
|
+
expect(wrapper.find('[data-testid="notifications-center-markall-read"]').exists()).toBe(false);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('dispatches notifications/markAllRead when clicked', async() => {
|
|
52
|
+
const { store, dispatch } = buildStore(2);
|
|
53
|
+
|
|
54
|
+
(globalThis as any).__testStore = store;
|
|
55
|
+
|
|
56
|
+
const wrapper = mount(NotificationHeader, { global: buildGlobal(store) });
|
|
57
|
+
|
|
58
|
+
await wrapper.find('[data-testid="notifications-center-markall-read"]').trigger('click');
|
|
59
|
+
|
|
60
|
+
expect(dispatch).toHaveBeenCalledWith('notifications/markAllRead');
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Regression test for https://github.com/rancher/dashboard/issues/16923
|
|
64
|
+
// "Mark all as read" was originally an <a href="#"> which, on click, navigated
|
|
65
|
+
// to "#" and stripped any existing URL hash fragment (e.g. #pod). Rendering it
|
|
66
|
+
// as a <button> (via RcButton) removes the default navigation behavior entirely,
|
|
67
|
+
// so the URL hash is preserved and extensions scoped via LocationConfig.hash
|
|
68
|
+
// continue to match after activation.
|
|
69
|
+
it('renders mark all read as a <button> so activating it cannot strip the URL hash', () => {
|
|
70
|
+
const { store } = buildStore(2);
|
|
71
|
+
|
|
72
|
+
(globalThis as any).__testStore = store;
|
|
73
|
+
|
|
74
|
+
const wrapper = mount(NotificationHeader, { global: buildGlobal(store) });
|
|
75
|
+
const markAll = wrapper.find('[data-testid="notifications-center-markall-read"]');
|
|
76
|
+
|
|
77
|
+
expect(markAll.element.tagName).toBe('BUTTON');
|
|
78
|
+
expect(markAll.attributes('href')).toBeUndefined();
|
|
79
|
+
});
|
|
80
|
+
});
|
|
@@ -35,7 +35,18 @@ interface UpdateArgs {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
type MgmtCluster = {
|
|
38
|
-
[key: string]: any
|
|
38
|
+
[key: string]: any,
|
|
39
|
+
id: string,
|
|
40
|
+
nameDisplay: string,
|
|
41
|
+
canExplore: boolean,
|
|
42
|
+
providerMenuLogo: string,
|
|
43
|
+
badge: string,
|
|
44
|
+
iconColor: string,
|
|
45
|
+
isLocal: boolean,
|
|
46
|
+
pinned: boolean,
|
|
47
|
+
description: string,
|
|
48
|
+
pin: () => void
|
|
49
|
+
unpin: () => void
|
|
39
50
|
}
|
|
40
51
|
|
|
41
52
|
type ProvCluster = {
|
|
@@ -148,7 +159,8 @@ export abstract class BaseTopLevelMenuHelper {
|
|
|
148
159
|
return {
|
|
149
160
|
id: mgmtCluster.id,
|
|
150
161
|
label: mgmtCluster.nameDisplay,
|
|
151
|
-
|
|
162
|
+
// Align side nav cluster, home page name link and cluster management cluster explore buttons on canExplore
|
|
163
|
+
ready: mgmtCluster.canExplore,
|
|
152
164
|
providerNavLogo: mgmtCluster.providerMenuLogo,
|
|
153
165
|
badge: mgmtCluster.badge,
|
|
154
166
|
iconColor: mgmtCluster.iconColor,
|
|
@@ -488,7 +500,7 @@ export class TopLevelMenuHelperLegacy extends BaseTopLevelMenuHelper implements
|
|
|
488
500
|
const maxClustersToShow = args.unPinnedMax || 10;
|
|
489
501
|
|
|
490
502
|
const search = (clusterFilter || '').toLowerCase();
|
|
491
|
-
let localCluster:
|
|
503
|
+
let localCluster: TopLevelMenuCluster | null = null;
|
|
492
504
|
|
|
493
505
|
const filtered = clusters.filter((c) => {
|
|
494
506
|
// If we're searching we don't care if pinned or not
|
|
@@ -98,6 +98,17 @@ export default {
|
|
|
98
98
|
return count?.summary.count;
|
|
99
99
|
},
|
|
100
100
|
|
|
101
|
+
routeComboActive() {
|
|
102
|
+
if (!this.routeCombo) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
const ready = [...this.appBar.pinFiltered, ...this.appBar.clustersFiltered].filter((c) => c.ready);
|
|
107
|
+
const readyCount = ready.length;
|
|
108
|
+
|
|
109
|
+
return readyCount > 1 || (readyCount === 1 && this.clusterId !== ready[0].id);
|
|
110
|
+
},
|
|
111
|
+
|
|
101
112
|
// New
|
|
102
113
|
search() {
|
|
103
114
|
return (this.clusterFilter || '').toLowerCase();
|
|
@@ -386,7 +397,7 @@ export default {
|
|
|
386
397
|
},
|
|
387
398
|
|
|
388
399
|
clusterMenuClick(ev, cluster) {
|
|
389
|
-
if (this.
|
|
400
|
+
if (this.routeComboActive) {
|
|
390
401
|
ev.preventDefault();
|
|
391
402
|
|
|
392
403
|
if (this.isCurrRouteClusterExplorer && this.productFromRoute === this.currentProduct?.name) {
|
|
@@ -423,7 +434,7 @@ export default {
|
|
|
423
434
|
},
|
|
424
435
|
|
|
425
436
|
async goToHarvesterCluster() {
|
|
426
|
-
const localCluster = this.$store.getters['management/
|
|
437
|
+
const localCluster = this.$store.getters['management/byId'](CAPI.RANCHER_CLUSTER, 'fleet-local/local');
|
|
427
438
|
|
|
428
439
|
try {
|
|
429
440
|
await localCluster.goToHarvesterCluster();
|
|
@@ -446,7 +457,7 @@ export default {
|
|
|
446
457
|
content = this.shown ? null : contentText;
|
|
447
458
|
|
|
448
459
|
// if key combo is pressed, then we update the tooltip as well
|
|
449
|
-
} else if (this.
|
|
460
|
+
} else if (this.routeComboActive &&
|
|
450
461
|
typeof item === 'object' &&
|
|
451
462
|
!Array.isArray(item) &&
|
|
452
463
|
item !== null &&
|
|
@@ -706,7 +717,7 @@ export default {
|
|
|
706
717
|
<ClusterIconMenu
|
|
707
718
|
v-clean-tooltip="getTooltipConfig(c, true)"
|
|
708
719
|
:cluster="c"
|
|
709
|
-
:route-combo="
|
|
720
|
+
:route-combo="routeComboActive"
|
|
710
721
|
class="rancher-provider-icon"
|
|
711
722
|
/>
|
|
712
723
|
<div
|
|
@@ -785,7 +796,7 @@ export default {
|
|
|
785
796
|
<ClusterIconMenu
|
|
786
797
|
v-clean-tooltip="getTooltipConfig(c, true)"
|
|
787
798
|
:cluster="c"
|
|
788
|
-
:route-combo="
|
|
799
|
+
:route-combo="routeComboActive"
|
|
789
800
|
class="rancher-provider-icon"
|
|
790
801
|
/>
|
|
791
802
|
<div
|
package/components/nav/Type.vue
CHANGED
|
@@ -68,8 +68,9 @@ export default {
|
|
|
68
68
|
},
|
|
69
69
|
|
|
70
70
|
isActive() {
|
|
71
|
-
|
|
72
|
-
const
|
|
71
|
+
// Use .path instead of .fullPath to ignore query parameters and hashes when comparing routes
|
|
72
|
+
const typePath = this.$router.resolve(this.typeRoute)?.path.toLowerCase();
|
|
73
|
+
const pagePath = this.$route.path?.toLowerCase();
|
|
73
74
|
const routeMetaNav = this.$route.meta?.nav;
|
|
74
75
|
|
|
75
76
|
// If the route explicitly declares the nav path that should be highlighted, then use that
|
|
@@ -80,14 +81,14 @@ export default {
|
|
|
80
81
|
.replace(':cluster', cluster)
|
|
81
82
|
.replace(':product', product);
|
|
82
83
|
|
|
83
|
-
if (navPath ===
|
|
84
|
+
if (navPath === typePath) {
|
|
84
85
|
return true;
|
|
85
86
|
}
|
|
86
87
|
}
|
|
87
88
|
|
|
88
89
|
if ( !this.type.exact) {
|
|
89
|
-
const typeSplit =
|
|
90
|
-
const pageSplit =
|
|
90
|
+
const typeSplit = typePath.split('/');
|
|
91
|
+
const pageSplit = pagePath.split('/');
|
|
91
92
|
|
|
92
93
|
for (let index = 0; index < typeSplit.length; ++index) {
|
|
93
94
|
if ( index >= pageSplit.length || typeSplit[index] !== pageSplit[index] ) {
|
|
@@ -98,7 +99,7 @@ export default {
|
|
|
98
99
|
return true;
|
|
99
100
|
}
|
|
100
101
|
|
|
101
|
-
return
|
|
102
|
+
return typePath === pagePath;
|
|
102
103
|
},
|
|
103
104
|
|
|
104
105
|
typeRoute() {
|
|
@@ -131,7 +132,7 @@ export default {
|
|
|
131
132
|
<router-link
|
|
132
133
|
v-if="type.route"
|
|
133
134
|
:key="type.name"
|
|
134
|
-
v-slot="{ href, navigate,isExactActive }"
|
|
135
|
+
v-slot="{ href, navigate, isExactActive }"
|
|
135
136
|
custom
|
|
136
137
|
:to="typeRoute"
|
|
137
138
|
>
|
|
@@ -36,7 +36,7 @@ const props = defineProps({
|
|
|
36
36
|
|
|
37
37
|
const { loadComponent } = useComponentsMount();
|
|
38
38
|
|
|
39
|
-
const { isPanelEnabled } = usePanelsHandler(
|
|
39
|
+
const { isPanelEnabled } = usePanelsHandler(props);
|
|
40
40
|
const { tabs } = useTabsHandler();
|
|
41
41
|
</script>
|
|
42
42
|
|
|
@@ -66,6 +66,7 @@ const { tabs } = useTabsHandler();
|
|
|
66
66
|
:active="true"
|
|
67
67
|
:height="tab.containerHeight"
|
|
68
68
|
:width="tab.containerWidth"
|
|
69
|
+
:layout="layout"
|
|
69
70
|
v-bind="tab.attrs"
|
|
70
71
|
/>
|
|
71
72
|
</keep-alive>
|