@rancher/shell 0.1.2 → 0.1.4

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 (347) hide show
  1. package/assets/brand/suse/dark/rancher-logo.svg +1 -148
  2. package/assets/brand/suse/rancher-logo.svg +1 -130
  3. package/assets/images/featured/img1.jpg +0 -0
  4. package/assets/images/featured.jpg +0 -0
  5. package/assets/images/generic-plugin.svg +7 -0
  6. package/assets/styles/themes/_dark.scss +3 -0
  7. package/assets/styles/themes/_light.scss +3 -0
  8. package/assets/styles/themes/_suse.scss +1 -1
  9. package/assets/translations/en-us.yaml +209 -813
  10. package/assets/translations/zh-hans.yaml +28 -792
  11. package/components/ActionMenu.vue +3 -3
  12. package/components/AsyncButton.vue +17 -2
  13. package/components/ButtonDropdown.vue +4 -0
  14. package/components/Carousel.vue +291 -0
  15. package/components/CodeMirror.vue +6 -8
  16. package/components/CommunityLinks.vue +70 -19
  17. package/components/ContainerResourceLimit.vue +14 -0
  18. package/components/CruResource.vue +11 -3
  19. package/components/Dialog.vue +102 -0
  20. package/components/ExplorerMembers.vue +121 -0
  21. package/components/ExplorerProjectsNamespaces.vue +404 -0
  22. package/components/GrafanaDashboard.vue +17 -2
  23. package/components/IconMessage.vue +9 -1
  24. package/components/LocaleSelector.vue +114 -0
  25. package/components/PromptModal.vue +2 -3
  26. package/components/ResourceList/index.vue +1 -1
  27. package/components/ResourceTable.vue +9 -7
  28. package/components/SimpleBox.vue +6 -4
  29. package/components/SingleClusterInfo.vue +1 -1
  30. package/components/SortableTable/index.vue +18 -25
  31. package/components/SortableTable/selection.js +1 -0
  32. package/components/Tabbed/Tab.vue +5 -0
  33. package/components/Tabbed/index.vue +29 -2
  34. package/components/auth/AzureWarning.vue +5 -1
  35. package/components/auth/Principal.vue +2 -1
  36. package/components/auth/RoleDetailEdit.vue +18 -11
  37. package/components/fleet/FleetBundles.vue +8 -3
  38. package/components/fleet/FleetRepos.vue +0 -2
  39. package/components/fleet/FleetSummary.vue +6 -0
  40. package/components/form/KeyValue.vue +80 -58
  41. package/components/form/NameNsDescription.vue +12 -8
  42. package/components/form/NodeScheduling.vue +1 -1
  43. package/components/form/ResourceTabs/index.vue +5 -1
  44. package/components/form/WorkloadPorts.vue +1 -1
  45. package/components/formatter/ClusterLink.vue +3 -7
  46. package/components/formatter/WorkloadHealthScale.vue +1 -1
  47. package/components/nav/Header.vue +9 -9
  48. package/components/nav/NamespaceFilter.vue +10 -7
  49. package/components/nav/TopLevelMenu.vue +10 -65
  50. package/components/nav/WindowManager/ContainerLogs.vue +1 -1
  51. package/config/footer.js +13 -14
  52. package/config/labels-annotations.js +2 -1
  53. package/config/product/explorer.js +5 -4
  54. package/config/product/harvester-manager.js +64 -2
  55. package/config/product/legacy.js +0 -47
  56. package/config/product/manager.js +9 -0
  57. package/config/product/multi-cluster-apps.js +0 -12
  58. package/config/product/settings.js +12 -1
  59. package/config/product/uiplugins.js +17 -0
  60. package/config/settings.js +37 -72
  61. package/config/table-headers.js +0 -1
  62. package/config/types.js +9 -25
  63. package/config/uiplugins.js +60 -0
  64. package/content/docs/en-us/getting-started.md +1 -26
  65. package/core/plugin-routes.ts +34 -22
  66. package/core/plugin.ts +15 -3
  67. package/core/plugins-loader.js +2 -0
  68. package/core/plugins.js +91 -36
  69. package/core/types.ts +7 -1
  70. package/detail/provisioning.cattle.io.cluster.vue +15 -2
  71. package/detail/workload/index.vue +11 -5
  72. package/{components/dialog → dialog}/AddClusterMemberDialog.vue +0 -0
  73. package/{components/dialog → dialog}/AddCustomBadgeDialog.vue +0 -0
  74. package/{components/dialog → dialog}/AddProjectMemberDialog.vue +0 -0
  75. package/{components/dialog → dialog}/AddonConfigConfirmationDialog.vue +0 -0
  76. package/dialog/DiagnosticTimingsDialog.vue +116 -0
  77. package/{components/dialog → dialog}/DrainNode.vue +0 -0
  78. package/{components/dialog → dialog}/ForceMachineRemoveDialog.vue +0 -0
  79. package/{components/dialog → dialog}/GenericPrompt.vue +0 -0
  80. package/{components/dialog → dialog}/RollbackWorkloadDialog.vue +0 -0
  81. package/{components/dialog → dialog}/RotateCertificatesDialog.vue +9 -3
  82. package/{components/dialog → dialog}/RotateEncryptionKeyDialog.vue +0 -0
  83. package/{components/dialog → dialog}/SaveAsRKETemplateDialog.vue +0 -0
  84. package/{components/dialog → dialog}/ScaleMachineDownDialog.vue +0 -0
  85. package/edit/auth/azuread.vue +44 -6
  86. package/edit/management.cattle.io.project.vue +2 -2
  87. package/edit/namespace.vue +17 -10
  88. package/edit/networking.k8s.io.ingress/index.vue +2 -2
  89. package/edit/persistentvolume/index.vue +3 -0
  90. package/edit/persistentvolumeclaim.vue +1 -0
  91. package/edit/pod.vue +27 -0
  92. package/edit/provisioning.cattle.io.cluster/CustomCommand.vue +1 -1
  93. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +33 -5
  94. package/edit/provisioning.cattle.io.cluster/rke2.vue +76 -5
  95. package/edit/service.vue +8 -6
  96. package/edit/workload/__tests__/Upgrading.test.ts +1 -0
  97. package/edit/workload/index.vue +375 -15
  98. package/edit/workload/mixins/workload.js +62 -7
  99. package/edit/workload/storage/ContainerMountPaths.vue +240 -0
  100. package/edit/workload/storage/Mount.vue +1 -0
  101. package/edit/workload/storage/awsElasticBlockStore.vue +20 -1
  102. package/edit/workload/storage/azureDisk.vue +22 -2
  103. package/edit/workload/storage/azureFile.vue +20 -2
  104. package/edit/workload/storage/csi/index.vue +23 -1
  105. package/edit/workload/storage/gcePersistentDisk.vue +20 -2
  106. package/edit/workload/storage/index.vue +23 -49
  107. package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +1 -0
  108. package/edit/workload/storage/vsphereVolume.vue +11 -1
  109. package/layouts/default.vue +63 -32
  110. package/layouts/error.vue +5 -1
  111. package/layouts/home.vue +14 -5
  112. package/layouts/plain.vue +10 -5
  113. package/list/harvesterhci.io.management.cluster.vue +74 -33
  114. package/list/management.cattle.io.setting.vue +3 -3
  115. package/list/namespace.vue +3 -5
  116. package/list/provisioning.cattle.io.cluster.vue +1 -1
  117. package/machine-config/amazonec2.vue +2 -0
  118. package/machine-config/harvester.vue +100 -51
  119. package/middleware/authenticated.js +56 -52
  120. package/mixins/form-validation.js +1 -1
  121. package/mixins/resource-fetch.js +3 -1
  122. package/models/catalog.cattle.io.uiplugin.js +34 -0
  123. package/models/cluster/node.js +25 -2
  124. package/models/fleet.cattle.io.bundle.js +27 -20
  125. package/models/harvesterhci.io.management.cluster.js +200 -5
  126. package/models/management.cattle.io.cluster.js +1 -1
  127. package/models/management.cattle.io.clusterroletemplatebinding.js +9 -0
  128. package/models/management.cattle.io.project.js +23 -2
  129. package/models/namespace.js +19 -3
  130. package/models/pod.js +19 -2
  131. package/models/provisioning.cattle.io.cluster.js +16 -6
  132. package/models/workload.js +9 -246
  133. package/models/workload.service.js +314 -0
  134. package/nuxt.config.js +80 -34
  135. package/package.json +107 -108
  136. package/pages/auth/login.vue +11 -2
  137. package/pages/auth/setup.vue +1 -1
  138. package/pages/c/_cluster/_product/members/index.vue +3 -93
  139. package/pages/c/_cluster/_product/projectsnamespaces.vue +6 -403
  140. package/pages/c/_cluster/apps/charts/index.vue +46 -1
  141. package/pages/c/_cluster/apps/charts/install.vue +10 -9
  142. package/pages/c/_cluster/explorer/index.vue +72 -9
  143. package/pages/c/_cluster/explorer/tools/index.vue +12 -5
  144. package/pages/c/_cluster/mcapps/index.vue +1 -1
  145. package/pages/c/_cluster/settings/brand.vue +0 -40
  146. package/pages/c/_cluster/settings/links.vue +200 -0
  147. package/pages/c/_cluster/settings/performance.vue +19 -16
  148. package/pages/c/_cluster/uiplugins/DeveloperInstallDialog.vue +232 -0
  149. package/pages/c/_cluster/uiplugins/InstallDialog.vue +242 -0
  150. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +284 -0
  151. package/pages/c/_cluster/uiplugins/RemoveUIPlugins.vue +130 -0
  152. package/pages/c/_cluster/uiplugins/SetupUIPlugins.vue +253 -0
  153. package/pages/c/_cluster/uiplugins/UninstallDialog.vue +115 -0
  154. package/pages/c/_cluster/uiplugins/index.vue +694 -0
  155. package/pages/diagnostic.vue +185 -101
  156. package/pages/docs/_doc.vue +3 -1
  157. package/pages/fail-whale.vue +1 -10
  158. package/pages/home.vue +21 -56
  159. package/pages/index.vue +18 -4
  160. package/pages/prefs.vue +108 -86
  161. package/pages/safeMode.vue +17 -0
  162. package/pages/support/index.vue +23 -15
  163. package/pkg/auto-import.js +44 -7
  164. package/pkg/dynamic-importer.lib.js +4 -0
  165. package/pkg/dynamic-plugin-loader.js +28 -0
  166. package/pkg/import.js +2 -2
  167. package/pkg/model-loader-require.lib.js +3 -0
  168. package/pkg/vue.config.js +9 -6
  169. package/plugins/dashboard-store/model-loader-require.js +12 -0
  170. package/plugins/dashboard-store/model-loader.js +4 -1
  171. package/plugins/dashboard-store/resource-class.js +12 -5
  172. package/plugins/formatters.js +15 -0
  173. package/plugins/plugin.js +56 -4
  174. package/plugins/steve/actions.js +1 -1
  175. package/plugins/steve/index.js +6 -4
  176. package/plugins/steve/mutations.js +1 -1
  177. package/plugins/steve/subscribe.js +89 -56
  178. package/plugins/steve/web-worker.steve-sub-worker.js +24 -15
  179. package/promptRemove/management.cattle.io.globalrole.vue +47 -0
  180. package/promptRemove/management.cattle.io.roletemplate.vue +47 -0
  181. package/promptRemove/mixin/roleDeletionCheck.js +97 -0
  182. package/rancher-components/Form/Checkbox/Checkbox.test.ts +77 -0
  183. package/rancher-components/Form/Checkbox/Checkbox.vue +12 -2
  184. package/scripts/build-pkg.sh +48 -2
  185. package/scripts/drone-build-pkg.sh +31 -0
  186. package/scripts/publish-shell.sh +11 -12
  187. package/scripts/serve-pkgs +17 -10
  188. package/scripts/sync-shell-deps +37 -0
  189. package/store/catalog.js +12 -9
  190. package/store/i18n.js +26 -12
  191. package/store/index.js +4 -181
  192. package/store/prefs.js +46 -2
  193. package/store/type-map.js +47 -33
  194. package/store/uiplugins.ts +15 -61
  195. package/utils/__tests__/object.test.ts +0 -24
  196. package/utils/__tests__/selector.test.ts +1 -1
  197. package/utils/cluster.js +1 -1
  198. package/utils/custom-validators.js +1 -12
  199. package/utils/dynamic-importer.js +5 -1
  200. package/utils/grafana.js +2 -6
  201. package/utils/socket.js +41 -20
  202. package/utils/string.js +1 -7
  203. package/utils/validators/formRules/__tests__/index.test.ts +108 -0
  204. package/utils/validators/formRules/index.ts +9 -1
  205. package/utils/validators/setting.js +0 -35
  206. package/yarn-error.log +195 -0
  207. package/components/FilterLabel.vue +0 -254
  208. package/components/HarvesterUpgradeProgressBarList.vue +0 -109
  209. package/components/VMConsoleBar.vue +0 -87
  210. package/components/dialog/harvester/AddHotplugModal.vue +0 -159
  211. package/components/dialog/harvester/BackupModal.vue +0 -117
  212. package/components/dialog/harvester/CloneTemplate.vue +0 -125
  213. package/components/dialog/harvester/EjectCDROMDialog.vue +0 -157
  214. package/components/dialog/harvester/ExportImageDialog.vue +0 -152
  215. package/components/dialog/harvester/MaintenanceDialog.vue +0 -94
  216. package/components/dialog/harvester/MigrationDialog.vue +0 -154
  217. package/components/dialog/harvester/RestoreDialog.vue +0 -153
  218. package/components/dialog/harvester/SupportBundle.vue +0 -217
  219. package/components/dialog/harvester/UnplugVolume.vue +0 -108
  220. package/components/form/SerialConsole/index.vue +0 -267
  221. package/components/formatter/AttachVMWithName.vue +0 -46
  222. package/components/formatter/CloudInitType.vue +0 -27
  223. package/components/formatter/HarvesterBackupTargetValidation.vue +0 -43
  224. package/components/formatter/HarvesterCPUUsed.vue +0 -122
  225. package/components/formatter/HarvesterDiskState.vue +0 -66
  226. package/components/formatter/HarvesterHostName.vue +0 -66
  227. package/components/formatter/HarvesterIpAddress.vue +0 -90
  228. package/components/formatter/HarvesterMemoryUsed.vue +0 -140
  229. package/components/formatter/HarvesterMigrationState.vue +0 -85
  230. package/components/formatter/HarvesterNodeName.vue +0 -49
  231. package/components/formatter/HarvesterStorageUsed.vue +0 -194
  232. package/components/formatter/HarvesterVmState.vue +0 -123
  233. package/components/nav/HarvesterUpgrade.vue +0 -232
  234. package/components/novnc/NovncConsole.vue +0 -93
  235. package/components/novnc/NovncConsoleItem.vue +0 -89
  236. package/components/novnc/NovncConsoleWrapper.vue +0 -243
  237. package/config/harvester-map.js +0 -44
  238. package/config/harvester-table-headers.js +0 -27
  239. package/config/product/harvester.js +0 -305
  240. package/detail/harvesterhci.io.host/HarvesterHostBasic.vue +0 -364
  241. package/detail/harvesterhci.io.host/HarvesterHostDisk.vue +0 -200
  242. package/detail/harvesterhci.io.host/HarvesterHostNetwork.vue +0 -89
  243. package/detail/harvesterhci.io.host/VirtualMachineInstance.vue +0 -134
  244. package/detail/harvesterhci.io.host/index.vue +0 -243
  245. package/detail/harvesterhci.io.virtualmachinebackup/index.vue +0 -221
  246. package/detail/harvesterhci.io.virtualmachineimage.vue +0 -118
  247. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineBasics.vue +0 -279
  248. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineEvents.vue +0 -75
  249. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineKeypairs.vue +0 -114
  250. package/detail/kubevirt.io.virtualmachine/VirtualMachineTabs/VirtualMachineMigration.vue +0 -79
  251. package/detail/kubevirt.io.virtualmachine/index.vue +0 -213
  252. package/edit/harvesterhci.io.cloudtemplate.vue +0 -123
  253. package/edit/harvesterhci.io.host/HarvesterDisk.vue +0 -262
  254. package/edit/harvesterhci.io.host/index.vue +0 -533
  255. package/edit/harvesterhci.io.keypair.vue +0 -112
  256. package/edit/harvesterhci.io.managedchart/index.vue +0 -25
  257. package/edit/harvesterhci.io.managedchart/rancher-monitoring.vue +0 -172
  258. package/edit/harvesterhci.io.networkattachmentdefinition.vue +0 -210
  259. package/edit/harvesterhci.io.setting/additional-ca.vue +0 -36
  260. package/edit/harvesterhci.io.setting/backup-target.vue +0 -182
  261. package/edit/harvesterhci.io.setting/http-proxy.vue +0 -79
  262. package/edit/harvesterhci.io.setting/index.vue +0 -201
  263. package/edit/harvesterhci.io.setting/overcommit-config.vue +0 -94
  264. package/edit/harvesterhci.io.setting/ssl-certificates.vue +0 -117
  265. package/edit/harvesterhci.io.setting/ssl-parameters.vue +0 -161
  266. package/edit/harvesterhci.io.setting/support-bundle-image.vue +0 -134
  267. package/edit/harvesterhci.io.setting/support-bundle-namespaces.vue +0 -73
  268. package/edit/harvesterhci.io.setting/vip-pools.vue +0 -244
  269. package/edit/harvesterhci.io.setting/vm-force-reset-policy.vue +0 -81
  270. package/edit/harvesterhci.io.virtualmachinebackup.vue +0 -256
  271. package/edit/harvesterhci.io.virtualmachineimage.vue +0 -364
  272. package/edit/harvesterhci.io.virtualmachinetemplateversion.vue +0 -340
  273. package/edit/harvesterhci.io.volume.vue +0 -195
  274. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/AccessCredentialsUsers.vue +0 -190
  275. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/index.vue +0 -212
  276. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/basicAuth.vue +0 -94
  277. package/edit/kubevirt.io.virtualmachine/VirtualMachineAccessCredentials/type/sshkey.vue +0 -85
  278. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/DataTemplate.vue +0 -153
  279. package/edit/kubevirt.io.virtualmachine/VirtualMachineCloudConfig/index.vue +0 -279
  280. package/edit/kubevirt.io.virtualmachine/VirtualMachineCpuMemory.vue +0 -113
  281. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/__tests__/HarvesterEditNetwork.test.ts +0 -41
  282. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/base.vue +0 -281
  283. package/edit/kubevirt.io.virtualmachine/VirtualMachineNetwork/index.vue +0 -142
  284. package/edit/kubevirt.io.virtualmachine/VirtualMachineReserved.vue +0 -54
  285. package/edit/kubevirt.io.virtualmachine/VirtualMachineSSHKey.vue +0 -256
  286. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/index.vue +0 -391
  287. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditContainer.test.ts +0 -40
  288. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditExisting.test.ts +0 -102
  289. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVMImage.test.ts +0 -117
  290. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/__tests__/HarvesterEditVolume.test.ts +0 -74
  291. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/container.vue +0 -132
  292. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/existing.vue +0 -303
  293. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/vmImage.vue +0 -285
  294. package/edit/kubevirt.io.virtualmachine/VirtualMachineVolume/type/volume.vue +0 -188
  295. package/edit/kubevirt.io.virtualmachine/index.vue +0 -642
  296. package/edit/network.harvesterhci.io.clusternetwork/index.vue +0 -19
  297. package/edit/network.harvesterhci.io.clusternetwork/vlan.vue +0 -134
  298. package/edit/workload/types/Deployment.vue +0 -377
  299. package/edit/workload/types/Generic.vue +0 -295
  300. package/list/harvesterhci.io.cloudtemplate.vue +0 -78
  301. package/list/harvesterhci.io.dashboard/HarvesterUpgrade.vue +0 -211
  302. package/list/harvesterhci.io.dashboard/UpgradeInfo.vue +0 -40
  303. package/list/harvesterhci.io.dashboard/index.vue +0 -752
  304. package/list/harvesterhci.io.host/index.vue +0 -186
  305. package/list/harvesterhci.io.networkattachmentdefinition.vue +0 -167
  306. package/list/harvesterhci.io.setting.vue +0 -241
  307. package/list/harvesterhci.io.virtualmachinebackup.vue +0 -172
  308. package/list/harvesterhci.io.virtualmachineimage.vue +0 -80
  309. package/list/harvesterhci.io.virtualmachinetemplateversion.vue +0 -173
  310. package/list/harvesterhci.io.volume.vue +0 -122
  311. package/list/kubevirt.io.virtualmachine.vue +0 -193
  312. package/mixins/harvester-vm/impl.js +0 -267
  313. package/mixins/harvester-vm/index.js +0 -1357
  314. package/models/harvester/configmap.js +0 -32
  315. package/models/harvester/harvesterhci.io.blockdevice.js +0 -55
  316. package/models/harvester/harvesterhci.io.keypair.js +0 -12
  317. package/models/harvester/harvesterhci.io.setting.js +0 -127
  318. package/models/harvester/harvesterhci.io.supportbundle.js +0 -35
  319. package/models/harvester/harvesterhci.io.upgrade.js +0 -226
  320. package/models/harvester/harvesterhci.io.virtualmachinebackup.js +0 -116
  321. package/models/harvester/harvesterhci.io.virtualmachineimage.js +0 -255
  322. package/models/harvester/harvesterhci.io.virtualmachinerestore.js +0 -43
  323. package/models/harvester/harvesterhci.io.virtualmachinetemplate.js +0 -69
  324. package/models/harvester/harvesterhci.io.virtualmachinetemplateversion.js +0 -227
  325. package/models/harvester/k8s.cni.cncf.io.networkattachmentdefinition.js +0 -32
  326. package/models/harvester/kubevirt.io.virtualmachine.js +0 -850
  327. package/models/harvester/kubevirt.io.virtualmachineinstance.js +0 -142
  328. package/models/harvester/management.cattle.io.managedchart.js +0 -191
  329. package/models/harvester/management.cattle.io.setting.js +0 -40
  330. package/models/harvester/network.harvesterhci.io.clusternetwork.js +0 -100
  331. package/models/harvester/network.harvesterhci.io.nodenetwork.js +0 -34
  332. package/models/harvester/node.js +0 -255
  333. package/models/harvester/persistentvolumeclaim.js +0 -166
  334. package/models/harvester/pod.js +0 -185
  335. package/pages/c/_cluster/harvester/airgapupgrade/index.vue +0 -309
  336. package/pages/c/_cluster/harvester/console/_uid/serial.vue +0 -51
  337. package/pages/c/_cluster/harvester/console/_uid/vnc.vue +0 -52
  338. package/pages/c/_cluster/harvester/index.vue +0 -24
  339. package/pages/c/_cluster/harvester/support/index.vue +0 -154
  340. package/pages/plugins.vue +0 -387
  341. package/pkg/model-loader.lib.js +0 -3
  342. package/promptRemove/kubevirt.io.virtualmachine.vue +0 -164
  343. package/server/verdaccio-middleware.js +0 -56
  344. package/store/harvester-common.js +0 -126
  345. package/utils/validators/vm-datavolumes.js +0 -38
  346. package/utils/validators/vm-image.js +0 -32
  347. package/utils/validators/vm.js +0 -221
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/prefs.vue CHANGED
@@ -1,32 +1,41 @@
1
1
  <script>
