@rancher/shell 0.1.3 → 0.1.21

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 (245) hide show
  1. package/assets/brand/suse/dark/rancher-logo.svg +1 -148
  2. package/assets/brand/suse/favicon.png +0 -0
  3. package/assets/brand/suse/rancher-logo.svg +1 -130
  4. package/assets/images/featured/img1.jpg +0 -0
  5. package/assets/images/featured.jpg +0 -0
  6. package/assets/images/generic-plugin.svg +1 -0
  7. package/assets/styles/themes/_dark.scss +3 -0
  8. package/assets/styles/themes/_light.scss +3 -0
  9. package/assets/styles/themes/_suse.scss +1 -1
  10. package/assets/translations/en-us.yaml +219 -47
  11. package/assets/translations/zh-hans.yaml +21 -24
  12. package/components/AsyncButton.vue +17 -2
  13. package/components/ButtonDropdown.vue +4 -0
  14. package/components/Carousel.vue +291 -0
  15. package/components/CommunityLinks.vue +64 -22
  16. package/components/CruResource.vue +11 -3
  17. package/components/Dialog.vue +102 -0
  18. package/components/ExplorerMembers.vue +2 -4
  19. package/components/ExplorerProjectsNamespaces.vue +25 -9
  20. package/components/IconMessage.vue +9 -1
  21. package/components/LazyImage.vue +21 -8
  22. package/components/LocaleSelector.vue +62 -29
  23. package/components/PromptRemove.vue +2 -2
  24. package/components/ResourceList/Masthead.vue +21 -1
  25. package/components/ResourceList/ResourceLoadingIndicator.vue +0 -8
  26. package/components/ResourceList/index.vue +9 -23
  27. package/components/ResourceTable.vue +7 -2
  28. package/components/SimpleBox.vue +6 -4
  29. package/components/SortableTable/index.vue +18 -25
  30. package/components/Tabbed/Tab.vue +5 -0
  31. package/components/Tabbed/index.vue +54 -9
  32. package/components/TypeDescription.vue +10 -1
  33. package/components/auth/Principal.vue +1 -0
  34. package/components/fleet/FleetBundles.vue +8 -3
  35. package/components/fleet/FleetClusters.vue +6 -0
  36. package/components/fleet/FleetRepos.vue +7 -1
  37. package/components/fleet/FleetSummary.vue +6 -0
  38. package/components/form/Command.vue +5 -0
  39. package/components/form/EnvVars.vue +5 -0
  40. package/components/form/KeyValue.vue +80 -58
  41. package/components/form/NameNsDescription.vue +13 -5
  42. package/components/form/NodeScheduling.vue +6 -1
  43. package/components/form/PodAffinity.vue +5 -0
  44. package/components/form/ResourceTabs/index.vue +5 -1
  45. package/components/form/ServiceNameSelect.vue +5 -0
  46. package/components/form/ValueFromResource.vue +7 -1
  47. package/components/formatter/ClusterLink.vue +3 -7
  48. package/components/nav/NamespaceFilter.vue +3 -3
  49. package/components/nav/TopLevelMenu.vue +12 -29
  50. package/config/home-links.js +155 -0
  51. package/config/labels-annotations.js +2 -1
  52. package/config/private-label.js +1 -1
  53. package/config/product/explorer.js +5 -4
  54. package/config/product/legacy.js +0 -47
  55. package/config/product/manager.js +0 -2
  56. package/config/product/multi-cluster-apps.js +0 -12
  57. package/config/product/settings.js +12 -1
  58. package/config/product/uiplugins.js +17 -0
  59. package/config/settings.js +23 -2
  60. package/config/types.js +5 -1
  61. package/config/uiplugins.js +117 -0
  62. package/config/version.js +17 -0
  63. package/content/docs/en-us/getting-started.md +1 -26
  64. package/core/plugin.ts +12 -0
  65. package/core/plugins.js +38 -2
  66. package/core/types.ts +6 -0
  67. package/creators/app/{.eslintignore → files/.eslintignore} +0 -0
  68. package/creators/app/{.eslintrc.js → files/.eslintrc.js} +0 -0
  69. package/creators/app/{.vscode → files/.vscode}/settings.json +0 -0
  70. package/creators/app/{babel.config.js → files/babel.config.js} +0 -0
  71. package/creators/app/{nuxt.config.js → files/nuxt.config.js} +0 -0
  72. package/creators/app/{tsconfig.json → files/tsconfig.json} +2 -1
  73. package/creators/app/init +16 -17
  74. package/creators/app/package.json +6 -0
  75. package/creators/pkg/{babel.config.js → files/babel.config.js} +0 -0
  76. package/creators/pkg/{index.ts → files/index.ts} +0 -0
  77. package/creators/pkg/{tsconfig.json → files/tsconfig.json} +13 -12
  78. package/creators/pkg/{vue.config.js → files/vue.config.js} +0 -0
  79. package/creators/pkg/init +1 -1
  80. package/creators/update/init +54 -0
  81. package/creators/update/package.json +20 -0
  82. package/creators/update/upgrade +56 -0
  83. package/creators/update/yarn-error.log +54 -0
  84. package/detail/provisioning.cattle.io.cluster.vue +3 -3
  85. package/detail/workload/index.vue +3 -2
  86. package/dialog/DiagnosticTimingsDialog.vue +116 -0
  87. package/dialog/RotateCertificatesDialog.vue +9 -3
  88. package/edit/auth/azuread.vue +28 -9
  89. package/edit/networking.k8s.io.ingress/index.vue +2 -2
  90. package/edit/persistentvolume/index.vue +51 -13
  91. package/edit/persistentvolumeclaim.vue +31 -13
  92. package/edit/pod.vue +27 -0
  93. package/edit/provisioning.cattle.io.cluster/rke2.vue +103 -24
  94. package/edit/service.vue +7 -5
  95. package/edit/workload/__tests__/Upgrading.test.ts +1 -0
  96. package/edit/workload/index.vue +32 -10
  97. package/edit/workload/mixins/workload.js +121 -126
  98. package/edit/workload/storage/ContainerMountPaths.vue +240 -0
  99. package/edit/workload/storage/Mount.vue +1 -0
  100. package/edit/workload/storage/awsElasticBlockStore.vue +20 -1
  101. package/edit/workload/storage/azureDisk.vue +22 -2
  102. package/edit/workload/storage/azureFile.vue +20 -2
  103. package/edit/workload/storage/csi/index.vue +23 -1
  104. package/edit/workload/storage/gcePersistentDisk.vue +20 -2
  105. package/edit/workload/storage/index.vue +33 -65
  106. package/edit/workload/storage/persistentVolumeClaim/index.vue +5 -0
  107. package/edit/workload/storage/secret.vue +6 -1
  108. package/edit/workload/storage/vsphereVolume.vue +11 -1
  109. package/layouts/default.vue +14 -8
  110. package/layouts/home.vue +9 -4
  111. package/layouts/plain.vue +10 -5
  112. package/list/catalog.cattle.io.app.vue +10 -9
  113. package/list/catalog.cattle.io.clusterrepo.vue +6 -61
  114. package/list/cis.cattle.io.clusterscan.vue +12 -12
  115. package/list/fleet.cattle.io.bundle.vue +33 -28
  116. package/list/fleet.cattle.io.cluster.vue +26 -22
  117. package/list/fleet.cattle.io.clustergroup.vue +6 -0
  118. package/list/fleet.cattle.io.clusterregistrationtoken.vue +28 -24
  119. package/list/fleet.cattle.io.gitrepo.vue +25 -14
  120. package/list/helm.cattle.io.projecthelmchart.vue +52 -33
  121. package/list/logging.banzaicloud.io.clusterflow.vue +7 -12
  122. package/list/logging.banzaicloud.io.flow.vue +7 -14
  123. package/list/management.cattle.io.cluster.vue +26 -15
  124. package/list/management.cattle.io.feature.vue +13 -8
  125. package/list/management.cattle.io.setting.vue +3 -3
  126. package/list/management.cattle.io.user.vue +38 -19
  127. package/list/monitoring.coreos.com.alertmanagerconfig.vue +8 -15
  128. package/list/namespace.vue +14 -1
  129. package/list/node.vue +13 -16
  130. package/list/persistentvolume.vue +16 -9
  131. package/list/persistentvolumeclaim.vue +5 -8
  132. package/list/provisioning.cattle.io.cluster.vue +35 -9
  133. package/list/service.vue +24 -12
  134. package/list/ui.cattle.io.navlink.vue +6 -0
  135. package/list/workload.vue +2 -2
  136. package/machine-config/harvester.vue +5 -3
  137. package/middleware/authenticated.js +6 -0
  138. package/mixins/resource-fetch.js +12 -18
  139. package/mixins/resource-manager.js +126 -0
  140. package/models/catalog.cattle.io.uiplugin.js +38 -0
  141. package/models/cluster/node.js +25 -2
  142. package/models/fleet.cattle.io.bundle.js +1 -1
  143. package/models/harvesterhci.io.management.cluster.js +11 -5
  144. package/models/pod.js +15 -5
  145. package/models/provisioning.cattle.io.cluster.js +16 -6
  146. package/models/workload.js +5 -3
  147. package/models/workload.service.js +10 -0
  148. package/nuxt.config.js +70 -25
  149. package/package.json +108 -109
  150. package/pages/auth/login.vue +11 -1
  151. package/pages/auth/verify.vue +9 -0
  152. package/pages/c/_cluster/apps/charts/index.vue +46 -1
  153. package/pages/c/_cluster/apps/charts/install.vue +10 -9
  154. package/pages/c/_cluster/explorer/index.vue +72 -9
  155. package/pages/c/_cluster/explorer/tools/index.vue +12 -5
  156. package/pages/c/_cluster/mcapps/index.vue +1 -1
  157. package/pages/c/_cluster/settings/DefaultLinksEditor.vue +108 -0
  158. package/pages/c/_cluster/settings/brand.vue +0 -40
  159. package/pages/c/_cluster/settings/links.vue +152 -0
  160. package/pages/c/_cluster/settings/performance.vue +90 -7
  161. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +232 -0
  162. package/pages/c/_cluster/uiplugins/InstallDialog.vue +293 -0
  163. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +300 -0
  164. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +125 -0
  165. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +261 -0
  166. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +122 -0
  167. package/pages/c/_cluster/uiplugins/index.vue +808 -0
  168. package/pages/diagnostic.vue +185 -101
  169. package/pages/docs/_doc.vue +3 -1
  170. package/pages/home.vue +21 -56
  171. package/pages/prefs.vue +108 -88
  172. package/pages/safeMode.vue +17 -0
  173. package/pages/support/index.vue +34 -137
  174. package/pkg/dynamic-importer.lib.js +4 -0
  175. package/plugins/dashboard-store/actions.js +19 -0
  176. package/plugins/dashboard-store/getters.js +20 -3
  177. package/plugins/dashboard-store/mutations.js +13 -7
  178. package/plugins/dashboard-store/resource-class.js +2 -2
  179. package/plugins/formatters.js +15 -0
  180. package/plugins/plugin.js +61 -6
  181. package/plugins/steve/getters.js +12 -0
  182. package/plugins/steve/mutations.js +1 -1
  183. package/plugins/steve/subscribe.js +94 -72
  184. package/plugins/steve/web-worker.steve-sub-worker.js +24 -15
  185. package/plugins/version.js +21 -0
  186. package/promptRemove/management.cattle.io.globalrole.vue +47 -0
  187. package/promptRemove/management.cattle.io.roletemplate.vue +47 -0
  188. package/promptRemove/mixin/roleDeletionCheck.js +97 -0
  189. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +6 -7
  190. package/rancher-components/components/BadgeState/BadgeState.spec.ts +12 -0
  191. package/rancher-components/components/BadgeState/BadgeState.vue +107 -0
  192. package/rancher-components/components/BadgeState/index.ts +1 -0
  193. package/rancher-components/components/Banner/Banner.test.ts +13 -0
  194. package/rancher-components/components/Banner/Banner.vue +163 -0
  195. package/rancher-components/components/Banner/index.ts +1 -0
  196. package/rancher-components/components/Card/Card.vue +150 -0
  197. package/rancher-components/components/Card/index.ts +1 -0
  198. package/rancher-components/components/Form/Checkbox/Checkbox.test.ts +77 -0
  199. package/rancher-components/components/Form/Checkbox/Checkbox.vue +395 -0
  200. package/rancher-components/components/Form/Checkbox/index.ts +1 -0
  201. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +29 -0
  202. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +343 -0
  203. package/rancher-components/components/Form/LabeledInput/index.ts +1 -0
  204. package/rancher-components/components/Form/Radio/RadioButton.vue +270 -0
  205. package/rancher-components/components/Form/Radio/RadioGroup.vue +235 -0
  206. package/rancher-components/components/Form/Radio/index.ts +2 -0
  207. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +168 -0
  208. package/rancher-components/components/Form/TextArea/index.ts +1 -0
  209. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.test.ts +107 -0
  210. package/rancher-components/components/Form/ToggleSwitch/ToggleSwitch.vue +137 -0
  211. package/rancher-components/components/Form/ToggleSwitch/index.ts +1 -0
  212. package/rancher-components/components/Form/index.ts +5 -0
  213. package/rancher-components/components/LabeledTooltip/LabeledTooltip.vue +137 -0
  214. package/rancher-components/components/LabeledTooltip/index.ts +1 -0
  215. package/scripts/publish-shell.sh +40 -7
  216. package/scripts/record-deps.js +37 -0
  217. package/scripts/sync-shell-deps +37 -0
  218. package/scripts/test-plugins-build.sh +8 -5
  219. package/scripts/typegen.sh +84 -0
  220. package/store/auth.js +3 -0
  221. package/store/catalog.js +9 -8
  222. package/store/i18n.js +10 -1
  223. package/store/index.js +12 -3
  224. package/store/prefs.js +16 -0
  225. package/store/type-map.js +32 -5
  226. package/store/uiplugins.ts +15 -61
  227. package/types/shell/index.d.ts +3046 -0
  228. package/utils/__tests__/object.test.ts +0 -24
  229. package/utils/__tests__/selector.test.ts +1 -1
  230. package/utils/dynamic-importer.js +4 -0
  231. package/utils/favicon.js +8 -2
  232. package/utils/gc/gc-interval.ts +40 -0
  233. package/utils/gc/gc-root-store.js +76 -0
  234. package/utils/gc/gc-route-changed.ts +44 -0
  235. package/utils/gc/gc-types.ts +21 -0
  236. package/utils/gc/gc.ts +282 -0
  237. package/utils/grafana.js +2 -6
  238. package/utils/socket.js +41 -20
  239. package/utils/string.js +1 -7
  240. package/utils/validators/formRules/__tests__/index.test.ts +108 -0
  241. package/utils/validators/formRules/index.ts +9 -1
  242. package/config/footer.js +0 -19
  243. package/creators/pkg/nuxt.config.js +0 -6
  244. package/pages/plugins.vue +0 -387
  245. package/server/verdaccio-middleware.js +0 -56
