Client - refactoring pagination query

This commit is contained in:
Sam 2021-11-02 10:58:25 +01:00
parent 73a0b53dd7
commit c5428c28a6
4 changed files with 304 additions and 37 deletions

View File

@ -7,8 +7,8 @@
{{ $t('admin.BACK_TO_ADMIN') }} {{ $t('admin.BACK_TO_ADMIN') }}
</button> </button>
<AdminUsersSelects <AdminUsersSelects
:sort="sort" :sort="sortList"
:order_by="order_by" :order_by="orderByList"
:query="query" :query="query"
@updateSelect="reloadUsers" @updateSelect="reloadUsers"
/> />
@ -135,6 +135,7 @@
import { IPagination, TPaginationPayload } from '@/types/api' import { IPagination, TPaginationPayload } from '@/types/api'
import { IUserProfile } from '@/types/user' import { IUserProfile } from '@/types/user'
import { useStore } from '@/use/useStore' import { useStore } from '@/use/useStore'
import { getQuery, sortList } from '@/utils/api'
import { getDateWithTZ } from '@/utils/dates' import { getDateWithTZ } from '@/utils/dates'
export default defineComponent({ export default defineComponent({
@ -149,14 +150,16 @@
const route = useRoute() const route = useRoute()
const router = useRouter() const router = useRouter()
const sort: string[] = ['asc', 'desc'] const orderByList: string[] = [
const order_by: string[] = [
'admin', 'admin',
'created_at', 'created_at',
'username', 'username',
'workouts_count', 'workouts_count',
] ]
let query: TPaginationPayload = reactive(getQuery(route.query)) const defaultOrderBy = 'created_at'
let query: TPaginationPayload = reactive(
getQuery(route.query, orderByList, defaultOrderBy)
)
const authUser: ComputedRef<IUserProfile> = computed( const authUser: ComputedRef<IUserProfile> = computed(
() => store.getters[USER_STORE.GETTERS.AUTH_USER_PROFILE] () => store.getters[USER_STORE.GETTERS.AUTH_USER_PROFILE]
@ -174,32 +177,6 @@
function loadUsers(queryParams: TPaginationPayload) { function loadUsers(queryParams: TPaginationPayload) {
store.dispatch(USERS_STORE.ACTIONS.GET_USERS, queryParams) store.dispatch(USERS_STORE.ACTIONS.GET_USERS, queryParams)
} }
function getPage(page: string | (string | null)[] | null): number {
return page && typeof page === 'string' && +page > 0 ? +page : 1
}
function getPerPage(perPage: string | (string | null)[] | null): number {
return perPage && typeof perPage === 'string' && +perPage > 0
? +perPage
: 10
}
function getOrder(order: string | (string | null)[] | null): string {
return order && typeof order === 'string' && sort.includes(order)
? order
: 'asc'
}
function getOrderBy(order: string | (string | null)[] | null): string {
return order && typeof order === 'string' && order_by.includes(order)
? order
: 'created_at'
}
function getQuery(query: LocationQuery): TPaginationPayload {
return {
page: getPage(query.page),
per_page: getPerPage(query.per_page),
order: getOrder(query.order),
order_by: getOrderBy(query.order_by),
}
}
function updateUser(username: string, admin: boolean) { function updateUser(username: string, admin: boolean) {
store.dispatch(USERS_STORE.ACTIONS.UPDATE_USER, { store.dispatch(USERS_STORE.ACTIONS.UPDATE_USER, {
username, username,
@ -219,10 +196,7 @@
watch( watch(
() => route.query, () => route.query,
(newQuery: LocationQuery) => { (newQuery: LocationQuery) => {
query.page = getPage(newQuery.page) query = getQuery(newQuery, orderByList, defaultOrderBy, { query })
query.per_page = getPerPage(newQuery.per_page)
query.order = getOrder(newQuery.order)
query.order_by = getOrderBy(newQuery.order_by)
loadUsers(query) loadUsers(query)
} }
) )
@ -234,10 +208,10 @@
return { return {
authUser, authUser,
errorMessages, errorMessages,
orderByList,
pagination, pagination,
order_by,
query, query,
sort, sortList,
users, users,
capitalize, capitalize,
format, format,

View File

@ -13,3 +13,8 @@ export type TPaginationPayload = {
per_page: number per_page: number
page: number page: number
} }
export interface IQueryOptions {
defaultSort?: string
query?: TPaginationPayload
}

View File

@ -0,0 +1,50 @@
import { LocationQuery } from 'vue-router'
import { IQueryOptions, TPaginationPayload } from '@/types/api'
export const sortList: string[] = ['asc', 'desc']
export const defaultPage = 1
export const defaultPerPage = 10
export const getNumberQueryValue = (
queryValue: string | (string | null)[] | null,
defaultValue: number
): number => {
return queryValue && typeof queryValue === 'string' && +queryValue > 0
? +queryValue
: defaultValue
}
export const getStringQueryValue = (
queryValue: string | (string | null)[] | null,
availableValues: string[],
defaultValue: string
): string => {
return queryValue &&
typeof queryValue === 'string' &&
availableValues.includes(queryValue)
? queryValue
: defaultValue
}
export const getQuery = (
locationQuery: LocationQuery,
orderByList: string[],
defaultOrderBy: string,
options?: IQueryOptions
): TPaginationPayload => {
const queryOptions = options || {}
const defaultSort = queryOptions.defaultSort || 'asc'
const query = queryOptions.query || <TPaginationPayload>{}
query.page = getNumberQueryValue(locationQuery.page, defaultPage)
query.per_page = getNumberQueryValue(locationQuery.per_page, defaultPerPage)
query.order = getStringQueryValue(locationQuery.order, sortList, defaultSort)
query.order_by = getStringQueryValue(
locationQuery.order_by,
orderByList,
defaultOrderBy
)
return query
}

View File

@ -0,0 +1,238 @@
import { assert } from 'chai'
import {
defaultPerPage,
defaultPage,
sortList,
getNumberQueryValue,
getStringQueryValue,
getQuery,
} from '@/utils/api'
const orderByList = ['admin', 'created_at', 'username', 'workouts_count']
const defaultSort = 'desc'
const defaultOrderBy = 'created_at'
const generateLocationQuery = (
query: Record<string, string>
): Record<string, string | (string | null)[] | null> => {
return query
}
describe('getNumberQueryValue', () => {
const testsParams = [
{
description: 'returns 2 if input value is 2',
inputValue: '2',
inputDefaultValue: 2,
expectedValue: 2,
},
{
description: 'returns default value if input value is null',
inputValue: null,
inputDefaultValue: 1,
expectedValue: 1,
},
{
description: 'returns default value if input value is negative value',
inputValue: '-1',
inputDefaultValue: 1,
expectedValue: 1,
},
{
description: 'returns default value if input value is not a number',
inputValue: 'a',
inputDefaultValue: 1,
expectedValue: 1,
},
]
testsParams.map((testParams) => {
it(testParams.description, () => {
assert.equal(
getNumberQueryValue(
testParams.inputValue,
testParams.inputDefaultValue
),
testParams.expectedValue
)
})
})
})
describe('getStringQueryValue', () => {
const testsParams = [
{
description: 'returns input value if input value is in list',
inputValue: 'asc',
inputDefaultValue: 'asc',
expectedValue: 'asc',
},
{
description: 'returns default value if input value is null',
inputValue: null,
inputDefaultValue: 'asc',
expectedValue: 'asc',
},
{
description: 'returns default value if input value is not in list',
inputValue: '1',
inputDefaultValue: 'asc',
expectedValue: 'asc',
},
]
testsParams.map((testParams) => {
it(testParams.description, () => {
assert.equal(
getStringQueryValue(
testParams.inputValue,
sortList,
testParams.inputDefaultValue
),
testParams.expectedValue
)
})
})
})
describe('getQuery', () => {
const testsParams = [
{
description: 'returns default query if location query is an empty object',
inputLocationQuery: {},
expectedQuery: {
page: defaultPage,
per_page: defaultPerPage,
order: defaultSort,
order_by: defaultOrderBy,
},
},
{
description: 'returns query with input page',
inputLocationQuery: generateLocationQuery({ page: '2' }),
expectedQuery: {
page: 2,
per_page: defaultPerPage,
order: defaultSort,
order_by: defaultOrderBy,
},
},
{
description: 'returns query with input per_page',
inputLocationQuery: generateLocationQuery({ per_page: '20' }),
expectedQuery: {
page: defaultPage,
per_page: 20,
order: defaultSort,
order_by: defaultOrderBy,
},
},
{
description: 'returns query with input order',
inputLocationQuery: generateLocationQuery({ order: 'asc' }),
expectedQuery: {
page: defaultPage,
per_page: defaultPerPage,
order: 'asc',
order_by: defaultOrderBy,
},
},
{
description: 'returns query with input order_by',
inputLocationQuery: generateLocationQuery({ order_by: 'username' }),
expectedQuery: {
page: defaultPage,
per_page: defaultPerPage,
order: defaultSort,
order_by: 'username',
},
},
{
description:
'returns default query with input location query values are invalid',
inputLocationQuery: generateLocationQuery({
page: '0',
per_page: '0',
order: 'random',
order_by: 'name',
}),
expectedQuery: {
page: defaultPage,
per_page: defaultPerPage,
order: defaultSort,
order_by: defaultOrderBy,
},
},
]
testsParams.map((testParams) => {
it(testParams.description, () => {
assert.deepEqual(
getQuery(testParams.inputLocationQuery, orderByList, defaultOrderBy, {
defaultSort,
}),
testParams.expectedQuery
)
})
})
})
describe('getQuery w/ default values', () => {
it('returns default query if location query is an empty object', () => {
assert.deepEqual(getQuery({}, orderByList, defaultOrderBy), {
page: 1,
per_page: 10,
order: 'asc',
order_by: defaultOrderBy,
})
})
})
describe('getQuery w/ default values and input pagination payload', () => {
const inputQuery = {
page: 2,
per_page: 20,
order: 'desc',
order_by: 'username',
}
it('returns query updated with default values', () => {
assert.deepEqual(
getQuery({}, orderByList, defaultOrderBy, { query: inputQuery }),
{
page: 1,
per_page: 10,
order: 'asc',
order_by: defaultOrderBy,
}
)
})
it('returns query updated with input values', () => {
assert.deepEqual(
getQuery({}, orderByList, defaultOrderBy, {
defaultSort: 'desc',
query: inputQuery,
}),
{
page: 1,
per_page: 10,
order: 'desc',
order_by: defaultOrderBy,
}
)
})
it('returns query updated', () => {
assert.deepEqual(
getQuery(
{ page: '3', per_page: '10', order: 'asc', order_by: 'workouts_count' },
orderByList,
defaultOrderBy,
{ query: inputQuery }
),
{ page: 3, per_page: 10, order: 'asc', order_by: 'workouts_count' }
)
})
})