@rancher/shell 3.0.5-rc.8 → 3.0.5-rc.9

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 (171) hide show
  1. package/assets/styles/base/_color.scss +4 -1
  2. package/assets/styles/global/_tooltip.scss +7 -4
  3. package/assets/styles/themes/_dark.scss +11 -0
  4. package/assets/styles/themes/_light.scss +13 -1
  5. package/assets/styles/themes/_modern.scss +22 -0
  6. package/assets/translations/en-us.yaml +136 -14
  7. package/assets/translations/zh-hans.yaml +0 -1
  8. package/chart/monitoring/grafana/index.vue +8 -2
  9. package/components/ActionMenuShell.vue +3 -1
  10. package/components/Cron/CronExpressionEditor.vue +299 -0
  11. package/components/Cron/CronExpressionEditorModal.vue +247 -0
  12. package/components/Cron/CronTooltip.vue +87 -0
  13. package/components/Cron/types.ts +13 -0
  14. package/components/ForceDirectedTreeChart/composable.ts +11 -0
  15. package/components/PromptModal.vue +1 -1
  16. package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +1 -0
  17. package/components/Resource/Detail/CopyToClipboard.vue +78 -0
  18. package/components/Resource/Detail/FetchLoader/__tests__/composables.test.ts +69 -0
  19. package/components/Resource/Detail/FetchLoader/composables.ts +27 -0
  20. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +1 -1
  21. package/components/Resource/Detail/Metadata/Annotations/index.vue +1 -1
  22. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +13 -61
  23. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +33 -6
  24. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +24 -38
  25. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +25 -5
  26. package/components/Resource/Detail/Metadata/KeyValue.vue +12 -23
  27. package/components/Resource/Detail/Metadata/KeyValueRow.vue +144 -0
  28. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +1 -0
  29. package/components/Resource/Detail/Metadata/Labels/index.vue +1 -0
  30. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +30 -32
  31. package/components/Resource/Detail/Metadata/__tests__/KeyValueRow.test.ts +108 -0
  32. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +0 -3
  33. package/components/Resource/Detail/Metadata/__tests__/index.test.ts +12 -5
  34. package/components/Resource/Detail/Metadata/composables.ts +1 -4
  35. package/components/Resource/Detail/Metadata/index.vue +1 -0
  36. package/components/Resource/Detail/Preview/Content.vue +63 -0
  37. package/components/Resource/Detail/Preview/Preview.vue +128 -0
  38. package/components/Resource/Detail/Preview/__tests__/Content.spec.ts +71 -0
  39. package/components/Resource/Detail/Preview/__tests__/Preview.spec.ts +121 -0
  40. package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +141 -0
  41. package/components/Resource/Detail/ResourcePopover/__tests__/ResourcePopoverCard.test.ts +136 -0
  42. package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +245 -0
  43. package/components/Resource/Detail/ResourcePopover/index.vue +226 -0
  44. package/components/Resource/Detail/SpacedRow.vue +1 -0
  45. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +0 -5
  46. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +1 -1
  47. package/components/Resource/Detail/TitleBar/composables.ts +1 -3
  48. package/components/Resource/Detail/TitleBar/index.vue +2 -29
  49. package/components/Resource/Detail/ViewOptions/composable.ts +9 -0
  50. package/components/Resource/Detail/ViewOptions/index.vue +41 -0
  51. package/components/Resource/Detail/__tests__/CopyToClipboard.spec.ts +82 -0
  52. package/components/ResourceDetail/Masthead/legacy.vue +0 -19
  53. package/components/ResourceDetail/index.vue +1 -26
  54. package/components/ResourceTable.vue +24 -0
  55. package/components/SortableTable/index.vue +7 -1
  56. package/components/SortableTable/paging.js +3 -0
  57. package/components/Tabbed/Tab.vue +43 -1
  58. package/components/Tabbed/index.vue +3 -1
  59. package/components/__tests__/Cron/CronExpressionEditor.test.ts +151 -0
  60. package/components/__tests__/Cron/CronExpressionEditorModal.test.ts +81 -0
  61. package/components/auth/login/saml.vue +86 -0
  62. package/components/form/LabeledSelect.vue +8 -8
  63. package/components/form/ResourceTabs/composable.ts +54 -0
  64. package/components/form/ResourceTabs/index.vue +10 -7
  65. package/components/form/Select.vue +13 -10
  66. package/components/form/__tests__/LabeledSelect.test.ts +133 -0
  67. package/components/form/__tests__/Select.test.ts +134 -0
  68. package/composables/useExtensionManager.ts +17 -0
  69. package/config/home-links.js +12 -0
  70. package/config/labels-annotations.js +0 -1
  71. package/config/page-actions.js +0 -1
  72. package/config/product/explorer.js +3 -1
  73. package/config/product/fleet.js +2 -7
  74. package/config/product/manager.js +0 -5
  75. package/config/query-params.js +1 -0
  76. package/config/router/navigation-guards/clusters.js +2 -1
  77. package/config/router/navigation-guards/products.js +1 -1
  78. package/core/extension-manager-impl.js +518 -0
  79. package/core/plugins.js +35 -468
  80. package/core/types.ts +8 -2
  81. package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +1 -0
  82. package/detail/catalog.cattle.io.app.vue +7 -4
  83. package/detail/fleet.cattle.io.bundle.vue +1 -5
  84. package/detail/fleet.cattle.io.cluster.vue +3 -2
  85. package/detail/fleet.cattle.io.gitrepo.vue +76 -49
  86. package/detail/fleet.cattle.io.helmop.vue +78 -49
  87. package/dialog/AddonConfigConfirmationDialog.vue +1 -1
  88. package/dialog/GenericPrompt.vue +1 -1
  89. package/dialog/ImportDialog.vue +9 -2
  90. package/dialog/InstallExtensionDialog.vue +18 -10
  91. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +2 -1
  92. package/edit/__tests__/resources.cattle.io.restore.test.ts +106 -0
  93. package/edit/cloudcredential.vue +31 -17
  94. package/edit/constraints.gatekeeper.sh.constraint/index.vue +10 -2
  95. package/edit/fleet.cattle.io.cluster.vue +19 -0
  96. package/edit/fleet.cattle.io.gitrepo.vue +23 -16
  97. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +12 -11
  98. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +11 -1
  99. package/edit/provisioning.cattle.io.cluster/index.vue +14 -19
  100. package/edit/provisioning.cattle.io.cluster/rke2.vue +11 -3
  101. package/edit/resources.cattle.io.restore.vue +5 -8
  102. package/list/__tests__/workload.test.ts +1 -0
  103. package/list/workload.vue +8 -1
  104. package/machine-config/components/GCEImage.vue +6 -5
  105. package/machine-config/google.vue +11 -6
  106. package/mixins/__tests__/chart.test.ts +139 -1
  107. package/mixins/chart.js +58 -18
  108. package/models/__tests__/namespace.test.ts +69 -0
  109. package/models/apps.statefulset.js +8 -10
  110. package/models/chart.js +5 -1
  111. package/models/fleet-application.js +16 -46
  112. package/models/fleet.cattle.io.bundle.js +1 -38
  113. package/models/fleet.cattle.io.gitrepo.js +4 -0
  114. package/models/fleet.cattle.io.helmop.js +4 -0
  115. package/models/management.cattle.io.project.js +12 -0
  116. package/models/namespace.js +30 -0
  117. package/models/workload.js +3 -0
  118. package/package.json +10 -10
  119. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +26 -11
  120. package/pages/c/_cluster/apps/charts/chart.vue +29 -20
  121. package/pages/c/_cluster/apps/charts/index.vue +1 -0
  122. package/pages/c/_cluster/apps/charts/install.vue +6 -5
  123. package/pages/c/_cluster/explorer/tools/__tests__/index.test.ts +102 -12
  124. package/pages/c/_cluster/explorer/tools/index.vue +145 -254
  125. package/pages/c/_cluster/manager/cloudCredential/index.vue +18 -1
  126. package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +12 -2
  127. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -1
  128. package/pages/c/_cluster/uiplugins/__tests__/index.spec.ts +318 -0
  129. package/pages/c/_cluster/uiplugins/index.vue +221 -363
  130. package/pages/home.vue +1 -9
  131. package/plugins/dashboard-store/resource-class.js +49 -0
  132. package/public/index.html +2 -1
  133. package/rancher-components/Card/Card.vue +1 -1
  134. package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
  135. package/rancher-components/Form/Radio/RadioButton.vue +1 -1
  136. package/rancher-components/Form/Radio/RadioGroup.vue +1 -1
  137. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -11
  138. package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.test.ts +53 -0
  139. package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.vue +65 -0
  140. package/rancher-components/Pill/RcCounterBadge/index.ts +1 -0
  141. package/rancher-components/Pill/RcCounterBadge/types.ts +7 -0
  142. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +1 -1
  143. package/rancher-components/Pill/RcStatusBadge/index.ts +1 -1
  144. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +3 -3
  145. package/rancher-components/Pill/RcStatusIndicator/types.ts +1 -1
  146. package/rancher-components/Pill/RcTag/RcTag.test.ts +64 -0
  147. package/rancher-components/Pill/RcTag/RcTag.vue +94 -0
  148. package/rancher-components/Pill/RcTag/index.ts +1 -0
  149. package/rancher-components/Pill/RcTag/types.ts +9 -0
  150. package/rancher-components/Pill/types.ts +1 -0
  151. package/rancher-components/RcItemCard/RcItemCard.vue +1 -0
  152. package/rancher-components/RcItemCard/RcItemCardAction.vue +12 -0
  153. package/store/__tests__/catalog.test.ts +63 -0
  154. package/store/catalog.js +2 -2
  155. package/store/type-map.js +3 -15
  156. package/types/extension-manager.ts +26 -0
  157. package/types/shell/index.d.ts +121 -16
  158. package/utils/__tests__/product.test.ts +129 -0
  159. package/utils/__tests__/resource.test.ts +87 -0
  160. package/utils/alertmanagerconfig.js +2 -2
  161. package/utils/auth.js +3 -76
  162. package/utils/product.ts +39 -0
  163. package/utils/resource.ts +35 -0
  164. package/utils/select.js +0 -24
  165. package/utils/validators/formRules/__tests__/index.test.ts +3 -0
  166. package/utils/validators/formRules/index.ts +2 -1
  167. package/vue.config.js +1 -1
  168. package/components/Resource/Detail/Metadata/Rectangle.vue +0 -34
  169. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +0 -24
  170. package/components/ResourceDetail/Masthead/__tests__/legacy.test.ts +0 -65
  171. /package/components/{ForceDirectedTreeChart.vue → ForceDirectedTreeChart/index.vue} +0 -0
