dashboard-shell-shell 3.0.2-rc.105 → 3.0.2-test.20250913

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.
@@ -417,7 +417,7 @@ export default {
417
417
  const isLoading = this.loading || false;
418
418
 
419
419
  let isCreatable = false;
420
- const lastPath = this.$route.path.split('/').pop();
420
+ const lastPath = this.$route?.path.split('/').pop();
421
421
 
422
422
  if (lastPath.includes('.')) {
423
423
  isCreatable = this.$store.getters['type-map/optionsFor'](lastPath).isCreatable;
@@ -1753,10 +1753,11 @@ export default {
1753
1753
  @mouseover="setBulkActionOfInterest(act)"
1754
1754
  @mouseleave="setBulkActionOfInterest(null)"
1755
1755
  >
1756
- <i
1756
+ <!-- <i
1757
1757
  v-if="act.icon"
1758
1758
  :class="act.icon"
1759
- />
1759
+ style="line-height: 12px;height: 12px;font-size: 12px;"
1760
+ /> -->
1760
1761
  <span v-clean-html="act.label" />
1761
1762
  </button>
1762
1763
  <template v-if="featureDropdownMenu">
@@ -388,17 +388,6 @@ export default {
388
388
  });
389
389
  }
390
390
 
391
- rows = rows.map((item) => {
392
- if (item.key && item.key.includes('harvester')) {
393
- item.key = item.key.replace('harvester', 'cloud');
394
- }
395
- if (item.key && item.value.includes('harvester')) {
396
- item.value = item.value.replace('harvester', 'cloud');
397
- }
398
-
399
- return item;
400
- });
401
-
402
391
  return rows;
403
392
  },
404
393
 
@@ -409,8 +398,6 @@ export default {
409
398
  [this.valueName]: value,
410
399
  };
411
400
 
412
- obj.key = obj.key?.replace('harvester', 'cloud');
413
- obj.value = obj.value?.replace('harvester', 'cloud');
414
401
  obj.binary = false;
415
402
  obj.canEncode = this.handleBase64;
416
403
  obj.supported = true;
