@rancher/shell 3.0.8-rc.8 → 3.0.8-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 (142) hide show
  1. package/assets/brand/suse/dark/rancher-logo.svg +1 -64
  2. package/assets/translations/en-us.yaml +9 -1
  3. package/components/BackLink.vue +8 -0
  4. package/components/BannerGraphic.vue +1 -5
  5. package/components/BrandImage.vue +17 -6
  6. package/components/Cron/CronExpressionEditor.vue +1 -1
  7. package/components/Cron/CronExpressionEditorModal.vue +1 -1
  8. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +1 -0
  9. package/components/Drawer/ResourceDetailDrawer/index.vue +1 -0
  10. package/components/Drawer/ResourceDetailDrawer/types.ts +2 -1
  11. package/components/Questions/__tests__/index.test.ts +159 -0
  12. package/components/Resource/Detail/Metadata/Annotations/index.vue +2 -2
  13. package/components/Resource/Detail/Metadata/Labels/index.vue +2 -2
  14. package/components/Resource/Detail/Metadata/index.vue +3 -3
  15. package/components/Resource/Detail/composables.ts +2 -2
  16. package/components/Tabbed/__tests__/index.test.ts +86 -0
  17. package/components/auth/SelectPrincipal.vue +24 -6
  18. package/components/auth/__tests__/SelectPrincipal.test.ts +119 -0
  19. package/components/formatter/InternalExternalIP.vue +4 -1
  20. package/components/formatter/__tests__/InternalExternalIP.test.ts +1 -1
  21. package/components/templates/standalone.vue +1 -1
  22. package/composables/useI18n.ts +10 -1
  23. package/config/__test__/uiplugins.test.ts +309 -0
  24. package/config/labels-annotations.js +1 -0
  25. package/config/product/explorer.js +3 -1
  26. package/config/router/routes.js +6 -2
  27. package/config/types.js +7 -0
  28. package/config/uiplugins.js +46 -2
  29. package/core/__test__/extension-manager-impl.test.js +236 -0
  30. package/core/extension-manager-impl.js +23 -6
  31. package/core/types-provisioning.ts +1 -1
  32. package/detail/provisioning.cattle.io.cluster.vue +1 -0
  33. package/dialog/DeveloperLoadExtensionDialog.vue +12 -3
  34. package/dialog/RollbackWorkloadDialog.vue +2 -5
  35. package/edit/__tests__/fleet.cattle.io.helmop.test.ts +2 -2
  36. package/edit/autoscaling.horizontalpodautoscaler/index.vue +1 -0
  37. package/edit/configmap.vue +1 -0
  38. package/edit/constraints.gatekeeper.sh.constraint/index.vue +1 -0
  39. package/edit/fleet.cattle.io.helmop.vue +6 -6
  40. package/edit/helm.cattle.io.projecthelmchart.vue +1 -0
  41. package/edit/k8s.cni.cncf.io.networkattachmentdefinition.vue +1 -0
  42. package/edit/logging-flow/index.vue +1 -0
  43. package/edit/logging.banzaicloud.io.output/index.vue +1 -0
  44. package/edit/management.cattle.io.fleetworkspace.vue +1 -1
  45. package/edit/management.cattle.io.project.vue +1 -0
  46. package/edit/monitoring.coreos.com.alertmanagerconfig/index.vue +4 -1
  47. package/edit/monitoring.coreos.com.alertmanagerconfig/receiverConfig.vue +2 -1
  48. package/edit/monitoring.coreos.com.prometheusrule/index.vue +1 -0
  49. package/edit/monitoring.coreos.com.receiver/index.vue +2 -1
  50. package/edit/monitoring.coreos.com.route.vue +1 -1
  51. package/edit/namespace.vue +1 -0
  52. package/edit/networking.istio.io.destinationrule/index.vue +1 -0
  53. package/edit/networking.k8s.io.ingress/index.vue +1 -0
  54. package/edit/networking.k8s.io.networkpolicy/PolicyRules.vue +1 -0
  55. package/edit/networking.k8s.io.networkpolicy/index.vue +1 -0
  56. package/edit/node.vue +1 -0
  57. package/edit/persistentvolume/index.vue +27 -22
  58. package/edit/persistentvolume/plugins/awsElasticBlockStore.vue +13 -14
  59. package/edit/persistentvolume/plugins/azureDisk.vue +49 -48
  60. package/edit/persistentvolume/plugins/azureFile.vue +15 -14
  61. package/edit/persistentvolume/plugins/cephfs.vue +15 -14
  62. package/edit/persistentvolume/plugins/cinder.vue +15 -14
  63. package/edit/persistentvolume/plugins/csi.vue +18 -16
  64. package/edit/persistentvolume/plugins/fc.vue +13 -14
  65. package/edit/persistentvolume/plugins/flexVolume.vue +15 -14
  66. package/edit/persistentvolume/plugins/flocker.vue +1 -3
  67. package/edit/persistentvolume/plugins/gcePersistentDisk.vue +13 -14
  68. package/edit/persistentvolume/plugins/glusterfs.vue +15 -14
  69. package/edit/persistentvolume/plugins/hostPath.vue +40 -39
  70. package/edit/persistentvolume/plugins/iscsi.vue +13 -14
  71. package/edit/persistentvolume/plugins/local.vue +1 -3
  72. package/edit/persistentvolume/plugins/longhorn.vue +23 -22
  73. package/edit/persistentvolume/plugins/nfs.vue +15 -14
  74. package/edit/persistentvolume/plugins/photonPersistentDisk.vue +1 -14
  75. package/edit/persistentvolume/plugins/portworxVolume.vue +15 -14
  76. package/edit/persistentvolume/plugins/quobyte.vue +15 -14
  77. package/edit/persistentvolume/plugins/rbd.vue +15 -14
  78. package/edit/persistentvolume/plugins/scaleIO.vue +15 -14
  79. package/edit/persistentvolume/plugins/storageos.vue +15 -14
  80. package/edit/persistentvolume/plugins/vsphereVolume.vue +1 -3
  81. package/edit/provisioning.cattle.io.cluster/rke2.vue +1 -0
  82. package/edit/secret/index.vue +1 -1
  83. package/edit/service.vue +1 -0
  84. package/edit/serviceaccount.vue +1 -0
  85. package/edit/storage.k8s.io.storageclass/index.vue +1 -0
  86. package/edit/workload/index.vue +2 -1
  87. package/edit/workload/mixins/workload.js +1 -1
  88. package/initialize/App.vue +4 -4
  89. package/initialize/install-plugins.js +17 -2
  90. package/mixins/__tests__/brand.spec.ts +2 -2
  91. package/mixins/brand.js +1 -7
  92. package/mixins/create-edit-view/index.js +5 -0
  93. package/models/__tests__/provisioning.cattle.io.cluster.test.ts +112 -5
  94. package/models/management.cattle.io.cluster.js +21 -3
  95. package/models/provisioning.cattle.io.cluster.js +21 -9
  96. package/package.json +5 -4
  97. package/pages/auth/login.vue +1 -3
  98. package/pages/c/_cluster/apps/charts/__tests__/chart.test.ts +135 -0
  99. package/pages/c/_cluster/apps/charts/chart.vue +33 -15
  100. package/pages/c/_cluster/explorer/index.vue +8 -6
  101. package/pages/c/_cluster/manager/hostedprovider/index.vue +12 -6
  102. package/pages/c/_cluster/settings/brand.vue +1 -1
  103. package/pages/c/_cluster/uiplugins/__tests__/index.test.ts +7 -0
  104. package/pages/c/_cluster/uiplugins/catalogs.vue +147 -0
  105. package/pages/c/_cluster/uiplugins/index.vue +126 -184
  106. package/plugins/dashboard-client-init.js +3 -0
  107. package/plugins/dashboard-store/getters.js +18 -1
  108. package/plugins/dashboard-store/resource-class.js +3 -2
  109. package/plugins/i18n.js +8 -0
  110. package/plugins/steve/__tests__/steve-pagination-utils.test.ts +333 -0
  111. package/plugins/steve/steve-pagination-utils.ts +39 -20
  112. package/rancher-components/Pill/RcStatusBadge/RcStatusBadge.vue +6 -42
  113. package/rancher-components/Pill/RcStatusBadge/index.ts +0 -1
  114. package/rancher-components/Pill/RcStatusBadge/types.ts +1 -1
  115. package/rancher-components/Pill/RcStatusIndicator/RcStatusIndicator.vue +5 -28
  116. package/rancher-components/Pill/RcStatusIndicator/types.ts +2 -1
  117. package/rancher-components/Pill/types.ts +0 -1
  118. package/rancher-components/RcIcon/RcIcon.test.ts +51 -0
  119. package/rancher-components/RcIcon/RcIcon.vue +46 -0
  120. package/rancher-components/RcIcon/index.ts +1 -0
  121. package/rancher-components/RcIcon/types.ts +160 -0
  122. package/rancher-components/utils/status.test.ts +67 -0
  123. package/rancher-components/utils/status.ts +77 -0
  124. package/scripts/typegen.sh +1 -0
  125. package/store/action-menu.js +8 -0
  126. package/store/auth.js +3 -3
  127. package/store/catalog.js +6 -0
  128. package/store/index.js +4 -4
  129. package/store/prefs.js +4 -5
  130. package/store/wm.ts +4 -4
  131. package/types/shell/index.d.ts +38 -2
  132. package/types/store/__tests__/pagination.types.spec.ts +137 -0
  133. package/types/store/pagination.types.ts +157 -9
  134. package/utils/__tests__/provider.test.ts +98 -0
  135. package/utils/__tests__/selector-typed.test.ts +263 -0
  136. package/utils/color.js +1 -1
  137. package/utils/dynamic-content/__tests__/info.test.ts +6 -0
  138. package/utils/dynamic-content/info.ts +43 -0
  139. package/utils/favicon.js +4 -4
  140. package/utils/provider.ts +14 -0
  141. package/utils/selector-typed.ts +6 -2
  142. package/plugins/nuxt-client-init.js +0 -3
