Skip to content
Merged

Table #119

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions src/lib/components/Table/TableContent.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@
toggle = false, // Whether to display the fitToScreen toggle
search = true, // Whether to display the search input
pageSizes = [5, 10, 20, 50, 100], // Page sizes to display in the pagination component
pageIndexStringType = 'items', // items by default
fitToScreen = true, // Whether to fit the table to the screen,
exportable = false, // Whether to display the export button and enable export functionality
server
Expand Down Expand Up @@ -644,7 +643,7 @@
? utils.minWidth(cell.id, columns)
: $colWidths[index]
}px;`
: 'max-width: min-content;'}
: ''}
>
<Render of={cell.render()} />
</div>
Expand Down Expand Up @@ -686,7 +685,6 @@
{serverItemCount}
updateTable={updateTableWithParams}
{pageSizes}
{pageIndexStringType}
id={tableId}
/>
{:else}
Expand All @@ -695,7 +693,6 @@
pageConfig={pluginStates.page}
{pageSizes}
id={tableId}
{pageIndexStringType}
/>
{/if}
{/if}
Expand Down
122 changes: 28 additions & 94 deletions src/lib/components/Table/TablePagination.svelte
Original file line number Diff line number Diff line change
@@ -1,41 +1,17 @@
<script lang="ts">
import Fa from 'svelte-fa';
import {
faAnglesRight,
faAngleRight,
faAnglesLeft,
faAngleLeft,
faChevronDown
} from '@fortawesome/free-solid-svg-icons';
import { ListBox, ListBoxItem, popup, type PopupSettings } from '@skeletonlabs/skeleton';
import { faChevronDown } from '@fortawesome/free-solid-svg-icons';
import { ListBox, ListBoxItem, Paginator, popup } from '@skeletonlabs/skeleton';
import type { PopupSettings } from '@skeletonlabs/skeleton';

export let itemCount;
export let pageConfig;
export let pageSizes;
export let pageIndexStringType;
export let id;

let indexInformation = '';

const { pageIndex, pageCount, pageSize, hasNextPage, hasPreviousPage } = pageConfig;

const goToFirstPage = () => ($pageIndex = 0);
const goToLastPage = () => ($pageIndex = $pageCount - 1);
const goToNextPage = () => ($pageIndex += 1);
const goToPreviousPage = () => ($pageIndex -= 1);

// Handles the input change event
const handleChange = (e) => {
const value = e.target.value;

if (value > $pageCount) {
$pageIndex = $pageCount - 1;
} else if (value < 1) {
$pageIndex = 0;
} else {
$pageIndex = value - 1;
}
};
const { pageIndex, pageCount, pageSize } = pageConfig;

let pageSizeDropdownValue: string = $pageSize;

Expand All @@ -47,46 +23,34 @@
};

const getIndexInfomationString = () => {
if (pageIndexStringType === 'pages') {
return $pageCount > 0 ? `Page ${$pageIndex + 1} of ${$pageCount}` : 'No pages';
} else {
return itemCount === 0 ? 'No items' : `Displaying items ${$pageIndex * $pageSize + 1} - ${Math.min(
($pageIndex + 1) * $pageSize,
itemCount
)} of ${Math.min($pageCount * $pageSize, itemCount)}`;
}
return itemCount === 0
? 'No items'
: `Displaying items ${$pageIndex * $pageSize + 1} - ${Math.min(
($pageIndex + 1) * $pageSize,
itemCount
)} of ${Math.min($pageCount * $pageSize, itemCount)}`;
};

$: goToFirstPageDisabled = !$pageIndex;
$: goToLastPageDisabled = $pageIndex == $pageCount - 1;
$: goToNextPageDisabled = !$hasNextPage;
$: goToPreviousPageDisabled = !$hasPreviousPage;
$: paginationSettings = {
size: itemCount,
limit: $pageSize,
page: $pageIndex,
amounts: pageSizes
};
$: $pageSize = pageSizeDropdownValue;
$: $pageCount, $pageIndex, $pageSize, itemCount, (indexInformation = getIndexInfomationString());
</script>

<div class="flex justify-between w-full items-stretch gap-10">
<div class="grid grid-cols-3 w-full items-stretch gap-10">
<div class="flex justify-start">
<!-- <select
name="pageSize"
id="{id}-pageSize"
class="select variant-filled-primary w-min font-bold"
bind:value={$pageSize}
>
{#each pageSizes as size}
<option value={size} class="">{size}</option>
{/each}
</select> -->

<button
aria-label="Open menu to select number of items to display per page"
class="btn variant-filled-primary w-20 justify-between"
class="btn variant-filled-primary w-20 !px-3 !py-1.5 justify-between"
use:popup={pageSizePopup}
>
<span class="capitalize font-semibold">{pageSizeDropdownValue}</span>
<Fa icon={faChevronDown} size="xs" />
</button>

<div class="card w-20 shadow-xl py-2" data-popup={`#${id}-pageSizeDropdown`}>
<ListBox rounded="rounded-none">
{#each pageSizes as size}
Expand All @@ -98,48 +62,18 @@
<div class="arrow bg-surface-100-800-token" />
</div>
</div>
<div class="flex justify-center gap-1">
<button
class="btn btn-sm variant-filled-primary"
on:click|preventDefault={goToFirstPage}
aria-label="Go to first page"
disabled={goToFirstPageDisabled}
id="{id}-first"
>
<Fa icon={faAnglesLeft} /></button
>
<button
class="btn btn-sm variant-filled-primary"
id="{id}-previous"
aria-label="Go to previous page"
on:click|preventDefault={goToPreviousPage}
disabled={goToPreviousPageDisabled}><Fa icon={faAngleLeft} /></button
>
<input
type="number"
class="input border border-primary-500 rounded flex w-24"
value={$pageIndex + 1}
max={$pageCount}
aria-label="Current page"
min={1}
on:change={handleChange}
<div class="flex justify-center">
<Paginator
on:page={(page) => ($pageIndex = page.detail)}
settings={paginationSettings}
select="hidden"
buttonClasses="disabled:!variant-filled-surface !px-3 !py-1.5 !fill-current !variant-filled-primary"
active="!variant-filled-secondary"
maxNumerals={1}
showNumerals
/>
<button
class="btn btn-sm variant-filled-primary"
id="{id}-next"
aria-label="Go to next page"
on:click|preventDefault={goToNextPage}
disabled={goToNextPageDisabled}><Fa icon={faAngleRight} /></button
>
<button
class="btn btn-sm variant-filled-primary"
aria-label="Go to last page"
id="{id}-last"
on:click|preventDefault={goToLastPage}
disabled={goToLastPageDisabled}><Fa icon={faAnglesRight} /></button
>
</div>
<div class="flex justify-end items-center">
<span class="text-sm text-gray-500">{indexInformation}</span>
<span class="text-xs text-gray-500">{indexInformation}</span>
</div>
</div>
14 changes: 6 additions & 8 deletions src/lib/components/Table/TablePaginationServer.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
export let id; // Unique table ID
export let pageIndex;
export let pageSize;
export let pageIndexStringType;
export let pageSizes; // Available page sizes
export let serverItemCount; // Total number of items expected from the server. `serverSide` must be true on table config.
export let updateTable; // Function to update table
Expand Down Expand Up @@ -63,13 +62,12 @@
};