2
2
  import day from 'dayjs';
3
3
  import { mapGetters } from 'vuex';
4
+ import { isAdminUser } from '@shell/store/type-map';
4
5
  import BackLink from '@shell/components/BackLink';
5
6
  import BackRoute from '@shell/mixins/back-link';
6
7
  import ButtonGroup from '@shell/components/ButtonGroup';
7
8
  import { Checkbox } from '@components/Form/Checkbox';
8
9
  import LandingPagePreference from '@shell/components/LandingPagePreference';
9
10
  import {
10
- mapPref, THEME, KEYMAP, DEV, DATE_FORMAT, TIME_FORMAT, ROWS_PER_PAGE, HIDE_DESC, SHOW_PRE_RELEASE, MENU_MAX_CLUSTERS
11
+ mapPref, THEME, KEYMAP, DATE_FORMAT, TIME_FORMAT, ROWS_PER_PAGE, HIDE_DESC, SHOW_PRE_RELEASE, MENU_MAX_CLUSTERS,
12
+ VIEW_IN_API, ALL_NAMESPACES, THEME_SHORTCUT, PLUGIN_DEVELOPER
11
13
  } from '@shell/store/prefs';
12
14
  import LabeledSelect from '@shell/components/form/LabeledSelect';
13
15
  import { addObject } from '@shell/utils/array';
