@rancher/shell 0.1.2 → 0.1.3

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 (258) hide show
  1. package/assets/translations/en-us.yaml +27 -769
  2. package/assets/translations/zh-hans.yaml +8 -769
  3. package/components/ActionMenu.vue +3 -3
  4. package/components/CodeMirror.vue +6 -8
  5. package/components/CommunityLinks.vue +1 -1
  6. package/components/ContainerResourceLimit.vue +14 -0
  7. package/components/ExplorerMembers.vue +123 -0
  8. package/components/ExplorerProjectsNamespaces.vue +405 -0
  9. package/components/GrafanaDashboard.vue +17 -2
  10. package/components/LocaleSelector.vue +81 -0
  11. package/components/PromptModal.vue +2 -3
  12. package/components/ResourceList/index.vue +1 -1
  13. package/components/ResourceTable.vue +3 -6
  14. package/components/SingleClusterInfo.vue +1 -1
  15. package/components/SortableTable/index.vue +23 -20
  16. package/components/SortableTable/selection.js +1 -0
  17. package/components/auth/AzureWarning.vue +5 -1
  18. package/components/auth/Principal.vue +1 -1
  19. package/components/auth/RoleDetailEdit.vue +18 -11
  20. package/components/fleet/FleetRepos.vue +0 -2
  21. package/components/form/NameNsDescription.vue +4 -6
  22. package/components/form/NodeScheduling.vue +1 -1
  23. package/components/form/WorkloadPorts.vue +1 -1
  24. package/components/formatter/WorkloadHealthScale.vue +1 -1
  25. package/components/nav/Header.vue +9 -9
  26. package/components/nav/NamespaceFilter.vue +7 -4
  27. package/components/nav/TopLevelMenu.vue +6 -43
  28. package/components/nav/WindowManager/ContainerLogs.vue +1 -1
  29. package/config/product/harvester-manager.js +64 -2
  30. package/config/product/manager.js +9 -0
  31. package/config/settings.js +17 -71
  32. package/config/table-headers.js +0 -1
  33. package/config/types.js +5 -25
  34. package/core/plugin-routes.ts +34 -22
  35. package/core/plugin.ts +15 -3
  36. package/core/plugins-loader.js +2 -0
  37. package/core/plugins.js +79 -36
  38. package/core/types.ts +7 -1
  39. package/detail/provisioning.cattle.io.cluster.vue +13 -0
  40. package/detail/workload/index.vue +11 -5
  41. package/{components/dialog → dialog}/AddClusterMemberDialog.vue +0 -0
  42. package/{components/dialog → dialog}/AddCustomBadgeDialog.vue +0 -0
  43. package/{components/dialog → dialog}/AddProjectMemberDialog.vue +0 -0
  44. package/{components/dialog → dialog}/AddonConfigConfirmationDialog.vue +0 -0
  45. package/{components/dialog → dialog}/DrainNode.vue +0 -0
  46. package/{components/dialog → dialog}/ForceMachineRemoveDialog.vue +0 -0
  47. package/{components/dialog → dialog}/GenericPrompt.vue +0 -0
  48. package/{components/dialog → dialog}/RollbackWorkloadDialog.vue +0 -0
  49. package/{components/dialog → dialog}/RotateCertificatesDialog.vue +0 -0
  50. package/{components/dialog → dialog}/RotateEncryptionKeyDialog.vue +0 -0
  51. package/{components/dialog → dialog}/SaveAsRKETemplateDialog.vue +0 -0
  52. package/{components/dialog → dialog}/ScaleMachineDownDialog.vue +0 -0
  53. package/edit/auth/azuread.vue +20 -1
  54. package/edit/management.cattle.io.project.vue +2 -2
  55. package/edit/namespace.vue +17 -10
  56. package/edit/persistentvolumeclaim.vue +1 -0
  57. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +1 -1
  58. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +33 -5
  59. package/edit/service.vue +1 -1
  60. package/edit/workload/index.vue +363 -15
  61. package/edit/workload/mixins/workload.js +62 -7
  62. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +1 -0
  63. package/layouts/default.vue +52 -27
  64. package/layouts/error.vue +5 -1
  65. package/layouts/home.vue +6 -2
  66. package/list/harvesterhci.io.management.cluster.vue +74 -33
  67. package/list/namespace.vue +3 -5
  68. package/machine-config/amazonec2.vue +2 -0
  69. package/machine-config/harvester.vue +96 -49
  70. package/middleware/authenticated.js +56 -52
  71. package/mixins/form-validation.js +1 -1
  72. package/mixins/resource-fetch.js +3 -1
  73. package/models/fleet.cattle.io.bundle.js +26 -19
  74. package/models/harvesterhci.io.management.cluster.js +194 -5
  75. package/models/management.cattle.io.cluster.js +1 -1
  76. package/models/management.cattle.io.clusterroletemplatebinding.js +9 -0
  77. package/models/management.cattle.io.project.js +23 -2
  78. package/models/namespace.js +19 -3
  79. package/models/pod.js +19 -2
  80. package/models/provisioning.cattle.io.cluster.js +4 -0
  81. package/models/workload.js +4 -243
  82. package/models/workload.service.js +314 -0
  83. package/nuxt.config.js +11 -9
  84. package/package.json +3 -3
  85. package/pages/auth/login.vue +11 -2
  86. package/pages/auth/setup.vue +1 -1
  87. package/pages/c/_cluster/_product/members/index.vue +3 -93
  88. package/pages/c/_cluster/_product/projectsnamespaces.vue +6 -403
  89. package/pages/c/_cluster/settings/performance.vue +19 -16
  90. package/pages/fail-whale.vue +1 -10
  91. package/pages/index.vue +18 -4
  92. package/pages/plugins.vue +2 -2
  93. package/pages/prefs.vue +8 -6
  94. package/pkg/auto-import.js +44 -7
  95. package/pkg/dynamic-plugin-loader.js +28 -0
  96. package/pkg/import.js +2 -2
  97. package/pkg/model-loader-require.lib.js +3 -0
  98. package/pkg/vue.config.js +9 -6
  99. package/plugins/dashboard-store/model-loader-require.js +12 -0
  100. package/plugins/dashboard-store/model-loader.js +4 -1
  101. package/plugins/dashboard-store/resource-class.js +10 -3
  102. package/plugins/steve/actions.js +1 -1
  103. package/plugins/steve/index.js +6 -4
  104. package/plugins/steve/subscribe.js +34 -23
  105. package/rancher-components/Form/Checkbox/Checkbox.test.ts +77 -0
  106. package/rancher-components/Form/Checkbox/Checkbox.vue +12 -2
  107. package/scripts/build-pkg.sh +48 -2
  108. package/scripts/drone-build-pkg.sh +31 -0
  109. package/scripts/publish-shell.sh +10 -11
  110. package/scripts/serve-pkgs +17 -10
  111. package/store/catalog.js +3 -1
  112. package/store/i18n.js +16 -11
  113. package/store/index.js +4 -181
  114. package/store/prefs.js +30 -2
  115. package/store/type-map.js +16 -29
  116. package/utils/cluster.js +1 -1
  117. package/utils/custom-validators.js +1 -12
  118. package/utils/dynamic-importer.js +1 -1
  119. package/utils/validators/setting.js +0 -35
  120. package/components/FilterLabel.vue +0 -254
  121. package/components/HarvesterUpgradeProgressBarList.vue +0 -109
  122. package/components/VMConsoleBar.vue +0 -87
  123. package/components/dialog/harvester/AddHotplugModal.vue +0 -159
  124. package/components/dialog/harvester/BackupModal.vue +0 -117
  125. package/components/dialog/harvester/CloneTemplate.vue +0 -125
  126. package/components/dialog/harvester/EjectCDROMDialog.vue +0 -157
  127. package/components/dialog/harvester/ExportImageDialog.vue +0 -152
  128. package/components/dialog/harvester/MaintenanceDialog.vue +0 -94
  129. package/components/dialog/harvester/MigrationDialog.vue +0 -154
  130. package/components/dialog/harvester/RestoreDialog.vue +0 -153
  131. package/components/dialog/harvester/SupportBundle.vue +0 -217
  132. package/components/dialog/harvester/UnplugVolume.vue +0 -108
  133. package/components/form/SerialConsole/index.vue +0 -267
  134. package/components/formatter/AttachVMWithName.vue +0 -46
  135. package/components/formatter/CloudInitType.vue +0 -27
  136. package/components/formatter/HarvesterBackupTargetValidation.vue +0 -43
  137. package/components/formatter/HarvesterCPUUsed.vue +0 -122
  138. package/components/formatter/HarvesterDiskState.vue +0 -66
  139. package/components/formatter/HarvesterHostName.vue +0 -66
  140. package/components/formatter/HarvesterIpAddress.vue +0 -90
  141. package/components/formatter/HarvesterMemoryUsed.vue +0 -140
  142. package/components/formatter/HarvesterMigrationState.vue +0 -85
  143. package/components/formatter/HarvesterNodeName.vue +0 -49
  144. package/components/formatter/HarvesterStorageUsed.vue +0 -194
  145. package/components/formatter/HarvesterVmState.vue +0 -123
  146. package/components/nav/HarvesterUpgrade.vue +0 -232
  147. package/components/novnc/NovncConsole.vue +0 -93
  148. package/components/novnc/NovncConsoleItem.vue +0 -89
  149. package/components/novnc/NovncConsoleWrapper.vue +0 -243
  150. package/config/harvester-map.js +0 -44
  151. package/config/harvester-table-headers.js +0 -27
  152. package/config/product/harvester.js +0 -305
  153. package/detail/harvesterhci.io.host/HarvesterHostBasic.vue +0 -364
  154. package/detail/harvesterhci.io.host/HarvesterHostDisk.vue +0 -200
  155. package/detail/harvesterhci.io.host/HarvesterHostNetwork.vue +0 -89
  156. package/detail/harvesterhci.io.host/VirtualMachineInstance.vue +0 -134
  157. package/detail/harvesterhci.io.host/index.vue +0 -243
  158. package/detail/harvesterhci.io.virtualmachinebackup/index.vue +0 -221
  159. package/detail/harvesterhci.io.virtualmachineimage.vue +0 -118
  160. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineBasics.vue +0 -279
  161. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineEvents.vue +0 -75
  162. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineKeypairs.vue +0 -114
  163. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineMigration.vue +0 -79
  164. package/detail/kubevirt.io.virtualmachine/index.vue +0 -213
  165. package/edit/harvesterhci.io.cloudtemplate.vue +0 -123
  166. package/edit/harvesterhci.io.host/HarvesterDisk.vue +0 -262
  167. package/edit/harvesterhci.io.host/index.vue +0 -533
  168. package/edit/harvesterhci.io.keypair.vue +0 -112
  169. package/edit/harvesterhci.io.managedchart/index.vue +0 -25
  170. package/edit/harvesterhci.io.managedchart/rancher-monitoring.vue +0 -172
  171. package/edit/harvesterhci.io.networkattachmentdefinition.vue +0 -210
  172. package/edit/harvesterhci.io.setting/additional-ca.vue +0 -36
  173. package/edit/harvesterhci.io.setting/backup-target.vue +0 -182
  174. package/edit/harvesterhci.io.setting/http-proxy.vue +0 -79
  175. package/edit/harvesterhci.io.setting/index.vue +0 -201
  176. package/edit/harvesterhci.io.setting/overcommit-config.vue +0 -94
  177. package/edit/harvesterhci.io.setting/ssl-certificates.vue +0 -117
  178. package/edit/harvesterhci.io.setting/ssl-parameters.vue +0 -161
  179. package/edit/harvesterhci.io.setting/support-bundle-image.vue +0 -134
  180. package/edit/harvesterhci.io.setting/support-bundle-namespaces.vue +0 -73
  181. package/edit/harvesterhci.io.setting/vip-pools.vue +0 -244
  182. package/edit/harvesterhci.io.setting/vm-force-reset-policy.vue +0 -81
  183. package/edit/harvesterhci.io.virtualmachinebackup.vue +0 -256
  184. package/edit/harvesterhci.io.virtualmachineimage.vue +0 -364
  185. package/edit/harvesterhci.io.virtualmachinetemplateversion.vue +0 -340
  186. package/edit/harvesterhci.io.volume.vue +0 -195
  187. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/AccessCredentialsUsers.vue +0 -190
  188. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/index.vue +0 -212
  189. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/basicAuth.vue +0 -94
  190. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/sshkey.vue +0 -85
  191. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/DataTemplate.vue +0 -153
  192. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/index.vue +0 -279
  193. package/edit/kubevirt.io.virtualmachine/VirtualMachineCpuMemory.vue +0 -113
  194. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/__tests__/HarvesterEditNetwork.test.ts +0 -41
  195. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/base.vue +0 -281
  196. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/index.vue +0 -142
  197. package/edit/kubevirt.io.virtualmachine/VirtualMachineReserved.vue +0 -54
  198. package/edit/kubevirt.io.virtualmachine/VirtualMachineSSHKey.vue +0 -256
  199. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/index.vue +0 -391
  200. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditContainer.test.ts +0 -40
  201. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditExisting.test.ts +0 -102
  202. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVMImage.test.ts +0 -117
  203. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVolume.test.ts +0 -74
  204. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue +0 -132
  205. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/existing.vue +0 -303
  206. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue +0 -285
  207. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue +0 -188
  208. package/edit/kubevirt.io.virtualmachine/index.vue +0 -642
  209. package/edit/network.harvesterhci.io.clusternetwork/index.vue +0 -19
  210. package/edit/network.harvesterhci.io.clusternetwork/vlan.vue +0 -134
  211. package/edit/workload/types/Deployment.vue +0 -377
  212. package/edit/workload/types/Generic.vue +0 -295
  213. package/list/harvesterhci.io.cloudtemplate.vue +0 -78
  214. package/list/harvesterhci.io.dashboard/HarvesterUpgrade.vue +0 -211
  215. package/list/harvesterhci.io.dashboard/UpgradeInfo.vue +0 -40
  216. package/list/harvesterhci.io.dashboard/index.vue +0 -752
  217. package/list/harvesterhci.io.host/index.vue +0 -186
  218. package/list/harvesterhci.io.networkattachmentdefinition.vue +0 -167
  219. package/list/harvesterhci.io.setting.vue +0 -241
  220. package/list/harvesterhci.io.virtualmachinebackup.vue +0 -172
  221. package/list/harvesterhci.io.virtualmachineimage.vue +0 -80
  222. package/list/harvesterhci.io.virtualmachinetemplateversion.vue +0 -173
  223. package/list/harvesterhci.io.volume.vue +0 -122
  224. package/list/kubevirt.io.virtualmachine.vue +0 -193
  225. package/mixins/harvester-vm/impl.js +0 -267
  226. package/mixins/harvester-vm/index.js +0 -1357
  227. package/models/harvester/configmap.js +0 -32
  228. package/models/harvester/harvesterhci.io.blockdevice.js +0 -55
  229. package/models/harvester/harvesterhci.io.keypair.js +0 -12
  230. package/models/harvester/harvesterhci.io.setting.js +0 -127
  231. package/models/harvester/harvesterhci.io.supportbundle.js +0 -35
  232. package/models/harvester/harvesterhci.io.upgrade.js +0 -226
  233. package/models/harvester/harvesterhci.io.virtualmachinebackup.js +0 -116
  234. package/models/harvester/harvesterhci.io.virtualmachineimage.js +0 -255
  235. package/models/harvester/harvesterhci.io.virtualmachinerestore.js +0 -43
  236. package/models/harvester/harvesterhci.io.virtualmachinetemplate.js +0 -69
  237. package/models/harvester/harvesterhci.io.virtualmachinetemplateversion.js +0 -227
  238. package/models/harvester/k8s.cni.cncf.io.networkattachmentdefinition.js +0 -32
  239. package/models/harvester/kubevirt.io.virtualmachine.js +0 -850
  240. package/models/harvester/kubevirt.io.virtualmachineinstance.js +0 -142
  241. package/models/harvester/management.cattle.io.managedchart.js +0 -191
  242. package/models/harvester/management.cattle.io.setting.js +0 -40
  243. package/models/harvester/network.harvesterhci.io.clusternetwork.js +0 -100
  244. package/models/harvester/network.harvesterhci.io.nodenetwork.js +0 -34
  245. package/models/harvester/node.js +0 -255
  246. package/models/harvester/persistentvolumeclaim.js +0 -166
  247. package/models/harvester/pod.js +0 -185
  248. package/pages/c/_cluster/harvester/airgapupgrade/index.vue +0 -309
  249. package/pages/c/_cluster/harvester/console/_uid/serial.vue +0 -51
  250. package/pages/c/_cluster/harvester/console/_uid/vnc.vue +0 -52
  251. package/pages/c/_cluster/harvester/index.vue +0 -24
  252. package/pages/c/_cluster/harvester/support/index.vue +0 -154
  253. package/pkg/model-loader.lib.js +0 -3
  254. package/promptRemove/kubevirt.io.virtualmachine.vue +0 -164
  255. package/store/harvester-common.js +0 -126
  256. package/utils/validators/vm-datavolumes.js +0 -38
  257. package/utils/validators/vm-image.js +0 -32
  258. package/utils/validators/vm.js +0 -221
