@@ -455,13 +469,12 @@ const TableActionBar: React.FC = ({
)}
diff --git a/webui/react/src/e2e/models/components/TableActionBar.ts b/webui/react/src/e2e/models/components/TableActionBar.ts
index 17acec62672..433f339ea1f 100644
--- a/webui/react/src/e2e/models/components/TableActionBar.ts
+++ b/webui/react/src/e2e/models/components/TableActionBar.ts
@@ -26,6 +26,7 @@ export class TableActionBar extends NamedComponent {
heatmapToggle = new BaseComponent({ parent: this, selector: '[data-test="heatmapToggle"]' });
compare = new BaseComponent({ parent: this, selector: '[data-test="compare"]' });
clearSelection = new BaseComponent({ parent: this, selector: '[data-test="clear-selection"]' });
+ selectAll = new BaseComponent({ parent: this, selector: '[data-test="select-all"]' });
// TODO a bunch of modals
}
diff --git a/webui/react/src/e2e/tests/experimentList.spec.ts b/webui/react/src/e2e/tests/experimentList.spec.ts
index cd404d82e70..94f98b21631 100644
--- a/webui/react/src/e2e/tests/experimentList.spec.ts
+++ b/webui/react/src/e2e/tests/experimentList.spec.ts
@@ -59,10 +59,15 @@ test.describe('Experiment List', () => {
const count = await getCount();
if (count !== 0) {
await grid.headRow.clickSelectHeader();
- const isClearSelectionVisible =
- await projectDetailsPage.f_experimentList.tableActionBar.clearSelection.pwLocator.isVisible();
- if (isClearSelectionVisible) {
- await projectDetailsPage.f_experimentList.tableActionBar.clearSelection.pwLocator.click();
+ const selectAllButton = projectDetailsPage.f_experimentList.tableActionBar.selectAll;
+ const clearAllButton = projectDetailsPage.f_experimentList.tableActionBar.clearSelection;
+ if (await selectAllButton.pwLocator.isVisible()) {
+ await selectAllButton.pwLocator.click();
+ await clearAllButton.pwLocator.click();
+ } else if (await clearAllButton.pwLocator.isVisible()) {
+ await clearAllButton.pwLocator.click();
+ } else {
+ await grid.headRow.clickSelectHeader();
}
}
});
diff --git a/webui/react/src/pages/F_ExpList/F_ExperimentList.tsx b/webui/react/src/pages/F_ExpList/F_ExperimentList.tsx
index c816d04ec04..0314b426cbd 100644
--- a/webui/react/src/pages/F_ExpList/F_ExperimentList.tsx
+++ b/webui/react/src/pages/F_ExpList/F_ExperimentList.tsx
@@ -487,14 +487,6 @@ const F_ExperimentList: React.FC
= ({ project }) => {
[handleSelectionChange, openToast],
);
- const handleActualSelectAll = useCallback(() => {
- handleSelectionChange?.('add-all');
- }, [handleSelectionChange]);
-
- const handleClearSelect = useCallback(() => {
- handleSelectionChange?.('remove-all');
- }, [handleSelectionChange]);
-
const handleContextMenuComplete = useCallback(
(action: ExperimentAction, id: number, data?: Partial) =>
handleActionSuccess(action, [id], data),
@@ -987,12 +979,15 @@ const F_ExperimentList: React.FC = ({ project }) => {
compareViewOn={settings.compare}
entityCopy="Show experiments…"
formStore={formStore}
+ handleSelectionChange={handleSelectionChange}
heatmapBtnVisible={heatmapBtnVisible}
heatmapOn={settings.heatmapOn}
initialVisibleColumns={columnsIfLoaded}
isOpenFilter={isOpenFilter}
+ isRangeSelected={isRangeSelected}
labelPlural="experiments"
labelSingular="experiment"
+ pageSize={settings.pageLimit}
pinnedColumnsCount={settings.pinnedColumnsCount}
project={project}
projectColumns={projectColumns}
@@ -1005,8 +1000,6 @@ const F_ExperimentList: React.FC = ({ project }) => {
total={total}
onActionComplete={handleActionComplete}
onActionSuccess={handleActionSuccess}
- onActualSelectAll={handleActualSelectAll}
- onClearSelect={handleClearSelect}
onComparisonViewToggle={handleToggleComparisonView}
onHeatmapSelectionRemove={(id) => {
const newSelection = settings.heatmapSkipped.filter((s) => s !== id);
diff --git a/webui/react/src/pages/FlatRuns/FlatRuns.tsx b/webui/react/src/pages/FlatRuns/FlatRuns.tsx
index e9fbc37c353..389c01b08ea 100644
--- a/webui/react/src/pages/FlatRuns/FlatRuns.tsx
+++ b/webui/react/src/pages/FlatRuns/FlatRuns.tsx
@@ -46,7 +46,7 @@ import {
SpecialColumnNames,
} from 'components/FilterForm/components/type';
import TableFilter from 'components/FilterForm/TableFilter';
-import LoadableCount from 'components/LoadableCount';
+import LoadableCount, { SelectionAction } from 'components/LoadableCount';
import MultiSortMenu, { EMPTY_SORT, sortMenuItemsForColumn } from 'components/MultiSortMenu';
import { OptionsMenu, RowHeight } from 'components/OptionsMenu';
import {
@@ -779,21 +779,13 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => {
[updateSettings],
);
- const handleActualSelectAll = useCallback(() => {
- handleSelectionChange?.('add-all');
- }, [handleSelectionChange]);
-
- const handleClearSelect = useCallback(() => {
- handleSelectionChange?.('remove-all');
- }, [handleSelectionChange]);
-
const handleHeaderClick = useCallback(
(columnId: string): void => {
if (columnId === MULTISELECT) {
if (isRangeSelected([0, settings.pageLimit])) {
- handleSelectionChange?.('remove', [0, settings.pageLimit]);
+ handleSelectionChange('remove', [0, settings.pageLimit]);
} else {
- handleSelectionChange?.('add', [0, settings.pageLimit]);
+ handleSelectionChange('add', [0, settings.pageLimit]);
}
}
},
@@ -975,6 +967,20 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => {
};
}, [canceler, stopPolling]);
+ const selectionAction: SelectionAction = useMemo(() => {
+ return total.match({
+ _: () => 'NONE' as const,
+ Loaded: (loadedTotal) => {
+ if (isRangeSelected([0, settings.pageLimit]) && selectionSize < loadedTotal) {
+ return 'SELECT_ALL';
+ } else if (selectionSize > settings.pageLimit) {
+ return 'CLEAR_SELECTION';
+ }
+ return 'NONE';
+ },
+ });
+ }, [isRangeSelected, selectionSize, settings.pageLimit, total]);
+
return (
@@ -1029,13 +1035,12 @@ const FlatRuns: React.FC = ({ projectId, workspaceId, searchId }) => {
onActionComplete={onActionComplete}
/>