16
+ import LocaleSelector from '@shell/components/LocaleSelector';
14
17
 
15
18
  export default {
16
19
  layout: 'plain',
17
20
  components: {
18
- BackLink, ButtonGroup, LabeledSelect, Checkbox, LandingPagePreference
21
+ BackLink, ButtonGroup, LabeledSelect, Checkbox, LandingPagePreference, LocaleSelector
19
22
  },
20
- mixins: [BackRoute],
21
- computed: {
22
- keymap: mapPref(KEYMAP),
23
- dev: mapPref(DEV),
24
- dateFormat: mapPref(DATE_FORMAT),
25
- timeFormat: mapPref(TIME_FORMAT),
26
- perPage: mapPref(ROWS_PER_PAGE),
27
- hideDesc: mapPref(HIDE_DESC),
28
- showPreRelease: mapPref(SHOW_PRE_RELEASE),
29
- menuMaxClusters: mapPref(MENU_MAX_CLUSTERS),
23
+ mixins: [BackRoute],
24
+ data() {
25
+ return { admin: isAdminUser(this.$store.getters) };
26
+ },
27
+ computed: {
28
+ keymap: mapPref(KEYMAP),
29
+ viewInApi: mapPref(VIEW_IN_API),
30
+ allNamespaces: mapPref(ALL_NAMESPACES),
31
+ themeShortcut: mapPref(THEME_SHORTCUT),
32
+ dateFormat: mapPref(DATE_FORMAT),
33
+ timeFormat: mapPref(TIME_FORMAT),
34
+ perPage: mapPref(ROWS_PER_PAGE),
35
+ hideDesc: mapPref(HIDE_DESC),
36
+ showPreRelease: mapPref(SHOW_PRE_RELEASE),
37
+ menuMaxClusters: mapPref(MENU_MAX_CLUSTERS),
38
+ pluginDeveloper: mapPref(PLUGIN_DEVELOPER),
30
39
 
31
40
  ...mapGetters(['isSingleProduct']),
32
41
 
@@ -137,99 +146,112 @@ export default {
137
146
  this.hideDesc = val;
138
147
  }
139
148
  },
140
- },
149
+ }
141
150
  };
