feat(downloads): add column layout reset action
This commit is contained in:
@@ -512,6 +512,7 @@ export interface DownloadsTableHeaderProps {
|
|||||||
actions: DownloadsTableActions;
|
actions: DownloadsTableActions;
|
||||||
columnOrder: readonly string[];
|
columnOrder: readonly string[];
|
||||||
gridTemplate: string;
|
gridTemplate: string;
|
||||||
|
onResetColumnLayout?: () => void;
|
||||||
sortColumn: DownloadSortColumn;
|
sortColumn: DownloadSortColumn;
|
||||||
sortDirection: "asc" | "desc";
|
sortDirection: "asc" | "desc";
|
||||||
selectedCount: number;
|
selectedCount: number;
|
||||||
@@ -533,7 +534,7 @@ function moveColumnWithPointerActions(column: string, direction: -1 | 1, element
|
|||||||
actions.onColumnPointerUp(column, pointerEvent(clientX));
|
actions.onColumnPointerUp(column, pointerEvent(clientX));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function DownloadsTableHeader({ actions, columnOrder, gridTemplate, sortColumn, sortDirection, selectedCount, visibleIds }: DownloadsTableHeaderProps): ReactElement {
|
export function DownloadsTableHeader({ actions, columnOrder, gridTemplate, onResetColumnLayout, sortColumn, sortDirection, selectedCount, visibleIds }: DownloadsTableHeaderProps): ReactElement {
|
||||||
const allSelected = visibleIds.length > 0 && selectedCount === visibleIds.length;
|
const allSelected = visibleIds.length > 0 && selectedCount === visibleIds.length;
|
||||||
const mixedSelection = selectedCount > 0 && selectedCount < visibleIds.length;
|
const mixedSelection = selectedCount > 0 && selectedCount < visibleIds.length;
|
||||||
return (
|
return (
|
||||||
@@ -574,7 +575,7 @@ export function DownloadsTableHeader({ actions, columnOrder, gridTemplate, sortC
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
<span className="downloads-action-cell" role="columnheader">Aktion</span>
|
<span className="downloads-action-cell downloads-header-action-cell" role="columnheader"><span>Aktion</span>{onResetColumnLayout ? <button aria-label="Spaltenlayout zurücksetzen" className="downloads-column-reset-button" onClick={onResetColumnLayout} title="Spaltenlayout zurücksetzen" type="button">↺</button> : null}</span>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,6 +53,7 @@ export interface DownloadsViewModel extends DownloadsViewModelCore {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export interface DownloadsViewActions extends DownloadsTableActions {
|
export interface DownloadsViewActions extends DownloadsTableActions {
|
||||||
|
onResetColumnLayout: () => void;
|
||||||
onDisplayModeChange: (mode: DownloadDisplayMode) => void;
|
onDisplayModeChange: (mode: DownloadDisplayMode) => void;
|
||||||
onFilterChange: (filter: DownloadSidebarFilter) => void;
|
onFilterChange: (filter: DownloadSidebarFilter) => void;
|
||||||
onProviderFilterChange: (provider: string) => void;
|
onProviderFilterChange: (provider: string) => void;
|
||||||
@@ -148,7 +149,7 @@ export function DownloadsContent({ actions, model }: { actions: DownloadsViewAct
|
|||||||
return (
|
return (
|
||||||
<main className="downloads-content">
|
<main className="downloads-content">
|
||||||
<div className="downloads-table" role="table" aria-label="Downloads">
|
<div className="downloads-table" role="table" aria-label="Downloads">
|
||||||
<DownloadsTableHeader actions={actions} columnOrder={model.columnOrder} gridTemplate={model.gridTemplate} selectedCount={model.actionableSelectedIds.length} sortColumn={model.sortColumn ?? "name"} sortDirection={model.sortDirection ?? "asc"} visibleIds={model.visibleRowIds} />
|
<DownloadsTableHeader actions={actions} columnOrder={model.columnOrder} gridTemplate={model.gridTemplate} onResetColumnLayout={actions.onResetColumnLayout} selectedCount={model.actionableSelectedIds.length} sortColumn={model.sortColumn ?? "name"} sortDirection={model.sortDirection ?? "asc"} visibleIds={model.visibleRowIds} />
|
||||||
<VirtualizedDownloadsBody actions={actions} model={model} state={state} />
|
<VirtualizedDownloadsBody actions={actions} model={model} state={state} />
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -527,6 +527,21 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.downloads-header-action-cell {
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 1px;
|
||||||
|
line-height: 11px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.downloads-header-action-cell .downloads-column-reset-button {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
min-height: 20px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-size: 15px;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
.downloads-collapse-button {
|
.downloads-collapse-button {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
flex: 0 0 30px;
|
flex: 0 0 30px;
|
||||||
|
|||||||
@@ -95,6 +95,30 @@ describe("Downloadtabellen-Spalten", () => {
|
|||||||
expect(header.props.style.gridTemplateColumns).toBe(expected);
|
expect(header.props.style.gridTemplateColumns).toBe(expected);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("exposes a header action that delegates resetting the column layout", () => {
|
||||||
|
const reset = vi.fn();
|
||||||
|
const actions = createActions({ onResetColumnLayout: reset });
|
||||||
|
const model = withRuntime(createInput());
|
||||||
|
const content = renderToStaticMarkup(<DownloadsContent actions={actions} model={model} />);
|
||||||
|
const header = DownloadsTableHeader({
|
||||||
|
actions,
|
||||||
|
columnOrder: model.columnOrder,
|
||||||
|
gridTemplate: model.gridTemplate,
|
||||||
|
onResetColumnLayout: actions.onResetColumnLayout,
|
||||||
|
selectedCount: 0,
|
||||||
|
sortColumn: "name",
|
||||||
|
sortDirection: "asc",
|
||||||
|
visibleIds: model.visibleRowIds
|
||||||
|
});
|
||||||
|
const button = findElement(header, (element) => element.type === "button" && element.props["aria-label"] === "Spaltenlayout zurücksetzen");
|
||||||
|
|
||||||
|
button.props.onClick();
|
||||||
|
|
||||||
|
expect(content).toContain('aria-label="Spaltenlayout zurücksetzen"');
|
||||||
|
expect(button.props.title).toBe("Spaltenlayout zurücksetzen");
|
||||||
|
expect(reset).toHaveBeenCalledTimes(1);
|
||||||
|
});
|
||||||
|
|
||||||
it("never interpolates download grid tracks while column contents move", () => {
|
it("never interpolates download grid tracks while column contents move", () => {
|
||||||
const css = fs.readFileSync(path.join(process.cwd(), "src/renderer/views/downloads/downloads.css"), "utf8");
|
const css = fs.readFileSync(path.join(process.cwd(), "src/renderer/views/downloads/downloads.css"), "utf8");
|
||||||
|
|
||||||
@@ -651,6 +675,7 @@ function createLargeInput(packageCount: number, itemCount: number, overrides: Pa
|
|||||||
|
|
||||||
function createActions(overrides: Partial<DownloadsViewActions> = {}): DownloadsViewActions {
|
function createActions(overrides: Partial<DownloadsViewActions> = {}): DownloadsViewActions {
|
||||||
return {
|
return {
|
||||||
|
onResetColumnLayout: () => {},
|
||||||
onDisplayModeChange: () => {},
|
onDisplayModeChange: () => {},
|
||||||
onFilterChange: () => {},
|
onFilterChange: () => {},
|
||||||
onProviderFilterChange: () => {},
|
onProviderFilterChange: () => {},
|
||||||
|
|||||||
Reference in New Issue
Block a user