@rancher/shell 0.3.4 → 0.3.6

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 (289) hide show
  1. package/assets/images/providers/outscale.svg +19 -0
  2. package/assets/styles/app.scss +1 -1
  3. package/assets/styles/base/_basic.scss +18 -0
  4. package/assets/styles/base/_mixins.scss +0 -11
  5. package/assets/styles/base/_variables.scss +2 -4
  6. package/assets/styles/fonts/_fontstack.scss +11 -11
  7. package/assets/styles/global/_button.scss +12 -2
  8. package/assets/styles/vendor/vue-js-modal.scss +3 -3
  9. package/assets/translations/en-us.yaml +113 -22
  10. package/assets/translations/zh-hans.yaml +113 -24
  11. package/babel.config.js +13 -0
  12. package/chart/gatekeeper.vue +78 -0
  13. package/chart/istio.vue +135 -112
  14. package/chart/logging/index.vue +13 -4
  15. package/chart/monitoring/index.vue +15 -5
  16. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  17. package/chart/rancher-backup/index.vue +10 -3
  18. package/cloud-credential/aws.vue +1 -1
  19. package/cloud-credential/digitalocean.vue +1 -1
  20. package/cloud-credential/gcp.vue +1 -1
  21. package/cloud-credential/generic.vue +2 -2
  22. package/cloud-credential/linode.vue +1 -1
  23. package/cloud-credential/pnap.vue +1 -1
  24. package/components/ActionMenu.vue +3 -4
  25. package/components/AssignTo.vue +1 -1
  26. package/components/AsyncButton.vue +1 -1
  27. package/components/BannerGraphic.vue +1 -1
  28. package/components/BrandImage.vue +1 -4
  29. package/components/ButtonDropdown.vue +2 -3
  30. package/components/Carousel.vue +85 -37
  31. package/components/ChartPsp.vue +76 -0
  32. package/components/CruResource.vue +6 -2
  33. package/components/DashboardMetrics.vue +12 -10
  34. package/components/DetailText.vue +1 -1
  35. package/components/DisableAuthProviderModal.vue +1 -1
  36. package/components/EmberPage.vue +1 -1
  37. package/components/EtcdInfoBanner.vue +12 -7
  38. package/components/ExplorerMembers.vue +101 -6
  39. package/components/ExplorerProjectsNamespaces.vue +46 -3
  40. package/components/FileDiff.vue +6 -7
  41. package/components/GrafanaDashboard.vue +27 -23
  42. package/components/LazyImage.vue +10 -12
  43. package/components/LogItem.vue +1 -1
  44. package/components/Markdown.vue +1 -1
  45. package/components/PromptRemove.vue +2 -2
  46. package/components/PromptRestore.vue +1 -1
  47. package/components/ResourceDetail/Masthead.vue +16 -0
  48. package/components/ResourceDetail/index.vue +21 -4
  49. package/components/ResourceList/index.vue +1 -1
  50. package/components/ResourceTable.vue +4 -1
  51. package/components/SingleClusterInfo.vue +2 -2
  52. package/components/SortableTable/THead.vue +1 -1
  53. package/components/SortableTable/index.vue +28 -13
  54. package/components/SortableTable/selection.js +58 -50
  55. package/components/Wizard.vue +4 -2
  56. package/components/__tests__/AsyncButton.test.ts +3 -1
  57. package/components/__tests__/ChartPsp.test.ts +75 -0
  58. package/components/__tests__/CruResource.test.ts +3 -1
  59. package/components/auth/Principal.vue +1 -1
  60. package/components/auth/RoleDetailEdit.vue +2 -2
  61. package/components/fleet/FleetBundles.vue +3 -1
  62. package/components/fleet/FleetClusters.vue +1 -2
  63. package/components/fleet/FleetIntro.vue +9 -1
  64. package/components/fleet/FleetNoWorkspaces.vue +62 -0
  65. package/components/fleet/FleetSummary.vue +7 -1
  66. package/components/form/HookOption.vue +14 -10
  67. package/components/form/LabeledSelect.vue +14 -11
  68. package/components/form/Labels.vue +32 -27
  69. package/components/form/MatchExpressions.vue +19 -4
  70. package/components/form/Members/ClusterPermissionsEditor.vue +32 -7
  71. package/components/form/NameNsDescription.vue +32 -46
  72. package/components/form/ProjectMemberEditor.vue +46 -21
  73. package/components/form/ResourceSelector.vue +1 -1
  74. package/components/form/SecretSelector.vue +5 -1
  75. package/components/form/ServiceNameSelect.vue +1 -1
  76. package/components/form/SimpleSecretSelector.vue +9 -9
  77. package/components/form/Tolerations.vue +4 -1
  78. package/components/form/ValueFromResource.vue +14 -9
  79. package/components/form/WorkloadPorts.vue +2 -2
  80. package/components/form/__tests__/LabeledSelect.test.ts +138 -0
  81. package/components/form/__tests__/NameNsDescription.ts +59 -0
  82. package/components/formatter/InternalExternalIP.vue +6 -0
  83. package/components/formatter/InvolvedObjectLink.vue +54 -0
  84. package/components/formatter/Link.vue +20 -4
  85. package/components/formatter/LinkName.vue +6 -1
  86. package/components/formatter/ServiceTargets.vue +1 -1
  87. package/components/formatter/WorkloadHealthScale.vue +8 -2
  88. package/components/nav/Group.vue +2 -2
  89. package/components/nav/NamespaceFilter.vue +23 -11
  90. package/components/nav/TopLevelMenu.vue +2 -4
  91. package/components/nav/Type.vue +1 -1
  92. package/components/nav/WorkspaceSwitcher.vue +46 -5
  93. package/components/nuxt/nuxt-build-indicator.vue +143 -0
  94. package/components/nuxt/nuxt-child.js +122 -0
  95. package/components/nuxt/nuxt-error.vue +98 -0
  96. package/components/nuxt/nuxt-link.client.js +98 -0
  97. package/components/nuxt/nuxt-link.server.js +16 -0
  98. package/components/nuxt/nuxt-loading.vue +154 -0
  99. package/components/nuxt/nuxt.js +101 -0
  100. package/config/labels-annotations.js +17 -0
  101. package/config/middleware.js +12 -0
  102. package/config/product/auth.js +3 -2
  103. package/config/product/explorer.js +34 -6
  104. package/config/product/fleet.js +2 -0
  105. package/config/query-params.js +1 -0
  106. package/config/router.js +414 -0
  107. package/config/store.js +181 -0
  108. package/config/table-headers.js +54 -12
  109. package/config/types.js +18 -8
  110. package/config/uiplugins.js +30 -0
  111. package/content/docs/en-us/whats-new.md +10 -0
  112. package/content/docs/zh-hans/whats-new.md +11 -1
  113. package/core/plugin-routes.ts +23 -0
  114. package/core/plugin.ts +4 -2
  115. package/core/types.ts +258 -1
  116. package/creators/app/app.package.json +2 -1
  117. package/creators/app/files/.eslintrc.js +1 -1
  118. package/creators/app/files/babel.config.js +1 -18
  119. package/creators/app/files/tsconfig.json +0 -1
  120. package/creators/app/files/vue.config.js +6 -0
  121. package/creators/app/init +5 -5
  122. package/creators/pkg/files/.github/workflows/build-extension.yml +110 -0
  123. package/creators/pkg/files/tsconfig.json +0 -1
  124. package/creators/pkg/init +35 -4
  125. package/creators/pkg/pkg.package.json +3 -3
  126. package/creators/update/init +1 -1
  127. package/detail/constraints.gatekeeper.sh.constraint.vue +34 -17
  128. package/detail/fleet.cattle.io.clustergroup.vue +7 -1
  129. package/detail/fleet.cattle.io.gitrepo.vue +19 -11
  130. package/detail/harvesterhci.io.management.cluster.vue +3 -3
  131. package/detail/provisioning.cattle.io.cluster.vue +54 -12
  132. package/detail/workload/index.vue +3 -3
  133. package/dialog/AddClusterMemberDialog.vue +1 -1
  134. package/dialog/AddProjectMemberDialog.vue +2 -2
  135. package/dialog/AddonConfigConfirmationDialog.vue +27 -15
  136. package/dialog/DiagnosticTimingsDialog.vue +1 -1
  137. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  138. package/dialog/GenericPrompt.vue +18 -6
  139. package/dialog/RotateEncryptionKeyDialog.vue +1 -1
  140. package/dialog/SaveAsRKETemplateDialog.vue +1 -1
  141. package/dialog/ScaleMachineDownDialog.vue +1 -1
  142. package/edit/auth/github.vue +8 -8
  143. package/edit/auth/googleoauth.vue +5 -5
  144. package/edit/auth/ldap/index.vue +1 -1
  145. package/edit/auth/oidc.vue +1 -1
  146. package/edit/auth/saml.vue +1 -1
  147. package/edit/cis.cattle.io.clusterscan.vue +1 -1
  148. package/edit/fleet.cattle.io.clustergroup.vue +6 -4
  149. package/edit/fleet.cattle.io.gitrepo.vue +32 -4
  150. package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
  151. package/edit/logging.banzaicloud.io.output/index.vue +18 -5
  152. package/edit/logging.banzaicloud.io.output/providers/loki.vue +1 -0
  153. package/edit/management.cattle.io.fleetworkspace.vue +141 -6
  154. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
  155. package/edit/management.cattle.io.setting.vue +1 -1
  156. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
  157. package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
  158. package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
  159. package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
  160. package/edit/namespace.vue +14 -10
  161. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
  162. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  163. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +21 -4
  164. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
  165. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
  166. package/edit/provisioning.cattle.io.cluster/import.vue +23 -25
  167. package/edit/provisioning.cattle.io.cluster/rke2.vue +344 -102
  168. package/edit/resources.cattle.io.backup.vue +1 -1
  169. package/edit/service.vue +1 -1
  170. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
  171. package/edit/workload/__tests__/Job.test.ts +3 -1
  172. package/edit/workload/index.vue +8 -3
  173. package/edit/workload/mixins/workload.js +22 -7
  174. package/edit/workload/storage/Mount.vue +3 -3
  175. package/initialize/App.js +206 -0
  176. package/initialize/client.js +863 -0
  177. package/initialize/index.js +364 -0
  178. package/layouts/default.vue +7 -3
  179. package/layouts/standalone.vue +13 -0
  180. package/list/catalog.cattle.io.clusterrepo.vue +1 -0
  181. package/list/fleet.cattle.io.bundle.vue +6 -3
  182. package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
  183. package/list/fleet.cattle.io.gitrepo.vue +44 -5
  184. package/list/management.cattle.io.fleetworkspace.vue +45 -0
  185. package/list/node.vue +69 -16
  186. package/list/provisioning.cattle.io.cluster.vue +30 -1
  187. package/list/rbac.authorization.k8s.io.clusterrolebinding.vue +48 -0
  188. package/list/workload.vue +6 -4
  189. package/machine-config/azure.vue +97 -38
  190. package/middleware/authenticated.js +34 -0
  191. package/mixins/chart.js +101 -2
  192. package/mixins/fetch.client.js +95 -0
  193. package/mixins/fetch.server.js +73 -0
  194. package/mixins/labeled-form-element.ts +2 -2
  195. package/mixins/resource-fetch.js +2 -2
  196. package/models/apps.statefulset.js +28 -0
  197. package/models/cluster/node.js +23 -2
  198. package/models/cluster.x-k8s.io.machine.js +4 -2
  199. package/models/clusterroletemplatebinding.js +7 -0
  200. package/models/constraints.gatekeeper.sh.constraint.js +46 -0
  201. package/models/fleet.cattle.io.cluster.js +19 -10
  202. package/models/fleet.cattle.io.gitrepo.js +7 -2
  203. package/models/management.cattle.io.cluster.js +1 -1
  204. package/models/management.cattle.io.fleetworkspace.js +12 -0
  205. package/models/management.cattle.io.gitreporestriction.js +5 -0
  206. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
  207. package/models/pod.js +4 -0
  208. package/models/provisioning.cattle.io.cluster.js +7 -5
  209. package/models/rbac.authorization.k8s.io.clusterrolebinding.js +16 -0
  210. package/models/rbac.authorization.k8s.io.rolebinding.js +16 -0
  211. package/package.json +13 -21
  212. package/pages/auth/setup.vue +2 -2
  213. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
  214. package/pages/c/_cluster/apps/charts/chart.vue +4 -4
  215. package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
  216. package/pages/c/_cluster/apps/charts/install.vue +98 -102
  217. package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
  218. package/pages/c/_cluster/explorer/index.vue +29 -25
  219. package/pages/c/_cluster/explorer/tools/index.vue +8 -8
  220. package/pages/c/_cluster/fleet/index.vue +95 -34
  221. package/pages/c/_cluster/gatekeeper/index.vue +1 -1
  222. package/pages/c/_cluster/istio/index.vue +5 -5
  223. package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
  224. package/pages/c/_cluster/monitoring/index.vue +7 -0
  225. package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
  226. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
  227. package/pages/c/_cluster/uiplugins/index.vue +49 -17
  228. package/pages/diagnostic.vue +32 -25
  229. package/pages/home.vue +9 -4
  230. package/pages/index.vue +10 -1
  231. package/pages/rio/mesh.vue +1 -2
  232. package/pkg/tsconfig.json +0 -1
  233. package/plugins/clean-html-directive.js +34 -0
  234. package/plugins/dashboard-store/actions.js +32 -9
  235. package/plugins/dashboard-store/index.js +1 -1
  236. package/plugins/dashboard-store/mutations.js +5 -2
  237. package/plugins/dashboard-store/resource-class.js +8 -1
  238. package/plugins/plugin.js +0 -14
  239. package/plugins/portal-vue.js +4 -0
  240. package/plugins/steve/mutations.js +3 -2
  241. package/plugins/steve/steve-description-class.js +5 -1
  242. package/plugins/steve/subscribe.js +63 -54
  243. package/plugins/steve-create-worker.js +14 -0
  244. package/promptRemove/management.cattle.io.globalrole.vue +2 -2
  245. package/promptRemove/management.cattle.io.project.vue +2 -2
  246. package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
  247. package/promptRemove/pod.vue +1 -1
  248. package/public/index.html +65 -0
  249. package/rancher-components/components/Banner/Banner.test.ts +7 -1
  250. package/rancher-components/components/Banner/Banner.vue +2 -1
  251. package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
  252. package/rancher-components/components/Form/Radio/RadioButton.test.ts +31 -0
  253. package/rancher-components/components/Form/Radio/RadioButton.vue +14 -3
  254. package/scripts/build-pkg.sh +1 -0
  255. package/scripts/clean +6 -0
  256. package/scripts/extension/bundle +58 -0
  257. package/scripts/extension/helmpatch +89 -0
  258. package/scripts/extension/publish +333 -0
  259. package/scripts/serve-pkgs +6 -2
  260. package/scripts/test-plugins-build.sh +4 -0
  261. package/store/__tests__/index.test.ts +110 -0
  262. package/store/index.js +145 -58
  263. package/store/type-map.js +6 -2
  264. package/tsconfig.default.json +36 -0
  265. package/tsconfig.json +23 -0
  266. package/types/rancher/index.d.ts +2 -0
  267. package/types/shell/index.d.ts +466 -320
  268. package/utils/__tests__/grafana.test.ts +44 -0
  269. package/utils/__tests__/string.test.ts +12 -0
  270. package/utils/auth.js +65 -0
  271. package/utils/axios.js +190 -0
  272. package/utils/cookie-universal-nuxt.js +10 -0
  273. package/utils/dom.js +15 -0
  274. package/utils/grafana.js +35 -16
  275. package/utils/monitoring.js +2 -1
  276. package/utils/nuxt.js +659 -0
  277. package/utils/position.js +5 -8
  278. package/utils/router.scrollBehavior.js +80 -0
  279. package/utils/select.js +1 -3
  280. package/utils/socket.js +1 -0
  281. package/utils/string.js +13 -0
  282. package/utils/time.js +9 -0
  283. package/vue.config.js +690 -0
  284. package/chart/rancher-alerting-drivers.vue +0 -53
  285. package/chart/rancher-gatekeeper.vue +0 -37
  286. package/creators/app/files/nuxt.config.js +0 -6
  287. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
  288. package/nuxt.config.js +0 -798
  289. package/plugins/dashboard-store/extensions.js +0 -22