142
151
  </script>
143
152
 
144
153
  <template>
145
154
  <div>
146
155
  <BackLink :link="backLink" />
147
- <h1 v-t="'prefs.title'" />
148
-
149
- <h4 v-t="'prefs.theme.label'" />
150
- <div>
151
- <ButtonGroup v-model="theme" :options="themeOptions" />
156
+ <h1 v-t="'prefs.title'" class="mb-20" />
157
+ <!-- Language -->
158
+ <div class="mt-10 mb-10">
159
+ <h4 v-t="'prefs.language'" />
160
+ <div class="row">
161
+ <div class="col span-4">
162
+ <LocaleSelector />
163
+ </div>
164
+ </div>
152
165
  </div>
153
- <div class="mt-10">
154
- <t k="prefs.theme.autoDetail" :pm="pm" :am="am" />
166
+ <!-- Theme -->
167
+ <div class="mt-10 mb-10">
168
+ <hr />
169
+ <h4 v-t="'prefs.theme.label'" />
170
+ <ButtonGroup v-model="theme" :options="themeOptions" />
171
+ <div class="mt-10">
172
+ <t k="prefs.theme.autoDetail" :pm="pm" :am="am" />
173
+ </div>
155
174
  </div>
156
- <div v-if="!isSingleProduct">
175
+ <!-- Login landing page -->
176
+ <div v-if="!isSingleProduct" class="mt-10 mb-10">
157
177
  <hr />