@@ -0,0 +1,160 @@
1
+ import { Status } from '../utils/status';
2
+
3
+ export const RcIconType = {
4
+ actions: 'icon-actions',
5
+ ai: 'icon-ai',
6
+ 'alert-alt': 'icon-alert-alt',
7
+ alert: 'icon-alert',
8
+ anchor: 'icon-anchor',
9
+ apple: 'icon-apple',
10
+ application: 'icon-application',
11
+ apps: 'icon-apps',
12
+ archive: 'icon-archive',
13
+ 'backup-restore': 'icon-backup-restore',
14
+ backup: 'icon-backup',
15
+ 'brush-icon': 'icon-brush-icon',
16
+ 'category-alt': 'icon-category-alt',
17
+ checkmark: 'icon-checkmark',
18
+ 'chevron-beginning': 'icon-chevron-beginning',
19
+ 'chevron-down': 'icon-chevron-down',
20
+ 'chevron-end': 'icon-chevron-end',
21
+ 'chevron-left': 'icon-chevron-left',
22
+ 'chevron-right': 'icon-chevron-right',
23
+ 'chevron-up': 'icon-chevron-up',
24
+ 'circle-plus': 'icon-circle-plus',
25
+ cis: 'icon-cis',
26
+ close: 'icon-close',
27
+ 'cluster-management': 'icon-cluster-management',
28
+ cluster: 'icon-cluster',
29
+ code: 'icon-code',
30
+ comment: 'icon-comment',
31
+ commit: 'icon-commit',
32
+ compass: 'icon-compass',
33
+ 'confirmation-alt': 'icon-confirmation-alt',
34
+ copy: 'icon-copy',
35
+ dashboard: 'icon-dashboard',
36
+ dock: 'icon-dock',
37
+ docker: 'icon-docker',
38
+ document: 'icon-document',
39
+ 'dot-half': 'icon-dot-half',
40
+ 'dot-open': 'icon-dot-open',
41
+ dot: 'icon-dot',
42
+ 'downgrade-alt': 'icon-downgrade-alt',
43
+ download: 'icon-download',
44
+ edit: 'icon-edit',
45
+ elemental: 'icon-elemental',
46
+ endpoints_connected: 'icon-endpoints_connected',
47
+ endpoints_disconnected: 'icon-endpoints_disconnected',
48
+ epinio: 'icon-epinio',
49
+ error: 'icon-error',
50
+ explore: 'icon-explore',
51
+ extension: 'icon-extension',
52
+ 'external-link': 'icon-external-link',
53
+ file: 'icon-file',
54
+ filter_alt: 'icon-filter_alt',
55
+ flask: 'icon-flask',
56
+ fleet: 'icon-fleet',
57
+ folder: 'icon-folder',
58
+ fork: 'icon-fork',
59
+ gatekeeper: 'icon-gatekeeper',
60
+ gear: 'icon-gear',
61
+ gemini: 'icon-gemini',
62
+ git: 'icon-git',
63
+ github: 'icon-github',
64
+ gitlab: 'icon-gitlab',
65
+ globe: 'icon-globe',
66
+ groups: 'icon-groups',
67
+ harvester: 'icon-harvester',
68
+ helm: 'icon-helm',
69
+ hide: 'icon-hide',
70
+ history: 'icon-history',
71
+ home: 'icon-home',
72
+ 'info-circle': 'icon-info-circle',
73
+ info: 'icon-info',
74
+ init_container: 'icon-init_container',
75
+ istio: 'icon-istio',
76
+ keyboard: 'icon-keyboard',
77
+ keyboard_tab: 'icon-keyboard_tab',
78
+ linux: 'icon-linux',
79
+ 'list-flat': 'icon-list-flat',
80
+ 'list-grouped': 'icon-list-grouped',
81
+ lock: 'icon-lock',
82
+ logging: 'icon-logging',
83
+ longhorn: 'icon-longhorn',
84
+ marketplace: 'icon-marketplace',
85
+ menu: 'icon-menu',
86
+ minus: 'icon-minus',
87
+ monitoring: 'icon-monitoring',
88
+ more: 'icon-more',
89
+ namespace: 'icon-namespace',
90
+ notifier: 'icon-notifier',
91
+ 'notify-announcement': 'icon-notify-announcement',
92
+ 'notify-bell': 'icon-notify-bell',
93
+ 'notify-busy': 'icon-notify-busy',
94
+ 'notify-error': 'icon-notify-error',
95
+ 'notify-info': 'icon-notify-info',
96
+ 'notify-tick': 'icon-notify-tick',
97
+ 'notify-warning': 'icon-notify-warning',
98
+ ollama: 'icon-ollama',
99
+ openai: 'icon-openai',
100
+ 'os-management': 'icon-os-management',
101
+ pause: 'icon-pause',
102
+ 'pin-outlined': 'icon-pin-outlined',
103
+ pin: 'icon-pin',
104
+ pipeline: 'icon-pipeline',
105
+ play: 'icon-play',
106
+ plus: 'icon-plus',
107
+ pod_security: 'icon-pod_security',
108
+ print: 'icon-print',
109
+ 'question-mark': 'icon-question-mark',
110
+ 'quick-action': 'icon-quick-action',
111
+ 'rancher-desktop': 'icon-rancher-desktop',
112
+ 'rancher-observability': 'icon-rancher-observability',
113
+ 'refresh-alt': 'icon-refresh-alt',
114
+ refresh: 'icon-refresh',
115
+ 'repository-alt': 'icon-repository-alt',
116
+ repository: 'icon-repository',
117
+ rio: 'icon-rio',
118
+ 'role-binding': 'icon-role-binding',
119
+ search: 'icon-search',
120
+ send: 'icon-send',
121
+ service: 'icon-service',
122
+ show: 'icon-show',
123
+ snapshot: 'icon-snapshot',
124
+ 'sort-down': 'icon-sort-down',
125
+ 'sort-up': 'icon-sort-up',
126
+ sort: 'icon-sort',
127
+ sources: 'icon-sources',
128
+ spinner: 'icon-spinner',
129
+ stackstate: 'icon-stackstate',
130
+ 'star-open': 'icon-star-open',
131
+ star: 'icon-star',
132
+ storage: 'icon-storage',
133
+ 'tag-alt': 'icon-tag-alt',
134
+ terminal: 'icon-terminal',
135
+ 'thinking-process': 'icon-thinking-process',
136
+ trash: 'icon-trash',
137
+ unlock: 'icon-unlock',
138
+ 'upgrade-alt': 'icon-upgrade-alt',
139
+ upload: 'icon-upload',
140
+ 'user-check': 'icon-user-check',
141
+ 'user-xmark': 'icon-user-xmark',
142
+ user: 'icon-user',
143
+ 'version-alt': 'icon-version-alt',
144
+ warning: 'icon-warning',
145
+ windows: 'icon-windows',
146
+ };
147
+
148
+ export const RcIconSize = {
149
+ large: '25px',
150
+ medium: '18px',
151
+ small: '14px',
152
+ none: undefined
153
+ };
154
+
155
+ export interface RcIconProps {
156
+ size: keyof typeof RcIconSize;
157
+ type: keyof typeof RcIconType;
158
+ ariaHidden?: boolean;
159
+ status?: Status | 'inherit';
160
+ }
@@ -0,0 +1,67 @@
1
+
2
+ import { reactive } from 'vue';
3
+ import { wrapIfVar, useStatusColors, Status } from './status';
4
+
5
+ describe('utils: status', () => {
6
+ describe('wrapIfVar', () => {
7
+ it('should wrap a CSS variable', () => {
8
+ const result = wrapIfVar('--rc-info');
9
+
10
+ expect(result).toBe('var(--rc-info)');
11
+ });
12
+
13
+ it('should not wrap a normal color', () => {
14
+ const result = wrapIfVar('red');
15
+
16
+ expect(result).toBe('red');
17
+ });
18
+ });
19
+
20
+ describe('useStatusColors', () => {
21
+ it.each([
22
+ 'info',
23
+ 'success',
24
+ 'warning',
25
+ 'error',
26
+ 'unknown',
27
+ 'none'
28
+ ])('solid: should return the correct colors for status: %p', (status: Status) => {
29
+ const props = reactive({ status });
30
+ const {
31
+ borderColor,
32
+ backgroundColor,
33
+ textColor
34
+ } = useStatusColors(props, 'solid');
35
+
36
+ expect(borderColor.value).toBe(`var(--rc-${ status })`);
37
+ if (status !== 'none') {
38
+ // eslint-disable-next-line jest/no-conditional-expect
39
+ expect(backgroundColor.value).toBe(`var(--rc-${ status })`);
40
+ }
41
+ expect(textColor.value).toBe(`var(--rc-${ status }-secondary)`);
42
+ });
43
+
44
+ it.each([
45
+ 'info',
46
+ 'success',
47
+ 'warning',
48
+ 'error',
49
+ 'unknown',
50
+ 'none'
51
+ ])('outlined: should return the correct colors for status: %p', (status: Status) => {
52
+ const props = reactive({ status });
53
+ const {
54
+ borderColor,
55
+ backgroundColor,
56
+ textColor
57
+ } = useStatusColors(props, 'outlined');
58
+
59
+ expect(borderColor.value).toBe(`var(--rc-${ status }-secondary)`);
60
+ if (status !== 'none') {
61
+ // eslint-disable-next-line jest/no-conditional-expect
62
+ expect(backgroundColor.value).toBe(`var(--rc-${ status }-secondary)`);
63
+ }
64
+ expect(textColor.value).toBe(`var(--rc-${ status })`);
65
+ });
66
+ });
67
+ });
@@ -0,0 +1,77 @@
1
+ import { computed } from 'vue';
2
+
3
+ export const StatusDefinitions = {
4
+ info: {
5
+ primary: '--rc-info',
6
+ secondary: '--rc-info-secondary'
7
+ },
8
+ success: {
9
+ primary: '--rc-success',
10
+ secondary: '--rc-success-secondary'
11
+ },
12
+ warning: {
13
+ primary: '--rc-warning',
14
+ secondary: '--rc-warning-secondary'
15
+ },
16
+ error: {
17
+ primary: '--rc-error',
18
+ secondary: '--rc-error-secondary'
19
+ },
20
+ unknown: {
21
+ primary: '--rc-unknown',
22
+ secondary: '--rc-unknown-secondary'
23
+ },
24
+ none: {
25
+ primary: '--rc-none',
26
+ secondary: '--rc-none-secondary'
27
+ },
28
+ };
29
+
30
+ export type Status = keyof typeof StatusDefinitions;
31
+ export type StatusObject = { status: Status };
32
+ export type Style = 'solid' | 'outlined';
33
+
34
+ export function wrapIfVar(colorVar: string) {
35
+ return colorVar.startsWith('--') ? `var(${ colorVar })` : colorVar;
36
+ }
37
+
38
+ /**
39
+ * A composable to make it easier to use status colors in multiple components
40
+ *
41
+ * @param propsWithStatus The props which contain a `status: Status` property. Ideally I'd prefer to just pass status but doing so either forces the consumer to wrap the values in a Ref or this code is no longer reactive.
42
+ * @param style {@link Style} Will the block of code being using the solid or outlined styling
43
+ * @returns An object containing the relevant style colors
44
+ */
45
+ export function useStatusColors(propsWithStatus: StatusObject, style: Style) {
46
+ const statusColors = computed(() => {
47
+ return StatusDefinitions[propsWithStatus.status];
48
+ });
49
+ const isOutlined = style === 'outlined';
50
+
51
+ const borderColor = computed(() => {
52
+ const colorVar = isOutlined ? statusColors.value.secondary : statusColors.value.primary;
53
+
54
+ return wrapIfVar(colorVar);
55
+ });
56
+
57
+ const backgroundColor = computed(() => {
58
+ if (propsWithStatus.status === 'none') {
59
+ return 'none';
60
+ }
61
+ const colorVar = isOutlined ? statusColors.value.secondary : statusColors.value.primary;
62
+
63
+ return wrapIfVar(colorVar);
64
+ });
65
+
66
+ const textColor = computed(() => {
67
+ const colorVar = isOutlined ? statusColors.value.primary : statusColors.value.secondary;
68
+
69
+ return wrapIfVar(colorVar);
70
+ });
71
+
72
+ return {
73
+ borderColor,
74
+ backgroundColor,
75
+ textColor
76
+ };
77
+ }
@@ -29,6 +29,7 @@ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/prefs.js --declaration --al
29
29
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/store/plugins.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/store > /dev/null
30
30
 