@@ -4,19 +4,20 @@ import ResourceTable from '@shell/components/ResourceTable';
4
4
  import { STATE, AGE, NAME } from '@shell/config/table-headers';
5
5
  import { uniq } from '@shell/utils/array';
6
6
  import { MANAGEMENT, NAMESPACE, VIRTUAL_TYPES } from '@shell/config/types';
7
- import Loading from '@shell/components/Loading';
8
7
  import { PROJECT_ID } from '@shell/config/query-params';
9
8
  import Masthead from '@shell/components/ResourceList/Masthead';
10
- import { mapPref, GROUP_RESOURCES, DEV } from '@shell/store/prefs';
9
+ import { mapPref, GROUP_RESOURCES, ALL_NAMESPACES } from '@shell/store/prefs';
11
10
  import MoveModal from '@shell/components/MoveModal';
12
11
  import { defaultTableSortGenerationFn } from '@shell/components/ResourceTable.vue';
13
12
  import { NAMESPACE_FILTER_ALL_ORPHANS } from '@shell/utils/namespace-filter';
13
+ import ResourceFetch from '@shell/mixins/resource-fetch';
14
14
 
15
15
  export default {
16
16
  name: 'ListProjectNamespace',
17
17
  components: {
18
- Loading, Masthead, MoveModal, ResourceTable
18
+ Masthead, MoveModal, ResourceTable
19
19
  },
20
+ mixins: [ResourceFetch],
20
21
 
21
22
  props: {
22
23
  createProjectLocationOverride: {
@@ -43,14 +44,15 @@ export default {
43
44
  return;
44
45
  }
45
46
 
46
- this.namespaces = await this.$store.dispatch(`${ inStore }/findAll`, { type: NAMESPACE });
47
+ await this.$fetchType(NAMESPACE);
47
48
  this.projects = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.PROJECT, opt: { force: true } });
48
49
  },