@@ -1,7 +1,7 @@
1
- import $ from 'jquery';
2
1
  import { isMore, isRange, suppressContextMenu, isAlternate } from '@shell/utils/platform';
3
2
  import { get } from '@shell/utils/object';
4
3
  import { filterBy } from '@shell/utils/array';
4
+ import { getParent } from '@shell/utils/dom';
5
5
 
6
6
  export const ALL = 'all';
7
7
  export const SOME = 'some';
@@ -9,23 +9,23 @@ export const NONE = 'none';
9
9
 
10
10
  export default {
11
11
  mounted() {
12
- const $table = $('> TABLE', this.$el);
12
+ const table = this.$el.querySelector('TABLE');
13
13
 
14
14
  this._onRowClickBound = this.onRowClick.bind(this);
15
15
  this._onRowMousedownBound = this.onRowMousedown.bind(this);
16
16
  this._onRowContextBound = this.onRowContext.bind(this);
17
17
 
18
- $table.on('click', '> TBODY > TR', this._onRowClickBound);
19
- $table.on('mousedown', '> TBODY > TR', this._onRowMousedownBound);
20
- $table.on('contextmenu', '> TBODY > TR', this._onRowContextBound);
18
+ table.addEventListener('click', this._onRowClickBound);
19
+ table.addEventListener('mousedown', this._onRowMousedownBound);
20
+ table.addEventListener('contextmenu', this._onRowContextBound);
21
21
  },
22
22
 
23
23
  beforeDestroy() {
24
- const $table = $('> TABLE', this.$el);
24
+ const table = this.$el.querySelector('TABLE');
25
25
 
26
- $table.off('click', '> TBODY > TR', this._onRowClickBound);
27
- $table.off('mousedown', '> TBODY > TR', this._onRowMousedownBound);
28
- $table.off('contextmenu', '> TBODY > TR', this._onRowContextBound);
26
+ table.removeEventListener('click', this._onRowClickBound);
27
+ table.removeEventListener('mousedown', this._onRowMousedownBound);
28
+ table.removeEventListener('contextmenu', this._onRowContextBound);
29
29
  },
30
30
 
31
31
  computed: {
@@ -156,31 +156,31 @@ export default {
156
156
  },
157
157
 
158
158
  onRowMouseEnter(e) {
159
- const tr = $(e.target).closest('TR');
159
+ const tr = e.target.closest('TR');
160
160
 
161
- if (tr.hasClass('sub-row')) {
162
- const trMainRow = tr.prev('TR');
161
+ if (tr.classList.contains('sub-row')) {
162
+ const trMainRow = tr.previousElementSibling;
163
163
 
164
- trMainRow.toggleClass('sub-row-hovered', true);
164
+ trMainRow.classList.add('sub-row-hovered');
165
165
  }
166
166
  },
167
167
 
168
168
  onRowMouseLeave(e) {
169
- const tr = $(e.target).closest('TR');
169
+ const tr = e.target.closest('TR');
170
170
 
171
- if (tr.hasClass('sub-row')) {
172
- const trMainRow = tr.prev('TR');
171
+ if (tr.classList.contains('sub-row')) {
172
+ const trMainRow = tr.previousElementSibling;
173
173
 
174
- trMainRow.toggleClass('sub-row-hovered', false);
174
+ trMainRow.classList.remove('sub-row-hovered');
175
175
  }
176
176
  },
177
177
 
178
178
  nodeForEvent(e) {
179
179
  const tagName = e.target.tagName;
180
- const tgt = $(e.target);
181
- const actionElement = tgt.closest('.actions')[0];
180
+ const tgt = e.target;
181
+ const actionElement = tgt.closest('.actions');
182
182
 
183
- if ( tgt.hasClass('select-all-check') ) {
183
+ if ( tgt.classList.contains('select-all-check') ) {
184
184
  return;
185
185
  }
186
186
 
@@ -188,31 +188,31 @@ export default {
188
188
  if (
189
189
  tagName === 'A' ||
190
190
  tagName === 'BUTTON' ||
191
- tgt.parents('.btn').length
191
+ getParent(tgt, '.btn')
192
192
  ) {
193
193
  return;
194
194
  }
195
195
  }
196
196
 
197
- const tgtRow = $(e.currentTarget);
197
+ const tgtRow = e.target.closest('TR');
198
198
 
199
199
  return this.nodeForRow(tgtRow);
200
200
  },
201
201
 
202
202
  nodeForRow(tgtRow) {
203
- if ( tgtRow?.hasClass('separator-row') ) {
203
+ if ( tgtRow?.classList.contains('separator-row') ) {
204
204
  return;
205
205
  }
206
206
 
207
- while ( tgtRow && tgtRow.length && !tgtRow.hasClass('main-row') ) {
208
- tgtRow = tgtRow.prev();
207
+ while ( tgtRow && !tgtRow.classList.contains('main-row') ) {
208
+ tgtRow = tgtRow.previousElementSibling;
209
209
  }
210
210
 
211
- if ( !tgtRow || !tgtRow.length ) {
211
+ if ( !tgtRow ) {
212
212
  return;
213
213
  }
214
214
 
215
- const nodeId = tgtRow.data('node-id');
215
+ const nodeId = tgtRow.dataset.nodeId;
216
216
 
217
217
  if ( !nodeId ) {
218
218
  return;
@@ -225,15 +225,15 @@ export default {
225
225
 
226
226
  async onRowClick(e) {
227
227
  const node = this.nodeForEvent(e);
228
- const td = $(e.target).closest('TD');
229
- const skipSelect = td.hasClass('skip-select');
228
+ const td = e.target.closest('TD');
229
+ const skipSelect = td?.classList.contains('skip-select');
230
230
 
231
231
  if (skipSelect) {
232
232
  return;
233
233
  }
234
234
  const selection = this.selectedRows;
235
- const isCheckbox = this.isSelectionCheckbox(e.target) || td.hasClass('row-check');
236
- const isExpand = td.hasClass('row-expand');
235
+ const isCheckbox = this.isSelectionCheckbox(e.target) || td?.classList.contains('row-check');
236
+ const isExpand = td?.classList.contains('row-expand');
237
237
  const content = this.pagedRows;
238
238
 
239
239
  this.$emit('rowClick', e);
@@ -248,28 +248,30 @@ export default {
248
248
  return;
249
249
  }
250
250
 
251
- const actionElement = $(e.target).closest('.actions')[0];
251
+ const actionElement = e.target.closest('.actions');
252
252
 
253
253
  if ( actionElement ) {
254
254
  let resources = [node];
255
255
 
256
256
  if ( this.mangleActionResources ) {
257
- const i = $('i', actionElement);
257
+ const i = actionElement.querySelector('i');
258
258
 
259
- i.removeClass('icon-actions');
260
- i.addClass(['icon-spinner', 'icon-spin']);
259
+ i.classList.remove('icon-actions');
260
+ i.classList.add('icon-spinner');
261
+ i.classList.add('icon-spin');
261
262
 
262
263
  try {
263
264
  resources = await this.mangleActionResources(resources);
264
265
  } finally {
265
- i.removeClass(['icon-spinner', 'icon-spin']);
266
- i.addClass('icon-actions');
266
+ i.classList.remove('icon-spinner');
267
+ i.classList.remove('icon-spin');
268
+ i.classList.add('icon-actions');
267
269
  }
268
270
  }
269
271
 
270
272
  this.$store.commit(`action-menu/show`, {
271
273
  resources,
272
- event: e.originalEvent || e, // Handle jQuery event and raw event
274
+ event: e,
273
275
  elem: actionElement
274
276
  });
275
277
 
@@ -332,7 +334,7 @@ export default {
332
334
 
333
335
  this.$store.commit(`action-menu/show`, {
334
336
  resources,
335
- event: e.originalEvent,
337
+ event: e,
336
338
  });
337
339
  },
338
340
 
@@ -356,7 +358,7 @@ export default {
356
358
  isSelectionCheckbox(element) {
357
359
  return element.tagName === 'INPUT' &&
358
360
  element.type === 'checkbox' &&
359
- ($(element).closest('.selection-checkbox').length > 0);
361
+ element.closest('.selection-checkbox') !== null;
360
362
  },
361
363
 
362
364
  nodesBetween(a, b) {
@@ -445,7 +447,9 @@ export default {
445
447
  }
446
448
  });
447
449
 
448
- this.selectedRows.push(...toAdd);
450
+ if ( toAdd ) {
451
+ this.selectedRows.push(...toAdd);
452
+ }
449
453
 
450
454
  // Uncheck and check the checkboxes of nodes that have been added/removed
451
455
  if (toRemove.length) {
@@ -474,20 +478,24 @@ export default {
474
478
 
475
479
  if ( id ) {
476
480
  // Note: This is looking for the checkbox control for the row
477
- const input = $(`div[data-checkbox-ctrl][data-node-id="${ id }"]`);
481
+ const input = this.$el.querySelector(`div[data-checkbox-ctrl][data-node-id="${ id }"]`);
478
482
 
479
- if ( input && input.length && !input[0].disabled ) {
480
- const label = $(input[0]).find('label');
483
+ if ( input && !input.disabled ) {
484
+ const label = input.querySelector('label');
481
485
 
482
486
  if (label) {
483
- label.prop('value', on);
487
+ label.value = on;
484
488
  }
485
489
  let tr = input.closest('tr');
486
490
  let first = true;
487
491
 
488
- while ( tr && (first || tr.hasClass('sub-row') ) ) {
489
- tr.toggleClass('row-selected', on);
490
- tr = tr.next();
492
+ while ( tr && (first || tr.classList.contains('sub-row') ) ) {
493
+ if (on) {
494
+ tr.classList.add('row-selected');
495
+ } else {
496
+ tr.classList.remove('row-selected');
497
+ }
498
+ tr = tr.nextElementSibling;
491
499
  first = false;
492
500
  }
493
501
  }
@@ -497,9 +505,9 @@ export default {
497
505
  select(nodes) {
498
506
  nodes.forEach((node) => {
499
507
  const id = get(node, this.keyField);
500
- const input = $(`label[data-node-id="${ id }"]`);
508
+ const input = this.$el.querySelector(`label[data-node-id="${ id }"]`);
501
509
 
502
- input.trigger('click');
510
+ input.dispatchEvent(new Event('click'));
503
511
  });
504
512
  },
505
513
 
@@ -468,6 +468,9 @@ $spacer: 10px;
468
468
  flex-direction: column;
469
469
  flex: 1;
470
470
  padding: 0;
471
+ height: 100%;
472
+ position: relative;
473
+ justify-content: flex-start;
471
474
  }
472
475
 
473
476
  .header {
@@ -643,9 +646,8 @@ $spacer: 10px;
643
646
  flex-direction: column;
644
647
 
645
648
  &__step {
646
- display: flex;
647
- flex-direction: column;
648
649
  flex: 1;
650
+ overflow: auto;
649
651
  }
650
652
  }
651
653
 
@@ -1,5 +1,6 @@
1
1
  import { mount, Wrapper } from '@vue/test-utils';
2
2
  import AsyncButton, { ASYNC_BUTTON_STATES } from '@shell/components/AsyncButton.vue';
3
+ import { cleanHtmlDirective } from '@shell/plugins/clean-html-directive';
3
4
 
4
5
  describe('component: AsyncButton', () => {
5
6
  it('should render appropriately with default config', () => {
@@ -7,7 +8,8 @@ describe('component: AsyncButton', () => {
7
8
  const mockT = jest.fn().mockReturnValue('some-string');
8
9
 
9
10
  const wrapper: Wrapper<InstanceType<typeof AsyncButton> & { [key: string]: any }> = mount(AsyncButton, {
10
- mocks: {
11
+ directives: { cleanHtmlDirective },
12
+ mocks: {
11
13
  $store: {
12
14
  getters: {
13
15
  'i18n/exists': mockExists,
@@ -0,0 +1,75 @@
1
+ import { shallowMount, mount } from '@vue/test-utils';
2
+ import ChartPsp from '@shell/components/ChartPsp.vue';
3
+
4
+ describe('component: ChartPsp', () => {
5
+ it.each([
6
+ true, false
7
+ ])('should render checkbox referencing value.global.cattle.psp.enabled as %p', (value) => {
8
+ const version = 'v1.24.11+rke2r1';
9
+ const wrapper = shallowMount(ChartPsp, {
10
+ propsData: {
11
+ value: { global: { cattle: { psp: { enabled: value } } } },
12
+ cluster: { kubernetesVersion: version }
13
+ }
14
+ });
15
+
16
+ expect(wrapper.findComponent({ name: 'Checkbox' }).props().value).toBe(value);
17
+ });
18
+
19
+ it.each([
20
+ ['v1.24.11+rke2r1'],
21
+ ])('should display the checkbox for cluster with k8s version %p', (version) => {
22
+ const wrapper = shallowMount(ChartPsp, {
23
+ propsData: {
24
+ value: { global: { cattle: { psp: { enabled: false } } } },
25
+ cluster: { kubernetesVersion: version }
26
+ }
27
+ });
28
+
29
+ const input = wrapper.find(`[data-testid="psp-checkbox"]`).element as HTMLInputElement;
30
+
31
+ expect(input).toBeDefined();
32
+ });
33
+
34
+ it.each([
35
+ ['v1.25.11+rke2r1'],
36
+ ])('should not display the checkbox for cluster with k8s version %p', (version) => {
37
+ const wrapper = shallowMount(ChartPsp, {
38
+ propsData: {
39
+ value: { global: { cattle: { psp: { enabled: false } } } },
40
+ cluster: { kubernetesVersion: version }
41
+ }
42
+ });
43
+
44
+ const input = wrapper.find(`[data-testid="psp-checkbox"]`).element as HTMLInputElement;
45
+
46
+ expect(input).toBeUndefined();
47
+ });
48
+
49
+ it('should update value.global.cattle.psp.enabled when checkbox is toggled', async() => {
50
+ const chartValues = { global: {} } as any;
51
+ const version = 'v1.24.11+rke2r1';
52
+ const wrapper = mount(ChartPsp, {
53
+ propsData: {
54
+ value: chartValues,
55
+ cluster: { kubernetesVersion: version }
56
+ }
57
+ });
58
+
59
+ await wrapper.find('.checkbox-container').trigger('click');
60
+
61
+ expect(chartValues.global.cattle.psp.enabled).toBe(true);
62
+
63
+ await wrapper.find('.checkbox-container').trigger('click');
64
+ expect(chartValues.global.cattle.psp.enabled).toBe(false);
65
+ });
66
+
67
+ it.each([
68
+ { global: {} } as any,
69
+ { global: { cattle: {} } } as any,
70
+ ])('should define cattle.psp.enabled and set to false', (chartValues) => {
71
+ shallowMount(ChartPsp, { propsData: { value: chartValues } });
72
+
73
+ expect(chartValues.global.cattle.psp.enabled).toBe(false);
74
+ });
75
+ });
@@ -1,6 +1,7 @@
1
1
  import { mount } from '@vue/test-utils';
2
2
  import CruResource from '@shell/components/CruResource.vue';
3
3
  import { _EDIT, _YAML } from '@shell/config/query-params';
4
+ import { cleanHtmlDirective } from '@shell/plugins/clean-html-directive';
4
5
 
5
6
  describe('component: CruResource', () => {
6
7
  it('should hide Cancel button', () => {
@@ -33,7 +34,8 @@ describe('component: CruResource', () => {
33
34
  it('should display multiple errors', () => {
34
35
  const errors = ['mistake!', 'BiG MiStAke11'];
35
36
  const wrapper = mount(CruResource, {
36
- propsData: {
37
+ directives: { cleanHtmlDirective },
38
+ propsData: {
37
39
  canYaml: false,
38
40
  mode: _EDIT,
39
41
  resource: {},
@@ -66,9 +66,9 @@ export default {
66
66
  </div>
67
67
  </div>
68
68
  <div
69
+ v-clean-html="t('principal.loading', null, true)"
69
70
  class="name"
70
71
  :class="{'text-muted': useMuted}"
71
- v-html="t('principal.loading', null, true)"
72
72
  />
73
73
  <div class="description" />
74
74
  </template>
@@ -648,7 +648,7 @@ export default {
648
648
  </div>
649
649
  </template>
650
650
  <template #columns="props">
651
- <div class="columns row">
651
+ <div class="columns row mr-20">
652
652
  <div :class="ruleClass">
653
653
  <Select
654
654
  :value="props.row.value.verbs"
@@ -713,7 +713,7 @@ export default {
713
713
  :mode="mode"
714
714
  >
715
715
  <template #columns="props">
716
- <div class="columns row">
716
+ <div class="columns row mr-20">
717
717
  <div class="col span-12">
718
718
  <Select
719
719
  v-model="props.row.value"
@@ -26,7 +26,9 @@ export default {
26
26
  },
27
27
 
28
28
  async fetch() {
29
- this.allFleet = await this.$store.getters['management/all'](FLEET.CLUSTER);
29
+ if (this.$store.getters['management/schemaFor']( FLEET.CLUSTER )) {
30
+ this.allFleet = await this.$store.getters['management/all'](FLEET.CLUSTER);
31
+ }
30
32
  },
31
33
 
32
34
  data() {
@@ -71,8 +71,7 @@ export default {
71
71
  },
72
72
 
73
73
  pagingParams() {
74
- const inStore = this.$store.getters['currentStore'](FLEET.CLUSTER);
75
- const schema = this.$store.getters[`${ inStore }/schemaFor`](FLEET.CLUSTER);
74
+ const schema = this.$store.getters[`management/schemaFor`](FLEET.CLUSTER);
76
75
 
77
76
  return {
78
77
  singularLabel: this.$store.getters['type-map/labelFor'](schema),
@@ -1,5 +1,6 @@
1
1
  <script>
2
2
  import { AS, _YAML } from '@shell/config/query-params';
3
+ import { FLEET } from '@shell/config/types';
3
4
 
4
5
  export default {
5
6
 
@@ -18,10 +19,14 @@ export default {
18
19
  query: { [AS]: _YAML },
19
20
  };
20
21
 
22
+ const gitRepoSchema = this.$store.getters['management/schemaFor'](FLEET.GIT_REPO);
23
+ const canCreateRepos = gitRepoSchema && gitRepoSchema.resourceMethods.includes('PUT');
24
+
21
25
  return {
22
26
  formRoute,
23
27
  yamlRoute,
24
28
  hasEditComponent,
29
+ canCreateRepos
25
30
  };
26
31
  },
27
32
  };
@@ -32,7 +37,10 @@ export default {
32
37
  <div class="title">
33
38
  {{ t('fleet.gitRepo.repo.noRepos') }}
34
39
  </div>
35
- <div class="actions">
40
+ <div
41
+ v-if="canCreateRepos"
42
+ class="actions"
43
+ >
36
44
  <n-link
37
45
  :to="formRoute"
38
46
  class="btn role-secondary"
@@ -0,0 +1,62 @@
1
+
2
+ <script>
3
+ import { FLEET } from '@shell/config/types';
4
+ import { NAME } from '@shell/config/product/fleet';
5
+ export default {
6
+ name: 'NoWorkspaces',
7
+
8
+ props: {
9
+ canView: {
10
+ type: Boolean,
11
+ default: false,
12
+ },
13
+ },
14
+ data() {
15
+ const formRoute = {
16
+ name: `c-cluster-product-resource-create`,
17
+ params: { resource: FLEET.WORKSPACE, product: NAME }
18
+ };
19
+
20
+ return { hasWorkspaces: false, formRoute };
21
+ },
22
+ };
23
+ </script>
24
+ <template>
25
+ <div class="intro-box">
26
+ <i class="icon icon-repository" />
27
+ <div class="title">
28
+ <span v-clean-html="t('fleet.gitRepo.repo.noWorkspaces', null, true)" />
29
+ </div>
30
+ <div
31
+ v-if="canView"
32
+ class="actions"
33
+ >
34
+ <n-link
35
+ :to="formRoute"
36
+ class="btn role-secondary"
37
+ >
38
+ {{ t('fleet.gitRepo.workspace.addWorkspace') }}
39
+ </n-link>
40
+ </div>
41
+ </div>
42
+ </template>
43
+ <style lang="scss" scoped>
44
+ .intro-box {
45
+ height: calc(100vh - var(--header-height)*2);
46
+ display: flex;
47
+ align-items: center;
48
+ justify-content: center;
49
+ flex-direction: column;
50
+ }
51
+
52
+ .title {
53
+ margin-bottom: 15px;
54
+ font-size: $font-size-h2;
55
+ text-align: center;
56
+ max-width: 600px;
57
+ }
58
+ .icon-repository {
59
+ font-size: 96px;
60
+ margin-bottom: 32px;
61
+ }
62
+ </style>
@@ -80,7 +80,12 @@ export default {
80
80
  },
81
81
 
82
82
  bundleCounts() {
83
- const resources = this.bundles.filter(item => item.metadata.name.startsWith(`${ this.repoName }-`)) || [];
83
+ const resources = this.bundles.filter(item => item.metadata.name.startsWith(`${ this.repoName }-`));
84
+
85
+ if (!resources.length) {
86
+ return [];
87
+ }
88
+
84
89
  const out = { ...getResourceDefaultState(this.$store.getters['i18n/withFallback'], this.stateKey) };
85
90
 
86
91
  resources.forEach(({ status, metadata }) => {
@@ -176,6 +181,7 @@ export default {
176
181
  <template>
177
182
  <div class="row flexwrap">
178
183
  <FleetStatus
184
+ v-if="bundleCounts.length"
179
185
  title="Bundles"
180
186
  :values="bundleCounts"
181
187
  value-key="count"
@@ -202,16 +202,17 @@ export default {
202
202
  :mode="mode"
203
203
  />
204
204
  </template>
205
-
206
- <button
207
- v-if="!isView"
208
- type="button"
209
- class="btn role-link"
210
- :disabled="mode==='view'"
211
- @click.stop="removeHeader(index)"
212
- >
213
- <t k="generic.remove" />
214
- </button>
205
+ <div class="remove">
206
+ <button
207
+ v-if="!isView"
208
+ type="button"
209
+ class="btn role-link ml0"
210
+ :disabled="mode==='view'"
211
+ @click.stop="removeHeader(index)"
212
+ >
213
+ <t k="generic.remove" />
214
+ </button>
215
+ </div>
215
216
  </div>
216
217
 
217
218
  <div>
@@ -244,5 +245,8 @@ export default {
244
245
  .labeled-select {
245
246
  min-height: $input-height;
246
247
  }
248
+ .remove BUTTON {
249
+ padding: 0px;
250
+ }
247
251
  }
248
252
  </style>
@@ -1,11 +1,11 @@
1
1
  <script>
2
2
  import CompactInput from '@shell/mixins/compact-input';
3
3
  import LabeledFormElement from '@shell/mixins/labeled-form-element';
4
- import { findBy } from '@shell/utils/array';
5
4
  import { get } from '@shell/utils/object';
6
5
  import { LabeledTooltip } from '@components/LabeledTooltip';
7
6
  import VueSelectOverrides from '@shell/mixins/vue-select-overrides';
8
7
  import { onClickOption, calculatePosition } from '@shell/utils/select';
8
+ import isEqual from 'lodash/isEqual';
9
9
 
10
10
  export default {
11
11
  name: 'LabeledSelect',
@@ -105,16 +105,6 @@ export default {
105
105
  hasLabel() {
106
106
  return this.isCompact ? false : !!this.label || !!this.labelKey || !!this.$slots.label;
107
107
  },
108
-
109
- currentLabel() {
110
- const entry = findBy(this.options || [], 'value', this.value);
111
-
112
- if (entry) {
113
- return entry.label;
114
- }
115
-
116
- return this.getOptionLabel(this.value);
117
- },
118
108
  },
119
109
 
120
110
  methods: {
@@ -159,6 +149,19 @@ export default {
159
149
  return;
160
150
  }
161
151
 
152
+ // Force to update the option label if prop has been changed
153
+ const isOutdated = !this.options.find(opt => option[this.optionLabel] === opt[this.optionLabel]);
154
+
155
+ if (isOutdated && this.options) {
156
+ const newOption = this.options.find(opt => isEqual(this.reduce(option), this.reduce(opt)));
157
+
158
+ if (newOption) {
159
+ const label = get(newOption, this.optionLabel);
160
+
161
+ return this.localizedLabel ? this.$store.getters['i18n/t'](label) || label : label;
162
+ }
163
+ }
164
+
162
165
  if (this.$attrs['get-option-label']) {
163
166
  return this.$attrs['get-option-label'](option);
164
167
  }