158
178
  <h4 v-t="'prefs.landing.label'" />
159
179
  <LandingPagePreference />
160
180
  </div>
161
- <hr />
162
- <h4 v-t="'prefs.formatting'" />
163
- <div class="row">
164
- <div class="col span-4">
165
- <LabeledSelect
166
- v-model="dateFormat"
167
- :label="t('prefs.dateFormat.label')"
168
- :options="dateOptions"
169
- />
170
- </div>
171
- <div class="col span-4">
172
- <LabeledSelect
173
- v-model="timeFormat"
174
- :label="t('prefs.timeFormat.label')"
175
- :options="timeOptions"
176
- />
177
- </div>
178
-
179
- <div class="col span-4">
180
- <LabeledSelect
181
- v-model.number="perPage"
182
- :label="t('prefs.perPage.label')"
183
- :options="perPageOptions"
184
- option-key="value"
185
- option-label="label"
186
- placeholder="Select a row count"
187
- />
181
+ <!-- Display Settings -->
182
+ <div class="mt-10 mb-10">
183
+ <hr />
184
+ <h4 v-t="'prefs.displaySettings.title'" />
185
+ <p class="set-landing-leadin">
186
+ {{ t('prefs.displaySettings.detail', {}, raw=true) }}
187
+ </p>
188
+ <div class="row mt-20">
189
+ <div class="col span-4">
190
+ <LabeledSelect
191
+ v-model="dateFormat"
192
+ :label="t('prefs.dateFormat.label')"
193
+ :options="dateOptions"
194
+ />
195
+ </div>
196
+ <div class="col span-4">
197
+ <LabeledSelect
198
+ v-model="timeFormat"
199
+ :label="t('prefs.timeFormat.label')"
200
+ :options="timeOptions"
201
+ />
202
+ </div>
188
203
  </div>
189
- </div>
190
204
 
191
- <div class="row mt-20">
192
- <div class="col span-4">
193
- <LabeledSelect
194
- v-model.number="menuMaxClusters"
195
- :label="t('prefs.clusterToShow.label')"
196
- :options="menuClusterOptions"
197
- option-key="value"
198
- option-label="label"
199
- placeholder="Select a row count"
200
- />
205
+ <div class="row mt-20">
206
+ <div class="col span-4">
207
+ <LabeledSelect
208
+ v-model.number="perPage"
209
+ :label="t('prefs.perPage.label')"
210
+ :options="perPageOptions"
211
+ option-key="value"
212
+ option-label="label"
213
+ placeholder="Select a row count"
214
+ />
215
+ </div>
216
+ <div class="col span-4">
217
+ <LabeledSelect
218
+ v-model.number="menuMaxClusters"
219
+ :label="t('prefs.clusterToShow.label')"
220
+ :options="menuClusterOptions"
221
+ option-key="value"
222
+ option-label="label"
223
+ placeholder="Select a row count"
224
+ />
225
+ </div>
201
226
  </div>
202
227
  </div>
