@rancher/shell 3.0.5-rc.5 → 3.0.5-rc.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 (312) hide show
  1. package/assets/data/aws-regions.json +1 -0
  2. package/assets/images/key.svg +17 -0
  3. package/assets/styles/base/_spacing.scss +2 -2
  4. package/assets/styles/global/_form.scss +1 -1
  5. package/assets/styles/global/_labeled-input.scss +1 -1
  6. package/assets/styles/themes/_dark.scss +3 -0
  7. package/assets/styles/themes/_light.scss +3 -0
  8. package/assets/styles/vendor/vue-select.scss +1 -1
  9. package/assets/translations/en-us.yaml +404 -64
  10. package/assets/translations/zh-hans.yaml +3 -4
  11. package/cloud-credential/gcp.vue +9 -1
  12. package/components/AppModal.vue +2 -0
  13. package/components/CodeMirror.vue +1 -1
  14. package/components/ConfigMapSettings/Settings.vue +377 -0
  15. package/components/ConfigMapSettings/index.vue +354 -0
  16. package/components/CruResource.vue +1 -2
  17. package/components/DetailText.vue +61 -11
  18. package/components/Drawer/Chrome.vue +116 -0
  19. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +61 -0
  20. package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +48 -0
  21. package/components/Drawer/ResourceDetailDrawer/__tests__/ConfigTab.test.ts +54 -0
  22. package/components/Drawer/ResourceDetailDrawer/__tests__/YamlTab.test.ts +80 -0
  23. package/components/Drawer/ResourceDetailDrawer/__tests__/composables.test.ts +82 -0
  24. package/components/Drawer/ResourceDetailDrawer/__tests__/helpers.test.ts +42 -0
  25. package/components/Drawer/ResourceDetailDrawer/composables.ts +50 -0
  26. package/components/Drawer/ResourceDetailDrawer/helpers.ts +10 -0
  27. package/components/Drawer/ResourceDetailDrawer/index.vue +110 -0
  28. package/components/GrowlManager.vue +16 -15
  29. package/components/IconOrSvg.vue +5 -0
  30. package/components/KeyValueView.vue +1 -1
  31. package/components/LocaleSelector.vue +9 -1
  32. package/components/ProgressBarMulti.vue +1 -0
  33. package/components/PromptModal.vue +6 -1
  34. package/components/RelatedResources.vue +4 -12
  35. package/components/Resource/Detail/Additional.vue +46 -0
  36. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +1 -1
  37. package/components/Resource/Detail/Metadata/Annotations/index.vue +5 -0
  38. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +223 -0
  39. package/components/Resource/Detail/Metadata/IdentifyingInformation/composable.ts +37 -254
  40. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +298 -0
  41. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +27 -5
  42. package/components/Resource/Detail/Metadata/KeyValue.vue +25 -17
  43. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +1 -1
  44. package/components/Resource/Detail/Metadata/Labels/index.vue +4 -0
  45. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +1 -1
  46. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +1 -1
  47. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +75 -0
  48. package/components/Resource/Detail/Metadata/composables.ts +60 -11
  49. package/components/Resource/Detail/Metadata/index.vue +12 -5
  50. package/components/Resource/Detail/Page.vue +15 -0
  51. package/components/Resource/Detail/ResourceRow.vue +37 -18
  52. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/composables.test.ts +29 -0
  53. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/__tests__/index.test.ts +48 -0
  54. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/composables.ts +31 -0
  55. package/components/Resource/Detail/ResourceTabs/ConfigMapDataTab/index.vue +50 -0
  56. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/__tests__/composables.test.ts +66 -0
  57. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/composables.ts +21 -0
  58. package/components/Resource/Detail/ResourceTabs/KnownHostsTab/index.vue +31 -0
  59. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Basic.vue +45 -0
  60. package/components/Resource/Detail/ResourceTabs/SecretDataTab/BasicAuth.vue +31 -0
  61. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Certificate.vue +31 -0
  62. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Registry.vue +22 -0
  63. package/components/Resource/Detail/ResourceTabs/SecretDataTab/ServiceAccountToken.vue +31 -0
  64. package/components/Resource/Detail/ResourceTabs/SecretDataTab/Ssh.vue +32 -0
  65. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Basic.test.ts +40 -0
  66. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/BasicAuth.test.ts +33 -0
  67. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Certificate.test.ts +33 -0
  68. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Registry.test.ts +27 -0
  69. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/ServiceAccountToken.test.ts +33 -0
  70. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/Ssh.test.ts +33 -0
  71. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/auth-types.test.ts +186 -0
  72. package/components/Resource/Detail/ResourceTabs/SecretDataTab/__tests__/composables.test.ts +102 -0
  73. package/components/Resource/Detail/ResourceTabs/SecretDataTab/auth-types.ts +109 -0
  74. package/components/Resource/Detail/ResourceTabs/SecretDataTab/composeables.ts +52 -0
  75. package/components/Resource/Detail/ResourceTabs/SecretDataTab/index.vue +71 -0
  76. package/components/Resource/Detail/TitleBar/Title.vue +2 -1
  77. package/components/Resource/Detail/TitleBar/__tests__/Title.test.ts +1 -1
  78. package/components/Resource/Detail/TitleBar/__tests__/Top.test.ts +1 -1
  79. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +63 -0
  80. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +1 -1
  81. package/components/Resource/Detail/TitleBar/composables.ts +44 -0
  82. package/components/Resource/Detail/TitleBar/index.vue +83 -11
  83. package/components/Resource/Detail/composables.ts +45 -0
  84. package/components/ResourceDetail/Masthead/__tests__/index.test.ts +70 -0
  85. package/components/ResourceDetail/{__tests__/Masthead.test.ts → Masthead/__tests__/legacy.test.ts} +3 -3
  86. package/components/ResourceDetail/Masthead/index.vue +65 -0
  87. package/components/ResourceDetail/Masthead/latest.vue +44 -0
  88. package/components/ResourceDetail/__tests__/index.test.ts +26 -5
  89. package/components/ResourceDetail/index.vue +30 -16
  90. package/components/ResourceDetail/legacy.vue +18 -1
  91. package/components/ResourceList/Masthead.vue +6 -0
  92. package/components/ResourceYaml.vue +14 -1
  93. package/components/SlideInPanelManager.vue +46 -7
  94. package/components/StateDot/index.vue +28 -0
  95. package/components/Tabbed/index.vue +11 -15
  96. package/components/Wizard.vue +4 -2
  97. package/components/__tests__/ConfigMapSettings.test.ts +376 -0
  98. package/components/__tests__/GrowlManager.test.ts +0 -25
  99. package/components/auth/login/ldap.vue +1 -1
  100. package/components/fleet/FleetApplications.vue +0 -7
  101. package/components/fleet/FleetClusterTargets/TargetsList.vue +66 -0
  102. package/components/fleet/FleetClusterTargets/index.vue +455 -0
  103. package/components/fleet/FleetClusters.vue +25 -6
  104. package/components/fleet/FleetGitRepoPaths.vue +476 -0
  105. package/components/fleet/FleetHelmOps.vue +8 -0
  106. package/components/fleet/FleetRepos.vue +1 -6
  107. package/components/fleet/FleetResources.vue +4 -5
  108. package/components/fleet/FleetValuesFrom.vue +295 -0
  109. package/components/fleet/__tests__/FleetClusterTargets.test.ts +1224 -0
  110. package/components/fleet/__tests__/FleetGitRepoPaths.test.ts +265 -0
  111. package/components/fleet/__tests__/FleetOCIStorageSecret.test.ts +13 -13
  112. package/components/fleet/__tests__/FleetValuesFrom.test.ts +300 -0
  113. package/components/fleet/dashboard/ResourceCard.vue +1 -0
  114. package/components/fleet/dashboard/ResourceCardSummary.vue +1 -5
  115. package/components/fleet/dashboard/ResourceDetails.vue +8 -10
  116. package/components/fleet/dashboard/ResourcePanel.vue +15 -8
  117. package/components/form/ArrayList.vue +13 -2
  118. package/components/form/ChangePassword.vue +3 -1
  119. package/components/form/Footer.vue +10 -4
  120. package/components/form/KeyValue.vue +81 -43
  121. package/components/form/LabeledSelect.vue +56 -16
  122. package/components/form/Labels.vue +90 -17
  123. package/components/form/MatchExpressions.vue +46 -5
  124. package/components/form/NameNsDescription.vue +1 -1
  125. package/components/form/ResourceSelector.vue +1 -0
  126. package/components/form/ResourceTabs/index.vue +5 -0
  127. package/components/form/SecretSelector.vue +9 -2
  128. package/components/form/Select.vue +57 -19
  129. package/components/form/SimpleSecretSelector.vue +9 -2
  130. package/components/form/Taints.vue +21 -2
  131. package/components/form/UnitInput.vue +8 -0
  132. package/components/form/ValueFromResource.vue +1 -1
  133. package/components/form/__tests__/LabeledSelect.test.ts +8 -4
  134. package/components/form/__tests__/Labels.test.ts +360 -0
  135. package/components/form/__tests__/MatchExpressions.test.ts +16 -13
  136. package/components/form/__tests__/Select.test.ts +5 -2
  137. package/components/formatter/FleetApplicationSource.vue +1 -1
  138. package/components/formatter/WorkloadHealthScale.vue +1 -1
  139. package/components/google/AccountAccess.vue +211 -0
  140. package/components/google/types/gcp.d.ts +136 -0
  141. package/components/google/types/index.d.ts +101 -0
  142. package/components/google/util/__mocks__/gcp.ts +465 -0
  143. package/components/google/util/formatter.ts +82 -0
  144. package/components/google/util/gcp.ts +134 -0
  145. package/components/google/util/index.d.ts +11 -0
  146. package/components/nav/Favorite.vue +1 -1
  147. package/components/nav/Group.vue +70 -47
  148. package/components/nav/Header.vue +5 -1
  149. package/components/nav/NamespaceFilter.vue +13 -1
  150. package/components/nav/NotificationCenter/Notification.vue +510 -0
  151. package/components/nav/NotificationCenter/NotificationHeader.vue +112 -0
  152. package/components/nav/NotificationCenter/index.vue +148 -0
  153. package/composables/drawer.ts +26 -0
  154. package/composables/resources.test.ts +63 -0
  155. package/composables/resources.ts +38 -0
  156. package/composables/useIsNewDetailPageEnabled.ts +17 -0
  157. package/config/labels-annotations.js +6 -0
  158. package/config/product/auth.js +16 -1
  159. package/config/product/{cis.js → compliance.js} +23 -26
  160. package/config/product/explorer.js +5 -1
  161. package/config/product/fleet.js +7 -0
  162. package/config/product/settings.js +22 -11
  163. package/config/query-params.js +3 -0
  164. package/config/roles.ts +1 -1
  165. package/config/router/navigation-guards/authentication.js +51 -2
  166. package/config/router/routes.js +27 -31
  167. package/config/settings.ts +21 -3
  168. package/config/store.js +2 -0
  169. package/config/system-namespaces.js +1 -1
  170. package/config/table-headers.js +2 -2
  171. package/config/types.js +15 -6
  172. package/core/plugin.ts +32 -7
  173. package/core/types.ts +18 -1
  174. package/detail/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +22 -18
  175. package/detail/management.cattle.io.fleetworkspace.vue +18 -27
  176. package/detail/management.cattle.io.oidcclient.vue +369 -0
  177. package/detail/node.vue +2 -2
  178. package/detail/pod.vue +2 -2
  179. package/detail/service.vue +10 -1
  180. package/detail/workload/index.vue +8 -2
  181. package/dialog/ExtensionCatalogUninstallDialog.vue +7 -4
  182. package/dialog/GenericPrompt.vue +1 -1
  183. package/dialog/ImportDialog.vue +8 -8
  184. package/dialog/OidcClientSecretDialog.vue +117 -0
  185. package/edit/__tests__/cis.cattle.io.clusterscan.test.ts +3 -3
  186. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +5 -2
  187. package/edit/autoscaling.horizontalpodautoscaler/index.vue +4 -1
  188. package/edit/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +30 -31
  189. package/edit/{cis.cattle.io.clusterscanbenchmark.vue → compliance.cattle.io.clusterscanbenchmark.vue} +4 -4
  190. package/edit/{cis.cattle.io.clusterscanprofile.vue → compliance.cattle.io.clusterscanprofile.vue} +5 -5
  191. package/edit/configmap.vue +4 -1
  192. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  193. package/edit/fleet.cattle.io.gitrepo.vue +44 -222
  194. package/edit/fleet.cattle.io.helmop.vue +44 -269
  195. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  196. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  197. package/edit/logging-flow/index.vue +1 -0
  198. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  199. package/edit/management.cattle.io.fleetworkspace.vue +1 -0
  200. package/edit/management.cattle.io.oidcclient.vue +162 -0
  201. package/edit/management.cattle.io.project.vue +4 -1
  202. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +1 -1
  203. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +5 -0
  204. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  205. package/edit/monitoring.coreos.com.receiver/auth.vue +30 -30
  206. package/edit/monitoring.coreos.com.receiver/index.vue +1 -0
  207. package/edit/monitoring.coreos.com.receiver/types/email.vue +1 -1
  208. package/edit/monitoring.coreos.com.route.vue +1 -0
  209. package/edit/namespace.vue +1 -0
  210. package/edit/networking.istio.io.destinationrule/index.vue +4 -1
  211. package/edit/networking.k8s.io.ingress/index.vue +4 -1
  212. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +7 -2
  213. package/edit/networking.k8s.io.networkpolicy/index.vue +6 -2
  214. package/edit/node.vue +1 -0
  215. package/edit/persistentvolume/index.vue +4 -1
  216. package/edit/provisioning.cattle.io.cluster/rke2.vue +418 -382
  217. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +27 -27
  218. package/edit/provisioning.cattle.io.cluster/tabs/MachinePool.vue +5 -0
  219. package/edit/resources.cattle.io.restore.vue +1 -1
  220. package/edit/secret/index.vue +1 -0
  221. package/edit/service.vue +4 -1
  222. package/edit/serviceaccount.vue +4 -1
  223. package/edit/storage.k8s.io.storageclass/index.vue +4 -1
  224. package/edit/workload/index.vue +5 -0
  225. package/list/{cis.cattle.io.clusterscan.vue → compliance.cattle.io.clusterscan.vue} +2 -2
  226. package/list/management.cattle.io.oidcclient.vue +108 -0
  227. package/list/node.vue +2 -0
  228. package/machine-config/amazonec2.vue +3 -24
  229. package/machine-config/components/GCEImage.vue +374 -0
  230. package/machine-config/google.vue +617 -0
  231. package/mixins/__tests__/brand.spec.ts +170 -0
  232. package/mixins/brand.js +16 -17
  233. package/mixins/create-edit-view/index.js +5 -0
  234. package/mixins/resource-fetch-api-pagination.js +16 -0
  235. package/mixins/vue-select-overrides.js +1 -0
  236. package/models/{cis.cattle.io.clusterscan.js → compliance.cattle.io.clusterscan.js} +8 -8
  237. package/models/{cis.cattle.io.clusterscanbenchmark.js → compliance.cattle.io.clusterscanbenchmark.js} +1 -1
  238. package/models/{cis.cattle.io.clusterscanprofile.js → compliance.cattle.io.clusterscanprofile.js} +5 -5
  239. package/models/{cis.cattle.io.clusterscanreport.js → compliance.cattle.io.clusterscanreport.js} +1 -1
  240. package/models/fleet-application.js +8 -79
  241. package/models/fleet.cattle.io.cluster.js +11 -0
  242. package/models/fleet.cattle.io.gitrepo.js +2 -2
  243. package/models/fleet.cattle.io.helmop.js +9 -39
  244. package/models/management.cattle.io.fleetworkspace.js +2 -1
  245. package/models/management.cattle.io.oidcclient.js +18 -0
  246. package/models/management.cattle.io.registration.js +3 -0
  247. package/models/provisioning.cattle.io.cluster.js +5 -5
  248. package/models/service.js +4 -0
  249. package/models/workload.js +5 -0
  250. package/package.json +1 -1
  251. package/pages/about.vue +4 -58
  252. package/pages/auth/login.vue +1 -1
  253. package/pages/c/_cluster/apps/charts/AddRepoLink.vue +0 -1
  254. package/pages/c/_cluster/apps/charts/index.vue +285 -81
  255. package/pages/c/_cluster/auth/user.retention/index.vue +87 -78
  256. package/pages/c/_cluster/explorer/index.vue +3 -3
  257. package/pages/c/_cluster/explorer/tools/pages/_page.vue +0 -1
  258. package/pages/c/_cluster/fleet/application/create.vue +3 -2
  259. package/pages/c/_cluster/fleet/index.vue +94 -56
  260. package/pages/c/_cluster/fleet/settings/index.vue +229 -0
  261. package/pages/c/_cluster/longhorn/index.vue +5 -2
  262. package/pages/c/_cluster/uiplugins/CatalogList/index.vue +16 -1
  263. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +2 -2
  264. package/pages/explorer/resource/detail/configmap.vue +30 -7
  265. package/pages/explorer/resource/detail/secret.vue +50 -0
  266. package/pages/home.vue +9 -55
  267. package/pages/support/index.vue +4 -6
  268. package/plugins/dashboard-store/actions.js +19 -5
  269. package/plugins/dashboard-store/getters.js +4 -0
  270. package/plugins/dashboard-store/resource-class.js +16 -2
  271. package/plugins/steve/steve-pagination-utils.ts +26 -18
  272. package/plugins/steve/subscribe.js +6 -1
  273. package/rancher-components/Banner/Banner.vue +13 -0
  274. package/rancher-components/Form/Checkbox/Checkbox.vue +9 -4
  275. package/rancher-components/Form/LabeledInput/LabeledInput.vue +1 -1
  276. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -0
  277. package/rancher-components/RcItemCard/RcItemCard.vue +8 -3
  278. package/store/auth.js +2 -0
  279. package/store/catalog.js +23 -1
  280. package/store/growl.js +97 -8
  281. package/store/index.js +6 -0
  282. package/store/notifications.ts +426 -0
  283. package/store/prefs.js +0 -1
  284. package/store/type-map.js +19 -16
  285. package/store/uiplugins.ts +15 -1
  286. package/types/fleet.d.ts +24 -0
  287. package/types/notifications/index.ts +74 -0
  288. package/types/shell/index.d.ts +46 -32
  289. package/types/store/dashboard-store.types.ts +16 -0
  290. package/utils/__tests__/fleet.test.ts +148 -0
  291. package/utils/__tests__/object.test.ts +54 -1
  292. package/utils/__tests__/string.test.ts +273 -1
  293. package/utils/__tests__/time.test.ts +31 -0
  294. package/utils/auth.js +9 -2
  295. package/utils/crypto/encryption.ts +103 -0
  296. package/utils/cspAdaptor.ts +51 -0
  297. package/utils/fleet.ts +54 -65
  298. package/utils/object.js +36 -0
  299. package/utils/pagination-utils.ts +1 -1
  300. package/utils/release-notes.ts +48 -0
  301. package/utils/selector-typed.ts +7 -2
  302. package/utils/string.js +24 -0
  303. package/utils/{time.js → time.ts} +25 -6
  304. package/utils/uiplugins.ts +22 -0
  305. package/utils/validators/formRules/index.ts +3 -0
  306. package/components/Resource/Detail/TitleBar/composable.ts +0 -31
  307. package/config/product/legacy.js +0 -62
  308. package/pages/c/_cluster/legacy/pages/_page.vue +0 -29
  309. package/pages/c/_cluster/legacy/project/_page.vue +0 -57
  310. package/pages/c/_cluster/legacy/project/index.vue +0 -32
  311. package/pages/c/_cluster/legacy/project/pipelines.vue +0 -96
  312. /package/components/ResourceDetail/{Masthead.vue → Masthead/legacy.vue} +0 -0
