From 146fa2d35e1c518d8d546d70078e8c676f6fdacb Mon Sep 17 00:00:00 2001 From: Alex Lanz Date: Wed, 26 May 2021 13:43:53 +0200 Subject: [PATCH 1/2] Adjustable starting pages --- .../pagination-with-first-page-0.test.ts | 81 +++++++++++++++++++ ...s => pagination-with-first-page-1.test.ts} | 0 src/index.ts | 28 ++++--- 3 files changed, 97 insertions(+), 12 deletions(-) create mode 100644 src/__test__/pagination-with-first-page-0.test.ts rename src/__test__/{pagination.test.ts => pagination-with-first-page-1.test.ts} (100%) diff --git a/src/__test__/pagination-with-first-page-0.test.ts b/src/__test__/pagination-with-first-page-0.test.ts new file mode 100644 index 0000000..ae8a0fc --- /dev/null +++ b/src/__test__/pagination-with-first-page-0.test.ts @@ -0,0 +1,81 @@ +import { calculatePagination } from '../index' + +it('should return no pagination if not enough items are given', () => { + const page = 0 + const size = 5 + const total = 2 + const pagination = calculatePagination(page, size, total, 5, 0) + + expect(pagination).toBeNull() +}) +it('should return only a few pages', () => { + const page = 1 + const size = 5 + const total = 15 + const pagination = calculatePagination(page, size, total, 5, 0) + + expect(pagination).not.toBeNull() + expect(pagination?.pages).toHaveLength(3) + + expect(pagination?.pages[0].number).toBe(0) + expect(pagination?.pages[0].isCurrent).toBeFalsy() + expect(pagination?.pages[1].number).toBe(1) + expect(pagination?.pages[1].isCurrent).toBeTruthy() + expect(pagination?.pages[2].number).toBe(2) + expect(pagination?.pages[2].isCurrent).toBeFalsy() +}) +it('should return the maximum number of pages', () => { + const page = 4 + const size = 5 + const total = 50 + const maxPages = 5 + const pagination = calculatePagination(page, size, total, maxPages, 0) + + expect(pagination).not.toBeNull() + expect(pagination?.pages).toHaveLength(5) + + expect(pagination?.pages[0].number).toBe(2) + expect(pagination?.pages[0].isCurrent).toBeFalsy() + expect(pagination?.pages[1].number).toBe(3) + expect(pagination?.pages[1].isCurrent).toBeFalsy() + expect(pagination?.pages[2].number).toBe(4) + expect(pagination?.pages[2].isCurrent).toBeTruthy() + expect(pagination?.pages[3].number).toBe(5) + expect(pagination?.pages[3].isCurrent).toBeFalsy() + expect(pagination?.pages[4].number).toBe(6) + expect(pagination?.pages[4].isCurrent).toBeFalsy() +}) +it('should disable the previous link', () => { + const page = 0 + const size = 5 + const total = 10 + const pagination = calculatePagination(page, size, total, 5, 0) + + expect(pagination).not.toBeNull() + + expect(pagination?.previous.number).toBe(0) + expect(pagination?.previous.isDisabled).toBeTruthy() + + expect(pagination?.next.number).toBe(1) + expect(pagination?.next.isDisabled).toBeFalsy() + + expect(pagination?.pages[0].isCurrent).toBeTruthy() + expect(pagination?.pages[1].isCurrent).toBeFalsy() +}) +it('should disable the next link', () => { + const page = 1 + const size = 5 + const total = 10 + const pagination = calculatePagination(page, size, total, 5, 0) + + expect(pagination).not.toBeNull() + + expect(pagination?.previous.number).toBe(0) + expect(pagination?.previous.isDisabled).toBeFalsy() + + expect(pagination?.next.number).toBe(1) + expect(pagination?.next.isDisabled).toBeTruthy() + + expect(pagination?.pages[0].isCurrent).toBeFalsy() + expect(pagination?.pages[1].isCurrent).toBeTruthy() +}) diff --git a/src/__test__/pagination.test.ts b/src/__test__/pagination-with-first-page-1.test.ts similarity index 100% rename from src/__test__/pagination.test.ts rename to src/__test__/pagination-with-first-page-1.test.ts diff --git a/src/index.ts b/src/index.ts index 1a5d0d8..466113d 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,12 +1,13 @@ const calculateVisiblePages = ( page: number, - total: number, + firstPage: number, + lastPage: number, maxPages: number ): number[] => { const range = Math.floor(maxPages / 2) - let lowerBound = 1 + let lowerBound = firstPage let lowerBoundRest = 0 - let upperBound = total + let upperBound = lastPage let upperBoundRest = 0 if (page - range >= 1) { @@ -15,20 +16,22 @@ const calculateVisiblePages = ( lowerBoundRest = (page - range - 1) * -1 } - if (page + range <= total) { + if (page + range <= lastPage) { upperBound = page + range } else { - upperBoundRest = (total - range - page) * -1 + upperBoundRest = (lastPage - range - page) * -1 } if (upperBoundRest > 0) { lowerBound = - lowerBound - upperBoundRest > 0 ? lowerBound - upperBoundRest : 1 + lowerBound - upperBoundRest > 0 ? lowerBound - upperBoundRest : firstPage } if (lowerBoundRest > 0) { upperBound = - upperBound + lowerBoundRest < total ? upperBound + lowerBoundRest : total + upperBound + lowerBoundRest < lastPage + ? upperBound + lowerBoundRest + : lastPage } const pages = [] @@ -44,7 +47,8 @@ const calculatePagination = ( page: number, size: number, total: number, - maxPages = 5 + maxPages = 5, + firstPage = 1 ): { previous: { number: number @@ -63,20 +67,20 @@ const calculatePagination = ( return null } - const lastPage = Math.ceil(total / size) - const isCurrentTheFirstPage = page === 1 + const lastPage = Math.ceil(total / size) + (firstPage - 1) + const isCurrentTheFirstPage = page === firstPage const isCurrentTheLastPage = page === lastPage return { previous: { - number: isCurrentTheFirstPage ? 1 : page - 1, + number: isCurrentTheFirstPage ? firstPage : page - 1, isDisabled: isCurrentTheFirstPage, }, next: { number: isCurrentTheLastPage ? lastPage : page + 1, isDisabled: isCurrentTheLastPage, }, - pages: calculateVisiblePages(page, lastPage, maxPages).map( + pages: calculateVisiblePages(page, firstPage, lastPage, maxPages).map( (visiblePage) => { return { number: visiblePage, From 7502663b4c640908a073efeea1bcc7064c41cc1f Mon Sep 17 00:00:00 2001 From: Alex Lanz Date: Wed, 26 May 2021 13:59:55 +0200 Subject: [PATCH 2/2] Embedding the configuraitons into an configuraitons object --- readme.md | 4 +++- src/__test__/pagination-with-first-page-0.test.ts | 13 ++++++++----- src/__test__/pagination-with-first-page-1.test.ts | 4 +++- src/index.ts | 9 +++++++-- 4 files changed, 21 insertions(+), 9 deletions(-) diff --git a/readme.md b/readme.md index 1d62e16..0aac788 100644 --- a/readme.md +++ b/readme.md @@ -24,7 +24,9 @@ Second, you can call the calculate function by passing the following information - `page`: The current page - `size`: The amount of items shown per page - `total`: The amount of total items in the list/collection -- `maxPages`: The maximum amount of pages that should be shown (default: 5) +- `config`: A configuration object containing the following possible configuration values: + - `firstPage`: The first page of the pagination (default: 1) + - `maxPages`: The maximum amount of pages that should be shown (default: 5) In return, you receive an object with all relevant information: diff --git a/src/__test__/pagination-with-first-page-0.test.ts b/src/__test__/pagination-with-first-page-0.test.ts index ae8a0fc..f450b50 100644 --- a/src/__test__/pagination-with-first-page-0.test.ts +++ b/src/__test__/pagination-with-first-page-0.test.ts @@ -4,7 +4,7 @@ it('should return no pagination if not enough items are given', () => { const page = 0 const size = 5 const total = 2 - const pagination = calculatePagination(page, size, total, 5, 0) + const pagination = calculatePagination(page, size, total, { firstPage: 0 }) expect(pagination).toBeNull() }) @@ -12,7 +12,7 @@ it('should return only a few pages', () => { const page = 1 const size = 5 const total = 15 - const pagination = calculatePagination(page, size, total, 5, 0) + const pagination = calculatePagination(page, size, total, { firstPage: 0 }) expect(pagination).not.toBeNull() expect(pagination?.pages).toHaveLength(3) @@ -29,7 +29,10 @@ it('should return the maximum number of pages', () => { const size = 5 const total = 50 const maxPages = 5 - const pagination = calculatePagination(page, size, total, maxPages, 0) + const pagination = calculatePagination(page, size, total, { + firstPage: 0, + maxPages: maxPages, + }) expect(pagination).not.toBeNull() expect(pagination?.pages).toHaveLength(5) @@ -49,7 +52,7 @@ it('should disable the previous link', () => { const page = 0 const size = 5 const total = 10 - const pagination = calculatePagination(page, size, total, 5, 0) + const pagination = calculatePagination(page, size, total, { firstPage: 0 }) expect(pagination).not.toBeNull() @@ -66,7 +69,7 @@ it('should disable the next link', () => { const page = 1 const size = 5 const total = 10 - const pagination = calculatePagination(page, size, total, 5, 0) + const pagination = calculatePagination(page, size, total, { firstPage: 0 }) expect(pagination).not.toBeNull() diff --git a/src/__test__/pagination-with-first-page-1.test.ts b/src/__test__/pagination-with-first-page-1.test.ts index c66e582..33f3879 100644 --- a/src/__test__/pagination-with-first-page-1.test.ts +++ b/src/__test__/pagination-with-first-page-1.test.ts @@ -29,7 +29,9 @@ it('should return the maximum number of pages', () => { const size = 5 const total = 50 const maxPages = 5 - const pagination = calculatePagination(page, size, total, maxPages) + const pagination = calculatePagination(page, size, total, { + maxPages: maxPages, + }) expect(pagination).not.toBeNull() expect(pagination?.pages).toHaveLength(5) diff --git a/src/index.ts b/src/index.ts index 466113d..b5f3436 100644 --- a/src/index.ts +++ b/src/index.ts @@ -47,8 +47,10 @@ const calculatePagination = ( page: number, size: number, total: number, - maxPages = 5, - firstPage = 1 + config?: { + firstPage?: number + maxPages?: number + } ): { previous: { number: number @@ -67,6 +69,9 @@ const calculatePagination = ( return null } + const firstPage = config?.firstPage ?? 1 + const maxPages = config?.maxPages ?? 5 + const lastPage = Math.ceil(total / size) + (firstPage - 1) const isCurrentTheFirstPage = page === firstPage const isCurrentTheLastPage = page === lastPage