Finally fix the build pagination issue

This commit is contained in:
2022-04-21 20:48:34 +02:00
parent 2881835dee
commit 5de0e3aa32
14 changed files with 336 additions and 406 deletions

View File

@ -1,4 +1,4 @@
import { toParams } from '$lib/pagination/searchParams'
import { toParams } from '$lib/pagination/dropTakeParams'
import { last, range } from 'ramda'
export const Divider = 'divider'
@ -45,6 +45,5 @@ export function createHref(
pageNumber: number
) {
const filtersPath = toParams(filters)
console.log(filtersPath, filters)
return `/${href}/${filtersPath ? filtersPath + '/' : ''}page/${pageNumber}`
}

View File

@ -0,0 +1,11 @@
import { describe, test, expect } from 'vitest'
import { getDropTakeFromPageParams } from './dropTakeParams'
describe('convert search params', () => {
test('should convert from page size and page to offset and limit', () => {
expect(getDropTakeFromPageParams(7, 2)).toEqual({
offset: 7,
limit: 7,
})
})
})

View File

@ -0,0 +1,42 @@
import { splitEvery } from 'ramda'
export function parseParams(params: string) {
const splittedParams = params.split('/')
if (splittedParams.length % 2 !== 0) {
return []
}
const splits = splitEvery(2, splittedParams)
return Object.fromEntries(splits)
}
export function toParams(records: Record<string, string>) {
return Object.entries(records)
.map(([key, value]) => `${key}/${value}`)
.join('/')
}
export interface PaginationParams {
pageSize: number
page: number
filters?: Record<string, string>
}
export interface DropTakeParams {
offset: number
limit: number
}
/**
* Convert svelte `load` params into a `offset` and `limit` so they can be used to fetch endpoints with pagination queries
*/
export function getDropTakeFromPageParams(
pageSize: number,
page: number
): DropTakeParams {
const offset = pageSize * (page - 1)
const limit = pageSize
return {
offset,
limit,
}
}

View File

@ -1,79 +0,0 @@
import { describe, test, expect } from 'vitest'
import {
getPaginationQueryFromSearchParams,
getPaginationSearchParams,
parseParams,
} from './searchParams'
describe('convert search params', () => {
test('drop take params are not taken as filters', () => {
expect(
getPaginationQueryFromSearchParams(
new URLSearchParams('offset=2&limit=5')
)
).toEqual({ offset: 2, limit: 5 })
})
test('return empty paginationQuery if ', () => {
expect(getPaginationQueryFromSearchParams(new URLSearchParams(''))).toEqual(
{}
)
})
test('other than drop take params are moved to filters ', () => {
expect(
getPaginationQueryFromSearchParams(new URLSearchParams('tag=news'))
).toEqual({ filters: { tag: 'news' } })
})
test('offset and filter combined', () => {
expect(
getPaginationQueryFromSearchParams(
new URLSearchParams('offset=3&tag=news')
)
).toEqual({ offset: 3, filters: { tag: 'news' } })
})
})
describe('get search params', () => {
test('parse params', () => {
const params = 'tags/News/page/1'
expect(parseParams(params)).toEqual({ tags: 'News', page: '1' })
})
test('should parse values into searchParams for first page', () => {
const params = {
pageSize: 7,
page: 1,
filters: {
tags: 'News',
},
}
expect(getPaginationSearchParams(params).toString()).toEqual(
'limit=7&offset=0&tags=News'
)
})
test('should parse values into searchParams for third page', () => {
const params = {
pageSize: 7,
page: 3,
filters: {
tags: 'News',
},
}
expect(getPaginationSearchParams(params).toString()).toEqual(
'limit=7&offset=14&tags=News'
)
})
test('should return first page without any params specified', () => {
const params = {
pageSize: 7,
page: 1,
}
expect(getPaginationSearchParams(params).toString()).toEqual(
'limit=7&offset=0'
)
})
})

View File