const getIndexInfomationString = () => {
if (pageIndexStringType === 'pages') {
return pageCount > 0 ? `Page ${$pageIndex + 1} of ${pageCount}` : 'No pages';
} else {
return `Showing ${$pageIndex * $pageSize + 1} - ${($pageIndex + 1) * $pageSize} of ${
pageCount * $pageSize
} items`;
}
return serverItemCount === 0
? 'No items'
: `Displaying items ${$pageIndex * $pageSize + 1} - ${Math.min(
($pageIndex + 1) * $pageSize,
serverItemCount
)} of ${Math.min(pageCount * $pageSize, serverItemCount)}`;
};

$: pageCount = Math.ceil($serverItemCount / $pageSize);
Expand Down
44 changes: 20 additions & 24 deletions src/lib/components/Table/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,21 @@ export const cellStyle = (id: string, columns: Columns | undefined) => {
// Create and return styles separated by ';'
return styles.join(';');
};
// Styles for resizing the cells
export const getResizeStyles = (
rowHeights: { [key: number]: { max: number; min: number } },
id: string | number,
index: number
) => {
return `
min-height: ${rowHeights && rowHeights[+id] ? `${rowHeights[+id].min}px` : 'auto'};
max-height: ${index !== 0 && rowHeights && rowHeights[+id]
? `${rowHeights[+id].max}px`
: 'auto'
};
height: ${rowHeights && rowHeights[+id] ? `${rowHeights[+id].min}px` : 'auto'};
`;
}
// Function to normalize the filters for back-end
export const normalizeFilters = (filters: {
[key: string]: { [key in FilterOptionsEnum]?: number | string | Date };
Expand All @@ -54,7 +69,7 @@ export const normalizeFilters = (filters: {

return filter;
};

// Creates a CSV file and downloads it
export const exportAsCsv = (tableId: string, exportedData: string) => {
// Creating a hidden anchor element to download the CSV file
const anchor = document.createElement('a');
Expand All @@ -65,7 +80,7 @@ export const exportAsCsv = (tableId: string, exportedData: string) => {
anchor.click();
document.body.removeChild(anchor);
};

// Function to convert JSON data to CSV format
export const jsonToCsv = (data: string): string => {
const json = JSON.parse(data);

Expand Down Expand Up @@ -96,7 +111,6 @@ export const jsonToCsv = (data: string): string => {
// Join rows with newlines
return rows.join('\n');
}

// Resetting the resized columns and/or rows
export const resetResize = (
headerRows: any,
Expand Down Expand Up @@ -140,7 +154,7 @@ export const resetResize = (
});
}
};

// Finds the mapping for missing values
export const missingValuesFn = (
key: number | string,
missingValues: { [key: string | number]: string }
Expand All @@ -160,7 +174,6 @@ export const missingValuesFn = (

return foundKey ? missingValues[foundKey] : key;
};

// Function to update the server-side table data
export const updateTable = async (
pageSize: number,
Expand Down Expand Up @@ -230,7 +243,7 @@ export const updateTable = async (

return response;
};

// Function to convert server data to client data
export const convertServerColumns = (
serverColumns: ServerColumn[],
columns: Columns | undefined
Expand Down Expand Up @@ -288,7 +301,6 @@ export const convertServerColumns = (

return columnsConfig;
};

// Calculates the maximum height of the cells in each row
export const getMaxCellHeightInRow = (
tableRef: HTMLTableElement,
Expand Down Expand Up @@ -329,7 +341,6 @@ export const getMaxCellHeightInRow = (
});
});
};

// Calculates the minimum width of the cells in each column
export const getMinCellWidthInColumn = (
tableRef: HTMLTableElement,
Expand All @@ -355,19 +366,4 @@ export const getMinCellWidthInColumn = (
});
return cw;
});
};

