@rancher/shell 3.0.8-rc.1 → 3.0.8-rc.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/brand/suse/banner.svg +1 -0
- package/assets/brand/suse/dark/banner.svg +1 -0
- package/assets/brand/suse/dark/login-landscape.svg +1 -0
- package/assets/brand/suse/dark/rancher-logo.svg +1 -1
- package/assets/brand/suse/favicon.png +0 -0
- package/assets/brand/suse/login-landscape.svg +1 -0
- package/assets/brand/suse/metadata.json +11 -1
- package/assets/brand/suse/rancher-logo.svg +1 -1
- package/assets/fonts/suse/suse-v2-latin-300.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-300.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-600.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-600.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-700.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-700.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-800.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-800.woff2 +0 -0
- package/assets/fonts/suse/suse-v2-latin-regular.woff +0 -0
- package/assets/fonts/suse/suse-v2-latin-regular.woff2 +0 -0
- package/assets/images/content/README.md +5 -0
- package/assets/images/content/cloud-native.svg +84 -0
- package/assets/images/content/dark/cloud-native.svg +21 -0
- package/assets/images/content/dark/shield.svg +59 -0
- package/assets/images/content/dark/suse.svg +10 -0
- package/assets/images/content/shield.svg +59 -0
- package/assets/images/content/suse.svg +10 -0
- package/assets/styles/base/_typography.scss +1 -0
- package/assets/styles/fonts/_fontstack.scss +53 -1
- package/assets/styles/global/_cards.scss +0 -3
- package/assets/styles/global/_layout.scss +21 -35
- package/assets/styles/themes/_dark.scss +1 -1
- package/assets/styles/themes/_light.scss +1 -1
- package/assets/styles/themes/_modern.scss +11 -3
- package/assets/styles/themes/_suse.scss +116 -24
- package/assets/translations/en-us.yaml +94 -10
- package/components/AutoscalerCard.vue +113 -0
- package/components/AutoscalerTab.vue +94 -0
- package/components/BackLink.vue +8 -0
- package/components/BannerGraphic.vue +36 -21
- package/components/BrandImage.vue +17 -6
- package/components/ClusterIconMenu.vue +1 -1
- package/components/ClusterProviderIcon.vue +1 -1
- package/components/Cron/CronExpressionEditor.vue +1 -1
- package/components/Cron/CronExpressionEditorModal.vue +1 -1
- package/components/Drawer/Chrome.vue +2 -6
- package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +4 -9
- package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +3 -8
- package/components/Drawer/ResourceDetailDrawer/composables.ts +3 -4
- package/components/Drawer/ResourceDetailDrawer/index.vue +4 -9
- package/components/Drawer/ResourceDetailDrawer/types.ts +17 -0
- package/components/Drawer/types.ts +3 -0
- package/components/DynamicContent/DynamicContentBanner.vue +102 -0
- package/components/DynamicContent/DynamicContentCloseButton.vue +42 -0
- package/components/DynamicContent/DynamicContentIcon.vue +132 -0
- package/components/DynamicContent/DynamicContentPanel.vue +112 -0
- package/components/DynamicContent/content.ts +78 -0
- package/components/EmberPage.vue +1 -1
- package/components/IconOrSvg.vue +2 -2
- package/components/PaginatedResourceTable.vue +2 -6
- package/components/PopoverCard.vue +192 -0
- package/components/Questions/__tests__/index.test.ts +159 -0
- package/components/Resource/Detail/CopyToClipboard.vue +4 -1
- package/components/Resource/Detail/FetchLoader/composables.ts +18 -4
- package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
- package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +1 -1
- package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +4 -0
- package/components/Resource/Detail/Metadata/KeyValueRow.vue +1 -1
- package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
- package/components/Resource/Detail/Metadata/composables.ts +9 -9
- package/components/Resource/Detail/Metadata/index.vue +3 -3
- package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +2 -19
- package/components/Resource/Detail/ResourcePopover/__tests__/ResourcePopoverCard.test.ts +0 -29
- package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +132 -150
- package/components/Resource/Detail/ResourcePopover/index.vue +54 -159
- package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +0 -2
- package/components/Resource/Detail/TitleBar/composables.ts +2 -1
- package/components/Resource/Detail/TitleBar/index.vue +10 -6
- package/components/Resource/Detail/composables.ts +12 -0
- package/components/ResourceDetail/Masthead/latest.vue +29 -0
- package/components/ResourceDetail/index.vue +4 -1
- package/components/ResourceList/Masthead.vue +1 -1
- package/components/SortableTable/index.vue +1 -0
- package/components/Tabbed/__tests__/index.test.ts +86 -0
- package/components/{nav/WindowManager → Window}/ContainerLogs.vue +1 -1
- package/components/{nav/WindowManager → Window}/ContainerLogsActions.vue +1 -0
- package/components/{nav/WindowManager → Window}/__tests__/ContainerLogs.test.ts +1 -1
- package/components/{nav/WindowManager → Window}/__tests__/ContainerShell.test.ts +2 -2
- package/components/__tests__/AutoscalerCard.test.ts +154 -0
- package/components/__tests__/AutoscalerTab.test.ts +125 -0
- package/components/__tests__/PopoverCard.test.ts +204 -0
- package/components/auth/SelectPrincipal.vue +24 -6
- package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
- package/components/formatter/Autoscaler.vue +97 -0
- package/components/formatter/InternalExternalIP.vue +198 -24
- package/components/formatter/__tests__/Autoscaler.test.ts +156 -0
- package/components/formatter/__tests__/InternalExternalIP.test.ts +133 -0
- package/components/google/util/__tests__/formatter.test.ts +47 -0
- package/components/google/util/formatter.ts +5 -2
- package/components/nav/Group.vue +12 -3
- package/components/nav/Header.vue +36 -16
- package/components/nav/NamespaceFilter.vue +13 -1
- package/components/nav/NotificationCenter/index.vue +2 -1
- package/components/nav/TopLevelMenu.helper.ts +16 -6
- package/components/nav/TopLevelMenu.vue +4 -2
- package/components/{DraggableZone.vue → nav/WindowManager/PinArea.vue} +47 -80
- package/components/nav/WindowManager/composables/useComponentsMount.ts +70 -0
- package/components/nav/WindowManager/composables/useDimensionsHandler.ts +105 -0
- package/components/nav/WindowManager/composables/useDragHandler.ts +99 -0
- package/components/nav/WindowManager/composables/usePanelHandler.ts +72 -0
- package/components/nav/WindowManager/composables/usePanelsHandler.ts +14 -0
- package/components/nav/WindowManager/composables/useResizeHandler.ts +167 -0
- package/components/nav/WindowManager/composables/useTabsHandler.ts +51 -0
- package/components/nav/WindowManager/constants.ts +23 -0
- package/components/nav/WindowManager/index.vue +61 -575
- package/components/nav/WindowManager/panels/HorizontalPanel.vue +265 -0
- package/components/nav/WindowManager/panels/TabBodyContainer.vue +39 -0
- package/components/nav/WindowManager/panels/VerticalPanel.vue +308 -0
- package/components/templates/default.vue +4 -40
- package/components/templates/home.vue +31 -5
- package/components/templates/plain.vue +30 -4
- package/components/templates/standalone.vue +1 -1
- package/composables/useI18n.ts +10 -1
- package/composables/useInterval.ts +15 -0
- package/config/__test__/uiplugins.test.ts +309 -0
- package/config/labels-annotations.js +9 -1
- package/config/product/explorer.js +3 -1
- package/config/product/manager.js +20 -9
- package/config/router/routes.js +10 -2
- package/config/settings.ts +2 -1
- package/config/store.js +4 -2
- package/config/table-headers.js +8 -0
- package/config/types.js +9 -0
- package/config/uiplugins.js +46 -2
- package/config/version.js +1 -1
- package/core/__test__/extension-manager-impl.test.js +236 -0
- package/core/extension-manager-impl.js +23 -6
- package/core/plugin-helpers.ts +2 -0
- package/core/types-provisioning.ts +4 -1
- package/detail/pod.vue +1 -0
- package/detail/provisioning.cattle.io.cluster.vue +13 -1
- package/dialog/DeveloperLoadExtensionDialog.vue +12 -3
- package/dialog/RollbackWorkloadDialog.vue +2 -5
- package/directives/ui-context.ts +103 -0
- package/edit/__tests__/fleet.cattle.io.helmop.test.ts +2 -2
- package/edit/auth/__tests__/oidc.test.ts +26 -0
- package/edit/auth/github.vue +5 -0
- package/edit/auth/oidc.vue +5 -1
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
- package/edit/cloudcredential.vue +1 -1
- package/edit/configmap.vue +1 -0
- package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
- package/edit/fleet.cattle.io.gitrepo.vue +0 -10
- package/edit/fleet.cattle.io.helmop.vue +6 -6
- 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 +1 -1
- package/edit/management.cattle.io.project.vue +1 -0
- package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
- package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
- package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
- package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
- package/edit/monitoring.coreos.com.route.vue +1 -1
- package/edit/namespace.vue +1 -0
- package/edit/networking.istio.io.destinationrule/index.vue +1 -0
- package/edit/networking.k8s.io.ingress/index.vue +1 -0
- package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
- package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
- package/edit/node.vue +1 -0
- package/edit/persistentvolume/index.vue +27 -22
- package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
- package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
- package/edit/persistentvolume/plugins/azureFile.vue +15 -14
- package/edit/persistentvolume/plugins/cephfs.vue +15 -14
- package/edit/persistentvolume/plugins/cinder.vue +15 -14
- package/edit/persistentvolume/plugins/csi.vue +18 -16
- package/edit/persistentvolume/plugins/fc.vue +13 -14
- package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
- package/edit/persistentvolume/plugins/flocker.vue +1 -3
- package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
- package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
- package/edit/persistentvolume/plugins/hostPath.vue +40 -39
- package/edit/persistentvolume/plugins/iscsi.vue +13 -14
- package/edit/persistentvolume/plugins/local.vue +1 -3
- package/edit/persistentvolume/plugins/longhorn.vue +23 -22
- package/edit/persistentvolume/plugins/nfs.vue +15 -14
- package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
- package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
- package/edit/persistentvolume/plugins/quobyte.vue +15 -14
- package/edit/persistentvolume/plugins/rbd.vue +15 -14
- package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
- package/edit/persistentvolume/plugins/storageos.vue +15 -14
- package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
- package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +32 -5
- package/edit/provisioning.cattle.io.cluster/__tests__/CustomCommand.test.ts +35 -0
- package/edit/provisioning.cattle.io.cluster/__tests__/Networking.test.ts +155 -0
- package/edit/provisioning.cattle.io.cluster/index.vue +25 -15
- package/edit/provisioning.cattle.io.cluster/rke2.vue +42 -8
- package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +107 -5
- package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +92 -4
- package/edit/secret/index.vue +1 -1
- package/edit/service.vue +9 -4
- package/edit/serviceaccount.vue +1 -0
- package/edit/storage.k8s.io.storageclass/index.vue +1 -0
- package/edit/workload/index.vue +2 -1
- package/edit/workload/mixins/workload.js +1 -1
- package/initialize/App.vue +4 -4
- package/initialize/install-directives.js +2 -0
- package/initialize/install-plugins.js +19 -2
- package/list/provisioning.cattle.io.cluster.vue +15 -2
- package/machine-config/amazonec2.vue +42 -135
- package/machine-config/components/EC2Networking.vue +490 -0
- package/machine-config/components/__tests__/EC2Networking.test.ts +148 -0
- package/machine-config/components/__tests__/utils/vpcSubnetMockData.js +294 -0
- package/machine-config/digitalocean.vue +11 -0
- package/machine-config/google.vue +1 -1
- package/mixins/__tests__/brand.spec.ts +2 -2
- package/mixins/__tests__/chart.test.ts +21 -0
- package/mixins/brand.js +1 -7
- package/mixins/chart.js +7 -1
- package/mixins/create-edit-view/index.js +5 -0
- package/models/__tests__/chart.test.ts +33 -4
- package/models/__tests__/provisioning.cattle.io.cluster.test.ts +112 -5
- package/models/chart.js +25 -13
- package/models/cluster/node.js +13 -6
- package/models/cluster.x-k8s.io.machine.js +10 -20
- package/models/cluster.x-k8s.io.machinedeployment.js +5 -1
- package/models/management.cattle.io.cluster.js +21 -3
- package/models/management.cattle.io.kontainerdriver.js +1 -0
- package/models/provisioning.cattle.io.cluster.js +249 -33
- package/package.json +6 -5
- package/pages/auth/login.vue +38 -2
- package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
- package/pages/c/_cluster/apps/charts/chart.vue +33 -15
- package/pages/c/_cluster/apps/charts/index.vue +11 -13
- package/pages/c/_cluster/apps/charts/install.vue +1 -1
- package/pages/c/_cluster/explorer/index.vue +8 -6
- package/pages/c/_cluster/manager/hostedprovider/index.vue +220 -0
- package/pages/c/_cluster/settings/brand.vue +1 -1
- package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
- package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
- package/pages/c/_cluster/uiplugins/index.vue +126 -184
- package/pages/home.vue +14 -4
- package/pkg/dynamic-importer.lib.js +4 -0
- package/plugins/dashboard-client-init.js +3 -0
- package/plugins/dashboard-store/getters.js +18 -1
- package/plugins/dashboard-store/resource-class.js +4 -4
- package/plugins/dynamic-content.js +13 -0
- package/plugins/i18n.js +8 -0
- package/plugins/steve/__tests__/steve-pagination-utils.test.ts +333 -0
- package/plugins/steve/steve-pagination-utils.ts +39 -20
- package/plugins/steve/subscribe.js +17 -9
- package/plugins/subscribe-events.ts +4 -2
- package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
- package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -34
- package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
- package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
- package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
- package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
- package/rancher-components/Pill/types.ts +0 -1
- package/rancher-components/RcDropdown/RcDropdownItem.vue +1 -0
- package/rancher-components/RcDropdown/RcDropdownItemSelect.vue +5 -1
- package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
- package/rancher-components/RcIcon/RcIcon.vue +46 -0
- package/rancher-components/RcIcon/index.ts +1 -0
- package/rancher-components/RcIcon/types.ts +160 -0
- package/rancher-components/utils/status.test.ts +67 -0
- package/rancher-components/utils/status.ts +77 -0
- package/scripts/typegen.sh +1 -0
- package/store/action-menu.js +8 -0
- package/store/auth.js +3 -3
- package/store/catalog.js +6 -0
- package/store/features.js +1 -0
- package/store/index.js +36 -17
- package/store/notifications.ts +51 -4
- package/store/plugins.js +7 -3
- package/store/prefs.js +6 -6
- package/store/type-map.js +3 -3
- package/store/ui-context.ts +86 -0
- package/store/wm.ts +244 -0
- package/types/notifications/index.ts +27 -3
- package/types/shell/index.d.ts +79 -4
- package/types/store/__tests__/pagination.types.spec.ts +137 -0
- package/types/store/pagination.types.ts +157 -9
- package/types/store/subscribe-events.types.ts +8 -1
- package/types/store/subscribe.types.ts +1 -0
- package/types/window-manager.ts +24 -0
- package/utils/__tests__/object.test.ts +19 -0
- package/utils/__tests__/provider.test.ts +98 -0
- package/utils/__tests__/selector-typed.test.ts +263 -0
- package/utils/__tests__/version.test.ts +19 -1
- package/utils/autoscaler-utils.ts +7 -0
- package/utils/back-off.ts +3 -3
- package/utils/brand.ts +29 -0
- package/utils/chart.js +18 -0
- package/utils/color.js +1 -1
- package/utils/dynamic-content/__tests__/announcement.test.ts +498 -0
- package/utils/dynamic-content/__tests__/info.test.ts +21 -9
- package/utils/dynamic-content/announcement.ts +142 -0
- package/utils/dynamic-content/example.json +40 -0
- package/utils/dynamic-content/index.ts +6 -2
- package/utils/dynamic-content/info.ts +44 -2
- package/utils/dynamic-content/new-release.ts +1 -1
- package/utils/dynamic-content/notification-handler.ts +48 -0
- package/utils/dynamic-content/types.d.ts +53 -1
- package/utils/dynamic-importer.js +2 -2
- package/utils/favicon.js +4 -4
- package/utils/object.js +20 -2
- package/utils/pagination-wrapper.ts +12 -8
- package/utils/provider.ts +14 -0
- package/utils/scroll.js +7 -0
- package/utils/selector-typed.ts +6 -2
- package/utils/settings.ts +15 -0
- package/utils/validators/machine-pool.ts +13 -3
- package/utils/version.js +15 -0
- package/assets/images/icons/document.svg +0 -3
- package/plugins/nuxt-client-init.js +0 -3
- package/store/wm.js +0 -95
- /package/components/{nav/WindowManager → Window}/ChartReadme.vue +0 -0
- /package/components/{nav/WindowManager → Window}/ContainerShell.vue +0 -0
- /package/components/{nav/WindowManager → Window}/KubectlShell.vue +0 -0
- /package/components/{nav/WindowManager → Window}/MachineSsh.vue +0 -0
- /package/components/{nav/WindowManager → Window}/Window.vue +0 -0
package/pages/auth/login.vue
CHANGED
|
@@ -32,6 +32,7 @@ import loadPlugins from '@shell/plugins/plugin';
|
|
|
32
32
|
import Loading from '@shell/components/Loading';
|
|
33
33
|
import { HARVESTER_NAME as HARVESTER } from '@shell/config/features';
|
|
34
34
|
import TabTitle from '@shell/components/TabTitle.vue';
|
|
35
|
+
import { getBrandMeta } from '@shell/utils/brand';
|
|
35
36
|
|
|
36
37
|
export default {
|
|
37
38
|
name: 'Login',
|
|
@@ -134,6 +135,25 @@ export default {
|
|
|
134
135
|
hasLoginMessage() {
|
|
135
136
|
return this.errorToDisplay || this.loggedOut || this.timedOut;
|
|
136
137
|
},
|
|
138
|
+
|
|
139
|
+
customizations() {
|
|
140
|
+
const brandMeta = getBrandMeta(this.$store.getters['management/brand']);
|
|
141
|
+
const login = brandMeta?.login || {};
|
|
142
|
+
|
|
143
|
+
return {
|
|
144
|
+
welcomeLabelKey: 'login.welcome',
|
|
145
|
+
logoClass: 'login-logo',
|
|
146
|
+
...login,
|
|
147
|
+
};
|
|
148
|
+
},
|
|
149
|
+
|
|
150
|
+
bannerClass() {
|
|
151
|
+
return this.customizations.bannerClass;
|
|
152
|
+
},
|
|
153
|
+
|
|
154
|
+
brandLogo() {
|
|
155
|
+
return this.customizations.logo;
|
|
156
|
+
}
|
|
137
157
|
},
|
|
138
158
|
|
|
139
159
|
async fetch() {
|
|
@@ -335,11 +355,20 @@ export default {
|
|
|
335
355
|
</TabTitle>
|
|
336
356
|
<div class="row gutless mb-20">
|
|
337
357
|
<div class="col span-6 p-20">
|
|
338
|
-
<p
|
|
358
|
+
<p
|
|
359
|
+
v-if="!brandLogo"
|
|
360
|
+
class="text-center"
|
|
361
|
+
>
|
|
339
362
|
{{ t('login.howdy') }}
|
|
340
363
|
</p>
|
|
364
|
+
<BrandImage
|
|
365
|
+
v-else
|
|
366
|
+
:class="{[customizations.logoClass]: !!customizations.logoClass}"
|
|
367
|
+
:file-name="brandLogo"
|
|
368
|
+
:alt="t('login.landscapeAlt')"
|
|
369
|
+
/>
|
|
341
370
|
<h1 class="text-center login-welcome">
|
|
342
|
-
{{ t(
|
|
371
|
+
{{ t(customizations.welcomeLabelKey, {vendor}) }}
|
|
343
372
|
</h1>
|
|
344
373
|
<div
|
|
345
374
|
class="login-messages"
|
|
@@ -524,6 +553,7 @@ export default {
|
|
|
524
553
|
</div>
|
|
525
554
|
</div>
|
|
526
555
|
<BrandImage
|
|
556
|
+
:class="bannerClass"
|
|
527
557
|
class="col span-6 landscape"
|
|
528
558
|
data-testid="login-landscape__img"
|
|
529
559
|
file-name="login-landscape.svg"
|
|
@@ -552,6 +582,12 @@ export default {
|
|
|
552
582
|
margin: 0
|
|
553
583
|
}
|
|
554
584
|
|
|
585
|
+
.login-logo {
|
|
586
|
+
align-self: center;
|
|
587
|
+
max-width: 260px;
|
|
588
|
+
margin-bottom: 20px;
|
|
589
|
+
}
|
|
590
|
+
|
|
555
591
|
.login-messages {
|
|
556
592
|
display: flex;
|
|
557
593
|
justify-content: center;
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
import Chart from '@shell/pages/c/_cluster/apps/charts/chart.vue';
|
|
2
|
+
|
|
3
|
+
jest.mock('clipboard-polyfill', () => ({ writeText: () => {} }));
|
|
4
|
+
|
|
5
|
+
describe('page: Chart Detail', () => {
|
|
6
|
+
describe('computed: maintainers', () => {
|
|
7
|
+
it('should return an empty array if no maintainers are provided', () => {
|
|
8
|
+
const thisContext = {
|
|
9
|
+
version: {},
|
|
10
|
+
versionInfo: null,
|
|
11
|
+
};
|
|
12
|
+
const result = (Chart.computed!.maintainers as () => any[]).call(thisContext);
|
|
13
|
+
|
|
14
|
+
expect(result).toStrictEqual([]);
|
|
15
|
+
});
|
|
16
|
+
|
|
17
|
+
it('should return an empty array for empty maintainers arrays', () => {
|
|
18
|
+
const thisContext = {
|
|
19
|
+
version: { maintainers: [] },
|
|
20
|
+
versionInfo: { chart: { maintainers: [] } },
|
|
21
|
+
};
|
|
22
|
+
const result = (Chart.computed!.maintainers as () => any[]).call(thisContext);
|
|
23
|
+
|
|
24
|
+
expect(result).toStrictEqual([]);
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
it('should prioritize maintainers from "version"', () => {
|
|
28
|
+
const thisContext = {
|
|
29
|
+
version: {
|
|
30
|
+
maintainers: [
|
|
31
|
+
{ name: 'Version Maintainer', email: 'version@test.com' }
|
|
32
|
+
]
|
|
33
|
+
},
|
|
34
|
+
versionInfo: {
|
|
35
|
+
chart: {
|
|
36
|
+
maintainers: [
|
|
37
|
+
{ name: 'VersionInfo Maintainer', email: 'versioninfo@test.com' }
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
const result = (Chart.computed!.maintainers as () => any[]).call(thisContext);
|
|
43
|
+
|
|
44
|
+
expect(result).toHaveLength(1);
|
|
45
|
+
expect(result[0].name).toBe('Version Maintainer');
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
it('should fall back to maintainers from "versionInfo"', () => {
|
|
49
|
+
const thisContext = {
|
|
50
|
+
version: {},
|
|
51
|
+
versionInfo: {
|
|
52
|
+
chart: {
|
|
53
|
+
maintainers: [
|
|
54
|
+
{ name: 'VersionInfo Maintainer', email: 'versioninfo@test.com' }
|
|
55
|
+
]
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
const result = (Chart.computed!.maintainers as () => any[]).call(thisContext);
|
|
60
|
+
|
|
61
|
+
expect(result).toHaveLength(1);
|
|
62
|
+
expect(result[0].name).toBe('VersionInfo Maintainer');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('should correctly map all maintainer fields', () => {
|
|
66
|
+
const thisContext = {
|
|
67
|
+
version: {
|
|
68
|
+
maintainers: [
|
|
69
|
+
{
|
|
70
|
+
name: 'Full Maintainer', email: 'full@test.com', url: 'http://full.com'
|
|
71
|
+
}
|
|
72
|
+
]
|
|
73
|
+
},
|
|
74
|
+
versionInfo: null,
|
|
75
|
+
};
|
|
76
|
+
const result = (Chart.computed!.maintainers as () => any[]).call(thisContext);
|
|
77
|
+
const expected = {
|
|
78
|
+
id: 'Full Maintainer-0',
|
|
79
|
+
name: 'Full Maintainer',
|
|
80
|
+
href: 'http://full.com',
|
|
81
|
+
label: 'Full Maintainer'
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
expect(result[0]).toStrictEqual(expected);
|
|
85
|
+
});
|
|
86
|
+
|
|
87
|
+
it('should handle maintainers with missing optional fields', () => {
|
|
88
|
+
const thisContext = {
|
|
89
|
+
version: {
|
|
90
|
+
maintainers: [
|
|
91
|
+
{ name: 'No Email Maintainer', url: 'http://noemail.com' },
|
|
92
|
+
{ name: 'No URL Maintainer', email: 'nourl@test.com' },
|
|
93
|
+
{ name: 'Name Only Maintainer' },
|
|
94
|
+
{ url: 'http://noname.com' },
|
|
95
|
+
{ email: 'noname@test.com' }
|
|
96
|
+
]
|
|
97
|
+
},
|
|
98
|
+
versionInfo: null,
|
|
99
|
+
};
|
|
100
|
+
const result = (Chart.computed!.maintainers as () => any[]).call(thisContext);
|
|
101
|
+
|
|
102
|
+
expect(result).toHaveLength(5);
|
|
103
|
+
expect(result[0]).toStrictEqual({
|
|
104
|
+
id: 'No Email Maintainer-0',
|
|
105
|
+
name: 'No Email Maintainer',
|
|
106
|
+
href: 'http://noemail.com',
|
|
107
|
+
label: 'No Email Maintainer'
|
|
108
|
+
});
|
|
109
|
+
expect(result[1]).toStrictEqual({
|
|
110
|
+
id: 'No URL Maintainer-1',
|
|
111
|
+
name: 'No URL Maintainer',
|
|
112
|
+
href: 'mailto:nourl@test.com',
|
|
113
|
+
label: 'No URL Maintainer'
|
|
114
|
+
});
|
|
115
|
+
expect(result[2]).toStrictEqual({
|
|
116
|
+
id: 'Name Only Maintainer-2',
|
|
117
|
+
name: 'Name Only Maintainer',
|
|
118
|
+
href: null,
|
|
119
|
+
label: 'Name Only Maintainer'
|
|
120
|
+
});
|
|
121
|
+
expect(result[3]).toStrictEqual({
|
|
122
|
+
id: 'undefined-3',
|
|
123
|
+
name: undefined,
|
|
124
|
+
href: 'http://noname.com',
|
|
125
|
+
label: 'http://noname.com'
|
|
126
|
+
});
|
|
127
|
+
expect(result[4]).toStrictEqual({
|
|
128
|
+
id: 'undefined-4',
|
|
129
|
+
name: undefined,
|
|
130
|
+
href: 'mailto:noname@test.com',
|
|
131
|
+
label: 'noname@test.com'
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
});
|
|
135
|
+
});
|
|
@@ -84,11 +84,21 @@ export default {
|
|
|
84
84
|
maintainers() {
|
|
85
85
|
const maintainers = this.version.maintainers || this.versionInfo?.chart?.maintainers || [];
|
|
86
86
|
|
|
87
|
-
return maintainers.map((m) => {
|
|
87
|
+
return maintainers.map((m, i) => {
|
|
88
|
+
const label = m.name || m.url || m.email || this.t('generic.unknown');
|
|
89
|
+
let href = null;
|
|
90
|
+
|
|
91
|
+
if (m.url) {
|
|
92
|
+
href = m.url;
|
|
93
|
+
} else if (m.email) {
|
|
94
|
+
href = `mailto:${ m.email }`;
|
|
95
|
+
}
|
|
96
|
+
|
|
88
97
|
return {
|
|
89
|
-
id: m.name
|
|
90
|
-
|
|
91
|
-
|
|
98
|
+
id: `${ m.name }-${ i }`,
|
|
99
|
+
name: m.name,
|
|
100
|
+
label,
|
|
101
|
+
href
|
|
92
102
|
};
|
|
93
103
|
});
|
|
94
104
|
},
|
|
@@ -456,18 +466,26 @@ export default {
|
|
|
456
466
|
data-testid="chart-home-link"
|
|
457
467
|
>{{ home }}<i class="icon icon-external-link" /><span class="sr-only">{{ t('generic.opensInNewTab') }}</span></a>
|
|
458
468
|
</div>
|
|
459
|
-
<div
|
|
460
|
-
v-if="maintainers.length"
|
|
461
|
-
class="chart-body__info-section"
|
|
462
|
-
>
|
|
469
|
+
<div class="chart-body__info-section">
|
|
463
470
|
<h4>{{ t('catalog.chart.info.maintainers') }}</h4>
|
|
464
|
-
<
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
+
<template v-if="maintainers.length">
|
|
472
|
+
<div
|
|
473
|
+
v-for="m of maintainers"
|
|
474
|
+
:key="m.id"
|
|
475
|
+
>
|
|
476
|
+
<a
|
|
477
|
+
v-if="m.href"
|
|
478
|
+
v-clean-tooltip="m.name ? t('catalog.chart.info.maintainerContactTooltip', { maintainer: m.name }) : undefined"
|
|
479
|
+
:href="m.href"
|
|
480
|
+
rel="nofollow noopener noreferrer"
|
|
481
|
+
target="_blank"
|
|
482
|
+
>
|
|
483
|
+
{{ m.label }}
|
|
484
|
+
</a>
|
|
485
|
+
<span v-else>{{ m.label }}</span>
|
|
486
|
+
</div>
|
|
487
|
+
</template>
|
|
488
|
+
<span v-else>{{ t('generic.unknown') }}</span>
|
|
471
489
|
</div>
|
|
472
490
|
<div
|
|
473
491
|
v-if="version.sources"
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
REPO_TYPE, REPO, CHART, VERSION, SEARCH_QUERY, SORT_BY, _FLAGGED, CATEGORY, DEPRECATED, HIDDEN, TAG, STATUS
|
|
8
8
|
} from '@shell/config/query-params';
|
|
9
9
|
import { DOCS_BASE } from '@shell/config/private-label';
|
|
10
|
-
import { APP_STATUS,
|
|
10
|
+
import { APP_STATUS, filterAndArrangeCharts, normalizeFilterQuery } from '@shell/store/catalog';
|
|
11
11
|
import { lcFirst } from '@shell/utils/string';
|
|
12
12
|
import { sortBy } from '@shell/utils/sort';
|
|
13
13
|
import debounce from 'lodash/debounce';
|
|
@@ -24,6 +24,7 @@ import AppChartCardFooter from '@shell/pages/c/_cluster/apps/charts/AppChartCard
|
|
|
24
24
|
import AddRepoLink from '@shell/pages/c/_cluster/apps/charts/AddRepoLink';
|
|
25
25
|
import StatusLabel from '@shell/pages/c/_cluster/apps/charts/StatusLabel';
|
|
26
26
|
import RichTranslation from '@shell/components/RichTranslation.vue';
|
|
27
|
+
import { getLatestCompatibleVersion } from '@shell/utils/chart';
|
|
27
28
|
import Select from '@shell/components/form/Select';
|
|
28
29
|
|
|
29
30
|
const createInitialFilters = () => ({
|
|
@@ -190,6 +191,13 @@ export default {
|
|
|
190
191
|
sort: this.selectedSortOption
|
|
191
192
|
});
|
|
192
193
|
|
|
194
|
+
const OSs = this.currentCluster.workerOSs;
|
|
195
|
+
const showPrerelease = this.$store.getters['prefs/get'](SHOW_PRE_RELEASE);
|
|
196
|
+
|
|
197
|
+
res.forEach((chart) => {
|
|
198
|
+
chart._latestCompatibleVersion = getLatestCompatibleVersion(chart, OSs, showPrerelease);
|
|
199
|
+
});
|
|
200
|
+
|
|
193
201
|
// status filtering is separated from other filters because "isInstalled" and "upgradeable" statuses are already calculated in models/chart.js
|
|
194
202
|
// by doing this we won't need to re-calculate it in filterAndArrangeCharts
|
|
195
203
|
if (!statuses.length) {
|
|
@@ -265,7 +273,7 @@ export default {
|
|
|
265
273
|
statuses: chart.cardContent.statuses
|
|
266
274
|
},
|
|
267
275
|
subHeaderItems: chart.cardContent.subHeaderItems,
|
|
268
|
-
image: { src: chart.
|
|
276
|
+
image: { src: chart.latestCompatibleVersion.icon, alt: { text: this.t('catalog.charts.iconAlt', { app: get(chart, 'chartNameDisplay') }) } },
|
|
269
277
|
content: { text: chart.chartDescription },
|
|
270
278
|
footerItems: chart.cardContent.footerItems,
|
|
271
279
|
rawChart: chart
|
|
@@ -343,17 +351,7 @@ export default {
|
|
|
343
351
|
}, 100),
|
|
344
352
|
|
|
345
353
|
selectChart(chart) {
|
|
346
|
-
|
|
347
|
-
const OSs = this.currentCluster.workerOSs;
|
|
348
|
-
const showPrerelease = this.$store.getters['prefs/get'](SHOW_PRE_RELEASE);
|
|
349
|
-
const compatibleVersions = compatibleVersionsFor(chart, OSs, showPrerelease);
|
|
350
|
-
const versions = chart.versions;
|
|
351
|
-
|
|
352
|
-
if (compatibleVersions.length > 0) {
|
|
353
|
-
version = compatibleVersions[0].version;
|
|
354
|
-
} else {
|
|
355
|
-
version = versions[0].version;
|
|
356
|
-
}
|
|
354
|
+
const version = chart.latestCompatibleVersion.version;
|
|
357
355
|
|
|
358
356
|
const query = {
|
|
359
357
|
[REPO_TYPE]: chart.repoType,
|
|
@@ -1203,7 +1203,7 @@ export default {
|
|
|
1203
1203
|
const { allValues, values: crdValues } = versionInfo;
|
|
1204
1204
|
|
|
1205
1205
|
// only save crd values that differ from the defaults defined in chart values.yaml
|
|
1206
|
-
const customizedCrdValues = diff(crdValues, allValues);
|
|
1206
|
+
const customizedCrdValues = diff(crdValues, allValues, true);
|
|
1207
1207
|
|
|
1208
1208
|
// CRD globals should be overwritten by main chart globals
|
|
1209
1209
|
// we want to avoid including globals present on crd values and not main chart values
|
|
@@ -222,7 +222,7 @@ export default {
|
|
|
222
222
|
displayProvider() {
|
|
223
223
|
const other = 'other';
|
|
224
224
|
|
|
225
|
-
let provider = this.currentCluster?.status?.provider || other;
|
|
225
|
+
let provider = this.currentCluster?.status?.provider || this.currentCluster?.status?.driver.toLowerCase() || other;
|
|
226
226
|
|
|
227
227
|
if (provider === 'rke.windows') {
|
|
228
228
|
provider = 'rkeWindows';
|
|
@@ -484,6 +484,12 @@ export default {
|
|
|
484
484
|
hasNodes() {
|
|
485
485
|
return this.nodes?.length > 0;
|
|
486
486
|
},
|
|
487
|
+
kubernetesVersion() {
|
|
488
|
+
const base = this.currentCluster?.kubernetesVersionBase || '';
|
|
489
|
+
const extension = this.currentCluster?.kubernetesVersionExtension || '';
|
|
490
|
+
|
|
491
|
+
return `${ base }${ extension }`;
|
|
492
|
+
}
|
|
487
493
|
},
|
|
488
494
|
|
|
489
495
|
methods: {
|
|
@@ -661,11 +667,7 @@ export default {
|
|
|
661
667
|
</div>
|
|
662
668
|
<div data-testid="kubernetesVersion__label">
|
|
663
669
|
<label>{{ t('glance.version') }}: </label>
|
|
664
|
-
<span>{{
|
|
665
|
-
<span
|
|
666
|
-
v-if="currentCluster.kubernetesVersionExtension"
|
|
667
|
-
style="font-size: 0.75em"
|
|
668
|
-
>{{ currentCluster.kubernetesVersionExtension }}</span>
|
|
670
|
+
<span>{{ kubernetesVersion }}</span>
|
|
669
671
|
</div>
|
|
670
672
|
<div
|
|
671
673
|
v-if="hasNodes"
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
<script>
|
|
2
|
+
import { MANAGEMENT, HOSTED_PROVIDER } from '@shell/config/types';
|
|
3
|
+
import { SETTING } from '@shell/config/settings';
|
|
4
|
+
import { STATE, NAME } from '@shell/config/table-headers';
|
|
5
|
+
import ResourceTable from '@shell/components/ResourceTable';
|
|
6
|
+
import Masthead from '@shell/components/ResourceList/Masthead';
|
|
7
|
+
import Banner from '@components/Banner/Banner.vue';
|
|
8
|
+
import RcStatusBadge from '@components/Pill/RcStatusBadge/RcStatusBadge.vue';
|
|
9
|
+
import { exceptionToErrorsArray } from '@shell/utils/error';
|
|
10
|
+
import { isRancherPrime } from '@shell/config/version';
|
|
11
|
+
import { stateDisplay, STATES_ENUM } from '@shell/plugins/dashboard-store/resource-class';
|
|
12
|
+
import { getHostedProviders } from '@shell/utils/provider';
|
|
13
|
+
|
|
14
|
+
export default {
|
|
15
|
+
name: 'HostedProviders',
|
|
16
|
+
components: {
|
|
17
|
+
ResourceTable, Masthead, RcStatusBadge, Banner
|
|
18
|
+
},
|
|
19
|
+
data() {
|
|
20
|
+
return {
|
|
21
|
+
errors: [],
|
|
22
|
+
rows: [],
|
|
23
|
+
allProviders: null,
|
|
24
|
+
resource: HOSTED_PROVIDER,
|
|
25
|
+
schema: this.$store.getters['rancher/schemaFor'](HOSTED_PROVIDER),
|
|
26
|
+
prime: isRancherPrime(),
|
|
27
|
+
settingResource: null
|
|
28
|
+
};
|
|
29
|
+
},
|
|
30
|
+
fetch() {
|
|
31
|
+
this.allProviders = this.getProviders();
|
|
32
|
+
this.getSettings();
|
|
33
|
+
this.generateRows();
|
|
34
|
+
},
|
|
35
|
+
watch: {
|
|
36
|
+
settings() {
|
|
37
|
+
this.generateRows();
|
|
38
|
+
},
|
|
39
|
+
allProviders() {
|
|
40
|
+
this.generateRows();
|
|
41
|
+
}
|
|
42
|
+
},
|
|
43
|
+
computed: {
|
|
44
|
+
headers() {
|
|
45
|
+
return [
|
|
46
|
+
STATE,
|
|
47
|
+
NAME,
|
|
48
|
+
];
|
|
49
|
+
},
|
|
50
|
+
settings() {
|
|
51
|
+
const providerTypesJSON = this.settingResource?.value;
|
|
52
|
+
const providerTypes = providerTypesJSON ? JSON.parse(providerTypesJSON) : [];
|
|
53
|
+
const settingsDict = {};
|
|
54
|
+
|
|
55
|
+
providerTypes.forEach((p) => {
|
|
56
|
+
settingsDict[p.name] = p.active;
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
return settingsDict;
|
|
60
|
+
},
|
|
61
|
+
|
|
62
|
+
},
|
|
63
|
+
methods: {
|
|
64
|
+
getProviders() {
|
|
65
|
+
const context = {
|
|
66
|
+
dispatch: this.$store.dispatch,
|
|
67
|
+
getters: this.$store.getters,
|
|
68
|
+
axios: this.$store.$axios,
|
|
69
|
+
$extension: this.$store.app.$extension,
|
|
70
|
+
t: (...args) => this.t.apply(this, args),
|
|
71
|
+
};
|
|
72
|
+
|
|
73
|
+
return getHostedProviders(context);
|
|
74
|
+
},
|
|
75
|
+
getSettings() {
|
|
76
|
+
this.settingResource = this.$store.getters['management/byId'](MANAGEMENT.SETTING, SETTING.KEV2_OPERATORS );
|
|
77
|
+
},
|
|
78
|
+
stateDisplay(row) {
|
|
79
|
+
if (!row.active) {
|
|
80
|
+
return stateDisplay(STATES_ENUM.INACTIVE);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return stateDisplay(STATES_ENUM.ACTIVE);
|
|
84
|
+
},
|
|
85
|
+
async setSetting(resources, active) {
|
|
86
|
+
try {
|
|
87
|
+
const providerTypes = this.settingResource.value ? JSON.parse(this.settingResource.value) : [];
|
|
88
|
+
const providerMap = new Map(providerTypes.map((prov) => [prov.name, prov]));
|
|
89
|
+
|
|
90
|
+
resources.forEach((resource) => {
|
|
91
|
+
const provider = providerMap.get(resource.id);
|
|
92
|
+
|
|
93
|
+
if (provider) {
|
|
94
|
+
provider.active = active;
|
|
95
|
+
} else {
|
|
96
|
+
providerMap.set(resource.id, { name: resource.id, active });
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
this.settingResource.value = JSON.stringify(Array.from(providerMap.values()));
|
|
101
|
+
await this.settingResource.save();
|
|
102
|
+
this.getSettings();
|
|
103
|
+
} catch (e) {
|
|
104
|
+
this.errors = exceptionToErrorsArray(e);
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
async generateRows() {
|
|
108
|
+
this.rows = this.allProviders.map((p) => {
|
|
109
|
+
const active = p.id in this.settings ? this.settings[p.id] : true;
|
|
110
|
+
const canNotPrime = p.prime && !this.prime;
|
|
111
|
+
const canNotChangeSettings = !this.settingResource?.canUpdate;
|
|
112
|
+
const enableAction = {
|
|
113
|
+
action: 'activate',
|
|
114
|
+
label: this.t('action.activate'),
|
|
115
|
+
icon: 'icon icon-play',
|
|
116
|
+
bulkable: true,
|
|
117
|
+
enabled: !active && !canNotPrime && !canNotChangeSettings,
|
|
118
|
+
invoke: async(opts, resources) => {
|
|
119
|
+
await this.setSetting(resources, true);
|
|
120
|
+
}
|
|
121
|
+
};
|
|
122
|
+
const disableAction = {
|
|
123
|
+
action: 'deactivate',
|
|
124
|
+
label: this.t('action.deactivate'),
|
|
125
|
+
icon: 'icon icon-pause',
|
|
126
|
+
bulkable: true,
|
|
127
|
+
enabled: active && !canNotChangeSettings,
|
|
128
|
+
weight: -1,
|
|
129
|
+
invoke: async(opts, resources) => {
|
|
130
|
+
await this.setSetting(resources, false);
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
const availableActions = [enableAction, disableAction];
|
|
134
|
+
|
|
135
|
+
return {
|
|
136
|
+
id: p.id,
|
|
137
|
+
name: p.label,
|
|
138
|
+
nameDisplay: p.label,
|
|
139
|
+
description: p.description || '',
|
|
140
|
+
prime: p.prime,
|
|
141
|
+
active,
|
|
142
|
+
availableActions
|
|
143
|
+
};
|
|
144
|
+
}) || [];
|
|
145
|
+
},
|
|
146
|
+
closeError(index) {
|
|
147
|
+
this.errors.splice(index, 1);
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
};
|
|
151
|
+
</script>
|
|
152
|
+
|
|
153
|
+
<template>
|
|
154
|
+
<div>
|
|
155
|
+
<Masthead
|
|
156
|
+
:schema="schema"
|
|
157
|
+
:resource="resource"
|
|
158
|
+
:type-display="t('providers.hosted.title')"
|
|
159
|
+
:is-creatable="false"
|
|
160
|
+
/>
|
|
161
|
+
<Banner
|
|
162
|
+
color="warning"
|
|
163
|
+
:label="t('providers.hosted.warning')"
|
|
164
|
+
:closable="false"
|
|
165
|
+
/>
|
|
166
|
+
<Banner
|
|
167
|
+
v-for="(err, i) in errors"
|
|
168
|
+
:key="i"
|
|
169
|
+
color="error"
|
|
170
|
+
:label="err"
|
|
171
|
+
:closable="true"
|
|
172
|
+
@close="closeError(i)"
|
|
173
|
+
/>
|
|
174
|
+
<ResourceTable
|
|
175
|
+
:schema="schema"
|
|
176
|
+
:resource="resource"
|
|
177
|
+
:rows="rows"
|
|
178
|
+
:headers="headers"
|
|
179
|
+
:row-actions="true"
|
|
180
|
+
:table-actions="true"
|
|
181
|
+
:data-testid="'hosted-provider-list'"
|
|
182
|
+
key-field="id"
|
|
183
|
+
>
|
|
184
|
+
<template #cell:state="{row}">
|
|
185
|
+
<RcStatusBadge
|
|
186
|
+
:status="!row.active ? 'error' : 'success'"
|
|
187
|
+
>
|
|
188
|
+
{{ stateDisplay(row) }}
|
|
189
|
+
</RcStatusBadge>
|
|
190
|
+
</template>
|
|
191
|
+
<template #cell:name="{row}">
|
|
192
|
+
<div class="col">
|
|
193
|
+
<div class="row">
|
|
194
|
+
<span class="mr-10">{{ row.name }}</span>
|
|
195
|
+
<RcStatusBadge
|
|
196
|
+
v-if="row.prime"
|
|
197
|
+
class="prime-badge"
|
|
198
|
+
status="success"
|
|
199
|
+
>
|
|
200
|
+
{{ t('providers.hosted.prime') }}
|
|
201
|
+
</RcStatusBadge>
|
|
202
|
+
</div>
|
|
203
|
+
<div
|
|
204
|
+
v-if="row.description"
|
|
205
|
+
class="description text-muted text-small"
|
|
206
|
+
>
|
|
207
|
+
{{ row.description }}
|
|
208
|
+
</div>
|
|
209
|
+
</div>
|
|
210
|
+
</template>
|
|
211
|
+
</ResourceTable>
|
|
212
|
+
</div>
|
|
213
|
+
</template>
|
|
214
|
+
|
|
215
|
+
<style lang="scss" scoped>
|
|
216
|
+
.prime-badge {
|
|
217
|
+
font-size: 10px;
|
|
218
|
+
line-height: 15px;
|
|
219
|
+
}
|
|
220
|
+
</style>
|
|
@@ -18,7 +18,7 @@ import { _EDIT, _VIEW } from '@shell/config/query-params';
|
|
|
18
18
|
import { setFavIcon } from '@shell/utils/favicon';
|
|
19
19
|
import TabTitle from '@shell/components/TabTitle';
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
import Color from 'color';
|
|
22
22
|
|
|
23
23
|
export default {
|
|
24
24
|
components: {
|
|
@@ -164,6 +164,13 @@ describe('page: UI plugins/Extensions', () => {
|
|
|
164
164
|
});
|
|
165
165
|
|
|
166
166
|
describe('getFooterItems', () => {
|
|
167
|
+
it('should return "developer" label for isDeveloper plugins', () => {
|
|
168
|
+
const plugin = { isDeveloper: true };
|
|
169
|
+
const items = wrapper.vm.getFooterItems(plugin);
|
|
170
|
+
|
|
171
|
+
expect(items[0].labels).toContain('plugins.labels.isDeveloper');
|
|
172
|
+
});
|
|
173
|
+
|
|
167
174
|
it('should return "builtin" label for builtin plugins', () => {
|
|
168
175
|
const plugin = { builtin: true };
|
|
169
176
|
const items = wrapper.vm.getFooterItems(plugin);
|