@rancher/shell 0.3.4 → 0.3.5

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 (246) hide show
  1. package/assets/styles/app.scss +1 -1
  2. package/assets/styles/fonts/_fontstack.scss +11 -11
  3. package/assets/styles/vendor/vue-js-modal.scss +3 -3
  4. package/assets/translations/en-us.yaml +92 -22
  5. package/assets/translations/zh-hans.yaml +84 -15
  6. package/babel.config.js +13 -0
  7. package/chart/gatekeeper.vue +77 -0
  8. package/chart/istio.vue +108 -111
  9. package/chart/logging/index.vue +13 -4
  10. package/chart/monitoring/index.vue +15 -5
  11. package/chart/monitoring/steps/uninstall-v1.vue +2 -2
  12. package/chart/rancher-backup/index.vue +10 -3
  13. package/cloud-credential/aws.vue +1 -1
  14. package/cloud-credential/digitalocean.vue +1 -1
  15. package/cloud-credential/gcp.vue +1 -1
  16. package/cloud-credential/generic.vue +2 -2
  17. package/cloud-credential/linode.vue +1 -1
  18. package/cloud-credential/pnap.vue +1 -1
  19. package/components/ActionMenu.vue +3 -4
  20. package/components/AssignTo.vue +1 -1
  21. package/components/AsyncButton.vue +1 -1
  22. package/components/BannerGraphic.vue +1 -1
  23. package/components/ButtonDropdown.vue +2 -3
  24. package/components/ChartPsp.vue +76 -0
  25. package/components/CruResource.vue +6 -2
  26. package/components/DashboardMetrics.vue +12 -10
  27. package/components/DetailText.vue +1 -1
  28. package/components/DisableAuthProviderModal.vue +1 -1
  29. package/components/EmberPage.vue +1 -1
  30. package/components/EtcdInfoBanner.vue +5 -4
  31. package/components/ExplorerMembers.vue +1 -1
  32. package/components/ExplorerProjectsNamespaces.vue +14 -1
  33. package/components/FileDiff.vue +6 -7
  34. package/components/GrafanaDashboard.vue +18 -21
  35. package/components/LazyImage.vue +10 -12
  36. package/components/LogItem.vue +1 -1
  37. package/components/Markdown.vue +1 -1
  38. package/components/PromptRemove.vue +2 -2
  39. package/components/PromptRestore.vue +1 -1
  40. package/components/ResourceDetail/Masthead.vue +16 -0
  41. package/components/ResourceDetail/index.vue +21 -4
  42. package/components/ResourceList/index.vue +1 -1
  43. package/components/ResourceTable.vue +4 -1
  44. package/components/SingleClusterInfo.vue +2 -2
  45. package/components/SortableTable/THead.vue +1 -1
  46. package/components/SortableTable/index.vue +5 -2
  47. package/components/__tests__/AsyncButton.test.ts +3 -1
  48. package/components/__tests__/ChartPsp.test.ts +75 -0
  49. package/components/__tests__/CruResource.test.ts +3 -1
  50. package/components/auth/Principal.vue +1 -1
  51. package/components/fleet/FleetBundles.vue +3 -1
  52. package/components/fleet/FleetClusters.vue +1 -2
  53. package/components/fleet/FleetIntro.vue +9 -1
  54. package/components/fleet/FleetNoWorkspaces.vue +62 -0
  55. package/components/fleet/FleetSummary.vue +7 -1
  56. package/components/form/LabeledSelect.vue +14 -11
  57. package/components/form/MatchExpressions.vue +17 -2
  58. package/components/form/NameNsDescription.vue +31 -45
  59. package/components/form/ResourceSelector.vue +1 -1
  60. package/components/form/SecretSelector.vue +5 -1
  61. package/components/form/ServiceNameSelect.vue +1 -1
  62. package/components/form/SimpleSecretSelector.vue +9 -9
  63. package/components/form/__tests__/LabeledSelect.test.ts +138 -0
  64. package/components/form/__tests__/NameNsDescription.ts +32 -0
  65. package/components/formatter/InternalExternalIP.vue +6 -0
  66. package/components/formatter/InvolvedObjectLink.vue +54 -0
  67. package/components/formatter/Link.vue +20 -4
  68. package/components/formatter/LinkName.vue +6 -1
  69. package/components/formatter/ServiceTargets.vue +1 -1
  70. package/components/nav/Group.vue +2 -2
  71. package/components/nav/NamespaceFilter.vue +15 -11
  72. package/components/nav/TopLevelMenu.vue +2 -4
  73. package/components/nav/Type.vue +1 -1
  74. package/components/nav/WorkspaceSwitcher.vue +46 -5
  75. package/config/labels-annotations.js +17 -0
  76. package/config/product/auth.js +3 -2
  77. package/config/product/explorer.js +11 -4
  78. package/config/product/fleet.js +2 -0
  79. package/config/router.js +414 -0
  80. package/config/table-headers.js +10 -2
  81. package/config/types.js +11 -8
  82. package/config/uiplugins.js +30 -0
  83. package/content/docs/en-us/whats-new.md +10 -0
  84. package/content/docs/zh-hans/whats-new.md +11 -1
  85. package/core/plugin-routes.ts +23 -0
  86. package/creators/app/app.package.json +2 -1
  87. package/creators/app/files/.eslintrc.js +1 -1
  88. package/creators/app/files/babel.config.js +1 -18
  89. package/creators/app/files/vue.config.js +7 -0
  90. package/creators/app/init +5 -5
  91. package/creators/pkg/files/.github/workflows/build-extension.yml +111 -0
  92. package/creators/pkg/init +35 -4
  93. package/creators/update/init +1 -1
  94. package/detail/constraints.gatekeeper.sh.constraint.vue +20 -10
  95. package/detail/fleet.cattle.io.gitrepo.vue +19 -11
  96. package/detail/harvesterhci.io.management.cluster.vue +3 -3
  97. package/detail/provisioning.cattle.io.cluster.vue +54 -12
  98. package/detail/workload/index.vue +3 -3
  99. package/dialog/AddClusterMemberDialog.vue +1 -1
  100. package/dialog/AddProjectMemberDialog.vue +2 -2
  101. package/dialog/AddonConfigConfirmationDialog.vue +27 -15
  102. package/dialog/DiagnosticTimingsDialog.vue +1 -1
  103. package/dialog/ForceMachineRemoveDialog.vue +1 -1
  104. package/dialog/GenericPrompt.vue +18 -6
  105. package/dialog/RotateEncryptionKeyDialog.vue +1 -1
  106. package/dialog/SaveAsRKETemplateDialog.vue +1 -1
  107. package/dialog/ScaleMachineDownDialog.vue +1 -1
  108. package/edit/auth/github.vue +8 -8
  109. package/edit/auth/googleoauth.vue +5 -5
  110. package/edit/auth/ldap/index.vue +1 -1
  111. package/edit/auth/oidc.vue +1 -1
  112. package/edit/auth/saml.vue +1 -1
  113. package/edit/cis.cattle.io.clusterscan.vue +1 -1
  114. package/edit/fleet.cattle.io.clustergroup.vue +6 -4
  115. package/edit/fleet.cattle.io.gitrepo.vue +16 -3
  116. package/edit/helm.cattle.io.projecthelmchart.vue +5 -1
  117. package/edit/management.cattle.io.fleetworkspace.vue +141 -6
  118. package/edit/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +4 -1
  119. package/edit/management.cattle.io.setting.vue +1 -1
  120. package/edit/monitoring.coreos.com.alertmanagerconfig/types/webhook.vue +2 -2
  121. package/edit/monitoring.coreos.com.receiver/tls.vue +18 -18
  122. package/edit/monitoring.coreos.com.receiver/types/webhook.banner.vue +4 -4
  123. package/edit/monitoring.coreos.com.receiver/types/webhook.vue +1 -1
  124. package/edit/namespace.vue +2 -2
  125. package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +126 -45
  126. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
  127. package/edit/provisioning.cattle.io.cluster/MachinePool.vue +10 -0
  128. package/edit/provisioning.cattle.io.cluster/RegistryConfigs.vue +1 -0
  129. package/edit/provisioning.cattle.io.cluster/__tests__/rke2.test.ts +202 -2
  130. package/edit/provisioning.cattle.io.cluster/rke2.vue +248 -84
  131. package/edit/resources.cattle.io.backup.vue +1 -1
  132. package/edit/service.vue +1 -1
  133. package/edit/storage.k8s.io.storageclass/provisioners/driver.harvesterhci.io.vue +2 -2
  134. package/edit/workload/__tests__/Job.test.ts +3 -1
  135. package/edit/workload/index.vue +8 -3
  136. package/edit/workload/mixins/workload.js +16 -0
  137. package/layouts/default.vue +7 -3
  138. package/list/fleet.cattle.io.bundle.vue +6 -3
  139. package/list/fleet.cattle.io.clusterregistrationtoken.vue +3 -1
  140. package/list/fleet.cattle.io.gitrepo.vue +44 -5
  141. package/list/management.cattle.io.fleetworkspace.vue +45 -0
  142. package/list/node.vue +69 -16
  143. package/list/provisioning.cattle.io.cluster.vue +30 -1
  144. package/machine-config/azure.vue +97 -38
  145. package/middleware/authenticated.js +34 -0
  146. package/mixins/chart.js +73 -2
  147. package/mixins/resource-fetch.js +2 -2
  148. package/models/apps.statefulset.js +28 -0
  149. package/models/cluster/node.js +23 -2
  150. package/models/cluster.x-k8s.io.machine.js +4 -2
  151. package/models/clusterroletemplatebinding.js +7 -0
  152. package/models/constraints.gatekeeper.sh.constraint.js +9 -0
  153. package/models/fleet.cattle.io.cluster.js +19 -10
  154. package/models/fleet.cattle.io.gitrepo.js +7 -2
  155. package/models/management.cattle.io.cluster.js +1 -1
  156. package/models/management.cattle.io.fleetworkspace.js +12 -0
  157. package/models/management.cattle.io.gitreporestriction.js +5 -0
  158. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.js +3 -0
  159. package/models/provisioning.cattle.io.cluster.js +7 -5
  160. package/nuxt/App.js +210 -0
  161. package/nuxt/axios.js +186 -0
  162. package/nuxt/client.js +817 -0
  163. package/nuxt/components/nuxt-build-indicator.vue +143 -0
  164. package/nuxt/components/nuxt-child.js +122 -0
  165. package/nuxt/components/nuxt-error.vue +98 -0
  166. package/nuxt/components/nuxt-link.client.js +98 -0
  167. package/nuxt/components/nuxt-link.server.js +16 -0
  168. package/nuxt/components/nuxt-loading.vue +154 -0
  169. package/nuxt/components/nuxt.js +101 -0
  170. package/nuxt/cookie-universal-nuxt.js +9 -0
  171. package/nuxt/empty.js +1 -0
  172. package/nuxt/index.js +365 -0
  173. package/nuxt/jsonp.js +82 -0
  174. package/nuxt/loading.html +39 -0
  175. package/nuxt/middleware.js +12 -0
  176. package/nuxt/mixins/fetch.client.js +90 -0
  177. package/nuxt/mixins/fetch.server.js +69 -0
  178. package/nuxt/portal-vue.js +4 -0
  179. package/nuxt/server.js +312 -0
  180. package/nuxt/store.js +178 -0
  181. package/nuxt/utils.js +630 -0
  182. package/nuxt/views/app.template.html +9 -0
  183. package/nuxt/views/error.html +23 -0
  184. package/package.json +5 -9
  185. package/pages/auth/setup.vue +2 -2
  186. package/pages/c/_cluster/apps/charts/__tests__/install.helper.test.ts +33 -0
  187. package/pages/c/_cluster/apps/charts/chart.vue +4 -4
  188. package/pages/c/_cluster/apps/charts/install.helpers.js +26 -0
  189. package/pages/c/_cluster/apps/charts/install.vue +40 -66
  190. package/pages/c/_cluster/explorer/EventsTable.vue +5 -19
  191. package/pages/c/_cluster/explorer/index.vue +29 -25
  192. package/pages/c/_cluster/explorer/tools/index.vue +8 -8
  193. package/pages/c/_cluster/fleet/index.vue +95 -34
  194. package/pages/c/_cluster/gatekeeper/index.vue +1 -1
  195. package/pages/c/_cluster/istio/index.vue +5 -5
  196. package/pages/c/_cluster/manager/cloudCredential/index.vue +1 -1
  197. package/pages/c/_cluster/monitoring/index.vue +7 -0
  198. package/pages/c/_cluster/uiplugins/InstallDialog.vue +8 -8
  199. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +20 -7
  200. package/pages/c/_cluster/uiplugins/index.vue +49 -17
  201. package/pages/home.vue +9 -4
  202. package/pages/index.vue +10 -1
  203. package/plugins/clean-html-directive.js +31 -0
  204. package/plugins/dashboard-store/actions.js +32 -9
  205. package/plugins/dashboard-store/mutations.js +5 -2
  206. package/plugins/dashboard-store/resource-class.js +8 -1
  207. package/plugins/steve/mutations.js +3 -2
  208. package/plugins/steve/steve-description-class.js +5 -1
  209. package/plugins/steve/subscribe.js +63 -54
  210. package/plugins/steve-create-worker.js +14 -0
  211. package/promptRemove/management.cattle.io.globalrole.vue +2 -2
  212. package/promptRemove/management.cattle.io.project.vue +2 -2
  213. package/promptRemove/management.cattle.io.roletemplate.vue +2 -2
  214. package/promptRemove/pod.vue +1 -1
  215. package/public/index.html +65 -0
  216. package/rancher-components/components/Banner/Banner.test.ts +9 -1
  217. package/rancher-components/components/Banner/Banner.vue +1 -1
  218. package/rancher-components/components/Form/Checkbox/Checkbox.vue +2 -0
  219. package/rancher-components/components/Form/Radio/RadioButton.vue +1 -1
  220. package/scripts/build-pkg.sh +1 -0
  221. package/scripts/clean +6 -0
  222. package/scripts/extension/bundle +58 -0
  223. package/scripts/extension/helmpatch +89 -0
  224. package/scripts/extension/publish +314 -0
  225. package/scripts/test-plugins-build.sh +4 -0
  226. package/store/__tests__/index.test.ts +110 -0
  227. package/store/index.js +145 -58
  228. package/store/type-map.js +5 -1
  229. package/tsconfig.default.json +36 -0
  230. package/tsconfig.json +24 -0
  231. package/types/shell/index.d.ts +420 -343
  232. package/utils/__tests__/string.test.ts +12 -0
  233. package/utils/auth.js +65 -0
  234. package/utils/monitoring.js +2 -1
  235. package/utils/position.js +5 -8
  236. package/utils/router.scrollBehavior.js +80 -0
  237. package/utils/select.js +1 -3
  238. package/utils/socket.js +1 -0
  239. package/utils/string.js +13 -0
  240. package/utils/time.js +9 -0
  241. package/vue.config.js +679 -0
  242. package/chart/rancher-alerting-drivers.vue +0 -53
  243. package/chart/rancher-gatekeeper.vue +0 -37
  244. package/creators/app/files/nuxt.config.js +0 -6
  245. package/models/management.cattle.io.podsecurityadmissionconfigurationtemplate.ts +0 -4
  246. package/nuxt.config.js +0 -798