203
-
204
- <hr />
205
- <div class="row">
206
- <div class="col prefs-advanced">
207
- <h4 v-t="'prefs.advanced'" />
208
- <Checkbox v-model="dev" :label="t('prefs.dev.label', {}, true)" />
209
- <p class="wrap-text">
210
- {{ t('prefs.advancedTooltip', {}, raw=true) }}
211
- </p>
212
- <br>
213
- <Checkbox v-if="!isSingleProduct" v-model="hideDescriptions" :label="t('prefs.hideDesc.label')" class="mt-10" />
214
- </div>
228
+ <!-- Advanced Features -->
229
+ <div class="col adv-features mt-10 mb-10">
230
+ <hr />
231
+ <h4 v-t="'prefs.advFeatures.title'" />
232
+ <Checkbox v-model="viewInApi" :label="t('prefs.advFeatures.viewInApi', {}, true)" class="mt-10" />
233
+ <br />
234
+ <Checkbox v-model="allNamespaces" :label="t('prefs.advFeatures.allNamespaces', {}, true)" class="mt-20" />
235
+ <br />
236
+ <Checkbox v-model="themeShortcut" :label="t('prefs.advFeatures.themeShortcut', {}, true)" class="mt-20" />
237
+ <br />
238
+ <Checkbox v-if="!isSingleProduct" v-model="hideDescriptions" :label="t('prefs.hideDesc.label')" class="mt-20" />
239
+ <template v-if="admin">
240
+ <br />
241
+ <Checkbox v-model="pluginDeveloper" :label="t('prefs.advFeatures.pluginDeveloper', {}, true)" class="mt-20" />
242
+ </template>
215
243
  </div>
216
-
217
- <hr />
218
- <div class="row">
219
- <div class="col span-12">
220
- <h4 v-t="'prefs.keymap.label'" />
221
- <ButtonGroup v-model="keymap" :options="keymapOptions" />
222
- </div>
244
+ <!-- YAML editor key mapping -->
245
+ <div class="col mt-10 mb-10">
246
+ <hr />
247
+ <h4 v-t="'prefs.keymap.label'" />
248
+ <ButtonGroup v-model="keymap" :options="keymapOptions" />
223
249
  </div>
224
-
225
- <div v-if="!isSingleProduct">
250
+ <!-- Helm Charts -->
251
+ <div v-if="!isSingleProduct" class="col mt-10 mb-40">
226
252
  <hr />
227
- <div class="row mb-20">
228
- <div class="col span-12">
229
- <h4 v-t="'prefs.helm.label'" />
230
- <ButtonGroup v-model="showPreRelease" :options="helmOptions" />
231
- </div>
232
- </div>
253
+ <h4 v-t="'prefs.helm.label'" />
254
+ <ButtonGroup v-model="showPreRelease" :options="helmOptions" />
233
255
  </div>
234
256
  </div>
235
257
  </template>
@@ -0,0 +1,17 @@
1
+ <script>
2
+ export default {
3
+ middleware({ redirect, store } ) {
4
+ const dashboardHome = { name: 'home' };
5
+ const t = store.getters['i18n/t'];
6
+
7
+ setTimeout(() => {
8
+ store.dispatch('growl/success', {
9
+ title: t('plugins.safeMode.title'),
10
+ message: t('plugins.safeMode.message')
11
+ }, { root: true });
12
+ }, 1000);
13
+
14
+ return redirect(dashboardHome);
15
+ }
16
+ };
17
+ </script>
@@ -52,7 +52,6 @@ export default {
52
52
  }
53
53
  this.supportSetting = await fetchOrCreateSetting('has-support', 'false');
54
54
  this.brandSetting = await fetchOrCreateSetting(SETTING.BRAND, '');
55
- this.communitySetting = await fetchOrCreateSetting(SETTING.COMMUNITY_LINKS, 'true');
56
55
  this.serverUrlSetting = await fetchOrCreateSetting(SETTING.SERVER_URL, '');
57
56
  this.uiIssuesSetting = await this.$store.dispatch('management/find', { type: MANAGEMENT.SETTING, id: SETTING.ISSUES });
58
57
  },
