dashboard-shell-shell 3.0.5-test.5 → 3.0.5-test.51
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.
- package/assets/brand/csp/favicon.png +0 -0
- package/assets/icons/iconfont.css +4 -1
- package/assets/images/pl/dark/logo.png +0 -0
- package/assets/styles/all.scss +23 -3
- package/assets/styles/base/_variables.scss +5 -5
- package/assets/styles/fonts/_icons.scss +3 -2
- package/assets/styles/global/_button.scss +2 -2
- package/assets/styles/global/_form.scss +1 -0
- package/assets/styles/global/_select.scss +1 -1
- package/assets/styles/global/_tooltip.scss +5 -1
- package/assets/styles/themes/_light.scss +3 -3
- package/assets/styles/vendor/vue-select.scss +2 -1
- package/assets/translations/en-us.yaml +64 -0
- package/assets/translations/zh-hans.yaml +206 -21
- package/components/ButtonDropdown.vue +3 -1
- package/components/ClusterIconMenu.vue +1 -1
- package/components/CodeMirror.vue +6 -4
- package/components/ConsumptionGauge.vue +1 -1
- package/components/ContainerResourceLimit.vue +2 -2
- package/components/CruResource.vue +3 -2
- package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +10 -7
- package/components/Drawer/ResourceDetailDrawer/YamlTab.vue +1 -1
- package/components/Drawer/ResourceDetailDrawer/index.vue +3 -2
- package/components/ExplorerMembers.vue +10 -1
- package/components/GlobalRoleBindings.vue +69 -114
- package/components/PodSecurityAdmission.vue +1 -1
- package/components/PromptRemove.vue +23 -1
- package/components/RelatedResources.vue +3 -0
- package/components/Resource/Detail/Metadata/index.vue +1 -0
- package/components/Resource/Detail/TitleBar/Top.vue +2 -0
- package/components/Resource/Detail/TitleBar/composables.ts +16 -1
- package/components/Resource/Detail/TitleBar/index.vue +42 -23
- package/components/ResourceDetail/Masthead/index.vue +1 -1
- package/components/ResourceDetail/Masthead/latest.vue +1 -1
- package/components/ResourceDetail/Masthead/legacy.vue +8 -7
- package/components/ResourceDetail/legacy.vue +15 -15
- package/components/ResourceList/Masthead.vue +13 -17
- package/components/ResourceTable.vue +16 -0
- package/components/SideNav.vue +21 -21
- package/components/SingleClusterInfo.vue +2 -1
- package/components/SortableTable/THead.vue +46 -1
- package/components/SortableTable/index.vue +55 -19
- package/components/Tabbed/index.vue +7 -2
- package/components/auth/Principal.vue +16 -8
- package/components/auth/RoleDetailEdit.vue +11 -7
- package/components/breadcrumb/index.vue +15 -236
- package/components/form/ArrayList.vue +164 -147
- package/components/form/ArrayListGrouped.vue +5 -3
- package/components/form/ChangePassword.vue +1 -1
- package/components/form/ClusterAppearance.vue +4 -3
- package/components/form/Command.vue +4 -5
- package/components/form/Conditions.vue +15 -1
- package/components/form/Footer.vue +1 -0
- package/components/form/HealthCheck.vue +0 -2
- package/components/form/HookOption.vue +87 -58
- package/components/form/InputWithSelect.vue +8 -7
- package/components/form/KeyValue.vue +20 -2
- package/components/form/LabeledSelect.vue +3 -1
- package/components/form/Labels.vue +2 -2
- package/components/form/MatchExpressions.vue +4 -4
- package/components/form/Members/ClusterMembershipEditor.vue +1 -1
- package/components/form/Members/ClusterPermissionsEditor.vue +60 -41
- package/components/form/Members/MembershipEditor.vue +4 -4
- package/components/form/Members/ProjectMembershipEditor.vue +1 -1
- package/components/form/NameNsDescription.vue +2 -1
- package/components/form/Networking.vue +6 -9
- package/components/form/NodeAffinity.vue +29 -28
- package/components/form/PodAffinity.vue +23 -23
- package/components/form/Probe.vue +15 -11
- package/components/form/ProjectMemberEditor.vue +66 -48
- package/components/form/ResourceQuota/Namespace.vue +4 -4
- package/components/form/ResourceQuota/NamespaceRow.vue +11 -9
- package/components/form/ResourceQuota/Project.vue +4 -4
- package/components/form/ResourceQuota/ProjectRow.vue +36 -30
- package/components/form/ResourceSelector.vue +1 -1
- package/components/form/Security.vue +1 -3
- package/components/form/Select.vue +7 -1
- package/components/form/ServiceNameSelect.vue +2 -5
- package/components/form/ServicePorts.vue +149 -75
- package/components/form/Tolerations.vue +13 -9
- package/components/form/ValueFromResource.vue +110 -96
- package/components/formatter/WorkloadHealthScale.vue +4 -3
- package/components/nav/Group.vue +6 -0
- package/components/nav/Header.vue +17 -137
- package/components/nav/NamespaceFilter.vue +15 -21
- package/components/nav/TopLevelMenu.vue +99 -125
- package/components/nav/Type.vue +11 -3
- package/config/menuRouteMap.js +10 -0
- package/config/product/explorer.js +32 -10
- package/config/product/manager.js +28 -17
- package/config/router/navigation-guards/index.js +61 -3
- package/detail/node.vue +28 -23
- package/dialog/AddCustomBadgeDialog.vue +17 -9
- package/dialog/RollbackWorkloadDialog.vue +1 -1
- package/edit/autoscaling.horizontalpodautoscaler/external-metric.vue +1 -1
- package/edit/autoscaling.horizontalpodautoscaler/hpa-scaling-rule.vue +9 -6
- package/edit/autoscaling.horizontalpodautoscaler/index.vue +3 -1
- package/edit/autoscaling.horizontalpodautoscaler/metric-identifier.vue +2 -2
- package/edit/autoscaling.horizontalpodautoscaler/metric-object-reference.vue +7 -5
- package/edit/autoscaling.horizontalpodautoscaler/metric-target.vue +5 -3
- package/edit/autoscaling.horizontalpodautoscaler/metrics-row.vue +2 -2
- package/edit/autoscaling.horizontalpodautoscaler/object-metric.vue +2 -2
- package/edit/autoscaling.horizontalpodautoscaler/pod-metric.vue +1 -1
- package/edit/autoscaling.horizontalpodautoscaler/resource-metric.vue +2 -2
- package/edit/configmap.vue +4 -0
- package/edit/networking.k8s.io.ingress/Certificate.vue +14 -5
- package/edit/networking.k8s.io.ingress/DefaultBackend.vue +2 -2
- package/edit/networking.k8s.io.ingress/Rule.vue +5 -11
- package/edit/networking.k8s.io.ingress/RulePath.vue +105 -96
- package/edit/networking.k8s.io.networkpolicy/PolicyRule.vue +3 -3
- package/edit/networking.k8s.io.networkpolicy/PolicyRulePort.vue +4 -2
- package/edit/networking.k8s.io.networkpolicy/PolicyRuleTarget.vue +12 -11
- package/edit/networking.k8s.io.networkpolicy/index.vue +1 -1
- package/edit/persistentvolume/index.vue +3 -1
- package/edit/persistentvolumeclaim.vue +2 -0
- package/edit/provisioning.cattle.io.cluster/tabs/Basics.vue +1 -1
- package/edit/secret/index.vue +2 -2
- package/edit/service.vue +4 -1
- package/edit/storage.k8s.io.storageclass/index.vue +10 -8
- package/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/aws-ebs.vue +34 -27
- package/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/gce-pd.vue +15 -13
- package/edit/storage.k8s.io.storageclass/provisioners/kubernetes.io/vsphere-volume.vue +41 -39
- package/edit/workload/Job.vue +31 -34
- package/edit/workload/Upgrading.vue +5 -5
- package/edit/workload/index.vue +19 -15
- package/edit/workload/storage/Mount.vue +1 -0
- package/edit/workload/storage/awsElasticBlockStore.vue +9 -7
- package/edit/workload/storage/azureDisk.vue +14 -10
- package/edit/workload/storage/azureFile.vue +9 -7
- package/edit/workload/storage/csi/index.vue +6 -9
- package/edit/workload/storage/emptyDir.vue +7 -5
- package/edit/workload/storage/gcePersistentDisk.vue +9 -7
- package/edit/workload/storage/hostPath.vue +7 -5
- package/edit/workload/storage/nfs.vue +8 -6
- package/edit/workload/storage/persistentVolumeClaim/index.vue +12 -10
- package/edit/workload/storage/persistentVolumeClaim/persistentvolumeclaim.vue +20 -15
- package/edit/workload/storage/secret.vue +9 -6
- package/edit/workload/storage/vsphereVolume.vue +11 -7
- package/initialize/app-extended.js +7 -1
- package/list/management.cattle.io.podsecurityadmissionconfigurationtemplate.vue +8 -6
- package/mixins/create-edit-view/impl.js +10 -0
- package/models/provisioning.cattle.io.cluster.js +19 -18
- package/models/workload.js +2 -2
- package/package.json +1 -1
- package/pages/account/index.vue +96 -115
- package/pages/auth/setup.vue +36 -17
- package/pages/c/_cluster/auth/roles/index.vue +65 -8
- package/pages/c/_cluster/explorer/ConfigBadge.vue +1 -1
- package/pages/c/_cluster/explorer/index.vue +2 -1
- package/pages/c/_cluster/explorer/tools/index.vue +6 -6
- package/pages/home.vue +55 -13
- package/pkg/tsconfig.json +9 -9
- package/pkg/vue.config.js +1 -1
- package/plugins/dashboard-store/actions.js +1 -1
- package/plugins/dashboard-store/resource-class.js +28 -27
- package/rancher-components/Banner/Banner.vue +14 -2
- package/rancher-components/Form/Radio/RadioGroup.vue +9 -1
- package/rancher-components/LabeledTooltip/LabeledTooltip.vue +31 -2
- package/scripts/build-pkg.sh +18 -23
- package/scripts/publish-shell.sh +1 -1
- package/store/i18n.js +1 -0
- package/store/type-map.js +1 -3
- package/types/shell/index.d.ts +12 -30
- package/utils/error.js +26 -4
- package/utils/errorTranslate.json +390 -6
- package/utils/errorTranslateNew.json +39 -0
- package/utils/roleFiltering.js +33 -0
- package/vue.config.js +1 -1
|
@@ -115,6 +115,10 @@ export default {
|
|
|
115
115
|
labelKey: 'tableHeaders.role',
|
|
116
116
|
value: 'roleTemplate.nameDisplay'
|
|
117
117
|
},
|
|
118
|
+
{
|
|
119
|
+
name: '操作',
|
|
120
|
+
labelKey: 'tableHeaders.action',
|
|
121
|
+
},
|
|
118
122
|
],
|
|
119
123
|
loadingProjectBindings: true,
|
|
120
124
|
loadingClusterBindings: true
|
|
@@ -361,12 +365,13 @@ export default {
|
|
|
361
365
|
v-trim-whitespace
|
|
362
366
|
class="group-tab"
|
|
363
367
|
>
|
|
368
|
+
|
|
364
369
|
<div
|
|
365
370
|
v-clean-html="getProjectLabel(group)"
|
|
366
371
|
class="project-name"
|
|
367
372
|
/>
|
|
368
373
|
</div>
|
|
369
|
-
<div class="right">
|
|
374
|
+
<div class="right" style="margin-right: 80px;">
|
|
370
375
|
<button
|
|
371
376
|
v-if="canEditProjectMembers"
|
|
372
377
|
type="button"
|
|
@@ -460,8 +465,12 @@ export default {
|
|
|
460
465
|
& :deep() .group-bar{
|
|
461
466
|
display: flex;
|
|
462
467
|
justify-content: space-between;
|
|
468
|
+
align-items: center;
|
|
463
469
|
}
|
|
464
470
|
}
|
|
471
|
+
.role-secondary.btn-sm:focus, .role-secondary.btn-sm.focused{
|
|
472
|
+
border: 1px solid #d7d7d7;
|
|
473
|
+
}
|
|
465
474
|
.cluster-add {
|
|
466
475
|
justify-content: flex-end;
|
|
467
476
|
}
|
|
@@ -103,23 +103,36 @@ export default {
|
|
|
103
103
|
this.sortedRoles.global.push(...remainingGlobalRoles);
|
|
104
104
|
// End sort of global roles
|
|
105
105
|
|
|
106
|
+
if (!(sessionStorage.getItem('TOPLEVELPERMISSIONS') && sessionStorage.getItem('TOPLEVELPERMISSIONS') === 'superadmin')) {
|
|
107
|
+
delete this.sortedRoles.builtin
|
|
108
|
+
delete this.sortedRoles.custom
|
|
109
|
+
}
|
|
110
|
+
|
|
106
111
|
this.update();
|
|
107
112
|
}
|
|
108
113
|
} catch (e) { }
|
|
109
114
|
},
|
|
110
115
|
data() {
|
|
111
116
|
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
let globalPermissions = [
|
|
118
|
+
'admin',
|
|
119
|
+
'safe-admin',
|
|
120
|
+
'tenant',
|
|
121
|
+
]
|
|
116
122
|
|
|
117
|
-
|
|
118
|
-
globalPermissions
|
|
123
|
+
if (sessionStorage.getItem('TOPLEVELPERMISSIONS') === 'superadmin') {
|
|
124
|
+
globalPermissions = [
|
|
119
125
|
'admin',
|
|
126
|
+
'safe-admin',
|
|
120
127
|
'user',
|
|
121
128
|
'user-base',
|
|
122
|
-
|
|
129
|
+
'tenant',
|
|
130
|
+
]
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
// This not only identifies global roles but the order here is the order we want to display them in the UI
|
|
135
|
+
globalPermissions,
|
|
123
136
|
globalRoleBindings: null,
|
|
124
137
|
sortedRoles: null,
|
|
125
138
|
selectedRoles: [],
|
|
@@ -333,119 +346,60 @@ export default {
|
|
|
333
346
|
|
|
334
347
|
<div v-else>
|
|
335
348
|
<form v-if="selectedRoles">
|
|
336
|
-
<
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
:show-actions="false"
|
|
346
|
-
>
|
|
347
|
-
<template v-slot:title>
|
|
348
|
-
<div class="type-title">
|
|
349
|
-
<h3>{{ t(`rbac.globalRoles.types.${roleType}.label`) }}</h3>
|
|
350
|
-
<div class="type-description">
|
|
351
|
-
{{ t(`rbac.globalRoles.types.${roleType}.description`, { isUser }) }}
|
|
352
|
-
</div>
|
|
353
|
-
</div>
|
|
354
|
-
</template>
|
|
355
|
-
<template v-slot:body>
|
|
356
|
-
<div
|
|
357
|
-
class="checkbox-section"
|
|
358
|
-
:class="'checkbox-section--' + roleType"
|
|
359
|
-
>
|
|
360
|
-
<div
|
|
361
|
-
v-for="(role, i) in sortedRoles[roleType]"
|
|
362
|
-
:key="i"
|
|
363
|
-
class="checkbox mb-10 mr-10"
|
|
364
|
-
>
|
|
365
|
-
<Checkbox
|
|
366
|
-
v-model:value="selectedRoles"
|
|
367
|
-
:value-when-true="role.id"
|
|
368
|
-
:disabled="!!assignOnlyRoles[role.id]"
|
|
369
|
-
:label="role.nameDisplay"
|
|
370
|
-
:description="role.descriptionDisplay"
|
|
371
|
-
:mode="mode"
|
|
372
|
-
:data-testId="'grb-checkbox-' + role.id"
|
|
373
|
-
@update:value="checkboxChanged"
|
|
374
|
-
>
|
|
375
|
-
<template #label>
|
|
376
|
-
<div class="checkbox-label-slot">
|
|
377
|
-
<span class="checkbox-label">{{ role.nameDisplay }}</span>
|
|
378
|
-
<i
|
|
379
|
-
v-if="!!assignOnlyRoles[role.id]"
|
|
380
|
-
v-clean-tooltip="t('rbac.globalRoles.assignOnlyRole')"
|
|
381
|
-
class="checkbox-info icon icon-info icon-lg"
|
|
382
|
-
/>
|
|
383
|
-
</div>
|
|
384
|
-
</template>
|
|
385
|
-
</Checkbox>
|
|
386
|
-
</div>
|
|
387
|
-
</div>
|
|
388
|
-
</template>
|
|
389
|
-
</Card>
|
|
390
|
-
</div>
|
|
391
|
-
</template>
|
|
392
|
-
|
|
393
|
-
<template v-else>
|
|
394
|
-
<div
|
|
395
|
-
v-for="(sortedRole, roleType) in { global: sortedRoles['global'] }"
|
|
396
|
-
:key="roleType"
|
|
397
|
-
class="role-group mb-10"
|
|
349
|
+
<div
|
|
350
|
+
v-for="(sortedRole, roleType) in sortedRoles"
|
|
351
|
+
:key="roleType"
|
|
352
|
+
class="role-group mb-10"
|
|
353
|
+
>
|
|
354
|
+
<Card
|
|
355
|
+
v-if="Object.keys(sortedRole).length"
|
|
356
|
+
:show-highlight-border="false"
|
|
357
|
+
:show-actions="false"
|
|
398
358
|
>
|
|
399
|
-
<
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
<template v-slot:title>
|
|
405
|
-
<div class="type-title">
|
|
406
|
-
<h3>{{ t(`rbac.globalRoles.types.${roleType}.label`) }}</h3>
|
|
407
|
-
<div class="type-description">
|
|
408
|
-
{{ t(`rbac.globalRoles.types.${roleType}.description`, { isUser }) }}
|
|
409
|
-
</div>
|
|
359
|
+
<template v-slot:title>
|
|
360
|
+
<div class="type-title">
|
|
361
|
+
<h3>{{ t(`rbac.globalRoles.types.${roleType}.label`) }}</h3>
|
|
362
|
+
<div class="type-description">
|
|
363
|
+
{{ t(`rbac.globalRoles.types.${roleType}.description`, { isUser }) }}
|
|
410
364
|
</div>
|
|
411
|
-
</
|
|
412
|
-
|
|
365
|
+
</div>
|
|
366
|
+
</template>
|
|
367
|
+
<template v-slot:body>
|
|
368
|
+
<div
|
|
369
|
+
class="checkbox-section"
|
|
370
|
+
:class="'checkbox-section--' + roleType"
|
|
371
|
+
>
|
|
413
372
|
<div
|
|
414
|
-
|
|
415
|
-
:
|
|
373
|
+
v-for="(role, i) in sortedRoles[roleType]"
|
|
374
|
+
:key="i"
|
|
375
|
+
class="checkbox mb-10 mr-10"
|
|
416
376
|
>
|
|
417
|
-
<
|
|
418
|
-
v-
|
|
419
|
-
:
|
|
420
|
-
|
|
377
|
+
<Checkbox
|
|
378
|
+
v-model:value="selectedRoles"
|
|
379
|
+
:value-when-true="role.id"
|
|
380
|
+
:disabled="!!assignOnlyRoles[role.id]"
|
|
381
|
+
:label="role.nameDisplay"
|
|
382
|
+
:description="role.descriptionDisplay"
|
|
383
|
+
:mode="mode"
|
|
384
|
+
:data-testId="'grb-checkbox-' + role.id"
|
|
385
|
+
@update:value="checkboxChanged"
|
|
421
386
|
>
|
|
422
|
-
<
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
>
|
|
432
|
-
|
|
433
|
-
<div class="checkbox-label-slot">
|
|
434
|
-
<span class="checkbox-label">{{ role.nameDisplay }}</span>
|
|
435
|
-
<i
|
|
436
|
-
v-if="!!assignOnlyRoles[role.id]"
|
|
437
|
-
v-clean-tooltip="t('rbac.globalRoles.assignOnlyRole')"
|
|
438
|
-
class="checkbox-info icon icon-info icon-lg"
|
|
439
|
-
/>
|
|
440
|
-
</div>
|
|
441
|
-
</template>
|
|
442
|
-
</Checkbox>
|
|
443
|
-
</div>
|
|
387
|
+
<template #label>
|
|
388
|
+
<div class="checkbox-label-slot">
|
|
389
|
+
<span class="checkbox-label">{{ role.nameDisplay }}</span>
|
|
390
|
+
<i
|
|
391
|
+
v-if="!!assignOnlyRoles[role.id]"
|
|
392
|
+
v-clean-tooltip="t('rbac.globalRoles.assignOnlyRole')"
|
|
393
|
+
class="checkbox-info icon icon-info icon-lg"
|
|
394
|
+
/>
|
|
395
|
+
</div>
|
|
396
|
+
</template>
|
|
397
|
+
</Checkbox>
|
|
444
398
|
</div>
|
|
445
|
-
</
|
|
446
|
-
</
|
|
447
|
-
</
|
|
448
|
-
</
|
|
399
|
+
</div>
|
|
400
|
+
</template>
|
|
401
|
+
</Card>
|
|
402
|
+
</div>
|
|
449
403
|
</form>
|
|
450
404
|
</div>
|
|
451
405
|
</template>
|
|
@@ -490,4 +444,5 @@ export default {
|
|
|
490
444
|
}
|
|
491
445
|
}
|
|
492
446
|
}
|
|
447
|
+
|
|
493
448
|
</style>
|
|
@@ -83,6 +83,22 @@ export default {
|
|
|
83
83
|
return this.$store.getters['type-map/labelFor'](schema, this.toRemove.length);
|
|
84
84
|
},
|
|
85
85
|
|
|
86
|
+
typeZh() {
|
|
87
|
+
const typeLabel = this.type
|
|
88
|
+
|
|
89
|
+
const lowerKey = typeLabel.toLowerCase();
|
|
90
|
+
const i18nKey = `promptRemoveText.${lowerKey}`;
|
|
91
|
+
|
|
92
|
+
console.log(i18nKey, ' i18nKey-------------------------');
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
if (this.t(i18nKey)) {
|
|
96
|
+
return this.t(i18nKey);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
return typeLabel;
|
|
100
|
+
},
|
|
101
|
+
|
|
86
102
|
selfLinks() {
|
|
87
103
|
return this.toRemove.map((resource) => {
|
|
88
104
|
return get(resource, 'links.self');
|
|
@@ -296,6 +312,12 @@ export default {
|
|
|
296
312
|
this.done();
|
|
297
313
|
} catch (err) {
|
|
298
314
|
this.error = err.message || err;
|
|
315
|
+
if (this.error.includes('not supported')) {
|
|
316
|
+
this.$store.dispatch('growl/error', {
|
|
317
|
+
title: '权限不足',
|
|
318
|
+
message: '当前用户不允许删除集群'
|
|
319
|
+
}, { root: true });
|
|
320
|
+
}
|
|
299
321
|
btnCB(false);
|
|
300
322
|
}
|
|
301
323
|
},
|
|
@@ -380,7 +402,7 @@ export default {
|
|
|
380
402
|
:needs-confirm="needsConfirm"
|
|
381
403
|
:value="toRemove"
|
|
382
404
|
:names="names"
|
|
383
|
-
:type="
|
|
405
|
+
:type="typeZh"
|
|
384
406
|
:done-location="doneLocation"
|
|
385
407
|
@errors="e => error = e"
|
|
386
408
|
@done="done"
|
|
@@ -14,7 +14,22 @@ export const useDefaultTitleBarProps = (resource: any, resourceSubtype?: Ref<str
|
|
|
14
14
|
const resourceSubtypeValue = toValue(resourceSubtype);
|
|
15
15
|
const currentStore = store.getters['currentStore'](resourceValue.type);
|
|
16
16
|
const schema = store.getters[`${ currentStore }/schemaFor`](resourceValue.type);
|
|
17
|
-
|
|
17
|
+
let resourceTypeLabel = resourceValue.parentNameOverride || store.getters['type-map/labelFor'](schema);
|
|
18
|
+
|
|
19
|
+
// 转换为中文
|
|
20
|
+
const displayName_zh_hans: Record<string, string> = {
|
|
21
|
+
'GlobalRole': '全局角色',
|
|
22
|
+
'RoleTemplate': '集群角色',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (displayName_zh_hans[resourceTypeLabel]) {
|
|
26
|
+
resourceTypeLabel = displayName_zh_hans[resourceTypeLabel]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (resourceTypeLabel == '集群角色' && (route.query?.roleContext == 'NAMESPACE' || resource?.parentLocationOverride?.hash == '#NAMESPACE')) {
|
|
30
|
+
resourceTypeLabel = '项目或资源组角色'
|
|
31
|
+
}
|
|
32
|
+
|
|
18
33
|
const resourceName = resourceSubtypeValue ? `${ resourceSubtypeValue } - ${ resourceValue.nameDisplay }` : resourceValue.nameDisplay;
|
|
19
34
|
const resourceTo = resourceValue.listLocation || {
|
|
20
35
|
name: 'c-cluster-product-resource',
|
|
@@ -14,6 +14,7 @@ import ButtonGroup from '@shell/components/ButtonGroup';
|
|
|
14
14
|
import { ExtensionPoint, PanelLocation } from '@shell/core/types';
|
|
15
15
|
import ExtensionPanel from '@shell/components/ExtensionPanel.vue';
|
|
16
16
|
import breadcrumb from '@shell/components/breadcrumb/index.vue'
|
|
17
|
+
import { useDefaultConfigTabProps } from '@shell/components/Drawer/ResourceDetailDrawer/composables';
|
|
17
18
|
|
|
18
19
|
export interface Badge {
|
|
19
20
|
color: 'bg-success' | 'bg-error' | 'bg-warning' | 'bg-info';
|
|
@@ -37,7 +38,6 @@ export interface TitleBarProps {
|
|
|
37
38
|
showViewOptions?: boolean;
|
|
38
39
|
|
|
39
40
|
onShowConfiguration?: (returnFocusSelector: string) => void;
|
|
40
|
-
value?: any;
|
|
41
41
|
parentRouteOverride?: string;
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -46,9 +46,10 @@ const showConfigurationIcon = require(`@shell/assets/images/icons/document.svg`)
|
|
|
46
46
|
|
|
47
47
|
<script setup lang="ts">
|
|
48
48
|
const {
|
|
49
|
-
parentRouteOverride,
|
|
49
|
+
parentRouteOverride, resource, resourceTypeLabel, resourceTo, resourceName, description, badge, showViewOptions, onShowConfiguration,
|
|
50
50
|
} = defineProps<TitleBarProps>();
|
|
51
51
|
|
|
52
|
+
|
|
52
53
|
const store = useStore();
|
|
53
54
|
const i18n = useI18n(store);
|
|
54
55
|
const router = useRouter();
|
|
@@ -57,6 +58,10 @@ const emit = defineEmits(['show-configuration']);
|
|
|
57
58
|
const showConfigurationDataTestId = 'show-configuration-cta';
|
|
58
59
|
const showConfigurationReturnFocusSelector = computed(() => `[data-testid="${ showConfigurationDataTestId }"]`);
|
|
59
60
|
|
|
61
|
+
|
|
62
|
+
const configTabProps = useDefaultConfigTabProps(resource);
|
|
63
|
+
|
|
64
|
+
|
|
60
65
|
const currentView = ref(router?.currentRoute?.value?.query?.as || _CONFIG);
|
|
61
66
|
const viewOptions = computed(() => {
|
|
62
67
|
if (!showViewOptions) {
|
|
@@ -77,39 +82,42 @@ const viewOptions = computed(() => {
|
|
|
77
82
|
|
|
78
83
|
const Svg = require('~shell/assets/images/API.svg')
|
|
79
84
|
|
|
80
|
-
const parent = computed(() =>{
|
|
81
|
-
|
|
85
|
+
const parent = computed(() => {
|
|
86
|
+
|
|
82
87
|
const product = store.getters['currentProduct'].name;
|
|
83
88
|
|
|
84
89
|
const defaultLocation = {
|
|
85
|
-
name:
|
|
90
|
+
name: 'c-cluster-product-resource',
|
|
86
91
|
params: {
|
|
87
|
-
resource
|
|
92
|
+
resource,
|
|
88
93
|
product,
|
|
89
94
|
}
|
|
90
95
|
};
|
|
91
96
|
|
|
92
|
-
const location =
|
|
97
|
+
const location = resource?.parentLocationOverride || defaultLocation;
|
|
93
98
|
|
|
94
99
|
if (parentRouteOverride) {
|
|
95
100
|
location.name = parentRouteOverride;
|
|
96
101
|
}
|
|
97
102
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
};
|
|
101
|
-
|
|
102
|
-
return out;
|
|
103
|
-
})
|
|
103
|
+
return { location };
|
|
104
|
+
});
|
|
104
105
|
|
|
105
106
|
const menuIcon = computed(() => {
|
|
106
107
|
const product = store.getters['productId'];
|
|
108
|
+
const resources = parent.value.location?.params?.resource || '';
|
|
109
|
+
return store.getters['type-map/groupsForVirTypes'](product, resources) || 'default menuIcon';
|
|
110
|
+
});
|
|
107
111
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
})
|
|
112
|
+
const hiddenTypes = [
|
|
113
|
+
'harvesterhci.io.virtualmachinebackup',
|
|
114
|
+
];
|
|
112
115
|
|
|
116
|
+
const shouldShowConfiguration = computed(() =>
|
|
117
|
+
onShowConfiguration &&
|
|
118
|
+
configTabProps &&
|
|
119
|
+
!hiddenTypes.includes(resource?.type)
|
|
120
|
+
);
|
|
113
121
|
|
|
114
122
|
watch(
|
|
115
123
|
() => currentView.value,
|
|
@@ -121,10 +129,10 @@ watch(
|
|
|
121
129
|
|
|
122
130
|
<template>
|
|
123
131
|
<div class="title-bar">
|
|
124
|
-
<breadcrumb :resource="resource"/>
|
|
132
|
+
<breadcrumb :resourceTypeLabel="resourceTypeLabel" :resource="resource"/>
|
|
125
133
|
<Top>
|
|
126
134
|
<Title class="title">
|
|
127
|
-
<span
|
|
135
|
+
<span class="detailIcon-span">
|
|
128
136
|
<img
|
|
129
137
|
v-if="parentRouteOverride === 'account' && resource=== 'token'"
|
|
130
138
|
:src="Svg"
|
|
@@ -182,18 +190,18 @@ watch(
|
|
|
182
190
|
:options="viewOptions"
|
|
183
191
|
/>
|
|
184
192
|
<RcButton
|
|
185
|
-
v-if="
|
|
193
|
+
v-if="shouldShowConfiguration"
|
|
186
194
|
:data-testid="showConfigurationDataTestId"
|
|
187
195
|
class="show-configuration"
|
|
188
196
|
:primary="true"
|
|
189
197
|
:aria-label="i18n.t('component.resource.detail.titleBar.ariaLabel.showConfiguration', { resource: resourceName })"
|
|
190
198
|
@click="() => emit('show-configuration', showConfigurationReturnFocusSelector)"
|
|
191
199
|
>
|
|
192
|
-
|
|
200
|
+
<!-- <img
|
|
193
201
|
:src="showConfigurationIcon"
|
|
194
202
|
class="mmr-3"
|
|
195
203
|
aria-hidden="true"
|
|
196
|
-
>
|
|
204
|
+
> -->
|
|
197
205
|
{{ i18n.t('component.resource.detail.titleBar.showConfiguration') }}
|
|
198
206
|
</RcButton>
|
|
199
207
|
<ActionMenu
|
|
@@ -215,6 +223,7 @@ watch(
|
|
|
215
223
|
</template>
|
|
216
224
|
|
|
217
225
|
<style lang="scss" scoped>
|
|
226
|
+
|
|
218
227
|
.detailIcon-span{
|
|
219
228
|
width: 24px;
|
|
220
229
|
height: 24px;
|
|
@@ -223,6 +232,17 @@ watch(
|
|
|
223
232
|
background: var(--primary);
|
|
224
233
|
margin-right: 10px;
|
|
225
234
|
}
|
|
235
|
+
.detailIcon{
|
|
236
|
+
position: absolute;
|
|
237
|
+
color: #fff;
|
|
238
|
+
font-size: 38px;
|
|
239
|
+
left: 4px;
|
|
240
|
+
top: -2px;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.detailIcon-span-title{
|
|
244
|
+
font-weight: bold;
|
|
245
|
+
}
|
|
226
246
|
.resourceTypeLabelCls {
|
|
227
247
|
font-weight: 700;
|
|
228
248
|
}
|
|
@@ -253,7 +273,6 @@ watch(
|
|
|
253
273
|
flex-direction: row;
|
|
254
274
|
justify-content: center;
|
|
255
275
|
align-items: center;
|
|
256
|
-
background-color: var(--primary);
|
|
257
276
|
|
|
258
277
|
a{
|
|
259
278
|
color: #fff;
|
|
@@ -254,7 +254,7 @@ export default {
|
|
|
254
254
|
},
|
|
255
255
|
|
|
256
256
|
parent() {
|
|
257
|
-
|
|
257
|
+
let displayName = this.value?.parentNameOverride || this.$store.getters['type-map/labelFor'](this.schema);
|
|
258
258
|
const product = this.$store.getters['currentProduct'].name;
|
|
259
259
|
|
|
260
260
|
const defaultLocation = {
|
|
@@ -418,14 +418,14 @@ export default {
|
|
|
418
418
|
demoDisplay() {
|
|
419
419
|
const product = this.$store.getters['productId'];
|
|
420
420
|
|
|
421
|
-
const resources = this.location?.params?.resource || ''
|
|
421
|
+
const resources = this.location?.params?.resource || this.$route.params?.resource || ''
|
|
422
422
|
|
|
423
423
|
const productId = this.$store.getters['type-map/groupForBasicType'](this.$store.getters['productId'], resources);
|
|
424
424
|
|
|
425
425
|
if (productId === undefined) {
|
|
426
426
|
return '';
|
|
427
427
|
}
|
|
428
|
-
const parts = productId
|
|
428
|
+
const parts = productId?.split('::') || [];
|
|
429
429
|
const newString = 'root';
|
|
430
430
|
|
|
431
431
|
if (!parts?.includes(newString)) {
|
|
@@ -441,9 +441,10 @@ export default {
|
|
|
441
441
|
menuIcon() {
|
|
442
442
|
const product = this.$store.getters['productId'];
|
|
443
443
|
|
|
444
|
-
const resources = this.location?.params?.resource || ''
|
|
444
|
+
const resources = this.location?.params?.resource || this.$route.params?.resource || ''
|
|
445
445
|
|
|
446
|
-
|
|
446
|
+
|
|
447
|
+
return this.$store.getters['type-map/groupsForVirTypes'](product, resources) || 'default menuIcon';
|
|
447
448
|
},
|
|
448
449
|
|
|
449
450
|
location() {
|
|
@@ -506,7 +507,7 @@ export default {
|
|
|
506
507
|
<span>/</span>
|
|
507
508
|
</span>
|
|
508
509
|
<span class="excram-last-name">
|
|
509
|
-
{{ (realMode === 'view'? '查看': realMode === 'edit' ? '编辑':'创建') + parent
|
|
510
|
+
{{ (realMode === 'view'? '查看': realMode === 'edit' ? '编辑':'创建') + parent?.displayName }}
|
|
510
511
|
</span>
|
|
511
512
|
</div>
|
|
512
513
|
<header>
|
|
@@ -530,7 +531,7 @@ export default {
|
|
|
530
531
|
:class="'icon-'+ menuIcon + ' detailIcon'"
|
|
531
532
|
/>
|
|
532
533
|
</span>
|
|
533
|
-
<span class="detailIcon-span-title">{{ realMode=== 'create'? '创建': '' }}{{ parent
|
|
534
|
+
<span class="detailIcon-span-title">{{ realMode=== 'create'? '创建': '' }}{{ parent?.displayName }}{{ realMode=== 'create'? '': '名称:' }}</span>
|
|
534
535
|
<span v-if="realMode !== 'create'">
|
|
535
536
|
<span v-if="value.detailPageHeaderActionOverride && value.detailPageHeaderActionOverride(realMode)">{{ value.detailPageHeaderActionOverride(realMode) }}</span>
|
|
536
537
|
<t
|
|
@@ -523,21 +523,21 @@ export default {
|
|
|
523
523
|
/>
|
|
524
524
|
|
|
525
525
|
<component
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
526
|
+
:is="showComponent"
|
|
527
|
+
v-else
|
|
528
|
+
ref="comp"
|
|
529
|
+
v-model:value="value"
|
|
530
|
+
v-bind="$data"
|
|
531
|
+
:done-params="doneParams"
|
|
532
|
+
:done-route="doneRoute"
|
|
533
|
+
:mode="mode"
|
|
534
|
+
:initial-value="initialModel"
|
|
535
|
+
:live-value="liveModel"
|
|
536
|
+
:real-mode="realMode"
|
|
537
|
+
:class="{'flex-content': flexContent}"
|
|
538
|
+
@update:value="$emit('input', $event)"
|
|
539
|
+
@update:mode="setMode"
|
|
540
|
+
@set-subtype="setSubtype"
|
|
541
541
|
/>
|
|
542
542
|
|
|
543
543
|
<button
|