dashboard-shell-shell 3.0.2-test.20250913 → 3.0.5-test.2
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 +3 -0
- package/assets/icons/demo.css:Zone.Identifier +0 -0
- package/assets/icons/demo_index.html:Zone.Identifier +0 -0
- package/assets/icons/iconfont.css:Zone.Identifier +0 -0
- package/assets/icons/iconfont.js:Zone.Identifier +0 -0
- package/assets/icons/iconfont.json:Zone.Identifier +0 -0
- package/assets/icons/iconfont.ttf:Zone.Identifier +0 -0
- package/assets/icons/iconfont.woff2:Zone.Identifier +0 -0
- package/assets/icons/iconfont.woff:Zone.Identifier +0 -0
- package/assets/images/icons/document.svg +3 -0
- package/assets/images/key.svg +17 -0
- package/assets/images/providers/sks.svg +1 -0
- package/assets/images/vendor/cognito.svg +1 -0
- package/assets/styles/app.scss +3 -0
- package/assets/styles/base/_basic.scss +10 -0
- package/assets/styles/base/_spacing.scss +29 -0
- package/assets/styles/base/_variables.scss +16 -10
- package/assets/styles/global/_labeled-input.scss +1 -1
- package/assets/styles/global/_layout.scss +1 -1
- package/assets/styles/themes/_dark.scss +30 -0
- package/assets/styles/themes/_light.scss +80 -2
- package/assets/translations/en-us.yaml +822 -105
- package/assets/translations/zh-hans.yaml +13 -3
- package/chart/__tests__/S3.test.ts +2 -1
- package/chart/monitoring/index.vue +1 -1
- package/cloud-credential/gcp.vue +9 -1
- package/components/ActionMenuShell.vue +3 -7
- package/components/AppModal.vue +9 -28
- package/components/AsyncButton.vue +2 -0
- package/components/BrandImage.vue +0 -21
- package/components/Certificates.vue +5 -0
- package/components/CodeMirror.vue +3 -3
- package/components/CommunityLinks.vue +3 -58
- package/components/ConfigMapSettings/Settings.vue +377 -0
- package/components/ConfigMapSettings/index.vue +354 -0
- package/components/CruResource.vue +103 -16
- package/components/DetailText.vue +61 -11
- package/components/Drawer/Chrome.vue +115 -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 +106 -0
- package/components/Drawer/ResourceDetailDrawer/__tests__/helpers.test.ts +42 -0
- package/components/Drawer/ResourceDetailDrawer/composables.ts +53 -0
- package/components/Drawer/ResourceDetailDrawer/helpers.ts +10 -0
- package/components/Drawer/ResourceDetailDrawer/index.vue +123 -0
- package/components/ExplorerProjectsNamespaces.vue +46 -29
- package/components/FilterPanel.vue +156 -0
- package/components/FixedBanner.vue +19 -5
- 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/LandingPagePreference.vue +2 -0
- package/components/Loading.vue +1 -1
- package/components/LocaleSelector.vue +10 -2
- package/components/PaginatedResourceTable.vue +53 -1
- package/components/ProgressBarMulti.vue +1 -0
- package/components/PromptModal.vue +38 -7
- package/components/PromptRemove.vue +5 -1
- package/components/PromptRestore.vue +22 -44
- 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 +72 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +317 -0
- package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +140 -0
- package/components/Resource/Detail/Metadata/KeyValue.vue +140 -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 +34 -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 +81 -0
- package/components/Resource/Detail/Metadata/index.vue +88 -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 +46 -0
- package/components/Resource/Detail/TitleBar/index.vue +204 -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/{Masthead.vue → Masthead/legacy.vue} +0 -1
- package/components/ResourceDetail/__tests__/index.test.ts +135 -0
- package/components/ResourceDetail/index.vue +75 -575
- package/components/ResourceDetail/legacy.vue +564 -0
- package/components/ResourceList/Masthead.vue +69 -20
- package/components/ResourceList/index.vue +3 -2
- package/components/ResourceTable.vue +59 -85
- package/components/ResourceYaml.vue +15 -2
- package/components/RichTranslation.vue +106 -0
- package/components/SlideInPanelManager.vue +116 -14
- package/components/SortableTable/index.vue +10 -2
- package/components/SortableTable/paging.js +15 -16
- package/components/SortableTable/selection.js +22 -10
- package/components/StateDot/index.vue +28 -0
- package/components/StatusBadge.vue +6 -4
- package/components/SubtleLink.vue +25 -0
- package/components/Tabbed/index.vue +38 -22
- package/components/Wizard.vue +16 -3
- package/components/YamlEditor.vue +1 -2
- package/components/__tests__/AsyncButton.test.ts +39 -0
- package/components/__tests__/ConfigMapSettings.test.ts +376 -0
- package/components/__tests__/CruResource.test.ts +63 -0
- package/components/__tests__/FilterPanel.test.ts +81 -0
- package/components/__tests__/GrowlManager.test.ts +0 -25
- package/components/__tests__/PromptModal.test.ts +146 -0
- package/components/__tests__/PromptRestore.test.ts +1 -65
- package/components/__tests__/RichTranslation.test.ts +115 -0
- package/components/auth/AuthBanner.vue +15 -14
- package/components/auth/Principal.vue +0 -1
- package/components/auth/RoleDetailEdit.vue +44 -4
- package/components/auth/login/ldap.vue +2 -2
- 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 +69 -27
- 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 +384 -0
- package/components/form/ArrayList.vue +144 -116
- package/components/form/BannerSettings.vue +117 -50
- package/components/form/ChangePassword.vue +3 -1
- package/components/form/ColorInput.vue +35 -6
- package/components/form/FileImageSelector.vue +1 -1
- package/components/form/Footer.vue +10 -4
- package/components/form/KeyValue.vue +92 -51
- package/components/form/LabeledSelect.vue +72 -54
- package/components/form/Labels.vue +91 -21
- package/components/form/MatchExpressions.vue +56 -9
- package/components/form/NameNsDescription.vue +12 -8
- package/components/form/Networking.vue +24 -19
- package/components/form/NotificationSettings.vue +15 -1
- package/components/form/ResourceLabeledSelect.vue +22 -8
- package/components/form/ResourceSelector.vue +27 -23
- package/components/form/ResourceTabs/index.vue +7 -1
- package/components/form/SSHKnownHosts/index.vue +14 -11
- package/components/form/SecretSelector.vue +18 -2
- package/components/form/Select.vue +57 -26
- package/components/form/SelectOrCreateAuthSecret.vue +6 -3
- package/components/form/SimpleSecretSelector.vue +17 -4
- package/components/form/Taints.vue +21 -2
- package/components/form/UnitInput.vue +21 -0
- package/components/form/ValueFromResource.vue +31 -19
- package/components/form/__tests__/ArrayList.test.ts +32 -0
- package/components/form/__tests__/ColorInput.test.ts +35 -0
- package/components/form/__tests__/KeyValue.test.ts +36 -0
- package/components/form/__tests__/LabeledSelect.test.ts +79 -2
- package/components/form/__tests__/Labels.test.ts +360 -0
- package/components/form/__tests__/MatchExpressions.test.ts +16 -13
- package/components/form/__tests__/Networking.test.ts +116 -0
- package/components/form/__tests__/SSHKnownHosts.test.ts +11 -2
- package/components/form/__tests__/Select.test.ts +37 -1
- package/components/form/__tests__/UnitInput.test.ts +23 -1
- package/components/form/labeled-select-utils/labeled-select-pagination.ts +3 -38
- package/components/formatter/ClusterLink.vue +5 -8
- package/components/formatter/Description.vue +30 -0
- package/components/formatter/FleetApplicationClustersReady.vue +77 -0
- package/components/formatter/FleetApplicationSource.vue +79 -0
- package/components/formatter/FleetSummaryGraph.vue +7 -0
- package/components/formatter/PodImages.vue +1 -1
- package/components/formatter/WorkloadHealthScale.vue +1 -1
- package/components/formatter/__tests__/ClusterLink.test.ts +2 -32
- package/components/formatter/__tests__/LiveDate.test.ts +10 -2
- package/components/google/AccountAccess.vue +209 -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 +5 -0
- package/components/nav/Header.vue +24 -38
- package/components/nav/NamespaceFilter.vue +141 -84
- package/components/nav/NotificationCenter/Notification.vue +484 -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/components/nav/WindowManager/ContainerLogs.vue +87 -61
- package/components/nav/WindowManager/ContainerLogsActions.vue +76 -0
- package/components/nav/WindowManager/index.vue +3 -2
- package/components/templates/default.vue +0 -3
- package/components/templates/plain.vue +0 -3
- package/composables/drawer.ts +26 -0
- package/composables/focusTrap.ts +3 -3
- 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 +22 -11
- package/config/pagination-table-headers.js +8 -1
- package/config/private-label.js +0 -1
- package/config/product/auth.js +20 -3
- package/config/product/{cis.js → compliance.js} +23 -26
- package/config/product/explorer.js +49 -17
- package/config/product/fleet.js +77 -17
- package/config/product/manager.js +1 -29
- package/config/product/settings.js +23 -11
- package/config/query-params.js +16 -1
- package/config/roles.ts +2 -1
- package/config/router/navigation-guards/authentication.js +51 -2
- package/config/router/navigation-guards/index.js +5 -67
- package/config/router/routes.js +65 -31
- package/config/secret.ts +15 -0
- package/config/settings.ts +33 -16
- package/config/store.js +2 -0
- package/config/system-namespaces.js +1 -1
- package/config/table-headers.js +91 -30
- package/config/types.js +18 -7
- package/config/version.js +1 -1
- package/core/plugin-helpers.ts +3 -2
- package/core/plugin.ts +32 -7
- package/core/types.ts +25 -7
- package/detail/catalog.cattle.io.app.vue +5 -1
- package/detail/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +22 -18
- package/detail/fleet.cattle.io.bundle.vue +70 -6
- package/detail/fleet.cattle.io.cluster.vue +28 -15
- package/detail/fleet.cattle.io.gitrepo.vue +11 -2
- 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/namespace.vue +0 -3
- package/detail/node.vue +20 -16
- package/detail/pod.vue +2 -2
- package/detail/provisioning.cattle.io.cluster.vue +16 -50
- package/detail/service.vue +10 -2
- package/detail/workload/index.vue +48 -39
- package/dialog/AddCustomBadgeDialog.vue +0 -1
- package/{pages/c/_cluster/uiplugins/AddExtensionRepos.vue → dialog/AddExtensionReposDialog.vue} +72 -42
- package/dialog/AddonConfigConfirmationDialog.vue +1 -1
- package/dialog/AssignToDialog.vue +176 -0
- package/dialog/ChangePasswordDialog.vue +106 -0
- package/{pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue → dialog/DeveloperLoadExtensionDialog.vue} +74 -71
- package/dialog/DisableAuthProviderDialog.vue +101 -0
- package/dialog/DrainNode.vue +1 -1
- package/{pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue → dialog/ExtensionCatalogInstallDialog.vue} +100 -88
- package/{pages/c/_cluster/uiplugins/CatalogList/CatalogUninstallDialog.vue → dialog/ExtensionCatalogUninstallDialog.vue} +87 -66
- package/dialog/FeatureFlagListDialog.vue +288 -0
- package/dialog/ForceMachineRemoveDialog.vue +1 -1
- package/dialog/GenericPrompt.vue +1 -1
- package/dialog/HelmOpForceUpdateDialog.vue +132 -0
- package/{components/Import.vue → dialog/ImportDialog.vue} +8 -13
- package/{pages/c/_cluster/uiplugins/InstallDialog.vue → dialog/InstallExtensionDialog.vue} +124 -106
- package/{components/form/SSHKnownHosts → dialog}/KnownHostsEditDialog.vue +52 -62
- package/dialog/MoveNamespaceDialog.vue +157 -0
- package/dialog/OidcClientSecretDialog.vue +117 -0
- package/dialog/RedeployWorkloadDialog.vue +164 -0
- package/dialog/RotateEncryptionKeyDialog.vue +10 -30
- package/dialog/ScalePoolDownDialog.vue +1 -1
- package/{components/nav/Jump.vue → dialog/SearchDialog.vue} +34 -14
- package/{pages/c/_cluster/uiplugins/UninstallDialog.vue → dialog/UninstallExtensionDialog.vue} +67 -58
- package/dialog/WechatDialog.vue +57 -0
- package/{components/form/SSHKnownHosts → dialog}/__tests__/KnownHostsEditDialog.test.ts +15 -34
- package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +3 -3
- package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +60 -68
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
- package/edit/__tests__/service.test.ts +2 -1
- package/edit/auth/ldap/__tests__/config.test.ts +14 -0
- package/edit/auth/ldap/config.vue +24 -0
- 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 +8 -2
- package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
- package/edit/fleet.cattle.io.gitrepo.vue +70 -256
- package/edit/fleet.cattle.io.helmop.vue +786 -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 +2 -1
- package/edit/logging.banzaicloud.io.output/providers/awsElasticsearch.vue +5 -6
- 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 +3 -3
- 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 +2 -4
- package/edit/networking.istio.io.destinationrule/index.vue +4 -1
- package/edit/networking.k8s.io.ingress/Certificate.vue +11 -3
- package/edit/networking.k8s.io.ingress/__tests__/Certificate.test.ts +37 -0
- package/edit/networking.k8s.io.ingress/index.vue +4 -1
- package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +3 -14
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +57 -62
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +10 -16
- package/edit/networking.k8s.io.networkpolicy/__tests__/PolicyRuleTarget.test.ts +72 -41
- package/edit/networking.k8s.io.networkpolicy/__tests__/utils/mock.json +17 -1
- package/edit/networking.k8s.io.networkpolicy/index.vue +23 -31
- package/edit/node.vue +1 -0
- package/edit/persistentvolume/index.vue +4 -1
- package/edit/provisioning.cattle.io.cluster/__tests__/DirectoryConfig.test.ts +26 -12
- package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +69 -2
- package/edit/provisioning.cattle.io.cluster/__tests__/utils/rke2-test-data.ts +58 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +21 -73
- package/edit/provisioning.cattle.io.cluster/rke2.vue +535 -428
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +48 -39
- package/edit/provisioning.cattle.io.cluster/tabs/DirectoryConfig.vue +5 -3
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +5 -0
- package/edit/provisioning.cattle.io.cluster/tabs/registries/RegistryConfigs.vue +2 -2
- package/edit/resources.cattle.io.restore.vue +1 -1
- package/edit/secret/basic.vue +1 -0
- package/edit/secret/index.vue +127 -15
- package/edit/service.vue +17 -29
- package/edit/serviceaccount.vue +4 -1
- package/edit/storage.k8s.io.storageclass/index.vue +4 -1
- package/edit/workload/index.vue +11 -15
- package/edit/workload/mixins/workload.js +0 -2
- 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/harvesterhci.io.management.cluster.vue +0 -17
- package/list/management.cattle.io.feature.vue +4 -288
- package/list/management.cattle.io.oidcclient.vue +108 -0
- package/list/management.cattle.io.user.vue +13 -20
- package/list/namespace.vue +6 -2
- package/list/node.vue +2 -0
- package/list/projectsecret.vue +345 -0
- package/list/secret.vue +109 -0
- package/list/workload.vue +6 -2
- package/machine-config/__tests__/vmwarevsphere.test.ts +5 -7
- package/machine-config/amazonec2.vue +3 -24
- package/machine-config/components/GCEImage.vue +374 -0
- package/machine-config/google.vue +617 -0
- package/machine-config/vmwarevsphere.vue +7 -17
- 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/impl.js +10 -1
- package/mixins/create-edit-view/index.js +5 -0
- package/mixins/preset.js +100 -0
- package/mixins/resource-fetch-api-pagination.js +73 -44
- package/mixins/resource-fetch.js +18 -8
- package/mixins/resource-table-watch.js +45 -0
- package/mixins/vue-select-overrides.js +1 -4
- package/models/__tests__/chart.test.ts +296 -0
- package/models/__tests__/fleet.cattle.io.gitrepo.test.ts +1 -1
- package/models/__tests__/fleet.cattle.io.helmop.test.ts +224 -0
- package/models/__tests__/node.test.ts +7 -63
- package/models/__tests__/workload.test.ts +1 -0
- package/models/chart.js +157 -2
- package/models/cluster/node.js +2 -1
- package/models/cluster.js +32 -2
- package/models/cluster.x-k8s.io.machinedeployment.js +11 -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 +297 -0
- package/models/fleet.cattle.io.bundle.js +9 -8
- package/models/fleet.cattle.io.cluster.js +21 -4
- package/models/fleet.cattle.io.gitrepo.js +46 -382
- package/models/fleet.cattle.io.helmop.js +202 -0
- package/models/management.cattle.io.authconfig.js +1 -0
- package/models/management.cattle.io.cluster.js +0 -20
- package/models/management.cattle.io.feature.js +7 -1
- package/models/management.cattle.io.fleetworkspace.js +14 -1
- package/models/management.cattle.io.node.js +7 -22
- package/models/management.cattle.io.nodepool.js +12 -0
- package/models/management.cattle.io.oidcclient.js +18 -0
- package/models/management.cattle.io.registration.js +3 -0
- package/models/management.cattle.io.setting.js +0 -1
- package/models/namespace.js +12 -1
- package/models/provisioning.cattle.io.cluster.js +60 -97
- package/models/secret.js +157 -2
- package/models/service.js +28 -9
- package/models/storage.k8s.io.storageclass.js +2 -2
- package/models/workload.js +91 -51
- package/package.json +6 -5
- package/pages/about.vue +17 -61
- package/pages/account/index.vue +9 -1
- package/pages/auth/login.vue +2 -3
- 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 +57 -0
- package/pages/c/_cluster/apps/charts/StatusLabel.vue +33 -0
- package/pages/c/_cluster/apps/charts/index.vue +501 -468
- package/pages/c/_cluster/apps/charts/install.vue +0 -1
- package/pages/c/_cluster/auth/roles/index.vue +19 -48
- 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 +14 -3
- package/pages/c/_cluster/explorer/projectsecret.vue +34 -0
- package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -1
- package/pages/c/_cluster/fleet/__tests__/index.test.ts +720 -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 +866 -328
- package/pages/c/_cluster/fleet/settings/index.vue +229 -0
- package/pages/c/_cluster/longhorn/index.vue +5 -2
- package/pages/c/_cluster/settings/banners.vue +56 -2
- package/pages/c/_cluster/settings/brand.vue +2 -1
- package/pages/c/_cluster/settings/performance.vue +7 -26
- package/pages/c/_cluster/uiplugins/CatalogList/index.vue +16 -1
- package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +2 -2
- package/pages/c/_cluster/uiplugins/__tests__/AddExtensionRepos.test.ts +4 -7
- package/pages/c/_cluster/uiplugins/index.vue +98 -55
- package/pages/explorer/resource/detail/configmap.vue +42 -0
- package/pages/explorer/resource/detail/projectsecret.vue +9 -0
- package/pages/explorer/resource/detail/secret.vue +63 -0
- package/pages/home.vue +8 -104
- package/pages/prefs.vue +0 -1
- package/pages/support/index.vue +4 -6
- package/plugins/clean-html.js +2 -0
- package/plugins/dashboard-store/__tests__/actions.test.ts +4 -1
- package/plugins/dashboard-store/__tests__/normalize.test.ts +223 -0
- package/plugins/dashboard-store/__tests__/resource-class.test.ts +191 -0
- package/plugins/dashboard-store/__tests__/utils/normalize-usecases.ts +1526 -0
- package/plugins/dashboard-store/actions.js +212 -55
- package/plugins/dashboard-store/getters.js +112 -24
- package/plugins/dashboard-store/mutations.js +61 -12
- package/plugins/dashboard-store/normalize.js +29 -19
- package/plugins/dashboard-store/resource-class.js +132 -49
- package/plugins/steve/__tests__/getters.test.ts +19 -12
- package/plugins/steve/__tests__/steve-class.test.ts +1 -0
- package/plugins/steve/__tests__/subscribe.spec.ts +324 -1
- package/plugins/steve/actions.js +37 -24
- package/plugins/steve/getters.js +47 -12
- package/plugins/steve/resourceWatcher.js +10 -3
- package/plugins/steve/steve-class.js +5 -0
- package/plugins/steve/steve-pagination-utils.ts +225 -43
- package/plugins/steve/subscribe.js +418 -53
- package/plugins/steve/worker/web-worker.advanced.js +5 -1
- package/rancher-components/Banner/Banner.test.ts +51 -3
- package/rancher-components/Banner/Banner.vue +37 -6
- package/rancher-components/Form/Checkbox/Checkbox.test.ts +59 -1
- package/rancher-components/Form/Checkbox/Checkbox.vue +27 -9
- package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +51 -0
- package/rancher-components/Form/LabeledInput/LabeledInput.vue +21 -3
- package/rancher-components/Form/Radio/RadioButton.test.ts +36 -1
- package/rancher-components/Form/Radio/RadioButton.vue +21 -5
- package/rancher-components/Form/Radio/RadioGroup.test.ts +60 -0
- package/rancher-components/Form/Radio/RadioGroup.vue +81 -38
- package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +4 -0
- package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +22 -1
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
- package/rancher-components/RcButton/RcButton.vue +1 -1
- package/rancher-components/RcDropdown/RcDropdown.test.ts +98 -0
- package/rancher-components/RcDropdown/RcDropdown.vue +6 -0
- package/rancher-components/RcDropdown/RcDropdownItem.vue +8 -55
- package/rancher-components/RcDropdown/RcDropdownItemCheckbox.vue +69 -0
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +93 -0
- package/rancher-components/RcDropdown/RcDropdownMenu.vue +7 -8
- package/rancher-components/RcDropdown/index.ts +2 -0
- package/rancher-components/RcDropdown/useDropdownContext.ts +21 -0
- package/rancher-components/RcDropdown/useDropdownItem.ts +92 -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/rancher-components/StringList/StringList.vue +1 -1
- package/scripts/extension/publish +1 -1
- package/static/loading-indicator.html +1 -1
- package/store/action-menu.js +26 -56
- package/store/auth.js +3 -0
- package/store/catalog.js +85 -25
- package/store/features.js +0 -1
- package/store/growl.js +97 -8
- package/store/i18n.js +1 -1
- package/store/index.js +44 -14
- package/store/notifications.ts +426 -0
- package/store/prefs.js +2 -8
- package/store/slideInPanel.ts +6 -0
- package/store/type-map.js +34 -17
- package/store/type-map.utils.ts +49 -6
- package/store/uiplugins.ts +15 -1
- package/types/fleet.d.ts +60 -1
- package/types/kube/kube-api.ts +34 -0
- package/types/notifications/index.ts +74 -0
- package/types/resources/fleet.d.ts +43 -0
- package/types/resources/pod-security-admission.ts +36 -0
- package/types/resources/settings.d.ts +107 -0
- package/types/resources/userPreferences.d.ts +13 -0
- package/types/shell/index.d.ts +971 -745
- package/types/store/dashboard-store.types.ts +57 -4
- package/types/store/pagination.types.ts +41 -9
- package/types/store/subscribe.types.ts +50 -0
- package/utils/__mocks__/tabbable.js +13 -0
- package/utils/__tests__/back-off.test.ts +354 -0
- package/utils/__tests__/create-yaml.test.ts +235 -0
- package/utils/__tests__/fleet.test.ts +148 -0
- package/utils/__tests__/kontainer.test.ts +19 -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 -6
- package/utils/back-off.ts +176 -0
- package/utils/cluster.js +24 -20
- package/utils/create-yaml.js +103 -9
- package/utils/crypto/encryption.ts +103 -0
- package/utils/cspAdaptor.ts +51 -0
- package/utils/error.js +0 -5
- package/utils/fleet-types.ts +0 -0
- package/utils/fleet.ts +204 -74
- package/utils/grafana.js +1 -0
- package/utils/kontainer.ts +3 -5
- package/utils/object.js +36 -12
- package/utils/pagination-utils.ts +50 -3
- package/utils/pagination-wrapper.ts +132 -50
- package/utils/perf-setting.utils.ts +28 -0
- package/utils/release-notes.ts +48 -0
- package/utils/selector-typed.ts +210 -0
- package/utils/selector.js +29 -6
- 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 +41 -8
- package/utils/v-sphere.ts +5 -1
- package/utils/validators/formRules/__tests__/index.test.ts +76 -6
- package/utils/validators/formRules/index.ts +99 -4
- package/utils/window.js +11 -7
- package/.DS_Store +0 -0
- package/components/AssignTo.vue +0 -199
- package/components/DisableAuthProviderModal.vue +0 -115
- package/components/MoveModal.vue +0 -167
- package/components/PromptChangePassword.vue +0 -123
- package/components/ResourceList/Masthead-btn.vue +0 -225
- package/components/__tests__/ApplicationCard.test.ts +0 -27
- package/components/cards/ApplicationCard.vue +0 -145
- package/components/fleet/FleetBundleResources.vue +0 -86
- package/components/fleet/ForceDirectedTreeChart/chartIcons.js +0 -17
- package/components/formatter/RKETemplateName.vue +0 -37
- package/config/product/legacy.js +0 -62
- package/config/secret.js +0 -14
- package/dialog/SaveAsRKETemplateDialog.vue +0 -139
- package/models/etcdbackup.js +0 -45
- package/pages/auth copy/login.vue +0 -595
- package/pages/auth copy/logout.vue +0 -47
- package/pages/auth copy/setup.vue +0 -523
- package/pages/auth copy/verify.vue +0 -203
- 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
|
@@ -0,0 +1,426 @@
|
|
|
1
|
+
import { md5 } from '@shell/utils/crypto';
|
|
2
|
+
import { randomStr } from '@shell/utils/string';
|
|
3
|
+
import { EncryptedNotification, Notification, StoredNotification } from '@shell/types/notifications';
|
|
4
|
+
import { encrypt, decrypt, deriveKey } from '@shell/utils/crypto/encryption';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Key used to store notifications in the browser's local storage
|
|
8
|
+
*/
|
|
9
|
+
const LOCAL_STORAGE_KEY_PREFIX = 'rancher-notifications-';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Expire notifications in seconds (14 days)
|
|
13
|
+
*/
|
|
14
|
+
const EXPIRY = 14 * 24 * 60 * 60;
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Maximum number of notifications that will be kept
|
|
18
|
+
*/
|
|
19
|
+
const MAX_NOTIFICATIONS = 50;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Broadcast channel name to send changes across tabs
|
|
23
|
+
*/
|
|
24
|
+
const NOTIFICATION_CHANNEL_NAME = 'rancher-notification-sync';
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Store for the UI Notification Centre
|
|
28
|
+
*/
|
|
29
|
+
interface NotificationsStore {
|
|
30
|
+
localStorageKey: string,
|
|
31
|
+
userId: string;
|
|
32
|
+
notifications: StoredNotification[],
|
|
33
|
+
encryptionKey: CryptoKey | undefined,
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const state = function(): NotificationsStore {
|
|
37
|
+
const notifications: StoredNotification[] = [];
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
localStorageKey: '',
|
|
41
|
+
userId: '',
|
|
42
|
+
encryptionKey: undefined,
|
|
43
|
+
notifications,
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
let bc: BroadcastChannel;
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Sync notifications to other tabs using the broadcast channel. Send the user id, to cover corner case
|
|
51
|
+
* where a stale login exists for a different user in another tab.
|
|
52
|
+
*/
|
|
53
|
+
function sync(userId: string, operation: string, param?: any) {
|
|
54
|
+
bc?.postMessage({
|
|
55
|
+
userId,
|
|
56
|
+
operation,
|
|
57
|
+
param
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async function saveEncryptedNotification(getters: any, notification: Notification) {
|
|
62
|
+
const toEncrypt: EncryptedNotification = {
|
|
63
|
+
title: notification.title,
|
|
64
|
+
message: notification.message,
|
|
65
|
+
level: notification.level,
|
|
66
|
+
primaryAction: notification.primaryAction,
|
|
67
|
+
secondaryAction: notification.secondaryAction,
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
const localStorageKey = getters['localStorageKey'];
|
|
71
|
+
const encryptionKey = getters['encryptionKey'];
|
|
72
|
+
|
|
73
|
+
try {
|
|
74
|
+
const data = JSON.stringify(toEncrypt);
|
|
75
|
+
const enc = await encrypt(data, encryptionKey);
|
|
76
|
+
|
|
77
|
+
window.localStorage.setItem(`${ localStorageKey }-${ notification.id }`, JSON.stringify(enc));
|
|
78
|
+
} catch (e) {
|
|
79
|
+
console.error('Unable to save notification to local storage', e); // eslint-disable-line no-console
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Sync the notifications index to local storage.
|
|
85
|
+
*
|
|
86
|
+
* We only store the non-sensitive data about the notifications in the index - the other data is stored in individual entries which are encrypted.
|
|
87
|
+
*/
|
|
88
|
+
function syncIndex(state: NotificationsStore) {
|
|
89
|
+
const localStorageKey = state.localStorageKey;
|
|
90
|
+
|
|
91
|
+
// We just want the id, created, read and progress properties for the index
|
|
92
|
+
const index = state.notifications.map((n) => ({
|
|
93
|
+
id: n.id,
|
|
94
|
+
created: n.created,
|
|
95
|
+
read: n.read,
|
|
96
|
+
progress: n.progress,
|
|
97
|
+
}));
|
|
98
|
+
|
|
99
|
+
try {
|
|
100
|
+
window.localStorage.setItem(localStorageKey, JSON.stringify(index));
|
|
101
|
+
} catch (e) {
|
|
102
|
+
console.error('Unable to save notifications index to local storage', e); // eslint-disable-line no-console
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export const getters = {
|
|
107
|
+
all: (state: NotificationsStore) => {
|
|
108
|
+
return state.notifications;
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
item: (state: NotificationsStore) => {
|
|
112
|
+
return (id: string) => {
|
|
113
|
+
return state.notifications.find((i) => i.id === id);
|
|
114
|
+
};
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
// Count of unread notifications
|
|
118
|
+
unreadCount: (state: NotificationsStore) => {
|
|
119
|
+
return state.notifications.filter((n) => !n.read).length;
|
|
120
|
+
},
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* Local storage key includes the user key
|
|
124
|
+
*/
|
|
125
|
+
localStorageKey: (state: NotificationsStore) => {
|
|
126
|
+
return state.localStorageKey;
|
|
127
|
+
},
|
|
128
|
+
|
|
129
|
+
userId: (state: NotificationsStore) => {
|
|
130
|
+
return state.userId;
|
|
131
|
+
},
|
|
132
|
+
|
|
133
|
+
encryptionKey: (state: NotificationsStore) => {
|
|
134
|
+
return state.encryptionKey;
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
export const mutations = {
|
|
139
|
+
add(state: NotificationsStore, notification: Notification) {
|
|
140
|
+
if (!notification.id) {
|
|
141
|
+
notification.id = randomStr();
|
|
142
|
+
} else {
|
|
143
|
+
// Check that there is not already a notification with this id
|
|
144
|
+
const index = state.notifications.findIndex((n) => n.id === notification.id);
|
|
145
|
+
|
|
146
|
+
if (index !== -1) {
|
|
147
|
+
console.error(`Can not add a notification with the same id as an existing notification (${ notification.id })`); // eslint-disable-line no-console
|
|
148
|
+
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const stored = {
|
|
154
|
+
...notification,
|
|
155
|
+
read: false,
|
|
156
|
+
created: new Date()
|
|
157
|
+
};
|
|
158
|
+
|
|
159
|
+
// Add to top of list
|
|
160
|
+
state.notifications.unshift(stored);
|
|
161
|
+
|
|
162
|
+
// Check that we have not exceeded the maximum number of notifications
|
|
163
|
+
if (state.notifications.length > MAX_NOTIFICATIONS) {
|
|
164
|
+
const removed = state.notifications.pop();
|
|
165
|
+
|
|
166
|
+
if (removed) {
|
|
167
|
+
// Remove the encrypted data for the notification that we just removed
|
|
168
|
+
window.localStorage.removeItem(`${ state.localStorageKey }-${ removed.id }`);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
syncIndex(state);
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
markRead(state: NotificationsStore, id: string) {
|
|
176
|
+
const notification = state.notifications.find((n) => n.id === id);
|
|
177
|
+
|
|
178
|
+
if (notification && !notification.read) {
|
|
179
|
+
notification.read = true;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
syncIndex(state);
|
|
183
|
+
},
|
|
184
|
+
|
|
185
|
+
markUnread(state: NotificationsStore, id: string) {
|
|
186
|
+
const notification = state.notifications.find((n) => n.id === id);
|
|
187
|
+
|
|
188
|
+
if (notification && notification.read) {
|
|
189
|
+
notification.read = false;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
syncIndex(state);
|
|
193
|
+
},
|
|
194
|
+
|
|
195
|
+
markAllRead(state: NotificationsStore) {
|
|
196
|
+
state.notifications.forEach((notification) => {
|
|
197
|
+
if (!notification.read) {
|
|
198
|
+
notification.read = true;
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
|
|
202
|
+
syncIndex(state);
|
|
203
|
+
},
|
|
204
|
+
|
|
205
|
+
update(state: NotificationsStore, notification: Partial<Notification>) {
|
|
206
|
+
if (notification?.id) {
|
|
207
|
+
const index = state.notifications.findIndex((n) => n.id === notification.id);
|
|
208
|
+
|
|
209
|
+
if (index >= 0) {
|
|
210
|
+
state.notifications[index] = {
|
|
211
|
+
...state.notifications[index],
|
|
212
|
+
...notification
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
syncIndex(state);
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
clearAll(state: NotificationsStore) {
|
|
221
|
+
// Remove the encrypted data for each notification
|
|
222
|
+
state.notifications.forEach((n) => {
|
|
223
|
+
window.localStorage.removeItem(`${ state.localStorageKey }-${ n.id }`);
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
state.notifications = [];
|
|
227
|
+
syncIndex(state);
|
|
228
|
+
},
|
|
229
|
+
|
|
230
|
+
remove(state: NotificationsStore, id: string) {
|
|
231
|
+
// Remove the encrypted data for the notification
|
|
232
|
+
window.localStorage.removeItem(`${ state.localStorageKey }-${ id }`);
|
|
233
|
+
|
|
234
|
+
state.notifications = state.notifications.filter((n) => n.id !== id);
|
|
235
|
+
syncIndex(state);
|
|
236
|
+
},
|
|
237
|
+
|
|
238
|
+
load(state: NotificationsStore, notifications: StoredNotification[]) {
|
|
239
|
+
state.notifications = notifications;
|
|
240
|
+
},
|
|
241
|
+
|
|
242
|
+
localStorageKey(state: NotificationsStore, userKey: string) {
|
|
243
|
+
state.localStorageKey = `${ LOCAL_STORAGE_KEY_PREFIX }${ userKey }`;
|
|
244
|
+
},
|
|
245
|
+
|
|
246
|
+
userId(state: NotificationsStore, userId: string) {
|
|
247
|
+
state.userId = userId;
|
|
248
|
+
},
|
|
249
|
+
|
|
250
|
+
encryptionKey(state: NotificationsStore, encryptionKey: CryptoKey) {
|
|
251
|
+
state.encryptionKey = encryptionKey;
|
|
252
|
+
},
|
|
253
|
+
};
|
|
254
|
+
|
|
255
|
+
export const actions = {
|
|
256
|
+
async add( { commit, dispatch, getters }: any, notification: Notification) {
|
|
257
|
+
// We encrypt the notification on add - this is the only time we will encrypt it
|
|
258
|
+
if (!notification.id) {
|
|
259
|
+
notification.id = randomStr();
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// Need to save the encrypted notification to local storage
|
|
263
|
+
await saveEncryptedNotification(getters, notification);
|
|
264
|
+
|
|
265
|
+
commit('add', notification);
|
|
266
|
+
sync(getters['userId'], 'add', notification);
|
|
267
|
+
|
|
268
|
+
// Show a growl for the notification if necessary
|
|
269
|
+
dispatch('growl/notification', notification, { root: true });
|
|
270
|
+
},
|
|
271
|
+
|
|
272
|
+
async fromGrowl( { commit, getters }: any, notification: Notification) {
|
|
273
|
+
notification.id = randomStr();
|
|
274
|
+
|
|
275
|
+
// Need to save the encrypted notification to local storage
|
|
276
|
+
await saveEncryptedNotification(getters, notification);
|
|
277
|
+
|
|
278
|
+
commit('add', notification);
|
|
279
|
+
sync(getters['userId'], 'add', notification);
|
|
280
|
+
|
|
281
|
+
return notification.id;
|
|
282
|
+
},
|
|
283
|
+
|
|
284
|
+
update({ commit, getters }: any, notification: Notification) {
|
|
285
|
+
commit('update', notification);
|
|
286
|
+
sync(getters['userId'], 'update', notification);
|
|
287
|
+
},
|
|
288
|
+
|
|
289
|
+
async markRead({ commit, dispatch, getters }: any, id: string) {
|
|
290
|
+
commit('markRead', id);
|
|
291
|
+
sync(getters['userId'], 'markRead', id);
|
|
292
|
+
|
|
293
|
+
const notification = getters.item(id);
|
|
294
|
+
|
|
295
|
+
if (notification?.preference) {
|
|
296
|
+
await dispatch('prefs/set', notification.preference, { root: true });
|
|
297
|
+
}
|
|
298
|
+
},
|
|
299
|
+
|
|
300
|
+
async markUnread({ commit, dispatch, getters }: any, id: string) {
|
|
301
|
+
commit('markUnread', id);
|
|
302
|
+
sync(getters['userId'], 'markUnread', id);
|
|
303
|
+
|
|
304
|
+
const notification = getters.item(id) as Notification;
|
|
305
|
+
|
|
306
|
+
if (notification?.preference) {
|
|
307
|
+
await dispatch('prefs/set', {
|
|
308
|
+
key: notification.preference.key,
|
|
309
|
+
value: notification.preference.unsetValue || '',
|
|
310
|
+
}, { root: true });
|
|
311
|
+
}
|
|
312
|
+
},
|
|
313
|
+
|
|
314
|
+
async markAllRead({ commit, dispatch, getters }: any) {
|
|
315
|
+
commit('markAllRead');
|
|
316
|
+
sync(getters['userId'], 'markAllRead');
|
|
317
|
+
|
|
318
|
+
// For all notifications that have a preference, set the preference, since they are now read
|
|
319
|
+
const withPreference = getters.all.filter((n: Notification) => !!n.preference);
|
|
320
|
+
|
|
321
|
+
for (let i = 0; i < withPreference.length; i++) {
|
|
322
|
+
await dispatch('prefs/set', withPreference[i].preference, { root: true });
|
|
323
|
+
}
|
|
324
|
+
},
|
|
325
|
+
|
|
326
|
+
remove({ commit, getters }: any, id: string) {
|
|
327
|
+
commit('remove', id);
|
|
328
|
+
sync(getters['userId'], 'remove', id);
|
|
329
|
+
},
|
|
330
|
+
|
|
331
|
+
clearAll({ commit, getters }: any) {
|
|
332
|
+
commit('clearAll');
|
|
333
|
+
sync(getters['userId'], 'clearAll');
|
|
334
|
+
},
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Initialize the notifications store and load the notifications from local storage
|
|
338
|
+
*/
|
|
339
|
+
async init({ commit, getters } : any, userData: any) {
|
|
340
|
+
const userKey = userData.id;
|
|
341
|
+
const userId = userData.v3User?.uuid;
|
|
342
|
+
|
|
343
|
+
if (!userKey || !userId) {
|
|
344
|
+
console.error('Unable to initialize notifications - required user info not available'); // eslint-disable-line no-console
|
|
345
|
+
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
// Notifications are stored under a key for the current user, so set the local storage key based on the user id
|
|
350
|
+
commit('localStorageKey', md5(userKey, 'hex'));
|
|
351
|
+
commit('userId', userId);
|
|
352
|
+
|
|
353
|
+
let index: StoredNotification[] = [];
|
|
354
|
+
let notifications: StoredNotification[] = [];
|
|
355
|
+
const localStorageKey = getters['localStorageKey'];
|
|
356
|
+
|
|
357
|
+
let encryptionKey;
|
|
358
|
+
|
|
359
|
+
try {
|
|
360
|
+
encryptionKey = await deriveKey(userId);
|
|
361
|
+
} catch (e) {
|
|
362
|
+
console.error('Unable to generate encryption key for notifications', e); // eslint-disable-line no-console
|
|
363
|
+
|
|
364
|
+
return;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
// Store the encryption key
|
|
368
|
+
commit('encryptionKey', encryptionKey);
|
|
369
|
+
|
|
370
|
+
// Load the notifications from local storage
|
|
371
|
+
// We store the index of notifications in local storage, and the actual notification data is stored in individual entries which are encrypted
|
|
372
|
+
try {
|
|
373
|
+
const data = window.localStorage.getItem(localStorageKey) || '[]';
|
|
374
|
+
|
|
375
|
+
index = JSON.parse(data) as StoredNotification[];
|
|
376
|
+
} catch (e) {
|
|
377
|
+
console.error('Unable to read notifications from local storage', e); // eslint-disable-line no-console
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
for (let i = 0; i < index.length; i++) {
|
|
381
|
+
const n = index[i];
|
|
382
|
+
|
|
383
|
+
try {
|
|
384
|
+
const data = window.localStorage.getItem(`${ localStorageKey }-${ n.id }`);
|
|
385
|
+
const parsedData = data ? JSON.parse(data) : '{}';
|
|
386
|
+
const decryptedString = await decrypt(parsedData, encryptionKey);
|
|
387
|
+
const decrypted = JSON.parse(decryptedString) as EncryptedNotification;
|
|
388
|
+
|
|
389
|
+
// Overlay the decrypted data onto the notification
|
|
390
|
+
notifications.push({
|
|
391
|
+
...n,
|
|
392
|
+
...decrypted
|
|
393
|
+
});
|
|
394
|
+
} catch (e) {
|
|
395
|
+
console.error('Unable to decrypt notification data', e); // eslint-disable-line no-console
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
// Expire old notifications
|
|
400
|
+
const now = new Date();
|
|
401
|
+
|
|
402
|
+
notifications = notifications.filter((n: StoredNotification) => {
|
|
403
|
+
// Try ... catch in case the date parsing fails
|
|
404
|
+
try {
|
|
405
|
+
const created = new Date(n.created);
|
|
406
|
+
const diff = (now.getTime() - created.getTime()) / 1000; // Diff in seconds
|
|
407
|
+
|
|
408
|
+
return diff < EXPIRY;
|
|
409
|
+
} catch (e) {}
|
|
410
|
+
|
|
411
|
+
return true;
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
commit('load', notifications);
|
|
415
|
+
|
|
416
|
+
// Set up broadcast listener to listen for updates from other tabs
|
|
417
|
+
bc = new BroadcastChannel(NOTIFICATION_CHANNEL_NAME);
|
|
418
|
+
|
|
419
|
+
bc.onmessage = (msgEvent: any) => {
|
|
420
|
+
// Ignore events where the user id does not match (corner case of stale login in another tab)
|
|
421
|
+
if (msgEvent?.data?.operation && msgEvent?.data?.userId === userId) {
|
|
422
|
+
commit(msgEvent.data.operation, msgEvent.data.param);
|
|
423
|
+
}
|
|
424
|
+
};
|
|
425
|
+
}
|
|
426
|
+
};
|
package/store/prefs.js
CHANGED
|
@@ -57,12 +57,10 @@ export const PINNED_CLUSTERS = create('pinned-clusters', [], { parseJSON });
|
|
|
57
57
|
export const GROUP_RESOURCES = create('group-by', 'namespace');
|
|
58
58
|
export const DIFF = create('diff', 'unified', { options: ['unified', 'split'] });
|
|
59
59
|
export const THEME = create('theme', 'auto', {
|
|
60
|
-
// options: ['light', 'auto', 'dark'],
|
|
61
60
|
options: ['light'],
|
|
62
61
|
asCookie,
|
|
63
62
|
parseJSON,
|
|
64
63
|
mangleRead: (x) => x.replace(/^ui-/, ''),
|
|
65
|
-
// mangleWrite: (x) => `ui-${ x }`,
|
|
66
64
|
mangleWrite: (x) => `ui-light`, // 接口同时修改为 白色
|
|
67
65
|
});
|
|
68
66
|
export const PREFERS_SCHEME = create('pcs', '', { asCookie, asUserPreference: false });
|
|
@@ -76,7 +74,6 @@ export const HIDE_REPOS = create('hide-repos', [], { parseJSON });
|
|
|
76
74
|
export const HIDE_DESC = create('hide-desc', [], { parseJSON });
|
|
77
75
|
export const HIDE_SENSITIVE = create('hide-sensitive', true, { options: [true, false], parseJSON });
|
|
78
76
|
export const SHOW_PRE_RELEASE = create('show-pre-release', false, { options: [false, true], parseJSON });
|
|
79
|
-
export const SHOW_CHART_MODE = create('chart-mode', 'featured', { parseJSON });
|
|
80
77
|
|
|
81
78
|
export const DATE_FORMAT = create('date-format', 'ddd, MMM D YYYY', {
|
|
82
79
|
options: [
|
|
@@ -105,10 +102,7 @@ export const THEME_SHORTCUT = create('theme-shortcut', false, { parseJSON, inher
|
|
|
105
102
|
export const LAST_VISITED = create('last-visited', 'home', { parseJSON });
|
|
106
103
|
export const SEEN_WHATS_NEW = create('seen-whatsnew', '', { parseJSON });
|
|
107
104
|
export const READ_WHATS_NEW = create('read-whatsnew', '', { parseJSON });
|
|
108
|
-
export const AFTER_LOGIN_ROUTE = create('after-login-route', 'home', {
|
|
109
|
-
parseJSON,
|
|
110
|
-
// mangleWrite: (x) => `ui-light`, // 接口同时修改为 白色
|
|
111
|
-
} );
|
|
105
|
+
export const AFTER_LOGIN_ROUTE = create('after-login-route', 'home', { parseJSON } );
|
|
112
106
|
export const HIDE_HOME_PAGE_CARDS = create('home-page-cards', {}, { parseJSON } );
|
|
113
107
|
export const PLUGIN_DEVELOPER = create('plugin-developer', false, { parseJSON, inheritFrom: DEV }); // Is the user a plugin developer?
|
|
114
108
|
|
|
@@ -154,7 +148,7 @@ export const getters = {
|
|
|
154
148
|
}
|
|
155
149
|
|
|
156
150
|
const def = clone(definition.def);
|
|
157
|
-
|
|
151
|
+
|
|
158
152
|
if (key === THEME) {
|
|
159
153
|
// 无论 state 里存的是什么,都强制返回 light
|
|
160
154
|
return 'light';
|
package/store/slideInPanel.ts
CHANGED
|
@@ -3,18 +3,21 @@ import { MutationTree, GetterTree, ActionTree } from 'vuex';
|
|
|
3
3
|
|
|
4
4
|
export interface SlideInPanelState {
|
|
5
5
|
isOpen: boolean;
|
|
6
|
+
isClosing: boolean;
|
|
6
7
|
component: Component | null;
|
|
7
8
|
componentProps: Record<string, any>;
|
|
8
9
|
}
|
|
9
10
|
|
|
10
11
|
const state = (): SlideInPanelState => ({
|
|
11
12
|
isOpen: false,
|
|
13
|
+
isClosing: false,
|
|
12
14
|
component: null,
|
|
13
15
|
componentProps: {}
|
|
14
16
|
});
|
|
15
17
|
|
|
16
18
|
const getters: GetterTree<SlideInPanelState, any> = {
|
|
17
19
|
isOpen: (state) => state.isOpen,
|
|
20
|
+
isClosing: (state) => state.isClosing,
|
|
18
21
|
component: (state) => state.component,
|
|
19
22
|
componentProps: (state) => state.componentProps
|
|
20
23
|
};
|
|
@@ -26,12 +29,15 @@ const mutations: MutationTree<SlideInPanelState> = {
|
|
|
26
29
|
state.componentProps = payload.componentProps || {};
|
|
27
30
|
},
|
|
28
31
|
close(state) {
|
|
32
|
+
state.isClosing = true;
|
|
29
33
|
state.isOpen = false;
|
|
30
34
|
|
|
31
35
|
// Delay clearing component/props for 500ms (same as transition duration)
|
|
32
36
|
setTimeout(() => {
|
|
33
37
|
state.component = null;
|
|
34
38
|
state.componentProps = {};
|
|
39
|
+
|
|
40
|
+
state.isClosing = false;
|
|
35
41
|
}, 500);
|
|
36
42
|
}
|
|
37
43
|
};
|
package/store/type-map.js
CHANGED
|
@@ -154,7 +154,6 @@ import { haveV2Monitoring } from '@shell/utils/monitoring';
|
|
|
154
154
|
import { NEU_VECTOR_NAMESPACE } from '@shell/config/product/neuvector';
|
|
155
155
|
import { createHeaders, rowValueGetter } from '@shell/store/type-map.utils';
|
|
156
156
|
import { defineAsyncComponent } from 'vue';
|
|
157
|
-
import { cloud2harvesterhci } from '@shell/utils/router';
|
|
158
157
|
|
|
159
158
|
export const NAMESPACED = 'namespaced';
|
|
160
159
|
export const CLUSTER_LEVEL = 'cluster';
|
|
@@ -396,6 +395,7 @@ export function productsLoaded() {
|
|
|
396
395
|
|
|
397
396
|
export const state = function() {
|
|
398
397
|
return {
|
|
398
|
+
actionsWidth: 0,
|
|
399
399
|
products: [],
|
|
400
400
|
virtualTypes: {},
|
|
401
401
|
spoofedTypes: {},
|
|
@@ -465,6 +465,8 @@ export const getters = {
|
|
|
465
465
|
};
|
|
466
466
|
},
|
|
467
467
|
|
|
468
|
+
actionsWidth: (state) => state.actionsWidth,
|
|
469
|
+
|
|
468
470
|
// Turns a group name into a display label (e.g. management.cattle.io.v3.cluster -> Cluster)
|
|
469
471
|
groupLabelFor(state) {
|
|
470
472
|
return (schemaOrName) => {
|
|
@@ -519,20 +521,22 @@ export const getters = {
|
|
|
519
521
|
|
|
520
522
|
optionsFor(state, getters, rootState, rootGetters) {
|
|
521
523
|
const def = {
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
524
|
+
listCreateButtonLabelKey: undefined,
|
|
525
|
+
isCreatable: true,
|
|
526
|
+
isEditable: true,
|
|
527
|
+
isRemovable: true,
|
|
528
|
+
showState: true,
|
|
529
|
+
showAge: true,
|
|
530
|
+
canYaml: true,
|
|
531
|
+
namespaced: null,
|
|
532
|
+
listGroups: [],
|
|
533
|
+
listGroupsWillOverride: false,
|
|
534
|
+
listMandatorySort: null,
|
|
535
|
+
depaginate: false,
|
|
536
|
+
customRoute: undefined,
|
|
537
|
+
resourceEditMasthead: true,
|
|
538
|
+
custom: {},
|
|
539
|
+
subTypes: [],
|
|
536
540
|
};
|
|
537
541
|
|
|
538
542
|
return (schemaOrType, pagination) => {
|
|
@@ -677,7 +681,14 @@ export const getters = {
|
|
|
677
681
|
}
|
|
678
682
|
}
|
|
679
683
|
|
|
680
|
-
|
|
684
|
+
let labelDisplay = highlightLabel(label, icon, count, typeObj.schema);
|
|
685
|
+
|
|
686
|
+
// If we did not match on just the label, add the schema name and see if that matches
|
|
687
|
+
if (!labelDisplay && typeObj.schema?.attributes) {
|
|
688
|
+
const schemaName = `${ typeObj.schema.attributes.resource }.${ typeObj.schema.attributes.group }`;
|
|
689
|
+
|
|
690
|
+
labelDisplay = highlightLabel(`${ label } (${ schemaName })`, count, typeObj.schema);
|
|
691
|
+
}
|
|
681
692
|
|
|
682
693
|
if ( !labelDisplay ) {
|
|
683
694
|
// Search happens in highlight and returns null if not found
|
|
@@ -764,11 +775,13 @@ export const getters = {
|
|
|
764
775
|
let group = findBy(tree.children, 'name', name);
|
|
765
776
|
|
|
766
777
|
if ( !group ) {
|
|
778
|
+
const groupDefaultTypeFor = getters.groupDefaultTypeFor(name);
|
|
779
|
+
|
|
767
780
|
group = {
|
|
768
781
|
name,
|
|
769
782
|
label,
|
|
770
783
|
weight: getters.groupWeightFor(name, forBasic),
|
|
771
|
-
defaultType:
|
|
784
|
+
defaultType: typeof groupDefaultTypeFor === 'function' ? groupDefaultTypeFor() : groupDefaultTypeFor,
|
|
772
785
|
};
|
|
773
786
|
|
|
774
787
|
tree.children.push(group);
|
|
@@ -1484,6 +1497,10 @@ export const getters = {
|
|
|
1484
1497
|
};
|
|
1485
1498
|
|
|
1486
1499
|
export const mutations = {
|
|
1500
|
+
setActionsWidth(state, width) {
|
|
1501
|
+
state.actionsWidth = width
|
|
1502
|
+
},
|
|
1503
|
+
|
|
1487
1504
|
schemaChanged(state) {
|
|
1488
1505
|
state.schemaGeneration = state.schemaGeneration + 1;
|
|
1489
1506
|
},
|
package/store/type-map.utils.ts
CHANGED
|
@@ -62,12 +62,12 @@ export function createHeaders(
|
|
|
62
62
|
} = columns;
|
|
63
63
|
const { rootGetters } = ctx;
|
|
64
64
|
const out = typeOptions.showState ? [stateColumn] : [];
|
|
65
|
-
const attributes = (schema
|
|
66
|
-
const columnsFromSchema = attributes
|
|
65
|
+
const attributes = (schema?.attributes as SchemaAttribute) || {};
|
|
66
|
+
const columnsFromSchema = attributes?.columns || [];
|
|
67
67
|
|
|
68
68
|
// A specific list has been provided
|
|
69
|
-
if ( headers?.[schema
|
|
70
|
-
return headers[schema
|
|
69
|
+
if ( headers?.[schema?.id]?.length ) {
|
|
70
|
+
return headers[schema?.id].map((entry: any) => {
|
|
71
71
|
if ( typeof entry === 'string' ) {
|
|
72
72
|
const col = findBy(columnsFromSchema, 'name', entry);
|
|
73
73
|
|
|
@@ -100,7 +100,7 @@ export function createHeaders(
|
|
|
100
100
|
|
|
101
101
|
// Always try to have an identifier
|
|
102
102
|
if ( !hasName ) {
|
|
103
|
-
insertAt(out, 1,
|
|
103
|
+
insertAt(out, 1, nameColumn || idColumn );
|
|
104
104
|
if ( namespaced ) {
|
|
105
105
|
insertAt(out, 2, namespaceColumn);
|
|
106
106
|
}
|
|
@@ -181,6 +181,49 @@ export function headerFromSchemaCol(col: SchemaAttributeColumn, rootGetters: Vue
|
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
/**
|
|
185
|
+
* Rewrite a JSON Path expression, so that it is compatible with the library we use.
|
|
186
|
+
* Specifically, ensure we can handle path keys that contain an escaped '.' character (\.)
|
|
187
|
+
*
|
|
188
|
+
* For example, this function re-writes the expression:
|
|
189
|
+
* $.metadata.labels.topology\.kubernetes\.io/zone
|
|
190
|
+
* to:
|
|
191
|
+
* $.metadata.labels.["topology.kubernetes.io/zone"]
|
|
192
|
+
*
|
|
193
|
+
* @param path JSON Path expression
|
|
194
|
+
* @returns Re-written JSON Path expression
|
|
195
|
+
*/
|
|
196
|
+
function rewriteJsonPath(path: any): any {
|
|
197
|
+
// Check if we should re-write, otherwise just return the input expression as is
|
|
198
|
+
if (typeof path === 'string' && path.startsWith('$') && path.includes('\\.')) {
|
|
199
|
+
const parts = path.split('.');
|
|
200
|
+
let inField = false;
|
|
201
|
+
let res = '';
|
|
202
|
+
|
|
203
|
+
parts.forEach((part) => {
|
|
204
|
+
let prefix = res.length ? '.' : '';
|
|
205
|
+
|
|
206
|
+
if (part.endsWith('\\')) {
|
|
207
|
+
if (!inField) {
|
|
208
|
+
inField = true;
|
|
209
|
+
prefix = `${ prefix }["`;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
res = `${ res }${ prefix }${ part.substr(0, part.length - 1) }`;
|
|
213
|
+
} else {
|
|
214
|
+
const postfix = inField ? '"]' : '';
|
|
215
|
+
|
|
216
|
+
res += `${ prefix }${ part }${ postfix }`;
|
|
217
|
+
inField = false;
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
return res;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return path;
|
|
225
|
+
}
|
|
226
|
+
|
|
184
227
|
export function rowValueGetter(col: SchemaAttributeColumn, asFn = true): string | ((row: any) => string) {
|
|
185
228
|
// 'field' comes from the schema - typically it is of the form $.metadata.field[N]
|
|
186
229
|
// We will use JsonPath to look up this value, which is costly - so if we can detect this format
|
|
@@ -198,7 +241,7 @@ export function rowValueGetter(col: SchemaAttributeColumn, asFn = true): string
|
|
|
198
241
|
return `metadata.fields.${ fieldIndex }`;
|
|
199
242
|
}
|
|
200
243
|
|
|
201
|
-
return value;
|
|
244
|
+
return rewriteJsonPath(value);
|
|
202
245
|
}
|
|
203
246
|
|
|
204
247
|
type conditionalDepaginateArgs ={
|