115 lines
3.7 KiB
TypeScript
115 lines
3.7 KiB
TypeScript
// file: kb-app-demo-desktop/frontend/ts/demo_store_block_pagination.ts
|
|
// version: 1
|
|
|
|
export type StoreBlockMetadata = {
|
|
blockSize: number;
|
|
blockIndex: number;
|
|
totalRows: string;
|
|
totalBlocks: number;
|
|
nextCursor: string | null;
|
|
};
|
|
|
|
export type StoreBlockState = {
|
|
blockSize: number;
|
|
currentBlock: number;
|
|
totalBlocks: number;
|
|
totalRows: string;
|
|
nextCursor: string | null;
|
|
cursors: Map<number, string | null>;
|
|
};
|
|
|
|
export type StoreBlockControls = {
|
|
firstSelector: string;
|
|
previousSelector: string;
|
|
nextSelector: string;
|
|
summarySelector: string;
|
|
};
|
|
|
|
export function createStoreBlockState(): StoreBlockState {
|
|
return {
|
|
blockSize: 500,
|
|
currentBlock: 0,
|
|
totalBlocks: 0,
|
|
totalRows: "0",
|
|
nextCursor: null,
|
|
cursors: new Map<number, string | null>([[1, null]]),
|
|
};
|
|
}
|
|
|
|
export function resetStoreBlockState(state: StoreBlockState): void {
|
|
state.blockSize = 500;
|
|
state.currentBlock = 0;
|
|
state.totalBlocks = 0;
|
|
state.totalRows = "0";
|
|
state.nextCursor = null;
|
|
state.cursors = new Map<number, string | null>([[1, null]]);
|
|
}
|
|
|
|
export function applyStoreBlockMetadata(
|
|
state: StoreBlockState,
|
|
metadata: StoreBlockMetadata,
|
|
controls: StoreBlockControls,
|
|
): void {
|
|
state.blockSize = metadata.blockSize;
|
|
state.currentBlock = metadata.blockIndex;
|
|
state.totalBlocks = metadata.totalBlocks;
|
|
state.totalRows = metadata.totalRows;
|
|
state.nextCursor = metadata.nextCursor;
|
|
if (metadata.blockIndex > 0 && metadata.nextCursor !== null) {
|
|
state.cursors.set(metadata.blockIndex + 1, metadata.nextCursor);
|
|
}
|
|
renderStoreBlockControls(state, controls);
|
|
}
|
|
|
|
export function renderStoreBlockControls(
|
|
state: StoreBlockState,
|
|
controls: StoreBlockControls,
|
|
): void {
|
|
const firstButton = document.querySelector<HTMLButtonElement>(controls.firstSelector);
|
|
const previousButton = document.querySelector<HTMLButtonElement>(controls.previousSelector);
|
|
const nextButton = document.querySelector<HTMLButtonElement>(controls.nextSelector);
|
|
const summary = document.querySelector<HTMLElement>(controls.summarySelector);
|
|
const hasRows = state.totalBlocks > 0;
|
|
if (firstButton !== null) {
|
|
firstButton.disabled = !hasRows || state.currentBlock <= 1;
|
|
}
|
|
if (previousButton !== null) {
|
|
previousButton.disabled = !hasRows || state.currentBlock <= 1;
|
|
}
|
|
if (nextButton !== null) {
|
|
nextButton.disabled = state.nextCursor === null;
|
|
}
|
|
if (summary !== null) {
|
|
summary.textContent = hasRows
|
|
? `Bloc ${state.currentBlock} / ${state.totalBlocks} · ${state.totalRows} résultat(s) · ${state.blockSize}/bloc`
|
|
: `Bloc 0 / 0 · 0 résultat · ${state.blockSize}/bloc`;
|
|
}
|
|
}
|
|
|
|
export function markStoreBlockFiltersDirty(
|
|
state: StoreBlockState,
|
|
controls: StoreBlockControls,
|
|
): void {
|
|
resetStoreBlockState(state);
|
|
const firstButton = document.querySelector<HTMLButtonElement>(controls.firstSelector);
|
|
const previousButton = document.querySelector<HTMLButtonElement>(controls.previousSelector);
|
|
const nextButton = document.querySelector<HTMLButtonElement>(controls.nextSelector);
|
|
const summary = document.querySelector<HTMLElement>(controls.summarySelector);
|
|
if (firstButton !== null) {
|
|
firstButton.disabled = true;
|
|
}
|
|
if (previousButton !== null) {
|
|
previousButton.disabled = true;
|
|
}
|
|
if (nextButton !== null) {
|
|
nextButton.disabled = true;
|
|
}
|
|
if (summary !== null) {
|
|
summary.textContent = "Filtres modifiés — rechargez le premier bloc.";
|
|
}
|
|
}
|
|
|
|
export function cursorForBlock(state: StoreBlockState, blockIndex: number): string | null | undefined {
|
|
return state.cursors.get(blockIndex);
|
|
}
|