@@ -1,403 +1,6 @@
1
- <script>
2
- import ResourceTable from '@shell/components/ResourceTable';
3
- import { STATE, AGE, NAME } from '@shell/config/table-headers';
4
- import { uniq } from '@shell/utils/array';
5
- import { MANAGEMENT, NAMESPACE, VIRTUAL_TYPES } from '@shell/config/types';
6
- import Loading from '@shell/components/Loading';
7
- import { PROJECT_ID } from '@shell/config/query-params';
8
- import Masthead from '@shell/components/ResourceList/Masthead';
9
- import { mapPref, GROUP_RESOURCES, DEV } from '@shell/store/prefs';
10
- import MoveModal from '@shell/components/MoveModal';
11
- import { defaultTableSortGenerationFn } from '@shell/components/ResourceTable.vue';
12
- import { NAMESPACE_FILTER_ALL_ORPHANS } from '@shell/utils/namespace-filter';
13
- import { mapGetters } from 'vuex';
14
-
15
- export default {
16
- name: 'ListNamespace',
17
- components: {
18
- Loading, Masthead, MoveModal, ResourceTable
19
- },
20
-
21
- props: {},
22
-
23
- async fetch() {
24
- const inStore = this.$store.getters['currentStore'](NAMESPACE);
25
-
26
- this.schema = this.$store.getters[`${ inStore }/schemaFor`](NAMESPACE);
27
- this.projectSchema = this.$store.getters[`management/schemaFor`](MANAGEMENT.PROJECT);
28
-
29
- if ( !this.schema ) {
30
- // clusterReady: When switching routes, it will cause clusterReady to change, causing itself to repeat rendering。
31
- // this.$store.dispatch('loadingError', `Type ${ NAMESPACE } not found`);
32
-
33
- return;
34
- }
35
-
36
- this.namespaces = await this.$store.dispatch(`${ inStore }/findAll`, { type: NAMESPACE });
37
- this.projects = await this.$store.dispatch('management/findAll', { type: MANAGEMENT.PROJECT, opt: { force: true } });
38
- },
39
-
40
- data() {
41
- return {
42
- schema: null,
43
- namespaces: [],
44
- projects: [],
45
- projectSchema: null,
46
- MANAGEMENT,
47
- VIRTUAL_TYPES
48
- };
49
- },
50
-
51
- computed: {
52
- ...mapGetters(['currentCluster']),
53
-
54
- isNamespaceCreatable() {
55
- return (this.schema?.collectionMethods || []).includes('POST');
56
- },
57
- headers() {
58
- const project = {
59
- name: 'project',
60
- label: 'Project',
61
- value: 'project.nameDisplay',
62
- sort: ['projectNameSort', 'nameSort'],
63
- };
64
-
65
- return [
66
- STATE,
67
- NAME,
68
- this.groupPreference === 'none' ? project : null,
69
- AGE
70
- ].filter(h => h);
71
- },
72
- projectIdsWithNamespaces() {
73
- const ids = this.rows
74
- .map(row => row.projectId)
75
- .filter(id => id);
76
-
77
- return uniq(ids);
78
- },
79
- clusterProjects() {
80
- const clusterId = this.$store.getters['currentCluster'].id;
81
-
82
- // Get the list of projects from the store so that the list
83
- // is updated if a new project is created or removed.
84
- const projectsInAllClusters = this.$store.getters['management/all'](MANAGEMENT.PROJECT);
85
-
86
- const clustersInProjects = projectsInAllClusters.filter(project => project.spec.clusterName === clusterId);
87
-
88
- return clustersInProjects;
89
- },
90
- projectsWithoutNamespaces() {
91
- return this.activeProjects.filter((project) => {
92
- return !this.projectIdsWithNamespaces.find(item => project?.id?.endsWith(`/${ item }`));
93
- });
94
- },
95
- // We're using this because we need to show projects as groups even if the project doesn't have any namespaces.
96
- rowsWithFakeNamespaces() {
97
- const fakeRows = this.projectsWithoutNamespaces.map((project) => {
98
- return {
99
- groupByLabel: `${ ('resourceTable.groupLabel.notInAProject') }-${ project.id }`,
100
- isFake: true,
101
- mainRowKey: project.id,
102
- nameDisplay: project.spec?.displayName, // Enable filtering by the project name
103
- project,
104
- availableActions: []
105
- };
106
- });
107
-
108
- if (this.showMockNotInProjectGroup) {
109
- fakeRows.push( {
110
- groupByLabel: this.t('resourceTable.groupLabel.notInAProject'), // Same as the groupByLabel for the namespace model
111
- mainRowKey: 'fake-empty',
112
- });
113
- }
114
-
115
- return [...this.rows, ...fakeRows];
116
- },
117
- createProjectLocation() {
118
- return {
119
- name: 'c-cluster-product-resource-create',
120
- params: {
121
- product: this.$store.getters['currentProduct'].name,
122
- resource: MANAGEMENT.PROJECT
123
- },
124
- };
125
- },
126
- groupPreference: mapPref(GROUP_RESOURCES),
127
- activeNamespaceFilters() {
128
- return this.$store.getters['activeNamespaceFilters'];
129
- },
130
- activeProjectFilters() {
131
- const activeProjects = {};
132
-
133
- for (const filter of this.activeNamespaceFilters) {
134
- const [type, id] = filter.split('://', 2);
135
-
136
- if (type === 'project') {
137
- activeProjects[id] = true;
138
- }
139
- }
140
-
141
- return activeProjects;
142
- },
143
- activeProjects() {
144
- const namespaceFilters = this.$store.getters['activeNamespaceFilters'];
145
-
146
- if (namespaceFilters.includes(NAMESPACE_FILTER_ALL_ORPHANS) && Object.keys(this.activeProjectFilters).length === 0) {
147
- // If the user wants to only see namespaces that are not
148
- // in a project, don't show any projects.
149
- return [];
150
- }
151
-
152
- // If the user is not filtering by any projects or namespaces, return
153
- // all projects in the cluster.
154
- if (!this.userIsFilteringForSpecificNamespaceOrProject()) {
155
- return this.clusterProjects;
156
- }
157
-
158
- // Filter out projects that are not selected in the top nav.
159
- return this.clusterProjects.filter((projectData) => {
160
- const projectId = projectData.id.split('/')[1];
161
-
162
- return !!this.activeProjectFilters[projectId];
163
- });
164
- },
165
- activeNamespaces() {
166
- // Apply namespace filters from the top nav.
167
- const activeNamespaces = this.$store.getters['namespaces']();
168
-
169
- return this.namespaces.filter((namespaceData) => {
170
- return !!activeNamespaces[namespaceData.metadata.name];
171
- });
172
- },
173
- filteredRows() {
174
- return this.groupPreference === 'none' ? this.rows : this.rowsWithFakeNamespaces;
175
- },
176
- rows() {
177
- if (this.$store.getters['prefs/get'](DEV)) {
178
- // If developer tools are turned on in the user preferences,
179
- // return all namespaces including system namespaces and RBAC
180
- // management namespaces.
181
- return this.activeNamespaces;
182
- }
183
-
184
- const isVirtualCluster = this.$store.getters['isVirtualCluster'];
185
-
186
- return this.activeNamespaces.filter((namespace) => {
187
- const isSettingSystemNamespace = this.$store.getters['systemNamespaces'].includes(namespace.metadata.name);
188
-
189
- const systemNS = namespace.isSystem || namespace.isFleetManaged || isSettingSystemNamespace;
190
-
191
- // For Harvester, filter out system namespaces AND obscure namespaces.
192
- if (isVirtualCluster) {
193
- return !systemNS && !namespace.isObscure;
194
- }
195
-
196
- // Otherwise only filter out obscure namespaces, such as namespaces
197
- // that Rancher uses to manage RBAC for projects, which should not be
198
- // edited or deleted by Rancher users.
199
- return !namespace.isObscure;
200
- });
201
- },
202
-
203
- canSeeProjectlessNamespaces() {
204
- return this.currentCluster.canUpdate;
205
- },
206
-
207
- showMockNotInProjectGroup() {
208
- if (!this.canSeeProjectlessNamespaces) {
209
- return false;
210
- }
211
-
212
- const someNamespacesAreNotInProject = !this.rows.some(row => !row.project);
213
-
214
- // Hide the "Not in a Project" group if the user is filtering
215
- // for specific namespaces or projects.
216
- const usingSpecificFilter = this.userIsFilteringForSpecificNamespaceOrProject();
217
-
218
- return !usingSpecificFilter && someNamespacesAreNotInProject;
219
- },
220
-
221
- notInProjectKey() {
222
- return this.$store.getters['i18n/t']('resourceTable.groupLabel.notInAProject');
223
- }
224
- },
225
- methods: {
226
- userIsFilteringForSpecificNamespaceOrProject() {
227
- const activeFilters = this.$store.getters['namespaceFilters'];
228
-
229
- for (let i = 0; i < activeFilters.length; i++) {
230
- const filter = activeFilters[i];
231
- const filterType = filter.split('://')[0];
232
-
233
- if (filterType === 'ns' || filterType === 'project') {
234
- return true;
235
- }
236
- }
237
-
238
- return false;
239
- },
240
- slotName(project) {
241
- return `main-row:${ project.id }`;
242
- },
243
- createNamespaceLocation(group) {
244
- const project = group.rows[0].project;
245
-
246
- return {
247
- name: 'c-cluster-product-resource-create',
248
- params: {
249
- product: this.$store.getters['currentProduct'].name,
250
- resource: NAMESPACE
251
- },
252
- query: { [PROJECT_ID]: project?.metadata.name }
253
- };
254
- },
255
- showProjectAction(event, group) {
256
- const project = group.rows[0].project;
257
-
258
- this.$store.commit(`action-menu/show`, {
259
- resources: [project],
260
- elem: event.target
261
- });
262
- },
263
- showProjectActionButton(group) {
264
- const project = group.rows[0].project;
265
-
266
- return !!project;
267
- },
268
- projectLabel(group) {
269
- const row = group.rows[0];
270
-
271
- if (row.isFake) {
272
- return this.t('resourceTable.groupLabel.project', { name: row.project?.nameDisplay }, true);
273
- }
274
-
275
- return row.groupByLabel;
276
- },
277
-
278
- projectDescription(group) {
279
- const project = group.rows[0].project;
280
-
281
- return project?.description;
282
- },
283
-
284
- clearSelection() {
285
- this.$refs.table.clearSelection();
286
- },
287
-
288
- sortGenerationFn() {
289
- // The sort generation function creates a unique value and is used to create a key including sort details.
290
- // The unique key determines if the list is redrawn or a cached version is shown.
291
- // Because we ensure the 'not in a project' group is there via a row, and timing issues, the unqiue key doesn't change
292
- // after a namespace is removed... so the list won't update... so we need to inject a string to ensure the key is fresh
293
- const base = defaultTableSortGenerationFn(this.schema, this.$store);
294
-
295
- return base + (this.showMockNotInProjectGroup ? '-mock' : '');
296
- },
297
-
298
- }
299
- };
300
- </script>
301
-
302
- <template>
303
- <Loading v-if="$fetchState.pending" />
304
- <div v-else class="project-namespaces">
305
- <Masthead
306
- :schema="projectSchema"
307
- :type-display="t('projectNamespaces.label')"
308
- :resource="MANAGEMENT.PROJECT"
309
- :favorite-resource="VIRTUAL_TYPES.PROJECT_NAMESPACES"
310
- :create-location="createProjectLocation"
311
- :create-button-label="t('projectNamespaces.createProject')"
312
- />
313
- <ResourceTable
314
- ref="table"
315
- class="table"
316
- v-bind="$attrs"
317
- :schema="schema"
318
- :headers="headers"
319
- :rows="filteredRows"
320
- :groupable="true"
321
- :sort-generation-fn="sortGenerationFn"
322
- group-tooltip="resourceTable.groupBy.project"
323
- key-field="_key"
324
- v-on="$listeners"
325
- >
326
- <template #group-by="group">
327
- <div class="project-bar" :class="{'has-description': projectDescription(group.group)}">
328
- <div v-trim-whitespace class="group-tab">
329
- <div class="project-name" v-html="projectLabel(group.group)" />
330
- <div v-if="projectDescription(group.group)" class="description text-muted text-small">
331
- {{ projectDescription(group.group) }}
332
- </div>
333
- </div>
334
- <div class="right">
335
- <n-link
336
- v-if="isNamespaceCreatable && (canSeeProjectlessNamespaces || group.group.key !== notInProjectKey)"
337
- class="create-namespace btn btn-sm role-secondary mr-5"
338
- :to="createNamespaceLocation(group.group)"
339
- >
340
- {{ t('projectNamespaces.createNamespace') }}
341
- </n-link>
342
- <button type="button" class="project-action btn btn-sm role-multi-action actions mr-10" :class="{invisible: !showProjectActionButton(group.group)}" @click="showProjectAction($event, group.group)">
343
- <i class="icon icon-actions" />
344
- </button>
345
- </div>
346
- </div>
347
- </template>
348
- <template #cell:project="{row}">
349
- <span v-if="row.project">{{ row.project.nameDisplay }}</span>
350
- <span v-else class="text-muted">&ndash;</span>
351
- </template>
352
- <template v-for="project in projectsWithoutNamespaces" v-slot:[slotName(project)]>
353
- <tr :key="project.id" class="main-row">
354
- <td class="empty text-center" colspan="5">
355
- {{ t('projectNamespaces.noNamespaces') }}
356
- </td>
357
- </tr>
358
- </template>
359
- <template #main-row:fake-empty>
360
- <tr class="main-row">
361
- <td class="empty text-center" colspan="5">
362
- {{ t('projectNamespaces.noProjectNoNamespaces') }}
363
- </td>
364
- </tr>
365
- </template>
366
- </ResourceTable>
367
- <MoveModal @moving="clearSelection" />
368
- </div>
369
- </template>
370
- <style lang="scss" scoped>
371
- .project-namespaces {
372
- & ::v-deep {
373
- .project-name {
374
- line-height: 30px;
375
- }
376
-
377
- .project-bar {
378
- display: flex;
379
- flex-direction: row;
380
- justify-content: space-between;
381
-
382
- &.has-description {
383
- .right {
384
- margin-top: 5px;
385
- }
386
- .group-tab {
387
- &, &::after {
388
- height: 50px;
389
- }
390
-
391
- &::after {
392
- right: -20px;
393
- }
394
-
395
- .description {
396
- margin-top: -20px;
397
- }
398
- }
399
- }
400
- }
401
- }
402
- }
403
- </style>
1
+ <script>
2
+ import ExplorerProjectsNamespaces from '@shell/components/ExplorerProjectsNamespaces';
3
+ export default { components: { ExplorerProjectsNamespaces } };
4
+ </script>
5
+
6
+ <template><ExplorerProjectsNamespaces v-bind="$attrs" /></template>
@@ -5,18 +5,8 @@ import AsyncButton from '@shell/components/AsyncButton';
5
5
  import { Banner } from '@components/Banner';