31
31
  # # plugins
32
+ ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/i18n.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/ > /dev/null
32
33
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/dashboard-store/normalize.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/plugins/dashboard-store/ > /dev/null
33
34
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/dashboard-store/resource-class.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/plugins/dashboard-store/ > /dev/null
34
35
  ${BASE_DIR}/node_modules/.bin/tsc ${SHELL_DIR}/plugins/dashboard-store/classify.js --declaration --allowJs --emitDeclarationOnly --outDir ${SHELL_DIR}/tmp/plugins/dashboard-store/ > /dev/null
@@ -111,6 +111,14 @@ export const mutations = {
111
111
  state.modalData = data;
112
112
  },
113
113
 
114
+ updateModalData(state, data) {
115
+ state.modalData = state.modalData || {};
116
+
117
+ data.forEach(({ key, value }) => {
118
+ state.modalData[key] = value;
119
+ });
120
+ },
121
+
114
122
  clearCallbackData(state) {
115
123
  state.performCallbackData = undefined;
116
124
  },
package/store/auth.js CHANGED
@@ -404,18 +404,18 @@ export const actions = {
404
404
  // Unload plugins - we will load again on login
405
405
  await rootState.$plugin.logout();
406
406
 
407
- let logoutAction = 'logout';
407
+ let logoutAction = '';
408
408
  const data = {};
409
409
 
410
410
  // SLO - Single-sign logout - will logout auth provider from all places where it's logged in
411
411
  if (options.slo) {
412
- logoutAction = 'logoutAll';
412
+ logoutAction = '?logoutAll';
413
413
  data.finalRedirectUrl = returnTo({ isSlo: true }, this);
414
414
  }
415
415
 
416
416
  try {
417
417
  const res = await dispatch('rancher/request', {
418
- url: `/v3/tokens?action=${ logoutAction }`,
418
+ url: `/v1/logout${ logoutAction }`,
419
419
  method: 'post',
420
420
  data,
421
421
  headers: { 'Content-Type': 'application/json' },
package/store/catalog.js CHANGED
@@ -504,11 +504,16 @@ function addChart(ctx, map, chart, repo) {
504
504
 
505
505
  if ( !obj ) {
506
506
  if ( ctx ) { }
507
+
508
+ const primeOnly = chart.annotations?.[CATALOG_ANNOTATIONS.PRIME_ONLY] === 'true';
507
509
  const experimental = !!chart.annotations?.[CATALOG_ANNOTATIONS.EXPERIMENTAL];
508
510
  const windowsIncompatible = !(chart.annotations?.[CATALOG_ANNOTATIONS.PERMITTED_OS] || '').includes('windows');
509
511
  const deploysOnWindows = (chart.annotations?.[CATALOG_ANNOTATIONS.DEPLOYED_OS] || '').includes('windows');
510
512
  const tags = [];
511
513
 
514
+ if (primeOnly) {
515
+ tags.push(ctx.rootGetters['i18n/withFallback']('generic.primeOnly'));
516
+ }
512
517
  if (experimental) {
513
518
  tags.push(ctx.rootGetters['i18n/withFallback']('generic.experimental'));
514
519
  }
@@ -542,6 +547,7 @@ function addChart(ctx, map, chart, repo) {
542
547
  keywords: chart.keywords || [],
543
548
  categories: filterCategories(chart.keywords),
544
549
  deprecated: !!chart.deprecated,
550
+ primeOnly,
545
551
  experimental,
546
552
  hidden: !!chart.annotations?.[CATALOG_ANNOTATIONS.HIDDEN],
547
553
  targetNamespace: chart.annotations?.[CATALOG_ANNOTATIONS.NAMESPACE],
package/store/index.js CHANGED
@@ -1251,10 +1251,10 @@ export const actions = {
1251
1251
  }
1252
1252
  },
1253
1253
 
1254
- nuxtClientInit({ dispatch, commit, rootState }, nuxt) {
1255
- commit('setRouter', nuxt.app.router);
1256
- commit('setRoute', nuxt.route);
1257
- commit('setPlugin', nuxt.app.$plugin);
1254
+ dashboardClientInit({ dispatch, commit, rootState }, context) {
1255
+ commit('setRouter', context.app.router);
1256
+ commit('setRoute', context.route);
1257
+ commit('setPlugin', context.app.$plugin);
1258
1258
 
1259
1259
  dispatch('management/rehydrateSubscribe');
1260
1260
  dispatch('cluster/rehydrateSubscribe');
package/store/prefs.js CHANGED
@@ -523,15 +523,14 @@ export const actions = {
523
523
  setBrandStyle({ rootState, rootGetters }, dark = false) {
524
524
  if (rootState.managementReady) {
525
525
  try {
526
- const brandSetting = rootGetters['management/byId'](MANAGEMENT.SETTING, SETTING.BRAND);
526
+ const brandSetting = rootGetters['management/brand'];
527
527
 
528
- if (brandSetting && brandSetting.value && brandSetting.value !== '') {
529
- const brand = brandSetting.value;
530
- const brandMeta = getBrandMeta(brand);
528
+ if (brandSetting !== '') {
529
+ const brandMeta = getBrandMeta(brandSetting);
531
530
  const hasStylesheet = brandMeta.hasStylesheet === 'true';
532
531
 
533
532
  if (hasStylesheet) {
534
- document.body.classList.add(brand);
533
+ document.body.classList.add(brandMeta);
535
534
  } else {
536
535
  // TODO option apply color at runtime
537
536
  }
package/store/wm.ts CHANGED
@@ -80,11 +80,11 @@ export const mutations = {
80
80
  addTab(state: State, tab: Tab) {
81
81
  const existing = state.tabs.find((x) => x.id === tab.id);
82
82
 
83
- if (!existing) {
84
- if (tab.position === undefined) {
85
- tab.position = (window.localStorage.getItem(STORAGE_KEY['pin']) || BOTTOM) as Position;
86
- }
83
+ if (tab.position === undefined || tab.position as string === 'undefined') {
84
+ tab.position = (window.localStorage.getItem(STORAGE_KEY['pin']) || BOTTOM) as Position;
85
+ }
87
86
 
87
+ if (!existing) {
88
88
  if (state.lockedPositions.includes(BOTTOM)) {
89
89
  tab.position = BOTTOM;
90
90
  }
@@ -79,6 +79,7 @@ export namespace CATALOG {
79
79
  let _RANCHER: string;
80
80
  let _PARTNER: string;
81
81
  let _OTHER: string;
82
+ let PRIME_ONLY: string;
82
83
  let EXPERIMENTAL: string;
83
84
  let NAMESPACE: string;
84
85
  let RELEASE_NAME: string;
@@ -2206,6 +2207,12 @@ export namespace MANAGEMENT {
2206
2207
  export let CLUSTER_PROXY_CONFIG: string;
2207
2208
  export let OIDC_CLIENT: string;
2208
2209
  }
2210
+ export namespace BRAND {
2211
+ let SUSE: string;
2212
+ let CSP: string;
2213
+ let FEDERAL: string;
2214
+ let RGS: string;
2215
+ }
2209
2216
  export namespace EXT {
2210
2217
  let USER_ACTIVITY: string;
2211
2218
  }
@@ -2442,6 +2449,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
2442
2449
  type: BooleanConstructor;
2443
2450
  default: any;
2444
2451
  };
2452
+ defaultTab: {
2453
+ type: StringConstructor;
2454
+ default: any;
2455
+ };
2445
2456
  }>, {}, {
2446
2457
  errors: any[];
2447
2458
  }, {
@@ -2499,6 +2510,10 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
2499
2510
  type: BooleanConstructor;
2500
2511
  default: any;
2501
2512
  };
2513
+ defaultTab: {
2514
+ type: StringConstructor;
2515
+ default: any;
2516
+ };
2502
2517
  }>> & Readonly<{
2503
2518
  [x: `on${Capitalize<string>}`]: (...args: any[]) => any;
2504
2519
  }>, {
@@ -2509,6 +2524,7 @@ declare const _default: import("vue").DefineComponent<import("vue").ExtractPropT
2509
2524
  liveValue: Record<string, any>;
2510
2525
  realMode: string;
2511
2526
  useTabbedHash: boolean;
2527
+ defaultTab: string;
2512
2528
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2513
2529
  export default _default;
2514
2530
  }
@@ -3315,7 +3331,7 @@ export default class Resource {
3315
3331
  weight: number;
3316
3332
  divider?: undefined;
3317
3333
  })[];
3318
- showConfiguration(returnFocusSelector: any): void;
3334
+ showConfiguration(returnFocusSelector: any, defaultTab: any): void;
3319
3335
  get _availableActions(): ({
3320
3336
  action: string;
3321
3337
  label: any;
@@ -3633,6 +3649,26 @@ export default class Resource {
3633
3649
  }
3634
3650
  }
3635
3651
 
3652
+ // @shell/plugins/i18n
3653
+
3654
+ declare module '@shell/plugins/i18n' {
3655
+ /**
3656
+ * @param {import('vuex').Store<any>} store
3657
+ * @param {string} key
3658
+ * @param {Record<string, any>} [args]
3659
+ * @param {boolean} [raw]
3660
+ * @param {boolean} [escapehtml]
3661
+ * @returns {string}
3662
+ */
3663
+ export function stringFor(store: import("vuex").Store<any>, key: string, args?: Record<string, any>, raw?: boolean, escapehtml?: boolean): string;
3664
+ export function directiveSsr(vnode: any, binding: any): void;
3665
+ export default i18n;
3666
+ declare namespace i18n {
3667
+ let name: string;
3668
+ function install(vueApp: any, _options: any): void;
3669
+ }
3670
+ }
3671
+
3636
3672
  // @shell/plugins/steve/hybrid-class
3637
3673
 
3638
3674
  declare module '@shell/plugins/steve/hybrid-class' {
@@ -4083,7 +4119,7 @@ export function contrastColor(color: any, contrastOptions?: {
4083
4119
  dark: string;
4084
4120
  light: string;
4085
4121
  }): string;
4086
- export function parseColor(str: any): any;
4122
+ export function parseColor(str: any): import("color").ColorInstance;
4087
4123
  export function textColor(color: any): "black" | "white";
4088
4124
  export function hexToRgb(hex: any): {
4089
4125
  r: number;
@@ -0,0 +1,137 @@
1
+ import { PaginationFilterEquality, PaginationFilterField } from '@shell/types/store/pagination.types';
2
+
3
+ describe('pagination-types', () => {
4
+ describe('class: PaginationFilterField', () => {
5
+ describe('constructor', () => {
6
+ it('should set properties correctly with default values', () => {
7
+ const field = 'testField';
8
+ const value = 'testValue';
9
+ const filterField = new PaginationFilterField({ field, value });
10
+
11
+ expect(filterField.field).toBe(field);
12
+ expect(filterField.value).toBe(value);
13
+ expect(filterField.equals).toBe(true);
14
+ expect(filterField.exact).toBe(true);
15
+ expect(filterField.exists).toBe(false);
16
+ expect(filterField.equality).toBe(PaginationFilterEquality.EQUALS);
17
+ });
18
+
19
+ it('should handle deprecated `equals` and `exact` to set `equality`', () => {
20
+ // equals: true, exact: true
21
+ let ff = new PaginationFilterField({
22
+ field: 'f', value: 'v', equals: true, exact: true
23
+ });
24
+
25
+ expect(ff.equality).toBe(PaginationFilterEquality.EQUALS);
26
+
27
+ // equals: true, exact: false
28
+ ff = new PaginationFilterField({
29
+ field: 'f', value: 'v', equals: true, exact: false
30
+ });
31
+ expect(ff.equality).toBe(PaginationFilterEquality.CONTAINS);
32
+
33
+ // equals: false, exact: true
34
+ ff = new PaginationFilterField({
35
+ field: 'f', value: 'v', equals: false, exact: true
36
+ });
37
+ expect(ff.equality).toBe(PaginationFilterEquality.NOT_EQUALS);
38
+
39
+ // equals: false, exact: false
40
+ ff = new PaginationFilterField({
41
+ field: 'f', value: 'v', equals: false, exact: false
42
+ });
43
+ expect(ff.equality).toBe(PaginationFilterEquality.NOT_CONTAINS);
44
+ });
45
+
46
+ it('should prioritize `equality` over `equals` and `exact`', () => {
47
+ const filterField = new PaginationFilterField({
48
+ field: 'f',
49
+ value: 'v',
50
+ equals: false,
51
+ exact: false,
52
+ equality: PaginationFilterEquality.GREATER_THAN
53
+ });
54
+
55
+ expect(filterField.equality).toBe(PaginationFilterEquality.GREATER_THAN);
56
+ });
57
+
58
+ it('should throw an error if no equality can be determined', () => {
59
+ expect(() => new PaginationFilterField({
60
+ field: 'f',
61
+ value: 'v',
62
+ equals: null,
63
+ exact: null
64
+ })).toThrow('A pagination filter must have either equals or equality set');
65
+ });
66
+
67
+ it('should set `exists` property', () => {
68
+ const filterField = new PaginationFilterField({ field: 'f', exists: true });
69
+
70
+ expect(filterField.exists).toBe(true);
71
+ });
72
+ });
73
+
74
+ describe('safeEquality', () => {
75
+ it('should return EQUALS for equals=true, exact=true', () => {
76
+ const equality = PaginationFilterField.safeEquality({ equals: true, exact: true });
77
+
78
+ expect(equality).toBe(PaginationFilterEquality.EQUALS);
79
+ });
80
+
81
+ it('should return CONTAINS for equals=true, exact=false', () => {
82
+ const equality = PaginationFilterField.safeEquality({ equals: true, exact: false });
83
+
84
+ expect(equality).toBe(PaginationFilterEquality.CONTAINS);
85
+ });
86
+
87
+ it('should return NOT_EQUALS for equals=false, exact=true', () => {
88
+ const equality = PaginationFilterField.safeEquality({ equals: false, exact: true });
89
+
90
+ expect(equality).toBe(PaginationFilterEquality.NOT_EQUALS);
91
+ });
92
+
93
+ it('should return NOT_CONTAINS for equals=false, exact=false', () => {
94
+ const equality = PaginationFilterField.safeEquality({ equals: false, exact: false });
95
+
96
+ expect(equality).toBe(PaginationFilterEquality.NOT_CONTAINS);
97
+ });
98
+
99
+ it('should return equality if it is provided', () => {
100
+ const equality = PaginationFilterField.safeEquality({ equality: PaginationFilterEquality.IN });
101
+
102
+ expect(equality).toBe(PaginationFilterEquality.IN);
103
+ });
104
+
105
+ it('should prioritize equality over equals/exact', () => {
106
+ const equality = PaginationFilterField.safeEquality({
107
+ equals: true,
108
+ exact: false,
109
+ equality: PaginationFilterEquality.LESS_THAN
110
+ });
111
+
112
+ expect(equality).toBe(PaginationFilterEquality.LESS_THAN);
113
+ });
114
+
115
+ it('should return undefined if no equality can be determined', () => {
116
+ const equality = PaginationFilterField.safeEquality({});
117
+
118
+ expect(equality).toBeUndefined();
119
+ });
120
+
121
+ it('should work with an instance of PaginationFilterField', () => {
122
+ const ff = new PaginationFilterField({
123
+ field: 'f',
124
+ value: 'v',
125
+ equals: false,
126
+ exact: false,
127
+ equality: PaginationFilterEquality.GREATER_THAN
128
+ });
129
+
130
+ // safeEquality will prioritize the `equality` property on the instance
131
+ const equality = PaginationFilterField.safeEquality(ff);
132
+
133
+ expect(equality).toBe(PaginationFilterEquality.GREATER_THAN);
134
+ });
135
+ });
136
+ });
137
+ });