@@ -0,0 +1,46 @@
1
+ <script lang="ts">
2
+ import { computed } from 'vue';
3
+
4
+ export interface Props {
5
+ items: string[];
6
+ }
7
+ </script>
8
+
9
+ <script setup lang="ts">
10
+
11
+ const { items } = defineProps<Props>();
12
+
13
+ const first = computed(() => items[0]);
14
+ const tooltipValue = computed(() => {
15
+ let rows = '';
16
+
17
+ items.forEach((item) => {
18
+ rows += `&#8226; ${ item }<br>`;
19
+ });
20
+
21
+ return rows;
22
+ });
23
+ </script>
24
+
25
+ <template>
26
+ <div class="additional">
27
+ <div class="initial">
28
+ {{ first }}
29
+ </div>
30
+ <div
31
+ v-if="items.length > 1"
32
+ v-clean-tooltip.bottom="tooltipValue"
33
+ class="more text-muted"
34
+ >
35
+ {{ t('generic.plusMore', {n: items.length-1}) }}
36
+ </div>
37
+ </div>
38
+ </template>
39
+
40
+ <style lang="scss" scoped>
41
+ .more {
42
+ margin-top: 4px;
43
+ cursor: help;
44
+ font-size: 0.8em;
45
+ }
46
+ </style>
@@ -3,7 +3,7 @@ import Annotations from '@shell/components/Resource/Detail/Metadata/Annotations/
3
3
  import { createStore } from 'vuex';
