Client - refactoring pagination query
This commit is contained in:
parent
73a0b53dd7
commit
c5428c28a6
@ -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,
|
||||||
|
@ -13,3 +13,8 @@ export type TPaginationPayload = {
|
|||||||
per_page: number
|
per_page: number
|
||||||
page: number
|
page: number
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface IQueryOptions {
|
||||||
|
defaultSort?: string
|
||||||
|
query?: TPaginationPayload
|
||||||
|
}
|
||||||
|
50
fittrackee_client/src/utils/api.ts
Normal file
50
fittrackee_client/src/utils/api.ts
Normal 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
|
||||||
|
}
|
238
fittrackee_client/tests/unit/utils/api.spec.ts
Normal file
238
fittrackee_client/tests/unit/utils/api.spec.ts
Normal 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' }
|
||||||
|
)
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in New Issue
Block a user