@rancher/shell 3.0.5-rc.3 → 3.0.5-rc.6
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/data/aws-regions.json +1 -0
- package/assets/images/icons/document.svg +3 -0
- package/assets/images/key.svg +17 -0
- package/assets/images/vendor/cognito.svg +1 -0
- package/assets/styles/app.scss +1 -0
- package/assets/styles/base/_basic.scss +10 -0
- package/assets/styles/base/_spacing.scss +29 -0
- package/assets/styles/global/_form.scss +1 -1
- package/assets/styles/global/_labeled-input.scss +1 -1
- package/assets/styles/global/_layout.scss +1 -1
- package/assets/styles/themes/_dark.scss +28 -0
- package/assets/styles/themes/_light.scss +68 -0
- package/assets/styles/vendor/vue-select.scss +1 -1
- package/assets/translations/en-us.yaml +721 -83
- package/assets/translations/zh-hans.yaml +11 -9
- package/cloud-credential/gcp.vue +9 -1
- package/components/AppModal.vue +2 -0
- package/components/Certificates.vue +5 -0
- package/components/CodeMirror.vue +1 -1
- package/components/ConfigMapSettings/Settings.vue +377 -0
- package/components/ConfigMapSettings/index.vue +354 -0
- package/components/CruResource.vue +1 -2
- package/components/DetailText.vue +61 -11
- package/components/Drawer/Chrome.vue +116 -0
- package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +61 -0
- package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +48 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +54 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/YamlTab.test.ts +80 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +82 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/helpers.test.ts +42 -0
- package/components/Drawer/ResourceDetailDrawer/composables.ts +50 -0
- package/components/Drawer/ResourceDetailDrawer/helpers.ts +10 -0
- package/components/Drawer/ResourceDetailDrawer/index.vue +110 -0
- package/components/FilterPanel.vue +156 -0
- package/components/{fleet/ForceDirectedTreeChart/index.vue → ForceDirectedTreeChart.vue} +47 -41
- package/components/GrowlManager.vue +16 -15
- package/components/IconOrSvg.vue +19 -35
- package/components/KeyValueView.vue +1 -1
- package/components/LocaleSelector.vue +9 -1
- package/components/ProgressBarMulti.vue +1 -0
- package/components/PromptModal.vue +6 -1
- package/components/PromptRemove.vue +5 -1
- package/components/RelatedResources.vue +4 -12
- package/components/Resource/Detail/Additional.vue +46 -0
- package/components/Resource/Detail/Card/PodsCard/Bubble.vue +13 -0
- package/components/Resource/Detail/Card/PodsCard/composable.ts +30 -0
- package/components/Resource/Detail/Card/PodsCard/index.vue +118 -0
- package/components/Resource/Detail/Card/ResourceUsageCard/composable.ts +51 -0
- package/components/Resource/Detail/Card/ResourceUsageCard/index.vue +79 -0
- package/components/Resource/Detail/Card/Scaler.vue +89 -0
- package/components/Resource/Detail/Card/StateCard/composables.ts +112 -0
- package/components/Resource/Detail/Card/StateCard/index.vue +39 -0
- package/components/Resource/Detail/Card/VerticalGap.vue +11 -0
- package/components/Resource/Detail/Card/__tests__/Card.test.ts +36 -0
- package/components/Resource/Detail/Card/__tests__/PodsCard.test.ts +84 -0
- package/components/Resource/Detail/Card/__tests__/ResourceUsageCard.test.ts +72 -0
- package/components/Resource/Detail/Card/__tests__/Scaler.test.ts +87 -0
- package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +53 -0
- package/components/Resource/Detail/Card/__tests__/VerticalGap.test.ts +14 -0
- package/components/Resource/Detail/Card/__tests__/index.test.ts +36 -0
- package/components/Resource/Detail/Card/index.vue +56 -0
- package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +19 -0
- package/components/Resource/Detail/Metadata/Annotations/composable.ts +12 -0
- package/components/Resource/Detail/Metadata/Annotations/index.vue +31 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +223 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +103 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +64 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +298 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +133 -0
- package/components/Resource/Detail/Metadata/KeyValue.vue +138 -0
- package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +18 -0
- package/components/Resource/Detail/Metadata/Labels/composable.ts +12 -0
- package/components/Resource/Detail/Metadata/Labels/index.vue +31 -0
- package/components/Resource/Detail/Metadata/Rectangle.vue +32 -0
- package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +107 -0
- package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +24 -0
- package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +75 -0
- package/components/Resource/Detail/Metadata/__tests__/index.test.ts +91 -0
- package/components/Resource/Detail/Metadata/composables.ts +78 -0
- package/components/Resource/Detail/Metadata/index.vue +73 -0
- package/components/Resource/Detail/Page.vue +37 -0
- package/components/Resource/Detail/PercentageBar.vue +40 -0
- package/components/Resource/Detail/ResourceRow.vue +138 -0
- package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/composables.test.ts +29 -0
- package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/index.test.ts +48 -0
- package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/composables.ts +31 -0
- package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/index.vue +50 -0
- package/components/Resource/Detail/ResourceTabs/KnownHostsTab/__tests__/composables.test.ts +66 -0
- package/components/Resource/Detail/ResourceTabs/KnownHostsTab/composables.ts +21 -0
- package/components/Resource/Detail/ResourceTabs/KnownHostsTab/index.vue +31 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/Basic.vue +45 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/BasicAuth.vue +31 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/Certificate.vue +31 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/Registry.vue +22 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/ServiceAccountToken.vue +31 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/Ssh.vue +32 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Basic.test.ts +40 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/BasicAuth.test.ts +33 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Certificate.test.ts +33 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Registry.test.ts +27 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/ServiceAccountToken.test.ts +33 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Ssh.test.ts +33 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/auth-types.test.ts +186 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/composables.test.ts +102 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/auth-types.ts +109 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/composeables.ts +52 -0
- package/components/Resource/Detail/ResourceTabs/SecretDataTab/index.vue +71 -0
- package/components/Resource/Detail/SpacedRow.vue +14 -0
- package/components/Resource/Detail/StatusBar.vue +59 -0
- package/components/Resource/Detail/StatusRow.vue +61 -0
- package/components/Resource/Detail/TitleBar/Title.vue +14 -0
- package/components/Resource/Detail/TitleBar/Top.vue +14 -0
- package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +17 -0
- package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +17 -0
- package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +63 -0
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +142 -0
- package/components/Resource/Detail/TitleBar/composables.ts +44 -0
- package/components/Resource/Detail/TitleBar/index.vue +196 -0
- package/components/Resource/Detail/Top/index.vue +34 -0
- package/components/Resource/Detail/__tests__/Page.test.ts +32 -0
- package/components/Resource/Detail/composables.ts +45 -0
- package/components/ResourceDetail/Masthead/__tests__/index.test.ts +70 -0
- package/components/ResourceDetail/{__tests__/Masthead.test.ts → Masthead/__tests__/legacy.test.ts} +3 -3
- package/components/ResourceDetail/Masthead/index.vue +65 -0
- package/components/ResourceDetail/Masthead/latest.vue +44 -0
- package/components/ResourceDetail/__tests__/index.test.ts +135 -0
- package/components/ResourceDetail/index.vue +73 -557
- package/components/ResourceDetail/legacy.vue +562 -0
- package/components/ResourceList/Masthead.vue +6 -0
- package/components/ResourceTable.vue +41 -7
- package/components/ResourceYaml.vue +14 -1
- package/components/SlideInPanelManager.vue +117 -10
- package/components/SortableTable/index.vue +13 -2
- package/components/SortableTable/selection.js +21 -8
- package/components/StateDot/index.vue +28 -0
- package/components/StatusBadge.vue +6 -4
- package/components/SubtleLink.vue +25 -0
- package/components/Tabbed/index.vue +11 -15
- package/components/Wizard.vue +16 -3
- package/components/YamlEditor.vue +1 -1
- package/components/__tests__/ConfigMapSettings.test.ts +376 -0
- package/components/__tests__/FilterPanel.test.ts +81 -0
- package/components/__tests__/GrowlManager.test.ts +0 -25
- package/components/auth/AuthBanner.vue +2 -3
- package/components/auth/RoleDetailEdit.vue +45 -3
- package/components/auth/login/ldap.vue +1 -1
- package/components/auth/login/oidc.vue +6 -1
- package/components/fleet/FleetApplications.vue +174 -0
- package/components/fleet/FleetClusterTargets/TargetsList.vue +66 -0
- package/components/fleet/FleetClusterTargets/index.vue +455 -0
- package/components/fleet/FleetClusters.vue +25 -6
- package/components/fleet/FleetGitRepoPaths.vue +476 -0
- package/components/fleet/FleetHelmOps.vue +123 -0
- package/components/fleet/FleetIntro.vue +58 -28
- package/components/fleet/FleetNoWorkspaces.vue +5 -1
- package/components/fleet/FleetOCIStorageSecret.vue +171 -0
- package/components/fleet/FleetRepos.vue +37 -80
- package/components/fleet/FleetResources.vue +53 -26
- package/components/fleet/FleetSummary.vue +26 -51
- package/components/fleet/FleetValuesFrom.vue +295 -0
- package/components/fleet/__tests__/FleetClusterTargets.test.ts +1224 -0
- package/components/fleet/__tests__/FleetGitRepoPaths.test.ts +265 -0
- package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +213 -0
- package/components/fleet/__tests__/FleetSummary.test.ts +39 -39
- package/components/fleet/__tests__/FleetValuesFrom.test.ts +300 -0
- package/components/fleet/dashboard/Empty.vue +73 -0
- package/components/fleet/dashboard/ResourceCard.vue +184 -0
- package/components/fleet/dashboard/ResourceCardSummary.vue +195 -0
- package/components/fleet/dashboard/ResourceDetails.vue +194 -0
- package/components/fleet/dashboard/ResourcePanel.vue +383 -0
- package/components/form/ArrayList.vue +19 -2
- package/components/form/ChangePassword.vue +3 -1
- package/components/form/Footer.vue +10 -4
- package/components/form/KeyValue.vue +81 -43
- package/components/form/LabeledSelect.vue +56 -16
- package/components/form/Labels.vue +90 -17
- package/components/form/MatchExpressions.vue +46 -5
- package/components/form/NameNsDescription.vue +1 -1
- package/components/form/ResourceSelector.vue +1 -0
- package/components/form/ResourceTabs/index.vue +5 -0
- package/components/form/SecretSelector.vue +9 -2
- package/components/form/Select.vue +57 -19
- package/components/form/SimpleSecretSelector.vue +17 -4
- package/components/form/Taints.vue +21 -2
- package/components/form/UnitInput.vue +8 -0
- package/components/form/ValueFromResource.vue +31 -19
- package/components/form/__tests__/LabeledSelect.test.ts +8 -4
- package/components/form/__tests__/Labels.test.ts +360 -0
- package/components/form/__tests__/MatchExpressions.test.ts +16 -13
- package/components/form/__tests__/Select.test.ts +5 -2
- package/components/formatter/FleetApplicationClustersReady.vue +77 -0
- package/components/formatter/FleetApplicationSource.vue +71 -0
- package/components/formatter/FleetSummaryGraph.vue +7 -0
- package/components/formatter/WorkloadHealthScale.vue +1 -1
- package/components/google/AccountAccess.vue +211 -0
- package/components/google/types/gcp.d.ts +136 -0
- package/components/google/types/index.d.ts +101 -0
- package/components/google/util/__mocks__/gcp.ts +465 -0
- package/components/google/util/formatter.ts +82 -0
- package/components/google/util/gcp.ts +134 -0
- package/components/google/util/index.d.ts +11 -0
- package/components/nav/Favorite.vue +1 -1
- package/components/nav/Group.vue +70 -47
- package/components/nav/Header.vue +13 -8
- package/components/nav/NamespaceFilter.vue +13 -1
- package/components/nav/NotificationCenter/Notification.vue +510 -0
- package/components/nav/NotificationCenter/NotificationHeader.vue +112 -0
- package/components/nav/NotificationCenter/index.vue +148 -0
- package/components/nav/TopLevelMenu.helper.ts +55 -34
- package/components/nav/TopLevelMenu.vue +11 -0
- package/components/nav/Type.vue +4 -1
- package/composables/drawer.ts +26 -0
- package/composables/resources.test.ts +63 -0
- package/composables/resources.ts +38 -0
- package/composables/useI18n.ts +12 -11
- package/composables/useIsNewDetailPageEnabled.ts +17 -0
- package/config/labels-annotations.js +20 -11
- package/config/product/auth.js +17 -1
- package/config/product/{cis.js → compliance.js} +23 -26
- package/config/product/explorer.js +5 -1
- package/config/product/fleet.js +77 -17
- package/config/product/settings.js +22 -11
- package/config/query-params.js +6 -1
- package/config/roles.ts +2 -1
- package/config/router/navigation-guards/authentication.js +51 -2
- package/config/router/routes.js +45 -31
- package/config/secret.ts +15 -0
- package/config/settings.ts +24 -5
- package/config/store.js +2 -0
- package/config/system-namespaces.js +1 -1
- package/config/table-headers.js +53 -23
- package/config/types.js +17 -6
- package/core/plugin-helpers.ts +3 -2
- package/core/plugin.ts +32 -7
- package/core/types.ts +18 -1
- package/detail/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +22 -18
- package/detail/fleet.cattle.io.cluster.vue +28 -15
- package/detail/fleet.cattle.io.gitrepo.vue +10 -1
- package/detail/fleet.cattle.io.helmop.vue +157 -0
- package/detail/management.cattle.io.fleetworkspace.vue +18 -27
- package/detail/management.cattle.io.oidcclient.vue +369 -0
- package/detail/node.vue +2 -2
- package/detail/pod.vue +2 -2
- package/detail/service.vue +10 -1
- package/detail/workload/index.vue +8 -2
- package/dialog/ExtensionCatalogUninstallDialog.vue +7 -4
- package/dialog/GenericPrompt.vue +1 -1
- package/dialog/HelmOpForceUpdateDialog.vue +132 -0
- package/dialog/ImportDialog.vue +8 -8
- package/dialog/OidcClientSecretDialog.vue +117 -0
- package/dialog/RedeployWorkloadDialog.vue +164 -0
- package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +3 -3
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +60 -68
- package/edit/auth/oidc.vue +159 -93
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +4 -1
- package/edit/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +30 -31
- package/edit/{cis.cattle.io.clusterscanbenchmark.vue → compliance.cattle.io.clusterscanbenchmark.vue} +4 -4
- package/edit/{cis.cattle.io.clusterscanprofile.vue → compliance.cattle.io.clusterscanprofile.vue} +5 -5
- package/edit/configmap.vue +4 -1
- package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
- package/edit/fleet.cattle.io.gitrepo.vue +70 -255
- package/edit/fleet.cattle.io.helmop.vue +772 -0
- package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
- package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
- package/edit/logging-flow/index.vue +1 -0
- package/edit/logging.banzaicloud.io.output/index.vue +1 -0
- package/edit/management.cattle.io.fleetworkspace.vue +44 -10
- package/edit/management.cattle.io.oidcclient.vue +162 -0
- package/edit/management.cattle.io.project.vue +4 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +5 -0
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
- package/edit/monitoring.coreos.com.receiver/auth.vue +30 -30
- package/edit/monitoring.coreos.com.receiver/index.vue +1 -0
- package/edit/monitoring.coreos.com.receiver/types/email.vue +1 -1
- package/edit/monitoring.coreos.com.route.vue +1 -0
- package/edit/namespace.vue +1 -0
- package/edit/networking.istio.io.destinationrule/index.vue +4 -1
- package/edit/networking.k8s.io.ingress/index.vue +4 -1
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +7 -2
- package/edit/networking.k8s.io.networkpolicy/index.vue +6 -2
- package/edit/node.vue +1 -0
- package/edit/persistentvolume/index.vue +4 -1
- package/edit/provisioning.cattle.io.cluster/rke2.vue +418 -382
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +27 -27
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +5 -0
- package/edit/resources.cattle.io.restore.vue +1 -1
- package/edit/secret/index.vue +1 -0
- package/edit/service.vue +4 -1
- package/edit/serviceaccount.vue +4 -1
- package/edit/storage.k8s.io.storageclass/index.vue +4 -1
- package/edit/workload/index.vue +5 -0
- package/list/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +2 -2
- package/list/fleet.cattle.io.gitrepo.vue +1 -1
- package/list/fleet.cattle.io.helmop.vue +108 -0
- package/list/management.cattle.io.oidcclient.vue +108 -0
- package/list/namespace.vue +5 -2
- package/list/node.vue +2 -0
- package/machine-config/amazonec2.vue +3 -24
- package/machine-config/components/GCEImage.vue +374 -0
- package/machine-config/google.vue +617 -0
- package/mixins/__tests__/brand.spec.ts +170 -0
- package/mixins/auth-config.js +8 -1
- package/mixins/brand.js +16 -17
- package/mixins/create-edit-view/index.js +5 -0
- package/mixins/preset.js +100 -0
- package/mixins/resource-fetch-api-pagination.js +18 -0
- package/mixins/resource-fetch.js +1 -1
- package/mixins/resource-table-watch.js +45 -0
- package/mixins/vue-select-overrides.js +1 -0
- package/models/__tests__/chart.test.ts +273 -0
- package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
- package/models/chart.js +144 -2
- package/models/{cis.cattle.io.clusterscan.js → compliance.cattle.io.clusterscan.js} +8 -8
- package/models/{cis.cattle.io.clusterscanbenchmark.js → compliance.cattle.io.clusterscanbenchmark.js} +1 -1
- package/models/{cis.cattle.io.clusterscanprofile.js → compliance.cattle.io.clusterscanprofile.js} +5 -5
- package/models/{cis.cattle.io.clusterscanreport.js → compliance.cattle.io.clusterscanreport.js} +1 -1
- package/models/fleet-application.js +314 -0
- package/models/fleet.cattle.io.bundle.js +9 -8
- package/models/fleet.cattle.io.cluster.js +11 -0
- package/models/fleet.cattle.io.gitrepo.js +41 -365
- package/models/fleet.cattle.io.helmop.js +198 -0
- package/models/management.cattle.io.authconfig.js +1 -0
- package/models/management.cattle.io.fleetworkspace.js +14 -1
- package/models/management.cattle.io.oidcclient.js +18 -0
- package/models/management.cattle.io.registration.js +3 -0
- package/models/provisioning.cattle.io.cluster.js +5 -5
- package/models/service.js +4 -0
- package/models/workload.js +19 -18
- package/package.json +2 -1
- package/pages/about.vue +4 -58
- package/pages/auth/login.vue +1 -1
- package/pages/auth/verify.vue +13 -1
- package/pages/c/_cluster/apps/charts/AddRepoLink.vue +36 -0
- package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +80 -0
- package/pages/c/_cluster/apps/charts/AppChartCardSubHeader.vue +54 -0
- package/pages/c/_cluster/apps/charts/StatusLabel.vue +33 -0
- package/pages/c/_cluster/apps/charts/index.vue +487 -465
- package/pages/c/_cluster/auth/user.retention/index.vue +87 -78
- package/pages/c/_cluster/explorer/EventsTable.vue +1 -1
- package/pages/c/_cluster/explorer/index.vue +3 -3
- package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -1
- package/pages/c/_cluster/fleet/__tests__/index.test.ts +426 -0
- package/pages/c/_cluster/fleet/application/_resource/_id.vue +14 -0
- package/pages/c/_cluster/fleet/application/_resource/create.vue +14 -0
- package/pages/c/_cluster/fleet/application/create.vue +341 -0
- package/pages/c/_cluster/fleet/application/index.vue +139 -0
- package/pages/c/_cluster/fleet/graph/config.js +277 -0
- package/pages/c/_cluster/fleet/index.vue +809 -329
- package/pages/c/_cluster/fleet/settings/index.vue +229 -0
- package/pages/c/_cluster/longhorn/index.vue +5 -2
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +16 -1
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +2 -2
- package/pages/explorer/resource/detail/configmap.vue +42 -0
- package/pages/explorer/resource/detail/secret.vue +50 -0
- package/pages/home.vue +9 -55
- package/pages/support/index.vue +4 -6
- package/plugins/dashboard-store/actions.js +50 -14
- package/plugins/dashboard-store/getters.js +38 -21
- package/plugins/dashboard-store/mutations.js +51 -7
- package/plugins/dashboard-store/resource-class.js +30 -4
- package/plugins/steve/__tests__/subscribe.spec.ts +66 -1
- package/plugins/steve/actions.js +3 -0
- package/plugins/steve/steve-pagination-utils.ts +17 -8
- package/plugins/steve/subscribe.js +235 -43
- package/rancher-components/BadgeState/BadgeState.vue +3 -1
- package/rancher-components/Banner/Banner.vue +13 -0
- package/rancher-components/Form/Checkbox/Checkbox.vue +11 -6
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
- package/rancher-components/RcItemCard/RcItemCard.test.ts +189 -0
- package/rancher-components/RcItemCard/RcItemCard.vue +430 -0
- package/rancher-components/RcItemCard/RcItemCardAction.vue +24 -0
- package/rancher-components/RcItemCard/index.ts +2 -0
- package/store/auth.js +3 -0
- package/store/catalog.js +85 -25
- package/store/growl.js +97 -8
- package/store/index.js +39 -14
- package/store/notifications.ts +426 -0
- package/store/prefs.js +0 -1
- package/store/slideInPanel.ts +6 -0
- package/store/type-map.js +19 -15
- package/store/uiplugins.ts +15 -1
- package/types/fleet.d.ts +59 -0
- package/types/notifications/index.ts +74 -0
- package/types/resources/settings.d.ts +19 -1
- package/types/shell/index.d.ts +388 -307
- package/types/store/dashboard-store.types.ts +33 -3
- package/types/store/pagination.types.ts +6 -1
- package/types/store/subscribe.types.ts +50 -0
- package/utils/__tests__/fleet.test.ts +148 -0
- package/utils/__tests__/object.test.ts +54 -1
- package/utils/__tests__/string.test.ts +273 -1
- package/utils/__tests__/time.test.ts +31 -0
- package/utils/auth.js +41 -5
- package/utils/crypto/encryption.ts +103 -0
- package/utils/cspAdaptor.ts +51 -0
- package/utils/fleet-types.ts +0 -0
- package/utils/fleet.ts +190 -2
- package/utils/object.js +36 -0
- package/utils/pagination-utils.ts +27 -2
- package/utils/pagination-wrapper.ts +132 -50
- package/utils/release-notes.ts +48 -0
- package/utils/selector-typed.ts +7 -2
- package/utils/settings.ts +4 -1
- package/utils/string.js +24 -0
- package/utils/style.ts +39 -0
- package/utils/{time.js → time.ts} +25 -6
- package/utils/uiplugins.ts +22 -0
- package/utils/validators/formRules/__tests__/index.test.ts +36 -3
- package/utils/validators/formRules/index.ts +13 -3
- package/utils/window.js +11 -7
- package/components/__tests__/ApplicationCard.test.ts +0 -27
- package/components/cards/ApplicationCard.vue +0 -145
- package/components/fleet/ForceDirectedTreeChart/chartIcons.js +0 -17
- package/config/product/legacy.js +0 -62
- package/config/secret.js +0 -14
- package/pages/c/_cluster/fleet/GitRepoGraphConfig.js +0 -249
- package/pages/c/_cluster/legacy/pages/_page.vue +0 -29
- package/pages/c/_cluster/legacy/project/_page.vue +0 -57
- package/pages/c/_cluster/legacy/project/index.vue +0 -32
- package/pages/c/_cluster/legacy/project/pipelines.vue +0 -96
- /package/components/ResourceDetail/{Masthead.vue → Masthead/legacy.vue} +0 -0
- /package/{components/form/SSHKnownHosts → dialog}/__tests__/KnownHostsEditDialog.test.ts +0 -0
|
@@ -1,70 +1,152 @@
|
|
|
1
1
|
import paginationUtils from '@shell/utils/pagination-utils';
|
|
2
|
-
import { PaginationArgs, PaginationResourceContext
|
|
2
|
+
import { PaginationArgs, PaginationResourceContext } from '@shell/types/store/pagination.types';
|
|
3
3
|
import { VuexStore } from '@shell/types/store/vuex';
|
|
4
|
-
import { ActionFindPageArgs } from '@shell/types/store/dashboard-store.types';
|
|
4
|
+
import { ActionFindPageArgs, ActionFindPageTransientResult } from '@shell/types/store/dashboard-store.types';
|
|
5
|
+
import {
|
|
6
|
+
STEVE_WATCH_EVENT_LISTENER_CALLBACK, STEVE_UNWATCH_EVENT_PARAMS, STEVE_WATCH_EVENT, STEVE_WATCH_EVENT_PARAMS, STEVE_WATCH_EVENT_PARAMS_COMMON, STEVE_WATCH_MODE
|
|
7
|
+
} from '@shell/types/store/subscribe.types';
|
|
8
|
+
import { Reactive, reactive } from 'vue';
|
|
5
9
|
|
|
6
|
-
interface
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
interface Args {
|
|
11
|
+
$store: VuexStore,
|
|
12
|
+
/**
|
|
13
|
+
* Unique ID for this request. Used for watch purposes
|
|
14
|
+
*/
|
|
15
|
+
id: string,
|
|
16
|
+
/**
|
|
17
|
+
* Args used when determining if this resource type supports SSP
|
|
18
|
+
*/
|
|
19
|
+
enabledFor: PaginationResourceContext,
|
|
20
|
+
/**
|
|
21
|
+
* Callback called when the resource is changed (notified by socket)
|
|
22
|
+
*/
|
|
23
|
+
onChange?: () => void,
|
|
24
|
+
|
|
25
|
+
formatResponse?: {
|
|
26
|
+
/**
|
|
27
|
+
* Convert the response into a model class instance
|
|
28
|
+
*/
|
|
29
|
+
classify?: boolean,
|
|
30
|
+
reactive?: boolean,
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface Result<T> extends Omit<ActionFindPageTransientResult<T>, 'data'> {
|
|
35
|
+
data: Reactive<T[]>
|
|
9
36
|
}
|
|
10
37
|
|
|
11
38
|
/**
|
|
12
|
-
* This is a helper class that will assist in fetching a resource
|
|
13
|
-
* - Handle if the resource can be fetched by the new pagination api
|
|
14
|
-
* - Make a request to get a page (including classify)
|
|
15
|
-
* - Provide updates when the resource changes
|
|
39
|
+
* This is a helper class that will assist in fetching a resource via the new Server-Side Pagination API
|
|
16
40
|
*
|
|
17
41
|
* This is designed to work in places where we don't/can't store the resource in the store
|
|
18
42
|
* - There already exists a resource we don't want to overwrite
|
|
19
|
-
* - We're transient and want something nicer than just cluster/request
|
|
43
|
+
* - We're transient and want something nicer than just `cluster/request` + all the trimmings
|
|
44
|
+
*
|
|
45
|
+
* It ...
|
|
46
|
+
* - Handles if the resource can be fetched by the new pagination api
|
|
47
|
+
* - Makes a request to get a page (including optional classify & reactive)
|
|
48
|
+
* - Provide updates when the resource changes
|
|
20
49
|
*/
|
|
21
|
-
class PaginationWrapper<T
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
50
|
+
class PaginationWrapper<T extends object> {
|
|
51
|
+
private $store: VuexStore;
|
|
52
|
+
private enabledFor: PaginationResourceContext;
|
|
53
|
+
private onChange?: STEVE_WATCH_EVENT_LISTENER_CALLBACK;
|
|
54
|
+
private id: string;
|
|
55
|
+
private classify: boolean;
|
|
56
|
+
private reactive: boolean;
|
|
57
|
+
|
|
58
|
+
public isEnabled: boolean;
|
|
59
|
+
private steveWatchParams: STEVE_WATCH_EVENT_PARAMS_COMMON | undefined;
|
|
60
|
+
|
|
61
|
+
constructor(args: Args) {
|
|
62
|
+
const {
|
|
63
|
+
$store, id, enabledFor, onChange, formatResponse
|
|
64
|
+
} = args;
|
|
65
|
+
|
|
66
|
+
this.$store = $store;
|
|
67
|
+
this.id = id;
|
|
68
|
+
this.enabledFor = enabledFor;
|
|
69
|
+
this.onChange = onChange;
|
|
70
|
+
this.classify = formatResponse?.classify || false;
|
|
71
|
+
this.reactive = formatResponse?.reactive || false;
|
|
72
|
+
|
|
73
|
+
this.isEnabled = paginationUtils.isEnabled({ rootGetters: $store.getters }, enabledFor);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async request(args: {
|
|
77
|
+
pagination: PaginationArgs,
|
|
78
|
+
}): Promise<Result<T>> {
|
|
79
|
+
if (!this.isEnabled) {
|
|
80
|
+
throw new Error(`Wrapper for type '${ this.enabledFor.store }/${ this.enabledFor.resource?.id }' in context '${ this.enabledFor.resource?.context }' not supported`);
|
|
81
|
+
}
|
|
82
|
+
const { pagination } = args;
|
|
83
|
+
const opt: ActionFindPageArgs = {
|
|
84
|
+
watch: false,
|
|
85
|
+
pagination,
|
|
86
|
+
transient: true,
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// Fetch
|
|
90
|
+
const out: ActionFindPageTransientResult<T> = await this.$store.dispatch(`${ this.enabledFor.store }/findPage`, { opt, type: this.enabledFor.resource?.id });
|
|
91
|
+
|
|
92
|
+
// Watch
|
|
93
|
+
if (this.onChange && !this.steveWatchParams) {
|
|
94
|
+
this.steveWatchParams = {
|
|
95
|
+
event: STEVE_WATCH_EVENT.CHANGES,
|
|
96
|
+
id: this.id,
|
|
97
|
+
params: {
|
|
98
|
+
type: this.enabledFor.resource?.id as string,
|
|
99
|
+
mode: STEVE_WATCH_MODE.RESOURCE_CHANGES,
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
this.watch();
|
|
43
104
|
}
|
|
44
105
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
transient: true,
|
|
55
|
-
pagination
|
|
106
|
+
// Convert Response
|
|
107
|
+
if (this.classify) {
|
|
108
|
+
out.data = await this.$store.dispatch(`${ this.enabledFor.store }/createMany`, out.data);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (this.reactive) {
|
|
112
|
+
return {
|
|
113
|
+
...out,
|
|
114
|
+
data: reactive(out.data)
|
|
56
115
|
};
|
|
116
|
+
}
|
|
57
117
|
|
|
58
|
-
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
59
120
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
}
|
|
64
|
-
}
|
|
121
|
+
private async watch() {
|
|
122
|
+
if (!this.steveWatchParams) {
|
|
123
|
+
console.error('Calling watch but no watch params created'); // eslint-disable-line no-console
|
|
65
124
|
|
|
66
|
-
return
|
|
125
|
+
return;
|
|
67
126
|
}
|
|
127
|
+
const watchParams: STEVE_WATCH_EVENT_PARAMS = {
|
|
128
|
+
...this.steveWatchParams,
|
|
129
|
+
callback: this.onChange as STEVE_WATCH_EVENT_LISTENER_CALLBACK, // we must have it by now
|
|
130
|
+
};
|
|
131
|
+
|
|
132
|
+
await this.$store.dispatch(`${ this.enabledFor.store }/watchEvent`, watchParams);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
private async unWatch() {
|
|
136
|
+
if (!this.steveWatchParams) {
|
|
137
|
+
console.error('Calling unWatch but no watch params created'); // eslint-disable-line no-console
|
|
138
|
+
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const unWatchParams: STEVE_UNWATCH_EVENT_PARAMS = { ...this.steveWatchParams };
|
|
143
|
+
|
|
144
|
+
await this.$store.dispatch(`${ this.enabledFor.store }/unwatchEvent`, unWatchParams);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
async onDestroy() {
|
|
148
|
+
await this.unWatch();
|
|
149
|
+
}
|
|
68
150
|
}
|
|
69
151
|
|
|
70
152
|
export default PaginationWrapper;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { getVersionData } from '@shell/config/version';
|
|
2
|
+
import { READ_WHATS_NEW } from '@shell/store/prefs';
|
|
3
|
+
import { NotificationLevel } from '@shell/types/notifications';
|
|
4
|
+
|
|
5
|
+
export async function addReleaseNotesNotification(dispatch: any, getters: any) {
|
|
6
|
+
const rancherVersion = getVersionData().Version.split('-')[0];
|
|
7
|
+
const prefix = 'release-notes-';
|
|
8
|
+
const id = `${ prefix }${ rancherVersion }`;
|
|
9
|
+
let found = false;
|
|
10
|
+
const all = getters['notifications/all'];
|
|
11
|
+
const lastReadVersion = getters['prefs/get'](READ_WHATS_NEW) || '';
|
|
12
|
+
const t = getters['i18n/t'];
|
|
13
|
+
const releaseNotesUrl = getters['releaseNotesUrl'];
|
|
14
|
+
|
|
15
|
+
// Delete notification(s) for old release notes
|
|
16
|
+
for (let i = 0; i < all.length; i++) {
|
|
17
|
+
const notification = all[i];
|
|
18
|
+
|
|
19
|
+
if (notification.id.startsWith(prefix)) {
|
|
20
|
+
if (notification.id === id) {
|
|
21
|
+
found = true;
|
|
22
|
+
} else {
|
|
23
|
+
await dispatch('notifications/delete', notification.id);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Also use pref, so if we expired it, we don't add it back
|
|
29
|
+
if (!found && lastReadVersion !== rancherVersion) {
|
|
30
|
+
// Register notification
|
|
31
|
+
const notification = {
|
|
32
|
+
id,
|
|
33
|
+
level: NotificationLevel.Info,
|
|
34
|
+
title: t('landing.whatsNew.title', { version: rancherVersion }),
|
|
35
|
+
message: t('landing.whatsNew.message'),
|
|
36
|
+
preference: {
|
|
37
|
+
key: READ_WHATS_NEW,
|
|
38
|
+
value: rancherVersion
|
|
39
|
+
},
|
|
40
|
+
primaryAction: {
|
|
41
|
+
label: t('landing.whatsNew.link'),
|
|
42
|
+
target: releaseNotesUrl
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
await dispatch('notifications/add', notification);
|
|
47
|
+
}
|
|
48
|
+
}
|
package/utils/selector-typed.ts
CHANGED
|
@@ -34,7 +34,7 @@ export async function matching({
|
|
|
34
34
|
$store,
|
|
35
35
|
inScopeCount = undefined,
|
|
36
36
|
namespace = undefined,
|
|
37
|
-
transient =
|
|
37
|
+
transient = true,
|
|
38
38
|
}: {
|
|
39
39
|
/**
|
|
40
40
|
* Standard kube label selector object.
|
|
@@ -101,7 +101,12 @@ export async function matching({
|
|
|
101
101
|
const filterByNamespaceButNoNamespace = isNamespaced && !!namespace && (!safeNamespaces || safeNamespaces.length === 0);
|
|
102
102
|
const explicityNullLabelSelector = labelSelector === null || (labelSelector?.matchLabels === null && !labelSelector.matchExpressions === null);
|
|
103
103
|
|
|
104
|
-
|
|
104
|
+
// If we have matchLabels or matchExpression entries they must have a key
|
|
105
|
+
const matchLabelKeys = Object.keys(labelSelector.matchLabels || {});
|
|
106
|
+
const invalidMatchLabelKeys = matchLabelKeys.length && matchLabelKeys.filter((k) => !k).length;
|
|
107
|
+
const invalidMatchExpressionKeys = labelSelector?.matchExpressions?.length && labelSelector.matchExpressions.filter((me) => !me.key).length;
|
|
108
|
+
|
|
109
|
+
if (noCandidates || filterByNamespaceButNoNamespace || explicityNullLabelSelector || invalidMatchLabelKeys || invalidMatchExpressionKeys) {
|
|
105
110
|
return generateMatchingResponse([], inScopeCount || 0);
|
|
106
111
|
}
|
|
107
112
|
|
package/utils/settings.ts
CHANGED
|
@@ -59,7 +59,10 @@ export const fetchInitialSettings = async(store: Store<any>): Promise<any> => {
|
|
|
59
59
|
// We're authed, we will always get the full list
|
|
60
60
|
return await store.dispatch('management/findAll', {
|
|
61
61
|
type: MANAGEMENT.SETTING,
|
|
62
|
-
opt: {
|
|
62
|
+
opt: {
|
|
63
|
+
url: `/v1/${ pluralize(MANAGEMENT.SETTING) }`,
|
|
64
|
+
watch: false, // Watch requires FF and Settings, see `loadManagement` to see how this is handled
|
|
65
|
+
}
|
|
63
66
|
} );
|
|
64
67
|
}
|
|
65
68
|
|
package/utils/string.js
CHANGED
|
@@ -358,3 +358,27 @@ export function isBase64(value) {
|
|
|
358
358
|
export function generateRandomAlphaString(length) {
|
|
359
359
|
return Array.from({ length }, () => String.fromCharCode(97 + Math.random() * 26 | 0)).join('');
|
|
360
360
|
}
|
|
361
|
+
|
|
362
|
+
/**
|
|
363
|
+
* Generate a key-value nested object from a list of paths that represents a directory tree.
|
|
364
|
+
*
|
|
365
|
+
* Each key is a subpath
|
|
366
|
+
* Each value contains the children of the subpath
|
|
367
|
+
*/
|
|
368
|
+
export function pathArrayToTree(paths) {
|
|
369
|
+
const result = [];
|
|
370
|
+
const level = { result };
|
|
371
|
+
|
|
372
|
+
paths.forEach((path) => {
|
|
373
|
+
path?.split('/').reduce((r, name) => {
|
|
374
|
+
if (!r[name]) {
|
|
375
|
+
r[name] = { result: [] };
|
|
376
|
+
r.result.push({ name, children: r[name].result });
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
return r[name];
|
|
380
|
+
}, level);
|
|
381
|
+
});
|
|
382
|
+
|
|
383
|
+
return result;
|
|
384
|
+
}
|
package/utils/style.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type StateColor = 'success' | 'warning' | 'error' | 'info' | 'disabled';
|
|
2
|
+
export const ALL_STATE_COLORS: StateColor[] = ['success', 'warning', 'error', 'info', 'disabled'];
|
|
3
|
+
|
|
4
|
+
export function stateColorCssVar(color: StateColor) {
|
|
5
|
+
return `var(--${ color })`;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export function toBgColor(color?: StateColor) {
|
|
9
|
+
const withDefaultColor = color || 'info';
|
|
10
|
+
|
|
11
|
+
return `bg-${ withDefaultColor }`;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Checks if 'a' is considered a higher alert than 'b'
|
|
16
|
+
* @param a target
|
|
17
|
+
* @param b comparison
|
|
18
|
+
* @returns true if 'a' is a higher alert than 'b' and false otherwise.
|
|
19
|
+
*/
|
|
20
|
+
export function isHigherAlert(a: StateColor, b: StateColor) {
|
|
21
|
+
const order: StateColor[] = ['info', 'success', 'warning', 'error'];
|
|
22
|
+
|
|
23
|
+
const aIndex = order.indexOf(a);
|
|
24
|
+
const bIndex = order.indexOf(b);
|
|
25
|
+
|
|
26
|
+
return aIndex > bIndex;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function getHighestAlertColor(colors: StateColor[]) {
|
|
30
|
+
let highestAlert: StateColor = 'info';
|
|
31
|
+
|
|
32
|
+
for (const color of colors) {
|
|
33
|
+
if (isHigherAlert(color, highestAlert)) {
|
|
34
|
+
highestAlert = color;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return highestAlert;
|
|
39
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import day from 'dayjs';
|
|
2
|
+
import { escapeHtml } from '@shell/utils/string';
|
|
3
|
+
import { DATE_FORMAT, TIME_FORMAT } from '@shell/store/prefs';
|
|
4
|
+
import { type Store } from 'vuex';
|
|
2
5
|
|
|
3
6
|
const FACTORS = [60, 60, 24];
|
|
4
7
|
const LABELS = ['sec', 'min', 'hour', 'day'];
|
|
@@ -6,7 +9,7 @@ const LABELS = ['sec', 'min', 'hour', 'day'];
|
|
|
6
9
|
// Diff two dates and return an object with values for presentation
|
|
7
10
|
// If 't' is also passed, 'string' property is set on the return object with the diff formatted as a string
|
|
8
11
|
// e.g. formats a date difference to return '1 day', '20 hours' etc
|
|
9
|
-
export function diffFrom(value, from, t) {
|
|
12
|
+
export function diffFrom(value: any, from: any, t: any) {
|
|
10
13
|
const now = day();
|
|
11
14
|
|
|
12
15
|
from = from || now;
|
|
@@ -15,7 +18,7 @@ export function diffFrom(value, from, t) {
|
|
|
15
18
|
let absDiff = Math.abs(diff);
|
|
16
19
|
|
|
17
20
|
let next = 1;
|
|
18
|
-
let label = '?';
|
|
21
|
+
let label: any = '?';
|
|
19
22
|
|
|
20
23
|
let i = 0;
|
|
21
24
|
|
|
@@ -30,7 +33,7 @@ export function diffFrom(value, from, t) {
|
|
|
30
33
|
} else {
|
|
31
34
|
label = Math.floor(absDiff);
|
|
32
35
|
}
|
|
33
|
-
const ret = {
|
|
36
|
+
const ret: any = {
|
|
34
37
|
diff,
|
|
35
38
|
absDiff,
|
|
36
39
|
label,
|
|
@@ -47,7 +50,7 @@ export function diffFrom(value, from, t) {
|
|
|
47
50
|
return ret;
|
|
48
51
|
}
|
|
49
52
|
|
|
50
|
-
export function safeSetTimeout(timeout, callback, that) {
|
|
53
|
+
export function safeSetTimeout(timeout: any, callback: any, that: any) {
|
|
51
54
|
if (timeout <= 2147483647) {
|
|
52
55
|
// Max value setTimeout can take is max 32 bit int (about 24.9 days)
|
|
53
56
|
return setTimeout(() => {
|
|
@@ -56,7 +59,7 @@ export function safeSetTimeout(timeout, callback, that) {
|
|
|
56
59
|
}
|
|
57
60
|
}
|
|
58
61
|
|
|
59
|
-
export function getSecondsDiff(startDate, endDate) {
|
|
62
|
+
export function getSecondsDiff(startDate: any, endDate: any) {
|
|
60
63
|
return Math.round(
|
|
61
64
|
Math.abs(Date.parse(endDate) - Date.parse(startDate)) / 1000
|
|
62
65
|
);
|
|
@@ -68,7 +71,7 @@ export function getSecondsDiff(startDate, endDate) {
|
|
|
68
71
|
* diff: update frequency in seconds
|
|
69
72
|
* label: content of the cell's column
|
|
70
73
|
*/
|
|
71
|
-
export function elapsedTime(seconds) {
|
|
74
|
+
export function elapsedTime(seconds: any) {
|
|
72
75
|
if (!seconds) {
|
|
73
76
|
return {};
|
|
74
77
|
}
|
|
@@ -119,3 +122,19 @@ export function elapsedTime(seconds) {
|
|
|
119
122
|
label: `${ hours }h${ minutes - (hours * 60) }m`,
|
|
120
123
|
};
|
|
121
124
|
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Format date and time using user preferences
|
|
128
|
+
* @param value Date string to format
|
|
129
|
+
* @returns Formatted date string
|
|
130
|
+
*/
|
|
131
|
+
export const dateTimeFormat = (value: string | undefined, store: Store<any>): string => {
|
|
132
|
+
if (!value) return '';
|
|
133
|
+
|
|
134
|
+
const dateFormat = escapeHtml( store.getters['prefs/get'](DATE_FORMAT));
|
|
135
|
+
const timeFormat = escapeHtml( store.getters['prefs/get'](TIME_FORMAT));
|
|
136
|
+
|
|
137
|
+
const format = `${ dateFormat } ${ timeFormat }`;
|
|
138
|
+
|
|
139
|
+
return day(value).format(format);
|
|
140
|
+
};
|
package/utils/uiplugins.ts
CHANGED
|
@@ -321,3 +321,25 @@ export async function getHelmChart(store: any, repository: any, chartName: strin
|
|
|
321
321
|
await new Promise((resolve) => setTimeout(resolve, RETRY_WAIT));
|
|
322
322
|
}
|
|
323
323
|
}
|
|
324
|
+
|
|
325
|
+
export async function onExtensionsReady(store: any) {
|
|
326
|
+
const alreadyReady = store.getters['uiplugins/ready'];
|
|
327
|
+
|
|
328
|
+
if (alreadyReady) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
const extensions = store.getters['uiplugins/plugins'] || [];
|
|
333
|
+
|
|
334
|
+
for (let i = 0; i < extensions.length; i++) {
|
|
335
|
+
const ext = extensions[i];
|
|
336
|
+
|
|
337
|
+
try {
|
|
338
|
+
await ext.onLogIn(store);
|
|
339
|
+
} catch (e) {
|
|
340
|
+
console.error(`Exception caught in onReady for extension ${ ext.name }`, e); // eslint-disable-line no-console
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
await store.dispatch('uiplugins/setReady', true);
|
|
345
|
+
}
|
|
@@ -96,8 +96,8 @@ describe('formRules', () => {
|
|
|
96
96
|
);
|
|
97
97
|
});
|
|
98
98
|
|
|
99
|
-
describe('
|
|
100
|
-
const message = JSON.stringify({ message: 'validation.git.
|
|
99
|
+
describe('urlRepository', () => {
|
|
100
|
+
const message = JSON.stringify({ message: 'validation.git.url' });
|
|
101
101
|
const testCases = [
|
|
102
102
|
// Valid HTTP(s)
|
|
103
103
|
['https://github.com/rancher/dashboard.git', undefined],
|
|
@@ -128,7 +128,40 @@ describe('formRules', () => {
|
|
|
128
128
|
it.each(testCases)(
|
|
129
129
|
'should return undefined or correct message based on the provided Git url: %p',
|
|
130
130
|
(url, expected) => {
|
|
131
|
-
const formRuleResult = formRules.
|
|
131
|
+
const formRuleResult = formRules.urlRepository(url);
|
|
132
|
+
|
|
133
|
+
expect(formRuleResult).toStrictEqual(expected);
|
|
134
|
+
}
|
|
135
|
+
);
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
describe('ociRegistry', () => {
|
|
139
|
+
const message = JSON.stringify({ message: 'validation.oci.url' });
|
|
140
|
+
const testCases = [
|
|
141
|
+
// Valid
|
|
142
|
+
['oci://bucket/object', undefined],
|
|
143
|
+
['oci://region.objectstorage.example.com/n', undefined],
|
|
144
|
+
['oci://a', undefined],
|
|
145
|
+
['oci://UPPERCASE/path', undefined],
|
|
146
|
+
|
|
147
|
+
// Invalid
|
|
148
|
+
['http://example.com/oci', message],
|
|
149
|
+
['https://oci.cloud.com', message],
|
|
150
|
+
['ftp://oci.server.net', message],
|
|
151
|
+
['/path/to/oci', message],
|
|
152
|
+
['oci:/missing/slash', message],
|
|
153
|
+
['oci:', message],
|
|
154
|
+
['oci://', message],
|
|
155
|
+
['oci://space between', message],
|
|
156
|
+
['oci://resource multiple spaces', message],
|
|
157
|
+
['', message],
|
|
158
|
+
[undefined, message],
|
|
159
|
+
];
|
|
160
|
+
|
|
161
|
+
it.each(testCases)(
|
|
162
|
+
'should return undefined or correct message based on the provided OCI url: %p',
|
|
163
|
+
(url, expected) => {
|
|
164
|
+
const formRuleResult = formRules.ociRegistry(url);
|
|
132
165
|
|
|
133
166
|
expect(formRuleResult).toStrictEqual(expected);
|
|
134
167
|
}
|
|
@@ -170,19 +170,27 @@ export default function(
|
|
|
170
170
|
|
|
171
171
|
const url: Validator = (val: string) => val && !isUrl(val) ? t('validation.setting.serverUrl.url') : undefined;
|
|
172
172
|
|
|
173
|
-
const
|
|
173
|
+
const genericUrl: Validator = (val: string) => val && !isUrl(val) ? t('validation.genericUrl') : undefined;
|
|
174
|
+
|
|
175
|
+
const urlRepository: Validator = (url: string) => {
|
|
174
176
|
const regexPart1 = /^((http|git|ssh|http(s)|file|\/?)|(git@[\w\.]+))(:(\/\/)?)/gm;
|
|
175
177
|
const regexPart2 = /^([\w\.@\:\/\-]+)([\d\/\w.-]+?)(.git){0,1}(\/)?$/gm;
|
|
176
178
|
|
|
177
179
|
if (url) {
|
|
178
180
|
const urlPart2 = url.replaceAll(regexPart1, '');
|
|
179
181
|
|
|
180
|
-
return !urlPart2 || url === urlPart2 || !regexPart2.test(urlPart2.replaceAll('%20', '')) ? t('validation.git.
|
|
182
|
+
return !urlPart2 || url === urlPart2 || !regexPart2.test(urlPart2.replaceAll('%20', '')) ? t('validation.git.url') : undefined;
|
|
181
183
|
}
|
|
182
184
|
|
|
183
185
|
return undefined;
|
|
184
186
|
};
|
|
185
187
|
|
|
188
|
+
const ociRegistry: Validator = (url: string) => {
|
|
189
|
+
const regex = /^oci:\/\/\S+$/gm;
|
|
190
|
+
|
|
191
|
+
return !regex.test(url) ? t('validation.oci.url') : undefined;
|
|
192
|
+
};
|
|
193
|
+
|
|
186
194
|
const alphanumeric: Validator = (val: string) => val && !/^[a-zA-Z0-9]+$/.test(val) ? t('validation.alphanumeric', { key }) : undefined;
|
|
187
195
|
|
|
188
196
|
const interval: Validator = (val: string) => !/^\d+[hms]$/.test(val) ? t('validation.monitoring.route.interval', { key }) : undefined;
|
|
@@ -527,7 +535,7 @@ export default function(
|
|
|
527
535
|
dnsLabelRestricted,
|
|
528
536
|
externalName,
|
|
529
537
|
fileRequired,
|
|
530
|
-
|
|
538
|
+
urlRepository,
|
|
531
539
|
groupsAreValid,
|
|
532
540
|
hostname,
|
|
533
541
|
imageUrl,
|
|
@@ -536,12 +544,14 @@ export default function(
|
|
|
536
544
|
localhost,
|
|
537
545
|
trailingForwardSlash,
|
|
538
546
|
url,
|
|
547
|
+
genericUrl,
|
|
539
548
|
matching,
|
|
540
549
|
maxLength,
|
|
541
550
|
maxValue,
|
|
542
551
|
minLength,
|
|
543
552
|
minValue,
|
|
544
553
|
noUpperCase,
|
|
554
|
+
ociRegistry,
|
|
545
555
|
portNumber,
|
|
546
556
|
registryUrl,
|
|
547
557
|
required,
|
package/utils/window.js
CHANGED
|
@@ -28,7 +28,7 @@ export class Popup {
|
|
|
28
28
|
this.popup = null;
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
-
open(url, name, opt) {
|
|
31
|
+
open(url, name, opt, doNotPollForClosure) {
|
|
32
32
|
this.onOpen();
|
|
33
33
|
this.popup = open(url, name, opt);
|
|
34
34
|
|
|
@@ -36,11 +36,15 @@ export class Popup {
|
|
|
36
36
|
throw new Error('Please disable your popup blocker for this site');
|
|
37
37
|
}
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
39
|
+
// In some cases, for example, if the origin policy does not allow, we will think the window has closed
|
|
40
|
+
// when it has not - we will see it as closed, because we don't have access
|
|
41
|
+
if (!doNotPollForClosure) {
|
|
42
|
+
const timer = setInterval(() => {
|
|
43
|
+
if (this.popup.closed) {
|
|
44
|
+
clearInterval(timer);
|
|
45
|
+
this.onClose();
|
|
46
|
+
}
|
|
47
|
+
}, 500);
|
|
48
|
+
}
|
|
45
49
|
}
|
|
46
50
|
}
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import { mount } from '@vue/test-utils';
|
|
2
|
-
import ApplicationCard from '@shell/components/cards/ApplicationCard.vue';
|
|
3
|
-
|
|
4
|
-
describe('component: ApplicationCard', () => {
|
|
5
|
-
const wrapper = mount(ApplicationCard, {
|
|
6
|
-
slots: {
|
|
7
|
-
cardIcon: '<i class="icon icon-fw icon-epinio"></i>',
|
|
8
|
-
'top-left': '<h1>Routes</h1> <ul><li> <a target="_blank" rel="noopener noreferrer nofollow"> route1 </a> </li> <li><a target="_blank" rel="noopener noreferrer nofollow"> route1 </a></li> </ul>',
|
|
9
|
-
}
|
|
10
|
-
});
|
|
11
|
-
|
|
12
|
-
it.each([
|
|
13
|
-
'cardIcon',
|
|
14
|
-
'top-left',
|
|
15
|
-
'top-right',
|
|
16
|
-
'resourcesCount',
|
|
17
|
-
])('should have a populated %p slot', (slot) => {
|
|
18
|
-
const content = '<div>text</div>';
|
|
19
|
-
const ele = mount(ApplicationCard, { slots: { [slot]: content } });
|
|
20
|
-
|
|
21
|
-
expect(ele.find(`[data-testid="${ slot }-section"`).find('div').html()).toContain(content);
|
|
22
|
-
});
|
|
23
|
-
|
|
24
|
-
it('should have card-icon slot with an icon', () => {
|
|
25
|
-
expect(wrapper.find('[data-testid="cardIcon-section"]').find('i').classes()).toContain('icon-epinio');
|
|
26
|
-
});
|
|
27
|
-
});
|