dashboard-shell-shell 3.0.5-test.3 → 3.0.5-test.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 (30) hide show
  1. package/assets/styles/global/_button.scss +7 -7
  2. package/assets/styles/global/_tooltip.scss +4 -4
  3. package/assets/styles/themes/_light.scss +3 -1
  4. package/assets/translations/zh-hans.yaml +76 -0
  5. package/components/ActionDropdown.vue +1 -1
  6. package/components/CopyToClipboard.vue +15 -0
  7. package/components/Drawer/Chrome.vue +2 -2
  8. package/components/Drawer/ResourceDetailDrawer/ConfigTab.vue +23 -23
  9. package/components/Drawer/ResourceDetailDrawer/index.vue +2 -2
  10. package/components/ExplorerMembers.vue +18 -3
  11. package/components/PodSecurityAdmission.vue +1 -1
  12. package/components/Resource/Detail/Metadata/IdentifyingInformation/index.vue +1 -3
  13. package/components/Resource/Detail/Metadata/KeyValue.vue +8 -4
  14. package/components/Resource/Detail/Metadata/index.vue +2 -1
  15. package/components/Resource/Detail/TitleBar/Title.vue +4 -3
  16. package/components/Resource/Detail/TitleBar/index.vue +103 -24
  17. package/components/ResourceDetail/Masthead/legacy.vue +235 -164
  18. package/components/ResourceDetail/legacy.vue +29 -13
  19. package/components/SortableTable/index.vue +1 -1
  20. package/components/Tabbed/index.vue +1 -1
  21. package/components/auth/Principal.vue +35 -11
  22. package/components/breadcrumb/index.vue +340 -0
  23. package/components/form/LabeledSelect.vue +3 -2
  24. package/components/form/Taints.vue +2 -1
  25. package/components/form/WorkloadPorts.vue +143 -123
  26. package/edit/workload/index.vue +3 -3
  27. package/package.json +1 -1
  28. package/rancher-components/BadgeState/BadgeState.vue +33 -52
  29. package/rancher-components/RcDropdown/RcDropdownMenu.vue +8 -7
  30. package/store/i18n.js +3 -0
@@ -254,7 +254,7 @@ export default {
254
254
  },
255
255
 
