@rancher/shell 0.5.3 → 1.2.0

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 (356) hide show
  1. package/.DS_Store +0 -0
  2. package/assets/images/providers/aks-black.svg +28 -0
  3. package/assets/images/providers/aks.svg +31 -0
  4. package/assets/styles/global/_labeled-input.scss +1 -0
  5. package/assets/styles/global/_layout.scss +0 -99
  6. package/assets/translations/en-us.yaml +76 -74
  7. package/assets/translations/zh-hans.yaml +25 -23
  8. package/babel.config.js +1 -7
  9. package/chart/gatekeeper.vue +11 -2
  10. package/chart/istio.vue +10 -1
  11. package/chart/logging/index.vue +11 -2
  12. package/chart/monitoring/alerting/index.vue +21 -7
  13. package/chart/monitoring/grafana/index.vue +2 -57
  14. package/chart/monitoring/index.vue +26 -52
  15. package/chart/monitoring/prometheus/index.vue +43 -37
  16. package/chart/rancher-backup/index.vue +10 -3
  17. package/cloud-credential/azure.vue +17 -4
  18. package/components/AsyncButton.vue +0 -9
  19. package/components/Carousel.vue +0 -1
  20. package/components/ChartPsp.vue +76 -0
  21. package/components/ClusterIconMenu.vue +9 -24
  22. package/components/CodeMirror.vue +16 -75
  23. package/components/CopyCode.vue +2 -6
  24. package/components/CopyToClipboard.vue +1 -2
  25. package/components/CopyToClipboardText.vue +9 -14
  26. package/components/CruResource.vue +0 -1
  27. package/components/EtcdInfoBanner.vue +5 -5
  28. package/components/ExplorerProjectsNamespaces.vue +1 -25
  29. package/components/FixedBanner.vue +0 -1
  30. package/components/IconOrSvg.vue +1 -1
  31. package/components/Markdown.vue +12 -16
  32. package/components/Questions/index.vue +1 -1
  33. package/components/ResourceDetail/Masthead.vue +9 -25
  34. package/components/ResourceDetail/index.vue +4 -1
  35. package/components/ResourceList/Masthead.vue +18 -1
  36. package/components/ResourceTable.vue +2 -14
  37. package/components/ResourceYaml.vue +5 -34
  38. package/components/SideNav.vue +65 -43
  39. package/components/SortableTable/THead.vue +9 -7
  40. package/components/SortableTable/index.vue +2 -1
  41. package/components/StatusTable.vue +1 -5
  42. package/components/TabTitle.vue +84 -0
  43. package/components/Tabbed/index.vue +0 -12
  44. package/components/YamlEditor.vue +0 -1
  45. package/components/__tests__/ChartPsp.test.ts +75 -0
  46. package/components/__tests__/CopyCode.test.ts +4 -5
  47. package/components/fleet/FleetBundles.vue +11 -5
  48. package/components/fleet/FleetRepos.vue +27 -62
  49. package/components/fleet/FleetResources.vue +1 -6
  50. package/components/fleet/FleetStatus.vue +3 -3
  51. package/components/fleet/FleetSummary.vue +30 -35
  52. package/components/form/ArrayList.vue +8 -1
  53. package/components/form/ArrayListSelect.vue +9 -9
  54. package/components/form/BannerSettings.vue +0 -3
  55. package/components/form/FileSelector.vue +0 -1
  56. package/components/form/KeyValue.vue +0 -2
  57. package/components/form/LabeledSelect.vue +0 -4
  58. package/components/form/Password.vue +1 -3
  59. package/components/form/Select.vue +1 -1
  60. package/components/form/SelectOrCreateAuthSecret.vue +4 -4
  61. package/components/form/__tests__/KeyValue.test.ts +1 -1
  62. package/components/formatter/Checked.vue +3 -11
  63. package/components/formatter/ClusterProvider.vue +18 -1
  64. package/components/formatter/FleetSummaryGraph.vue +11 -23
  65. package/components/formatter/LiveDate.vue +16 -0
  66. package/components/formatter/LiveDuration.vue +1 -1
  67. package/components/formatter/PercentageBar.vue +1 -1
  68. package/components/formatter/WorkloadDetailEndpoints.vue +22 -12
  69. package/components/formatter/__tests__/ClusterProvider.test.ts +28 -0
  70. package/components/nav/Group.vue +2 -2
  71. package/components/nav/Header.vue +2 -2
  72. package/components/nav/Jump.vue +9 -19
  73. package/components/nav/TopLevelMenu.vue +18 -66
  74. package/components/nav/Type.vue +7 -16
  75. package/components/nav/WindowManager/ContainerLogs.vue +19 -120
  76. package/components/nav/WindowManager/ContainerShell.vue +1 -6
  77. package/components/nav/WindowManager/index.vue +10 -11
  78. package/components/nav/__tests__/TopLevelMenu.test.ts +1 -34
  79. package/components/nav/__tests__/Type.test.ts +1 -31
  80. package/components/nuxt/nuxt-child.js +78 -14
  81. package/components/nuxt/nuxt.js +1 -1
  82. package/components/user.retention/user-retention-header.vue +34 -0
  83. package/composables/useI18n.ts +26 -0
  84. package/composables/useStore.ts +16 -0
  85. package/config/harvester-manager-types.js +0 -2
  86. package/config/home-links.js +32 -2
  87. package/config/private-label.js +0 -22
  88. package/config/product/explorer.js +4 -4
  89. package/config/product/fleet.js +1 -6
  90. package/config/product/legacy.js +1 -84
  91. package/config/product/manager.js +15 -8
  92. package/config/query-params.js +0 -1
  93. package/config/router.js +368 -385
  94. package/config/settings.ts +9 -2
  95. package/config/store.js +1 -1
  96. package/config/system-namespaces.js +0 -3
  97. package/config/table-headers.js +27 -47
  98. package/config/types.js +5 -0
  99. package/config/uiplugins.js +1 -1
  100. package/core/plugin-helpers.js +5 -3
  101. package/core/plugin-routes.ts +114 -56
  102. package/core/plugin.ts +10 -16
  103. package/core/plugins-loader.js +9 -7
  104. package/core/plugins.js +3 -0
  105. package/core/types-provisioning.ts +0 -7
  106. package/creators/app/init +0 -19
  107. package/detail/fleet.cattle.io.bundle.vue +1 -1
  108. package/detail/fleet.cattle.io.cluster.vue +1 -11
  109. package/detail/node.vue +0 -42
  110. package/detail/pod.vue +1 -68
  111. package/detail/provisioning.cattle.io.cluster.vue +8 -25
  112. package/detail/workload/index.vue +1 -15
  113. package/dialog/ScaleMachineDownDialog.vue +17 -34
  114. package/edit/auth/googleoauth.vue +5 -1
  115. package/edit/catalog.cattle.io.clusterrepo.vue +7 -20
  116. package/edit/cloudcredential.vue +0 -2
  117. package/edit/fleet.cattle.io.gitrepo.vue +4 -3
  118. package/edit/management.cattle.io.project.vue +52 -1
  119. package/edit/management.cattle.io.setting.vue +2 -32
  120. package/edit/monitoring.coreos.com.alertmanagerconfig/types/opsgenie.vue +1 -1
  121. package/edit/monitoring.coreos.com.alertmanagerconfig/types/pagerduty.vue +2 -1
  122. package/edit/monitoring.coreos.com.alertmanagerconfig/types/slack.vue +1 -1
  123. package/edit/monitoring.coreos.com.prometheusrule/AlertingRule.vue +3 -12
  124. package/edit/monitoring.coreos.com.prometheusrule/GroupRules.vue +1 -2
  125. package/edit/networking.k8s.io.networkpolicy/__tests__/PolicyRuleTarget.spec.ts +1 -1
  126. package/edit/provisioning.cattle.io.cluster/{tabs/Basics.vue → Basics.vue} +125 -106
  127. package/edit/provisioning.cattle.io.cluster/{tabs/MachinePool.vue → MachinePool.vue} +7 -1
  128. package/edit/provisioning.cattle.io.cluster/SelectCredential.vue +7 -15
  129. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.tests.ts +237 -0
  130. package/edit/provisioning.cattle.io.cluster/__tests__/{CustomCommand.test.ts → CustomCommand.tests.ts} +0 -6
  131. package/edit/provisioning.cattle.io.cluster/__tests__/DrainOptions.test.ts +1 -1
  132. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +1 -7
  133. package/edit/provisioning.cattle.io.cluster/import.vue +2 -2
  134. package/edit/provisioning.cattle.io.cluster/index.vue +40 -109
  135. package/edit/provisioning.cattle.io.cluster/rke2.vue +689 -152
  136. package/edit/service.vue +0 -12
  137. package/edit/token.vue +0 -1
  138. package/edit/workload/Upgrading.vue +2 -3
  139. package/edit/workload/index.vue +1 -2
  140. package/edit/workload/mixins/workload.js +1 -1
  141. package/initialize/App.js +71 -25
  142. package/initialize/client.js +162 -21
  143. package/initialize/index.js +124 -47
  144. package/initialize/layouts.ts +26 -0
  145. package/{components/templates → layouts}/blank.vue +1 -1
  146. package/{components/templates → layouts}/default.vue +98 -8
  147. package/{components/templates → layouts}/error.vue +19 -10
  148. package/{components/templates → layouts}/home.vue +1 -4
  149. package/{components/templates → layouts}/plain.vue +1 -4
  150. package/{components/templates → layouts}/standalone.vue +1 -1
  151. package/{components/templates → layouts}/unauthenticated.vue +1 -1
  152. package/list/catalog.cattle.io.app.vue +0 -1
  153. package/list/management.cattle.io.feature.vue +7 -1
  154. package/list/management.cattle.io.setting.vue +0 -1
  155. package/list/management.cattle.io.user.vue +25 -1
  156. package/list/node.vue +0 -1
  157. package/machine-config/__tests__/vmwarevsphere.test.ts +161 -56
  158. package/machine-config/azure.vue +37 -21
  159. package/machine-config/vmwarevsphere.vue +47 -42
  160. package/middleware/authenticated.js +19 -14
  161. package/mixins/auth-config.js +7 -2
  162. package/mixins/brand.js +41 -29
  163. package/mixins/fetch.server.js +73 -0
  164. package/mixins/labeled-form-element.ts +1 -6
  165. package/models/__tests__/management.cattle.io.node.ts +0 -85
  166. package/models/__tests__/namespace.test.ts +9 -49
  167. package/models/cluster/node.js +4 -4
  168. package/models/cluster.x-k8s.io.machine.js +1 -1
  169. package/models/cluster.x-k8s.io.machinedeployment.js +0 -14
  170. package/models/fleet.cattle.io.cluster.js +0 -4
  171. package/models/fleet.cattle.io.gitrepo.js +13 -56
  172. package/models/management.cattle.io.cluster.js +3 -11
  173. package/models/management.cattle.io.kontainerdriver.js +0 -1
  174. package/models/management.cattle.io.node.js +14 -18
  175. package/models/management.cattle.io.nodepool.js +0 -17
  176. package/models/management.cattle.io.project.js +36 -0
  177. package/models/management.cattle.io.setting.js +7 -11
  178. package/models/management.cattle.io.user.js +65 -0
  179. package/models/namespace.js +1 -1
  180. package/models/pod.js +0 -20
  181. package/models/provisioning.cattle.io.cluster.js +9 -91
  182. package/models/secret.js +18 -126
  183. package/models/storage.k8s.io.storageclass.js +1 -1
  184. package/models/workload.js +0 -16
  185. package/models/workload.service.js +0 -18
  186. package/package.json +10 -12
  187. package/pages/about.vue +1 -0
  188. package/pages/account/create-key.vue +1 -0
  189. package/pages/account/index.vue +1 -0
  190. package/pages/auth/login.vue +1 -0
  191. package/pages/auth/logout.vue +2 -0
  192. package/pages/auth/setup.vue +4 -37
  193. package/pages/auth/verify.vue +8 -14
  194. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +17 -2
  195. package/pages/c/_cluster/apps/charts/index.vue +58 -64
  196. package/pages/c/_cluster/apps/charts/install.helpers.js +13 -2
  197. package/pages/c/_cluster/apps/charts/install.vue +5 -5
  198. package/pages/c/_cluster/apps/index.vue +2 -0
  199. package/pages/c/_cluster/auth/index.vue +2 -0
  200. package/pages/c/_cluster/auth/user.retention/index.vue +384 -0
  201. package/pages/c/_cluster/ecm/index.vue +2 -0
  202. package/pages/c/_cluster/explorer/index.vue +53 -56
  203. package/pages/c/_cluster/explorer/tools/index.vue +3 -171
  204. package/pages/c/_cluster/fleet/index.vue +1 -1
  205. package/pages/c/_cluster/index.vue +2 -0
  206. package/pages/c/_cluster/manager/pages/_page.vue +5 -4
  207. package/pages/c/_cluster/monitoring/index.vue +1 -17
  208. package/pages/c/_cluster/settings/DefaultLinksEditor.vue +1 -1
  209. package/pages/c/_cluster/settings/banners.vue +2 -0
  210. package/pages/c/_cluster/settings/brand.vue +2 -3
  211. package/pages/c/_cluster/settings/index.vue +2 -0
  212. package/pages/c/_cluster/settings/links.vue +3 -2
  213. package/pages/c/_cluster/settings/performance.vue +1 -0
  214. package/pages/c/_cluster/uiplugins/CatalogList/CatalogLoadDialog.vue +1 -2
  215. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +46 -10
  216. package/pages/c/_cluster/uiplugins/index.vue +2 -0
  217. package/pages/c/index.vue +9 -0
  218. package/pages/diagnostic.vue +2 -1
  219. package/pages/fail-whale.vue +1 -0
  220. package/pages/prefs.vue +1 -0
  221. package/pages/rio/mesh.vue +508 -0
  222. package/pages/support/index.vue +8 -2
  223. package/pkg/auto-import.js +1 -1
  224. package/plugins/axios.js +36 -0
  225. package/plugins/back-button.js +5 -3
  226. package/plugins/clean-html-directive.js +19 -1
  227. package/plugins/clean-tooltip-directive.js +1 -1
  228. package/plugins/codemirror-loader.js +1 -1
  229. package/plugins/codemirror.js +0 -41
  230. package/plugins/dashboard-store/__tests__/{mutations.test.ts → mutations.spec.ts} +1 -1
  231. package/plugins/dashboard-store/actions.js +17 -16
  232. package/plugins/dashboard-store/classify.js +18 -1
  233. package/plugins/dashboard-store/getters.js +7 -70
  234. package/plugins/dashboard-store/index.js +12 -0
  235. package/plugins/dashboard-store/mutations.js +4 -0
  236. package/plugins/dashboard-store/resource-class.js +20 -65
  237. package/plugins/i18n.js +1 -1
  238. package/plugins/steve/__tests__/getters.spec.ts +48 -26
  239. package/plugins/steve/__tests__/subscribe.spec.ts +106 -0
  240. package/plugins/steve/actions.js +37 -3
  241. package/plugins/steve/getters.js +24 -7
  242. package/plugins/steve/mutations.js +5 -2
  243. package/plugins/steve/norman-class.js +0 -19
  244. package/plugins/steve/steve-class.js +0 -22
  245. package/plugins/steve/subscribe.js +34 -13
  246. package/plugins/transitions.js +4 -0
  247. package/plugins/vue-clipboard2.js +4 -0
  248. package/rancher-components/Accordion/Accordion.vue +3 -2
  249. package/rancher-components/BadgeState/BadgeState.vue +3 -3
  250. package/rancher-components/Banner/Banner.test.ts +1 -5
  251. package/rancher-components/Banner/Banner.vue +2 -2
  252. package/rancher-components/Card/Card.vue +4 -4
  253. package/rancher-components/Form/Checkbox/Checkbox.vue +4 -3
  254. package/rancher-components/Form/LabeledInput/LabeledInput.test.ts +1 -1
  255. package/rancher-components/Form/LabeledInput/LabeledInput.vue +55 -24
  256. package/rancher-components/Form/Radio/RadioButton.test.ts +1 -3
  257. package/rancher-components/Form/Radio/RadioButton.vue +13 -7
  258. package/rancher-components/Form/Radio/RadioGroup.vue +4 -3
  259. package/rancher-components/Form/TextArea/TextAreaAutoGrow.vue +7 -5
  260. package/rancher-components/Form/ToggleSwitch/ToggleSwitch.vue +7 -4
  261. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +9 -4
  262. package/rancher-components/StringList/StringList.vue +8 -8
  263. package/rancher-components/components/Accordion/Accordion.vue +3 -2
  264. package/rancher-components/components/BadgeState/BadgeState.test.ts +12 -0
  265. package/rancher-components/components/Form/LabeledInput/LabeledInput.test.ts +2 -19
  266. package/rancher-components/components/Form/LabeledInput/LabeledInput.vue +14 -11
  267. package/rancher-components/components/Form/TextArea/TextAreaAutoGrow.vue +1 -1
  268. package/rancher-components/components/StringList/StringList.test.ts +0 -270
  269. package/rancher-components/components/StringList/StringList.vue +18 -57
  270. package/scripts/extension/bundle +7 -19
  271. package/scripts/extension/helm/scripts/package +3 -11
  272. package/scripts/extension/parse-tag-name +4 -4
  273. package/scripts/extension/publish +9 -20
  274. package/scripts/publish-shell.sh +1 -11
  275. package/scripts/test-plugins-build.sh +9 -85
  276. package/store/catalog.js +1 -1
  277. package/store/features.js +0 -1
  278. package/store/i18n.js +0 -11
  279. package/store/index.js +13 -11
  280. package/store/prefs.js +38 -33
  281. package/store/type-map.js +82 -157
  282. package/tsconfig.default.json +46 -0
  283. package/tsconfig.json +9 -35
  284. package/types/shell/index.d.ts +404 -465
  285. package/utils/axios.js +19 -0
  286. package/utils/create-yaml.js +1 -5
  287. package/utils/custom-validators.js +2 -0
  288. package/utils/error.js +1 -16
  289. package/utils/monitoring.js +2 -37
  290. package/utils/nuxt.js +39 -18
  291. package/utils/object.js +0 -24
  292. package/utils/router.scrollBehavior.js +14 -12
  293. package/utils/socket.js +1 -0
  294. package/utils/time.js +1 -1
  295. package/utils/title.ts +3 -0
  296. package/utils/url.ts +1 -1
  297. package/utils/validators/formRules/__tests__/index.test.ts +4 -49
  298. package/utils/validators/formRules/index.ts +9 -12
  299. package/utils/validators/setting.js +10 -6
  300. package/vue.config.js +3 -24
  301. package/chart/monitoring/steps/uninstall-v1.vue +0 -135
  302. package/components/Certificates.vue +0 -164
  303. package/components/__tests__/CodeMirror.spec.ts +0 -99
  304. package/components/fleet/__tests__/FleetSummary.test.ts +0 -316
  305. package/components/formatter/FleetClusterSummaryGraph.vue +0 -27
  306. package/components/formatter/__tests__/Checked.test.ts +0 -19
  307. package/components/formatter/__tests__/WorkloadDetailEndpoints.test.ts +0 -81
  308. package/components/nav/WindowManager/__tests__/ContainerLogs.test.ts +0 -186
  309. package/composables/useCompactInput.ts +0 -20
  310. package/composables/useLabeledFormElement.ts +0 -138
  311. package/creators/app/files/.gitlab-ci.yml +0 -14
  312. package/detail/__tests__/provisioning.cattle.io.cluster.test.ts +0 -77
  313. package/edit/__tests__/service.test.ts +0 -89
  314. package/edit/provisioning.cattle.io.cluster/__tests__/Advanced.test.ts +0 -112
  315. package/edit/provisioning.cattle.io.cluster/__tests__/Basics.test.ts +0 -473
  316. package/edit/provisioning.cattle.io.cluster/__tests__/index.test.ts +0 -73
  317. package/edit/provisioning.cattle.io.cluster/__tests__/utils/cluster.ts +0 -386
  318. package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +0 -137
  319. package/edit/provisioning.cattle.io.cluster/tabs/Advanced.vue +0 -157
  320. package/edit/provisioning.cattle.io.cluster/tabs/etcd/index.vue +0 -135
  321. package/edit/provisioning.cattle.io.cluster/tabs/networking/index.vue +0 -189
  322. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +0 -147
  323. package/edit/provisioning.cattle.io.cluster/tabs/upgrade/index.vue +0 -76
  324. package/mixins/v1-workload-metrics.js +0 -43
  325. package/models/__tests__/management.cattle.io.cluster.test.ts +0 -23
  326. package/models/__tests__/management.cattle.io.nodepool.ts +0 -83
  327. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +0 -241
  328. package/models/__tests__/secret.test.ts +0 -37
  329. package/models/__tests__/storage.k8s.io.storageclass.test.ts +0 -22
  330. package/models/__tests__/workload.test.ts +0 -91
  331. package/plugins/clean-html.js +0 -53
  332. package/plugins/dashboard-store/__tests__/resource-class.test.ts +0 -49
  333. package/plugins/dashboard-store/__tests__/utils/store-mocks.ts +0 -7
  334. package/plugins/index.js +0 -11
  335. package/plugins/steve/__tests__/resource-utils.test.ts +0 -159
  336. package/plugins/steve/__tests__/steve-class.spec.ts +0 -59
  337. package/plugins/steve/__tests__/utils/steve-mocks.ts +0 -31
  338. package/plugins/steve/resource-utils.ts +0 -38
  339. package/scripts/.gitlab/workflows/build-extension-catalog.gitlab-ci.yml +0 -50
  340. package/server/har-file.js +0 -183
  341. package/store/__tests__/type-map.test.ts +0 -1122
  342. package/tsconfig.paths.json +0 -18
  343. package/utils/azure.js +0 -24
  344. package/utils/clipboard.js +0 -5
  345. /package/components/form/__tests__/{NameNsDescription.test.ts → NameNsDescription.ts} +0 -0
  346. /package/edit/networking.k8s.io.networkpolicy/__tests__/utils/{selectors.test.ts → selectors.ts} +0 -0
  347. /package/edit/provisioning.cattle.io.cluster/{tabs/networking/ACE.vue → ACE.vue} +0 -0
  348. /package/edit/provisioning.cattle.io.cluster/{tabs/AgentConfiguration.vue → AgentConfiguration.vue} +0 -0
  349. /package/edit/provisioning.cattle.io.cluster/{tabs/upgrade/DrainOptions.vue → DrainOptions.vue} +0 -0
  350. /package/edit/provisioning.cattle.io.cluster/{tabs/MemberRoles.vue → MemberRoles.vue} +0 -0
  351. /package/edit/provisioning.cattle.io.cluster/{tabs/registries/RegistryConfigs.vue → RegistryConfigs.vue} +0 -0
  352. /package/edit/provisioning.cattle.io.cluster/{tabs/registries/RegistryMirrors.vue → RegistryMirrors.vue} +0 -0
  353. /package/edit/provisioning.cattle.io.cluster/{tabs/etcd/S3Config.vue → S3Config.vue} +0 -0
  354. /package/plugins/dashboard-store/__tests__/{actions.test.ts → actions.spec.ts} +0 -0
  355. /package/plugins/dashboard-store/__tests__/{getters.test.ts → getters.spec.ts} +0 -0
  356. /package/rancher-components/BadgeState/{BadgeState.spec.ts → BadgeState.test.ts} +0 -0
