@rancher/shell 3.0.8-rc.8 → 3.0.8-rc.9

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.
Files changed (142) hide show
  1. package/assets/brand/suse/dark/rancher-logo.svg +1 -64
  2. package/assets/translations/en-us.yaml +9 -1
  3. package/components/BackLink.vue +8 -0
  4. package/components/BannerGraphic.vue +1 -5
  5. package/components/BrandImage.vue +17 -6
  6. package/components/Cron/CronExpressionEditor.vue +1 -1
  7. package/components/Cron/CronExpressionEditorModal.vue +1 -1
  8. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +1 -0
  9. package/components/Drawer/ResourceDetailDrawer/index.vue +1 -0
  10. package/components/Drawer/ResourceDetailDrawer/types.ts +2 -1
  11. package/components/Questions/__tests__/index.test.ts +159 -0
  12. package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
  13. package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
  14. package/components/Resource/Detail/Metadata/index.vue +3 -3
  15. package/components/Resource/Detail/composables.ts +2 -2
  16. package/components/Tabbed/__tests__/index.test.ts +86 -0
  17. package/components/auth/SelectPrincipal.vue +24 -6
  18. package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
  19. package/components/formatter/InternalExternalIP.vue +4 -1
  20. package/components/formatter/__tests__/InternalExternalIP.test.ts +1 -1
  21. package/components/templates/standalone.vue +1 -1
  22. package/composables/useI18n.ts +10 -1
  23. package/config/__test__/uiplugins.test.ts +309 -0
  24. package/config/labels-annotations.js +1 -0
  25. package/config/product/explorer.js +3 -1
  26. package/config/router/routes.js +6 -2
  27. package/config/types.js +7 -0
  28. package/config/uiplugins.js +46 -2
  29. package/core/__test__/extension-manager-impl.test.js +236 -0
  30. package/core/extension-manager-impl.js +23 -6
  31. package/core/types-provisioning.ts +1 -1
  32. package/detail/provisioning.cattle.io.cluster.vue +1 -0
  33. package/dialog/DeveloperLoadExtensionDialog.vue +12 -3
  34. package/dialog/RollbackWorkloadDialog.vue +2 -5
  35. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +2 -2
  36. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
  37. package/edit/configmap.vue +1 -0
  38. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  39. package/edit/fleet.cattle.io.helmop.vue +6 -6
  40. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  41. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  42. package/edit/logging-flow/index.vue +1 -0
  43. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  44. package/edit/management.cattle.io.fleetworkspace.vue +1 -1
  45. package/edit/management.cattle.io.project.vue +1 -0
  46. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
  47. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
  48. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  49. package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
  50. package/edit/monitoring.coreos.com.route.vue +1 -1
  51. package/edit/namespace.vue +1 -0
  52. package/edit/networking.istio.io.destinationrule/index.vue +1 -0
  53. package/edit/networking.k8s.io.ingress/index.vue +1 -0
  54. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
  55. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
  56. package/edit/node.vue +1 -0
  57. package/edit/persistentvolume/index.vue +27 -22
  58. package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
  59. package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
  60. package/edit/persistentvolume/plugins/azureFile.vue +15 -14
  61. package/edit/persistentvolume/plugins/cephfs.vue +15 -14
  62. package/edit/persistentvolume/plugins/cinder.vue +15 -14
  63. package/edit/persistentvolume/plugins/csi.vue +18 -16
  64. package/edit/persistentvolume/plugins/fc.vue +13 -14
  65. package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
  66. package/edit/persistentvolume/plugins/flocker.vue +1 -3
  67. package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
  68. package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
  69. package/edit/persistentvolume/plugins/hostPath.vue +40 -39
  70. package/edit/persistentvolume/plugins/iscsi.vue +13 -14
  71. package/edit/persistentvolume/plugins/local.vue +1 -3
  72. package/edit/persistentvolume/plugins/longhorn.vue +23 -22
  73. package/edit/persistentvolume/plugins/nfs.vue +15 -14
  74. package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
  75. package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
  76. package/edit/persistentvolume/plugins/quobyte.vue +15 -14
  77. package/edit/persistentvolume/plugins/rbd.vue +15 -14
  78. package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
  79. package/edit/persistentvolume/plugins/storageos.vue +15 -14
  80. package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
  81. package/edit/provisioning.cattle.io.cluster/rke2.vue +1 -0
  82. package/edit/secret/index.vue +1 -1
  83. package/edit/service.vue +1 -0
  84. package/edit/serviceaccount.vue +1 -0
  85. package/edit/storage.k8s.io.storageclass/index.vue +1 -0
  86. package/edit/workload/index.vue +2 -1
  87. package/edit/workload/mixins/workload.js +1 -1
  88. package/initialize/App.vue +4 -4
  89. package/initialize/install-plugins.js +17 -2
  90. package/mixins/__tests__/brand.spec.ts +2 -2
  91. package/mixins/brand.js +1 -7
  92. package/mixins/create-edit-view/index.js +5 -0
  93. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +112 -5
  94. package/models/management.cattle.io.cluster.js +21 -3
  95. package/models/provisioning.cattle.io.cluster.js +21 -9
  96. package/package.json +5 -4
  97. package/pages/auth/login.vue +1 -3
  98. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
  99. package/pages/c/_cluster/apps/charts/chart.vue +33 -15
  100. package/pages/c/_cluster/explorer/index.vue +8 -6
  101. package/pages/c/_cluster/manager/hostedprovider/index.vue +12 -6
  102. package/pages/c/_cluster/settings/brand.vue +1 -1
  103. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
  104. package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
  105. package/pages/c/_cluster/uiplugins/index.vue +126 -184
  106. package/plugins/dashboard-client-init.js +3 -0
  107. package/plugins/dashboard-store/getters.js +18 -1
  108. package/plugins/dashboard-store/resource-class.js +3 -2
  109. package/plugins/i18n.js +8 -0
  110. package/plugins/steve/__tests__/steve-pagination-utils.test.ts +333 -0
  111. package/plugins/steve/steve-pagination-utils.ts +39 -20
  112. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -42
  113. package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
  114. package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
  115. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
  116. package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
  117. package/rancher-components/Pill/types.ts +0 -1
  118. package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
  119. package/rancher-components/RcIcon/RcIcon.vue +46 -0
  120. package/rancher-components/RcIcon/index.ts +1 -0
  121. package/rancher-components/RcIcon/types.ts +160 -0
  122. package/rancher-components/utils/status.test.ts +67 -0
  123. package/rancher-components/utils/status.ts +77 -0
  124. package/scripts/typegen.sh +1 -0
  125. package/store/action-menu.js +8 -0
  126. package/store/auth.js +3 -3
  127. package/store/catalog.js +6 -0
  128. package/store/index.js +4 -4
  129. package/store/prefs.js +4 -5
  130. package/store/wm.ts +4 -4
  131. package/types/shell/index.d.ts +38 -2
  132. package/types/store/__tests__/pagination.types.spec.ts +137 -0
  133. package/types/store/pagination.types.ts +157 -9
  134. package/utils/__tests__/provider.test.ts +98 -0
  135. package/utils/__tests__/selector-typed.test.ts +263 -0
  136. package/utils/color.js +1 -1
  137. package/utils/dynamic-content/__tests__/info.test.ts +6 -0
  138. package/utils/dynamic-content/info.ts +43 -0
  139. package/utils/favicon.js +4 -4
  140. package/utils/provider.ts +14 -0
  141. package/utils/selector-typed.ts +6 -2
  142. package/plugins/nuxt-client-init.js +0 -3
