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
@@ -28,6 +28,7 @@ import ActionMenu from '@shell/components/ActionMenuShell.vue';
28
28
  import { useRuntimeFlag } from '@shell/composables/useRuntimeFlag';
29
29
  import ActionDropdownShell from '@shell/components/ActionDropdownShell.vue';
30
30
  import { harvesterhci2cloud, cloud2harvesterhci } from '@shell/utils/router'
31
+ import MastheadBtn from '@shell/components/ResourceList/Masthead-btn.vue'
31
32
 
32
33
  // Uncomment for table performance debugging
33
34
  // import tableDebug from './debug';
@@ -415,33 +416,16 @@ export default {
415
416
 
416
417
  const isLoading = this.loading || false;
417
418
 
418
- console.log(this.$route.path, ' this.$route?.path');
419
-
420
419
  let isCreatable = false;
421
- const lastPath = this.$route?.path?.split('/').pop();
422
-
423
- console.log(lastPath, ' lastPath-----------------------');
420
+ const lastPath = this.$route?.path.split('/').pop();
424
421
 
425
- if (lastPath?.includes('.')) {
422
+ if (lastPath.includes('.')) {
426
423
  isCreatable = this.$store.getters['type-map/optionsFor'](lastPath).isCreatable;
427
424
  } else if (lastPath === 'namespace') {
428
425
  isCreatable = this.$store.getters['type-map/optionsFor'](this.$route.name).isCreatable;
429
426
  }
430
427
 
431
- const resource = this.$route.params.resource;
432
-
433
- let hasEditComponent = false
434
-
435
- if (lastPath?.includes('.')) {
436
- hasEditComponent = this.$store.getters['type-map/hasCustomEdit'](lastPath);
437
- } else if (lastPath === 'namespace') {
438
- hasEditComponent = this.$store.getters['type-map/hasCustomEdit'](this.$route.name);
439
- } else {
440
- hasEditComponent = this.$store.getters['type-map/hasCustomEdit'](resource);
441
- }
442
-
443
428
  return {
444
- hasEditComponent,
445
429
  refreshButtonPhase: isLoading ? ASYNC_BUTTON_STATES.WAITING : ASYNC_BUTTON_STATES.ACTION,
446
430
  expanded: {},
447
431
  searchQuery,
@@ -629,17 +613,22 @@ export default {
629
613
  }
630
614
  };
631
615
 
632
- onMounted(() => {
633
- table.value.addEventListener('keyup', handleEnterKey);
634
- });
635
616
 
636
617
  onBeforeUnmount(() => {
637
- table.value.removeEventListener('keyup', handleEnterKey);
618
+ table.value && table.value.removeEventListener('keyup', handleEnterKey);
638
619
  });
639
620
 
640
621
  const store = useStore();
641
622
  const { featureDropdownMenu } = useRuntimeFlag(store);
642
623
 
624
+ onMounted(() => {
625
+ table.value && table.value.addEventListener('keyup', handleEnterKey);
626
+
627
+ console.log(featureDropdownMenu, ' featureDropdownMenu---------------------');
628
+
629
+
630
+ });
631
+
643
632
  return {
644
633
  table,
645
634
  featureDropdownMenu,
@@ -868,6 +857,25 @@ export default {
868
857
  },
869
858
 
870
859
  methods: {
860
+ // getTableList () {
861
+ // const q = this.eventualSearchQuery;
862
+
863
+ // this.searchQuery = q;
864
+
865
+ // if (!this.hasAdvancedFiltering && this.useQueryParamsForSimpleFiltering) {
866
+ // const route = {
867
+ // name: this.$route.name,
868
+ // params: { ...this.$route.params },
869
+ // query: { ...this.$route.query, q }
870
+ // };
871
+
872
+ // if (!q && this.$route.query?.q) {
873
+ // route.query = {};
874
+ // }
875
+
876
+ // this.$router.replace(route);
877
+ // }
878
+ // },
871
879
  onTableScroll(table, e) {
872
880
  // 记录最后滚动的距离
873
881
  let lastScrollTop = 0;
@@ -1241,38 +1249,30 @@ export default {
1241
1249
  ref="container"
1242
1250
  :data-testid="componentTestid + '-list-container'"
1243
1251
  >
1252
+ <!-- 主标题和过滤器区域 -->
1244
1253
  <div
1245
- :class="{'titled': $slots.title && $slots.title.length, 'mb-40': isFilterLabel, 'mb-20': search || isCreatable}"
1246
- class="sortable-table-header "
1247
- :style="{marginTop: search&& !isBanner ? marginTopValue + 'px' : '0px',marginLeft: isCreatable && hasEditComponent ? '100px' : '-10px',maxHeight: '32px'}"
1254
+ :class="{'titled': $slots.title && $slots.title.length, 'mb-40': isFilterLabel}"
1255
+ class="sortable-table-header mb-20"
1248
1256
  >
1249
1257
  <slot name="title" />
1258
+
1259
+ <!-- 顶部功能行区域 -->
1250
1260
  <div
1251
1261
  v-if="showHeaderRow"
1252
- class="fixed-header-actions"
1262
+ class="fixed-header-table-actions"
1253
1263
  :class="{button: !!$slots['header-button'], 'advanced-filtering': hasAdvancedFiltering, }"
1254
1264
  style="display: flex;"
1255
1265
  >
1256
- <!-- <div
1257
- :class="bulkActionsClass"
1258
- class="bulk"
1259
- >
1260
-
1261
- </div> -->
1262
- <div
1263
- v-if="!hasAdvancedFiltering && $slots['header-middle']"
1264
- class="middle"
1265
- style="margin-left: 10px;margin-right: -10px;"
1266
- >
1267
- <slot name="header-middle" />
1268
- </div>
1269
1266
 
1267
+ <!-- 搜索栏、右插槽、刷新按钮、高级筛选等区域 -->
1270
1268
  <div
1271
1269
  v-if="search || hasAdvancedFiltering || isTooManyItemsToAutoUpdate || $slots['header-right']"
1272
1270
  class="search row"
1273
1271
  data-testid="search-box-filter-row"
1274
- style="max-height: 32px;display: contents;"
1272
+ style="max-height: 32px;"
1275
1273
  >
1274
+
1275
+ <!-- 已应用的高级筛选 -->
1276
1276
  <ul
1277
1277
  v-if="hasAdvancedFiltering"
1278
1278
  class="advanced-filters-applied"
@@ -1289,14 +1289,9 @@ export default {
1289
1289
  <div class="bg" />
1290
1290
  </li>
1291
1291
  </ul>
1292
+
1292
1293
  <slot name="header-right" />
1293
- <AsyncButton
1294
- v-if="isTooManyItemsToAutoUpdate"
1295
- mode="manual-refresh"
1296
- :size="manualRefreshButtonSize"
1297
- :current-phase="refreshButtonPhase"
1298
- @click="debouncedRefreshTableData"
1299
- />
1294
+
1300
1295
  <div
1301
1296
  v-if="hasAdvancedFiltering"
1302
1297
  ref="advanced-filter-group"
@@ -1352,6 +1347,8 @@ export default {
1352
1347
  </div>
1353
1348
  </div>
1354
1349
  </div>
1350
+
1351
+ <!-- 搜索描述文本(隐藏) -->
1355
1352
  <p
1356
1353
  v-else-if="search"
1357
1354
  id="describe-filter-sortable-table"
@@ -1359,326 +1356,357 @@ export default {
1359
1356
  >
1360
1357
  {{ t('sortableTable.filteringDescription') }}
1361
1358
  </p>
1362
- <slot name="header-button" />
1363
- <input
1364
- v-if="search"
1365
- ref="searchQuery"
1366
- v-model="eventualSearchQuery"
1367
- type="search"
1368
- class="input-sm search-box"
1369
- :aria-label="t('sortableTable.searchLabel')"
1370
- aria-describedby="describe-filter-sortable-table"
1371
- :placeholder="t('sortableTable.search')+searchPlaceholder"
1372
- >
1359
+ <slot name="header-button" />
1360
+
1361
+ <div style="display: flex;">
1362
+
1363
+ <slot name="search-main-button" />
1364
+
1365
+ <!-- 搜索输入框 -->
1366
+ <input
1367
+ v-if="search"
1368
+ ref="searchQuery"
1369
+ v-model="eventualSearchQuery"
1370
+ type="search"
1371
+ class="input-sm search-box"
1372
+ :aria-label="t('sortableTable.searchLabel')"
1373
+ aria-describedby="describe-filter-sortable-table"
1374
+ :placeholder="t('sortableTable.search')+searchPlaceholder"
1375
+ >
1376
+ <!-- <button v-if="search" @click="getTableList(eventualSearchQuery)" calss="search-btn role-secondary">
1377
+ 检索
1378
+ </button> -->
1379
+
1380
+ <!-- 手动刷新按钮 -->
1381
+ <AsyncButton
1382
+ v-if="isTooManyItemsToAutoUpdate"
1383
+ mode="manual-refresh"
1384
+ :size="manualRefreshButtonSize"
1385
+ :current-phase="refreshButtonPhase"
1386
+ @click="debouncedRefreshTableData"
1387
+ />
1388
+
1389
+ </div>
1373
1390
 
1374
1391
  </div>
1392
+
1393
+ <!-- 中间区域插槽 -->
1394
+ <div
1395
+ v-if="!hasAdvancedFiltering && $slots['header-middle']"
1396
+ class="middle"
1397
+ style="margin-left: 10px;"
1398
+ >
1399
+ <slot name="header-middle" />
1400
+ </div>
1375
1401
  </div>
1376
1402
  </div>
1403
+
1377
1404
  <div v-if="$slots['banner']">
1378
1405
  <slot name="banner"></slot>
1379
1406
  </div>
1380
- <div class="sort-table-div">
1381
- <table
1382
- ref="table"
1383
- class="sortable-table"
1384
- :class="classObject"
1385
- width="100%"
1386
- role="table"
1387
- >
1388
- <THead
1389
- v-if="showHeaders"
1390
- :label-for="labelFor"
1391
- :columns="columns"
1392
- :group="group"
1393
- :group-options="advGroupOptions"
1394
- :has-advanced-filtering="hasAdvancedFiltering"
1395
- :adv-filter-hide-labels-as-cols="advFilterHideLabelsAsCols"
1396
- :table-actions="tableActions"
1397
- :table-cols-options="columnOptions"
1398
- :row-actions="rowActions"
1399
- :sub-expand-column="subExpandColumn"
1400
- :row-actions-width="rowActionsWidth"
1401
- :how-much-selected="howMuchSelected"
1402
- :sort-by="sortBy"
1403
- :default-sort-by="_defaultSortBy"
1404
- :descending="descending"
1405
- :no-rows="noRows"
1406
- :loading="isLoading && !loadingDelay"
1407
- :no-results="noResults"
1408
- @on-toggle-all="onToggleAll"
1409
- @on-sort-change="changeSort"
1410
- @col-visibility-change="changeColVisibility"
1411
- @group-value-change="(val) => $emit('group-value-change', val)"
1412
- @update-cols-options="updateColsOptions"
1413
- />
1414
1407
 
1415
- <!-- Don't display anything if we're loading and the delay has yet to pass -->
1416
- <div v-if="isLoading && !loadingDelay" />
1408
+ <div class="sort-table-div">
1409
+ <table
1410
+ ref="table"
1411
+ class="sortable-table"
1412
+ :class="classObject"
1413
+ width="100%"
1414
+ role="table"
1415
+ >
1416
+ <THead
1417
+ v-if="showHeaders"
1418
+ :label-for="labelFor"
1419
+ :columns="columns"
1420
+ :group="group"
1421
+ :group-options="advGroupOptions"
1422
+ :has-advanced-filtering="hasAdvancedFiltering"
1423
+ :adv-filter-hide-labels-as-cols="advFilterHideLabelsAsCols"
1424
+ :table-actions="tableActions"
1425
+ :table-cols-options="columnOptions"
1426
+ :row-actions="rowActions"
1427
+ :sub-expand-column="subExpandColumn"
1428
+ :row-actions-width="rowActionsWidth"
1429
+ :how-much-selected="howMuchSelected"
1430
+ :sort-by="sortBy"
1431
+ :default-sort-by="_defaultSortBy"
1432
+ :descending="descending"
1433
+ :no-rows="noRows"
1434
+ :loading="isLoading && !loadingDelay"
1435
+ :no-results="noResults"
1436
+ @on-toggle-all="onToggleAll"
1437
+ @on-sort-change="changeSort"
1438
+ @col-visibility-change="changeColVisibility"
1439
+ @group-value-change="(val) => $emit('group-value-change', val)"
1440
+ @update-cols-options="updateColsOptions"
1441
+ />
1417
1442
 
1418
- <tbody v-else-if="isLoading && !altLoading">
1419
- <slot name="loading">
1420
- <tr>
1421
- <td :colspan="fullColspan">
1422
- <div class="data-loading">
1423
- <i class="icon-spin icon icon-spinner" />
1443
+ <!-- Don't display anything if we're loading and the delay has yet to pass -->
1444
+ <div v-if="isLoading && !loadingDelay" />
1445
+
1446
+ <tbody v-else-if="isLoading && !altLoading">
1447
+ <slot name="loading">
1448
+ <tr>
1449
+ <td :colspan="fullColspan">
1450
+ <div class="data-loading">
1451
+ <i class="icon-spin icon icon-spinner" />
1452
+ <t
1453
+ k="generic.loading"
1454
+ :raw="true"
1455
+ />
1456
+ </div>
1457
+ </td>
1458
+ </tr>
1459
+ </slot>
1460
+ </tbody>
1461
+ <tbody v-else-if="noRows">
1462
+ <slot name="no-rows">
1463
+ <tr class="no-rows">
1464
+ <td :colspan="fullColspan">
1424
1465
  <t
1425
- k="generic.loading"
1426
- :raw="true"
1466
+ v-if="showNoRows"
1467
+ :k="noRowsKey"
1427
1468
  />
1428
- </div>
1429
- </td>
1430
- </tr>
1431
- </slot>
1432
- </tbody>
1433
- <tbody v-else-if="noRows">
1434
- <slot name="no-rows">
1435
- <tr class="no-rows">
1436
- <td :colspan="fullColspan">
1437
- <t
1438
- v-if="showNoRows"
1439
- :k="noRowsKey"
1440
- />
1441
- </td>
1442
- </tr>
1443
- </slot>
1444
- </tbody>
1445
- <tbody v-else-if="noResults">
1446
- <slot name="no-results">
1447
- <tr class="no-results">
1448
- <td
1449
- :colspan="fullColspan"
1450
- class="text-center"
1451
- >
1452
- <t :k="noDataKey" />
1453
- </td>
1454
- </tr>
1455
- </slot>
1456
- </tbody>
1457
- <tbody
1458
- v-for="(groupedRows) in displayRows"
1459
- v-else
1460
- :key="groupedRows.key"
1461
- tabindex="-1"
1462
- :class="{ group: groupBy }"
1463
- >
1464
- <slot
1465
- v-if="groupBy"
1466
- name="group-row"
1467
- :group="groupedRows"
1468
- :fullColspan="fullColspan"
1469
- >
1470
- <tr class="group-row">
1471
- <td :colspan="fullColspan">
1472
- <slot
1473
- name="group-by"
1474
- :group="groupedRows.grp"
1469
+ </td>
1470
+ </tr>
1471
+ </slot>
1472
+ </tbody>
1473
+ <tbody v-else-if="noResults">
1474
+ <slot name="no-results">
1475
+ <tr class="no-results">
1476
+ <td
1477
+ :colspan="fullColspan"
1478
+ class="text-center"
1475
1479
  >
1476
- <div
1477
- v-trim-whitespace
1478
- class="group-tab"
1479
- >
1480
- {{ groupedRows.ref }}
1481
- </div>
1482
- </slot>
1483
- </td>
1484
- </tr>
1485
- </slot>
1486
- <template
1487
- v-for="(row, i) in groupedRows.rows"
1488
- :key="i"
1480
+ <t :k="noDataKey" />
1481
+ </td>
1482
+ </tr>
1483
+ </slot>
1484
+ </tbody>
1485
+ <tbody
1486
+ v-for="(groupedRows) in displayRows"
1487
+ v-else
1488
+ :key="groupedRows.key"
1489
+ tabindex="-1"
1490
+ :class="{ group: groupBy }"
1489
1491
  >
1490
1492
  <slot
1491
- name="main-row"
1492
- :row="row.row"
1493
+ v-if="groupBy"
1494
+ name="group-row"
1495
+ :group="groupedRows"
1496
+ :fullColspan="fullColspan"
1497
+ >
1498
+ <tr class="group-row">
1499
+ <td :colspan="fullColspan">
1500
+ <slot
1501
+ name="group-by"
1502
+ :group="groupedRows.grp"
1503
+ >
1504
+ <div
1505
+ v-trim-whitespace
1506
+ class="group-tab"
1507
+ >
1508
+ {{ groupedRows.ref }}
1509
+ </div>
1510
+ </slot>
1511
+ </td>
1512
+ </tr>
1513
+ </slot>
1514
+ <template
1515
+ v-for="(row, i) in groupedRows.rows"
1516
+ :key="i"
1493
1517
  >
1494
1518
  <slot
1495
- :name="'main-row:' + (row.row.mainRowKey || i)"
1496
- :full-colspan="fullColspan"
1519
+ name="main-row"
1520
+ :row="row.row"
1497
1521
  >
1498
- <!-- The data-cant-run-bulk-action-of-interest attribute is being used instead of :class because
1499
- because our selection.js invokes toggleClass and :class clobbers what was added by toggleClass if
1500
- the value of :class changes. -->
1501
- <tr
1502
- class="main-row"
1503
- :data-testid="componentTestid + '-' + i + '-row'"
1504
- :class="{ 'has-sub-row': row.showSubRow}"
1505
- :data-node-id="row.key"
1506
- :data-cant-run-bulk-action-of-interest="actionOfInterest && !row.canRunBulkActionOfInterest"
1522
+ <slot
1523
+ :name="'main-row:' + (row.row.mainRowKey || i)"
1524
+ :full-colspan="fullColspan"
1507
1525
  >
1508
- <td
1509
- v-if="tableActions"
1510
- class="row-check"
1511
- align="middle"
1526
+ <!-- The data-cant-run-bulk-action-of-interest attribute is being used instead of :class because
1527
+ because our selection.js invokes toggleClass and :class clobbers what was added by toggleClass if
1528
+ the value of :class changes. -->
1529
+ <tr
1530
+ class="main-row"
1531
+ :data-testid="componentTestid + '-' + i + '-row'"
1532
+ :class="{ 'has-sub-row': row.showSubRow}"
1533
+ :data-node-id="row.key"
1534
+ :data-cant-run-bulk-action-of-interest="actionOfInterest && !row.canRunBulkActionOfInterest"
1512
1535
  >
1513
- {{ row.mainRowKey }}
1514
- <Checkbox
1515
- class="selection-checkbox"
1516
- :data-node-id="row.key"
1517
- :data-testid="componentTestid + '-' + i + '-checkbox'"
1518
- :value="selectedRows.includes(row.row)"
1519
- :alternate-label="t('sortableTable.genericRowCheckbox', { item: row && row.row ? row.row.id : '' })"
1520
- />
1521
- </td>
1522
- <td
1523
- v-if="subExpandColumn"
1524
- class="row-expand"
1525
- align="middle"
1526
- >
1527
- <i
1528
- data-title="Toggle Expand"
1529
- :class="{
1530
- icon: true,
1531
- 'icon-chevron-right': !expanded[row.row[keyField]],
1532
- 'icon-chevron-down': !!expanded[row.row[keyField]]
1533
- }"
1534
- @click.stop="toggleExpand(row.row)"
1535
- />
1536
- </td>
1537
- <template
1538
- v-for="(col, j) in row.columns"
1539
- :key="j"
1540
- >
1541
- <slot
1542
- :name="'col:' + col.col.name"
1543
- :row="row.row"
1544
- :col="col.col"
1545
- :dt="dt"
1546
- :expanded="expanded"
1547
- :rowKey="row.key"
1536
+ <td
1537
+ v-if="tableActions"
1538
+ class="row-check"
1539
+ align="middle"
1540
+ >
1541
+ {{ row.mainRowKey }}
1542
+ <Checkbox
1543
+ class="selection-checkbox"
1544
+ :data-node-id="row.key"
1545
+ :data-testid="componentTestid + '-' + i + '-checkbox'"
1546
+ :value="selectedRows.includes(row.row)"
1547
+ :alternate-label="t('sortableTable.genericRowCheckbox', { item: row && row.row ? row.row.id : '' })"
1548
+ />
1549
+ </td>
1550
+ <td
1551
+ v-if="subExpandColumn"
1552
+ class="row-expand"
1553
+ align="middle"
1548
1554
  >
1549
- <td
1550
- v-show="!hasAdvancedFiltering || (hasAdvancedFiltering && col.col.isColVisible)"
1551
- :key="col.col.name"
1552
- :data-title="col.col.label"
1553
- :data-testid="`sortable-cell-${ i }-${ j }`"
1554
- :align="col.col.align || 'left'"
1555
- :class="{['col-'+col.dasherize]: !!col.col.formatter, [col.col.breakpoint]: !!col.col.breakpoint, ['skip-select']: col.col.skipSelect}"
1556
- :width="col.col.width"
1555
+ <i
1556
+ data-title="Toggle Expand"
1557
+ :class="{
1558
+ icon: true,
1559
+ 'icon-chevron-right': !expanded[row.row[keyField]],
1560
+ 'icon-chevron-down': !!expanded[row.row[keyField]]
1561
+ }"
1562
+ @click.stop="toggleExpand(row.row)"
1563
+ />
1564
+ </td>
1565
+ <template
1566
+ v-for="(col, j) in row.columns"
1567
+ :key="j"
1568
+ >
1569
+ <slot
1570
+ :name="'col:' + col.col.name"
1571
+ :row="row.row"
1572
+ :col="col.col"
1573
+ :dt="dt"
1574
+ :expanded="expanded"
1575
+ :rowKey="row.key"
1557
1576
  >
1558
- <slot
1559
- :name="'cell:' + col.col.name"
1560
- :row="row.row"
1561
- :col="col.col"
1562
- :value="col.value"
1577
+ <td
1578
+ v-show="!hasAdvancedFiltering || (hasAdvancedFiltering && col.col.isColVisible)"
1579
+ :key="col.col.name"
1580
+ :data-title="col.col.label"
1581
+ :data-testid="`sortable-cell-${ i }-${ j }`"
1582
+ :align="'left'"
1583
+ :class="{['col-'+col.dasherize]: !!col.col.formatter, [col.col.breakpoint]: !!col.col.breakpoint, ['skip-select']: col.col.skipSelect}"
1584
+ :width="col.col.width"
1563
1585
  >
1564
- <component
1565
- :is="col.component"
1566
- v-if="col.component && col.needRef"
1567
- ref="column"
1568
- :value="col.value"
1586
+ <slot
1587
+ :name="'cell:' + col.col.name"
1569
1588
  :row="row.row"
1570
1589
  :col="col.col"
1571
- :get-custom-detail-link="getCustomDetailLink"
1572
- v-bind="col.col.formatterOpts"
1573
- :row-key="row.key"
1574
- />
1575
- <component
1576
- :is="col.component"
1577
- v-else-if="col.component"
1578
1590
  :value="col.value"
1579
- :row="row.row"
1580
- :col="col.col"
1581
- v-bind="col.col.formatterOpts"
1582
- :row-key="row.key"
1591
+ >
1592
+ <component
1593
+ :is="col.component"
1594
+ v-if="col.component && col.needRef"
1595
+ ref="column"
1596
+ :value="col.value"
1597
+ :row="row.row"
1598
+ :col="col.col"
1599
+ :get-custom-detail-link="getCustomDetailLink"
1600
+ v-bind="col.col.formatterOpts"
1601
+ :row-key="row.key"
1602
+ />
1603
+ <component
1604
+ :is="col.component"
1605
+ v-else-if="col.component"
1606
+ :value="col.value"
1607
+ :row="row.row"
1608
+ :col="col.col"
1609
+ v-bind="col.col.formatterOpts"
1610
+ :row-key="row.key"
1611
+ />
1612
+ <component
1613
+ :is="col.col.formatter"
1614
+ v-else-if="col.col.formatter"
1615
+ :value="col.value"
1616
+ :row="row.row"
1617
+ :col="col.col"
1618
+ v-bind="col.col.formatterOpts"
1619
+ :row-key="row.key"
1620
+ />
1621
+ <template v-else-if="col.value !== ''">
1622
+ {{ col.formatted }}
1623
+ </template>
1624
+ <template v-else-if="col.col.dashIfEmpty">
1625
+ <span class="text-muted">&mdash;</span>
1626
+ </template>
1627
+ </slot>
1628
+ </td>
1629
+ </slot>
1630
+ </template>
1631
+ <td
1632
+ v-if="rowActions"
1633
+ :align="'left'"
1634
+ style="height:60px"
1635
+ >
1636
+ <div style="display: flex;align-items: center;">
1637
+ <slot
1638
+ name="row-actions"
1639
+ :row="row.row"
1640
+ :index="i"
1641
+ >
1642
+ </slot>
1643
+ <template v-if="featureDropdownMenu">
1644
+ <ActionMenu
1645
+ :resource="row.row"
1646
+ :data-testid="componentTestid + '-' + i + '-action-button'"
1647
+ :button-aria-label="t('sortableTable.tableActionsLabel', { resource: row?.row?.id || '' })"
1583
1648
  />
1584
- <component
1585
- :is="col.col.formatter"
1586
- v-else-if="col.col.formatter"
1587
- :value="col.value"
1588
- :row="row.row"
1589
- :col="col.col"
1590
- v-bind="col.col.formatterOpts"
1591
- :row-key="row.key"
1649
+ </template>
1650
+ <template v-else>
1651
+ <ButtonMultiAction
1652
+ :id="`actionButton+${i}+${(row.row && row.row.name) ? row.row.name : ''}`"
1653
+ :ref="`actionButton${i}`"
1654
+ aria-haspopup="true"
1655
+ aria-expanded="false"
1656
+ :aria-label="t('sortableTable.tableActionsLabel', { resource: row?.row?.id || '' })"
1657
+ :data-testid="componentTestid + '-' + i + '-action-button'"
1658
+ :borderless="true"
1659
+ @click="handleActionButtonClick(i, $event)"
1660
+ @keyup.enter="handleActionButtonClick(i, $event)"
1661
+ @keyup.space="handleActionButtonClick(i, $event)"
1592
1662
  />
1593
- <template v-else-if="col.value !== ''">
1594
- {{ col.formatted }}
1595
- </template>
1596
- <template v-else-if="col.col.dashIfEmpty">
1597
- <span class="text-muted">&mdash;</span>
1598
- </template>
1599
- </slot>
1600
- </td>
1601
- </slot>
1602
- </template>
1663
+ </template>
1664
+ </div>
1665
+ </td>
1666
+ </tr>
1667
+ </slot>
1668
+ </slot>
1669
+ <!-- <slot
1670
+ v-if="row.showSubRow"
1671
+ name="sub-row"
1672
+ :full-colspan="fullColspan"
1673
+ :row="row.row"
1674
+ :sub-matches="subMatches"
1675
+ :keyField="keyField"
1676
+ :componentTestid="componentTestid"
1677
+ :i="i"
1678
+ :onRowMouseEnter="onRowMouseEnter"
1679
+ :onRowMouseLeave="onRowMouseLeave"
1680
+ >
1681
+ <tr
1682
+ v-if="row.row.stateDescription"
1683
+ :key="row.row[keyField] + '-description'"
1684
+ :data-testid="componentTestid + '-' + i + '-row-description'"
1685
+ class="state-description sub-row"
1686
+ @mouseenter="onRowMouseEnter"
1687
+ @mouseleave="onRowMouseLeave"
1688
+ >
1689
+ <td
1690
+ v-if="tableActions"
1691
+ class="row-check"
1692
+ align="middle"
1693
+ />
1603
1694
  <td
1604
- v-if="rowActions"
1605
- :align="'left'"
1606
- style="height:60px"
1695
+ :colspan="fullColspan - (tableActions ? 1: 0)"
1696
+ :class="{ 'text-error' : row.row.stateObj.error }"
1607
1697
  >
1608
- <div style="display: flex;align-items: center;">
1609
- <slot
1610
- name="row-actions"
1611
- :row="row.row"
1612
- :index="i"
1613
- >
1614
- </slot>
1615
- <template v-if="featureDropdownMenu">
1616
- <ActionMenu
1617
- :resource="row.row"
1618
- :data-testid="componentTestid + '-' + i + '-action-button'"
1619
- :button-aria-label="t('sortableTable.tableActionsLabel', { resource: row?.row?.id || '' })"
1620
- />
1621
- </template>
1622
- <template v-else>
1623
- <ButtonMultiAction
1624
- :id="`actionButton+${i}+${(row.row && row.row.name) ? row.row.name : ''}`"
1625
- :ref="`actionButton${i}`"
1626
- aria-haspopup="true"
1627
- aria-expanded="false"
1628
- :aria-label="t('sortableTable.tableActionsLabel', { resource: row?.row?.id || '' })"
1629
- :data-testid="componentTestid + '-' + i + '-action-button'"
1630
- :borderless="true"
1631
- @click="handleActionButtonClick(i, $event)"
1632
- @keyup.enter="handleActionButtonClick(i, $event)"
1633
- @keyup.space="handleActionButtonClick(i, $event)"
1634
- />
1635
- </template>
1636
- </div>
1698
+ {{ row.row.stateDescription }}
1637
1699
  </td>
1638
1700
  </tr>
1639
- </slot>
1640
- </slot>
1641
- <!-- <slot
1642
- v-if="row.showSubRow"
1643
- name="sub-row"
1644
- :full-colspan="fullColspan"
1645
- :row="row.row"
1646
- :sub-matches="subMatches"
1647
- :keyField="keyField"
1648
- :componentTestid="componentTestid"
1649
- :i="i"
1650
- :onRowMouseEnter="onRowMouseEnter"
1651
- :onRowMouseLeave="onRowMouseLeave"
1652
- >
1653
- <tr
1654
- v-if="row.row.stateDescription"
1655
- :key="row.row[keyField] + '-description'"
1656
- :data-testid="componentTestid + '-' + i + '-row-description'"
1657
- class="state-description sub-row"
1658
- @mouseenter="onRowMouseEnter"
1659
- @mouseleave="onRowMouseLeave"
1660
- >
1661
- <td
1662
- v-if="tableActions"
1663
- class="row-check"
1664
- align="middle"
1665
- />
1666
- <td
1667
- :colspan="fullColspan - (tableActions ? 1: 0)"
1668
- :class="{ 'text-error' : row.row.stateObj.error }"
1669
- >
1670
- {{ row.row.stateDescription }}
1671
- </td>
1672
- </tr>
1673
- </slot> -->
1674
- </template>
1675
- </tbody>
1676
- </table>
1677
- </div>
1701
+ </slot> -->
1702
+ </template>
1703
+ </tbody>
1704
+ </table>
1705
+ </div>
1678
1706
  <div
1679
1707
  v-if="!noRows && !noResults"
1680
1708
  :class="$route.path=== '/account'? 'chebox-padding':''"
1681
- style="display: flex;justify-content: flex-start;align-content: center;height: 62px;position: sticky;bottom: 0;background-color: var(--header-bg);padding: 15px 20px 0 30px;margin: 0 -20px 0 -20px;z-index:20"
1709
+ style="display: flex;justify-content: flex-start;align-content: center;height: 62px;position: sticky;bottom: 0;background-color: var(--header-bg);padding: 15px 20px 0 30px;margin: 0 -20px 0 -20px;z-index:13"
1682
1710
  >
1683
1711
  <div style="display: flex;justify-content: center;height: 32px;">
1684
1712
  <Checkbox
@@ -1699,7 +1727,7 @@ export default {
1699
1727
  <slot name="title" />
1700
1728
  <div
1701
1729
  v-if="showHeaderRow"
1702
- class="fixed-header-actions"
1730
+ class="fixed-footer-actions"
1703
1731
  :class="{button: !!$slots['header-button'], 'advanced-filtering': hasAdvancedFiltering,}"
1704
1732
  >
1705
1733
  <div
@@ -1725,10 +1753,11 @@ export default {
1725
1753
  @mouseover="setBulkActionOfInterest(act)"
1726
1754
  @mouseleave="setBulkActionOfInterest(null)"
1727
1755
  >
1728
- <i
1756
+ <!-- <i
1729
1757
  v-if="act.icon"
1730
1758
  :class="act.icon"
1731
- />
1759
+ style="line-height: 12px;height: 12px;font-size: 12px;"
1760
+ /> -->
1732
1761
  <span v-clean-html="act.label" />
1733
1762
  </button>
1734
1763
  <template v-if="featureDropdownMenu">
@@ -1903,7 +1932,7 @@ export default {
1903
1932
 
1904
1933
  <!-- 分页页码切换 -->
1905
1934
  <Select
1906
- :mode="inputPerPage"
1935
+ :mode="inputPerPage"
1907
1936
  :searchable="false"
1908
1937
  :clearable="false"
1909
1938
  :options="perPageOptions"
@@ -2164,77 +2193,32 @@ export default {
2164
2193
  td {
2165
2194
  padding: 8px 5px;
2166
2195
  border: 0;
2167
- background: var(--sortable-table-row-bg);
2168
2196
 
2169
2197
  &:first-child {
2170
2198
  padding-left: 10px;
2171
- position: sticky;
2172
- left: 0;
2173
- z-index: 2;
2174
- }
2175
- &:nth-child(2) {
2176
- padding-left: 10px;
2177
- position: sticky;
2178
- left: 29px;
2179
- z-index: 2;
2180
2199
  }
2181
2200
 
2182
2201
  &:last-child {
2183
2202
  padding-right: 10px;
2184
- position: sticky;
2185
- right: 0;
2186
- z-index: 2;
2187
- /* padding-left: 10px; */
2188
2203
  }
2189
2204
 
2190
2205
  &.row-check {
2191
2206
  padding-top: 12px;
2192
- right: 0;
2193
- position: sticky;
2194
2207
  }
2195
2208
  }
2196
- th {
2197
- padding: 13px 5px;
2198
- border: 0;
2199
- /* height: 50.84px; */
2200
- box-sizing: border-box;
2201
- background: var(--sortable-table-header-bg);
2202
-
2203
- &:first-child {
2204
- padding-left: 10px;
2205
- position: sticky;
2206
- left: 0;
2207
- z-index: 2;
2208
- }
2209
- &:nth-child(2) {
2210
- padding-left: 10px;
2211
- position: sticky;
2212
- left: 29px;
2213
- z-index: 2;
2214
- }
2215
-
2216
- &:last-child {
2217
- padding-left: 10px;
2218
- padding-right: 10px;
2219
- position: sticky;
2220
- right: 0;
2221
- z-index: 2;
2222
- }
2223
2209
 
2224
- }
2225
2210
  tbody {
2226
2211
  tr {
2227
2212
  border-bottom: 1px solid var(--sortable-table-top-divider);
2228
2213
  background-color: var(--sortable-table-row-bg);
2229
- height: 60px;
2230
2214
 
2231
2215
  &.main-row.has-sub-row {
2232
- /* border-bottom: 0; */
2216
+ border-bottom: 0;
2233
2217
  }
2234
2218
 
2235
2219
  // if a main-row is hovered also hover it's sibling sub row. note - the reverse is handled in selection.js
2236
2220
  &.main-row:not(.row-selected):hover + .sub-row {
2237
- /* background-color: var(--sortable-table-hover-bg); */
2221
+ background-color: var(--sortable-table-hover-bg);
2238
2222
  }
2239
2223
 
2240
2224
  &:last-of-type {
@@ -2287,7 +2271,6 @@ export default {
2287
2271
 
2288
2272
  tr.group-row {
2289
2273
  background-color: initial;
2290
- height: 40px;
2291
2274
 
2292
2275
  &:first-child {
2293
2276
  border-bottom: 2px solid var(--sortable-table-row-bg);
@@ -2379,11 +2362,11 @@ export default {
2379
2362
  align-items: center;
2380
2363
  }
2381
2364
  }
2382
- .fixed-header-actions.button{
2365
+ .fixed-footer-actions.button{
2383
2366
  grid-template-columns: [bulk] auto [middle] min-content [search] minmax(min-content, 350px);
2384
2367
  }
2385
2368
 
2386
- .fixed-header-actions {
2369
+ .fixed-footer-actions {
2387
2370
  /* padding: 0 0 20px 0; */
2388
2371
  width: 100%;
2389
2372
  z-index: z-index('fixedTableHeader');
@@ -2499,6 +2482,114 @@ export default {
2499
2482
  }
2500
2483
  }
2501
2484
 
2485
+
2486
+ .fixed-header-table-actions {
2487
+ width: 100%;
2488
+ z-index: z-index('fixedTableHeader');
2489
+ background: transparent;
2490
+ display: flex;
2491
+ justify-content: space-between;
2492
+
2493
+
2494
+ .bulk {
2495
+ $gap: 10px;
2496
+
2497
+ & > BUTTON {
2498
+ display: none; // Handled dynamically
2499
+ }
2500
+
2501
+ & > BUTTON:not(:last-of-type) {
2502
+ margin-right: $gap;
2503
+ }
2504
+
2505
+ .action-availability {
2506
+ display: none; // Handled dynamically
2507
+ margin-left: $gap;
2508
+ vertical-align: middle;
2509
+ margin-top: 2px;
2510
+ }
2511
+
2512
+ .dropdown-button {
2513
+ $disabled-color: var(--disabled-text);
2514
+ $disabled-cursor: not-allowed;
2515
+ li.disabled {
2516
+ color: $disabled-color;
2517
+ cursor: $disabled-cursor;
2518
+
2519
+ &:hover {
2520
+ color: $disabled-color;
2521
+ background-color: unset;
2522
+ cursor: $disabled-cursor;
2523
+ }
2524
+ }
2525
+ }
2526
+
2527
+ .bulk-action {
2528
+ .icon {
2529
+ vertical-align: -10%;
2530
+ }
2531
+ }
2532
+ }
2533
+
2534
+ .middle {
2535
+ white-space: nowrap;
2536
+
2537
+ .icon.icon-backup.animate {
2538
+ animation-name: spin;
2539
+ animation-duration: 1000ms;
2540
+ animation-iteration-count: infinite;
2541
+ animation-timing-function: linear;
2542
+ }
2543
+
2544
+ @keyframes spin {
2545
+ from {
2546
+ transform:rotate(0deg);
2547
+ }
2548
+ to {
2549
+ transform:rotate(360deg);
2550
+ }
2551
+ }
2552
+ }
2553
+
2554
+ .search {
2555
+ text-align: right;
2556
+ justify-content: flex-end;
2557
+ }
2558
+
2559
+ .bulk-actions-dropdown {
2560
+ display: none; // Handled dynamically
2561
+
2562
+ .dropdown-button {
2563
+ background-color: var(--primary);
2564
+
2565
+ &:hover {
2566
+ background-color: var(--primary-hover-bg);
2567
+ color: var(--primary-hover-text);
2568
+ }
2569
+
2570
+ > *, .icon-chevron-down {
2571
+ color: var(--primary-text);
2572
+ }
2573
+
2574
+ .button-divider {
2575
+ border-color: var(--primary-text);
2576
+ }
2577
+
2578
+ &.disabled {
2579
+ border-color: var(--disabled-bg);
2580
+
2581
+ .icon-chevron-down {
2582
+ color: var(--disabled-text) !important;
2583
+ }
2584
+
2585
+ .button-divider {
2586
+ border-color: var(--disabled-text);
2587
+ }
2588
+ }
2589
+ }
2590
+ }
2591
+ }
2592
+
2502
2593
  .paging {
2503
2594
  //text-align: center;
2504
2595
  display: flex;
@@ -2511,6 +2602,7 @@ export default {
2511
2602
  SPAN {
2512
2603
  display: inline-block;
2513
2604
  //min-width: 200px;
2605
+ min-width: auto;
2514
2606
  }
2515
2607
 
2516
2608
  /* 针对Webkit浏览器(如Chrome, Safari) */
@@ -2547,6 +2639,7 @@ export default {
2547
2639
  margin-top: 0px !important;
2548
2640
  }
2549
2641
  .pageSelect {
2642
+ overflow: hidden;
2550
2643
  max-width: 100px;
2551
2644
  }
2552
2645
  .page-btn-normal {