@ -1,60 +0,0 @@
import { splitEvery } from 'ramda'
import type { PaginationQuery } from './pagination'
export function getPaginationQueryFromSearchParams(
searchParams: URLSearchParams
) {
return Array.from(searchParams).reduce<PaginationQuery>(
(acc, [key, value]) => {
const isDropTake = ['offset', 'limit'].includes(key)
if (isDropTake) {
return {
...acc,
[key]: Number(value),
}
}
return {
...acc,
filters: {
...acc.filters,
[key]: value,
},
}
},
{}
)
}
export function parseParams(params: string) {
const splittedParams = params.split('/')
if (splittedParams.length % 2 !== 0) {
return []
}
const splits = splitEvery(2, splittedParams)
return Object.fromEntries(splits)
}
export function toParams(records: Record<string, string>) {
return Object.entries(records)
.map(([key, value]) => `${key}/${value}`)
.join('/')
}
export interface PaginationSearchParams {
pageSize: number
page: number
filters?: Record<string, string>
}
/**
* Convert svelte `load` params into a `URLSearchParams` so they can be used to fetch endpoints with pagination queries
*/
export function getPaginationSearchParams({
pageSize,
page,
filters,
}: PaginationSearchParams) {
const offset = pageSize * (page - 1)
const limit = pageSize
return new URLSearchParams({ limit, offset, ...filters })
}

View File

@ -1,5 +1,4 @@
/** @type {import('@sveltejs/kit').ParamMatcher} */
export function match(param: string) {
console.debug('parma', param)
return !['tags', 'page'].some((keyword) => param.startsWith(keyword))
}

View File

@ -3,7 +3,7 @@
import type { LoadInput, LoadOutput } from '@sveltejs/kit/types/page'
export async function load({ fetch, url }: LoadInput): Promise<LoadOutput> {
const blogPostsResponse = await fetch(`/blog/articles?limit=5`)
const blogPostsResponse = await fetch(`/blog/articles/pageSize/5.json`)
const blogPostsContent = await blogPostsResponse.json()
return {
props: {

View File

@ -1,21 +1,13 @@
<script lang="ts" context="module">
import {
getPaginationSearchParams,
parseParams,
} from '$lib/pagination/searchParams'
const pageSize = 7
import { parseParams } from '$lib/pagination/dropTakeParams'
/**
* @type {import('@sveltejs/kit').Load}
*/
export async function load({ fetch, params }) {
console.log('params', params)
const { page = 1, ...filters } = parseParams(params.params)
const searchParams = getPaginationSearchParams({ pageSize, page, filters })
console.log('searchpprsm', searchParams)
const { page = 1, pageSize = 7, ...filters } = parseParams(params.params)
const articleResponse = await fetch(
`/blog/articles?${searchParams.toString()}`
`/blog/articles/${params.params ? params.params : 'index'}.json`
).then((r) => r.json())
return {
@ -40,6 +32,7 @@
export let filters: Record<string, string>
export let page: number
export let pageSize: number
let totalPages = Math.ceil(posts.totalCount / pageSize)
</script>
@ -47,7 +40,6 @@
<title>My blog @michalvankodev</title>
</svelte:head>
{@debug posts}
{#if posts.items.length === 0}
<p class="no-posts">You've found void in the space.</p>
{:else}
@ -75,7 +67,7 @@
/>
</header>
<ul class="post-list {postListClass}">
{#each posts.items as post}
{#each posts.items as post (post.slug)}
<li>
<article>
<header>

View File

@ -1,14 +0,0 @@
import { getPaginationQueryFromSearchParams } from '$lib/pagination/searchParams'
import { getBlogListing } from './_content'
export async function get({ url: { searchParams } }) {
const paginationQuery = getPaginationQueryFromSearchParams(searchParams)
const filteredContents = await getBlogListing(paginationQuery)
return {
status: 200,
body: {
posts: filteredContents,
},
}
}

View File

@ -0,0 +1,25 @@
import {
getDropTakeFromPageParams,
parseParams,
} from '$lib/pagination/dropTakeParams'
import { getBlogListing } from '../_content'
export async function get({ params }) {
console.log('article-params', params)
const handledParams = params.params === 'index' ? '' : params.params
const { page = 1, pageSize = 7, ...filters } = parseParams(handledParams)
const paginationParams = getDropTakeFromPageParams(
Number(pageSize),
Number(page)
)
const paginationQuery = { ...paginationParams, filters }
const filteredContents = await getBlogListing(paginationQuery)
console.log(filteredContents.items.map((item) => item.slug))
return {
status: 200,
body: {
posts: filteredContents,
},
}
}