dashboard-shell-shell 1.0.1000000113 → 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 (125) 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 -25
  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 +480 -370
  35. package/components/Tabbed/index.vue +4 -5
  36. package/components/auth/Principal.vue +3 -2
  37. package/components/auth/RoleDetailEdit.vue +59 -6
  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/router/navigation-guards/index.js +3 -3
  66. package/config/settings.ts +28 -0
  67. package/edit/management.cattle.io.user.vue +17 -4
  68. package/edit/networking.k8s.io.ingress/RulePath.vue +1 -1
  69. package/edit/token.vue +1 -1
  70. package/list/harvesterhci.io.management.cluster.vue +17 -0
  71. package/list/management.cattle.io.setting.vue +22 -13
  72. package/list/management.cattle.io.user.vue +25 -14
  73. package/list/provisioning.cattle.io.cluster.vue +6 -7
  74. package/mixins/brand.js +17 -0
  75. package/package.json +1 -1
  76. package/pages/auth/login.vue +84 -29
  77. package/pages/c/_cluster/auth/roles/index.vue +61 -14
  78. package/pages/c/_cluster/settings/banners.vue +174 -101
  79. package/pages/c/_cluster/settings/brand.vue +348 -301
  80. package/pages/c/_cluster/settings/performance.vue +61 -38
  81. package/pages/home.vue +70 -21
  82. package/pages/prefs.vue +25 -23
  83. package/pkg/tsconfig.json +9 -9
  84. package/pkg/vue.config.js +1 -1
  85. package/promptRemove/mixin/roleDeletionCheck.js +2 -2
  86. package/scripts/clean +0 -0
  87. package/scripts/extension/bundle +0 -0
  88. package/scripts/extension/helm/scripts/package +0 -0
  89. package/scripts/extension/helm/scripts/patch +0 -0
  90. package/scripts/extension/helm/scripts/version +0 -0
  91. package/scripts/extension/helmpatch +0 -0
  92. package/scripts/extension/parse-tag-name +0 -0
  93. package/scripts/extension/publish +0 -0
  94. package/scripts/publish-shell.sh +86 -60
  95. package/scripts/serve-pkgs +0 -0
  96. package/scripts/sync-shell-deps +0 -0
  97. package/scripts/typegen.sh +44 -28
  98. package/store/i18n.js +5 -5
  99. package/store/prefs.js +17 -5
  100. package/store/type-map.js +2 -1
  101. package/types/shell/index.d.ts +1 -1
  102. package/utils/error.js +4 -0
  103. package/utils/router.js +4 -4
  104. package/vue.config.js +1 -6
  105. package/components/rancherResourceDetail/Masthead.vue +0 -769
  106. package/components/rancherResourceDetail/__tests__/Masthead.test.ts +0 -65
  107. package/components/rancherResourceDetail/index.vue +0 -591
  108. package/components/rancherResourceList/Masthead.vue +0 -375
  109. package/components/rancherResourceList/ResourceLoadingIndicator.vue +0 -140
  110. package/components/rancherResourceList/index.vue +0 -307
  111. package/components/rancherResourceList/resource-list.config.js +0 -7
  112. package/components/rancherResourceTable.vue +0 -783
  113. package/components/rancherSortableTable/THead.vue +0 -561
  114. package/components/rancherSortableTable/actions.js +0 -153
  115. package/components/rancherSortableTable/advanced-filtering.js +0 -272
  116. package/components/rancherSortableTable/debug.js +0 -117
  117. package/components/rancherSortableTable/filtering.js +0 -290
  118. package/components/rancherSortableTable/grouping.js +0 -48
  119. package/components/rancherSortableTable/index.vue +0 -2712
  120. package/components/rancherSortableTable/paging.js +0 -155
  121. package/components/rancherSortableTable/selection.js +0 -629
  122. package/components/rancherSortableTable/sortable-config.ts +0 -4
  123. package/components/rancherSortableTable/sorting.js +0 -129
  124. package/types/cloud-shell/index.d.ts +0 -11014
  125. /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';
