mirror of
https://github.com/appwrite/console.git
synced 2026-06-06 19:27:48 +00:00
@@ -1,54 +1,96 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
export let sum: number;
|
||||
export let limit: number;
|
||||
export let offset: number;
|
||||
export let sum: number;
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
const totalPages = Math.ceil(sum / limit);
|
||||
let currentPage = Math.floor(offset / limit + 1);
|
||||
|
||||
const next = () => {
|
||||
if (offset + limit > sum) {
|
||||
offset = sum;
|
||||
} else {
|
||||
offset += limit;
|
||||
function handleOptionClick(page: number) {
|
||||
if (currentPage !== page) {
|
||||
offset = limit * (page - 1);
|
||||
currentPage = page;
|
||||
dispatch('change');
|
||||
}
|
||||
dispatch('change');
|
||||
};
|
||||
}
|
||||
|
||||
const prev = () => {
|
||||
if (offset - limit < 0) {
|
||||
offset = 0;
|
||||
} else {
|
||||
offset -= limit;
|
||||
function handleButtonPage(direction: string) {
|
||||
if (direction === 'next' && currentPage < totalPages) {
|
||||
currentPage += 1;
|
||||
offset = limit * (currentPage - 1);
|
||||
dispatch('change');
|
||||
} else if (direction === 'prev' && currentPage > 1) {
|
||||
currentPage -= 1;
|
||||
offset = limit * (currentPage - 1);
|
||||
dispatch('change');
|
||||
}
|
||||
dispatch('change');
|
||||
};
|
||||
}
|
||||
|
||||
$: noPrev = offset === 0;
|
||||
$: noNext = sum - limit < offset;
|
||||
$: currentPage = offset / limit + 1;
|
||||
$: totalPages = Math.ceil(sum / limit);
|
||||
let pages = pagination(currentPage, totalPages);
|
||||
|
||||
function pagination(current: number, total: number) {
|
||||
let delta = 2,
|
||||
left = current - delta,
|
||||
right = current + delta + 1,
|
||||
range = [],
|
||||
rangeWithDots = [];
|
||||
|
||||
for (let i = 1; i <= total; i++) {
|
||||
if (i == 1 || i == total || (i >= left && i < right)) {
|
||||
range.push(i);
|
||||
}
|
||||
}
|
||||
|
||||
rangeWithDots = range.reduce((prev, current, index) => {
|
||||
if (current - prev[index - 1] > delta) {
|
||||
prev.push('...');
|
||||
}
|
||||
prev.push(current);
|
||||
return prev;
|
||||
}, []);
|
||||
return rangeWithDots;
|
||||
}
|
||||
</script>
|
||||
|
||||
{#if sum >= limit}
|
||||
<nav class="pagination is-center">
|
||||
{#if totalPages > 1}
|
||||
<nav class="pagination">
|
||||
<button
|
||||
on:click={prev}
|
||||
disabled={noPrev}
|
||||
class:is-disabled={noPrev}
|
||||
class="button is-only-icon"
|
||||
aria-label="previous page">
|
||||
<span class="icon-left-open" aria-hidden="true" />
|
||||
on:click={() => handleButtonPage('prev')}
|
||||
class:is-disabled={currentPage <= 1}
|
||||
class="button is-text"
|
||||
aria-label="prev page">
|
||||
<span class="icon-cheveron-left" aria-hidden="true" />
|
||||
<span class="text">Prev</span>
|
||||
</button>
|
||||
<span class="pagination-info">{currentPage} / {totalPages}</span>
|
||||
<ol class="pagination-list is-only-desktop">
|
||||
{#each pages as page}
|
||||
{#if typeof page === 'number'}
|
||||
<li class="pagination-item">
|
||||
<button
|
||||
class="button"
|
||||
on:click={() => handleOptionClick(page)}
|
||||
class:is-disabled={currentPage === page}
|
||||
class:is-text={currentPage !== page}
|
||||
aria-label="page">
|
||||
<span class="text">{page}</span>
|
||||
</button>
|
||||
</li>
|
||||
{:else}
|
||||
<li class="li is-text">
|
||||
<span class="icon">...</span>
|
||||
</li>
|
||||
{/if}
|
||||
{/each}
|
||||
</ol>
|
||||
<button
|
||||
on:click={next}
|
||||
disabled={noNext}
|
||||
class:is-disabled={noNext}
|
||||
class="button is-only-icon"
|
||||
on:click={() => handleButtonPage('next')}
|
||||
class:is-disabled={currentPage === totalPages}
|
||||
class="button is-text"
|
||||
aria-label="next page">
|
||||
<span class="icon-right-open" aria-hidden="true" />
|
||||
<span class="text">Next</span>
|
||||
<span class="icon-cheveron-right" aria-hidden="true" />
|
||||
</button>
|
||||
</nav>
|
||||
{/if}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
let search = '';
|
||||
let showCreate = false;
|
||||
let offset = 0;
|
||||
const limit = 25;
|
||||
const limit = 5;
|
||||
|
||||
const project = $page.params.project;
|
||||
const getAvatar = (name: string) => sdkForProject.avatars.getInitials(name, 30, 30).toString();
|
||||
@@ -90,7 +90,7 @@
|
||||
</Table>
|
||||
<div class="u-flex common-section u-main-space-between">
|
||||
<p class="text">Total results: {response.total}</p>
|
||||
<Pagination {limit} bind:offset sum={response.total} />
|
||||
<Pagination bind:offset {limit} sum={response.total} />
|
||||
</div>
|
||||
{:else if search}
|
||||
<Empty>
|
||||
|
||||
@@ -4,11 +4,11 @@ import { Pagination } from '../../../src/lib/components';
|
||||
|
||||
test('shows controls', () => {
|
||||
const { getByLabelText } = render(Pagination, {
|
||||
limit: 0,
|
||||
limit: 100,
|
||||
offset: 0,
|
||||
sum: 100
|
||||
sum: 150
|
||||
});
|
||||
expect(getByLabelText('previous page')).toBeInTheDocument();
|
||||
expect(getByLabelText('prev page')).toBeInTheDocument();
|
||||
expect(getByLabelText('next page')).toBeInTheDocument();
|
||||
});
|
||||
|
||||
@@ -19,8 +19,8 @@ test('pagination - first page', () => {
|
||||
sum: 100
|
||||
});
|
||||
|
||||
expect(getByLabelText('previous page')).toBeDisabled();
|
||||
expect(getByLabelText('next page')).not.toBeDisabled();
|
||||
expect(getByLabelText('prev page')).toHaveClass('is-disabled');
|
||||
expect(getByLabelText('next page')).not.toHaveClass('is-disabled');
|
||||
});
|
||||
|
||||
test('pagination - last page', () => {
|
||||
@@ -30,8 +30,8 @@ test('pagination - last page', () => {
|
||||
sum: 30
|
||||
});
|
||||
|
||||
expect(getByLabelText('previous page')).not.toBeDisabled();
|
||||
expect(getByLabelText('next page')).toBeDisabled();
|
||||
expect(getByLabelText('prev page')).not.toHaveClass('is-disabled');
|
||||
expect(getByLabelText('next page')).toHaveClass('is-disabled');
|
||||
});
|
||||
|
||||
test('pagination - forward', async () => {
|
||||
@@ -41,9 +41,9 @@ test('pagination - forward', async () => {
|
||||
sum: 60
|
||||
});
|
||||
|
||||
const back = getByLabelText('previous page');
|
||||
const back = getByLabelText('prev page');
|
||||
const forth = getByLabelText('next page');
|
||||
expect(back).toBeDisabled();
|
||||
expect(back).toHaveClass('is-disabled');
|
||||
|
||||
await fireEvent.click(forth);
|
||||
expect(component.offset).toEqual(25);
|
||||
@@ -52,8 +52,8 @@ test('pagination - forward', async () => {
|
||||
expect(component.offset).toEqual(50);
|
||||
|
||||
await fireEvent.click(forth);
|
||||
expect(component.offset).toEqual(60);
|
||||
expect(forth).toBeDisabled();
|
||||
expect(component.offset).toEqual(50);
|
||||
expect(forth).toHaveClass('is-disabled');
|
||||
});
|
||||
|
||||
test('pagination - backwards', async () => {
|
||||
@@ -63,19 +63,50 @@ test('pagination - backwards', async () => {
|
||||
sum: 60
|
||||
});
|
||||
|
||||
const back = getByLabelText('previous page');
|
||||
const back = getByLabelText('prev page');
|
||||
const forth = getByLabelText('next page');
|
||||
expect(forth).toBeDisabled();
|
||||
expect(forth).toHaveClass('is-disabled');
|
||||
|
||||
await fireEvent.click(back);
|
||||
expect(component.offset).toEqual(30);
|
||||
|
||||
await fireEvent.click(back);
|
||||
expect(component.offset).toEqual(5);
|
||||
expect(component.offset).toEqual(25);
|
||||
|
||||
await fireEvent.click(back);
|
||||
expect(component.offset).toEqual(0);
|
||||
expect(back).toBeDisabled();
|
||||
|
||||
await fireEvent.click(back);
|
||||
expect(component.offset).toEqual(0);
|
||||
expect(back).toHaveClass('is-disabled');
|
||||
});
|
||||
|
||||
test('pagination - number button click', async () => {
|
||||
const { getByText, getAllByLabelText, component } = render(Pagination, {
|
||||
limit: 25,
|
||||
offset: 0,
|
||||
sum: 60
|
||||
});
|
||||
|
||||
const buttons = getAllByLabelText('page');
|
||||
const [button1, button2, button3] = buttons;
|
||||
|
||||
const one = getByText('1');
|
||||
const two = getByText('2');
|
||||
const three = getByText('3');
|
||||
expect(button1).toHaveClass('is-disabled');
|
||||
|
||||
await fireEvent.click(two);
|
||||
expect(component.offset).toEqual(25);
|
||||
expect(button1).not.toHaveClass('is-disabled');
|
||||
expect(button2).toHaveClass('is-disabled');
|
||||
|
||||
await fireEvent.click(three);
|
||||
expect(component.offset).toEqual(50);
|
||||
expect(button2).not.toHaveClass('is-disabled');
|
||||
expect(button3).toHaveClass('is-disabled');
|
||||
|
||||
await fireEvent.click(one);
|
||||
expect(component.offset).toEqual(0);
|
||||
expect(button1).toHaveClass('is-disabled');
|
||||
expect(button3).not.toHaveClass('is-disabled');
|
||||
});
|
||||
|
||||
test('shows no controls', () => {
|
||||
@@ -85,6 +116,6 @@ test('shows no controls', () => {
|
||||
sum: 10
|
||||
});
|
||||
|
||||
expect(queryByLabelText('previous page')).not.toBeInTheDocument();
|
||||
expect(queryByLabelText('prev page')).not.toBeInTheDocument();
|
||||
expect(queryByLabelText('next page')).not.toBeInTheDocument();
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user