dashboard-shell-shell 1.0.1000000116 → 1.0.1000000117

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 (124) hide show
  1. package/assets/images/action.svg +6 -0
  2. package/assets/images/pl/logo.png +0 -0
  3. package/assets/styles/base/_functions.scss +0 -0
  4. package/assets/styles/base/_mixins.scss +1 -1
  5. package/assets/styles/global/_button.scss +17 -10
  6. package/assets/styles/global/_form.scss +2 -2
  7. package/assets/styles/global/_labeled-input.scss +6 -2
  8. package/assets/styles/global/_select.scss +6 -7
  9. package/assets/styles/global/_table.scss +3 -2
  10. package/assets/styles/global/_tooltip.scss +8 -1
  11. package/assets/styles/themes/_dark.scss +2 -0
  12. package/assets/styles/themes/_light.scss +5 -2
  13. package/assets/styles/vendor/vue-select.scss +2 -1
  14. package/assets/translations/en-us.yaml +1 -3
  15. package/assets/translations/zh-hans.yaml +51 -28
  16. package/components/ActionDropdown.vue +1 -0
  17. package/components/ActionMenuShell.vue +6 -3
  18. package/components/BrandImage.vue +22 -0
  19. package/components/ClusterIconMenu.vue +1 -1
  20. package/components/CodeMirror.vue +1 -0
  21. package/components/CruResource.vue +1 -1
  22. package/components/CruResourceFooter.vue +1 -1
  23. package/components/ExplorerProjectsNamespaces.vue +4 -24
  24. package/components/GlobalRoleBindings.vue +112 -48
  25. package/components/IndentedPanel.vue +4 -10
  26. package/components/PromptRemove.vue +3 -3
  27. package/components/ResourceDetail/Masthead.vue +190 -242
  28. package/components/ResourceDetail/index.vue +20 -5
  29. package/components/ResourceList/Masthead.vue +146 -84
  30. package/components/ResourceList/ResourceLoadingIndicator.vue +5 -2
  31. package/components/ResourceTable.vue +76 -1
  32. package/components/SideNav.vue +66 -29
  33. package/components/SortableTable/THead.vue +6 -0
  34. package/components/SortableTable/index.vue +481 -388
  35. package/components/Tabbed/index.vue +4 -5
  36. package/components/auth/Principal.vue +3 -2
  37. package/components/auth/RoleDetailEdit.vue +58 -5
  38. package/components/auth/SelectPrincipal.vue +1 -0
  39. package/components/form/BannerSettings.vue +18 -16
  40. package/components/form/ChangePassword.vue +4 -4
  41. package/components/form/ColorInput.vue +32 -8
  42. package/components/form/Footer.vue +1 -1
  43. package/components/form/InputWithSelect.vue +2 -0
  44. package/components/form/KeyValue.vue +31 -7
  45. package/components/form/LabeledSelect.vue +178 -178
  46. package/components/form/Members/ClusterPermissionsEditor.vue +1 -2
  47. package/components/form/Members/MembershipEditor.vue +1 -1
  48. package/components/form/NameNsDescription.vue +24 -11
  49. package/components/form/Password.vue +6 -2
  50. package/components/form/ResourceQuota/Namespace.vue +1 -1
  51. package/components/form/ResourceQuota/NamespaceRow.vue +13 -10
  52. package/components/form/ResourceQuota/ProjectRow.vue +0 -1
  53. package/components/form/Select.vue +2 -2
  54. package/components/nav/Favorite.vue +5 -1
  55. package/components/nav/Group.vue +69 -23
  56. package/components/nav/Header.vue +82 -17
  57. package/components/nav/HeaderPageActionMenu.vue +1 -0
  58. package/components/nav/NamespaceFilter.vue +0 -3
  59. package/components/nav/TopLevelMenu.vue +182 -119
  60. package/components/nav/Type.vue +48 -11
  61. package/composables/useClickOutside.ts +1 -1
  62. package/config/product/auth.js +16 -7
  63. package/config/product/explorer.js +1 -1
  64. package/config/product/settings.js +17 -8
  65. package/config/settings.ts +28 -0
  66. package/edit/management.cattle.io.user.vue +17 -4
  67. package/edit/networking.k8s.io.ingress/RulePath.vue +1 -1
  68. package/edit/token.vue +1 -1
  69. package/list/harvesterhci.io.management.cluster.vue +17 -0
  70. package/list/management.cattle.io.setting.vue +22 -13
  71. package/list/management.cattle.io.user.vue +25 -14
  72. package/list/provisioning.cattle.io.cluster.vue +6 -7
  73. package/mixins/brand.js +17 -0
  74. package/package.json +1 -1
  75. package/pages/auth/login.vue +84 -29
  76. package/pages/c/_cluster/auth/roles/index.vue +61 -14
  77. package/pages/c/_cluster/settings/banners.vue +174 -101
  78. package/pages/c/_cluster/settings/brand.vue +348 -301
  79. package/pages/c/_cluster/settings/performance.vue +61 -38
  80. package/pages/home.vue +70 -21
  81. package/pages/prefs.vue +25 -23
  82. package/pkg/tsconfig.json +9 -9
  83. package/pkg/vue.config.js +1 -1
  84. package/promptRemove/mixin/roleDeletionCheck.js +2 -2
  85. package/scripts/clean +0 -0
  86. package/scripts/extension/bundle +0 -0
  87. package/scripts/extension/helm/scripts/package +0 -0
  88. package/scripts/extension/helm/scripts/patch +0 -0
  89. package/scripts/extension/helm/scripts/version +0 -0
  90. package/scripts/extension/helmpatch +0 -0
  91. package/scripts/extension/parse-tag-name +0 -0
  92. package/scripts/extension/publish +0 -0
  93. package/scripts/publish-shell.sh +86 -60
  94. package/scripts/serve-pkgs +0 -0
  95. package/scripts/sync-shell-deps +0 -0
  96. package/scripts/typegen.sh +44 -28
  97. package/store/i18n.js +5 -5
  98. package/store/prefs.js +17 -5
  99. package/store/type-map.js +2 -1
  100. package/types/shell/index.d.ts +1 -1
  101. package/utils/error.js +4 -0
  102. package/utils/router.js +3 -3
  103. package/vue.config.js +1 -6
  104. package/components/rancherResourceDetail/Masthead.vue +0 -769
  105. package/components/rancherResourceDetail/__tests__/Masthead.test.ts +0 -65
  106. package/components/rancherResourceDetail/index.vue +0 -591
  107. package/components/rancherResourceList/Masthead.vue +0 -375
  108. package/components/rancherResourceList/ResourceLoadingIndicator.vue +0 -140
  109. package/components/rancherResourceList/index.vue +0 -307
  110. package/components/rancherResourceList/resource-list.config.js +0 -7
  111. package/components/rancherResourceTable.vue +0 -783
  112. package/components/rancherSortableTable/THead.vue +0 -561
  113. package/components/rancherSortableTable/actions.js +0 -153
  114. package/components/rancherSortableTable/advanced-filtering.js +0 -272
  115. package/components/rancherSortableTable/debug.js +0 -117
  116. package/components/rancherSortableTable/filtering.js +0 -290
  117. package/components/rancherSortableTable/grouping.js +0 -48
  118. package/components/rancherSortableTable/index.vue +0 -2712
  119. package/components/rancherSortableTable/paging.js +0 -155
  120. package/components/rancherSortableTable/selection.js +0 -629
  121. package/components/rancherSortableTable/sortable-config.ts +0 -4
  122. package/components/rancherSortableTable/sorting.js +0 -129
  123. package/types/cloud-shell/index.d.ts +0 -11014
  124. /package/components/{rancherResourceList → ResourceList}/Masthead-btn.vue +0 -0
