@rancher/shell 3.0.5-rc.8 → 3.0.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 (199) 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 +147 -19
  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/PodSecurityAdmission.vue +2 -0
  16. package/components/PromptModal.vue +1 -1
  17. package/components/Resource/Detail/Card/__tests__/StateCard.test.ts +1 -0
  18. package/components/Resource/Detail/CopyToClipboard.vue +78 -0
  19. package/components/Resource/Detail/FetchLoader/__tests__/composables.test.ts +69 -0
  20. package/components/Resource/Detail/FetchLoader/composables.ts +27 -0
  21. package/components/Resource/Detail/Metadata/Annotations/__tests__/index.test.ts +1 -1
  22. package/components/Resource/Detail/Metadata/Annotations/index.vue +1 -1
  23. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/identifying-fields.test.ts +13 -61
  24. package/components/Resource/Detail/Metadata/IdentifyingInformation/__tests__/index.test.ts +33 -6
  25. package/components/Resource/Detail/Metadata/IdentifyingInformation/identifying-fields.ts +24 -38
  26. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +25 -5
  27. package/components/Resource/Detail/Metadata/KeyValue.vue +12 -23
  28. package/components/Resource/Detail/Metadata/KeyValueRow.vue +144 -0
  29. package/components/Resource/Detail/Metadata/Labels/__tests__/index.test.ts +1 -0
  30. package/components/Resource/Detail/Metadata/Labels/index.vue +1 -0
  31. package/components/Resource/Detail/Metadata/__tests__/KeyValue.test.ts +30 -32
  32. package/components/Resource/Detail/Metadata/__tests__/KeyValueRow.test.ts +108 -0
  33. package/components/Resource/Detail/Metadata/__tests__/composables.test.ts +0 -3
  34. package/components/Resource/Detail/Metadata/__tests__/index.test.ts +12 -5
  35. package/components/Resource/Detail/Metadata/composables.ts +1 -4
  36. package/components/Resource/Detail/Metadata/index.vue +1 -0
  37. package/components/Resource/Detail/Preview/Content.vue +63 -0
  38. package/components/Resource/Detail/Preview/Preview.vue +128 -0
  39. package/components/Resource/Detail/Preview/__tests__/Content.spec.ts +71 -0
  40. package/components/Resource/Detail/Preview/__tests__/Preview.spec.ts +121 -0
  41. package/components/Resource/Detail/ResourcePopover/ResourcePopoverCard.vue +141 -0
  42. package/components/Resource/Detail/ResourcePopover/__tests__/ResourcePopoverCard.test.ts +136 -0
  43. package/components/Resource/Detail/ResourcePopover/__tests__/index.test.ts +245 -0
  44. package/components/Resource/Detail/ResourcePopover/index.vue +226 -0
  45. package/components/Resource/Detail/SpacedRow.vue +1 -0
  46. package/components/Resource/Detail/TitleBar/__tests__/composables.test.ts +0 -5
  47. package/components/Resource/Detail/TitleBar/__tests__/index.test.ts +1 -1
  48. package/components/Resource/Detail/TitleBar/composables.ts +1 -3
  49. package/components/Resource/Detail/TitleBar/index.vue +2 -29
  50. package/components/Resource/Detail/ViewOptions/composable.ts +9 -0
  51. package/components/Resource/Detail/ViewOptions/index.vue +41 -0
  52. package/components/Resource/Detail/__tests__/CopyToClipboard.spec.ts +82 -0
  53. package/components/ResourceDetail/Masthead/legacy.vue +0 -19
  54. package/components/ResourceDetail/index.vue +1 -26
  55. package/components/ResourceTable.vue +24 -0
  56. package/components/SortableTable/index.vue +7 -1
  57. package/components/SortableTable/paging.js +3 -0
  58. package/components/Tabbed/Tab.vue +43 -1
  59. package/components/Tabbed/index.vue +3 -1
  60. package/components/__tests__/Cron/CronExpressionEditor.test.ts +151 -0
  61. package/components/__tests__/Cron/CronExpressionEditorModal.test.ts +81 -0
  62. package/components/auth/login/saml.vue +86 -0
  63. package/components/form/LabeledSelect.vue +8 -8
  64. package/components/form/ProjectMemberEditor.vue +2 -0
  65. package/components/form/ResourceTabs/composable.ts +54 -0
  66. package/components/form/ResourceTabs/index.vue +10 -7
  67. package/components/form/Select.vue +13 -10
  68. package/components/form/__tests__/LabeledSelect.test.ts +133 -0
  69. package/components/form/__tests__/Select.test.ts +134 -0
  70. package/components/nav/Header.vue +6 -5
  71. package/composables/useExtensionManager.ts +17 -0
  72. package/config/home-links.js +12 -0
  73. package/config/labels-annotations.js +0 -1
  74. package/config/page-actions.js +0 -1
  75. package/config/product/explorer.js +3 -1
  76. package/config/product/fleet.js +2 -7
  77. package/config/product/manager.js +0 -5
  78. package/config/query-params.js +1 -0
  79. package/config/router/navigation-guards/clusters.js +2 -1
  80. package/config/router/navigation-guards/products.js +1 -1
  81. package/config/store.js +2 -0
  82. package/core/extension-manager-impl.js +518 -0
  83. package/core/plugins.js +35 -468
  84. package/core/types.ts +8 -2
  85. package/detail/__tests__/autoscaling.horizontalpodautoscaler.test.ts +1 -0
  86. package/detail/catalog.cattle.io.app.vue +7 -4
  87. package/detail/fleet.cattle.io.bundle.vue +1 -5
  88. package/detail/fleet.cattle.io.cluster.vue +3 -2
  89. package/detail/fleet.cattle.io.gitrepo.vue +76 -49
  90. package/detail/fleet.cattle.io.helmop.vue +78 -49
  91. package/dialog/AddonConfigConfirmationDialog.vue +1 -1
  92. package/dialog/GenericPrompt.vue +1 -1
  93. package/dialog/ImportDialog.vue +9 -2
  94. package/dialog/InstallExtensionDialog.vue +18 -10
  95. package/dialog/SloDialog.vue +1 -1
  96. package/edit/__tests__/fleet.cattle.io.gitrepo.test.ts +2 -1
  97. package/edit/__tests__/resources.cattle.io.restore.test.ts +106 -0
  98. package/edit/auth/oidc.vue +106 -6
  99. package/edit/auth/saml.vue +5 -5
  100. package/edit/cloudcredential.vue +31 -17
  101. package/edit/constraints.gatekeeper.sh.constraint/index.vue +10 -2
  102. package/edit/fleet.cattle.io.cluster.vue +19 -0
  103. package/edit/fleet.cattle.io.gitrepo.vue +23 -16
  104. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +12 -11
  105. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +11 -1
  106. package/edit/provisioning.cattle.io.cluster/index.vue +14 -19
  107. package/edit/provisioning.cattle.io.cluster/rke2.vue +11 -3
  108. package/edit/provisioning.cattle.io.cluster/tabs/AddOnAdditionalManifest.vue +1 -0
  109. package/edit/provisioning.cattle.io.cluster/tabs/AddOnConfig.vue +1 -0
  110. package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +1 -0
  111. package/edit/provisioning.cattle.io.cluster/tabs/etcd/S3Config.vue +1 -0
  112. package/edit/provisioning.cattle.io.cluster/tabs/registries/index.vue +2 -0
  113. package/edit/provisioning.cattle.io.cluster/tabs/upgrade/DrainOptions.vue +6 -0
  114. package/edit/resources.cattle.io.restore.vue +5 -8
  115. package/initialize/install-plugins.js +1 -3
  116. package/list/__tests__/workload.test.ts +1 -0
  117. package/list/workload.vue +8 -1
  118. package/machine-config/components/GCEImage.vue +6 -5
  119. package/machine-config/google.vue +11 -6
  120. package/mixins/__tests__/auth-config.test.ts +4 -6
  121. package/mixins/__tests__/chart.test.ts +139 -1
  122. package/mixins/auth-config.js +33 -10
  123. package/mixins/chart.js +58 -18
  124. package/models/__tests__/namespace.test.ts +69 -0
  125. package/models/apps.statefulset.js +8 -10
  126. package/models/chart.js +5 -1
  127. package/models/fleet-application.js +16 -46
  128. package/models/fleet.cattle.io.bundle.js +1 -38
  129. package/models/fleet.cattle.io.gitrepo.js +4 -0
  130. package/models/fleet.cattle.io.helmop.js +4 -0
  131. package/models/management.cattle.io.cluster.js +1 -1
  132. package/models/management.cattle.io.project.js +12 -0
  133. package/models/namespace.js +30 -0
  134. package/models/workload.js +4 -1
  135. package/package.json +10 -10
  136. package/pages/auth/login.vue +8 -3
  137. package/pages/auth/logout.vue +6 -5
  138. package/pages/c/_cluster/apps/charts/AppChartCardFooter.vue +26 -11
  139. package/pages/c/_cluster/apps/charts/chart.vue +29 -20
  140. package/pages/c/_cluster/apps/charts/index.vue +1 -0
  141. package/pages/c/_cluster/apps/charts/install.vue +6 -5
  142. package/pages/c/_cluster/explorer/tools/__tests__/index.test.ts +102 -12
  143. package/pages/c/_cluster/explorer/tools/index.vue +145 -254
  144. package/pages/c/_cluster/manager/cloudCredential/index.vue +18 -1
  145. package/pages/c/_cluster/manager/drivers/kontainerDriver/index.vue +12 -2
  146. package/pages/c/_cluster/uiplugins/PluginInfoPanel.vue +1 -1
  147. package/pages/c/_cluster/uiplugins/__tests__/index.spec.ts +318 -0
  148. package/pages/c/_cluster/uiplugins/index.vue +221 -363
  149. package/pages/home.vue +1 -9
  150. package/plugins/axios.js +3 -2
  151. package/plugins/dashboard-store/resource-class.js +49 -0
  152. package/plugins/ember-cookie.js +7 -3
  153. package/plugins/steve/subscribe.js +4 -2
  154. package/public/index.html +2 -1
  155. package/rancher-components/Card/Card.vue +1 -1
  156. package/rancher-components/Form/Checkbox/Checkbox.vue +1 -1
  157. package/rancher-components/Form/Radio/RadioButton.vue +1 -1
  158. package/rancher-components/Form/Radio/RadioGroup.vue +1 -1
  159. package/rancher-components/LabeledTooltip/LabeledTooltip.vue +1 -11
  160. package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.test.ts +53 -0
  161. package/rancher-components/Pill/RcCounterBadge/RcCounterBadge.vue +65 -0
  162. package/rancher-components/Pill/RcCounterBadge/index.ts +1 -0
  163. package/rancher-components/Pill/RcCounterBadge/types.ts +7 -0
  164. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +1 -1
  165. package/rancher-components/Pill/RcStatusBadge/index.ts +1 -1
  166. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +3 -3
  167. package/rancher-components/Pill/RcStatusIndicator/types.ts +1 -1
  168. package/rancher-components/Pill/RcTag/RcTag.test.ts +64 -0
  169. package/rancher-components/Pill/RcTag/RcTag.vue +94 -0
  170. package/rancher-components/Pill/RcTag/index.ts +1 -0
  171. package/rancher-components/Pill/RcTag/types.ts +9 -0
  172. package/rancher-components/Pill/types.ts +1 -0
  173. package/rancher-components/RcItemCard/RcItemCard.vue +1 -0
  174. package/rancher-components/RcItemCard/RcItemCardAction.vue +12 -0
  175. package/scripts/test-plugins-build.sh +0 -1
  176. package/store/__tests__/catalog.test.ts +63 -0
  177. package/store/__tests__/cookies.test.ts +72 -0
  178. package/store/auth.js +33 -10
  179. package/store/catalog.js +2 -2
  180. package/store/cookies.ts +30 -0
  181. package/store/prefs.js +10 -5
  182. package/store/type-map.js +3 -15
  183. package/types/extension-manager.ts +26 -0
  184. package/types/shell/index.d.ts +123 -27
  185. package/utils/__tests__/product.test.ts +129 -0
  186. package/utils/__tests__/resource.test.ts +87 -0
  187. package/utils/alertmanagerconfig.js +2 -2
  188. package/utils/auth.js +4 -77
  189. package/utils/product.ts +39 -0
  190. package/utils/resource.ts +35 -0
  191. package/utils/select.js +0 -24
  192. package/utils/validators/formRules/__tests__/index.test.ts +3 -0
  193. package/utils/validators/formRules/index.ts +2 -1
  194. package/vue.config.js +1 -1
  195. package/components/Resource/Detail/Metadata/Rectangle.vue +0 -34
  196. package/components/Resource/Detail/Metadata/__tests__/Rectangle.test.ts +0 -24
  197. package/components/ResourceDetail/Masthead/__tests__/legacy.test.ts +0 -65
  198. package/utils/cookie-universal.js +0 -10
  199. /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;
