@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
@@ -186,4 +186,73 @@ describe('class Namespace', () => {
186
186
  it.todo('should return the resourceQuota');
187
187
  it.todo('should set the resourceQuota as reactive Vue property');
188
188
  it.todo('should reset project with cleanForNew');
189
+
190
+ describe('glance', () => {
191
+ it('should return projectGlance instead of namespace when namespace is in a project', () => {
192
+ const t = jest.fn((key) => key);
193
+ const ctx = { rootGetters: { 'i18n/t': t } };
194
+ const namespace = new Namespace({}, ctx);
195
+
196
+ const project = {
197
+ detailLocation: 'project-detail',
198
+ nameDisplay: 'My Project',
199
+ };
200
+
201
+ jest.spyOn(namespace, 'project', 'get').mockReturnValue(project);
202
+ Object.defineProperty(namespace, '_glance', { get: jest.fn(() => [{ name: 'namespace' }, { name: 'other' }]) });
203
+
204
+ const result = namespace.glance;
205
+
206
+ expect(result).toHaveLength(2);
207
+ expect(result[0].name).toBe('project');
208
+ expect(result[0].label).toBe('component.resource.detail.glance.project');
209
+ expect(result[0].formatter).toBe('Link');
210
+ expect(result[0].formatterOpts?.to).toBe('project-detail');
211
+ expect(result[0].content).toBe('My Project');
212
+ expect(result[1].name).toBe('other');
213
+ });
214
+
215
+ it('should remove namespace from glance when namespace is not in a project', () => {
216
+ const namespace = new Namespace({});
217
+
218
+ jest.spyOn(namespace, 'project', 'get').mockReturnValue(null);
219
+ Object.defineProperty(namespace, '_glance', { get: jest.fn(() => [{ name: 'namespace' }, { name: 'other' }]) });
220
+
221
+ const result = namespace.glance;
222
+
223
+ expect(result).toHaveLength(1);
224
+ expect(result[0].name).toBe('other');
225
+ });
226
+ });
227
+
228
+ describe('projectGlance', () => {
229
+ it('should return undefined if namespace is not in a project', () => {
230
+ const namespace = new Namespace({});
231
+
232
+ jest.spyOn(namespace, 'project', 'get').mockReturnValue(null);
233
+
234
+ expect(namespace.projectGlance).toBeUndefined();
235
+ });
236
+
237
+ it('should return project glance information if namespace is in a project', () => {
238
+ const t = jest.fn((key) => key);
239
+ const ctx = { rootGetters: { 'i18n/t': t } };
240
+ const namespace = new Namespace({}, ctx);
241
+
242
+ const project = {
243
+ detailLocation: 'project-detail',
244
+ nameDisplay: 'My Project',
245
+ };
246
+
247
+ jest.spyOn(namespace, 'project', 'get').mockReturnValue(project);
248
+
249
+ const result = namespace.projectGlance;
250
+
251
+ expect(result?.name).toBe('project');
252
+ expect(result?.label).toBe('component.resource.detail.glance.project');
253
+ expect(result?.formatter).toBe('Link');
254
+ expect(result?.formatterOpts.to).toBe('project-detail');
255
+ expect(result?.content).toBe('My Project');
256
+ });
257
+ });
189
258
  });
@@ -1,5 +1,5 @@
1
1
  import Workload from './workload';
2
- import { WORKLOAD_TYPES, POD, WORKLOAD_TYPE_TO_KIND_MAPPING } from '@shell/config/types';
2
+ import { WORKLOAD_TYPES, WORKLOAD_TYPE_TO_KIND_MAPPING } from '@shell/config/types';
3
3
 