@@ -0,0 +1,76 @@
1
+ <script>
2
+ import { Checkbox } from '@components/Form/Checkbox';
3
+ import { mapGetters } from 'vuex';
4
+
5
+ export default {
6
+ components: { Checkbox },
7
+ props: {
8
+ value: {
9
+ type: Object,
10
+ default: () => {
11
+ return {};
12
+ }
13
+ },
14
+ mode: {
15
+ type: String,
16
+ default: 'edit'
17
+ },
18
+
19
+ /**
20
+ * Optional title section prior checkbox
21
+ */
22
+ title: {
23
+ type: String,
24
+ default: null
25
+ },
26
+
27
+ /**
28
+ * Cluster information
29
+ */
30
+ cluster: {
31
+ type: Object,
32
+ default: null
33
+ }
34
+ },
35
+ created() {
36
+ if (!this.value.global.cattle) {
37
+ this.$set(this.value.global, 'cattle', { psp: { enabled: false } });
38
+ }
39
+ if (!this.value.global.cattle.psp) {
40
+ this.$set(this.value.global.cattle, 'psp', { enabled: false });
41
+ }
42
+ },
43
+ computed: {
44
+ ...mapGetters({ t: 'i18n/t' }),
45
+
46
+ /**
47
+ * Display checkbox only if contains PSP or K8S version is less than 1.25
48
+ */
49
+ hasCheckbox() {
50
+ const clusterVersion = this.cluster?.kubernetesVersion || '';
51
+ const version = clusterVersion.match(/\d+/g);
52
+ const isRequiredVersion = version?.length ? +version[0] === 1 && +version[1] < 25 : false;
53
+
54
+ return isRequiredVersion;
55
+ }
56
+ }
57
+ };
58
+ </script>
59
+
60
+ <template>
61
+ <div
62
+ v-if="hasCheckbox"
63
+ class="mt-10 mb-10"
64
+ >
65
+ <h3 v-if="title">
66
+ {{ title }}
67
+ </h3>
68
+
69
+ <Checkbox
70
+ v-model="value.global.cattle.psp.enabled"
71
+ data-testid="psp-checkbox"
72
+ :mode="mode"
73
+ :label="t('catalog.chart.enablePSP')"
74
+ />
75
+ </div>
76
+ </template>
@@ -358,6 +358,10 @@ export default {
358
358
  const newNamespaceName = get(this.resource, this.namespaceKey);
359
359
  let namespaceAlreadyExists = false;
360
360
 
361
+ if (!this.createNamespace) {
362
+ return;
363
+ }
364
+
361
365
  try {
362
366
  // This is in a try-catch block because the call to fetch
363
367
  // a namespace throws an error if the namespace is not found.
@@ -461,7 +465,7 @@ export default {
461
465
  <h5>
462
466
  <span
463
467
  v-if="$store.getters['i18n/exists'](subtype.label)"
464
- v-html="t(subtype.label)"
468
+ v-clean-html="t(subtype.label)"
465
469
  />
466
470
  <span v-else>{{ subtype.label }}</span>
467
471
  </h5>
@@ -480,7 +484,7 @@ export default {
480
484
  >
481
485
  <span
482
486
  v-if="$store.getters['i18n/exists'](subtype.description)"
483
- v-html="t(subtype.description, {}, true)"
487
+ v-clean-html="t(subtype.description, {}, true)"
484
488
  />
485
489
  <span v-else>{{ subtype.description }}</span>
486
490
  </div>
@@ -47,25 +47,26 @@ export default {
47
47
  </script>
48
48
 
49
49
  <template>
50
- <div
51
- class="dashboard-metrics"
52
- :class="!hasSummaryAndDetail && 'external-link-pull-left'"
50
+ <div
51
+ class="dashboard-metrics"
52
+ :class="!hasSummaryAndDetail && 'external-link-pull-left'"
53
53
  >
54
54
  <div class="graph-options mb-10">
55
- <DashboardOptions
56
- v-model="graphOptions"
57
- :has-summary-and-detail="hasSummaryAndDetail"
55
+ <DashboardOptions
56
+ v-model="graphOptions"
57
+ :has-summary-and-detail="hasSummaryAndDetail"
58
58
  />
59
59
  </div>
60
60
  <div class="info">
61
61
  <slot />
62
62
  </div>
63
- <div
64
- class="graphs"
65
- :style="{height: graphHeight}"
63
+ <div
64
+ class="graphs"
65
+ :style="{height: graphHeight}"
66
66
  >
67
67
  <GrafanaDashboard
68
68
  v-if="graphOptions.type === 'detail'"
69
+ key="'detail'"
69
70
  class="col span-12 detail"
70
71
  :background-color="graphBackgroundColor"
71
72
  :theme="theme"
@@ -76,6 +77,7 @@ export default {
76
77
  />
77
78
  <GrafanaDashboard
78
79
  v-else
80
+ key="'summary'"
79
81
  class="col span-12 summary"
80
82
  :background-color="graphBackgroundColor"
81
83
  :theme="theme"
@@ -108,7 +110,7 @@ export default {
108
110
  .external-link {
109
111
  position: absolute;
110
112
  left: 10px;
111
- top: -45px;
113
+ top: -47px;
112
114
  }
113
115
  }
114
116
  }
@@ -169,8 +169,8 @@ export default {
169
169
 
170
170
  <span
171
171
  v-else
172
+ v-clean-html="bodyHtml"
172
173
  :class="{'conceal': concealed, 'monospace': monospace && !isBinary}"
173
- v-html="bodyHtml"
174
174
  />
175
175
 
176
176
  <template v-if="!isBinary && !jsonStr && isLong && !expanded">
@@ -49,7 +49,7 @@ export default {
49
49
  </h4>
50
50
  <div slot="body">
51
51
  <div class="mb-10">
52
- <p v-html="t('promptRemove.attemptingToRemoveAuthConfig', null, true)" />
52
+ <p v-clean-html="t('promptRemove.attemptingToRemoveAuthConfig', null, true)" />
53
53
  </div>
54
54
  </div>
55
55
  <template #actions>
@@ -522,8 +522,8 @@ export default {
522
522
  />
523
523
  <div
524
524
  v-if="inline && !loaded"
525
+ v-clean-html="t('generic.loading', {}, true)"
525
526
  class="inline-loading"
526
- v-html="t('generic.loading', {}, true)"
527
527
  />
528
528
  <div
529
529
  v-if="error"
@@ -26,10 +26,10 @@ export default {
26
26
 
27
27
  <template>
28
28
  <Loading v-if="$fetchState.pending" />
29
- <Banner
30
- v-else
31
- class="banner"
32
- color="info"
29
+ <Banner
30
+ v-else
31
+ class="banner"
32
+ color="info"
33
33
  >
34
34
  <div class="datum">
35
35
  <label>{{ t('etcdInfoBanner.hasLeader') }}</label> {{ hasLeader }}
@@ -51,6 +51,7 @@ export default {
51
51
 
52
52
  .datum {
53
53
  text-align: center;
54
+ margin-right: 5px;
54
55
  }
55
56
 
56
57
  & ::v-deep label {
@@ -291,8 +291,8 @@ export default {
291
291
  class="group-tab"
292
292
  >
293
293
  <div
294
+ v-clean-html="getProjectLabel(group)"
294
295
  class="project-name"
295
- v-html="getProjectLabel(group)"
296
296
  />
297
297
  </div>
298
298
  <div class="right">
@@ -112,6 +112,10 @@ export default {
112
112
  // is updated if a new project is created or removed.
113
113
  const projectsInAllClusters = this.$store.getters['management/all'](MANAGEMENT.PROJECT);
114
114
 
115
+ if (this.currentProduct?.customNamespaceFilter && this.currentProduct?.inStore && this.$store.getters[`${ this.currentProduct.inStore }/filterProject`]) {
116
+ return this.$store.getters[`${ this.currentProduct.inStore }/filterProject`];
117
+ }
118
+
115
119
  const clustersInProjects = projectsInAllClusters.filter(project => project.spec.clusterName === clusterId);
116
120
 
117
121
  return clustersInProjects;
@@ -364,8 +368,8 @@ export default {
364
368
  class="group-tab"
365
369
  >
366
370
  <div
371
+ v-clean-html="projectLabel(group.group)"
367
372
  class="project-name"
368
- v-html="projectLabel(group.group)"
369
373
  />
370
374
  <div
371
375
  v-if="projectDescription(group.group)"
@@ -411,6 +415,11 @@ export default {
411
415
  <span v-else>
412
416
  {{ row.name }}
413
417
  </span>
418
+ <i
419
+ v-if="row.injectionEnabled"
420
+ v-tooltip="t('projectNamespaces.isIstioInjectionEnabled')"
421
+ class="icon icon-istio ml-5"
422
+ />
414
423
  <i
415
424
  v-if="row.hasSystemLabels"
416
425
  v-tooltip="getPsaTooltip(row)"
@@ -483,6 +492,10 @@ export default {
483
492
  .namespace-name {
484
493
  display: flex;
485
494
  align-items: center;
495
+
496
+ .icon-istio {
497
+ color: var(--primary);
498
+ }
486
499
  }
487
500
  }
488
501
  }
@@ -1,7 +1,6 @@
1
1
  <script>
2
2
  import { Diff2Html } from 'diff2html';
3
3
  import { createPatch } from 'diff';
4
- import $ from 'jquery';
5
4
 
6
5
  export default {
7
6
  props: {
@@ -74,21 +73,21 @@ export default {
74
73
  return;
75
74
  }
76
75
 
77
- const container = $(this.$refs.root);
76
+ const container = this.$refs.root;
78
77
 
79
- if ( !container || !container.length ) {
78
+ if ( !container ) {
80
79
  return;
81
80
  }
82
81
 
83
- const offset = container.offset();
82
+ const offset = container.getBoundingClientRect();
84
83
 
85
84
  if ( !offset ) {
86
85
  return;
87
86
  }
88
87
 
89
- const desired = $(window).innerHeight() - offset.top - this.footerSpace;
88
+ const desired = window.innerHeight - offset.top - this.footerSpace;
90
89
 
91
- container.css('height', `${ Math.max(0, desired) }px`);
90
+ container.style.height = `${ Math.max(0, desired) }px`;
92
91
  },
93
92
  },
94
93
  };
@@ -99,8 +98,8 @@ export default {
99
98
  <resize-observer @notify="fit" />
100
99
  <div
101
100
  ref="root"
101
+ v-clean-html="html"
102
102
  class="root"
103
- v-html="html"
104
103
  />
105
104
  </div>
106
105
  </template>
@@ -54,14 +54,11 @@ export default {
54
54
  }
55
55
  },
56
56
  watch: {
57
- currentUrl() {
57
+ currentUrl(neu) {
58
+ // Should consider changing `this.graphWindow?.angular` to something like `!loaded && !error`
59
+ // https://github.com/rancher/dashboard/pull/5802
58
60
  if (this.graphHistory && this.graphWindow?.angular) {
59
- const angularElement = this.graphWindow.angular.element(this.graphDocument.querySelector('.grafana-app'));
60
- const injector = angularElement.injector();
61
-
62
- this.graphHistory.pushState({}, '', this.currentUrl);
63
- injector.get('$route').updateParams(this.computeParams());
64
- injector.get('$route').reload();
61
+ this.graphWindow.location.replace(neu);
65
62
  }
66
63
  },
67
64
 
@@ -222,15 +219,15 @@ export default {
222
219
 
223
220
  <template>
224
221
  <div class="grafana-graph">
225
- <Banner
226
- v-if="error"
227
- color="error"
228
- style="z-index: 1000"
222
+ <Banner
223
+ v-if="error"
224
+ color="error"
225
+ style="z-index: 1000"
229
226
  >
230
227
  <div class="text-center">
231
- {{ t('grafanaDashboard.failedToLoad') }} <a
232
- href="#"
233
- @click="reload"
228
+ {{ t('grafanaDashboard.failedToLoad') }} <a
229
+ href="#"
230
+ @click="reload"
234
231
  >{{ t('grafanaDashboard.reload') }}</a>
235
232
  </div>
236
233
  </Banner>
@@ -245,14 +242,14 @@ export default {
245
242
  <div v-if="loading">
246
243
  <Loading />
247
244
  </div>
248
- <div
249
- v-if="!loading && !error"
250
- class="external-link"
245
+ <div
246
+ v-if="!loading && !error"
247
+ class="external-link"
251
248
  >
252
- <a
253
- :href="grafanaUrl"
254
- target="_blank"
255
- rel="noopener noreferrer nofollow"
249
+ <a
250
+ :href="grafanaUrl"
251
+ target="_blank"
252
+ rel="noopener noreferrer nofollow"
256
253
  >{{ t('grafanaDashboard.grafana') }} <i class="icon icon-external-link" /></a>
257
254
  </div>
258
255
  </div>
@@ -1,6 +1,4 @@
1
1
  <script>
2
- import $ from 'jquery';
3
-
4
2
  export default {
5
3
  props: {
6
4
  initialSrc: {
@@ -32,31 +30,31 @@ export default {
32
30
  },
33
31
 
34
32
  beforeDestroy() {
35
- const $img = $(this.$refs.img);
33
+ const img = this.$refs.img;
36
34
 
37
- if ( $img?.length ) {
38
- $img.off('error', this.boundError);
35
+ if (img) {
36
+ img.removeEventListener('error', this.boundError);
39
37
  }
40
38
  },
41
39
 
42
40
  methods: {
43
41
  // Ensure we load the image when the source changes
44
42
  loadImage() {
45
- const $img = $(this.$refs.img);
43
+ const img = this.$refs.img;
46
44
 
47
- if ( this.src ) {
48
- $img.attr('src', this.src);
45
+ if (this.src) {
46
+ img.setAttribute('src', this.src);
49
47
  this.boundError = this.onError.bind(this);
50
48
 
51
- $img.on('error', this.boundError);
49
+ img.addEventListener('error', this.boundError);
52
50
  }
53
51
  },
54
52
 
55
53
  onError() {
56
- const $img = $(this.$refs.img);
54
+ const img = this.$refs.img;
57
55
 
58
- if ( $img?.length ) {
59
- $img.attr('src', this.errorSrc);
56
+ if (img) {
57
+ img.setAttribute('src', this.errorSrc);
60
58
  }
61
59
  }
62
60
  }
@@ -36,8 +36,8 @@ export default {
36
36
  <div class="line">
37
37
  <span class="time">{{ format(source.time) }}</span>
38
38
  <span
39
+ v-clean-html="source.msg"
39
40
  class="msg"
40
- v-html="source.msg"
41
41
  />
42
42
  </div>
43
43
  </template>
@@ -77,8 +77,8 @@ export default {
77
77
  <template>
78
78
  <div
79
79
  v-if="loaded"
80
+ v-clean-html="sanitized"
80
81
  class="markdown"
81
- v-html="sanitized"
82
82
  />
83
83
  <Loading v-else />
84
84
  </template>
@@ -343,7 +343,7 @@ export default {
343
343
  <div class="mb-10">
344
344
  <template v-if="!hasCustomRemove">
345
345
  {{ t('promptRemove.attemptingToRemove', { type }) }} <span
346
- v-html="resourceNames(names, plusMore, t)"
346
+ v-clean-html="resourceNames(names, plusMore, t)"
347
347
  />
348
348
  </template>
349
349
 
@@ -367,7 +367,7 @@ export default {
367
367
  class="mt-10"
368
368
  >
369
369
  <span
370
- v-html="t('promptRemove.confirmName', { nameToMatch: escapeHtml(nameToMatch) }, true)"
370
+ v-clean-html="t('promptRemove.confirmName', { nameToMatch: escapeHtml(nameToMatch) }, true)"
371
371
  />
372
372
  </div>
373
373
  </template>
@@ -218,8 +218,8 @@ export default {
218
218
  >
219
219
  <h4
220
220
  slot="title"
221
+ v-clean-html="t('promptRestore.title', null, true)"
221
222
  class="text-default-text"
222
- v-html="t('promptRestore.title', null, true)"
223
223
  />
224
224
 
225
225
  <div
@@ -429,6 +429,15 @@ export default {
429
429
  class="masthead-state"
430
430
  :value="value"
431
431
  />
432
+ <span
433
+ v-if="!isCreate && value.injectionEnabled"
434
+ class="masthead-istio"
435
+ >
436
+ <i
437
+ v-tooltip="t('projectNamespaces.isIstioInjectionEnabled')"
438
+ class="icon icon-sm icon-istio"
439
+ />
440
+ </span>
432
441
  </h1>
433
442
  </div>
434
443
  <div
@@ -568,6 +577,13 @@ export default {
568
577
  top: -2px;
569
578
  }
570
579
 
580
+ .masthead-istio {
581
+ .icon {
582
+ vertical-align: middle;
583
+ color: var(--primary);
584
+ }
585
+ }
586
+
571
587
  .left-right-split {
572
588
  display: grid;
573
589
  align-items: center;
@@ -13,6 +13,7 @@ import DetailTop from '@shell/components/DetailTop';
13
13
  import { clone, diff } from '@shell/utils/object';
14
14
  import IconMessage from '@shell/components/IconMessage';
15
15
  import ForceDirectedTreeChart from '@shell/components/fleet/ForceDirectedTreeChart';
16
+ import { checkSchemasForFindAllHash } from '@shell/utils/auth';
16
17
 
17
18
  function modeFor(route) {
18
19
  if ( route.query?.mode === _IMPORT ) {
@@ -159,9 +160,24 @@ export default {
159
160
  }
160
161
  } else {
161
162
  if ( as === _GRAPH ) {
162
- await store.dispatch('management/findAll', { type: FLEET.CLUSTER });
163
- await store.dispatch('management/findAll', { type: FLEET.BUNDLE });
164
- await store.dispatch('management/findAll', { type: FLEET.BUNDLE_DEPLOYMENT });
163
+ const graphSchema = await checkSchemasForFindAllHash({
164
+ cluster: {
165
+ inStoreType: 'management',
166
+ type: FLEET.CLUSTER
167
+ },
168
+ bundle: {
169
+ inStoreType: 'management',
170
+ type: FLEET.BUNDLE
171
+ },
172
+
173
+ bundleDeployment: {
174
+ inStoreType: 'management',
175
+ type: FLEET.BUNDLE_DEPLOYMENT
176
+ }
177
+
178
+ }, this.$store);
179
+
180
+ this.canViewChart = graphSchema.cluster && graphSchema.bundle && graphSchema.bundleDeployment;
165
181
  }
166
182
 
167
183
  let fqid = id;
@@ -249,6 +265,7 @@ export default {
249
265
  value: null,
250
266
  model: null,
251
267
  notFound: null,
268
+ canViewChart: true,
252
269
  };
253
270
  },
254
271
 
@@ -385,7 +402,7 @@ export default {
385
402
  </Masthead>
386
403
 
387
404
  <ForceDirectedTreeChart
388
- v-if="isGraph"
405
+ v-if="isGraph && canViewChart"
389
406
  :data="chartData"
390
407
  :fdc-config="getGraphConfig"
391
408
  />
@@ -177,8 +177,8 @@ export default {
177
177
  >
178
178
  <template #message>
179
179
  <span
180
+ v-clean-html="t('resourceList.nsFiltering', { resource: $store.getters['type-map/labelFor'](schema, 2) || customTypeDisplay }, true)"
180
181
  class="filter"
181
- v-html="t('resourceList.nsFiltering', { resource: $store.getters['type-map/labelFor'](schema, 2) || customTypeDisplay }, true)"
182
182
  />
183
183
  </template>
184
184
  </IconMessage>
@@ -30,6 +30,9 @@ export const defaultTableSortGenerationFn = (schema, $store) => {
30
30
  if ( nsFilterKey ) {
31
31
  return `${ sortKey }/${ nsFilterKey }`;
32
32
  }
33
+
34
+ // covers case where we have no current cluster's ns cache
35
+ return sortKey;
33
36
  };
34
37
 
35
38
  export default {
@@ -462,8 +465,8 @@ export default {
462
465
 
463
466
  <template #group-by="{group: thisGroup}">
464
467
  <div
468
+ v-clean-html="thisGroup.ref"
465
469
  class="group-tab"
466
- v-html="thisGroup.ref"
467
470
  />
468
471
  </template>
469
472
 
@@ -118,11 +118,11 @@ export default {
118
118
  class="glance-item"
119
119
  >
120
120
  <label>{{ t('glance.version') }}: </label>
121
+ <span>{{ clusterDetail.kubernetesVersionBase }}</span>
121
122
  <span
122
123
  v-if="clusterDetail.kubernetesVersionExtension"
123
- style="font-size: 0.5em"
124
+ style="font-size: 0.75em"
124
125
  >{{ clusterDetail.kubernetesVersionExtension }}</span>
125
- <span>{{ clusterDetail.kubernetesVersionBase }}</span>
126
126
  </div>
127
127
  <div class="glance-item">
128
128
  <label>{{ t('glance.created') }}: </label>
@@ -242,7 +242,7 @@ export default {
242
242
  v-if="col.sort"
243
243
  v-tooltip="tooltip(col)"
244
244
  >
245
- <span v-html="labelFor(col)" />
245
+ <span v-clean-html="labelFor(col)" />
246
246
  <i
247
247
  v-show="hasAdvancedFiltering && !col.isFilter"
248
248
  v-tooltip="t('sortableTable.tableHeader.noFilter')"
@@ -926,7 +926,7 @@ export default {
926
926
  v-if="act.icon"
927
927
  :class="act.icon"
928
928
  />
929
- <span v-html="act.label" />
929
+ <span v-clean-html="act.label" />
930
930
  </button>
931
931
  <ActionDropdown
932
932
  :class="bulkActionsDropdownClass"
@@ -964,7 +964,7 @@ export default {
964
964
  v-if="act.icon"
965
965
  :class="act.icon"
966
966
  />
967
- <span v-html="act.label" />
967
+ <span v-clean-html="act.label" />
968
968
  </li>
969
969
  </ul>
970
970
  </template>
@@ -1325,6 +1325,9 @@ export default {
1325
1325
  :full-colspan="fullColspan"
1326
1326
  :row="row.row"
1327
1327
  :sub-matches="subMatches"
1328
+ :keyField="keyField"
1329
+ :componentTestid="componentTestid"
1330
+ :i="i"
1328
1331
  :onRowMouseEnter="onRowMouseEnter"
1329
1332
  :onRowMouseLeave="onRowMouseLeave"
1330
1333
  >
@@ -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,