@@ -0,0 +1,147 @@
1
+
2
+ <script>
3
+ import CatalogList from './CatalogList/index.vue';
4
+
5
+ export default {
6
+ name: 'ExtensionsAirgappedView',
7
+ components: { CatalogList },
8
+ data() {
9
+ return {
10
+ extensionsPageLink: {
11
+ name: 'c-cluster-uiplugins',
12
+ params: { cluster: this.$route.params.cluster }
13
+ },
14
+ reloadRequired: false
15
+ };
16
+ },
17
+ methods: {
18
+ returnToExtensionsPage() {
19
+ this.$router.push(this.extensionsPageLink);
20
+ },
21
+ reload() {
22
+ this.$router.go();
23
+ },
24
+ showCatalogLoadDialog() {
25
+ this.$store.dispatch('management/promptModal', {
26
+ component: 'ExtensionCatalogInstallDialog',
27
+ returnFocusSelector: '[data-testid="extensions-catalog-load-dialog"]',
28
+ componentProps: {
29
+ refresh: () => {
30
+ this.reloadRequired = true;
31
+ }
32
+ }
33
+ });
34
+ },
35
+ showCatalogUninstallDialog(ev) {
36
+ this.$store.dispatch('management/promptModal', {
37
+ component: 'ExtensionCatalogUninstallDialog',
38
+ returnFocusSelector: '[data-testid="extensions-catalog-load-dialog"]',
39
+ componentProps: {
40
+ catalog: ev,
41
+ refresh: () => {
42
+ this.reloadRequired = true;
43
+ }
44
+ }
45
+ });
46
+ },
47
+ }
48
+ };
49
+ </script>
50
+
51
+ <template>
52
+ <div id="extensions-airgapped-main-page">
53
+ <div class="plugin-header">
54
+ <!-- catalog/airgapped header -->
55
+ <div class="catalog-title">
56
+ <h2
57
+ class="mb-0 mr-10"
58
+ data-testid="extensions-catalog-title"
59
+ >
60
+ <a
61
+ class="link"
62
+ role="link"
63
+ tabindex="0"
64
+ :aria-label="t('plugins.manageCatalog.title')"
65
+ @click="returnToExtensionsPage()"
66
+ >
67
+ {{ t('plugins.manageCatalog.title') }}:
68
+ </a>
69
+ <t k="plugins.manageCatalog.subtitle" />
70
+ </h2>
71
+ </div>
72
+ <div class="actions-container">
73
+ <!-- extensions reload toast/notification -->
74
+ <div
75
+ v-if="reloadRequired"
76
+ class="plugin-reload-banner mmr-6"
77
+ data-testid="extension-reload-banner"
78
+ >
79
+ <i class="icon icon-checkmark mr-10" />
80
+ <span>
81
+ {{ t('plugins.reload') }}
82
+ </span>
83
+ <button
84
+ class="ml-10 btn btn-sm role-primary"
85
+ data-testid="extension-reload-banner-reload-btn"
86
+ role="button"
87
+ :aria-label="t('plugins.labels.reloadRancher')"
88
+ @click="reload()"
89
+ >
90
+ {{ t('generic.reload') }}
91
+ </button>
92
+ </div>
93
+ </div>
94
+ </div>
95
+ <div>
96
+ <!-- Catalog list view -->
97
+ <CatalogList
98
+ @showCatalogLoadDialog="showCatalogLoadDialog"
99
+ @showCatalogUninstallDialog="showCatalogUninstallDialog($event)"
100
+ />
101
+ </div>
102
+ </div>
103
+ </template>
104
+
105
+ <style lang="scss" scoped>
106
+ .plugin-header {
107
+ display: flex;
108
+ align-items: center;
109
+ justify-content: space-between;
110
+ margin-bottom: 10px;
111
+
112
+ .catalog-title {
113
+ display: flex;
114
+ flex-direction: row;
115
+ align-items: center;
116
+ }
117
+
118
+ > h2 {
119
+ flex: 1;
120
+ margin-bottom: 0;
121
+ }
122
+
123
+ .link {
124
+ cursor: pointer;
125
+ }
126
+ }
127
+
128
+ .plugin-reload-banner {
129
+ align-items: center;
130
+ background-color: var(--success-banner-bg);
131
+ display: flex;
132
+ padding: 4px 4px 4px 12px;
133
+ border-radius: 5px;
134
+ min-height: 36px;
135
+
136
+ > i {
137
+ color: var(--success);
138
+ font-size: 14px;
139
+ font-weight: bold;
140
+ }
141
+
142
+ > button {
143
+ line-height: 30px;
144
+ min-height: 30px;
145
+ }
146
+ }
147
+ </style>
@@ -14,10 +14,8 @@ import ActionMenu from '@shell/components/ActionMenuShell';
14
14
  import Tabbed from '@shell/components/Tabbed/index.vue';