4
4
  export default class StatefulSet extends Workload {
5
5
  async rollBack(cluster, statefulSet, revision) {
@@ -21,16 +21,14 @@ export default class StatefulSet extends Workload {
21
21
  await this.rollBackWorkload(cluster, statefulSet, 'statefulsets', body);
22
22
  }
23
23
 
24
- // we need to provide a new pods getter for statefulsets because the relationship
25
- // done on the parent model "workload" is not correct
24
+ /**
25
+ * See fetchPods description for more info
26
+ */
26
27
  get pods() {
27
- const relationships = this.metadata?.relationships || [];
28
- const podRelationship = relationships.filter((relationship) => relationship.toType === POD)[0];
29
-
30
- if (podRelationship) {
31
- const pods = this.$getters['podsByNamespace'](this.metadata.namespace);
32
-
33
- return pods.filter((pod) => {
28
+ if (this.podMatchExpression) {
29
+ // Given https://github.com/rancher/dashboard/issues/7555 we want to avoid scenarios where we show pods that have an applicable label but aren't applicable (?!)
30
+ // super.pods is the pods that match the statefulsets podSelector, so start from that and then filter further by pod's owner
31
+ return super.pods.filter((pod) => {
34
32
  // a bit of a duplication of podRelationship, but always safe to check...
35
33
  if (pod.metadata?.ownerReferences?.length) {
36
34
  const ownerReferencesStatefulSet = pod.metadata?.ownerReferences?.find((own) => own.kind === WORKLOAD_TYPE_TO_KIND_MAPPING[WORKLOAD_TYPES.STATEFUL_SET]);
package/models/chart.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { compatibleVersionsFor, APP_UPGRADE_STATUS } from '@shell/store/catalog';
2
2
  import {
3
- REPO_TYPE, REPO, CHART, VERSION, _FLAGGED, HIDE_SIDE_NAV, CATEGORY, TAG
3
+ REPO_TYPE, REPO, CHART, VERSION, _FLAGGED, HIDE_SIDE_NAV, CATEGORY, TAG, DEPRECATED as DEPRECATED_QUERY
4
4
  } from '@shell/config/query-params';
5
5
  import { BLANK_CLUSTER } from '@shell/store/store-types.js';
6
6
  import SteveModel from '@shell/plugins/steve/steve-class';
@@ -29,6 +29,10 @@ export default class Chart extends SteveModel {
29
29
  [VERSION]: version,
30
30
  };
31
31
 
32
+ if (this.deprecated) {
33
+ out[DEPRECATED_QUERY] = true;
34
+ }
35
+
32
36
  if ( from ) {
33
37
  out[from] = _FLAGGED;
34
38
  }
@@ -1,7 +1,7 @@
1
1
  import { matching, convertSelectorObj } from '@shell/utils/selector';
2
2
  import isEmpty from 'lodash/isEmpty';
3
3
  import { escapeHtml } from '@shell/utils/string';
4
- import { FLEET, MANAGEMENT } from '@shell/config/types';
4
+ import { FLEET } from '@shell/config/types';
5
5
  import { FLEET as FLEET_ANNOTATIONS } from '@shell/config/labels-annotations';
6
6
  import { addObject, addObjects, findBy } from '@shell/utils/array';
7
7
  import SteveModel from '@shell/plugins/steve/steve-class';
@@ -29,8 +29,19 @@ function normalizeStateCounts(data) {
29
29
  }
30
30
 
31
31
  export default class FleetApplication extends SteveModel {
32
- get currentUser() {
33
- return this.$rootGetters['auth/v3User'] || {};
32
+ async getCurrentUser() {
33
+ const user = this.$rootGetters['auth/v3User'];
34
+
35
+ if (user?.id) {
36
+ return user;
37
+ }
38
+
39
+ const res = await this.$dispatch('rancher/request', {
40
+ url: '/v3/users?me=true',
41
+ method: 'get',
42
+ }, { root: true });
43
+
44
+ return res?.data?.[0] || {};
34
45
  }
35
46
 
36
47
  pause() {
@@ -48,10 +59,6 @@ export default class FleetApplication extends SteveModel {
48
59
  delete this.metadata.labels[FLEET_ANNOTATIONS.CREATED_BY_USER_ID];
49
60
  }
50
61
 
51
- if (this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_NAME]) {
52
- delete this.metadata.labels[FLEET_ANNOTATIONS.CREATED_BY_USER_NAME];
53
- }
54
-
55
62
  super.goToClone();
56
63
  }
57
64
 
@@ -144,11 +151,11 @@ export default class FleetApplication extends SteveModel {
144
151
  }
145
152
 
146
153
  statusResourceCountsForCluster(clusterId) {
147
- if (!this.targetClusters.some((c) => c.id === clusterId)) {
154
+ if (!(this.targetClusters || []).some((c) => c.id === clusterId)) {
148
155
  return {};
149
156
  }
150
157
 
151
- return this.status?.perClusterResourceCounts[clusterId] || { desiredReady: 0 };
158
+ return this.status?.perClusterResourceCounts?.[clusterId] || { desiredReady: 0 };
152
159
  }
153
160
 
154
161
  get resourcesStatuses() {
@@ -224,43 +231,6 @@ export default class FleetApplication extends SteveModel {
224
231
  return primaryDisplayStatusFromCount(resourceCounts) || STATES_ENUM.ACTIVE;
225
232
  }
226
233
 
227
- get authorId() {
228
- return this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_ID];
229
- }
230
-
231
- get author() {
232
- if (this.authorId) {
233
- return this.$rootGetters['management/byId'](MANAGEMENT.USER, this.authorId);
234
- }
235
-
236
- return null;
237
- }
238
-
239
- get createdBy() {
240
- const displayName = this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_NAME];
241
-
242
- if (!displayName) {
243
- return null;
244
- }
245
-
246
- return {
247
- displayName,
248
- location: !this.author ? null : {
249
- name: 'c-cluster-product-resource-id',
250
- params: {
251
- cluster: '_',
252
- product: 'auth',
253
- resource: MANAGEMENT.USER,
254
- id: this.author.id,
255
- }
256
- }
257
- };
258
- }
259
-
260
- get showCreatedBy() {
261
- return !!this.createdBy;
262
- }
263
-
264
234
  get clustersList() {
265
235
  return this.$getters['all'](FLEET.CLUSTER);
266
236
  }
@@ -1,7 +1,7 @@
1
1
  import { escapeHtml, ucFirst } from '@shell/utils/string';
2
2
  import SteveModel from '@shell/plugins/steve/steve-class';
3
3
  import { addObject, addObjects, findBy } from '@shell/utils/array';
4
- import { FLEET, MANAGEMENT } from '@shell/config/types';
4
+ import { FLEET } from '@shell/config/types';
5
5
  import { FLEET as FLEET_ANNOTATIONS } from '@shell/config/labels-annotations';
6
6
  import { convertSelectorObj, matching } from '@shell/utils/selector';
7
7
 
@@ -129,41 +129,4 @@ export default class FleetBundle extends SteveModel {
129
129
  );
130
130
  }
131
131
  }
132
-
133
- get authorId() {
134
- return this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_ID];
135
- }
136
-
137
- get author() {
138
- if (this.authorId) {
139
- return this.$rootGetters['management/byId'](MANAGEMENT.USER, this.authorId);
140
- }
141
-
142
- return null;
143
- }
144
-
145
- get createdBy() {
146
- const displayName = this.metadata?.labels?.[FLEET_ANNOTATIONS.CREATED_BY_USER_NAME];
147
-
148
- if (!displayName) {
149
- return null;
150
- }
151
-
152
- return {
153
- displayName,
154
- location: !this.author ? null : {
155
- name: 'c-cluster-product-resource-id',
156
- params: {
157
- cluster: '_',
158
- product: 'auth',
159
- resource: MANAGEMENT.USER,
160
- id: this.author.id,
161
- }
162
- }
163
- };
164
- }
165
-
166
- get showCreatedBy() {
167
- return !!this.createdBy;
168
- }
169
132
  }
@@ -209,4 +209,8 @@ export default class GitRepo extends FleetApplication {
209
209
  display: this.commitDisplay
210
210
  };
211
211
  }
212
+
213
+ get fullDetailPageOverride() {
214
+ return true;
215
+ }
212
216
  }
@@ -199,4 +199,8 @@ export default class HelmOp extends FleetApplication {
199
199
  get bundleDeployments() {
200
200
  return this.$getters['matching'](FLEET.BUNDLE_DEPLOYMENT, { [FLEET_ANNOTATIONS.HELM_NAME]: this.name });
201
201
  }
202
+
203
+ get fullDetailPageOverride() {
204
+ return true;
205
+ }
202
206
  }
@@ -278,7 +278,7 @@ export default class MgmtCluster extends SteveModel {
278
278
 
279
279
  // Color to use as the underline for the icon in the app bar
280
280
  get iconColor() {
281
- return this.metadata?.annotations[CLUSTER_BADGE.COLOR];
281
+ return this.metadata?.annotations?.[CLUSTER_BADGE.COLOR];
282
282
  }
283
283
 
284
284
  // Custom badge to show for the Cluster (if the appropriate annotations are set)
@@ -179,4 +179,16 @@ export default class Project extends HybridModel {
179
179
  get confirmRemove() {
180
180
  return true;
181
181
  }
182
+
183
+ get glance() {
184
+ const glance = [...this._glance];
185
+
186
+ const namespaceIndex = glance.findIndex((item) => item.name === 'namespace');
187
+
188
+ if (namespaceIndex > -1) {
189
+ glance.splice(namespaceIndex, 1);
190
+ }
191
+
192
+ return glance;
193
+ }
182
194
  }
@@ -269,4 +269,34 @@ export default class Namespace extends SteveModel {
269
269
  get hideDetailLocation() {
270
270
  return !!this.$rootGetters['currentProduct'].hideNamespaceLocation;
271
271
  }
272
+
273
+ get glance() {
274
+ const glance = [...this._glance];
275
+
276
+ const namespaceIndex = glance.findIndex((item) => item.name === 'namespace');
277
+
278
+ if (namespaceIndex > -1) {
279
+ glance.splice(namespaceIndex, 1, this.projectGlance);
280
+ }
281
+
282
+ // projectGlance could be undefined
283
+ return glance.filter(Boolean);
284
+ }
285
+
286
+ get projectGlance() {
287
+ // Not all namespaces are in a project
288
+ if (!this.project) {
289
+ return undefined;
290
+ }
291
+
292
+ return {
293
+ name: 'project',
294
+ label: this.t('component.resource.detail.glance.project'),
295
+ formatter: 'Link',
296
+ formatterOpts: {
297
+ to: this.project.detailLocation, row: {}, options: { internal: true }
298
+ },
299
+ content: this.project.nameDisplay
300
+ };
301
+ }
272
302
  }
@@ -43,7 +43,7 @@ export default class Workload extends WorkloadService {
43
43
  insertAt(out, 0, {
44
44
  action: 'toggleRollbackModal',
45
45
  label: this.t('action.rollback'),
46
- icon: 'icon icon-history',
46
+ icon: 'icon icon-downgrade-alt',
47
47
  enabled: !!this.links.update,
48
48
  });
49
49
 
@@ -595,6 +595,9 @@ export default class Workload extends WorkloadService {
595
595
  return selector;
596
596
  }
597
597
 
598
+ /**
599
+ * Match Expression version of the podSelector
600
+ */
598
601
  get podMatchExpression() {
599
602
  return this.podSelector ? parse(this.podSelector) : null;
600
603
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rancher/shell",
3
- "version": "3.0.5-rc.8",
3
+ "version": "3.0.5",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -28,7 +28,7 @@
28
28
  },
29
29
  "dependencies": {
30
30
  "@aws-sdk/client-ec2": "3.863.0",
31
- "@aws-sdk/client-eks": "3.863.0",
31
+ "@aws-sdk/client-eks": "3.879.0",
32
32
  "@aws-sdk/client-iam": "3.863.0",
33
33
  "@aws-sdk/client-kms": "3.863.0",
34
34
  "@smithy/fetch-http-handler": "5.1.1",
@@ -52,7 +52,7 @@
52
52
  "add": "2.0.6",
53
53
  "ansi_up": "5.0.0",
54
54
  "axios-retry": "3.1.9",
55
- "axios": "1.8.4",
55
+ "axios": "1.12.2",
56
56
  "babel-eslint": "10.1.0",
57
57
  "babel-plugin-module-resolver": "4.0.0",
58
58
  "babel-preset-vue": "2.0.2",
@@ -64,7 +64,7 @@
64
64
  "color": "4.2.3",
65
65
  "cookie-universal": "2.2.2",
66
66
  "cookie": "0.7.0",
67
- "core-js": "3.40.0",
67
+ "core-js": "3.45.0",
68
68
  "cron-validator": "1.4.0",
69
69
  "cronstrue": "2.53.0",
70
70
  "cross-env": "7.0.3",
@@ -74,7 +74,7 @@
74
74
  "cypress": "11.1.0",
75
75
  "d3-selection": "3.0.0",
76
76
  "d3": "7.3.0",
77
- "dayjs": "1.8.29",
77
+ "dayjs": "1.11.18",
78
78
  "defu": "5.0.1",
79
79
  "diff2html": "3.4.24",
80
80
  "dompurify": "3.2.5",
@@ -84,7 +84,7 @@
84
84
  "eslint-import-resolver-node": "0.3.9",
85
85
  "eslint-module-utils": "2.6.1",
86
86
  "eslint-plugin-cypress": "2.12.1",
87
- "eslint-plugin-import": "2.31.0",
87
+ "eslint-plugin-import": "2.32.0",
88
88
  "eslint-plugin-jest": "24.4.0",
89
89
  "eslint-plugin-n": "15.2.0",
90
90
  "eslint-plugin-vue": "9.32.0",
@@ -130,15 +130,15 @@
130
130
  "ufo": "0.7.11",
131
131
  "unfetch": "4.2.0",
132
132
  "url-parse": "1.5.10",
133
- "vue-router": "4.5.0",
133
+ "vue-router": "4.5.1",
134
134
  "vue-select": "4.0.0-beta.6",
135
135
  "vue-server-renderer": "2.7.16",
136
- "vue": "^3.2.13",
136
+ "vue": "3.5.18",
137
137
  "vue3-resize": "0.2.0",
138
138
  "vue3-virtual-scroll-list": "0.2.1",
139
139
  "vuedraggable": "4.1.0",
140
140
  "vuex": "4.1.0",
141
- "webpack-bundle-analyzer": "4.5.0",
141
+ "webpack-bundle-analyzer": "4.10.2",
142
142
  "webpack-virtual-modules": "0.4.3",
143
143
  "worker-loader": "3.0.8",
144
144
  "xterm-addon-canvas": "0.5.0",
@@ -172,4 +172,4 @@
172
172
  ".vue"
173
173
  ]
174
174
  }
175
- }
175
+ }
@@ -134,7 +134,8 @@ export default {
134
134
  },
135
135
 
136
136
  async fetch() {
137
- const username = this.$cookies.get(USERNAME, { parseJSON: false }) || '';
137
+ const cookie = this.$store.getters['cookies/get']({ key: USERNAME, options: { parseJSON: false } });
138
+ const username = cookie || '';
138
139
 
139
140
  this.username = username;
140
141
  this.remember = !!username;
@@ -272,15 +273,19 @@ export default {
272
273
  }
273
274
 
274
275
  if ( this.remember ) {
275
- this.$cookies.set(USERNAME, this.username, {
276
+ const options = {
276
277
  encode: (x) => x,
277
278
  maxAge: 86400 * 365,
278
279
  path: '/',
279
280
  sameSite: true,
280
281
  secure: true,
282
+ };
283
+
284
+ this.$store.commit('cookies/set', {
285
+ key: USERNAME, value: this.username, options
281
286
  });
282
287
  } else {
283
- this.$cookies.remove(USERNAME);
288
+ this.$store.commit('cookies/remove', { key: USERNAME });
284
289
  }
285
290
 
286
291
  // User logged with local login - we don't do any redirect/reload, so the boot-time plugin will not run again to laod the plugins
@@ -1,19 +1,20 @@
1
1
  <script>
2
2
  import { configType } from '@shell/models/management.cattle.io.authconfig';
3
+ import { SLO_AUTH_PROVIDERS } from '@shell/store/auth';
3
4
 
4
5
  export default {
5
6
  async fetch() {
6
7
  const publicAuthProviders = await this.$store.dispatch('auth/getAuthProviders');
7
8
 
8
- const samlAuthProvider = publicAuthProviders.find((authProvider) => configType[authProvider.id] === 'saml');
9
+ const sloAuthProvider = publicAuthProviders.find((authProvider) => SLO_AUTH_PROVIDERS.includes(configType[authProvider?.id]));
9
10
 
10
- if (!!samlAuthProvider) {
11
- const { logoutAllSupported, logoutAllEnabled, logoutAllForced } = samlAuthProvider;
11
+ if (!!sloAuthProvider) {
12
+ const { logoutAllSupported, logoutAllEnabled, logoutAllForced } = sloAuthProvider;
12
13
 
13
14
  if (logoutAllSupported && logoutAllEnabled && logoutAllForced) {
14
- // SAML - force SLO (logout from all apps)
15
+ // force SLO (logout from all apps)
15
16
  await this.$store.dispatch('auth/logout', {
16
- force: true, slo: true, provider: samlAuthProvider
17
+ force: true, slo: true, provider: sloAuthProvider
17
18
  }, { root: true });
18
19
  } else {
19
20
  // simple logout
@@ -5,12 +5,15 @@ interface FooterItem {
5
5
  icon?: string;
6
6
  iconTooltip?: Record<{key?: string, text?: string}>;
7
7
  labels: string[];
8
+ labelTooltip?: string;
9
+ type?: string;
8
10
  }
9
11
 
10
12
  const emit = defineEmits<{(e: 'click:item', type: string, label: string): void; }>();
11
13
 
12
14
  defineProps<{
13
15
  items: FooterItem[];
16
+ clickable?: boolean;
14
17
  }>();
15
18
 
16
19
  function onClickItem(type: string, label: string) {
@@ -32,20 +35,32 @@ function onClickItem(type: string, label: string) {
32
35
  v-clean-tooltip="t(footerItem.iconTooltip?.key)"
33
36
  :class="['icon', 'app-chart-card-footer-item-icon', footerItem.icon]"
34
37
  />
35
- <rc-item-card-action
38
+ <template
36
39
  v-for="(label, j) in footerItem.labels"
37
40
  :key="j"
38
- v-clean-tooltip="footerItem.labelTooltip"
39
- class="app-chart-card-footer-item-text secondary-text-link"
40
- data-testid="app-chart-card-footer-item-text"
41
- tabindex="0"
42
- :aria-label="t('catalog.charts.appChartCard.footerItem.ariaLabel')"
43
- @click="onClickItem(footerItem.type, label)"
44
- @keydown.enter="onClickItem(footerItem.type, label)"
45
- @keydown.space.prevent="onClickItem(footerItem.type, label)"
46
41
  >
47
- {{ label }}<span v-if="footerItem.labels.length > 1 && j !== footerItem.labels.length - 1">, </span>
48
- </rc-item-card-action>
42
+ <rc-item-card-action
43
+ v-if="clickable && footerItem.type"
44
+ v-clean-tooltip="footerItem.labelTooltip"
45
+ class="app-chart-card-footer-item-text secondary-text-link"
46
+ data-testid="app-chart-card-footer-item-text"
47
+ tabindex="0"
48
+ :aria-label="t('catalog.charts.appChartCard.footerItem.ariaLabel')"
49
+ @click="onClickItem(footerItem.type, label)"
50
+ >
51
+ {{ label }}
52
+ <span v-if="footerItem.labels.length > 1 && j !== footerItem.labels.length - 1">, </span>
53
+ </rc-item-card-action>
54
+ <span
55
+ v-else
56
+ v-clean-tooltip="footerItem.labelTooltip"
57
+ class="app-chart-card-footer-item-text"
58
+ data-testid="app-chart-card-footer-item-text"
59
+ >
60
+ {{ label }}
61
+ <span v-if="footerItem.labels.length > 1 && j !== footerItem.labels.length - 1">, </span>
62
+ </span>
63
+ </template>
49
64
  </div>
50
65
  </div>
51
66
  </template>
@@ -6,7 +6,7 @@ import ChartReadme from '@shell/components/ChartReadme';
6
6
  import LazyImage from '@shell/components/LazyImage';
7
7
  import isEqual from 'lodash/isEqual';
8
8
  import {
9
- CHART, REPO, REPO_TYPE, VERSION, SEARCH_QUERY, CATEGORY, TAG
9
+ CHART, REPO, REPO_TYPE, VERSION, SEARCH_QUERY, CATEGORY, TAG, DEPRECATED
10
10
  } from '@shell/config/query-params';
11
11
  import { DATE_FORMAT } from '@shell/store/prefs';
12
12
  import { ZERO_TIME } from '@shell/config/types';
@@ -50,7 +50,14 @@ export default {
50
50
  ...mapGetters(['currentCluster']),
51
51
 
52
52
  headerContent() {
53
- return this.chart.cardContent;
53
+ return {
54
+ ...this.chart.cardContent,
55
+ subHeaderItems: this.chart.cardContent.subHeaderItems.map((item, i) => i === 0 ? ({
56
+ icon: 'icon-version-alt',
57
+ iconTooltip: { key: 'tableHeaders.version' },
58
+ label: this.query.versionName
59
+ }) : item)
60
+ };
54
61
  },
55
62
 
56
63
  versions() {
@@ -144,10 +151,11 @@ export default {
144
151
  product: this.$store.getters['productId'],
145
152
  },
146
153
  query: {
147
- [REPO_TYPE]: this.query.repoType,
148
- [REPO]: this.query.repoName,
149
- [CHART]: this.query.chartName,
150
- [VERSION]: this.query.versionName,
154
+ [REPO_TYPE]: this.query.repoType,
155
+ [REPO]: this.query.repoName,
156
+ [CHART]: this.query.chartName,
157
+ [VERSION]: this.query.versionName,
158
+ [DEPRECATED]: this.query.deprecated,
151
159
  }
152
160
  });
153
161
  },
@@ -210,17 +218,6 @@ export default {
210
218
  <template>
211
219
  <Loading v-if="$fetchState.pending" />
212
220
  <main v-else>
213
- <Banner
214
- v-if="versionInfoError"
215
- color="error"
216
- :label="versionInfoError"
217
- />
218
- <Banner
219
- v-if="warningMessage"
220
- color="warning"
221
- :label="warningMessage"
222
- data-testid="deprecation-and-experimental-banner"
223
- />
224
221
  <div
225
222
  v-if="chart"
226
223
  class="chart-header"
@@ -284,6 +281,7 @@ export default {
284
281
  </div>
285
282
  <div class="header-bottom">
286
283
  <AppChartCardFooter
284
+ :clickable="true"
287
285
  :items="headerContent.footerItems"
288
286
  @click:item="handleHeaderItemClick"
289
287
  />
@@ -296,15 +294,26 @@ export default {
296
294
  @click.prevent="install"
297
295
  >
298
296
  <i
299
- v-if="action === 'upgrade'"
300
- class="icon icon-upgrade-alt mmr-2"
297
+ :class="['icon', action.icon, 'mmr-2']"
301
298
  />
302
- {{ t(`asyncButton.${action}.action` ) }}
299
+ {{ t(`catalog.chart.chartButton.action.${action.tKey}` ) }}
303
300
  </RcButton>
304
301
  </div>
305
302
 
306
303
  <div class="dashed-spacer" />
307
304
 
305
+ <Banner
306
+ v-if="versionInfoError"
307
+ color="error"
308
+ :label="versionInfoError"
309
+ />
310
+ <Banner
311
+ v-if="warningMessage"
312
+ color="warning"
313
+ :label="warningMessage"
314
+ data-testid="deprecation-and-experimental-banner"
315
+ />
316
+
308
317
  <div
309
318
  v-if="requires.length || warnings.length || targetedAppWarning || osWarning"
310
319
  class="chart-banners"