@@ -492,8 +479,8 @@ export default {
492
479
  // let value = (row[valueName] || '');
493
480
  // const key = (row[keyName] || '').trim();
494
481
 
495
- const key = (row[keyName].replace('cloud', 'harvester') || '').trim();
496
- let value = (row[valueName].replace('cloud', 'harvester') || '').trim();
482
+ const key = (row[keyName] || '').trim();
483
+ let value = (row[valueName] || '').trim();
497
484
 
498
485
  if (value && typeOf(value) === 'object') {
499
486
  out[key] = JSON.parse(JSON.stringify(value));
@@ -289,7 +289,7 @@ export default {
289
289
  :data-testid="`input-match-type-field-${index}`"
290
290
  >
291
291
  <div v-if="isView">
292
- {{ row.matching.replace('harvester', 'cloud') }}
292
+ {{ row.matching }}
293
293
  <!-- {{ row.matching }} -->
294
294
  </div>
295
295
  <LabeledSelect
@@ -305,7 +305,7 @@ export default {
305
305
  :data-testid="`input-match-expression-key-${index}`"
306
306
  >
307
307
  <div v-if="isView" class="view-item-value">
308
- {{ row.key.replace('harvester', 'cloud') }}
308
+ {{ row.key }}
309
309
  </div>
310
310
  <input
311
311
  v-else-if="!hasKeySelectOptions"
@@ -252,7 +252,7 @@ export default {
252
252
  const options = namespaces
253
253
  .map((namespace) => ({ nameDisplay: namespace, id: namespace }))
254
254
  .map(props.namespaceMapper || ((obj) => ({
255
- label: obj.nameDisplay.replace('harvester', 'cloud'),
255
+ label: obj.nameDisplay,
256
256
  value: obj.id,
257
257
  })));
258
258
 
@@ -753,7 +753,7 @@ export default {
753
753
  :data-testid="`namespaces-value-${j}`"
754
754
  class="ns-value"
755
755
  >
756
- <div>{{ ns.label.replace('harvester', 'cloud') }}</div>
756
+ <div>{{ ns.label }}</div>
757
757
  <!-- block user from removing the last selection if ns forced filtering is on -->
758
758
  <i
759
759
  v-if="!namespaceFilterMode || value.length > 1"
@@ -864,7 +864,7 @@ export default {
864
864
  v-if="opt.kind === NAMESPACE_FILTER_KINDS.NAMESPACE"
865
865
  class="icon icon-folder"
866
866
  />
867
- <div>{{ opt.label.replace('harvester', 'cloud') }}</div>
867
+ <div>{{ opt.label }}</div>
868
868
  <i
869
869
  v-if="opt.selected"
870
870
  class="icon icon-checkmark"
@@ -22,17 +22,17 @@ export function installNavigationGuards(router, context) {
22
22
  let changed = false;
23
23
  const params = { ...to.params };
24
24
 
25
- if (params.product?.includes('cloud')) {
25
+ if (params?.product?.includes('cloud')) {
26
26
  params.product = params.product.replace(/cloud/g, 'harvester');
27
27
  changed = true;
28
28
  }
29
29
 
30
- if (params.cluster?.includes('cloud')) {
30
+ if (params?.cluster?.includes('cloud')) {
31
31
  params.cluster = params.cluster.replace(/cloud/g, 'harvester');
32
32
  changed = true;
33
33
  }
34
34
 
35
- if (params.resource?.includes('cloud')) {
35
+ if (params?.resource?.includes('cloud')) {
36
36
  params.resource = params.resource.replace(/cloud/g, 'harvester');
37
37
  changed = true;
38
38
  }
@@ -64,14 +64,22 @@ export function installNavigationGuards(router, context) {
64
64
 
65
65
  // 🔹 最后执行:只改地址栏,不改内部
66
66
  router.afterEach((to) => {
67
+ const base = router.options.history?.base || ''; // 获取 router base,防止丢失
68
+ let cloudPath = to.fullPath.replace(/harvester/g, 'cloud');
67
69
 
68
- const cloudPath = to.fullPath
69
- .replace(/harvester/g, 'cloud')
70
+ // fullPath 可能已经不带 base,需要拼回去
71
+ if (!cloudPath.startsWith(base)) {
72
+ cloudPath = base + cloudPath;
73
+ }
74
+
75
+ // 获取当前地址栏完整 URL(path + search + hash)
76
+ const currentLocation = window.location.pathname + window.location.search + window.location.hash;
70
77
 
71
- if (cloudPath !== to.fullPath) {
78
+ // 只有在地址栏实际不同的时候才替换,避免死循环
79
+ if (cloudPath !== currentLocation) {
80
+ console.info('[URL Replace] Updating address bar:', currentLocation, '→', cloudPath);
72
81
  window.history.replaceState({}, '', cloudPath);
73
82
  }
74
-
75
83
  });
76
84
  }
77
85
 
@@ -162,7 +162,7 @@ export const NAMESPACE = {
162
162
  name: 'namespace',
163
163
  labelKey: 'tableHeaders.namespace',
164
164
  value: 'namespace',
165
- getValue: row => row && row.namespace && row.namespace.replace('harvester', 'cloud'),
165
+ getValue: row => row && row.namespace && row.namespace,
166
166
  sort: 'namespace',
167
167
  dashIfEmpty: true,
168
168
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dashboard-shell-shell",
3
- "version": "3.0.2-rc.105",
3
+ "version": "3.0.2-test.20250913",
4
4
  "description": "Rancher Dashboard Shell",
5
5
  "repository": "https://github.com/rancherlabs/dashboard",
6
6
  "license": "Apache-2.0",
@@ -307,47 +307,13 @@ export default {
307
307
  $plugin: this.$store.$plugin
308
308
  });
309
309
 
310
- // 等待集群列表加载完成,确保 defaultClusterId 可用
311
- await this.$store.dispatch('loadManagement'); // 确保管理模块初始化
312
- const clusterId = this.$store.getters['defaultClusterId'];
313
-
314
- let userRoute = {
315
- name: 'c-cluster-product-resource',
316
- params: {
317
- cluster: '_',
318
- product: 'auth',
319
- resource: 'management.cattle.io.user',
320
- }
321
- }
322
-
323
- // 构造 Harvester 路由
324
- let harvesterRoute = null;
325
-
326
- if (clusterId) {
327
- harvesterRoute = {
328
- name: 'c-cluster-product-resource',
329
- params: {
330
- cluster: clusterId,
331
- product: 'harvesterManager',
332
- resource: 'harvesterhci.io.management.cluster'
333
- }
334
- };
335
-
336
- // 写入 AFTER_LOGIN_ROUTE(复用页面设置登录首页逻辑)
337
- await this.$store.dispatch('prefs/set', {
338
- key: AFTER_LOGIN_ROUTE,
339
- value: harvesterRoute || userRoute
340
- });
341
-
342
- }
343
-
344
310
 
345
311
  // 登录跳转
346
312
  if (this.firstLogin || user[0]?.mustChangePassword) {
347
313
  this.$store.dispatch('auth/setInitialPass', this.password);
348
314
  this.$router.push({ name: 'auth-setup' });
349
315
  } else {
350
- this.$router.push(harvesterRoute || userRoute);
316
+ this.$router.push({ name: 'index' });
351
317
  }
352
318
 
353
319
  } catch (err) {
package/store/type-map.js CHANGED
@@ -513,7 +513,7 @@ export const getters = {
513
513
 
514
514
  groupsForVirTypes(state) {
515
515
  return (product, name) => {
516
- return state.virtualTypes?.[product]?.find(item => item.name === name)?.icon || '';
516
+ return state.virtualTypes?.[product].find(item => item.name === name)?.icon;
517
517
  };
518
518
  },
519
519
 
@@ -718,7 +718,6 @@ export const getters = {
718
718
  route.params = route.params || {};
719
719
  route.params.cluster = clusterId;
720
720
  route.params.product = productId;
721
- route.params.resource = route.params.resource;
722
721
  }
723
722
 
724
723
  group.children.push({
package/utils/error.js CHANGED
@@ -138,6 +138,10 @@ export const normalizeError = (err) => {
138
138
  };
139
139
  };
140
140
  export function translateError(error) {
141
+ error = typeof error === 'string'
142
+ ? error
143
+ : error?.message || error?.toString() || '';
144
+
141
145
  const originError = error;
142
146
  error = error?.toLowerCase().replace(/admission webhook(.*?)denied the request:/g, (match, p1) => {
143
147
  return '';
package/utils/router.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import { INSTALL_REDIRECT_META_KEY } from '@shell/config/router/navigation-guards/install-redirect';
2
2
 
3
3
  export function harvesterhci2cloud(str) {
4
- return str?.replace('harvesterhci.io', 'cloudhci.io')
4
+ return str?.replace('harvesterhci.io', 'cloudhci.io')
5
5
  }
6
6
 
7
7
  export function cloud2harvesterhci(str) {
@@ -14,11 +14,11 @@ export function cloud2harvesterhci(str) {
14
14
  }
15
15
 
16
16
  export function harvester2cloud(str) {
17
- return str?.replace(/harvester/g, 'cloud');
17
+ return str?.replace('harvester', 'cloud')
18
18
  }
19
19
 
20
20
  export function cloud2harvester(str) {
21
- return str?.replace(/cloud/g, 'harvester');
21
+ return str?.replace('cloud', 'harvester')
22
22
  }
23
23
 
24
24
  export function queryParamsFor(current, qp, defaults = {}) {
@@ -89,7 +89,7 @@ export const getPackageFromRoute = (route) => {
89
89
  };
90
90
 
91
91
  export const getResourceFromRoute = (to) => {
92
- let resource = cloud2harvesterhci(to.params?.resource);
92
+ let resource = to.params?.resource;
93
93
 
94
94
  if (!resource) {
95
95
  resource = findMeta(to, 'resource');