6
6
  import { LabeledInput } from '@components/Form/LabeledInput';
7
7
  import { MANAGEMENT } from '@shell/config/types';
8
- import { SETTING } from '@shell/config/settings';
8
+ import { DEFAULT_PERF_SETTING, SETTING } from '@shell/config/settings';
9
9
  import { _EDIT, _VIEW } from '@shell/config/query-params';
10
- const DEFAULT_PERF_SETTING = {
11
- incrementalLoading: {
12
- enabled: false,
13
- threshold: 2500,
14
- },
15
- manualRefresh: {
16
- enabled: false,
17
- threshold: 2500,
18
- }
19
- };
20
10
 
21
11
  export default {
22
12
  layout: 'authenticated',
@@ -27,6 +17,7 @@ export default {
27
17
  Banner,
28
18
  LabeledInput,
29
19
  },
20
+
30
21
  async fetch() {
31
22
  try {
32
23
  this.uiPerfSetting = await this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.UI_PERFORMANCE });
@@ -41,6 +32,7 @@ export default {
41
32
 
42
33
  this.value = JSON.parse(sValue);
43
34
  },
35
+
44
36
  data() {
45
37
  return {
46
38
  uiPerfSetting: DEFAULT_PERF_SETTING,
@@ -49,6 +41,7 @@ export default {
49
41
  errors: [],
50
42
  };
51
43
  },
44
+
52
45
  computed: {
53
46
  mode() {
54
47
  const schema = this.$store.getters[`management/schemaFor`](MANAGEMENT.SETTING);
@@ -56,10 +49,12 @@ export default {
56
49
  return schema?.resourceMethods?.includes('PUT') ? _EDIT : _VIEW;
57
50
  },
58
51
  },
52
+
59
53
  methods: {
60
54
  async save(btnCB) {
61
55
  this.uiPerfSetting.value = JSON.stringify(this.value);
62
56
  this.errors = [];
57
+
63
58
  try {
64
59
  await this.uiPerfSetting.save();
65
60
  btnCB(true);
@@ -78,12 +73,19 @@ export default {
78
73
  {{ t('performance.label') }}
79
74
  </h1>
80
75
  <div>
81
- <label class="text-label">
82
- {{ t(`performance.description`, {}, true) }}
83
- </label>
84
- <Banner color="error" label-key="performance.banner" />
85
- <!-- Incremental Loading -->
86
76
  <div class="ui-perf-setting">
77
+ <!-- Websocket Notifications -->
78
+ <div class="mt-40">
79
+ <h2>{{ t('performance.websocketNotification.label') }}</h2>
80
+ <p>{{ t('performance.websocketNotification.description') }}</p>
81
+ <Checkbox
82
+ v-model="value.disableWebsocketNotification"
83
+ :label="t('performance.websocketNotification.checkboxLabel')"
84
+ class="mt-10 mb-20"
85
+ :primary="true"
86
+ />
87
+ </div>
88
+ <!-- Incremental Loading -->
87
89
  <div class="mt-40">
88
90
  <h2>{{ t('performance.incrementalLoad.label') }}</h2>
89
91
  <p>{{ t('performance.incrementalLoad.description') }}</p>
@@ -111,6 +113,7 @@ export default {
111
113
  <div class="mt-40">
112
114
  <h2 v-t="'performance.manualRefresh.label'" />
113
115
  <p>{{ t('performance.manualRefresh.description') }}</p>
116
+ <Banner color="error" label-key="performance.manualRefresh.banner" />
114
117
  <Checkbox
115
118
  v-model="value.manualRefresh.enabled"
116
119
  :label="t('performance.manualRefresh.checkboxLabel')"
@@ -2,8 +2,6 @@
2
2
  import BrandImage from '@shell/components/BrandImage';
3
3
  import { mapGetters, mapState } from 'vuex';
4
4
  import { stringify } from '@shell/utils/error';
5
- import { getVendor } from '@shell/config/private-label';
6
- import { NAME as HARVESTER } from '@shell/config/product/harvester';
7
5
 
8
6
  export default {
9
7
  layout: 'home',
@@ -13,7 +11,7 @@ export default {
13
11
  data() {
14
12
  const store = this.$store;
15
13
 
16
- if ( process.client && !store.state.error && !store.state.cameFromError) {
14
+ if (!store.state.error && !store.state.cameFromError) {
17
15
  store.commit('cameFromError');
18
16
  this.$router.replace('/');
19
17
  }
@@ -29,13 +27,6 @@ export default {
29
27
  ...mapGetters(['isSingleProduct']),
30
28
 
31
29
  home() {
32
- const isOnlyHarvester = getVendor() === HARVESTER;
33
-
34
- if (isOnlyHarvester) {
35
- // This looks like it's covered by `isSingleProduct?.afterLoginRoute` too
36
- return 'c/local/harvester/harvesterhci.io.dashboard';
37
- }
38
-
39
30
  if (this.isSingleProduct?.afterLoginRoute) {
40
31
  return this.$router.resolve(this.isSingleProduct.afterLoginRoute).href;
41
32
  }
package/pages/index.vue CHANGED
@@ -2,21 +2,35 @@
2
2
  import { SEEN_WHATS_NEW } from '@shell/store/prefs';
3
3
  import { getVersionInfo } from '@shell/utils/version';
4
4
 
5
+ const validRoute = (route, router) => {
6
+ return !!route && !!router.resolve(route)?.resolved?.matched?.length;
7
+ };
8
+
5
9
  export default {
6
- middleware({ redirect, store } ) {
10
+ middleware({ redirect, store, app } ) {
7
11
  const seenWhatsNew = store.getters['prefs/get'](SEEN_WHATS_NEW);
8
12
  const versionInfo = getVersionInfo(store);
9
13
  const isSingleProduct = store.getters['isSingleProduct'];
14
+ const dashboardHome = { name: 'home' };
10
15
 
11
16
  // If this is a new version, then take the user to the home page to view the release notes
12
17
  if (versionInfo.fullVersion !== seenWhatsNew && !isSingleProduct) {
13
- return redirect({ name: 'home' });
18
+ return redirect(dashboardHome);
14
19
  }
15
20
 
16
- // Take the user to the configured login route
17
21
  const afterLoginRouteObject = store.getters['prefs/afterLoginRoute'];
18
22
 
19
- return redirect(afterLoginRouteObject);
23
+ // Confirm this is a valid route (it could have come from an uninstalled plugin)
24
+ if (validRoute(afterLoginRouteObject, app.router)) {
25
+ // Take the user to the configured login route
26
+ return redirect(afterLoginRouteObject);
27
+ }
28
+
29
+ if (validRoute(isSingleProduct?.afterLoginRoute, app.router)) {
30
+ return redirect(isSingleProduct.afterLoginRoute);
31
+ }
32
+
33
+ return redirect(dashboardHome);
20
34
  }
21
35
  };
22
36
  </script>
package/pages/plugins.vue CHANGED
@@ -242,7 +242,7 @@ export default {
242
242
  <LabeledInput v-model="location" label="Plugin URL" @input="updateLocation" />
243
243
  </div>
244
244
  <div class="dialog-buttons">
245
- <button class="btn" @click="closeAddDialog()">
245
+ <button class="btn role-secondary" @click="closeAddDialog()">
246
246
  Cancel
247
247
  </button>
248
248
  <button class="btn role-primary" @click="loadPlugin()">
@@ -268,7 +268,7 @@ export default {
268
268
  <LabeledInput v-model="catalogUrl" label="Catalog URL" />
269
269
  </div>
270
270
  <div class="dialog-buttons">
271
- <button class="btn" @click="closeAddCatalogDialog()">
271
+ <button class="btn role-secondary" @click="closeAddCatalogDialog()">
272
272
  Cancel
273
273
  </button>
274
274
  <button class="btn role-primary" @click="addCatalog()">
package/pages/prefs.vue CHANGED
@@ -159,8 +159,11 @@ export default {
159
159
  <LandingPagePreference />
160
160
  </div>
161
161
  <hr />
162
- <h4 v-t="'prefs.formatting'" />
163
- <div class="row">
162
+ <h4 v-t="'prefs.displaySettings.title'" />
163
+ <p class="set-landing-leadin">
164
+ {{ t('prefs.displaySettings.detail', {}, raw=true) }}
165
+ </p>
166
+ <div class="row mt-20">
164
167
  <div class="col span-4">
165
168
  <LabeledSelect
166
169
  v-model="dateFormat"
@@ -175,7 +178,9 @@ export default {
175
178
  :options="timeOptions"
176
179
  />
177
180
  </div>
181
+ </div>
178
182
 
183
+ <div class="row mt-20">
179
184
  <div class="col span-4">
180
185
  <LabeledSelect
181
186
  v-model.number="perPage"
@@ -186,9 +191,6 @@ export default {
186
191
  placeholder="Select a row count"
187
192
  />
188
193
  </div>
189
- </div>
190
-
191
- <div class="row mt-20">
192
194
  <div class="col span-4">
193
195
  <LabeledSelect
194
196
  v-model.number="menuMaxClusters"
@@ -207,7 +209,7 @@ export default {
207
209
  <h4 v-t="'prefs.advanced'" />
208
210
  <Checkbox v-model="dev" :label="t('prefs.dev.label', {}, true)" />
209
211
  <p class="wrap-text">
210
- {{ t('prefs.advancedTooltip', {}, raw=true) }}
212
+ {{ t('prefs.advancedTooltip') }}
211
213
  </p>
212
214
  <br>
213
215
  <Checkbox v-if="!isSingleProduct" v-model="hideDescriptions" :label="t('prefs.hideDesc.label')" class="mt-10" />