49
50
 
50
51
  data() {
51
52
  return {
53
+ loadResources: [NAMESPACE],
54
+ loadIndeterminate: true,
52
55
  schema: null,
53
- namespaces: [],
54
56
  projects: [],
55
57
  projectSchema: null,
56
58
  MANAGEMENT,
@@ -67,6 +69,17 @@ export default {
67
69
 
68
70
  computed: {
69
71
  ...mapGetters(['currentCluster', 'currentProduct']),
72
+ namespaces() {
73
+ const inStore = this.$store.getters['currentStore'](NAMESPACE);
74
+
75
+ return this.$store.getters[`${ inStore }/all`](NAMESPACE);
76
+ },
77
+ loading() {
78
+ return !this.currentCluster || this.namespaces.length ? false : this.$fetchState.pending;
79
+ },
80
+ showIncrementalLoadingIndicator() {
81
+ return this.perfConfig?.incrementalLoading?.enabled;
82
+ },
70
83
  isNamespaceCreatable() {
71
84
  return (this.schema?.collectionMethods || []).includes('POST');
72
85
  },
@@ -184,8 +197,8 @@ export default {
184
197
  return this.groupPreference === 'none' ? this.rows : this.rowsWithFakeNamespaces;
185
198
  },
186
199
  rows() {
187
- if (this.$store.getters['prefs/get'](DEV)) {
188
- // If developer tools are turned on in the user preferences,
200
+ if (this.$store.getters['prefs/get'](ALL_NAMESPACES)) {
201
+ // If all namespaces options are turned on in the user preferences,
189
202
  // return all namespaces including system namespaces and RBAC
190
203
  // management namespaces.
191
204
  return this.activeNamespaces;
@@ -302,8 +315,7 @@ export default {
302
315
  </script>
303
316
 
304
317
  <template>
305
- <Loading v-if="$fetchState.pending || !currentCluster" />
306
- <div v-else class="project-namespaces">
318
+ <div class="project-namespaces">
307
319
  <Masthead
308
320
  :schema="projectSchema"
309
321
  :type-display="t('projectNamespaces.label')"
@@ -311,6 +323,9 @@ export default {
311
323
  :favorite-resource="VIRTUAL_TYPES.PROJECT_NAMESPACES"
312
324
  :create-location="createProjectLocation"
313
325
  :create-button-label="t('projectNamespaces.createProject')"
326
+ :show-incremental-loading-indicator="showIncrementalLoadingIndicator"
327
+ :load-resources="loadResources"
328
+ :load-indeterminate="loadIndeterminate"
314
329
  />
315
330
  <ResourceTable
316
331
  ref="table"
@@ -321,6 +336,7 @@ export default {
321
336
  :rows="filteredRows"
322
337
  :groupable="true"
323
338
  :sort-generation-fn="sortGenerationFn"
339
+ :loading="loading"
324
340
  group-tooltip="resourceTable.groupBy.project"
325
341
  key-field="_key"
326
342
  v-on="$listeners"
@@ -21,12 +21,16 @@ export default {
21
21
  type: String,
22
22
  default: null
23
23
  },
24
+ subtle: {
25
+ type: Boolean,
26
+ default: false,
27
+ }
24
28
  },
25
29
  };
26
30
  </script>
27
31
 
28
32
  <template>
29
- <div class="message-icon" :class="{'vertical': vertical}">
33
+ <div class="message-icon" :class="{'vertical': vertical, 'subtle': subtle}">
30
34
  <i class="icon" :class="{ [icon]: true, [iconState]: !!iconState}" />
31
35
  <div class="message">
32
36
  <slot name="message">
@@ -47,6 +51,10 @@ export default {
47
51
  width: 100%;
48
52
  }
49
53
 
54
+ .subtle {
55
+ opacity: 0.7;
56
+ }
57
+
50
58
  .message-icon {
51
59
  display: flex;
52
60
  align-items: center;
@@ -19,17 +19,18 @@ export default {
19
19
  },
20
20
  },
21
21
 
22
- mounted() {
23
- const $img = $(this.$refs.img);
24
-
25
- if ( this.src ) {
26
- $img.attr('src', this.src);
27
- this.boundError = this.onError.bind(this);
28
-
29
- $img.on('error', this.boundError);
22
+ watch: {
23
+ src(neu, old) {
24
+ if (neu !== old) {
25
+ this.loadImage();
26
+ }
30
27
  }
31
28
  },
32
29
 
30
+ mounted() {
31
+ this.loadImage();
32
+ },
33
+
33
34
  beforeDestroy() {
34
35
  const $img = $(this.$refs.img);
35
36
 
@@ -39,6 +40,18 @@ export default {
39
40
  },
40
41
 
41
42
  methods: {
43
+ // Ensure we load the image when the source changes
44
+ loadImage() {
45
+ const $img = $(this.$refs.img);
46
+
47
+ if ( this.src ) {
48
+ $img.attr('src', this.src);
49
+ this.boundError = this.onError.bind(this);
50
+
51
+ $img.on('error', this.boundError);
52
+ }
53
+ },
54
+
42
55
  onError() {
43
56
  const $img = $(this.$refs.img);
44
57
 
@@ -1,12 +1,35 @@
1
1
  <script>
2
2
  import { mapGetters } from 'vuex';
3
+ import Select from '@shell/components/form/Select.vue';
3
4
 
4
5
  export default {
5
6
  name: 'LocalSelector',
6
7
 
8
+ components: { Select },
9
+
10
+ props: {
11
+ mode: {
12
+ type: String,
13
+ default: ''
14
+ },
15
+ },
16
+
7
17
  computed: {
8
18
  ...mapGetters('i18n', ['selectedLocaleLabel', 'availableLocales']),
9
19
 
20
+ localesOptions() {
21
+ return Object.keys(this.availableLocales).map((value) => {
22
+ return {
23
+ label: this.t(`locale.${ value }`),
24
+ value
25
+ };
26
+ });
27
+ },
28
+
29
+ selectedOption() {
30
+ return Object.keys(this.availableLocales)[Object.values(this.availableLocales).indexOf(this.selectedLocaleLabel)];
31
+ },
32
+
10
33
  showLocale() {
11
34
  return (this.availableLocales && Object.keys(this.availableLocales).length > 1) || this.dev;
12
35
  },
@@ -17,42 +40,52 @@ export default {
17
40
  },
18
41
 
19
42
  methods: {
20
- switchLocale(locale) {
21
- this.$store.dispatch('i18n/switchTo', locale);
43
+ switchLocale($event) {
44
+ this.$store.dispatch('i18n/switchTo', $event);
22
45
  },
23
46
  }
24
47
  };
25
48
  </script>
26
49
 
27
50
  <template>
28
- <div v-if="showLocale">
29
- <v-popover
30
- popover-class="localeSelector"
31
- placement="top"
32
- trigger="click"
33
- >
34
- <a
35
- data-testid="locale-selector"
36
- class="locale-chooser"
37
- >
38
- {{ selectedLocaleLabel }}
39
- <i class="icon icon-fw icon-sort-down" />
40
- </a>
41
-
42
- <template slot="popover">
43
- <ul class="list-unstyled dropdown" style="margin: -1px;">
44
- <li v-if="showNone" v-t="'locale.none'" class="hand" @click="switchLocale('none')" />
45
- <li
46
- v-for="(label, name) in availableLocales"
47
- :key="name"
48
- class="hand"
49
- @click="switchLocale(name)"
51
+ <div>
52
+ <div v-if="mode === 'login'">
53
+ <div v-if="showLocale">
54
+ <v-popover
55
+ popover-class="localeSelector"
56
+ placement="top"
57
+ trigger="click"
58
+ >
59
+ <a
60
+ data-testid="locale-selector"
61
+ class="locale-chooser"
50
62
  >
51
- {{ label }}
52
- </li>
53
- </ul>
54
- </template>
55
- </v-popover>
63
+ {{ selectedLocaleLabel }}
64
+ <i class="icon icon-fw icon-sort-down" />
65
+ </a>
66
+ <template slot="popover">
67
+ <ul class="list-unstyled dropdown" style="margin: -1px;">
68
+ <li v-if="showNone" v-t="'locale.none'" class="hand" @click="switchLocale('none')" />
69
+ <li
70
+ v-for="(label, name) in availableLocales"
71
+ :key="name"
72
+ class="hand"
73
+ @click="switchLocale(name)"
74
+ >
75
+ {{ label }}
76
+ </li>
77
+ </ul>
78
+ </template>
79
+ </v-popover>
80
+ </div>
81
+ </div>
82
+ <div v-else>
83
+ <Select
84
+ :value="selectedOption"
85
+ :options="localesOptions"
86
+ @input="switchLocale($event)"
87
+ />
88
+ </div>
56
89
  </div>
57
90
  </template>
58
91
 
@@ -266,7 +266,7 @@ export default {
266
266
  await this.refreshSpoofedTypes(spoofedTypes);
267
267
  this.done();
268
268
  } catch (err) {
269
- this.error = err;
269
+ this.error = err.message || err;
270
270
  btnCB(false);
271
271
  }
272
272
  },
@@ -278,7 +278,7 @@ export default {
278
278
  await this.refreshSpoofedTypes(spoofedTypes);
279
279
  this.done();
280
280
  } catch (err) {
281
- this.error = err;
281
+ this.error = err.message || err;
282
282
  btnCB(false);
283
283
  }
284
284
  },
@@ -4,6 +4,7 @@ import Favorite from '@shell/components/nav/Favorite';
4
4
  import TypeDescription from '@shell/components/TypeDescription';
5
5
  import { get } from '@shell/utils/object';
6
6
  import { AS, _YAML } from '@shell/config/query-params';
7
+ import ResourceLoadingIndicator from './ResourceLoadingIndicator';
7
8
 
8
9
  /**
9
10
  * Resource List Masthead component.
@@ -15,6 +16,7 @@ export default {
15
16
  components: {
16
17
  Favorite,
17
18
  TypeDescription,
19
+ ResourceLoadingIndicator,
18
20
  },
19
21
  props: {
20
22
  resource: {
@@ -53,6 +55,20 @@ export default {
53
55
  type: String,
54
56
  default: null
55
57
  },
58
+ loadResources: {
59
+ type: Array,
60
+ default: () => []
61
+ },
62
+
63
+ loadIndeterminate: {
64
+ type: Boolean,
65
+ default: false
66
+ },
67
+
68
+ showIncrementalLoadingIndicator: {
69
+ type: Boolean,
70
+ default: false
71
+ },
56
72
 
57
73
  /**
58
74
  * Inherited global identifier prefix for tests
@@ -155,7 +171,11 @@ export default {
155
171
  <h1 class="m-0">
156
172
  {{ _typeDisplay }} <Favorite v-if="isExplorer" :resource="favoriteResource || resource" />
157
173
  </h1>
158
- <slot name="header"></slot>
174
+ <ResourceLoadingIndicator
175
+ v-if="showIncrementalLoadingIndicator"
176
+ :resources="loadResources"
177
+ :indeterminate="loadIndeterminate"
178
+ />
159
179
  </div>
160
180
  <div class="actions-container">
161
181
  <slot name="actions">
@@ -16,10 +16,6 @@ export default {
16
16
  indeterminate: {
17
17
  type: Boolean,
18
18
  default: false,
19
- },
20
- rows: {
21
- type: Array,
22
- default: undefined,
23
19
  }
24
20
  },
25
21
 
@@ -32,10 +28,6 @@ export default {
32
28
  computed: {
33
29
  // Count of rows - either from the data provided or from the rows for the first resource
34
30
  rowsCount() {
35
- if (this.rows) {
36
- return this.rows.length;
37
- }
38
-
39
31
  if (this.resources.length > 0) {
40
32
  const existingData = this.$store.getters[`${ this.inStore }/all`](this.resources[0]) || [];
41
33
 
@@ -3,7 +3,7 @@ import ResourceTable from '@shell/components/ResourceTable';
3
3
  import Loading from '@shell/components/Loading';
4
4
  import Masthead from './Masthead';
5
5
  import ResourceLoadingIndicator from './ResourceLoadingIndicator';
6
- import ResourceFetch, { TYPES_RESTRICTED } from '@shell/mixins/resource-fetch';
6
+ import ResourceFetch from '@shell/mixins/resource-fetch';
7
7
 
8
8
  export default {
9
9
  components: {
@@ -43,8 +43,8 @@ export default {
43
43
  if (component?.$loadingResources) {
44
44
  const { loadResources, loadIndeterminate } = component?.$loadingResources(this.$route, this.$store);
45
45
 
46
- this.loadResources = loadResources;
47
- this.loadIndeterminate = loadIndeterminate;
46
+ this.loadResources = loadResources || [resource];
47
+ this.loadIndeterminate = loadIndeterminate || false;
48
48
  }
49
49
  }
50
50
 
@@ -55,11 +55,7 @@ export default {
55
55
  return;
56
56
  }
57
57
 
58
- if (TYPES_RESTRICTED.includes(resource)) {
59
- this.rows = await this.$fetchType(resource);
60
- } else {
61
- this.rows = await store.dispatch(`${ inStore }/findAll`, { type: resource });
62
- }
58
+ await this.$fetchType(resource);
63
59
  }
64
60
  },
65
61
 
@@ -75,13 +71,10 @@ export default {
75
71
 
76
72
  const showMasthead = getters[`type-map/optionsFor`](resource).showListMasthead;
77
73
 
78
- const existingData = getters[`${ inStore }/all`](resource) || [];
79
-
80
74
  return {
81
75
  inStore,
82
76
  schema,
83
77
  hasListComponent,
84
- hasData: existingData.length > 0,
85
78
  showMasthead: showMasthead === undefined ? true : showMasthead,
86
79
  resource,
87
80
  // manual refresh
@@ -89,7 +82,6 @@ export default {
89
82
  watch: false,
90
83
  force: false,
91
84
  // Provided by fetch later
92
- rows: [],
93
85
  customTypeDisplay: null,
94
86
  // incremental loading
95
87
  loadResources: [resource],
@@ -111,10 +103,6 @@ export default {
111
103
  return this.$store.getters['type-map/groupByFor'](this.schema);
112
104
  },
113
105
 
114
- loading() {
115
- return this.hasData ? false : this.$fetchState.pending;
116
- },
117
-
118
106
  showIncrementalLoadingIndicator() {
119
107
  return this.perfConfig?.incrementalLoading?.enabled;
120
108
  }
@@ -142,18 +130,16 @@ export default {
142
130
  :type-display="customTypeDisplay"
143
131
  :schema="schema"
144
132
  :resource="resource"
133
+ :show-incremental-loading-indicator="showIncrementalLoadingIndicator"
134
+ :load-resources="loadResources"
135
+ :load-indeterminate="loadIndeterminate"
145
136
  >
146
- <template v-slot:header>
147
- <ResourceLoadingIndicator
148
- v-if="showIncrementalLoadingIndicator"
149
- :resources="loadResources"
150
- :indeterminate="loadIndeterminate"
151
- />
152
- </template>
153
137
  </Masthead>
154
138
  <div v-if="hasListComponent">
155
139
  <component
156
140
  :is="listComponent"
141
+ :incremental-loading-indicator="showIncrementalLoadingIndicator"
142
+ :rows="rows"
157
143
  v-bind="$data"
158
144
  />
159
145
  </div>
@@ -116,7 +116,12 @@ export default {
116
116
  getCustomDetailLink: {
117
117
  type: Function,
118
118
  default: null
119
- }
119
+ },
120
+
121
+ ignoreFilter: {
122
+ type: Boolean,
123
+ default: false
124
+ },
120
125
  },
121
126
 
122
127
  data() {
@@ -197,7 +202,7 @@ export default {
197
202
  const isAll = this.$store.getters['isAllNamespaces'];
198
203
 
199
204
  // If the resources isn't namespaced or we want ALL of them, there's nothing to do.
200
- if ( !this.isNamespaced || (isAll && !this.currentProduct?.hideSystemResources)) {
205
+ if ( !this.isNamespaced || (isAll && !this.currentProduct?.hideSystemResources) || this.ignoreFilter) {
201
206
  return this.rows || [];
202
207
  }
203
208
 
@@ -29,10 +29,12 @@ export default {
29
29
 
30
30
  <template>
31
31
  <div v-if="shown" class="simple-box" v-on="$listeners">
32
- <div v-if="title || canClose" class="top">
33
- <h2 v-if="title">
34
- {{ title }}
35
- </h2>
32
+ <div v-if="title || canClose || $slots.title" class="top">
33
+ <slot name="title">
34
+ <h2 v-if="title">
35
+ {{ title }}
36
+ </h2>
37
+ </slot>
36
38
  <div v-if="canClose || pref" class="close-button" @click="closeBox($event)">
37
39
  <i class="icon icon-close" />
38
40
  </div>
@@ -20,6 +20,11 @@ import actions from './actions';
20
20
  // Uncomment for table performance debugging
21
21
  // import tableDebug from './debug';
22
22
 
23
+ // Its quicker to render if we directly supply the components for the formatters
24
+ // rather than just the name of a global component - so create a map of the formatter comoponents
25
+ // NOTE: This is populated by a plugin (formatters.js) to avoid issues with plugins
26
+ export const FORMATTERS = {};
27
+
23
28
  export const COLUMN_BREAKPOINTS = {
24
29
  /**
25
30
  * Only show column if at tablet width or wider
@@ -35,19 +40,6 @@ export const COLUMN_BREAKPOINTS = {
35
40
  DESKTOP: 'desktop'
36
41
  };
37
42
 
38
- // Its quicker to render if we directly supply the components for the formatters
39
- // rather than just the name of a global component - so create a map of the formatter comoponents
40
- const FORMATTERS = {};
41
-
42
- const components = require.context('@shell/components/formatter', false, /[A-Z]\w+\.(vue)$/);
43
-
44
- components.keys().forEach((fileName) => {
45
- const componentConfig = components(fileName);
46
- const componentName = fileName.split('/').pop().split('.')[0];
47
-
48
- FORMATTERS[componentName] = componentConfig.default || componentConfig;
49
- });
50
-
51
43
  // @TODO:
52
44
  // Fixed header/scrolling
53
45
 
@@ -334,6 +326,7 @@ export default {
334
326
  clearTimeout(this._loadingDelayTimer);
335
327
  clearTimeout(this._liveColumnsTimer);
336
328
  clearTimeout(this._delayedColumnsTimer);
329
+ clearTimeout(this.manualRefreshTimer);
337
330
 
338
331
  const $main = $('main');
339
332
 
@@ -348,23 +341,18 @@ export default {
348
341
  descending(neu, old) {
349
342
  this.watcherUpdateLiveAndDelayed(neu, old);
350
343
  },
351
-
352
344
  searchQuery(neu, old) {
353
345
  this.watcherUpdateLiveAndDelayed(neu, old);
354
346
  },
355
-
356
347
  sortFields(neu, old) {
357
348
  this.watcherUpdateLiveAndDelayed(neu, old);
358
349
  },
359
-
360
350
  groupBy(neu, old) {
361
351
  this.watcherUpdateLiveAndDelayed(neu, old);
362
352
  },
363
-
364
353
  namespaces(neu, old) {
365
354
  this.watcherUpdateLiveAndDelayed(neu, old);
366
355
  },
367
-
368
356
  page(neu, old) {
369
357
  this.watcherUpdateLiveAndDelayed(neu, old);
370
358
  },
@@ -380,14 +368,19 @@ export default {
380
368
  immediate: true
381
369
  },
382
370
 
383
- isManualRefreshLoading(neu, old) {
384
- this.currentPhase = neu ? ASYNC_BUTTON_STATES.WAITING : ASYNC_BUTTON_STATES.ACTION;
371
+ isManualRefreshLoading: {
372
+ handler(neu, old) {
373
+ this.currentPhase = neu ? ASYNC_BUTTON_STATES.WAITING : ASYNC_BUTTON_STATES.ACTION;
385
374
 
386
- // setTimeout is needed so that this is pushed further back on the JS computing queue
387
- // because nextTick isn't enough to capture the DOM update for the manual refresh only scenario
388
- setTimeout(() => {
389
- this.watcherUpdateLiveAndDelayed(neu, old);
390
- }, 500);
375
+ // setTimeout is needed so that this is pushed further back on the JS computing queue
376
+ // because nextTick isn't enough to capture the DOM update for the manual refresh only scenario
377
+ if (old && !neu) {
378
+ this.manualRefreshTimer = setTimeout(() => {
379
+ this.watcherUpdateLiveAndDelayed(neu, old);
380
+ }, 1000);
381
+ }
382
+ },
383
+ immediate: true
391
384
  }
392
385
  },
393
386
 
@@ -36,6 +36,11 @@ export default {
36
36
  type: Boolean,
37
37
  default: false
38
38
  },
39
+ badge: {
40
+ default: 0,
41
+ required: false,
42
+ type: Number
43
+ },
39
44
  },
40
45
 
41
46
  data() {