@@ -16,6 +16,7 @@ import { integerString, keyValueStrings } from '@shell/utils/computed';
16
16
  import { _CREATE, _EDIT, _VIEW } from '@shell/config/query-params';
17
17
 
18
18
  export const SENTINEL = '__SENTINEL__';
19
+ const NULLABLE_EMPTY_FIELDS = ['contentLibrary', 'folder', 'hostsystem'];
19
20
  const VAPP_MODE = {
20
21
  DISABLED: 'disabled',
21
22
  AUTO: 'auto',
@@ -168,7 +169,11 @@ export default {
168
169
  },
169
170
  disabled: {
170
171
  type: Boolean,
171
- default: false
172
+ default: false,
173
+ },
174
+ poolCreateMode: {
175
+ type: Boolean,
176
+ required: true,
172
177
  },
173
178
  },
174
179
 
@@ -223,7 +228,7 @@ export default {
223
228
  },
224
229
  ];
225
230
 
226
- if (this.mode === _CREATE && !this.value.initted) {
231
+ if ((this.mode === _CREATE || this.poolCreateMode) && !this.value.initted) {
227
232
  Object.defineProperty(this.value, 'initted', { value: true, enumerable: false });
228
233
 
229
234
  const {
@@ -296,10 +301,6 @@ export default {
296
301
  ...createOptionHelpers('attributeKeys'),
297
302
  ...createOptionHelpers('networks'),
298
303
 
299
- isDisabled() {
300
- return this.disabled || this.mode === _VIEW;
301
- },
302
-
303
304
  showTemplate() {
304
305
  return this.value.creationType === 'template';
305
306
  },
@@ -444,13 +445,13 @@ export default {
444
445
  const valueInContent = content.find((c) => c.value === this.value.datacenter );
445
446
 
446
447
  if (!valueInContent) {
447
- if (this.mode === _CREATE) {
448
+ if (this.mode === _CREATE || this.poolCreateMode) {
448
449
  set(this.value, 'datacenter', options[0]);
449
450
  set(this.value, 'cloneFrom', undefined);
450
451
  set(this.value, 'useDataStoreCluster', false);
451
452
  }
452
453
 
453
- if ([_EDIT, _VIEW].includes(this.mode)) {
454
+ if ([_EDIT, _VIEW].includes(this.mode) && !this.poolCreateMode) {
454
455
  this.manageErrors(errorActions.CREATE, 'datacenter');
455
456
  }
456
457
  } else {
@@ -650,15 +651,19 @@ export default {
650
651
  };
651
652
 
652
653
  if (!isValueInContent()) {
653
- if (this.mode === _CREATE) {
654
- const value = isArray ? [] : content[0]?.value;
655
-
656
- if (value !== SENTINEL) {
657
- set(this.value, key, value);
658
- }
654
+ const value = isArray ? [] : content[0]?.value;
655
+ const isNullOrEmpty = NULLABLE_EMPTY_FIELDS.includes(key) && (this.value[key] === null || this.value[key] === '');
656
+ const shouldHandleError =
657
+ [_EDIT, _VIEW].includes(this.mode) && // error messages should only be displayed in Edit or View mode
658
+ !this.poolCreateMode && // almost identical to Create mode
659
+ !isNullOrEmpty && // null and empty string are valid values for some fields e.g. contentLibrary, folder and hostsystem
660
+ !isArray; // this flag is used for network and tag fields, and should not display error for them
661
+
662
+ if ((this.mode === _CREATE || this.poolCreateMode) && value !== SENTINEL) {
663
+ set(this.value, key, value);
659
664
  }
660
665
 
661
- if ([_EDIT, _VIEW].includes(this.mode)) {
666
+ if (shouldHandleError) {
662
667
  this.manageErrors(errorActions.CREATE, key);
663
668
  }
664
669
  } else {
@@ -775,7 +780,7 @@ export default {
775
780
  :mode="mode"
776
781
  :options="dataCenters"
777
782
  :label="t('cluster.machineConfig.vsphere.scheduling.dataCenter')"
778
- :disabled="isDisabled"
783
+ :disabled="disabled"
779
784
  :tooltip="value.datacenter"
780
785
  />
781
786
  </div>
@@ -789,7 +794,7 @@ export default {
789
794
  :mode="mode"
790
795
  :options="resourcePools"
791
796
  :label="t('cluster.machineConfig.vsphere.scheduling.resourcePool')"
792
- :disabled="isDisabled"
797
+ :disabled="disabled"
793
798
  :tooltip="value.pool"
794
799
  />
795
800
  </div>
@@ -805,7 +810,7 @@ export default {
805
810
  :mode="mode"
806
811
  :options="dataStores"
807
812
  :label="t('cluster.machineConfig.vsphere.scheduling.dataStore')"
808
- :disabled="isDisabled"
813
+ :disabled="disabled"
809
814
  :tooltip="value.datastore"
810
815
  />
811
816
  </div>
@@ -819,7 +824,7 @@ export default {
819
824
  :mode="mode"
820
825
  :options="folders"
821
826
  :label="t('cluster.machineConfig.vsphere.scheduling.folder')"
822
- :disabled="isDisabled"
827
+ :disabled="disabled"
823
828
  :tooltip="value.folder"
824
829
  />
825
830
  </div>
@@ -835,7 +840,7 @@ export default {
835
840
  :mode="mode"
836
841
  :options="hosts"
837
842
  :label="t('cluster.machineConfig.vsphere.scheduling.host.label')"
838
- :disabled="isDisabled"
843
+ :disabled="disabled"
839
844
  :tooltip="host"
840
845
  />
841
846
  <p class="text-muted mt-5">
@@ -851,7 +856,7 @@ export default {
851
856
  :mode="mode"
852
857
  :label="t('cluster.machineConfig.vsphere.scheduling.gracefulShutdownTimeout.label')"
853
858
  :suffix="t('suffix.seconds', { count: gracefulShutdownTimeout})"
854
- :disabled="isDisabled"
859
+ :disabled="disabled"
855
860
  min="0"
856
861
  />
857
862
  <p class="text-muted mt-5">
@@ -883,7 +888,7 @@ export default {
883
888
  :mode="mode"
884
889
  :label="t('cluster.machineConfig.vsphere.instanceOptions.cpus')"
885
890
  :suffix="t('suffix.cores')"
886
- :disabled="isDisabled"
891
+ :disabled="disabled"
887
892
  />
888
893
  </div>
889
894
  <div class="col span-6">
@@ -892,7 +897,7 @@ export default {
892
897
  :mode="mode"
893
898
  :label="t('cluster.machineConfig.vsphere.instanceOptions.memory')"
894
899
  :suffix="t('suffix.mib')"
895
- :disabled="isDisabled"
900
+ :disabled="disabled"
896
901
  />
897
902
  </div>
898
903
  </div>
@@ -903,7 +908,7 @@ export default {
903
908
  :mode="mode"
904
909
  :label="t('cluster.machineConfig.vsphere.instanceOptions.disk')"
905
910
  :suffix="t('suffix.mib')"
906
- :disabled="isDisabled"
911
+ :disabled="disabled"
907
912
  />
908
913
  </div>
909
914
  <div class="col span-6">
@@ -912,7 +917,7 @@ export default {
912
917
  :mode="mode"
913
918
  :options="osOptions"
914
919
  :label="t('cluster.machineConfig.vsphere.instanceOptions.os')"
915
- :disabled="isDisabled"
920
+ :disabled="disabled"
916
921
  />
917
922
  </div>
918
923
  </div>
@@ -926,7 +931,7 @@ export default {
926
931
  :mode="mode"
927
932
  :options="creationMethods"
928
933
  :label="t('cluster.machineConfig.vsphere.instanceOptions.creationMethod')"
929
- :disabled="isDisabled"
934
+ :disabled="disabled"
930
935
  />
931
936
  </div>
932
937
  <div
@@ -939,7 +944,7 @@ export default {
939
944
  :mode="mode"
940
945
  :options="templates"
941
946
  :label="t('cluster.machineConfig.vsphere.instanceOptions.template.label')"
942
- :disabled="isDisabled"
947
+ :disabled="disabled"
943
948
  :status="templateStatus"
944
949
  :tooltip="templateTooltip"
945
950
  />
@@ -954,7 +959,7 @@ export default {
954
959
  :mode="mode"
955
960
  :options="contentLibraries"
956
961
  :label="t('cluster.machineConfig.vsphere.instanceOptions.contentLibrary')"
957
- :disabled="isDisabled"
962
+ :disabled="disabled"
958
963
  />
959
964
  </div>
960
965
  <div
@@ -968,7 +973,7 @@ export default {
968
973
  :options="libraryTemplates"
969
974
  :searchable="true"
970
975
  :label="t('cluster.machineConfig.vsphere.instanceOptions.libraryTemplate')"
971
- :disabled="isDisabled"
976
+ :disabled="disabled"
972
977
  :tooltip="value.cloneFrom"
973
978
  />
974
979
  </div>
@@ -982,7 +987,7 @@ export default {
982
987
  :mode="mode"
983
988
  :options="virtualMachines"
984
989
  :label="t('cluster.machineConfig.vsphere.instanceOptions.virtualMachine')"
985
- :disabled="isDisabled"
990
+ :disabled="disabled"
986
991
  :tooltip="value.cloneFrom"
987
992
  />
988
993
  </div>
@@ -995,7 +1000,7 @@ export default {
995
1000
  :mode="mode"
996
1001
  :label="t('cluster.machineConfig.vsphere.instanceOptions.osIsoUrl.label')"
997
1002
  :placeholder="t('cluster.machineConfig.vsphere.instanceOptions.osIsoUrl.placeholder')"
998
- :disabled="isDisabled"
1003
+ :disabled="disabled"
999
1004
  />
1000
1005
  </div>
1001
1006
  </div>
@@ -1009,7 +1014,7 @@ export default {
1009
1014
  :mode="mode"
1010
1015
  :label="t('cluster.machineConfig.vsphere.instanceOptions.cloudInit.label')"
1011
1016
  :placeholder="t('cluster.machineConfig.vsphere.instanceOptions.cloudInit.placeholder')"
1012
- :disabled="isDisabled"
1017
+ :disabled="disabled"
1013
1018
  />
1014
1019
  <p class="text-muted mt-5">
1015
1020
  {{ t('cluster.machineConfig.vsphere.instanceOptions.cloudInit.note') }}
@@ -1026,7 +1031,7 @@ export default {
1026
1031
  ref="yaml-additional"
1027
1032
  v-model="value.cloudConfig"
1028
1033
  :editor-mode="mode === 'view' ? 'VIEW_CODE' : 'EDIT_CODE'"
1029
- :disabled="isDisabled"
1034
+ :disabled="disabled"
1030
1035
  initial-yaml-values="# Additional Manifest YAML"
1031
1036
  class="yaml-editor"
1032
1037
  />
@@ -1042,7 +1047,7 @@ export default {
1042
1047
  :options="networks"
1043
1048
  :array-list-props="{ addLabel: t('cluster.machineConfig.vsphere.networks.add') }"
1044
1049
  :loading="networksLoading"
1045
- :disabled="isDisabled"
1050
+ :disabled="disabled"
1046
1051
  />
1047
1052
  </div>
1048
1053
  </div>
@@ -1057,7 +1062,7 @@ export default {
1057
1062
  :key-placeholder="t('cluster.machineConfig.vsphere.guestinfo.keyPlaceholder')"
1058
1063
  :value-placeholder="t('cluster.machineConfig.vsphere.guestinfo.valuePlaceholder')"
1059
1064
  :read-allowed="false"
1060
- :disabled="isDisabled"
1065
+ :disabled="disabled"
1061
1066
  />
1062
1067
  </div>
1063
1068
  </div>
@@ -1084,7 +1089,7 @@ export default {
1084
1089
  :options="tags"
1085
1090
  :array-list-props="{ addLabel: t('cluster.machineConfig.vsphere.tags.addTag') }"
1086
1091
  :loading="tagsLoading"
1087
- :disabled="isDisabled"
1092
+ :disabled="disabled"
1088
1093
  />
1089
1094
  </div>
1090
1095
  </Card>
@@ -1113,7 +1118,7 @@ export default {
1113
1118
  :loading="attributeKeysLoading"
1114
1119
  :key-taggable="false"
1115
1120
  :key-option-unique="true"
1116
- :disabled="isDisabled"
1121
+ :disabled="disabled"
1117
1122
  />
1118
1123
  </div>
1119
1124
  </Card>
@@ -1139,7 +1144,7 @@ export default {
1139
1144
  name="restoreMode"
1140
1145
  :label="t('cluster.machineConfig.vsphere.vAppOptions.restoreType')"
1141
1146
  :options="vAppOptions"
1142
- :disabled="isDisabled"
1147
+ :disabled="disabled"
1143
1148
  />
1144
1149
  </div>
1145
1150
  </div>
@@ -1154,7 +1159,7 @@ export default {
1154
1159
  :label="t('cluster.machineConfig.vsphere.vAppOptions.transport.label')"
1155
1160
  :tooltip="t('cluster.machineConfig.vsphere.vAppOptions.transport.tooltip')"
1156
1161
  :placeholder="t('cluster.machineConfig.vsphere.vAppOptions.transport.placeholder')"
1157
- :disabled="isDisabled"
1162
+ :disabled="disabled"
1158
1163
  />
1159
1164
  </div>
1160
1165
  <div class="col span-4">
@@ -1164,7 +1169,7 @@ export default {
1164
1169
  :label="t('cluster.machineConfig.vsphere.vAppOptions.protocol.label')"
1165
1170
  :tooltip="t('cluster.machineConfig.vsphere.vAppOptions.protocol.tooltip')"
1166
1171
  :placeholder="t('cluster.machineConfig.vsphere.vAppOptions.protocol.placeholder')"
1167
- :disabled="isDisabled"
1172
+ :disabled="disabled"
1168
1173
  />
1169
1174
  </div>
1170
1175
  <div class="col span-4">
@@ -1174,7 +1179,7 @@ export default {
1174
1179
  :label="t('cluster.machineConfig.vsphere.vAppOptions.allocation.label')"
1175
1180
  :tooltip="t('cluster.machineConfig.vsphere.vAppOptions.allocation.tooltip')"
1176
1181
  :placeholder="t('cluster.machineConfig.vsphere.vAppOptions.allocation.placeholder')"
1177
- :disabled="isDisabled"
1182
+ :disabled="disabled"
1178
1183
  />
1179
1184
  </div>
1180
1185
  </div>
@@ -1190,7 +1195,7 @@ export default {
1190
1195
  :value-placeholder="t('cluster.machineConfig.vsphere.vAppOptions.properties.valuePlaceholder')"
1191
1196
  :add-label="t('cluster.machineConfig.vsphere.vAppOptions.properties.add')"
1192
1197
  :read-allowed="false"
1193
- :disabled="isDisabled"
1198
+ :disabled="disabled"
1194
1199
  />
1195
1200
  </div>
1196
1201
  </div>
@@ -8,7 +8,7 @@ import { MANAGEMENT, NORMAN, DEFAULT_WORKSPACE } from '@shell/config/types';
8
8
  import { _ALL_IF_AUTHED } from '@shell/plugins/dashboard-store/actions';
9
9
  import { applyProducts } from '@shell/store/type-map';
10
10
  import { findBy } from '@shell/utils/array';
11
- import { ClusterNotFoundError, RedirectToError } from '@shell/utils/error';
11
+ import { ClusterNotFoundError } from '@shell/utils/error';
12
12
  import { get } from '@shell/utils/object';
13
13
  import { setFavIcon, haveSetFavIcon } from '@shell/utils/favicon';
14
14
  import dynamicPluginLoader from '@shell/pkg/dynamic-plugin-loader';
@@ -305,6 +305,9 @@ export default async function({
305
305
  notLoggedIn();
306
306
  } else {
307
307
  store.commit('setError', { error: e, locationError: new Error('Auth Middleware') });
308
+ if ( process.server ) {
309
+ redirect(302, '/fail-whale');
310
+ }
308
311
  }
309
312
 
310
313
  return;
@@ -315,12 +318,14 @@ export default async function({
315
318
  store.dispatch('gcStartIntervals');
316
319
  }
317
320
 
318
- const backTo = window.localStorage.getItem(BACK_TO);
321
+ if (!process.server) {
322
+ const backTo = window.localStorage.getItem(BACK_TO);
319
323
 
320
- if (backTo) {
321
- window.localStorage.removeItem(BACK_TO);
324
+ if (backTo) {
325
+ window.localStorage.removeItem(BACK_TO);
322
326
 
323
- window.location.href = backTo;
327
+ window.location.href = backTo;
328
+ }
324
329
  }
325
330
 
326
331
  // GC should be notified of route change before any find/get request is made that might be used for that page
@@ -361,12 +366,14 @@ export default async function({
361
366
  return redirected();
362
367
  }
363
368
 
364
- store.app.router.afterEach((to, from) => {
365
- // Clear state used to record if back button was used for navigation
366
- setTimeout(() => {
367
- window._popStateDetected = false;
368
- }, 1);
369
- });
369
+ if (process.client) {
370
+ store.app.router.afterEach((to, from) => {
371
+ // Clear state used to record if back button was used for navigation
372
+ setTimeout(() => {
373
+ window._popStateDetected = false;
374
+ }, 1);
375
+ });
376
+ }
370
377
  }
371
378
 
372
379
  try {
@@ -495,10 +502,8 @@ export default async function({
495
502
  }
496
503
  }
497
504
  } catch (e) {
498
- if ( e.name === ClusterNotFoundError.name ) {
505
+ if ( e instanceof ClusterNotFoundError ) {
499
506
  return redirect(302, '/home');
500
- } if ( e.name === RedirectToError.name ) {
501
- return redirect(302, e.url);
502
507
  } else {
503
508
  // Sets error 500 if lost connection to API
504
509
  store.commit('setError', { error: e, locationError: new Error(store.getters['i18n/t']('nav.failWhale.authMiddleware')) });
@@ -42,8 +42,13 @@ export default {
42
42
  },
43
43
 
44
44
  serverUrl() {
45
- // Client-side rendered: use the current window location
46
- return window.location.origin;
45
+ if (process.client) {
46
+ // Client-side rendered: use the current window location
47
+ return window.location.origin;
48
+ }
49
+
50
+ // Server-side rendered
51
+ return this.serverSetting || '';
47
52
  },
48
53
 
49
54
  baseUrl() {
package/mixins/brand.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { mapGetters } from 'vuex';
2
2
  import { CATALOG, MANAGEMENT } from '@shell/config/types';
3
+ import { getVendor } from '@shell/config/private-label';
3
4
  import { SETTING } from '@shell/config/settings';
4
5
  import { findBy } from '@shell/utils/array';
5
6
  import { createCssVars } from '@shell/utils/color';
6
7
  import { _ALL_IF_AUTHED } from '@shell/plugins/dashboard-store/actions';
7
- import { setTitle } from '@shell/config/private-label';
8
8
 
9
9
  const cspAdaptorApp = ['rancher-csp-adapter', 'rancher-csp-billing-adapter'];
10
10
 
@@ -116,7 +116,6 @@ export default {
116
116
  if (this.linkColor) {
117
117
  this.setCustomColor(this.linkColor, 'link');
118
118
  }
119
- this.setBodyClass();
120
119
  },
121
120
 
122
121
  cspAdapter(neu) {
@@ -143,15 +142,7 @@ export default {
143
142
  }
144
143
  }
145
144
  }
146
- },
147
- brand() {
148
- this.setBodyClass();
149
145
  }
150
-
151
- },
152
- mounted() {
153
- this.setBodyClass();
154
- setTitle();
155
146
  },
156
147
  methods: {
157
148
  setCustomColor(color, name = 'primary') {
@@ -168,26 +159,47 @@ export default {
168
159
  for (const prop in vars) {
169
160
  document.body.style.removeProperty(prop);
170
161
  }
171
- },
172
- setBodyClass() {
173
- const body = document.getElementsByTagName('body')[0];
174
- const cssClass = `overflow-hidden dashboard-body`;
175
- let bodyClass = `theme-${ this.theme } ${ cssClass }`;
176
-
177
- if ( this.brand ) {
178
- try {
179
- const brandMeta = require(`~shell/assets/brand/${ this.brand }/metadata.json`);
180
-
181
- if (brandMeta?.hasStylesheet === 'true') {
182
- bodyClass = `${ cssClass } ${ this.brand } theme-${ this.theme }`;
183
- } else {
184
- bodyClass = `theme-${ this.theme } overflow-hidden dashboard-body`;
185
- this.$store.dispatch('prefs/setBrandStyle', this.theme === 'dark');
186
- }
187
- } catch {}
162
+ }
163
+ },
164
+ head() {
165
+ let cssClass = `overflow-hidden dashboard-body`;
166
+ const out = {
167
+ bodyAttrs: { class: `theme-${ this.theme } ${ cssClass }` },
168
+ title: getVendor(),
169
+ };
170
+
171
+ if (getVendor() === 'Harvester') {
172
+ const ico = require(`~shell/assets/images/pl/harvester.png`);
173
+
174
+ out.title = 'Harvester';
175
+ out.link = [{
176
+ hid: 'icon',
177
+ rel: 'icon',
178
+ type: 'image/x-icon',
179
+ href: ico
180
+ }];
181
+ }
182
+
183
+ let brandMeta;
184
+
185
+ if ( this.brand ) {
186
+ try {
187
+ brandMeta = require(`~shell/assets/brand/${ this.brand }/metadata.json`);
188
+ } catch {
189
+ return out;
188
190
  }
189
- body.className = bodyClass;
190
191
  }
191
- }
192
+
193
+ if (brandMeta?.hasStylesheet === 'true') {
194
+ cssClass = `${ cssClass } ${ this.brand } theme-${ this.theme }`;
195
+ } else {
196
+ cssClass = `theme-${ this.theme } overflow-hidden dashboard-body`;
197
+ this.$store.dispatch('prefs/setBrandStyle', this.theme === 'dark');
198
+ }
199
+
200
+ out.bodyAttrs.class = cssClass;
201
+
202
+ return out;
203
+ },
192
204
 
193
205
  };
@@ -0,0 +1,73 @@
1
+ import Vue from 'vue';
2
+ import {
3
+ hasFetch, normalizeError, addLifecycleHook, purifyData, createGetCounter
4
+ } from '../../utils/nuxt';
5
+
6
+ async function serverPrefetch() {
7
+ if (!this._fetchOnServer) {
8
+ return;
9
+ }
10
+
11
+ // Call and await on $fetch
12
+ try {
13
+ await this.$options.fetch.call(this);
14
+ } catch (err) {
15
+ if (process.dev) {
16
+ console.error('Error in fetch():', err); // eslint-disable-line no-console
17
+ }
18
+ this.$fetchState.error = normalizeError(err);
19
+ }
20
+ this.$fetchState.pending = false;
21
+
22
+ // Define an ssrKey for hydration
23
+ this._fetchKey = this._fetchKey || this.$ssrContext.fetchCounters['']++;
24
+
25
+ // Add data-fetch-key on parent element of Component
26
+ const attrs = this.$vnode.data.attrs = this.$vnode.data.attrs || {};
27
+
28
+ attrs['data-fetch-key'] = this._fetchKey;
29
+
30
+ // Add to ssrContext for window.__NUXT__.fetch
31
+
32
+ if (this.$ssrContext.nuxt.fetch[this._fetchKey] !== undefined) {
33
+ console.warn(`Duplicate fetch key detected (${ this._fetchKey }). This may lead to unexpected results.`); // eslint-disable-line no-console
34
+ }
35
+
36
+ this.$ssrContext.nuxt.fetch[this._fetchKey] =
37
+ this.$fetchState.error ? { _error: this.$fetchState.error } : purifyData(this._data);
38
+ }
39
+
40
+ export default {
41
+ created() {
42
+ if (!hasFetch(this)) {
43
+ return;
44
+ }
45
+
46
+ if (typeof this.$options.fetchOnServer === 'function') {
47
+ this._fetchOnServer = this.$options.fetchOnServer.call(this) !== false;
48
+ } else {
49
+ this._fetchOnServer = this.$options.fetchOnServer !== false;
50
+ }
51
+
52
+ const defaultKey = this.$options._scopeId || this.$options.name || '';
53
+ const getCounter = createGetCounter(this.$ssrContext.fetchCounters, defaultKey);
54
+
55
+ if (typeof this.$options.fetchKey === 'function') {
56
+ this._fetchKey = this.$options.fetchKey.call(this, getCounter);
57
+ } else {
58
+ const key = typeof this.$options.fetchKey === 'string' ? this.$options.fetchKey : defaultKey;
59
+
60
+ this._fetchKey = key ? `${ key }:${ getCounter(key) }` : String(getCounter(key));
61
+ }
62
+
63
+ // Added for remove vue undefined warning while ssr
64
+ this.$fetch = () => {}; // issue #8043
65
+ Vue.util.defineReactive(this, '$fetchState', {
66
+ pending: true,
67
+ error: null,
68
+ timestamp: Date.now()
69
+ });
70
+
71
+ addLifecycleHook(this, 'serverPrefetch', serverPrefetch);
72
+ }
73
+ };
@@ -82,11 +82,6 @@ export default Vue.extend({
82
82
  type: Array,
83
83
  // we only want functions in the rules array
84
84
  validator: (rules: any) => rules.every((rule: any) => ['function'].includes(typeof rule))
85
- },
86
-
87
- requireDirty: {
88
- default: true,
89
- type: Boolean
90
85
  }
91
86
  },
92
87
 
@@ -146,7 +141,7 @@ export default Vue.extend({
146
141
  ruleMessages.push(message);
147
142
  }
148
143
  }
149
- if (ruleMessages.length > 0 && (this.blurred || this.focused || !this.requireDirty)) {
144
+ if (ruleMessages.length > 0 && (this.blurred || this.focused)) {
150
145
  return ruleMessages.join(', ');
151
146
  } else {
152
147
  return undefined;