256
256
  parent() {
257
- let displayName = this.value?.parentNameOverride || this.$store.getters['type-map/labelFor'](this.schema);
257
+ const 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 = {
@@ -491,192 +491,263 @@ export default {
491
491
  </script>
492
492
 
493
493
  <template>
494
-
495
- <!-- 顶部区域的容器 -->
496
494
  <div class="masthead">
497
495
  <div class="title">
498
-
499
- <!-- 面包屑导航(创建 API 密钥时不显示) -->
500
- <!-- <div
496
+ <!-- 创建api密钥不需要面包屑 -->
497
+ <div
501
498
  v-if="!(parentRouteOverride === 'account' && resource=== 'token')"
502
499
  class="excram-list"
503
500
  >
504
-
505
- 遍历 demoDisplay 生成面包屑路径
506
501
  <span
507
502
  v-for="(item,index) in demoDisplay"
508
503
  :key="index"
509
504
  >
510
- <span v-if="item">{{ item }}</span>
511
- <span v-if="item">/</span>
505
+ <span>{{ item }}</span>
506
+ <span>/</span>
512
507
  </span>
513
-
514
- 最后一个面包屑显示当前操作(查看/编辑/创建)+ 父资源名称
515
508
  <span class="excram-last-name">
516
509
  {{ (realMode === 'view'? '查看': realMode === 'edit' ? '编辑':'创建') + parent.displayName }}
517
510
  </span>
518
- </div> -->
519
-
520
- <header>
521
- <div class="title">
522
- <div class="primaryheader">
523
- <span class="primary-title">
524
-
525
- <!-- 图标区 -->
526
- <span v-if="menuIcon && !(parentRouteOverride === 'account' && resource=== 'token')" class="detailIcon-span">
527
- <!-- 如果是账户 API token,则显示图片,否则显示 icon -->
528
- <img
529
- v-if="parentRouteOverride === 'account' && resource=== 'token'"
530
- :src="Svg"
531
- style="margin-top: 4px; margin-left: 5px;"
532
- >
533
- <i
534
- v-else
535
- :class="'icon-'+ menuIcon + ' detailIcon'"
536
- />
537
- </span>
538
-
539
- <!-- 资源标题(创建时只显示“创建+名称”,否则显示“名称:”) -->
540
- <span class="detailIcon-span-title">{{ realMode=== 'create'? '创建': '' }}{{ parent.displayName }}{{ realMode=== 'create'? '': '名称:' }}</span>
541
-
542
- <!-- 如果不是创建模式,显示操作描述 -->
543
- <span v-if="realMode !== 'create'">
544
-
545
- <!-- 如果有覆盖方法,优先显示覆盖内容 -->
546
- <span v-if="value.detailPageHeaderActionOverride && value.detailPageHeaderActionOverride(realMode)">{{ value.detailPageHeaderActionOverride(realMode) }}</span>
547
-
548
- <!-- 否则用 t 组件国际化显示 -->
549
- <t
550
- v-else
551
- :k="'resourceDetail.header.' + realMode"
552
- :subtype="resourceSubtype"
553
- :name="displayName"
554
- :escapehtml="false"
555
- />
556
- </span>
557
-
558
- <!-- 状态点(DotState 组件) -->
559
- <DotState
560
- v-if="!isCreate && parent.showState"
561
- class="masthead-state"
562
- :value="value"
563
- />
564
-
565
- <!-- Istio 注入状态 -->
566
- <span
567
- v-if="!isCreate && value.injectionEnabled"
568
- class="masthead-istio"
511
+ </div>
512
+ <header>
513
+ <div class="title">
514
+ <div class="primaryheader">
515
+ <span class="primary-title">
516
+ <!-- <nuxt-link
517
+ v-if="location"
518
+ :to="location"
519
+ >
520
+ {{ parent.displayName }}:
521
+ </nuxt-link> -->
522
+ <span class="detailIcon-span">
523
+ <img
524
+ v-if="parentRouteOverride === 'account' && resource=== 'token'"
525
+ :src="Svg"
526
+ style="margin-top: 4px; margin-left: 5px;"
569
527
  >
570
- <i
571
- v-clean-tooltip="t('projectNamespaces.isIstioInjectionEnabled')"
572
- class="icon icon-sm icon-istio"
573
- />
574
- </span>
528
+ <i
529
+ v-else
530
+ :class="'icon-'+ menuIcon + ' detailIcon'"
531
+ />
575
532
  </span>
576
-
577
- <!-- 如果有返回路径,显示分隔符和“返回”链接 -->
533
+ <span class="detailIcon-span-title">{{ realMode=== 'create'? '创建': '' }}{{ parent.displayName }}{{ realMode=== 'create'? '': '名称:' }}</span>
534
+ <span v-if="realMode !== 'create'">
535
+ <span v-if="value.detailPageHeaderActionOverride && value.detailPageHeaderActionOverride(realMode)">{{ value.detailPageHeaderActionOverride(realMode) }}</span>
536
+ <t
537
+ v-else
538
+ :k="'resourceDetail.header.' + realMode"
539
+ :subtype="resourceSubtype"
540
+ :name="displayName"
541
+ :escapehtml="false"
542
+ />
543
+ </span>
544
+ <DotState
545
+ v-if="!isCreate && parent.showState"
546
+ class="masthead-state"
547
+ :value="value"
548
+ />
578
549
  <span
579
- v-if="location"
580
- class="valid"
581
- >|</span>
582
- <router-link
583
- v-if="location"
584
- :to="location"
550
+ v-if="!isCreate && value.injectionEnabled"
551
+ class="masthead-istio"
585
552
  >
586
- 返回
587
- </router-link>
588
- </div>
553
+ <i
554
+ v-clean-tooltip="t('projectNamespaces.isIstioInjectionEnabled')"
555
+ class="icon icon-sm icon-istio"
556
+ />
557
+ </span>
558
+ </span>
559
+ <span
560
+ v-if="location"
561
+ class="valid"
562
+ >|</span>
563
+ <router-link
564
+ v-if="location"
565
+ :to="location"
566
+ >
567
+ 返回
568
+ </router-link>
569
+ <!-- <h1>
570
+ <TabTitle
571
+ v-if="isCreate"
572
+ :showChild="false"
573
+ >
574
+ {{ parent.displayName }}
575
+ </TabTitle>
576
+ <TabTitle
577
+ v-else
578
+ :showChild="false"
579
+ >
580
+ {{ displayName }}
581
+ </TabTitle>
582
+ <router-link
583
+ v-if="location"
584
+ :to="location"
585
+ role="link"
586
+ class="masthead-resource-list-link"
587
+ :aria-label="parent.displayName"
588
+ >
589
+ {{ parent.displayName }}:
590
+ </router-link>
591
+ <span v-else>{{ parent.displayName }}:</span>
592
+ <span v-if="value?.detailPageHeaderActionOverride && value?.detailPageHeaderActionOverride(realMode)">{{ value?.detailPageHeaderActionOverride(realMode) }}</span>
593
+ <t
594
+ v-else
595
+ class="masthead-resource-title"
596
+ :k="'resourceDetail.header.' + realMode"
597
+ :subtype="resourceSubtype"
598
+ :name="displayName"
599
+ :escapehtml="false"
600
+ />
601
+ <BadgeState
602
+ v-if="!isCreate && parent.showState"
603
+ class="masthead-state"
604
+ :value="value"
605
+ />
606
+ <span
607
+ v-if="!isCreate && value.injectionEnabled"
608
+ class="masthead-istio"
609
+ >
610
+ <i
611
+ v-clean-tooltip="t('projectNamespaces.isIstioInjectionEnabled')"
612
+ class="icon icon-sm icon-istio"
613
+ />
614
+ </span>
615
+ <a
616
+ v-if="dev && !!resourceExternalLink"
617
+ v-clean-tooltip="t(resourceExternalLink.tipsKey || 'generic.resourceExternalLinkTips')"
618
+ class="resource-external"
619
+ rel="nofollow noopener noreferrer"
620
+ target="_blank"
621
+ :href="resourceExternalLink.url"
622
+ >
623
+ <i class="icon icon-external-link" />
624
+ </a>
625
+ </h1> -->
589
626
  </div>
590
-
591
- <!-- 右侧操作按钮区域(支持通过 slot 覆盖) -->
592
- <slot name="right">
593
- <div class="actions-container align-start" style="padding-right: 15px;">
594
- <div class="actions">
595
-
596
- <!-- 详情模式下的主操作按钮 -->
627
+ <!-- <div
628
+ v-if="!isCreate"
629
+ class="subheader"
630
+ >
631
+ <span v-if="isNamespace && project">{{ t("resourceDetail.masthead.project") }}: <router-link :to="project.detailLocation">{{ project.nameDisplay }}</router-link></span>
632
+ <span v-else-if="isWorkspace">{{ t("resourceDetail.masthead.workspace") }}: <router-link :to="workspaceLocation">{{ namespace }}</router-link></span>
633
+ <span v-else-if="namespace && !hasMultipleNamespaces">
634
+ {{ t("resourceDetail.masthead.namespace") }}:
635
+ <router-link
636
+ v-if="!hideNamespaceLocation"
637
+ :to="namespaceLocation"
638
+ data-testid="masthead-subheader-namespace"
639
+ >
640
+ {{ namespace }}
641
+ </router-link>
642
+ <span v-else>
643
+ {{ namespace }}
644
+ </span>
645
+ </span>
646
+ <span v-if="parent.showAge">
647
+ {{ t("resourceDetail.masthead.age") }}:
648
+ <LiveDate
649
+ class="live-date"
650
+ :value="value.creationTimestamp"
651
+ />
652
+ </span>
653
+ <span
654
+ v-if="value.showCreatedBy"
655
+ data-testid="masthead-subheader-createdBy"
656
+ >
657
+ {{ t("resourceDetail.masthead.createdBy") }}:
658
+ <router-link
659
+ v-if="value.createdBy.location"
660
+ :to="value.createdBy.location"
661
+ data-testid="masthead-subheader-createdBy-link"
662
+ >
663
+ {{ value.createdBy.displayName }}
664
+ </router-link>
665
+ <span
666
+ v-else
667
+ data-testid="masthead-subheader-createdBy_plain-text"
668
+ >
669
+ {{ value.createdBy.displayName }}
670
+ </span>
671
+ </span>
672
+ <span v-if="value.showPodRestarts">{{ t("resourceDetail.masthead.restartCount") }}:<span class="live-data"> {{ value.restartCount }}</span></span>
673
+ </div> -->
674
+ </div>
675
+ <slot name="right">
676
+ <div class="actions-container align-start">
677
+ <div class="actions">
678
+ <button
679
+ v-if="detailsAction && currentView === DETAIL_VIEW && isView"
680
+ type="button"
681
+ class="btn role-primary actions mr-10"
682
+ :disabled="!detailsAction.enabled"
683
+ @click="invokeDetailsAction"
684
+ >
685
+ {{ detailsAction.label }}
686
+ </button>
687
+ <ButtonGroup
688
+ v-if="showSensitiveToggle"
689
+ :value="!!hideSensitiveData"
690
+ icon-size="lg"
691
+ :options="sensitiveOptions"
692
+ class="mr-10"
693
+ @update:value="toggleSensitiveData"
694
+ />
695
+
696
+ <ButtonGroup
697
+ v-if="viewOptions && isView"
698
+ v-model:value="currentView"
699
+ :options="viewOptions"
700
+ class="mr-10"
701
+ />
702
+
703
+ <template v-if="featureDropdownMenu">
704
+ <ActionMenu
705
+ v-if="isView"
706
+ button-role="multiAction"
707
+ button-size="compact"
708
+ :resource="value"
709
+ data-testid="masthead-action-menu"
710
+ />
711
+ </template>
712
+ <template v-else>
597
713
  <button
598
- v-if="detailsAction && currentView === DETAIL_VIEW && isView && isManuallyHide"
714
+ v-if="isView"
715
+ ref="actions"
716
+ data-testid="masthead-action-menu"
717
+ aria-haspopup="true"
599
718
  type="button"
600
- class="btn role-primary actions mr-10"
601
- :disabled="!detailsAction.enabled"
602
- @click="invokeDetailsAction"
719
+ class="btn role-multi-action actions"
720
+ @click="showActions"
603
721
  >
604
- {{ detailsAction.label }}
722
+ <i class="icon icon-actions" />
605
723
  </button>
606
-
607
- <!-- 敏感信息显示/隐藏切换 -->
608
- <ButtonGroup
609
- v-if="showSensitiveToggle"
610
- :value="!!hideSensitiveData"
611
- icon-size="lg"
612
- :options="sensitiveOptions"
613
- class="mr-10"
614
- @update:value="toggleSensitiveData"
615
- />
616
-
617
- <!-- 视图切换按钮 -->
618
- <ButtonGroup
619
- v-if="viewOptions && isView"
620
- v-model:value="currentView"
621
- :options="viewOptions"
622
- class="mr-10"
623
- />
624
-
625
- <!-- 功能菜单:优先使用 ActionMenu 组件 -->
626
- <template v-if="featureDropdownMenu">
627
- <ActionMenu
628
- v-if="isView"
629
- button-role="multiAction"
630
- button-size="compact"
631
- :resource="value"
632
- data-testid="masthead-action-menu"
633
- />
634
- </template>
635
-
636
- <!-- 如果没有 featureDropdownMenu,则使用普通的多操作按钮 -->
637
- <template v-else>
638
- <button
639
- v-if="isView"
640
- ref="actions"
641
- data-testid="masthead-action-menu"
642
- aria-haspopup="true"
643
- type="button"
644
- class="btn role-multi-action actions"
645
- @click="showActions"
646
- >
647
- <i class="icon icon-actions" />
648
- </button>
649
- </template>
650
- </div>
724
+ </template>
651
725
  </div>
652
- </slot>
653
- </header>
654
-
655
- <!-- 扩展区域 -->
656
- <ExtensionPanel
657
- :resource="value"
658
- :type="extensionType"
659
- :location="extensionLocation"
660
- />
661
-
662
- <!-- 顶部状态 Banner -->
663
- <Banner
664
- v-if="banner && isView && !parent.hideBanner"
665
- class="state-banner mb-10"
666
- :color="banner.color"
667
- :label="banner.message == 'Waiting for API to be available' ? '等待 API 可用' : banner.message"
668
- />
669
-
670
- <!-- 管理警告 Banner -->
671
- <Banner
672
- v-if="managedWarning.show"
673
- color="warning"
674
- class="mb-20"
675
- :label="t('resourceDetail.masthead.managedWarning', managedWarning)"
676
- />
677
-
678
- <!-- 内容插槽 -->
679
- <slot />
726
+ </div>
727
+ </slot>
728
+ </header>
729
+
730
+ <!-- Extension area -->
731
+ <ExtensionPanel
732
+ :resource="value"
733
+ :type="extensionType"
734
+ :location="extensionLocation"
735
+ />
736
+
737
+ <Banner
738
+ v-if="banner && isView && !parent.hideBanner"
739
+ class="state-banner mb-10"
740
+ :color="banner.color"
741
+ :label="banner.message"
742
+ />
743
+ <Banner
744
+ v-if="managedWarning.show"
745
+ color="warning"
746
+ class="mb-20"
747
+ :label="t('resourceDetail.masthead.managedWarning', managedWarning)"
748
+ />
749
+
750
+ <slot />
680
751
  </div>
681
752
  </div>
682
753
  </template>
@@ -6,13 +6,14 @@ import {
6
6
  _VIEW, _EDIT, _CLONE, _IMPORT, _STAGE, _CREATE,
7
7
  AS, _YAML, _DETAIL, _CONFIG, _GRAPH, PREVIEW, MODE,
8
8
  } from '@shell/config/query-params';
9
- import { SCHEMA } from '@shell/config/types';
9
+ import { FLEET, SCHEMA } from '@shell/config/types';
10
10
  import { createYaml } from '@shell/utils/create-yaml';
11
11
  import Masthead from '@shell/components/ResourceDetail/Masthead';
12
12
  import DetailTop from '@shell/components/DetailTop';
13
13
  import { clone, diff } from '@shell/utils/object';
14
14
  import IconMessage from '@shell/components/IconMessage';
15
15
  import ForceDirectedTreeChart from '@shell/components/ForceDirectedTreeChart';
16
+ import { checkSchemasForFindAllHash } from '@shell/utils/auth';
16
17
  import { stringify } from '@shell/utils/error';
17
18
  import { Banner } from '@components/Banner';
18
19
 
@@ -171,6 +172,28 @@ export default {
171
172
  yaml = createYaml(schemas, resourceType, data);
172
173
  }
173
174
  } else {
175
+ if ( as === _GRAPH ) {
176
+ const graphSchema = await checkSchemasForFindAllHash({
177
+ cluster: {
178
+ inStoreType: 'management',
179
+ type: FLEET.CLUSTER
180
+ },
181
+ bundle: {
182
+ inStoreType: 'management',
183
+ type: FLEET.BUNDLE,
184
+ opt: { excludeFields: ['metadata.managedFields', 'spec.resources'] },
185
+ },
186
+
187
+ bundleDeployment: {
188
+ inStoreType: 'management',
189
+ type: FLEET.BUNDLE_DEPLOYMENT
190
+ }
191
+
192
+ }, this.$store);
193
+
194
+ this.canViewChart = graphSchema.cluster && graphSchema.bundle && graphSchema.bundleDeployment;
195
+ }
196
+
174
197
  let fqid = id;
175
198
 
176
199
  if ( schema.attributes?.namespaced && namespace ) {
@@ -273,6 +296,7 @@ export default {
273
296
  value: null,
274
297
  model: null,
275
298
  notFound: null,
299
+ canViewChart: true,
276
300
  canViewYaml: null,
277
301
  errors: []
278
302
  };
@@ -451,17 +475,16 @@ export default {
451
475
  :has-graph="hasGraph"
452
476
  :has-detail="hasCustomDetail"
453
477
  :has-edit="hasCustomEdit"
454
- :can-view-yaml="canViewYaml"
455
478
  :resource-subtype="resourceSubtype"
456
479
  :parent-route-override="parentRouteOverride"
457
480
  :store-override="storeOverride"
458
481
 
459
482
  :isManuallyHide="false"
460
483
  >
461
- <DetailTop
484
+ <!-- <DetailTop
462
485
  v-if="isView && isDetail"
463
486
  :value="liveModel"
464
- />
487
+ /> -->
465
488
  </Masthead>
466
489
  <div
467
490
  v-if="hasErrors"
@@ -481,7 +504,7 @@ export default {
481
504
  </div>
482
505
 
483
506
  <ForceDirectedTreeChart
484
- v-if="isGraph"
507
+ v-if="isGraph && canViewChart"
485
508
  :data="chartData"
486
509
  :fdc-config="getGraphConfig"
487
510
  />
@@ -495,9 +518,8 @@ export default {
495
518
  :offer-preview="offerPreview"
496
519
  :done-route="doneRoute"
497
520
  :done-override="value ? value.doneOverride : null"
498
- :show-errors="false"
499
521
  @update:value="$emit('input', $event)"
500
- @error="onYamlError"
522
+ @error="e=>errors.push(e)"
501
523
  />
502
524
 
503
525
  <component
@@ -555,10 +577,4 @@ export default {
555
577
  flex-direction: column;
556
578
  flex-grow: 1;
557
579
  }
558
- .cru__errors {
559
- position: sticky;
560
- top: 0;
561
- z-index: 1;
562
- background-color: var(--header-bg);
563
- }
564
580
  </style>
@@ -2664,7 +2664,7 @@ export default {
2664
2664
  .sort-table-div{
2665
2665
  width:100%;
2666
2666
  white-space:nowrap;
2667
- overflow-x: auto;
2667
+ // overflow-x: auto;
2668
2668
  }
2669
2669
 
2670
2670
  /* 滚动阴影左边 */
@@ -389,7 +389,7 @@ export default {
389
389
  flex-direction: row;
390
390
 
391
391
  + .tab-container {
392
- border: solid thin var(--border);
392
+ // border: solid thin var(--border);
393
393
  }
394
394
 
395
395
  .tab.active {
@@ -16,6 +16,10 @@ export default {
16
16
  showLabels: {
17
17
  type: Boolean,
18
18
  default: false,
19
+ },
20
+ isShowPass: {
21
+ type: Boolean,
22
+ default: false,
19
23
  }
20
24
  },
21
25
 
@@ -88,7 +92,7 @@ export default {
88
92
  <template v-else-if="principal">
89
93
  <div class="avatar">
90
94
  <img
91
- :src="principal.avatarSrc"
95
+ src="@shell/assets/images/user.png"
92
96
  :class="{'round': principal.roundAvatar}"
93
97
  :alt="t('principal.alt.avatar')"
94
98
  >
@@ -98,11 +102,19 @@ export default {
98
102
  class="name"
99
103
  >
100
104
  <table>
101
- <tbody>
102
- <tr><th>{{ t('principal.name') }}: </th><td>{{ principal.name || principal.loginName }}</td></tr>
103
- <tr><th>{{ t('principal.loginName') }}: </th><td>{{ principal.loginName }}</td></tr>
104
- <tr><th>{{ t('principal.type') }}: </th><td>{{ principal.displayType }}</td></tr>
105
- </tbody>
105
+ <tr class="mb-10">
106
+ <td>{{ t('principal.name') }}: </td><td>{{ principal.name || principal.loginName }}</td>
107
+ </tr>
108
+ <tr class="mb-10">
109
+ <td>{{ t('principal.loginName') }}: </td><td>{{ principal.loginName }}</td>
110
+ </tr>
111
+ <tr
112
+ v-if="isShowPass"
113
+ class="mb-10"
114
+ >
115
+ <td>修改密码: </td><td>****** <slot name="edit" /></td>
116
+ </tr>
117
+ <tr><td>{{ t('principal.type') }}: </td><td>{{ principal.displayType }}</td></tr>
106
118
  </table>
107
119
  </div>
108
120
  <template v-else>
@@ -172,23 +184,35 @@ export default {
172
184
  }
173
185
 
174
186
  &.showLabels {
175
- grid-template-areas:
187
+ /* grid-template-areas:
176
188
  "avatar name";
177
189
  grid-template-columns: 60px auto;
178
190
  grid-template-rows: 60px;
179
- column-gap: 0;
191
+ column-gap: 0; */
192
+ display: flex;
193
+ column-gap:0;
180
194
  .name {
195
+ display: flex;
181
196
  line-height: unset;
182
197
  }
183
-
198
+ table tr {
199
+ display: block;
200
+ }
184
201
  table tr td:not(:first-of-type) {
185
202
  padding-left: 10px;
186
203
  }
204
+ table tr td:not(:last-of-type) {
205
+ width: 100px;
206
+ }
187
207
  }
188
208
 
189
209
  .avatar {
190
- grid-area: avatar;
191
- text-align: center;
210
+ /* grid-area: avatar;
211
+ text-align: center; */
212
+ width: 287px;
213
+ display: flex;
214
+ justify-content: center;
215
+ align-items: center;
192
216
 
193
217
  DIV.empty {
194
218
  border: 1px solid var(--border);