@@ -1,769 +0,0 @@
1
- <script>
2
- import { KUBERNETES, PROJECT } from '@shell/config/labels-annotations';
3
- import { FLEET, NAMESPACE, MANAGEMENT, HELM } from '@shell/config/types';
4
- import ButtonGroup from '@shell/components/ButtonGroup';
5
- // import { BadgeState } from '@components/BadgeState';
6
- import DotState from '@shell/components/DotState.vue';
7
- import { Banner } from '@components/Banner';
8
- import { get } from '@shell/utils/object';
9
- import { NAME as FLEET_NAME } from '@shell/config/product/fleet';
10
- import { HIDE_SENSITIVE } from '@shell/store/prefs';
11
- import {
12
- AS, _DETAIL, _CONFIG, _YAML, MODE, _CREATE, _EDIT, _VIEW, _UNFLAG, _GRAPH
13
- } from '@shell/config/query-params';
14
- import { ExtensionPoint, PanelLocation } from '@shell/core/types';
15
- import ExtensionPanel from '@shell/components/ExtensionPanel';
16
- import TabTitle from '@shell/components/TabTitle';
17
- import ActionMenu from '@shell/components/ActionMenuShell.vue';
18
- import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
19
- import { useStore } from 'vuex';
20
- import { harvesterhci2cloud, cloud2harvesterhci } from '@shell/utils/router'
21
-
22
- // i18n-uses resourceDetail.header.*
23
-
24
- /**
25
- * Resource Detail Masthead component.
26
- *
27
- * ToDo: this component seem to be picking up a lot of logic from special cases, could be simplified down to parameters and then customized per use-case via wrapper component
28
- */
29
- export default {
30
-
31
- name: 'MastheadResourceDetail',
32
-
33
- components: {
34
- // BadgeState,
35
- DotState,
36
- Banner,
37
- ButtonGroup,
38
- ExtensionPanel,
39
- TabTitle,
40
- ActionMenu,
41
- },
42
- props: {
43
- value: {
44
- type: Object,
45
- default: () => {
46
- return {};
47
- }
48
- },
49
-
50
- mode: {
51
- type: String,
52
- default: 'create'
53
- },
54
-
55
- realMode: {
56
- type: String,
57
- default: 'create'
58
- },
59
-
60
- as: {
61
- type: String,
62
- default: _YAML,
63
- },
64
-
65
- hasGraph: {
66
- type: Boolean,
67
- default: false
68
- },
69
-
70
- hasDetail: {
71
- type: Boolean,
72
- default: false
73
- },
74
-
75
- hasEdit: {
76
- type: Boolean,
77
- default: false
78
- },
79
-
80
- storeOverride: {
81
- type: String,
82
- default: null,
83
- },
84
-
85
- resource: {
86
- type: String,
87
- default: null,
88
- },
89
-
90
- resourceSubtype: {
91
- type: String,
92
- default: null,
93
- },
94
-
95
- parentRouteOverride: {
96
- type: String,
97
- default: null,
98
- },
99
-
100
- canViewYaml: {
101
- type: Boolean,
102
- default: false,
103
- }
104
- },
105
-
106
- setup() {
107
- const store = useStore();
108
- const { featureDropdownMenu } = useRuntimeFlag(store);
109
-
110
- return { featureDropdownMenu };
111
- },
112
-
113
- data() {
114
- return {
115
- DETAIL_VIEW: _DETAIL,
116
- extensionType: ExtensionPoint.PANEL,
117
- extensionLocation: PanelLocation.DETAILS_MASTHEAD,
118
- Svg: require('~shell/assets/images/API.svg')
119
- };
120
- },
121
-
122
- computed: {
123
- dev() {
124
- return this.$store.getters['prefs/dev'];
125
- },
126
-
127
- schema() {
128
- const inStore = this.storeOverride || this.$store.getters['currentStore'](this.resource);
129
-
130
- return this.$store.getters[`${ inStore }/schemaFor`]( this.resource );
131
- },
132
-
133
- isView() {
134
- return this.mode === _VIEW;
135
- },
136
-
137
- isEdit() {
138
- return this.mode === _EDIT;
139
- },
140
-
141
- isCreate() {
142
- return this.mode === _CREATE;
143
- },
144
-
145
- isNamespace() {
146
- return this.schema?.id === NAMESPACE;
147
- },
148
-
149
- isProject() {
150
- return this.schema?.id === MANAGEMENT.PROJECT;
151
- },
152
-
153
- isProjectHelmChart() {
154
- return this.schema?.id === HELM.PROJECTHELMCHART;
155
- },
156
-
157
- hasMultipleNamespaces() {
158
- return !!this.value.namespaces;
159
- },
160
-
161
- namespace() {
162
- if (this.value?.metadata?.namespace) {
163
- return this.value?.metadata?.namespace;
164
- }
165
-
166
- return null;
167
- },
168
-
169
- detailsAction() {
170
- return this.value?.detailsAction;
171
- },
172
-
173
- shouldHifenize() {
174
- return (this.mode === 'view' || this.mode === 'edit') && this.resourceSubtype?.length && this.value?.nameDisplay?.length;
175
- },
176
-
177
- namespaceLocation() {
178
- if (!this.isNamespace) {
179
- return this.value.namespaceLocation || {
180
- name: 'c-cluster-product-resource-id',
181
- params: {
182
- cluster: this.$route.params.cluster,
183
- product: this.$store.getters['productId'],
184
- resource: NAMESPACE,
185
- id: this.$route.params.namespace
186
- }
187
- };
188
- }
189
-
190
- return null;
191
- },
192
-
193
- isWorkspace() {
194
- return this.$store.getters['productId'] === FLEET_NAME && !!this.value?.metadata?.namespace;
195
- },
196
-
197
- workspaceLocation() {
198
- return {
199
- name: 'c-cluster-product-resource-id',
200
- params: {
201
- cluster: this.$route.params.cluster,
202
- product: this.$store.getters['productId'],
203
- resource: FLEET.WORKSPACE,
204
- id: this.$route.params.namespace
205
- }
206
- };
207
- },
208
-
209
- project() {
210
- if (this.isNamespace) {
211
- const cluster = this.$store.getters['currentCluster'];
212
-
213
- if (cluster) {
214
- const id = (this.value?.metadata?.labels || {})[PROJECT];
215
-
216
- return this.$store.getters['management/byId'](MANAGEMENT.PROJECT, `${ cluster.id }/${ id }`);
217
- }
218
- }
219
-
220
- return null;
221
- },
222
-
223
- banner() {
224
- if (this.value?.stateObj?.error) {
225
- const defaultErrorMessage = this.t('resourceDetail.masthead.defaultBannerMessage.error', undefined, true);
226
-
227
- return {
228
- color: 'error',
229
- message: this.value.stateObj.message || defaultErrorMessage
230
- };
231
- }
232
-
233
- if (this.value?.spec?.paused) {
234
- return {
235
- color: 'info',
236
- message: this.t('asyncButton.pause.description')
237
- };
238
- }
239
-
240
- if (this.value?.stateObj?.transitioning) {
241
- const defaultTransitioningMessage = this.t('resourceDetail.masthead.defaultBannerMessage.transitioning', undefined, true);
242
-
243
- return {
244
- color: 'info',
245
- message: this.value.stateObj.message || defaultTransitioningMessage
246
- };
247
- }
248
-
249
- return null;
250
- },
251
-
252
- parent() {
253
- const displayName = this.value?.parentNameOverride || this.$store.getters['type-map/labelFor'](this.schema);
254
- const product = this.$store.getters['currentProduct'].name;
255
-
256
- const defaultLocation = {
257
- name: 'c-cluster-product-resource',
258
- params: {
259
- resource: this.resource,
260
- product,
261
- }
262
- };
263
-
264
- const location = this.value?.parentLocationOverride || defaultLocation;
265
-
266
- if (this.parentRouteOverride) {
267
- location.name = this.parentRouteOverride;
268
- }
269
-
270
- const typeOptions = this.$store.getters[`type-map/optionsFor`]( this.resource );
271
- const out = {
272
- displayName, location, ...typeOptions
273
- };
274
-
275
- return out;
276
- },
277
-
278
- hideSensitiveData() {
279
- return this.$store.getters['prefs/get'](HIDE_SENSITIVE);
280
- },
281
-
282
- sensitiveOptions() {
283
- return [
284
- {
285
- tooltipKey: 'resourceDetail.masthead.sensitive.hide',
286
- icon: 'icon-hide',
287
- value: true,
288
- },
289
- {
290
- tooltipKey: 'resourceDetail.masthead.sensitive.show',
291
- icon: 'icon-show',
292
- value: false
293
- }
294
- ];
295
- },
296
-
297
- viewOptions() {
298
- const out = [];
299
-
300
- if ( this.hasDetail ) {
301
- out.push({
302
- labelKey: 'resourceDetail.masthead.detail',
303
- value: _DETAIL,
304
- });
305
- }
306
-
307
- if ( this.hasEdit && this.parent?.showConfigView !== false) {
308
- out.push({
309
- labelKey: 'resourceDetail.masthead.config',
310
- value: _CONFIG,
311
- });
312
- }
313
-
314
- if ( this.hasGraph ) {
315
- out.push({
316
- labelKey: 'resourceDetail.masthead.graph',
317
- value: _GRAPH,
318
- });
319
- }
320
-
321
- if ( this.canViewYaml ) {
322
- out.push({
323
- labelKey: 'resourceDetail.masthead.yaml',
324
- value: _YAML,
325
- });
326
- }
327
-
328
- if ( out.length < 2 ) {
329
- return null;
330
- }
331
-
332
- return out;
333
- },
334
-
335
- currentView: {
336
- get() {
337
- return this.as;
338
- },
339
-
340
- set(val) {
341
- switch ( val ) {
342
- case _DETAIL:
343
- this.$router.applyQuery({
344
- [MODE]: _UNFLAG,
345
- [AS]: _UNFLAG,
346
- });
347
- break;
348
- case _CONFIG:
349
- this.$router.applyQuery({
350
- [MODE]: _UNFLAG,
351
- [AS]: _CONFIG,
352
- });
353
- break;
354
- case _GRAPH:
355
- this.$router.applyQuery({
356
- [MODE]: _UNFLAG,
357
- [AS]: _GRAPH,
358
- });
359
- break;
360
- case _YAML:
361
- this.$router.applyQuery({
362
- [MODE]: _UNFLAG,
363
- [AS]: _YAML,
364
- });
365
- break;
366
- }
367
- },
368
- },
369
-
370
- showSensitiveToggle() {
371
- return !!this.value.hasSensitiveData && this.mode === _VIEW && this.as !== _YAML;
372
- },
373
-
374
- managedWarning() {
375
- const { value } = this;
376
- const labels = value?.metadata?.labels || {};
377
-
378
- const managedBy = labels[KUBERNETES.MANAGED_BY] || '';
379
- const appName = labels[KUBERNETES.MANAGED_NAME] || labels[KUBERNETES.INSTANCE] || '';
380
-
381
- return {
382
- show: this.mode === _EDIT && !!managedBy,
383
- type: value?.kind || '',
384
- hasName: appName ? 'yes' : 'no',
385
- appName,
386
- managedBy,
387
- };
388
- },
389
-
390
- displayName() {
391
- let displayName = this.value.nameDisplay;
392
-
393
- if (this.isProjectHelmChart) {
394
- displayName = this.value.projectDisplayName;
395
- }
396
-
397
- return this.shouldHifenize ? ` - ${ displayName }` : displayName;
398
- },
399
-
400
- demoDisplay() {
401
- const product = this.$store.getters['productId'];
402
-
403
- const productId = this.$store.getters['type-map/groupForBasicType'](this.$store.getters['productId'], this.location.params.resource);
404
-
405
- if (productId === undefined) {
406
- return '';
407
- }
408
- const parts = productId.split('::');
409
- const newString = 'root';
410
-
411
- if (!parts?.includes(newString)) {
412
- parts.unshift(newString); // 将字符串添加到数组第一位
413
- }
414
-
415
- const partsEn = parts.map((item) => {
416
- return this.$store.getters['i18n/t'](`typeLabel."${ item.toLowerCase() }"`);
417
- });
418
-
419
- return partsEn;
420
- },
421
- menuIcon() {
422
- const product = this.$store.getters['productId'];
423
-
424
- const resources = this.location?.params?.resource || ''
425
-
426
- return this.$store.getters['type-map/groupsForVirTypes'](product, resources);
427
- },
428
-
429
- location() {
430
- const { parent } = this;
431
-
432
- return parent?.location;
433
- },
434
-
435
- hideNamespaceLocation() {
436
- return this.$store.getters['currentProduct'].hideNamespaceLocation || this.value.namespaceLocation === null;
437
- },
438
-
439
- resourceExternalLink() {
440
- return this.value.resourceExternalLink;
441
- },
442
- },
443
-
444
- methods: {
445
- get,
446
-
447
- showActions() {
448
- this.$store.commit('action-menu/show', {
449
- resources: this.value,
450
- elem: this.$refs.actions,
451
- });
452
- },
453
-
454
- toggleSensitiveData(e) {
455
- this.$store.dispatch('prefs/set', { key: HIDE_SENSITIVE, value: !!e });
456
- },
457
-
458
- invokeDetailsAction() {
459
- const action = this.detailsAction;
460
-
461
- if (action) {
462
- const fn = this.value[action.action];
463
-
464
- if (fn) {
465
- fn.apply(this.value, []);
466
- }
467
- }
468
- }
469
- }
470
- };
471
- </script>
472
-
473
- <template>
474
-
475
- <!-- 顶部区域的容器 -->
476
- <div class="masthead">
477
- <div class="title">
478
-
479
- <!-- 面包屑导航(创建 API 密钥时不显示) -->
480
- <div
481
- v-if="!(parentRouteOverride === 'account' && resource=== 'token')"
482
- class="excram-list"
483
- >
484
-
485
- <!-- 遍历 demoDisplay 生成面包屑路径 -->
486
- <span
487
- v-for="(item,index) in demoDisplay"
488
- :key="index"
489
- >
490
- <span v-if="item">{{ item }}</span>
491
- <span v-if="item">/</span>
492
- </span>
493
-
494
- <!-- 最后一个面包屑显示当前操作(查看/编辑/创建)+ 父资源名称 -->
495
- <span class="excram-last-name">
496
- {{ (realMode === 'view'? '查看': realMode === 'edit' ? '编辑':'创建') + parent.displayName }}
497
- </span>
498
- </div>
499
-
500
- <header>
501
- <div class="title">
502
- <div class="primaryheader">
503
- <span class="primary-title">
504
-
505
- <!-- 图标区 -->
506
- <span v-if="menuIcon && !(parentRouteOverride === 'account' && resource=== 'token')" class="detailIcon-span">
507
- <!-- 如果是账户 API token,则显示图片,否则显示 icon -->
508
- <img
509
- v-if="parentRouteOverride === 'account' && resource=== 'token'"
510
- :src="Svg"
511
- style="margin-top: 4px; margin-left: 5px;"
512
- >
513
- <i
514
- v-else
515
- :class="'icon-'+ menuIcon + ' detailIcon'"
516
- />
517
- </span>
518
-
519
- <!-- 资源标题(创建时只显示“创建+名称”,否则显示“名称:”) -->
520
- <span class="detailIcon-span-title">{{ realMode=== 'create'? '创建': '' }}{{ parent.displayName }}{{ realMode=== 'create'? '': '名称:' }}</span>
521
-
522
- <!-- 如果不是创建模式,显示操作描述 -->
523
- <span v-if="realMode !== 'create'">
524
-
525
- <!-- 如果有覆盖方法,优先显示覆盖内容 -->
526
- <span v-if="value.detailPageHeaderActionOverride && value.detailPageHeaderActionOverride(realMode)">{{ value.detailPageHeaderActionOverride(realMode) }}</span>
527
-
528
- <!-- 否则用 t 组件国际化显示 -->
529
- <t
530
- v-else
531
- :k="'resourceDetail.header.' + realMode"
532
- :subtype="resourceSubtype"
533
- :name="displayName"
534
- :escapehtml="false"
535
- />
536
- </span>
537
-
538
- <!-- 状态点(DotState 组件) -->
539
- <DotState
540
- v-if="!isCreate && parent.showState"
541
- class="masthead-state"
542
- :value="value"
543
- />
544
-
545
- <!-- Istio 注入状态 -->
546
- <span
547
- v-if="!isCreate && value.injectionEnabled"
548
- class="masthead-istio"
549
- >
550
- <i
551
- v-clean-tooltip="t('projectNamespaces.isIstioInjectionEnabled')"
552
- class="icon icon-sm icon-istio"
553
- />
554
- </span>
555
- </span>
556
-
557
- <!-- 如果有返回路径,显示分隔符和“返回”链接 -->
558
- <span
559
- v-if="location"
560
- class="valid"
561
- >|</span>
562
- <router-link
563
- v-if="location"
564
- :to="location"
565
- >
566
- 返回
567
- </router-link>
568
- </div>
569
- </div>
570
-
571
- <!-- 右侧操作按钮区域(支持通过 slot 覆盖) -->
572
- <slot name="right">
573
- <div class="actions-container align-start" style="padding-right: 15px;">
574
- <div class="actions">
575
-
576
- <!-- 详情模式下的主操作按钮 -->
577
- <button
578
- v-if="detailsAction && currentView === DETAIL_VIEW && isView"
579
- type="button"
580
- class="btn role-primary actions mr-10"
581
- :disabled="!detailsAction.enabled"
582
- @click="invokeDetailsAction"
583
- >
584
- {{ detailsAction.label }}
585
- </button>
586
-
587
- <!-- 敏感信息显示/隐藏切换 -->
588
- <ButtonGroup
589
- v-if="showSensitiveToggle"
590
- :value="!!hideSensitiveData"
591
- icon-size="lg"
592
- :options="sensitiveOptions"
593
- class="mr-10"
594
- @update:value="toggleSensitiveData"
595
- />
596
-
597
- <!-- 视图切换按钮 -->
598
- <ButtonGroup
599
- v-if="viewOptions && isView"
600
- v-model:value="currentView"
601
- :options="viewOptions"
602
- class="mr-10"
603
- />
604
-
605
- <!-- 功能菜单:优先使用 ActionMenu 组件 -->
606
- <template v-if="featureDropdownMenu">
607
- <ActionMenu
608
- v-if="isView"
609
- button-role="multiAction"
610
- button-size="compact"
611
- :resource="value"
612
- data-testid="masthead-action-menu"
613
- />
614
- </template>
615
-
616
- <!-- 如果没有 featureDropdownMenu,则使用普通的多操作按钮 -->
617
- <template v-else>
618
- <button
619
- v-if="isView"
620
- ref="actions"
621
- data-testid="masthead-action-menu"
622
- aria-haspopup="true"
623
- type="button"
624
- class="btn role-multi-action actions"
625
- @click="showActions"
626
- >
627
- <i class="icon icon-actions" />
628
- </button>
629
- </template>
630
- </div>
631
- </div>
632
- </slot>
633
- </header>
634
-
635
- <!-- 扩展区域 -->
636
- <ExtensionPanel
637
- :resource="value"
638
- :type="extensionType"
639
- :location="extensionLocation"
640
- />
641
-
642
- <!-- 顶部状态 Banner -->
643
- <Banner
644
- v-if="banner && isView && !parent.hideBanner"
645
- class="state-banner mb-10"
646
- :color="banner.color"
647
- :label="banner.message"
648
- />
649
-
650
- <!-- 管理警告 Banner -->
651
- <Banner
652
- v-if="managedWarning.show"
653
- color="warning"
654
- class="mb-20"
655
- :label="t('resourceDetail.masthead.managedWarning', managedWarning)"
656
- />
657
-
658
- <!-- 内容插槽 -->
659
- <slot />
660
- </div>
661
- </div>
662
- </template>
663
-
664
- <style lang='scss' scoped>
665
- .masthead {
666
- padding-bottom: 10px;
667
- /* border-bottom: 1px solid var(--border); */
668
- margin-bottom: 10px;
669
- }
670
-
671
- HEADER {
672
- margin: 0;
673
- }
674
-
675
- .primaryheader {
676
- display: flex;
677
- flex-direction: row;
678
- align-items: center;
679
- font-size:14px;
680
- height: 50px;
681
-
682
- h1 {
683
- margin: 0;
684
- }
685
- }
686
-
687
- .subheader{
688
- display: flex;
689
- flex-direction: row;
690
- color: var(--input-label);
691
- & > * {
692
- margin: 5px 20px 5px 0px;
693
- }
694
-
695
- .live-data {
696
- color: var(--body-text)
697
- }
698
- }
699
-
700
- .state-banner {
701
- margin: 3px 0 0 0;
702
- }
703
-
704
- .masthead-state {
705
- font-size: initial;
706
- display: inline-block;
707
- position: relative;
708
- /* top: -2px; */
709
- font-size: 12px;
710
- margin-left: 5px;
711
- }
712
-
713
- .masthead-istio {
714
- .icon {
715
- vertical-align: middle;
716
- color: var(--primary);
717
- }
718
- }
719
-
720
- .left-right-split {
721
- display: grid;
722
- align-items: center;
723
-
724
- .left-half {
725
- grid-column: 1;
726
- }
727
-
728
- .right-half {
729
- grid-column: 2;
730
- }
731
- }
732
-
733
- .resource-external {
734
- font-size: 18px;
735
- }
736
- .excram-list{
737
- font-size: 14px;
738
- margin-bottom: 20px;
739
- }
740
- .excram-last-name{
741
- color: var(--link);
742
- }
743
- .valid{
744
- color: #d7d7d7;
745
- margin: 0px 10px;
746
- }
747
- .detailIcon-span{
748
- width: 24px;
749
- height: 24px;
750
- display: inline-block;
751
- position: relative;
752
- background: var(--primary);
753
- margin-right: 10px;
754
- }
755
- .detailIcon{
756
- position: absolute;
757
- color: #fff;
758
- font-size: 38px;
759
- left: 4px;
760
- top: -2px;
761
- }
762
- .primary-title{
763
- display: flex;
764
- align-items: center;
765
- }
766
- .detailIcon-span-title{
767
- font-weight: bold;
768
- }
769
- </style>