4
4
 
5
5
  describe('component: Metadata/Annotations', () => {
6
- it('shoulder render KeyValue with the appropriate props', async() => {
6
+ it('should render KeyValue with the appropriate props', async() => {
7
7
  const annotations = [{ key: 'key', value: 'value' }];
8
8
  const wrapper = mount(Annotations, {
9
9
  props: { annotations },
@@ -7,12 +7,15 @@ export type Annotation = Row;
7
7
 
8
8
  export interface AnnotationsProps {
9
9
  annotations: Annotation[];
10
+
11
+ onShowConfiguration?: (returnFocusSelector: string) => void;
10
12
  }
11
13
 
12
14
  </script>
13
15
 
14
16
  <script setup lang="ts">
15
17
  const { annotations } = defineProps<AnnotationsProps>();
18
+ const emit = defineEmits(['show-configuration']);
16
19
  const store = useStore();
17
20
  const i18n = useI18n(store);
18
21
  </script>
@@ -22,5 +25,7 @@ const i18n = useI18n(store);
22
25
  :propertyName="i18n.t('component.resource.detail.metadata.annotations.title')"
23
26
  :rows="annotations"
24
27
  :outline="true"
28
+
29
+ @show-configuration="(returnFocusSelector: string) => emit('show-configuration', returnFocusSelector)"
25
30
  />
26
31
  </template>
@@ -0,0 +1,223 @@
1
+ import {
2
+ useNamespace, useWorkspace, useLiveDate, useCreatedBy, useProject,
3
+ useResourceDetails
4
+ } from '@shell/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields';
5
+ import { NAMESPACE, FLEET } from '@shell/config/types';
6
+ import { NAME as FLEET_NAME } from '@shell/config/product/fleet';
7
+
8
+ const mockStore = {
9
+ getters: {
10
+ productId: 'PRODUCT_ID', clusterId: 'CLUSTER_ID', 'type-map/optionsFor': jest.fn()
11
+ }
12
+ };
13
+ const mockRoute = { params: { cluster: 'CLUSTER', namespace: 'NAMESPACE' } };
14
+ const mockDrawer = { openResourceDetailDrawer: jest.fn() };
15
+
16
+ jest.mock('vuex', () => ({ useStore: () => mockStore }));
17
+ jest.mock('vue-router', () => ({ useRoute: () => mockRoute }));
18
+ jest.mock('@shell/components/Drawer/ResourceDetailDrawer/composables', () => ({ useResourceDetailDrawer: () => mockDrawer }));
19
+
20
+ describe('composables: IdentifyingFields', () => {
21
+ describe('useNamespace', () => {
22
+ it('should return undefined if namespace is falsy', () => {
23
+ const resource = {};
24
+ const result = useNamespace(resource);
25
+
26
+ expect(result).toBeUndefined();
27
+ });
28
+
29
+ it('should return undefined if namespaces is truthy', () => {
30
+ const resource = { namespaces: [] };
31
+ const result = useNamespace(resource);
32
+
33
+ expect(result).toBeUndefined();
34
+ });
35
+
36
+ it('should return a valid namespace row with namespaceLocation', () => {
37
+ const resource = { namespace: 'NAMESPACE', namespaceLocation: 'NAMESPACE_LOCATION' };
38
+ const result = useNamespace(resource);
39
+
40
+ expect(result?.value.to).toStrictEqual(resource.namespaceLocation);
41
+ expect(result?.value.value).toStrictEqual(resource.namespace);
42
+ expect(result?.value.label).toStrictEqual('component.resource.detail.metadata.identifyingInformation.namespace');
43
+ expect(result?.value.valueDataTestid).toStrictEqual('masthead-subheader-namespace');
44
+ });
45
+
46
+ it('should return a valid namespace row with computed `to`', () => {
47
+ const resource = { namespace: 'NAMESPACE' };
48
+ const result = useNamespace(resource);
49
+
50
+ expect(result?.value.to).toStrictEqual({
51
+ name: `c-cluster-product-resource-id`,
52
+ params: {
53
+ product: 'PRODUCT_ID',
54
+ cluster: 'CLUSTER_ID',
55
+ resource: NAMESPACE,
56
+ id: resource.namespace
57
+ }
58
+ });
59
+ expect(result?.value.value).toStrictEqual(resource.namespace);
60
+ expect(result?.value.label).toStrictEqual('component.resource.detail.metadata.identifyingInformation.namespace');
61
+ expect(result?.value.valueDataTestid).toStrictEqual('masthead-subheader-namespace');
62
+ });
63
+ });
64
+
65
+ describe('useWorkspace', () => {
66
+ it('should return undefined if productId is not fleet', () => {
67
+ const resource = { metadata: { namespace: true } };
68
+ const result = useWorkspace(resource);
69
+
70
+ expect(result).toBeUndefined();
71
+ });
72
+
73
+ it('should return undefined if productId is fleet and metadata namespace is falsy', () => {
74
+ mockStore.getters.productId = FLEET_NAME;
75
+ const resource = { };
76
+ const result = useWorkspace(resource);
77
+
78
+ expect(result).toBeUndefined();
79
+ });
80
+
81
+ it('should return a valid workspace row', () => {
82
+ mockStore.getters.productId = FLEET_NAME;
83
+ const resource = { namespace: 'NAMESPACE', metadata: { namespace: true } };
84
+ const result = useWorkspace(resource);
85
+
86
+ expect(result?.value.to).toStrictEqual({
87
+ name: `c-cluster-product-resource-id`,
88
+ params: {
89
+ product: FLEET_NAME,
90
+ cluster: 'CLUSTER_ID',
91
+ resource: FLEET.WORKSPACE,
92
+ id: mockRoute.params.namespace
93
+ }
94
+ });
95
+ expect(result?.value.value).toStrictEqual(resource.namespace);
96
+ expect(result?.value.label).toStrictEqual('component.resource.detail.metadata.identifyingInformation.workspace');
97
+ });
98
+ });
99
+
100
+ describe('useLiveDate', () => {
101
+ it('should return undefined if showAge is false', () => {
102
+ mockStore.getters[`type-map/optionsFor`].mockReturnValue({ showAge: false });
103
+
104
+ const resource = { };
105
+ const result = useLiveDate(resource);
106
+
107
+ expect(result).toBeUndefined();
108
+ });
109
+
110
+ it('should return a valid liveDate row', () => {
111
+ mockStore.getters[`type-map/optionsFor`].mockReturnValue({ showAge: true });
112
+
113
+ const resource = { creationTimestamp: 'CREATION_TIMESTAMP' };
114
+ const result = useLiveDate(resource);
115
+
116
+ expect(result?.value.valueOverride).toStrictEqual({
117
+ component: 'LiveDate',
118
+ props: { value: resource.creationTimestamp }
119
+ });
120
+ expect(result?.value.value).toStrictEqual(resource.creationTimestamp);
121
+ expect(result?.value.label).toStrictEqual('component.resource.detail.metadata.identifyingInformation.age');
122
+ });
123
+ });
124
+
125
+ describe('useCreatedBy', () => {
126
+ it('should return undefined if showCreatedBy is falsy', () => {
127
+ const resource = {};
128
+ const result = useCreatedBy(resource);
129
+
130
+ expect(result).toBeUndefined();
131
+ });
132
+
133
+ it('should return a valid createdBy row', () => {
134
+ mockStore.getters[`type-map/optionsFor`].mockReturnValue({ showAge: true });
135
+
136
+ const resource = { showCreatedBy: true, createdBy: { displayName: 'CREATED_BY' } };
137
+ const result = useCreatedBy(resource);
138
+
139
+ expect(result?.value.to).toBeUndefined();
140
+ expect(result?.value.value).toStrictEqual(resource.createdBy.displayName);
141
+ expect(result?.value.label).toStrictEqual('component.resource.detail.metadata.identifyingInformation.createdBy');
142
+ expect(result?.value.dataTestid).toStrictEqual('masthead-subheader-createdBy');
143
+ expect(result?.value.valueDataTestid).toStrictEqual('masthead-subheader-createdBy_plain-text');
144
+ });
145
+
146
+ it('should return a valid createdBy row with createdBy.location', () => {
147
+ mockStore.getters[`type-map/optionsFor`].mockReturnValue({ showAge: true });
148
+
149
+ const resource = { showCreatedBy: true, createdBy: { displayName: 'CREATED_BY', location: 'LOCATION' } };
150
+ const result = useCreatedBy(resource);
151
+
152
+ expect(result?.value.to).toStrictEqual(resource.createdBy.location);
153
+ expect(result?.value.value).toStrictEqual(resource.createdBy.displayName);
154
+ expect(result?.value.label).toStrictEqual('component.resource.detail.metadata.identifyingInformation.createdBy');
155
+ expect(result?.value.dataTestid).toStrictEqual('masthead-subheader-createdBy');
156
+ expect(result?.value.valueDataTestid).toStrictEqual('masthead-subheader-createdBy-link');
157
+ });
158
+ });
159
+
160
+ describe('useProject', () => {
161
+ it('should return undefined if type is not namespace', () => {
162
+ const resource = { type: 'anything' };
163
+ const result = useProject(resource);
164
+
165
+ expect(result).toBeUndefined();
166
+ });
167
+
168
+ it('should return undefined if project is falsy', () => {
169
+ const resource = { type: NAMESPACE };
170
+ const result = useProject(resource);
171
+
172
+ expect(result).toBeUndefined();
173
+ });
174
+
175
+ it('should return a valid project row', () => {
176
+ const resource = { type: NAMESPACE, project: { nameDisplay: 'PROJECT', detailLocation: 'LOCATION' } };
177
+ const result = useProject(resource);
178
+
179
+ expect(result?.value.to).toStrictEqual(resource.project.detailLocation);
180
+ expect(result?.value.value).toStrictEqual(resource.project.nameDisplay);
181
+ expect(result?.value.label).toStrictEqual('component.resource.detail.metadata.identifyingInformation.project');
182
+ });
183
+ });
184
+
185
+ describe('useResourceDetails', () => {
186
+ it('should return undefined if details is falsy', () => {
187
+ const resource = { };
188
+ const result = useResourceDetails(resource);
189
+
190
+ expect(result).toBeUndefined();
191
+ });
192
+
193
+ it('should return valid resourceDetail without valueOverride', () => {
194
+ const resource = { details: [{ label: 'LABEL', content: 'CONTENT' }] };
195
+ const result = useResourceDetails(resource);
196
+
197
+ expect(result?.value[0].label).toStrictEqual(resource.details[0].label);
198
+ expect(result?.value[0].value).toStrictEqual(resource.details[0].content);
199
+ expect(result?.value[0].valueOverride).toBeUndefined();
200
+ });
201
+
202
+ it('should omit separator details', () => {
203
+ const resource = { details: [{ separator: true }] };
204
+ const result = useResourceDetails(resource);
205
+
206
+ expect(result?.value).toHaveLength(0);
207
+ });
208
+
209
+ it('should return valid resourceDetail with valueOverride', () => {
210
+ const resource = {
211
+ details: [{
212
+ label: 'LABEL', content: 'CONTENT', formatter: 'FORMATTER', formatterOpts: { key: 'value' }
213
+ }]
214
+ };
215
+ const result = useResourceDetails(resource);
216
+
217
+ expect(result?.value[0].label).toStrictEqual(resource.details[0].label);
218
+ expect(result?.value[0].value).toStrictEqual(resource.details[0].content);
219
+ expect(result?.value[0].valueOverride?.component).toStrictEqual(resource.details[0].formatter);
220
+ expect(result?.value[0].valueOverride?.props).toStrictEqual({ value: resource.details[0].content, ...resource.details[0].formatterOpts });
221
+ });
222
+ });
223
+ });
@@ -1,263 +1,44 @@
1
- import { useI18n } from '@shell/composables/useI18n';
2
- import { computed, ComputedRef, markRaw, toValue } from 'vue';
3
- import LiveDate from '@shell/components/formatter/LiveDate.vue';
4
- import LinkName from '@shell/components/formatter/LinkName.vue';
5
- import Additional from '@shell/components/Resource/Detail/Additional.vue';
6
- import { useStore } from 'vuex';
7
- import CopyToClipboardText from '@shell/components/CopyToClipboardText.vue';
8
- import IconText from '@shell/components/formatter/IconText.vue';
9
- import { NODE } from '@shell/config/types';
10
- import day from 'dayjs';
1
+ import { computed, ComputedRef, toValue } from 'vue';
11
2
  import { Row } from '@shell/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue';
3
+ import {
4
+ useCertificate,
5
+ useExpires,
6
+ useImage, useIssuer, useLiveDate, useNamespace, useReady, useSecretType,
7
+ useServiceAccount
8
+ } from '@shell/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields';
9
+ import { useStore } from 'vuex';
10
+ import { useI18n } from '@shell/composables/useI18n';
12
11
 
13
- export const useContainerRuntime = (resource: any): ComputedRef<Row> => {
14
- const store = useStore();
15
- const i18n = useI18n(store);
16
- const resourceValue = toValue(resource);
17
-
18
- return computed(() => ({
19
- label: i18n.t('node.detail.detailTop.containerRuntime'),
20
- valueOverride: {
21
- component: markRaw(IconText),
22
- props: { value: resourceValue.containerRuntimeVersion, iconClass: resourceValue.containerRuntimeIcon }
23
- },
24
- value: resourceValue.containerRuntimeVersion
25
- }));
26
- };
27
-
28
- export const useExternalIp = (resource: any): ComputedRef<Row> => {
29
- const store = useStore();
30
- const i18n = useI18n(store);
31
- const resourceValue = toValue(resource);
32
-
33
- return computed(() => ({
34
- label: i18n.t('node.detail.detailTop.externalIP'),
35
- valueOverride: {
36
- component: markRaw(CopyToClipboardText),
37
- props: { text: resourceValue.externalIp }
38
- },
39
- value: resourceValue.externalIp
40
- }));
41
- };
42
-
43
- export const usePodIp = (resource: any): ComputedRef<Row> => {
44
- const store = useStore();
45
- const i18n = useI18n(store);
46
- const resourceValue = toValue(resource);
47
-
48
- return computed(() => ({
49
- label: i18n.t('workload.detailTop.podIP'),
50
- value: resourceValue.status.podIP
51
- }));
52
- };
53
-
54
- export const useWorkload = (resource: any): ComputedRef<Row> => {
55
- const store = useStore();
56
- const i18n = useI18n(store);
57
- const resourceValue = toValue(resource);
58
-
59
- return computed(() => ({
60
- label: i18n.t('workload.detailTop.workload'),
61
- valueOverride: {
62
- component: markRaw(LinkName),
63
- props: {
64
- type: resourceValue.workloadRef.type,
65
- value: resourceValue.workloadRef.name,
66
- namespace: resourceValue.workloadRef.namespace
67
- }
68
- },
69
- value: resourceValue.workloadRef.name
70
- }));
71
- };
72
-
73
- export const useNode = (resource: any): ComputedRef<Row> => {
74
- const store = useStore();
75
- const i18n = useI18n(store);
76
- const resourceValue = toValue(resource);
77
-
78
- return computed(() => ({
79
- label: i18n.t('workload.detailTop.node'),
80
- valueOverride: {
81
- component: markRaw(LinkName),
82
- props: { type: NODE, value: resourceValue.spec.nodeName }
83
- },
84
- value: resourceValue.spec.nodeName
85
- }));
86
- };
87
-
88
- export const useStarted = (resource: any): ComputedRef<Row> => {
89
- const store = useStore();
90
- const i18n = useI18n(store);
91
- const resourceValue = toValue(resource);
92
-
93
- return computed(() => ({
94
- label: i18n.t('workload.detailTop.started'),
95
- valueOverride: {
96
- component: markRaw(LiveDate),
97
- props: { addSuffix: true, value: resourceValue.status.startTime }
98
- },
99
- value: resourceValue.spec.nodeName
100
- }));
101
- };
102
-
103
- export const useDuration = (resource: any): ComputedRef<Row> => {
104
- const store = useStore();
105
- const i18n = useI18n(store);
106
- const resourceValue = toValue(resource);
107
-
108
- const FACTORS = [60, 60, 24];
109
- const LABELS = ['sec', 'min', 'hour', 'day'];
110
- const value = computed(() => {
111
- const { completionTime, startTime } = resourceValue.status;
112
- const end = day(completionTime);
113
- const start = day(startTime);
114
- let diff = end.diff(start) / 1000;
115
-
116
- let label: any;
117
-
118
- let i = 0;
119
-
120
- while (diff >= FACTORS[i] && i < FACTORS.length) {
121
- diff /= FACTORS[i];
122
- i++;
123
- }
124
-
125
- if (diff < 5) {
126
- label = Math.floor(diff * 10) / 10;
127
- } else {
128
- label = Math.floor(diff);
129
- }
130
-
131
- label += ` ${ i18n.t(`unit.${ LABELS[i] }`, { count: label }) } `;
132
- label = label.trim();
12
+ export const useDefaultIdentifyingInformation = (resource: any): ComputedRef<Row[]> => {
13
+ const namespace = useNamespace(resource);
14
+ const liveDate = useLiveDate(resource);
133
15
 
134
- return label;
16
+ return computed(() => {
17
+ return [
18
+ namespace?.value,
19
+ liveDate?.value
20
+ ].filter((info) => typeof info !== 'undefined');
135
21
  });
136
-
137
- return computed(() => ({
138
- label: i18n.t('workload.detailTop.duration'),
139
- valueOverride: {
140
- component: markRaw(LiveDate),
141
- props: { value: value.value }
142
- },
143
- value: value.value
144
- }));
145
- };
146
-
147
- export const useImage = (resource: any): ComputedRef<Row> => {
148
- const store = useStore();
149
- const i18n = useI18n(store);
150
- const resourceValue = toValue(resource);
151
-
152
- return computed(() => ({
153
- label: i18n.t('component.resource.detail.metadata.identifyingInformation.image'),
154
- value: resourceValue.imageNames,
155
- valueOverride: {
156
- component: markRaw(Additional),
157
- props: { items: resourceValue.imageNames }
158
- },
159
- }));
160
- };
161
-
162
- export const useReady = (resource: any): ComputedRef<Row> => {
163
- const store = useStore();
164
- const i18n = useI18n(store);
165
- const resourceValue = toValue(resource);
166
-
167
- return computed(() => ({
168
- label: i18n.t('component.resource.detail.metadata.identifyingInformation.ready'),
169
- value: resourceValue.ready,
170
- }));
171
- };
172
-
173
- export const useRestarts = (resource: any): ComputedRef<Row> => {
174
- const store = useStore();
175
- const i18n = useI18n(store);
176
- const resourceValue = toValue(resource);
177
-
178
- return computed(() => ({
179
- label: i18n.t('workload.detailTop.podRestarts'),
180
- value: resourceValue.restartCount
181
- }));
182
22
  };
183
23
 
184
- export const useInternalIp = (resource: any): ComputedRef<Row> => {
185
- const store = useStore();
186
- const i18n = useI18n(store);
187
- const resourceValue = toValue(resource);
24
+ export const useSecretIdentifyingInformation = (resource: any): ComputedRef<Row[]> => {
25
+ const secretType = useSecretType(resource);
26
+ const serviceAccount = useServiceAccount(resource);
27
+ const certificate = useCertificate(resource);
28
+ const issuer = useIssuer(resource);
29
+ const expires = useExpires(resource);
188
30
 
189
- return computed(() => ({
190
- label: i18n.t('node.detail.detailTop.internalIP'),
191
- valueOverride: {
192
- component: markRaw(CopyToClipboardText),
193
- props: { text: resourceValue.internalIp }
194
- },
195
- value: resourceValue.internalIp
196
- }));
197
- };
31
+ return computed(() => {
32
+ const rows = [
33
+ secretType?.value,
34
+ serviceAccount?.value,
35
+ certificate?.value,
36
+ issuer?.value,
37
+ expires?.value,
38
+ ];
198
39
 
199
- export const useVersion = (resource: any): ComputedRef<Row> => {
200
- const store = useStore();
201
- const i18n = useI18n(store);
202
- const resourceValue = toValue(resource);
203
-
204
- return computed(() => ({
205
- label: i18n.t('node.detail.detailTop.version'),
206
- value: resourceValue.version
207
- }));
208
- };
209
-
210
- export const useOs = (resource: any): ComputedRef<Row> => {
211
- const store = useStore();
212
- const i18n = useI18n(store);
213
- const resourceValue = toValue(resource);
214
-
215
- return computed(() => ({
216
- label: i18n.t('node.detail.detailTop.os'),
217
- value: resourceValue.status.nodeInfo.osImage
218
- }));
219
- };
220
-
221
- export const useLiveDate = (resource: any): ComputedRef<Row> => {
222
- const store = useStore();
223
- const i18n = useI18n(store);
224
- const resourceValue = toValue(resource);
225
-
226
- return computed(() => ({
227
- label: i18n.t('component.resource.detail.metadata.identifyingInformation.age'),
228
- valueOverride: {
229
- component: markRaw(LiveDate),
230
- props: { value: resourceValue.creationTimestamp }
231
- },
232
- value: resourceValue.age,
233
- }));
234
- };
235
-
236
- export const useProject = (resource: any): ComputedRef<Row> => {
237
- const store = useStore();
238
- const i18n = useI18n(store);
239
- const resourceValue = toValue(resource);
240
-
241
- return computed(() => ({
242
- label: i18n.t('component.resource.detail.metadata.identifyingInformation.project'),
243
- value: resourceValue.project.nameDisplay,
244
- to: '#'
245
- }));
246
- };
247
-
248
- export const useDefaultIdentifyingInformation = (resource: any): ComputedRef<Row[]> => {
249
- const store = useStore();
250
- const i18n = useI18n(store);
251
- const resourceValue = toValue(resource);
252
- const liveDate = useLiveDate(resource);
253
-
254
- return computed(() => [
255
- {
256
- label: i18n.t('component.resource.detail.metadata.identifyingInformation.namespace'),
257
- value: resourceValue.namespace,
258
- },
259
- liveDate.value
260
- ]);
40
+ return rows.filter((r) => typeof r !== 'undefined');
41
+ });
261
42
  };
262
43
 
263
44
  export const useDefaultWorkloadIdentifyingInformation = (resource: any): ComputedRef<Row[]> => {
@@ -265,10 +46,12 @@ export const useDefaultWorkloadIdentifyingInformation = (resource: any): Compute
265
46
  const i18n = useI18n(store);
266
47
 
267
48
  const resourceValue = toValue(resource);
49
+ const image = useImage(resource);
50
+ const ready = useReady(resource);
268
51
 
269
52
  return computed(() => [
270
- useImage(resource).value,
271
- useReady(resource).value,
53
+ image.value,
54
+ ready.value,
272
55
  {
273
56
  label: i18n.t('component.resource.detail.metadata.identifyingInformation.up-to-date'),
274
57
  value: resourceValue.upToDate,