package/pages/home.vue CHANGED
@@ -22,7 +22,7 @@ import { filterHiddenLocalCluster, filterOnlyKubernetesClusters, paginationFilte
22
22
  import TabTitle from '@shell/components/TabTitle.vue';
23
23
  import { ActionFindPageArgs } from '@shell/types/store/dashboard-store.types';
24
24
 
25
- import { RESET_CARDS_ACTION, SET_LOGIN_ACTION, SHOW_HIDE_BANNER_ACTION } from '@shell/config/page-actions';
25
+ import { SET_LOGIN_ACTION, SHOW_HIDE_BANNER_ACTION } from '@shell/config/page-actions';
26
26
  import { STEVE_NAME_COL, STEVE_STATE_COL } from '@shell/config/pagination-table-headers';
27
27
  import { PaginationParamFilter, FilterArgs, PaginationFilterField, PaginationArgs } from '@shell/types/store/pagination.types';
28
28
  import ProvCluster from '@shell/models/provisioning.cattle.io.cluster';
@@ -75,10 +75,6 @@ export default defineComponent({
75
75
  label: this.t('nav.header.showHideBanner'),
76
76
  action: SHOW_HIDE_BANNER_ACTION
77
77
  },
78
- {
79
- label: this.t('nav.header.restoreCards'),
80
- action: RESET_CARDS_ACTION
81
- },
82
78
  ],
83
79
  vendor: getVendor(),
84
80
 
@@ -368,10 +364,6 @@ export default defineComponent({
368
364
  */
369
365
  handlePageAction(action: any) {
370
366
  switch (action.action) {
371
- case RESET_CARDS_ACTION:
372
- this.resetCards();
373
- break;
374
-
375
367
  case SHOW_HIDE_BANNER_ACTION:
376
368
  this.toggleBanner();
377
369
  break;
@@ -1847,6 +1847,55 @@ export default class Resource {
1847
1847
  return details;
1848
1848
  }
1849
1849
 
1850
+ get glance() {
1851
+ return this._glance;
1852
+ }
1853
+
1854
+ get _glance() {
1855
+ const type = this.parentNameOverride || this.$rootGetters['type-map/labelFor'](this.schema);
1856
+
1857
+ return [
1858
+ {
1859
+ name: 'state',
1860
+ label: this.t('component.resource.detail.glance.state'),
1861
+ formatter: 'BadgeStateFormatter',
1862
+ formatterOpts: { row: this },
1863
+ content: this.stateDisplay
1864
+ },
1865
+ {
1866
+ name: 'type',
1867
+ label: this.t('component.resource.detail.glance.type'),
1868
+ formatter: 'Link',
1869
+ formatterOpts: {
1870
+ to: this.listLocation, row: {}, options: { internal: true }
1871
+ },
1872
+ content: type
1873
+ },
1874
+ {
1875
+ name: 'namespace',
1876
+ label: this.t('component.resource.detail.glance.namespace'),
1877
+ formatter: 'Link',
1878
+ formatterOpts: {
1879
+ to: {
1880
+ name: `c-cluster-product-resource-id`,
1881
+ product: this.$rootGetters['currentProduct'].id,
1882
+ cluster: this.$rootGetters['currentCluster'].id,
1883
+ resource: this.type
1884
+ },
1885
+ row: {},
1886
+ options: { internal: true }
1887
+ },
1888
+ content: this.namespacedName
1889
+ },
1890
+ {
1891
+ name: 'age',
1892
+ label: this.t('component.resource.detail.glance.age'),
1893
+ formatter: 'LiveDate',
1894
+ content: this.creationTimestamp
1895
+ }
1896
+ ];
1897
+ }
1898
+
1850
1899
  get t() {
1851
1900
  return this.$rootGetters['i18n/t'];
1852
1901
  }
package/public/index.html CHANGED
@@ -17,6 +17,7 @@
17
17
  </div>
18
18
  <div id="modals"><!--Portal content here--></div>
19
19
  <div id="slides"></div>
20
+ <div id="preview"></div>
20
21
 
21
22
  <script>
22
23
  (() => {
@@ -72,4 +73,4 @@
72
73
  </style>
73
74
  </body>
74
75
 
75
- </html>
76
+ </html>
@@ -98,7 +98,7 @@ export default defineComponent({
98
98
  </div>
99
99
  </template>
100
100
 
101
- <style lang='scss'>
101
+ <style lang='scss' scoped>
102
102
  .card-container {
103
103
  &.highlight-border {
104
104
  border-left: 5px solid var(--primary);
@@ -360,7 +360,7 @@ export default defineComponent({
360
360
  </div>
361
361
  </template>
362
362
 
363
- <style lang='scss'>
363
+ <style lang='scss' scoped>
364
364
  $fontColor: var(--input-label);
365
365
 
366
366
  .checkbox-outer-container {
@@ -226,7 +226,7 @@ export default defineComponent({
226
226
  </label>
227
227
  </template>
228
228
 
229
- <style lang='scss'>
229
+ <style lang='scss' scoped>
230
230
  $fontColor: var(--input-label);
231
231
 
232
232
  .radio-view {
@@ -311,7 +311,7 @@ export default defineComponent({
311
311
  </div>
312
312
  </template>
313
313
 
314
- <style lang='scss'>
314
+ <style lang='scss' scoped>
315
315
  .radio-group {
316
316
  &:focus, &:focus-visible {
317
317
  border: none;
@@ -95,7 +95,7 @@ export default defineComponent({
95
95
  </div>
96
96
  </template>
97
97
 
98
- <style lang='scss'>
98
+ <style lang='scss' scoped>
99
99
  .labeled-tooltip {
100
100
  position: absolute;
101
101
  width: 100%;
@@ -137,14 +137,4 @@ export default defineComponent({
137
137
  @include tooltipColors(var(--success));
138
138
  }
139
139
  }
140
-
141
- // Ensure code blocks inside tootips don't look awful
142
- .v-popper__popper.v-popper--theme-tooltip {
143
- .v-popper__inner {
144
- pre {
145
- padding: 2px;
146
- vertical-align: middle;
147
- }
148
- }
149
- }
150
140
  </style>
@@ -0,0 +1,53 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import RcCounterBadge from './index';
3
+ import { Type } from '../types';
4
+
5
+ describe('component: RcCounterBadge', () => {
6
+ const types: Type[] = ['active', 'inactive'];
7
+
8
+ it.each(types)('should apply correct classes for type "%s"', (type) => {
9
+ const wrapper = mount(RcCounterBadge, { props: { type, count: 1 } });
10
+
11
+ const shapeEl = wrapper.find('.rc-counter-badge');
12
+
13
+ expect(shapeEl.classes()).toContain(type);
14
+ });
15
+
16
+ it('should apply the correct class for disabled', () => {
17
+ const wrapper = mount(RcCounterBadge, {
18
+ props: {
19
+ type: 'active', disabled: true, count: 1
20
+ }
21
+ });
22
+
23
+ const shapeEl = wrapper.find('.rc-counter-badge');
24
+
25
+ expect(shapeEl.classes()).toContain('disabled');
26
+ });
27
+
28
+ it('should show the correct count below 1000', () => {
29
+ const count = 999;
30
+ const wrapper = mount(RcCounterBadge, {
31
+ props: {
32
+ type: 'active', disabled: true, count
33
+ }
34
+ });
35
+
36
+ const shapeEl = wrapper.find('.rc-counter-badge');
37
+
38
+ expect(shapeEl.text()).toBe(count.toString());
39
+ });
40
+
41
+ it('should show the correct count at or above 1000', () => {
42
+ const count = 1000;
43
+ const wrapper = mount(RcCounterBadge, {
44
+ props: {
45
+ type: 'active', disabled: true, count
46
+ }
47
+ });
48
+
49
+ const shapeEl = wrapper.find('.rc-counter-badge');
50
+
51
+ expect(shapeEl.text()).toBe('999+');
52
+ });
53
+ });
@@ -0,0 +1,65 @@
1
+ <script setup lang="ts">
2
+ import { RcCounterBadgeProps } from '@components/Pill/RcCounterBadge/types';
3
+ import { computed } from 'vue';
4
+ const props = withDefaults(defineProps<RcCounterBadgeProps>(), { disabled: false });
5
+ const displayCount = computed(() => props.count < 1000 ? props.count : '999+');
6
+ </script>
7
+
8
+ <template>
9
+ <div
10
+ class="rc-counter-badge"
11
+ :class="{[props.type]: true, disabled: props.disabled}"
12
+ >
13
+ {{ displayCount }}
14
+ </div>
15
+ </template>
16
+
17
+ <style lang="scss" scoped>
18
+ .rc-counter-badge {
19
+ display: inline-flex;
20
+ padding: 1px 8px;
21
+ align-items: center;
22
+ gap: 8px;
23
+
24
+ border-radius: 30px;
25
+ border: 1px solid var(--rc-active-border);
26
+
27
+ overflow: hidden;
28
+ text-overflow: ellipsis;
29
+ font-family: Lato;
30
+ font-size: 13px;
31
+ font-style: normal;
32
+ font-weight: 400;
33
+ line-height: 22px;
34
+ color: var(--body-text);
35
+
36
+ &.active {
37
+ border-color: var(--rc-active-border);
38
+ background: var(--rc-active-background);
39
+ cursor: pointer;
40
+
41
+ &:hover {
42
+ border-color: var(--rc-primary-hover);
43
+ background: var(--rc-active-background);
44
+ }
45
+
46
+ &.disabled {
47
+ border-color: var(--rc-active-border);
48
+ background: var(--rc-active-disabled-background);
49
+ color: var(--rc-disabled-text-color);
50
+
51
+ cursor: not-allowed;
52
+ }
53
+ }
54
+
55
+ &.inactive {
56
+ background: var(--rc-inactive-background);
57
+ border-color: var(--rc-inactive-border);
58
+
59
+ &.disabled {
60
+ border-color: var(--rc-inactive-disabled-border);
61
+ color: var(--rc-disabled-text-color);
62
+ }
63
+ }
64
+ }
65
+ </style>
@@ -0,0 +1 @@
1
+ export { default } from './RcCounterBadge.vue';
@@ -0,0 +1,7 @@
1
+ import { Type } from '../types';
2
+
3
+ export interface RcCounterBadgeProps {
4
+ count: number;
5
+ type: Type;
6
+ disabled?: boolean;
7
+ }
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { RcStatusBadgeProps } from '@components/Pill/RcStatusBadge/types';
2
+ import { RcStatusBadgeProps } from './types';
3
3
 
4
4
  const props = defineProps<RcStatusBadgeProps>();
5
5
  </script>
@@ -1,2 +1,2 @@
1
1
  export { default } from './RcStatusBadge.vue';
2
- export type { Status } from '@components/Pill/types';
2
+ export type { Status } from '../types';
@@ -1,5 +1,5 @@
1
1
  <script setup lang="ts">
2
- import { RcStatusIndicatorProps } from '@components/Pill/RcStatusIndicator/types';
2
+ import { RcStatusIndicatorProps } from './types';
3
3
 
4
4
  const props = defineProps<RcStatusIndicatorProps>();
5
5
  </script>
@@ -25,8 +25,8 @@ const props = defineProps<RcStatusIndicatorProps>();
25
25
  border: 1px solid transparent;
26
26
 
27
27
  &.disc {
28
- width: 6px;
29
- height: 6px;
28
+ width: 8px;
29
+ height: 8px;
30
30
  border-radius: 50%;
31
31
  }
32
32
 
@@ -1,4 +1,4 @@
1
- import { Status } from '@components/Pill/types';
1
+ import { Status } from '../types';
2
2
  export type Shape = 'disc' | 'horizontal-bar' | 'vertical-bar';
3
3
 
4
4
  export interface RcStatusIndicatorProps {
@@ -0,0 +1,64 @@
1
+ import { mount } from '@vue/test-utils';
2
+ import RcTag from './index';
3
+ import { Type } from './types';
4
+
5
+ describe('component: RcTag', () => {
6
+ const types: Type[] = ['active', 'inactive'];
7
+
8
+ it.each(types)('should apply correct classes for type "%s"', (type) => {
9
+ const wrapper = mount(RcTag, { props: { type } });
10
+
11
+ const shapeEl = wrapper.find('.rc-tag');
12
+
13
+ expect(shapeEl.classes()).toContain(type);
14
+ });
15
+
16
+ it('should apply the correct class for disabled', () => {
17
+ const wrapper = mount(RcTag, { props: { type: 'active', disabled: true } });
18
+
19
+ const shapeEl = wrapper.find('.rc-tag');
20
+
21
+ expect(shapeEl.classes()).toContain('disabled');
22
+ });
23
+
24
+ it('should show the close button if showClose is true', () => {
25
+ const wrapper = mount(RcTag, {
26
+ props: {
27
+ type: 'active', disabled: true, showClose: true
28
+ }
29
+ });
30
+
31
+ const shapeEl = wrapper.find('.rc-tag');
32
+
33
+ expect(shapeEl.find('.icon-close').exists()).toBeTruthy();
34
+ });
35
+
36
+ it('should emit close event when close button is clicked', () => {
37
+ const wrapper = mount(RcTag, {
38
+ props: {
39
+ type: 'active', disabled: true, showClose: true
40
+ }
41
+ });
42
+
43
+ const shapeEl = wrapper.find('.rc-tag');
44
+ const close = shapeEl.find('button');
45
+
46
+ close.trigger('click');
47
+
48
+ expect(wrapper.emitted('close')).toBeTruthy();
49
+ });
50
+
51
+ it('should add the aria-label to the button when specified', () => {
52
+ const closeAria = 'CLOSE_ARIA';
53
+ const wrapper = mount(RcTag, {
54
+ props: {
55
+ type: 'active', disabled: true, showClose: true, closeAriaLabel: closeAria
56
+ }
57
+ });
58
+
59
+ const shapeEl = wrapper.find('.rc-tag');
60
+ const close = shapeEl.find('button');
61
+
62
+ expect(close.attributes('aria-label')).toBe(closeAria);
63
+ });
64
+ });
@@ -0,0 +1,94 @@
1
+ <script setup lang="ts">
2
+ import RcButton from '@components/RcButton/RcButton.vue';
3
+ import { RcTagProps } from './types';
4
+
5
+ const props = withDefaults(defineProps<RcTagProps>(), {
6
+ disabled: false, showClose: false, highlight: undefined
7
+ });
8
+ const emit = defineEmits(['close']);
9
+ </script>
10
+
11
+ <template>
12
+ <div
13
+ class="rc-tag"
14
+ :class="{[props.type]: true, disabled: props.disabled, highlight: props.highlight}"
15
+ >
16
+ <slot name="default" />
17
+ <RcButton
18
+ v-if="props.showClose"
19
+ ghost
20
+ :aria-label="props.closeAriaLabel"
21
+ @click="emit('close')"
22
+ >
23
+ <i class="icon icon-close" />
24
+ </RcButton>
25
+ </div>
26
+ </template>
27
+
28
+ <style lang="scss" scoped>
29
+ .rc-tag {
30
+ display: inline-flex;
31
+ padding: 1px 8px;
32
+ align-items: center;
33
+ gap: 8px;
34
+
35
+ border-radius: 4px;
36
+ border: 1px solid var(--rc-active-border);
37
+
38
+ overflow: hidden;
39
+ text-overflow: ellipsis;
40
+ font-family: Lato;
41
+ font-size: 13px;
42
+ font-style: normal;
43
+ font-weight: 400;
44
+ line-height: 22px;
45
+ color: var(--body-text);
46
+
47
+ button {
48
+ $size: 12px;
49
+ padding: 0;
50
+ line-height: $size;
51
+ min-height: $size;
52
+ background: none;
53
+
54
+ &, .icon-close {
55
+ width: $size;
56
+ height: $size;
57
+ font-size: $size;
58
+ }
59
+ }
60
+
61
+ &.disabled button {
62
+ cursor: not-allowed;
63
+ }
64
+
65
+ &.active {
66
+ border-color: var(--rc-active-border);
67
+ background: var(--rc-active-background);
68
+ cursor: pointer;
69
+
70
+ &.highlight, &:hover {
71
+ border-color: var(--rc-primary-hover);
72
+ background: var(--rc-active-background);
73
+ }
74
+
75
+ &.disabled {
76
+ border-color: var(--rc-active-border);
77
+ background: var(--rc-active-disabled-background);
78
+ color: var(--rc-disabled-text-color);
79
+
80
+ cursor: not-allowed;
81
+ }
82
+ }
83
+
84
+ &.inactive {
85
+ background: var(--rc-inactive-background);
86
+ border-color: var(--rc-inactive-border);
87
+
88
+ &.disabled {
89
+ border-color: var(--rc-inactive-disabled-border);
90
+ color: var(--rc-disabled-text-color);
91
+ }
92
+ }
93
+ }
94
+ </style>
@@ -0,0 +1 @@
1
+ export { default } from './RcTag.vue';
@@ -0,0 +1,9 @@
1
+ import { Type } from '../types';
2
+
3
+ export interface RcTagProps {
4
+ type: Type;
5
+ disabled?: boolean;
6
+ showClose?: boolean;
7
+ closeAriaLabel?: string;
8
+ highlight?: boolean;
9
+ }
@@ -1,2 +1,3 @@
1
1
  export type Shape = 'disc' | 'horizontal-bar' | 'vertical-bar';
2
2
  export type Status = 'info' | 'success' | 'warning' | 'error' | 'unknown' | 'none';
3
+ export type Type = 'active' | 'inactive';
@@ -405,6 +405,7 @@ $image-medium-box-width: 48px;
405
405
 
406
406
  &-action-menu {
407
407
  margin-left: 8px;
408
+ margin-right: -8px;
408
409
  }
409
410
  }
410
411
 
@@ -17,8 +17,20 @@
17
17
  <template>
18
18
  <div
19
19
  item-card-action
20
+ class="rc-item-card-action"
20
21
  data-testid="rc-item-card-action"
21
22
  >
22
23
  <slot />
23
24
  </div>
24
25
  </template>
26
+
27
+ <style lang="scss">
28
+ .rc-item-card-action {
29
+ .v-popper {
30
+ .icon-actions {
31
+ color: var(--body-text);
32
+ font-size: 19px;
33
+ }
34
+ }
35
+ }
36
+ </style>
@@ -296,4 +296,67 @@ describe('catalog', () => {
296
296
  expect(result).toHaveLength(0);
297
297
  });
298
298
  });
299
+
300
+ describe('getters', () => {
301
+ describe('version', () => {
302
+ it('should find a version from a chart, respecting the showDeprecated flag for charts', () => {
303
+ // A regular chart with some versions
304
+ const regularChart = {
305
+ repoType: 'cluster',
306
+ repoName: 'rancher-charts',
307
+ chartName: 'regular-chart',
308
+ deprecated: false,
309
+ versions: [{ version: '1.2.3' }, { version: '1.2.4' }]
310
+ };
311
+ // A deprecated chart with some versions
312
+ const deprecatedChart = {
313
+ repoType: 'cluster',
314
+ repoName: 'rancher-charts',
315
+ chartName: 'deprecated-chart',
316
+ deprecated: true,
317
+ versions: [{ version: '2.0.0' }, { version: '2.1.0' }]
318
+ };
319
+
320
+ const allCharts = [regularChart, deprecatedChart];
321
+ const state = {};
322
+ const localGetters = {
323
+ charts: allCharts,
324
+ chart: (args: any) => getters.chart(state, { charts: allCharts })(args)
325
+ };
326
+
327
+ // Scenario 1: Get a version from a regular chart
328
+ const result1 = getters.version(state, localGetters)({
329
+ repoType: 'cluster',
330
+ repoName: 'rancher-charts',
331
+ chartName: 'regular-chart',
332
+ versionName: '1.2.3',
333
+ showDeprecated: false
334
+ });
335
+
336
+ expect(result1).toStrictEqual({ version: '1.2.3' });
337
+
338
+ // Scenario 2: Get a version from a deprecated chart
339
+ const result2 = getters.version(state, localGetters)({
340
+ repoType: 'cluster',
341
+ repoName: 'rancher-charts',
342
+ chartName: 'deprecated-chart',
343
+ versionName: '2.0.0',
344
+ showDeprecated: true
345
+ });
346
+
347
+ expect(result2).toStrictEqual({ version: '2.0.0' });
348
+
349
+ // Scenario 3: Try to get a version from a deprecated chart without the flag should fail
350
+ const result3 = getters.version(state, localGetters)({
351
+ repoType: 'cluster',
352
+ repoName: 'rancher-charts',
353
+ chartName: 'deprecated-chart',
354
+ versionName: '2.0.0',
355
+ showDeprecated: false
356
+ });
357
+
358
+ expect(result3).toBeNull();
359
+ });
360
+ });
361
+ });
299
362
  });
package/store/catalog.js CHANGED
@@ -237,10 +237,10 @@ export const getters = {
237
237
 
238
238
  version(state, getters) {
239
239
  return ({
240
- repoType, repoName, chartName, versionName
240
+ repoType, repoName, chartName, versionName, showDeprecated
241
241
  }) => {
242
242
  const chart = getters['chart']({
243
- repoType, repoName, chartName
243
+ repoType, repoName, chartName, showDeprecated
244
244
  });
245
245
 
246
246
  if ( !chart ) {
package/store/type-map.js CHANGED
@@ -103,8 +103,6 @@
103
103
  // depaginate: undefined -- Use this to depaginate requests for this type
104
104
  // resourceEditMasthead: true -- Show the Masthead in the edit resource component
105
105
  // customRoute: undefined,
106
- // hasGraph: undefined -- If true, render ForceDirectedTreeChart graph (ATTENTION: option graphConfig is needed also!!!)
107
- // graphConfig: undefined -- Use this to pass along the graph configuration
108
106
  // notFilterNamespace: undefined -- Define namespaces that do not need to be filtered
109
107
  // localOnly: False -- Hide this type from the nav/search bar on downstream clusters
110
108
  // custom: any - Custom options for a given type
@@ -208,7 +206,6 @@ export const SPOOFED_PREFIX = '__[[spoofed]]__';
208
206
  export const SPOOFED_API_PREFIX = '__[[spoofedapi]]__';
209
207
 
210
208
  const instanceMethods = {};
211
- const graphConfigMap = {};
212
209
 
213
210
  export const IF_HAVE = {
214
211
  V2_MONITORING: 'v2-monitoring',
@@ -291,10 +288,6 @@ export function DSL(store, product, module = 'type-map') {
291
288
  },
292
289
 
293
290
  configureType(match, options) {
294
- if (options.graphConfig) {
295
- graphConfigMap[match] = options.graphConfig;
296
- delete options.graphConfig;
297
- }
298
291
  store.commit(`${ module }/configureType`, { ...options, match });
299
292
  },
300
293
 
@@ -1178,14 +1171,9 @@ export const getters = {
1178
1171
  };
1179
1172
  },
1180
1173
 
1181
- hasGraph(state, getters) {
1182
- return (resource) => {
1183
- const typeOptions = getters['optionsFor'](resource);
1184
-
1185
- if (typeOptions && typeOptions.hasGraph) {
1186
- return graphConfigMap[resource];
1187
- }
1188
-
1174
+ // This has to be left in to support extensions which use shell version 3.0.5-rc.8 or earlier, this extensions have a version of ResourceDetail/index.vue which still invokes this method.
1175
+ hasGraph() {
1176
+ return () => {
1189
1177
  return null;
1190
1178
  };
1191
1179
  },