15
15
  import Tab from '@shell/components/Tabbed/Tab.vue';
16
16
  import IconMessage from '@shell/components/IconMessage.vue';
17
- import { BadgeState } from '@components/BadgeState';
18
17
  import PluginInfoPanel from './PluginInfoPanel.vue';
19
18
  import SetupUIPlugins from './SetupUIPlugins.vue';
20
- import CatalogList from './CatalogList/index.vue';
21
19
  import Banner from '@components/Banner/Banner.vue';
22
20
  import {
23
21
  isUIPlugin,
@@ -48,9 +46,7 @@ const TABS_VALUES = {
48
46
  export default {
49
47
  components: {
50
48
  ActionMenu,
51
- BadgeState,
52
49
  IconMessage,
53
- CatalogList,
54
50
  Banner,
55
51
  PluginInfoPanel,
56
52
  Tab,
@@ -79,8 +75,7 @@ export default {
79
75
  hasFeatureFlag: true,
80
76
  defaultIcon: require('~shell/assets/images/generic-plugin.svg'),
81
77
  reloadRequired: false,
82
- rancherVersion: null,
83
- showCatalogList: false
78
+ rancherVersion: null
84
79
  };
85
80
  },
86
81
 
@@ -175,14 +170,11 @@ export default {
175
170
  enabled: true
176
171
  });
177
172
 
178
- // Only show Manage Extension Catalogs when on main charts view
179
- if (!this.showCatalogList) {
180
- menuActions.push({
181
- action: 'manageExtensionView',
182
- label: this.t('plugins.manageCatalog.label'),
183
- enabled: true
184
- });
185
- }
173
+ menuActions.push({
174
+ action: 'manageExtensionView',
175
+ label: this.t('plugins.manageCatalog.label'),
176
+ enabled: true
177
+ });
186
178
 
187
179
  // Only show Developer Load action if the user has this enabled in preferences
188
180
  if (this.pluginDeveloper) {
@@ -204,7 +196,7 @@ export default {
204
196
  switch (this.activeTab) {
205
197
  case TABS_VALUES.INSTALLED:
206
198
  // We never show built-in extensions as installed - installed are just the ones the user has installed
207
- return all.filter((p) => !p.builtin && (!!p.installed || !!p.installing) && p.installableVersions?.length > 0);
199
+ return all.filter((p) => !p.builtin && (!!p.installed || !!p.installing));
208
200
  case TABS_VALUES.AVAILABLE:
209
201
  return all.filter((p) => !p.installed);
210
202
  case TABS_VALUES.BUILTIN:
@@ -284,6 +276,7 @@ export default {
284
276
  const latestNotCompatible = item.versions.find((version) => !version.isVersionCompatible);
285
277
 
286
278
  if (latestCompatible) {
279
+ item.primeOnly = latestCompatible?.annotations?.[CATALOG_ANNOTATIONS.PRIME_ONLY] === 'true';
287
280
  item.experimental = latestCompatible?.annotations?.[CATALOG_ANNOTATIONS.EXPERIMENTAL] === 'true';
288
281
  item.certified = latestCompatible?.annotations?.[CATALOG_ANNOTATIONS.CERTIFIED] === CATALOG_ANNOTATIONS._RANCHER;
289
282
 
@@ -292,6 +285,7 @@ export default {
292
285
  item.icon = latestCompatible.icon;
293
286
  item.created = latestCompatible.created;
294
287
  } else {
288
+ item.primeOnly = uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.PRIME_ONLY, 'true');
295
289
  item.experimental = uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.EXPERIMENTAL, 'true');
296
290
  item.certified = uiPluginHasAnnotation(chart, CATALOG_ANNOTATIONS.CERTIFIED, CATALOG_ANNOTATIONS._RANCHER);
297
291
 
@@ -349,6 +343,7 @@ export default {
349
343
  installed: true,
350
344
  installedVersion: p.metadata?.version,
351
345
  builtin: !!p.builtin,
346
+ primeOnly: rancher?.annotations?.[CATALOG_ANNOTATIONS.PRIME_ONLY] === 'true',
352
347
  experimental: rancher?.annotations?.[CATALOG_ANNOTATIONS.EXPERIMENTAL] === 'true',
353
348
  certified: rancher?.annotations?.[CATALOG_ANNOTATIONS.CERTIFIED] === CATALOG_ANNOTATIONS._RANCHER
354
349
  };
@@ -381,6 +376,7 @@ export default {
381
376
  const installedVersion = (chart.installableVersions || []).find((v) => (v.appVersion ?? v.version) === p.version);
382
377
 
383
378
  if (installedVersion) {
379
+ chart.primeOnly = installedVersion?.annotations?.[CATALOG_ANNOTATIONS.PRIME_ONLY] === 'true';
384
380
  chart.experimental = installedVersion?.annotations?.[CATALOG_ANNOTATIONS.EXPERIMENTAL] === 'true';
385
381
  chart.certified = installedVersion?.annotations?.[CATALOG_ANNOTATIONS.CERTIFIED] === CATALOG_ANNOTATIONS._RANCHER;
386
382
  }
@@ -397,6 +393,7 @@ export default {
397
393
  versions: [],
398
394
  displayVersion: p.version,
399
395
  displayVersionLabel: p.version || '-',
396
+ isDeveloper: p.isDeveloper,
400
397
  installed: true,
401
398
  installing: false,
402
399
  builtin: false,
@@ -593,37 +590,6 @@ export default {
593
590
  });
594
591
  },
595
592
 
596
- showCatalogLoadDialog() {
597
- this.$store.dispatch('management/promptModal', {
598
- component: 'ExtensionCatalogInstallDialog',
599
- returnFocusSelector: '[data-testid="extensions-catalog-load-dialog"]',
600
- componentProps: {
601
- refresh: () => {
602
- this.reloadRequired = true;
603
- },
604
- closed: (res) => {
605
- this.didInstall(res);
606
- }
607
- }
608
- });
609
- },
610
-
611
- showCatalogUninstallDialog(ev) {
612
- this.$store.dispatch('management/promptModal', {
613
- component: 'ExtensionCatalogUninstallDialog',
614
- returnFocusSelector: '[data-testid="extensions-catalog-load-dialog"]',
615
- componentProps: {
616
- catalog: ev,
617
- refresh: () => {
618
- this.reloadRequired = true;
619
- },
620
- closed: (res) => {
621
- this.didUninstall(res);
622
- }
623
- }
624
- });
625
- },
626
-
627
593
  showInstallDialog(plugin, action, ev, initialVersion = null) {
628
594
  ev?.target?.blur();
629
595
  ev?.preventDefault?.();
@@ -731,7 +697,10 @@ export default {
731
697
  },
732
698
 
733
699
  manageExtensionView() {
734
- this.showCatalogList = !this.showCatalogList;
700
+ this.$router.push({
701
+ name: 'c-cluster-uiplugins-catalogs',
702
+ params: { cluster: this.$route.params.cluster }
703
+ });
735
704
  },
736
705
 
737
706
  updateAddReposSetting() {
@@ -844,11 +813,20 @@ export default {
844
813
  getFooterItems(plugin) {
845
814
  const labels = [];
846
815
 
816
+ // "developer load" tag
817
+ if (plugin.isDeveloper) {
818
+ labels.push(this.t('plugins.labels.isDeveloper'));
819
+ }
820
+
821
+ if (plugin.primeOnly) {
822
+ labels.push(this.t('plugins.labels.primeOnly'));
823
+ }
824
+
847
825
  if (plugin.builtin) {
848
826
  labels.push(this.t('plugins.labels.builtin'));
849
827
  }
850
828
 
851
- if (!plugin.builtin && !plugin.certified) {
829
+ if (!plugin.builtin && !plugin.certified && !plugin.isDeveloper) {
852
830
  labels.push(this.t('plugins.labels.third-party'));
853
831
  }
854
832
 
@@ -908,39 +886,12 @@ export default {
908
886
  <template>
909
887
  <div id="extensions-main-page">
910
888
  <div class="plugin-header">
911
- <!-- catalog view header -->
912
- <template v-if="showCatalogList">
913
- <div class="catalog-title">
914
- <h2
915
- class="mb-0 mr-10"
916
- data-testid="extensions-catalog-title"
917
- >
918
- <a
919
- class="link"
920
- role="link"
921
- tabindex="0"
922
- :aria-label="t('plugins.manageCatalog.title')"
923
- @click="manageExtensionView()"
924
- >
925
- {{ t('plugins.manageCatalog.title') }}:
926
- </a>
927
- <t k="plugins.manageCatalog.subtitle" />
928
- </h2>
929
- <BadgeState
930
- color="bg-warning"
931
- :label="t('generic.experimental')"
932
- class="badge"
933
- />
934
- </div>
935
- </template>
936
889
  <!-- normal extensions view header -->
937
- <template v-else>
938
- <h2 data-testid="extensions-page-title">
939
- <TabTitle breadcrumb="vendor-only">
940
- {{ t('plugins.title') }}
941
- </TabTitle>
942
- </h2>
943
- </template>
890
+ <h2 data-testid="extensions-page-title">
891
+ <TabTitle breadcrumb="vendor-only">
892
+ {{ t('plugins.title') }}
893
+ </TabTitle>
894
+ </h2>
944
895
  <div class="actions-container">
945
896
  <!-- extensions reload toast/notification -->
946
897
  <div
@@ -1005,112 +956,103 @@ export default {
1005
956
  />
1006
957
  </div>
1007
958
  <div v-else>
1008
- <!-- Extension Catalog list view -->
1009
- <template v-if="showCatalogList">
1010
- <CatalogList
1011
- @showCatalogLoadDialog="showCatalogLoadDialog"
1012
- @showCatalogUninstallDialog="showCatalogUninstallDialog($event)"
1013
- />
1014
- </template>
1015
- <template v-else>
1016
- <Banner
1017
- v-if="!loading && showAddReposBanner"
1018
- color="warning"
1019
- class="add-repos-banner mb-20"
1020
- data-testid="extensions-new-repos-banner"
959
+ <Banner
960
+ v-if="!loading && showAddReposBanner"
961
+ color="warning"
962
+ class="add-repos-banner mb-20"
963
+ data-testid="extensions-new-repos-banner"
964
+ >
965
+ <span>{{ t('plugins.addRepos.banner', {}, true) }}</span>
966
+ <button
967
+ class="ml-10 btn btn-sm role-primary"
968
+ data-testid="extensions-new-repos-banner-action-btn"
969
+ role="button"
970
+ :aria-label="t('plugins.addRepos.bannerBtn')"
971
+ @click="showAddExtensionReposDialog()"
1021
972
  >
1022
- <span>{{ t('plugins.addRepos.banner', {}, true) }}</span>
1023
- <button
1024
- class="ml-10 btn btn-sm role-primary"
1025
- data-testid="extensions-new-repos-banner-action-btn"
1026
- role="button"
1027
- :aria-label="t('plugins.addRepos.bannerBtn')"
1028
- @click="showAddExtensionReposDialog()"
973
+ {{ t('plugins.addRepos.bannerBtn') }}
974
+ </button>
975
+ </Banner>
976
+
977
+ <Tabbed
978
+ v-if="!loading"
979
+ ref="tabs"
980
+ :tabs-only="true"
981
+ data-testid="extension-tabs"
982
+ @changed="tabChanged"
983
+ >
984
+ <Tab
985
+ v-if="installed.length"
986
+ :name="TABS_VALUES.INSTALLED"
987
+ data-testid="extension-tab-installed"
988
+ label-key="plugins.tabs.installed"
989
+ :badge="installed.length"
990
+ :weight="20"
991
+ />
992
+ <Tab
993
+ :name="TABS_VALUES.AVAILABLE"
994
+ data-testid="extension-tab-available"
995
+ label-key="plugins.tabs.available"
996
+ :weight="19"
997
+ />
998
+ <Tab
999
+ v-if="pluginDeveloper"
1000
+ :name="TABS_VALUES.BUILTIN"
1001
+ label-key="plugins.tabs.builtin"
1002
+ :weight="17"
1003
+ />
1004
+ </Tabbed>
1005
+ <div
1006
+ v-if="loading"
1007
+ class="data-loading"
1008
+ >
1009
+ <i class="icon-spin icon icon-spinner" />
1010
+ <t
1011
+ k="generic.loading"
1012
+ :raw="true"
1013
+ />
1014
+ </div>
1015
+ <div
1016
+ v-else
1017
+ class="plugin-cards"
1018
+ :class="{'v-margin': !list.length}"
1019
+ >
1020
+ <IconMessage
1021
+ v-if="list.length === 0"
1022
+ :vertical="true"
1023
+ :subtle="true"
1024
+ icon="icon-extension"
1025
+ class="mmt-9"
1026
+ :message="emptyMessage"
1027
+ />
1028
+ <template v-else>
1029
+ <rc-item-card
1030
+ v-for="card in pluginCards"
1031
+ :id="card.id"
1032
+ :key="card.id"
1033
+ :class="{ 'single-card': pluginCards.length === 1 }"
1034
+ :header="card.header"
1035
+ :image="card.image"
1036
+ :content="card.content"
1037
+ :actions="card.actions"
1038
+ :clickable="true"
1039
+ @card-click="showPluginDetail(card.plugin)"
1040
+ @uninstall="({event}) => showUninstallDialog(card.plugin, event)"
1041
+ @upgrade="({event}) => showInstallDialog(card.plugin, 'upgrade', event)"
1042
+ @downgrade="({event}) => showInstallDialog(card.plugin, 'downgrade', event)"
1043
+ @install="({event}) => showInstallDialog(card.plugin, 'install', event)"
1029
1044
  >
1030
- {{ t('plugins.addRepos.bannerBtn') }}
1031
- </button>
1032
- </Banner>
1033
-
1034
- <Tabbed
1035
- v-if="!loading"
1036
- ref="tabs"
1037
- :tabs-only="true"
1038
- data-testid="extension-tabs"
1039
- @changed="tabChanged"
1040
- >
1041
- <Tab
1042
- v-if="installed.length"
1043
- :name="TABS_VALUES.INSTALLED"
1044
- data-testid="extension-tab-installed"
1045
- label-key="plugins.tabs.installed"
1046
- :badge="installed.length"
1047
- :weight="20"
1048
- />
1049
- <Tab
1050
- :name="TABS_VALUES.AVAILABLE"
1051
- data-testid="extension-tab-available"
1052
- label-key="plugins.tabs.available"
1053
- :weight="19"
1054
- />
1055
- <Tab
1056
- v-if="pluginDeveloper"
1057
- :name="TABS_VALUES.BUILTIN"
1058
- label-key="plugins.tabs.builtin"
1059
- :weight="17"
1060
- />
1061
- </Tabbed>
1062
- <div
1063
- v-if="loading"
1064
- class="data-loading"
1065
- >
1066
- <i class="icon-spin icon icon-spinner" />
1067
- <t
1068
- k="generic.loading"
1069
- :raw="true"
1070
- />
1071
- </div>
1072
- <div
1073
- v-else
1074
- class="plugin-cards"
1075
- :class="{'v-margin': !list.length}"
1076
- >
1077
- <IconMessage
1078
- v-if="list.length === 0"
1079
- :vertical="true"
1080
- :subtle="true"
1081
- icon="icon-extension"
1082
- class="mmt-9"
1083
- :message="emptyMessage"
1084
- />
1085
- <template v-else>
1086
- <rc-item-card
1087
- v-for="card in pluginCards"
1088
- :id="card.id"
1089
- :key="card.id"
1090
- :class="{ 'single-card': pluginCards.length === 1 }"
1091
- :header="card.header"
1092
- :image="card.image"
1093
- :content="card.content"
1094
- :actions="card.actions"
1095
- :clickable="true"
1096
- @card-click="showPluginDetail(card.plugin)"
1097
- @uninstall="({event}) => showUninstallDialog(card.plugin, event)"
1098
- @upgrade="({event}) => showInstallDialog(card.plugin, 'upgrade', event)"
1099
- @downgrade="({event}) => showInstallDialog(card.plugin, 'downgrade', event)"
1100
- @install="({event}) => showInstallDialog(card.plugin, 'install', event)"
1101
- >
1102
- <template #item-card-sub-header>
1103
- <AppChartCardSubHeader
1104
- :items="card.subHeaderItems"
1105
- />
1106
- </template>
1107
- <template #item-card-footer>
1108
- <AppChartCardFooter :items="card.footerItems" />
1109
- </template>
1110
- </rc-item-card>
1111
- </template>
1112
- </div>
1113
- </template>
1045
+ <template #item-card-sub-header>
1046
+ <AppChartCardSubHeader
1047
+ :items="card.subHeaderItems"
1048
+ />
1049
+ </template>
1050
+ <template #item-card-footer>
1051
+ <AppChartCardFooter :items="card.footerItems" />
1052
+ </template>
1053
+ </rc-item-card>
1054
+ </template>
1055
+ </div>
1114
1056
  </div>
1115
1057
  </div>
1116
1058
  </template>
@@ -0,0 +1,3 @@
1
+ export default async(context) => {
2
+ await context.store.dispatch('dashboardClientInit', context);
3
+ };
@@ -1,5 +1,8 @@
1
1
 
2
- import { SCHEMA, COUNT, POD } from '@shell/config/types';
2
+ import {
3
+ SCHEMA, COUNT, POD, MANAGEMENT, BRAND
4
+ } from '@shell/config/types';
5
+ import { SETTING } from '@shell/config/settings';
3
6
 
4
7
  import { matches } from '@shell/utils/selector';
5
8
  import { typeMunge, typeRef, SIMPLE_TYPES } from '@shell/utils/create-yaml';
@@ -204,6 +207,20 @@ export default {
204
207
  }
205
208
  },
206
209
 
210
+ brand: (state, getters) => {
211
+ const brand = getters['byId'](MANAGEMENT.SETTING, SETTING.BRAND);
212
+
213
+ if (!brand?.value) {
214
+ return undefined;
215
+ }
216
+
217
+ if ([BRAND.CSP, BRAND.FEDERAL, BRAND.RGS].includes(brand.value)) {
218
+ return BRAND.SUSE;
219
+ }
220
+
221
+ return brand.value;
222
+ },
223
+
207
224
  /**
208
225
  * Checks a schema for the given path
209
226
  *
@@ -905,7 +905,7 @@ export default class Resource {
905
905
  return out;
906
906
  }
907
907
 
908
- showConfiguration(returnFocusSelector) {
908
+ showConfiguration(returnFocusSelector, defaultTab) {
909
909
  const onClose = () => this.$ctx.commit('slideInPanel/close', undefined, { root: true });
910
910
 
911
911
  this.$ctx.commit('slideInPanel/open', {
@@ -920,7 +920,8 @@ export default class Resource {
920
920
  'z-index': 101, // We want this to be above the main side menu
921
921
  closeOnRouteChange: ['name', 'params', 'query'], // We want to ignore hash changes, tables in extensions can trigger the drawer to close while opening
922
922
  triggerFocusTrap: true,
923
- returnFocusSelector
923
+ returnFocusSelector,
924
+ defaultTab
924
925
  }
925
926
  }, { root: true });
926
927
  }
package/plugins/i18n.js CHANGED
@@ -3,6 +3,14 @@ import { escapeHtml } from '../utils/string';
3
3
  import { watchEffect, ref, h } from 'vue';
4
4
  import { useStore } from 'vuex';
5
5
 
6
+ /**
7
+ * @param {import('vuex').Store<any>} store
8
+ * @param {string} key
9
+ * @param {Record<string, any>} [args]
10
+ * @param {boolean} [raw]
11
+ * @param {boolean} [escapehtml]
12
+ * @returns {string}
13
+ */
6
14
  export function stringFor(store, key, args, raw = false, escapehtml = true) {
7
15
  const translation = store.getters['i18n/t'](key, args);
8
16