@@ -65,7 +64,6 @@ export default {
65
64
  supportSetting: null,
66
65
  brandSetting: null,
67
66
  uiIssuesSetting: null,
68
- communitySetting: null,
69
67
  serverSetting: null,
70
68
  promos: [
71
69
  'support.promos.one',
@@ -104,11 +102,17 @@ export default {
104
102
  },
105
103
 
106
104
  hasSupport() {
107
- return (this.supportSetting?.value && this.supportSetting?.value !== 'false') || this.hasAWSSupport;
105
+ // NB: This is temporary until API implemented
106
+ return false;
108
107
  },
109
108
 
110
109
  options() {
111
- return options( this.uiIssuesSetting?.value, this.communitySetting?.value === 'false');
110
+ if (!this.uiIssuesSetting?.value) {
111
+ return;
112
+ }
113
+
114
+ // Load defaults for suppoet page
115
+ return options(true, this.uiIssuesSetting?.value);
112
116
  },
113
117
 
114
118
  title() {
@@ -194,11 +198,7 @@ export default {
194
198
  <div>{{ t(`${key}.text`) }}</div>
195
199
  </div>
196
200
  </div>
197
- <div v-if="!hasSupport" class="external">
198
- <a href="https://rancher.com/support-maintenance-terms" target="_blank" rel="noopener noreferrer nofollow">{{ t('support.community.learnMore') }} <i class="icon icon-external-link" /></a>
199
- or
200
- <a href="https://rancher.com/pricing" target="_blank" rel="noopener noreferrer nofollow">{{ t('support.community.pricing') }} <i class="icon icon-external-link" /></a>
201
- </div>
201
+
202
202
  <div v-if="!hasSupport" class="register row">
203
203
  <div>
204
204
  {{ t('support.subscription.haveSupport') }}
@@ -214,7 +214,16 @@ export default {
214
214
  </div>
215
215
  </div>
216
216
  <div class="community">
217
- <CommunityLinks />
217
+ <CommunityLinks :link-options="options">
218
+ <div v-if="!hasSupport" class="external support-links" :class="{ 'mt-15': !!options}">
219
+ <div class="support-link">
220
+ <a class="support-link" href="https://rancher.com/support-maintenance-terms" target="_blank" rel="noopener noreferrer nofollow">{{ t('support.community.learnMore') }}</a>
221
+ </div>
222
+ <div class="support-link">
223
+ <a class="support-link" href="https://rancher.com/pricing" target="_blank" rel="noopener noreferrer nofollow">{{ t('support.community.pricing') }}</a>
224
+ </div>
225
+ </div>
226
+ </CommunityLinks>
218
227
  </div>
219
228
  </div>
220
229
  </IndentedPanel>
@@ -279,13 +288,12 @@ export default {
279
288
  font-weight: 300;
280
289
  margin-bottom: 20px;
281
290
  }
282
- .support-link {
283
- margin: 10px 0;
284
- }
285
291
  }
286
- .external {
287
- margin-top: 20px;
292
+
293
+ .support-link:not(:first-child) {
294
+ margin: 15px 0 0 0;
288
295
  }
296
+
289
297
  .register {
290
298
  display: flex;
291
299
  align-items: center;
@@ -1,6 +1,6 @@
1
1
  const fs = require('fs');
2
2
  const path = require('path');
3
- const contextFolders = ['chart', 'cloud-credential', 'content', 'detail', 'edit', 'list', 'machine-config', 'models', 'promptRemove', 'l10n', 'windowComponents', 'formatters'];
3
+ const contextFolders = ['chart', 'cloud-credential', 'content', 'detail', 'edit', 'list', 'machine-config', 'models', 'promptRemove', 'l10n', 'windowComponents', 'dialog', 'formatters'];
4
4
  const contextMap = contextFolders.reduce((map, obj) => {
5
5
  map[obj] = true;
6
6
 
@@ -11,6 +11,19 @@ function replaceAll(str, find, replace) {
11
11
  return str.split(find).join(replace);
12
12
  }
13
13
 
14
+ function registerFile(file, type, pkg, f) {
15
+ const importType = (f === 'models') ? 'require' : 'import';
16
+ const chunkName = (f === 'l10n') ? '' : `/* webpackChunkName: "${ f }" */`;
17
+
18
+ return ` $plugin.register('${ f }', '${ type }', () => ${ importType }(${ chunkName }'${ pkg }/${ f }/${ file }'));\n`;
19
+ }
20
+
21
+ function register(file, pkg, f) {
22
+ const name = file.replace(/\.[^/.]+$/, '');
23
+
24
+ return registerFile(file, name, pkg, f);
25
+ }
26
+
14
27
  // This function is used to generate the code to register models, edit, detail, list etc for a type
15
28
  // This is used when building as a library - it does not use require.context - it scans the file system and build time.
16
29
  // This ensures that the webpackChunkName is respected (require.context does not support this) - so when build as a library
@@ -20,13 +33,34 @@ function generateTypeImport(pkg, dir) {
20
33
 
21
34
  // Auto-import if the folder exists
22
35
  contextFolders.forEach((f) => {
23
- if (fs.existsSync(path.join(dir, f))) {
36
+ const filePath = path.join(dir, f);
37
+
38
+ if (fs.existsSync(filePath)) {
24
39
  fs.readdirSync(path.join(dir, f)).forEach((file) => {
25
- const name = file.replace(/\.[^/.]+$/, '');
26
- const importType = (f === 'models') ? 'require' : 'import';
27
- const chunkName = (f === 'l10n') ? '' : `/* webpackChunkName: "${ f }" */`;
40
+ const fileStat = fs.lstatSync(path.join(filePath, file));
41
+
42
+ // Directories are special cases
43
+ if (fileStat.isDirectory()) {
44
+ // This might be a <type>/index.vue (aka nested component)
45
+ const indexFilePath = path.join(file, 'index.vue');
46
+ const fullIndexFilePath = path.join(filePath, indexFilePath);
28
47
 
29
- content += ` $plugin.register('${ f }', '${ name }', () => ${ importType }(${ chunkName }'${ pkg }/${ f }/${ file }'));\n`;
48
+ if (fs.existsSync(fullIndexFilePath)) {
49
+ content += registerFile(indexFilePath, file, pkg, f);
50
+
51
+ return;
52
+ }
53
+
54
+ // This might be a <store name>/<model name|type>.js file (aka nested model)
55
+ if (f === 'models') {
56
+ fs.readdirSync(path.join(filePath, file)).forEach((store) => {
57
+ content += register(path.join(file, store), pkg, f);
58
+ });
59
+ }
60
+ } else {
61
+ // This is a simple <resource type>.<file type> file
62
+ content += register(file, pkg, f);
63
+ }
30
64
  });
31
65
  }
32
66
  });
@@ -48,7 +82,10 @@ function generateDynamicTypeImport(pkg, dir) {
48
82
  // Auto-import if the folder exists
49
83
  contextFolders.forEach((f) => {
50
84
  if (fs.existsSync(path.join(dir, f))) {
51
- let genImport = replaceAll(template, 'NAME', f);
85
+ const safeName = f.replace(/\/|-/g, '_');
86
+ let genImport = replaceAll(template, 'NAME', safeName);
87
+
88
+ genImport = replaceAll(genImport, 'DIR', f );
52
89
  const importType = (f === 'models') ? 'require' : 'import';
53
90
  // Ensure i18n chunks are named with the request name (which will be the locale)
54
91
  const chunk = (f === 'l10n') ? '[request]' : f;
@@ -53,6 +53,10 @@ export function resolveList(key) {
53
53
  return undefined;
54
54
  }
55
55
 
56
+ export function resolveChart(key) {
57
+ return undefined;
58
+ }
59
+
56
60
  export function resolveEdit(key) {
57
61
  return undefined;
58
62
  }
@@ -0,0 +1,28 @@
1
+
2
+ /**
3
+ * Some plugins won't be bundled with the dashboard build but loaded on demand at run time.
4
+ * This file allows 'manager' style plugins to defined how to determine if a unknown route
5
+ * belongs to one of their associated plugins and how that plugin can be loaded
6
+ */
7
+ class DynamicPluginLoader {
8
+ dynamicPluginLoaders = [];
9
+
10
+ register(reg) {
11
+ this.dynamicPluginLoaders.push(reg);
12
+ }
13
+
14
+ async check({ route, store }) {
15
+ for (const dpl of this.dynamicPluginLoaders) {
16
+ // Check that the route is valid and then load the plugin associated with it
17
+ const res = await dpl.load({ route, store });
18
+
19
+ if (res) {
20
+ return res;
21
+ }
22
+ }
23
+ }
24
+ }
25
+
26
+ const dynamicPluginLoader = new DynamicPluginLoader();
27
+
28
+ export default dynamicPluginLoader;
package/pkg/import.js CHANGED
@@ -1,4 +1,4 @@
1
- const _NAME = require.context('BASE/NAME', true, /\.(vue|js|yaml)$/).keys();
1
+ const _NAME = require.context('BASE/DIR', true, /\.(vue|js|yaml)$/).keys();
2
2
 
3
3
  _NAME.forEach((f) => {
4
4
  let name = f.substr(2);
@@ -6,5 +6,5 @@ _NAME.forEach((f) => {
6
6
 
7
7
  name = name.substr(0, ext);
8
8
 
9
- $plugin.register('NAME', name, () => REQUIRE(CHUNK`BASE/NAME/${ name }EXT`)); // eslint-disable-line no-undef
9
+ $plugin.register('DIR', name, () => REQUIRE(CHUNK`BASE/DIR/${ name }EXT`)); // eslint-disable-line no-undef
10
10
  });
@@ -0,0 +1,3 @@
1
+ export default function modelLoaderRequire(type) {
2
+ return null;
3
+ }
package/pkg/vue.config.js CHANGED
@@ -46,20 +46,23 @@ module.exports = function(dir) {
46
46
  config.resolve.alias['~pkg'] = dir;
47
47
  delete config.resolve.alias['@'];
48
48
 
49
- // Prevent the dynamic importer and the model-loader from importing anything dynamically - we don't want all of the
49
+ // Prevent the dynamic importer and the model-loader-require from importing anything dynamically - we don't want all of the
50
50
  // models etc when we build as a library
51
- const dynamicImporterOveride = new webpack.NormalModuleReplacementPlugin(/dynamic-importer$/, (resource) => {
51
+ const dynamicImporterOverride = new webpack.NormalModuleReplacementPlugin(/dynamic-importer$/, (resource) => {
52
52
  resource.request = path.join(__dirname, 'dynamic-importer.lib.js');
53
53
  });
54
- const modelLoaderImporterOveride = new webpack.NormalModuleReplacementPlugin(/model-loader$/, (resource) => {
55
- resource.request = path.join(__dirname, 'model-loader.lib.js');
54
+ const modelLoaderImporterOverride = new webpack.NormalModuleReplacementPlugin(/model-loader-require$/, (resource) => {
55
+ const fileName = 'model-loader-require.lib.js';
56
+ const pkgModelLoaderRequire = path.join(dir, fileName);
57
+
58
+ resource.request = fs.existsSync(pkgModelLoaderRequire) ? pkgModelLoaderRequire : path.join(__dirname, fileName);
56
59
  });
57
60
 
58
61
  // Auto-generate module to import the types (model, detail, edit etc)
59
62
  const autoImportPlugin = new VirtualModulesPlugin({ 'node_modules/@rancher/auto-import': generateTypeImport('@pkg', dir) });
60
63
 
61
- config.plugins.unshift(dynamicImporterOveride);
62
- config.plugins.unshift(modelLoaderImporterOveride);
64
+ config.plugins.unshift(dynamicImporterOverride);
65
+ config.plugins.unshift(modelLoaderImporterOverride);
63
66
  config.plugins.unshift(autoImportPlugin);
64
67
  // config.plugins.unshift(debug);
65
68
 
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Fetch a model from the dashboard's local model's folder
3
+ *
4
+ * Splitting this out into a separate function means packages can
5
+ * override this to ensure dashboard models aren't bundled with it
6
+ *
7
+ * @param {string} type
8
+ * @returns Model for the given type
9
+ */
10
+ export default function modelLoaderRequire(type) {
11
+ return require(`@shell/models/${ type }`);
12
+ }
@@ -1,4 +1,5 @@
1
1
  import { normalizeType } from './normalize';
2
+ import modelLoaderRequire from './model-loader-require';
2
3
 
3
4
  const cache = {};
4
5
 
@@ -16,7 +17,9 @@ function find(cache, type, rootState) {
16
17
  let base;
17
18
 
18
19
  if (!pluginModel) {
19
- base = require(`@shell/models/${ type }`);
20
+ // Model hasn't come from a plugin, fall back on something reasonable
21
+ // by default this is the dashboard's local models folder
22
+ base = modelLoaderRequire(type);
20
23
  } else if (typeof pluginModel === 'function') {
21
24
  // pluginModel could be an object in the case the plugin is built-in
22
25
  base = pluginModel();
@@ -9,7 +9,7 @@ import {
9
9
  AS,
10
10
  MODE
11
11
  } from '@shell/config/query-params';
12
- import { DEV } from '@shell/store/prefs';
12
+ import { VIEW_IN_API } from '@shell/store/prefs';
13
13
  import { addObject, addObjects, findBy, removeAt } from '@shell/utils/array';
14
14
  import CustomValidators from '@shell/utils/custom-validators';
15
15
  import { downloadFile, generateZip } from '@shell/utils/download';
@@ -24,7 +24,7 @@ import {
24
24
  validateDnsLikeTypes,
25
25
  validateLength,
26
26
  } from '@shell/utils/validators';
27
- import formRulesGenerator from '@shell/utils/validators/formRules';
27
+ import formRulesGenerator from '@shell/utils/validators/formRules/index';
28
28
  import jsyaml from 'js-yaml';
29
29
  import compact from 'lodash/compact';
30
30
  import forIn from 'lodash/forIn';
@@ -966,7 +966,7 @@ export default class Resource {
966
966
  }
967
967
 
968
968
  get canViewInApi() {
969
- return this.hasLink('self') && this.$rootGetters['prefs/get'](DEV);
969
+ return this.hasLink('self') && this.$rootGetters['prefs/get'](VIEW_IN_API);
970
970
  }
971
971
 
972
972
  get canYaml() {
@@ -1587,8 +1587,15 @@ export default class Resource {
1587
1587
  if (!isEmpty(validatorName) && validatorExists) {
1588
1588
  CustomValidators[validatorName](pathValue, this.$rootGetters, errors, validatorArgs, displayKey, data);
1589
1589
  } else if (!isEmpty(validatorName) && !validatorExists) {
1590
- // eslint-disable-next-line
1591
- console.warn(this.t('validation.custom.missing', { validatorName }));
1590
+ // Check if validator is imported from plugin
1591
+ const pluginValidator = this.$rootState.$plugin?.getValidator(validatorName);
1592
+
1593
+ if (pluginValidator) {
1594
+ pluginValidator(pathValue, this.$rootGetters, errors, validatorArgs, displayKey, data);
1595
+ } else {
1596
+ // eslint-disable-next-line
1597
+ console.warn(this.t('validation.custom.missing', { validatorName }));
1598
+ }
1592
1599
  }
1593
1600
  });
1594
1601
  });
@@ -0,0 +1,15 @@
1
+ // This registers all of the built-in formatters into the SortableTable cache
2
+
3
+ // We do it here to keep it away from plugins
4
+ // It was in SortableTable itself, but this causes plugins to pull in all formatters and their dependencies
5
+
6
+ import { FORMATTERS } from '@shell/components/SortableTable';
7
+
8
+ const components = require.context('@shell/components/formatter', false, /[A-Z]\w+\.(vue)$/);
9
+
10
+ components.keys().forEach((fileName) => {
11
+ const componentConfig = components(fileName);
12
+ const componentName = fileName.split('/').pop().split('.')[0];
13
+
14
+ FORMATTERS[componentName] = componentConfig.default || componentConfig;
15
+ });