export const getResizeStyles = (
rowHeights: { [key: number]: { max: number; min: number } },
id: string | number,
index: number
) => {
return `
min-height: ${rowHeights && rowHeights[+id] ? `${rowHeights[+id].min}px` : 'auto'};
max-height: ${index !== 0 && rowHeights && rowHeights[+id]
? `${rowHeights[+id].max}px`
: 'auto'
};
height: ${rowHeights && rowHeights[+id] ? `${rowHeights[+id].min}px` : 'auto'};
`;
}
};
1 change: 0 additions & 1 deletion src/lib/models/Models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,6 @@ export interface TableConfig<T> {
exportable?: boolean; // false by default
pageSizes?: number[]; // [5, 10, 20, 50, 100] by default
defaultPageSize?: number; // 10 by default
pageIndexStringType?: 'items' | 'pages'; // pages by default
optionsComponent?: typeof SvelteComponent;

server?: ServerConfig;
Expand Down
2 changes: 0 additions & 2 deletions src/routes/components/table/data/codeBlocks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,6 @@ export const usersBDHTML = `
const usersBDConfig: TableConfig<UserBD> = {
id: 'usersBD',
data: usersBDStore,
pageIndexStringType: 'items',
columns: {
dateOfBirth: {
header: 'Date of birth',
Expand Down Expand Up @@ -214,7 +213,6 @@ export interface TableConfig<T> {
exportable?: boolean; // false by default
pageSizes?: number[]; // [5, 10, 20, 50, 100] by default
defaultPageSize?: number; // 10 by default
pageIndexStringType?: 'items' | 'pages'; // items by default
optionsComponent?: typeof SvelteComponent;

server?: ServerConfig;
Expand Down
15 changes: 0 additions & 15 deletions src/routes/components/table/docs/TableConfigDocs.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -190,21 +190,6 @@
</p>
</div>

<div class="items-center">
<div class="flex gap-2">
<div class="italic">pageIndexStringType:</div>
<div class="font-bold"><i>"items"</i> or <i>"pages"</i></div>
</div>

<p class="text-xl pl-10">
Whether the table should display page index information by number of items or pages. <code
class="!text-xl bg-tertiary-300 dark:bg-tertiary-700/50 rounded-md p-0.5 text-primary-500"
>"items"</code
>
by default.
</p>
</div>

<div class="items-center">
<div class="flex gap-2">
<div class="italic">optionsComponent:</div>
Expand Down
Loading