package/plugins/axios.js CHANGED
@@ -2,13 +2,14 @@ import https from 'https';
2
2
  import { CSRF } from '@shell/config/cookies';
3
3
 
4
4
  export default function({
5
- $axios, $cookies, isDev, req
5
+ $axios, store, isDev, req
6
6
  }) {
7
7
  $axios.defaults.headers.common['Accept'] = 'application/json';
8
8
  $axios.defaults.withCredentials = true;
9
9
 
10
10
  $axios.onRequest((config) => {
11
- const csrf = $cookies.get(CSRF, { parseJSON: false });
11
+ const options = { parseJSON: false };
12
+ const csrf = store.getters['cookies/get']({ key: CSRF, options });
12
13
 
13
14
  if ( csrf ) {
14
15
  config.headers['x-api-csrf'] = csrf;
@@ -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
  }
@@ -1,13 +1,17 @@
1
1
  import { REDIRECTED } from '@shell/config/cookies';
2
2
 
3
- export default function({ $cookies }) {
3
+ export default function({ store }) {
4
4
  // This tells Ember not to redirect back to us once you've already been to dashboard once.
5
5
  // TODO: Remove this once the ember portion of the app is no longer needed
6
- if ( !$cookies.get(REDIRECTED) ) {
7
- $cookies.set(REDIRECTED, 'true', {
6
+ if ( !store.getters['cookies/get']({ key: REDIRECTED })) {
7
+ const options = {
8
8
  path: '/',
9
9
  sameSite: true,
10
10
  secure: true,
11
+ };
12
+
13
+ store.commit('cookies/set', {
14
+ key: REDIRECTED, value: 'true', options
11
15
  });
12
16
  }
13
17
  }
@@ -369,13 +369,15 @@ const sharedActions = {
369
369
  if (!this.$workers[getters.storeName]) {
370
370
  await createWorker(this, ctx);
371
371
  }
372
+ const options = { parseJSON: false };
373
+ const csrf = rootGetters['cookies/get']({ key: CSRF, options });
372
374
 
373
375
  // if the worker is in advanced mode then it'll contain it's own socket which it calls a 'watcher'
374
376
  this.$workers[getters.storeName].postMessage({
375
377
  createWatcher: {
376
378
  metadata,
377
- url: `${ state.config.baseUrl }/subscribe`,
378
- csrf: this.$cookies.get(CSRF, { parseJSON: false }),
379
+ url: `${ state.config.baseUrl }/subscribe`,
380
+ csrf,
379
381
  maxTries
380
382
  }
381
383
  });
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>
@@ -239,7 +239,6 @@ function clone_repo_test_extension_build() {
239
239
  clone_repo_test_extension_build "rancher" "kubewarden-ui" "kubewarden"
240
240
  clone_repo_test_extension_build "rancher" "elemental-ui" "elemental"
241
241
  clone_repo_test_extension_build "neuvector" "manager-ext" "neuvector-ui-ext"
242
- clone_repo_test_extension_build "rancher" "capi-ui-extension" "capi"
243
242
  clone_repo_test_extension_build "StackVista" "rancher-extension-stackstate" "observability"
244
243
  clone_repo_test_extension_build "harvester" "harvester-ui-extension" "harvester"
245
244