@@ -416,7 +417,7 @@ export default {
416
417
  const isLoading = this.loading || false;
417
418
 
418
419
  let isCreatable = false;
419
- const lastPath = this.$route.path.split('/'.pop());
420
+ const lastPath = this.$route?.path.split('/').pop();
420
421
 
421
422
  if (lastPath.includes('.')) {
422
423
  isCreatable = this.$store.getters['type-map/optionsFor'](lastPath).isCreatable;
@@ -612,17 +613,22 @@ export default {
612
613
  }
613
614
  };
614
615
 
615
- onMounted(() => {
616
- table.value.addEventListener('keyup', handleEnterKey);
617
- });
618
616
 
619
617
  onBeforeUnmount(() => {
620
- table.value.removeEventListener('keyup', handleEnterKey);
618
+ table.value && table.value.removeEventListener('keyup', handleEnterKey);
621
619
  });
622
620
 
623
621
  const store = useStore();
624
622
  const { featureDropdownMenu } = useRuntimeFlag(store);
625
623
 
624
+ onMounted(() => {
625
+ table.value && table.value.addEventListener('keyup', handleEnterKey);
626
+
627
+ console.log(featureDropdownMenu, ' featureDropdownMenu---------------------');
628
+
629
+
630
+ });
631
+
626
632
  return {
627
633
  table,
628
634
  featureDropdownMenu,
@@ -851,6 +857,25 @@ export default {
851
857
  },
852
858
 
853
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
+ // },
854
879
  onTableScroll(table, e) {
855
880
  // 记录最后滚动的距离
856
881
  let lastScrollTop = 0;
@@ -1224,38 +1249,30 @@ export default {
1224
1249
  ref="container"
1225
1250
  :data-testid="componentTestid + '-list-container'"
1226
1251
  >
1252
+ <!-- 主标题和过滤器区域 -->
1227
1253
  <div
1228
- :class="{'titled': $slots.title && $slots.title.length, 'mb-40': isFilterLabel, 'mb-20': search || isCreatable}"
1229
- class="sortable-table-header "
1230
- :style="{marginTop: search&& !isBanner ? marginTopValue + 'px' : '0px',marginLeft: isCreatable ? '100px' : '-10px',maxHeight: '32px'}"
1254
+ :class="{'titled': $slots.title && $slots.title.length, 'mb-40': isFilterLabel}"
1255
+ class="sortable-table-header mb-20"
1231
1256
  >
1232
1257
  <slot name="title" />
1258
+
1259
+ <!-- 顶部功能行区域 -->
1233
1260
  <div
1234
1261
  v-if="showHeaderRow"
1235
- class="fixed-header-actions"
1262
+ class="fixed-header-table-actions"
1236
1263
  :class="{button: !!$slots['header-button'], 'advanced-filtering': hasAdvancedFiltering, }"
1237
1264
  style="display: flex;"
1238
1265
  >
1239
- <!-- <div
1240
- :class="bulkActionsClass"
1241
- class="bulk"
1242
- >
1243
-
1244
- </div> -->
1245
- <div
1246
- v-if="!hasAdvancedFiltering && $slots['header-middle']"
1247
- class="middle"
1248
- style="margin-left: 10px;margin-right: -10px;"
1249
- >
1250
- <slot name="header-middle" />
1251
- </div>
1252
1266
 
1267
+ <!-- 搜索栏、右插槽、刷新按钮、高级筛选等区域 -->
1253
1268
  <div
1254
1269
  v-if="search || hasAdvancedFiltering || isTooManyItemsToAutoUpdate || $slots['header-right']"
1255
1270
  class="search row"
1256
1271
  data-testid="search-box-filter-row"
1257
- style="max-height: 32px;display: contents;"
1272
+ style="max-height: 32px;"
1258
1273
  >
1274
+
1275
+ <!-- 已应用的高级筛选 -->
1259
1276
  <ul
1260
1277
  v-if="hasAdvancedFiltering"
1261
1278
  class="advanced-filters-applied"
@@ -1272,14 +1289,9 @@ export default {
1272
1289
  <div class="bg" />
1273
1290
  </li>
1274
1291
  </ul>
1292
+
1275
1293
  <slot name="header-right" />
1276
- <AsyncButton
1277
- v-if="isTooManyItemsToAutoUpdate"
1278
- mode="manual-refresh"
1279
- :size="manualRefreshButtonSize"
1280
- :current-phase="refreshButtonPhase"
1281
- @click="debouncedRefreshTableData"
1282
- />
1294
+
1283
1295
  <div
1284
1296
  v-if="hasAdvancedFiltering"
1285
1297
  ref="advanced-filter-group"
@@ -1335,6 +1347,8 @@ export default {
1335
1347
  </div>
1336
1348
  </div>
1337
1349
  </div>
1350
+
1351
+ <!-- 搜索描述文本(隐藏) -->
1338
1352
  <p
1339
1353
  v-else-if="search"
1340
1354
  id="describe-filter-sortable-table"
@@ -1342,326 +1356,357 @@ export default {
1342
1356
  >
1343
1357
  {{ t('sortableTable.filteringDescription') }}
1344
1358
  </p>
1345
- <slot name="header-button" />
1346
- <input
1347
- v-if="search"
1348
- ref="searchQuery"
1349
- v-model="eventualSearchQuery"
1350
- type="search"
1351
- class="input-sm search-box"
1352
- :aria-label="t('sortableTable.searchLabel')"
1353
- aria-describedby="describe-filter-sortable-table"
1354
- :placeholder="t('sortableTable.search')+searchPlaceholder"
1355
- >
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>
1356
1390
 
1357
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>
1358
1401
  </div>
1359
1402
  </div>
1403
+
1360
1404
  <div v-if="$slots['banner']">
1361
1405
  <slot name="banner"></slot>
1362
1406
  </div>
1363
- <div class="sort-table-div">
1364
- <table
1365
- ref="table"
1366
- class="sortable-table"
1367
- :class="classObject"
1368
- width="100%"
1369
- role="table"
1370
- >
1371
- <THead
1372
- v-if="showHeaders"
1373
- :label-for="labelFor"
1374
- :columns="columns"
1375
- :group="group"
1376
- :group-options="advGroupOptions"
1377
- :has-advanced-filtering="hasAdvancedFiltering"
1378
- :adv-filter-hide-labels-as-cols="advFilterHideLabelsAsCols"
1379
- :table-actions="tableActions"
1380
- :table-cols-options="columnOptions"
1381
- :row-actions="rowActions"
1382
- :sub-expand-column="subExpandColumn"
1383
- :row-actions-width="rowActionsWidth"
1384
- :how-much-selected="howMuchSelected"
1385
- :sort-by="sortBy"
1386
- :default-sort-by="_defaultSortBy"
1387
- :descending="descending"
1388
- :no-rows="noRows"
1389
- :loading="isLoading && !loadingDelay"
1390
- :no-results="noResults"
1391
- @on-toggle-all="onToggleAll"
1392
- @on-sort-change="changeSort"
1393
- @col-visibility-change="changeColVisibility"
1394
- @group-value-change="(val) => $emit('group-value-change', val)"
1395
- @update-cols-options="updateColsOptions"
1396
- />
1397
1407
 
1398
- <!-- Don't display anything if we're loading and the delay has yet to pass -->
1399
- <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
+ />
1400
1442
 
1401
- <tbody v-else-if="isLoading && !altLoading">
1402
- <slot name="loading">
1403
- <tr>
1404
- <td :colspan="fullColspan">
1405
- <div class="data-loading">
1406
- <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">
1407
1465
  <t
1408
- k="generic.loading"
1409
- :raw="true"
1466
+ v-if="showNoRows"
1467
+ :k="noRowsKey"
1410
1468
  />
1411
- </div>
1412
- </td>
1413
- </tr>
1414
- </slot>
1415
- </tbody>
1416
- <tbody v-else-if="noRows">
1417
- <slot name="no-rows">
1418
- <tr class="no-rows">
1419
- <td :colspan="fullColspan">
1420
- <t
1421
- v-if="showNoRows"
1422
- :k="noRowsKey"
1423
- />
1424
- </td>
1425
- </tr>
1426
- </slot>
1427
- </tbody>
1428
- <tbody v-else-if="noResults">
1429
- <slot name="no-results">
1430
- <tr class="no-results">
1431
- <td
1432
- :colspan="fullColspan"
1433
- class="text-center"
1434
- >
1435
- <t :k="noDataKey" />
1436
- </td>
1437
- </tr>
1438
- </slot>
1439
- </tbody>
1440
- <tbody
1441
- v-for="(groupedRows) in displayRows"
1442
- v-else
1443
- :key="groupedRows.key"
1444
- tabindex="-1"
1445
- :class="{ group: groupBy }"
1446
- >
1447
- <slot
1448
- v-if="groupBy"
1449
- name="group-row"
1450
- :group="groupedRows"
1451
- :fullColspan="fullColspan"
1452
- >
1453
- <tr class="group-row">
1454
- <td :colspan="fullColspan">
1455
- <slot
1456
- name="group-by"
1457
- :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"
1458
1479
  >
1459
- <div
1460
- v-trim-whitespace
1461
- class="group-tab"
1462
- >
1463
- {{ groupedRows.ref }}
1464
- </div>
1465
- </slot>
1466
- </td>
1467
- </tr>
1468
- </slot>
1469
- <template
1470
- v-for="(row, i) in groupedRows.rows"
1471
- :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 }"
1472
1491
  >
1473
1492
  <slot
1474
- name="main-row"
1475
- :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"
1476
1517
  >
1477
1518
  <slot
1478
- :name="'main-row:' + (row.row.mainRowKey || i)"
1479
- :full-colspan="fullColspan"
1519
+ name="main-row"
1520
+ :row="row.row"
1480
1521
  >
1481
- <!-- The data-cant-run-bulk-action-of-interest attribute is being used instead of :class because
1482
- because our selection.js invokes toggleClass and :class clobbers what was added by toggleClass if
1483
- the value of :class changes. -->
1484
- <tr
1485
- class="main-row"
1486
- :data-testid="componentTestid + '-' + i + '-row'"
1487
- :class="{ 'has-sub-row': row.showSubRow}"
1488
- :data-node-id="row.key"
1489
- :data-cant-run-bulk-action-of-interest="actionOfInterest && !row.canRunBulkActionOfInterest"
1522
+ <slot
1523
+ :name="'main-row:' + (row.row.mainRowKey || i)"
1524
+ :full-colspan="fullColspan"
1490
1525
  >
1491
- <td
1492
- v-if="tableActions"
1493
- class="row-check"
1494
- align="middle"
1495
- >
1496
- {{ row.mainRowKey }}
1497
- <Checkbox
1498
- class="selection-checkbox"
1499
- :data-node-id="row.key"
1500
- :data-testid="componentTestid + '-' + i + '-checkbox'"
1501
- :value="selectedRows.includes(row.row)"
1502
- :alternate-label="t('sortableTable.genericRowCheckbox', { item: row && row.row ? row.row.id : '' })"
1503
- />
1504
- </td>
1505
- <td
1506
- v-if="subExpandColumn"
1507
- class="row-expand"
1508
- align="middle"
1509
- >
1510
- <i
1511
- data-title="Toggle Expand"
1512
- :class="{
1513
- icon: true,
1514
- 'icon-chevron-right': !expanded[row.row[keyField]],
1515
- 'icon-chevron-down': !!expanded[row.row[keyField]]
1516
- }"
1517
- @click.stop="toggleExpand(row.row)"
1518
- />
1519
- </td>
1520
- <template
1521
- v-for="(col, j) in row.columns"
1522
- :key="j"
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"
1523
1535
  >
1524
- <slot
1525
- :name="'col:' + col.col.name"
1526
- :row="row.row"
1527
- :col="col.col"
1528
- :dt="dt"
1529
- :expanded="expanded"
1530
- :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"
1554
+ >
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"
1531
1568
  >
1532
- <td
1533
- v-show="!hasAdvancedFiltering || (hasAdvancedFiltering && col.col.isColVisible)"
1534
- :key="col.col.name"
1535
- :data-title="col.col.label"
1536
- :data-testid="`sortable-cell-${ i }-${ j }`"
1537
- :align="col.col.align || 'left'"
1538
- :class="{['col-'+col.dasherize]: !!col.col.formatter, [col.col.breakpoint]: !!col.col.breakpoint, ['skip-select']: col.col.skipSelect}"
1539
- :width="col.col.width"
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"
1540
1576
  >
1541
- <slot
1542
- :name="'cell:' + col.col.name"
1543
- :row="row.row"
1544
- :col="col.col"
1545
- :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"
1546
1585
  >
1547
- <component
1548
- :is="col.component"
1549
- v-if="col.component && col.needRef"
1550
- ref="column"
1551
- :value="col.value"
1586
+ <slot
1587
+ :name="'cell:' + col.col.name"
1552
1588
  :row="row.row"
1553
1589
  :col="col.col"
1554
- :get-custom-detail-link="getCustomDetailLink"
1555
- v-bind="col.col.formatterOpts"
1556
- :row-key="row.key"
1557
- />
1558
- <component
1559
- :is="col.component"
1560
- v-else-if="col.component"
1561
1590
  :value="col.value"
1562
- :row="row.row"
1563
- :col="col.col"
1564
- v-bind="col.col.formatterOpts"
1565
- :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 || '' })"
1566
1648
  />
1567
- <component
1568
- :is="col.col.formatter"
1569
- v-else-if="col.col.formatter"
1570
- :value="col.value"
1571
- :row="row.row"
1572
- :col="col.col"
1573
- v-bind="col.col.formatterOpts"
1574
- :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)"
1575
1662
  />
1576
- <template v-else-if="col.value !== ''">
1577
- {{ col.formatted }}
1578
- </template>
1579
- <template v-else-if="col.col.dashIfEmpty">
1580
- <span class="text-muted">&mdash;</span>
1581
- </template>
1582
- </slot>
1583
- </td>
1584
- </slot>
1585
- </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
+ >
1586
1689
  <td
1587
- v-if="rowActions"
1588
- :align="'left'"
1589
- style="height:60px"
1690
+ v-if="tableActions"
1691
+ class="row-check"
1692
+ align="middle"
1693
+ />
1694
+ <td
1695
+ :colspan="fullColspan - (tableActions ? 1: 0)"
1696
+ :class="{ 'text-error' : row.row.stateObj.error }"
1590
1697
  >
1591
- <div style="display: flex;align-items: center;">
1592
- <slot
1593
- name="row-actions"
1594
- :row="row.row"
1595
- :index="i"
1596
- >
1597
- </slot>
1598
- <template v-if="featureDropdownMenu">
1599
- <ActionMenu
1600
- :resource="row.row"
1601
- :data-testid="componentTestid + '-' + i + '-action-button'"
1602
- :button-aria-label="t('sortableTable.tableActionsLabel', { resource: row?.row?.id || '' })"
1603
- />
1604
- </template>
1605
- <template v-else>
1606
- <ButtonMultiAction
1607
- :id="`actionButton+${i}+${(row.row && row.row.name) ? row.row.name : ''}`"
1608
- :ref="`actionButton${i}`"
1609
- aria-haspopup="true"
1610
- aria-expanded="false"
1611
- :aria-label="t('sortableTable.tableActionsLabel', { resource: row?.row?.id || '' })"
1612
- :data-testid="componentTestid + '-' + i + '-action-button'"
1613
- :borderless="true"
1614
- @click="handleActionButtonClick(i, $event)"
1615
- @keyup.enter="handleActionButtonClick(i, $event)"
1616
- @keyup.space="handleActionButtonClick(i, $event)"
1617
- />
1618
- </template>
1619
- </div>
1698
+ {{ row.row.stateDescription }}
1620
1699
  </td>
1621
1700
  </tr>
1622
- </slot>
1623
- </slot>
1624
- <!-- <slot
1625
- v-if="row.showSubRow"
1626
- name="sub-row"
1627
- :full-colspan="fullColspan"
1628
- :row="row.row"
1629
- :sub-matches="subMatches"
1630
- :keyField="keyField"
1631
- :componentTestid="componentTestid"
1632
- :i="i"
1633
- :onRowMouseEnter="onRowMouseEnter"
1634
- :onRowMouseLeave="onRowMouseLeave"
1635
- >
1636
- <tr
1637
- v-if="row.row.stateDescription"
1638
- :key="row.row[keyField] + '-description'"
1639
- :data-testid="componentTestid + '-' + i + '-row-description'"
1640
- class="state-description sub-row"
1641
- @mouseenter="onRowMouseEnter"
1642
- @mouseleave="onRowMouseLeave"
1643
- >
1644
- <td
1645
- v-if="tableActions"
1646
- class="row-check"
1647
- align="middle"
1648
- />
1649
- <td
1650
- :colspan="fullColspan - (tableActions ? 1: 0)"
1651
- :class="{ 'text-error' : row.row.stateObj.error }"
1652
- >
1653
- {{ row.row.stateDescription }}
1654
- </td>
1655
- </tr>
1656
- </slot> -->
1657
- </template>
1658
- </tbody>
1659
- </table>
1660
- </div>
1701
+ </slot> -->
1702
+ </template>
1703
+ </tbody>
1704
+ </table>
1705
+ </div>
1661
1706
  <div
1662
1707
  v-if="!noRows && !noResults"
1663
1708
  :class="$route.path=== '/account'? 'chebox-padding':''"
1664
- 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"
1665
1710
  >
1666
1711
  <div style="display: flex;justify-content: center;height: 32px;">
1667
1712
  <Checkbox
@@ -1682,7 +1727,7 @@ export default {
1682
1727
  <slot name="title" />
1683
1728
  <div
1684
1729
  v-if="showHeaderRow"
1685
- class="fixed-header-actions"
1730
+ class="fixed-footer-actions"
1686
1731
  :class="{button: !!$slots['header-button'], 'advanced-filtering': hasAdvancedFiltering,}"
1687
1732
  >
1688
1733
  <div
@@ -1708,10 +1753,11 @@ export default {
1708
1753
  @mouseover="setBulkActionOfInterest(act)"
1709
1754
  @mouseleave="setBulkActionOfInterest(null)"
1710
1755
  >
1711
- <i
1756
+ <!-- <i
1712
1757
  v-if="act.icon"
1713
1758
  :class="act.icon"
1714
- />
1759
+ style="line-height: 12px;height: 12px;font-size: 12px;"
1760
+ /> -->
1715
1761
  <span v-clean-html="act.label" />
1716
1762
  </button>
1717
1763
  <template v-if="featureDropdownMenu">
@@ -1886,7 +1932,7 @@ export default {
1886
1932
 
1887
1933
  <!-- 分页页码切换 -->
1888
1934
  <Select
1889
- :mode="inputPerPage"
1935
+ :mode="inputPerPage"
1890
1936
  :searchable="false"
1891
1937
  :clearable="false"
1892
1938
  :options="perPageOptions"
@@ -2147,77 +2193,32 @@ export default {
2147
2193
  td {
2148
2194
  padding: 8px 5px;
2149
2195
  border: 0;
2150
- background: var(--sortable-table-row-bg);
2151
2196
 
2152
2197
  &:first-child {
2153
2198
  padding-left: 10px;
2154
- position: sticky;
2155
- left: 0;
2156
- z-index: 2;
2157
- }
2158
- &:nth-child(2) {
2159
- padding-left: 10px;
2160
- position: sticky;
2161
- left: 29px;
2162
- z-index: 2;
2163
2199
  }
2164
2200
 
2165
2201
  &:last-child {
2166
2202
  padding-right: 10px;
2167
- position: sticky;
2168
- right: 0;
2169
- z-index: 2;
2170
- /* padding-left: 10px; */
2171
2203
  }
2172
2204
 
2173
2205
  &.row-check {
2174
2206
  padding-top: 12px;
2175
- right: 0;
2176
- position: sticky;
2177
2207
  }
2178
2208
  }
2179
- th {
2180
- padding: 13px 5px;
2181
- border: 0;
2182
- /* height: 50.84px; */
2183
- box-sizing: border-box;
2184
- background: var(--sortable-table-header-bg);
2185
2209
 
2186
- &:first-child {
2187
- padding-left: 10px;
2188
- position: sticky;
2189
- left: 0;
2190
- z-index: 2;
2191
- }
2192
- &:nth-child(2) {
2193
- padding-left: 10px;
2194
- position: sticky;
2195
- left: 29px;
2196
- z-index: 2;
2197
- }
2198
-
2199
- &:last-child {
2200
- padding-left: 10px;
2201
- padding-right: 10px;
2202
- position: sticky;
2203
- right: 0;
2204
- z-index: 2;
2205
- }
2206
-
2207
- }
2208
2210
  tbody {
2209
2211
  tr {
2210
2212
  border-bottom: 1px solid var(--sortable-table-top-divider);
2211
2213
  background-color: var(--sortable-table-row-bg);
2212
- height: 60px;
2213
2214
 
2214
2215
  &.main-row.has-sub-row {
2215
- /* border-bottom: 0; */
2216
+ border-bottom: 0;
2216
2217
  }
2217
2218
 
2218
2219
  // if a main-row is hovered also hover it's sibling sub row. note - the reverse is handled in selection.js
2219
2220
  &.main-row:not(.row-selected):hover + .sub-row {
2220
- /* background-color: var(--sortable-table-hover-bg); */
2221
+ background-color: var(--sortable-table-hover-bg);
2221
2222
  }
2222
2223
 
2223
2224
  &:last-of-type {
@@ -2270,7 +2271,6 @@ export default {
2270
2271
 
2271
2272
  tr.group-row {
2272
2273
  background-color: initial;
2273
- height: 40px;
2274
2274
 
2275
2275
  &:first-child {
2276
2276
  border-bottom: 2px solid var(--sortable-table-row-bg);
@@ -2362,11 +2362,11 @@ export default {
2362
2362
  align-items: center;
2363
2363
  }
2364
2364
  }
2365
- .fixed-header-actions.button{
2365
+ .fixed-footer-actions.button{
2366
2366
  grid-template-columns: [bulk] auto [middle] min-content [search] minmax(min-content, 350px);
2367
2367
  }
2368
2368
 
2369
- .fixed-header-actions {
2369
+ .fixed-footer-actions {
2370
2370
  /* padding: 0 0 20px 0; */
2371
2371
  width: 100%;
2372
2372
  z-index: z-index('fixedTableHeader');
@@ -2482,6 +2482,114 @@ export default {
2482
2482
  }
2483
2483
  }
2484
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
+
2485
2593
  .paging {
2486
2594
  //text-align: center;
2487
2595
  display: flex;
@@ -2494,6 +2602,7 @@ export default {
2494
2602
  SPAN {
2495
2603
  display: inline-block;
2496
2604
  //min-width: 200px;
2605
+ min-width: auto;
2497
2606
  }
2498
2607
 
2499
2608
  /* 针对Webkit浏览器(如Chrome, Safari) */
@@ -2530,6 +2639,7 @@ export default {
2530
2639
  margin-top: 0px !important;
2531
2640
  }
2532
2641
  .pageSelect {
2642
+ overflow: hidden;
2533
2643
  max-width: 100px;
2534
2644
  }
2535
2645
  .page-btn-normal {