Client - add selects to sort users in administration
This commit is contained in:
parent
80afbe5968
commit
4a5f175053
@ -54,7 +54,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="sport-action">
|
<td class="sport-action">
|
||||||
<span class="cell-heading">
|
<span class="cell-heading">
|
||||||
{{ $t('admin.SPORTS.TABLE.ACTION') }}
|
{{ $t('admin.ACTION') }}
|
||||||
</span>
|
</span>
|
||||||
<div class="action-button">
|
<div class="action-button">
|
||||||
<button
|
<button
|
||||||
|
@ -6,6 +6,12 @@
|
|||||||
<button class="top-button" @click.prevent="$router.push('/admin')">
|
<button class="top-button" @click.prevent="$router.push('/admin')">
|
||||||
{{ $t('admin.BACK_TO_ADMIN') }}
|
{{ $t('admin.BACK_TO_ADMIN') }}
|
||||||
</button>
|
</button>
|
||||||
|
<AdminUsersSelects
|
||||||
|
:sort="sort"
|
||||||
|
:order_by="order_by"
|
||||||
|
:query="query"
|
||||||
|
@updateSelect="reloadUsers"
|
||||||
|
/>
|
||||||
<div class="responsive-table">
|
<div class="responsive-table">
|
||||||
<table>
|
<table>
|
||||||
<thead>
|
<thead>
|
||||||
@ -101,35 +107,39 @@
|
|||||||
ComputedRef,
|
ComputedRef,
|
||||||
computed,
|
computed,
|
||||||
defineComponent,
|
defineComponent,
|
||||||
|
reactive,
|
||||||
watch,
|
watch,
|
||||||
capitalize,
|
capitalize,
|
||||||
onBeforeMount,
|
onBeforeMount,
|
||||||
} from 'vue'
|
} from 'vue'
|
||||||
import { useRoute, LocationQuery } from 'vue-router'
|
import { LocationQuery, useRoute, useRouter } from 'vue-router'
|
||||||
|
|
||||||
|
import AdminUsersSelects from '@/components/Administration/AdminUsersSelects.vue'
|
||||||
import Pagination from '@/components/Common/Pagination.vue'
|
import Pagination from '@/components/Common/Pagination.vue'
|
||||||
import { ROOT_STORE, USER_STORE, USERS_STORE } from '@/store/constants'
|
import { ROOT_STORE, USER_STORE, USERS_STORE } from '@/store/constants'
|
||||||
import { IPagination, IPaginationPayload } 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'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'AdminUsers',
|
name: 'AdminUsers',
|
||||||
components: {
|
components: {
|
||||||
|
AdminUsersSelects,
|
||||||
Pagination,
|
Pagination,
|
||||||
},
|
},
|
||||||
setup() {
|
setup() {
|
||||||
const store = useStore()
|
const store = useStore()
|
||||||
const route = useRoute()
|
const route = useRoute()
|
||||||
|
const router = useRouter()
|
||||||
|
|
||||||
const orders: string[] = ['asc', 'desc']
|
const sort: string[] = ['asc', 'desc']
|
||||||
const order_types: string[] = [
|
const order_by: string[] = [
|
||||||
'admin',
|
'admin',
|
||||||
'created_at',
|
'created_at',
|
||||||
'username',
|
'username',
|
||||||
'workouts_count',
|
'workouts_count',
|
||||||
]
|
]
|
||||||
let query: IPaginationPayload = getQuery(route.query)
|
let query: TPaginationPayload = reactive(getQuery(route.query))
|
||||||
|
|
||||||
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]
|
||||||
@ -144,7 +154,7 @@
|
|||||||
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
() => store.getters[ROOT_STORE.GETTERS.ERROR_MESSAGES]
|
||||||
)
|
)
|
||||||
|
|
||||||
function loadUsers(queryParams: IPaginationPayload) {
|
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 {
|
function getPage(page: string | (string | null)[] | null): number {
|
||||||
@ -156,18 +166,16 @@
|
|||||||
: 10
|
: 10
|
||||||
}
|
}
|
||||||
function getOrder(order: string | (string | null)[] | null): string {
|
function getOrder(order: string | (string | null)[] | null): string {
|
||||||
return order && typeof order === 'string' && orders.includes(order)
|
return order && typeof order === 'string' && sort.includes(order)
|
||||||
? order
|
? order
|
||||||
: 'asc'
|
: 'asc'
|
||||||
}
|
}
|
||||||
function getOrderBy(order_by: string | (string | null)[] | null): string {
|
function getOrderBy(order: string | (string | null)[] | null): string {
|
||||||
return order_by &&
|
return order && typeof order === 'string' && order_by.includes(order)
|
||||||
typeof order_by === 'string' &&
|
? order
|
||||||
order_types.includes(order_by)
|
|
||||||
? order_by
|
|
||||||
: 'created_at'
|
: 'created_at'
|
||||||
}
|
}
|
||||||
function getQuery(query: LocationQuery): IPaginationPayload {
|
function getQuery(query: LocationQuery): TPaginationPayload {
|
||||||
return {
|
return {
|
||||||
page: getPage(query.page),
|
page: getPage(query.page),
|
||||||
per_page: getPerPage(query.per_page),
|
per_page: getPerPage(query.per_page),
|
||||||
@ -181,14 +189,24 @@
|
|||||||
admin,
|
admin,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
function reloadUsers(queryParam: string, queryValue: string) {
|
||||||
|
query[queryParam] = queryValue
|
||||||
|
if (queryParam === 'per_page') {
|
||||||
|
query.page = 1
|
||||||
|
}
|
||||||
|
router.push({ path: '/admin/users', query })
|
||||||
|
}
|
||||||
|
|
||||||
onBeforeMount(() => loadUsers(query))
|
onBeforeMount(() => loadUsers(query))
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => route.query,
|
() => route.query,
|
||||||
(newQuery) => {
|
(newQuery: LocationQuery) => {
|
||||||
query = getQuery(newQuery)
|
query.page = getPage(newQuery.page)
|
||||||
loadUsers(getQuery(newQuery))
|
query.per_page = getPerPage(newQuery.per_page)
|
||||||
|
query.order = getOrder(newQuery.order)
|
||||||
|
query.order_by = getOrderBy(newQuery.order_by)
|
||||||
|
loadUsers(query)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -196,9 +214,12 @@
|
|||||||
authUser,
|
authUser,
|
||||||
errorMessages,
|
errorMessages,
|
||||||
pagination,
|
pagination,
|
||||||
|
order_by,
|
||||||
query,
|
query,
|
||||||
|
sort,
|
||||||
users,
|
users,
|
||||||
capitalize,
|
capitalize,
|
||||||
|
reloadUsers,
|
||||||
updateUser,
|
updateUser,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -225,6 +246,9 @@
|
|||||||
display: block;
|
display: block;
|
||||||
margin-bottom: $default-margin * 2;
|
margin-bottom: $default-margin * 2;
|
||||||
}
|
}
|
||||||
|
.pagination-center {
|
||||||
|
margin-top: -3 * $default-margin;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -0,0 +1,105 @@
|
|||||||
|
<template>
|
||||||
|
<div class="table-selects">
|
||||||
|
<label>
|
||||||
|
{{ $t('admin.USERS.SELECTS.ORDER_BY.LABEL') }}:
|
||||||
|
<select
|
||||||
|
name="order_by"
|
||||||
|
id="order_by"
|
||||||
|
:value="query.order_by"
|
||||||
|
@change="onSelectUpdate"
|
||||||
|
>
|
||||||
|
<option v-for="order in order_by" :value="order" :key="order">
|
||||||
|
{{ $t(`admin.USERS.SELECTS.ORDER_BY.${order}`) }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
{{ $t('admin.USERS.SELECTS.ORDER.LABEL') }}:
|
||||||
|
<select
|
||||||
|
name="order"
|
||||||
|
id="order"
|
||||||
|
:value="query.order"
|
||||||
|
@change="onSelectUpdate"
|
||||||
|
>
|
||||||
|
<option v-for="order in sort" :value="order" :key="order">
|
||||||
|
{{ $t(`admin.USERS.SELECTS.ORDER.${order.toUpperCase()}`) }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
<label>
|
||||||
|
{{ $t('admin.USERS.SELECTS.PER_PAGE.LABEL') }}:
|
||||||
|
<select
|
||||||
|
name="per_page"
|
||||||
|
id="per_page"
|
||||||
|
:value="query.per_page"
|
||||||
|
@change="onSelectUpdate"
|
||||||
|
>
|
||||||
|
<option v-for="nb in per_page" :value="nb" :key="nb">
|
||||||
|
{{ nb }}
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="ts">
|
||||||
|
import { PropType, defineComponent } from 'vue'
|
||||||
|
|
||||||
|
import { TPaginationPayload } from '@/types/api'
|
||||||
|
|
||||||
|
export default defineComponent({
|
||||||
|
name: 'AdminUsersSelects',
|
||||||
|
props: {
|
||||||
|
order_by: {
|
||||||
|
type: Object as PropType<string[]>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
query: {
|
||||||
|
type: Object as PropType<TPaginationPayload>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
sort: {
|
||||||
|
type: Object as PropType<string[]>,
|
||||||
|
required: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
emits: ['updateSelect'],
|
||||||
|
setup(props, { emit }) {
|
||||||
|
function onSelectUpdate(event: Event & { target: HTMLInputElement }) {
|
||||||
|
emit('updateSelect', event.target.id, event.target.value)
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
per_page: [10, 50, 100],
|
||||||
|
onSelectUpdate,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
@import '~@/scss/base.scss';
|
||||||
|
|
||||||
|
.table-selects {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
margin: $default-margin 0;
|
||||||
|
|
||||||
|
label {
|
||||||
|
select {
|
||||||
|
margin-left: $default-margin;
|
||||||
|
padding: $default-padding * 0.5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: $small-limit) {
|
||||||
|
flex-wrap: wrap;
|
||||||
|
label {
|
||||||
|
margin-bottom: $default-margin;
|
||||||
|
select {
|
||||||
|
margin-left: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
@ -38,7 +38,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { PropType, defineComponent } from 'vue'
|
import { PropType, defineComponent } from 'vue'
|
||||||
|
|
||||||
import { IPagination, IPaginationPayload } from '@/types/api'
|
import { IPagination, TPaginationPayload } from '@/types/api'
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
name: 'Pagination',
|
name: 'Pagination',
|
||||||
@ -52,7 +52,7 @@
|
|||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
query: {
|
query: {
|
||||||
type: Object as PropType<IPaginationPayload>,
|
type: Object as PropType<TPaginationPayload>,
|
||||||
required: true,
|
required: true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@ -60,7 +60,7 @@
|
|||||||
function rangePagination(pages: number): number[] {
|
function rangePagination(pages: number): number[] {
|
||||||
return Array.from({ length: pages }, (_, i) => i + 1)
|
return Array.from({ length: pages }, (_, i) => i + 1)
|
||||||
}
|
}
|
||||||
function getQuery(page: number, cursor?: number): IPaginationPayload {
|
function getQuery(page: number, cursor?: number): TPaginationPayload {
|
||||||
const newQuery = Object.assign({}, props.query)
|
const newQuery = Object.assign({}, props.query)
|
||||||
newQuery.page = cursor ? page + cursor : page
|
newQuery.page = cursor ? page + cursor : page
|
||||||
return newQuery
|
return newQuery
|
||||||
|
@ -31,6 +31,23 @@
|
|||||||
"TABLE": {
|
"TABLE": {
|
||||||
"ADD_ADMIN_RIGHTS": "Add admin rights",
|
"ADD_ADMIN_RIGHTS": "Add admin rights",
|
||||||
"REMOVE_ADMIN_RIGHTS": "Remove admin rights"
|
"REMOVE_ADMIN_RIGHTS": "Remove admin rights"
|
||||||
|
},
|
||||||
|
"SELECTS": {
|
||||||
|
"ORDER_BY": {
|
||||||
|
"LABEL": "order by",
|
||||||
|
"admin": "admin status",
|
||||||
|
"created_at": "registration date",
|
||||||
|
"username": "username",
|
||||||
|
"workouts_count": "workout count"
|
||||||
|
},
|
||||||
|
"ORDER": {
|
||||||
|
"LABEL": "sort",
|
||||||
|
"ASC": "ascending",
|
||||||
|
"DESC": "descending"
|
||||||
|
},
|
||||||
|
"PER_PAGE": {
|
||||||
|
"LABEL": "par page"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,23 @@
|
|||||||
"TABLE": {
|
"TABLE": {
|
||||||
"ADD_ADMIN_RIGHTS": "Ajouter les drois d'admin",
|
"ADD_ADMIN_RIGHTS": "Ajouter les drois d'admin",
|
||||||
"REMOVE_ADMIN_RIGHTS": "Retirer les drois d'admin"
|
"REMOVE_ADMIN_RIGHTS": "Retirer les drois d'admin"
|
||||||
|
},
|
||||||
|
"SELECTS": {
|
||||||
|
"ORDER_BY": {
|
||||||
|
"LABEL": "trier par ",
|
||||||
|
"admin": "status administrateur",
|
||||||
|
"created_at": "date d'inscription",
|
||||||
|
"username": "nom d'utilisateur",
|
||||||
|
"workouts_count": "nombre de séances"
|
||||||
|
},
|
||||||
|
"ORDER": {
|
||||||
|
"LABEL": "tri",
|
||||||
|
"ASC": "ascendant",
|
||||||
|
"DESC": "descendant"
|
||||||
|
},
|
||||||
|
"PER_PAGE": {
|
||||||
|
"LABEL": "par page"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,14 +4,14 @@ import authApi from '@/api/authApi'
|
|||||||
import { ROOT_STORE, USERS_STORE } from '@/store/constants'
|
import { ROOT_STORE, USERS_STORE } from '@/store/constants'
|
||||||
import { IRootState } from '@/store/modules/root/types'
|
import { IRootState } from '@/store/modules/root/types'
|
||||||
import { IUsersActions, IUsersState } from '@/store/modules/users/types'
|
import { IUsersActions, IUsersState } from '@/store/modules/users/types'
|
||||||
import { IPaginationPayload } from '@/types/api'
|
import { TPaginationPayload } from '@/types/api'
|
||||||
import { IAdminUserPayload } from '@/types/user'
|
import { IAdminUserPayload } from '@/types/user'
|
||||||
import { handleError } from '@/utils'
|
import { handleError } from '@/utils'
|
||||||
|
|
||||||
export const actions: ActionTree<IUsersState, IRootState> & IUsersActions = {
|
export const actions: ActionTree<IUsersState, IRootState> & IUsersActions = {
|
||||||
[USERS_STORE.ACTIONS.GET_USERS](
|
[USERS_STORE.ACTIONS.GET_USERS](
|
||||||
context: ActionContext<IUsersState, IRootState>,
|
context: ActionContext<IUsersState, IRootState>,
|
||||||
payload: IPaginationPayload
|
payload: TPaginationPayload
|
||||||
): void {
|
): void {
|
||||||
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
||||||
context.commit(USERS_STORE.MUTATIONS.UPDATE_USERS_LOADING, true)
|
context.commit(USERS_STORE.MUTATIONS.UPDATE_USERS_LOADING, true)
|
||||||
@ -40,7 +40,6 @@ export const actions: ActionTree<IUsersState, IRootState> & IUsersActions = {
|
|||||||
context: ActionContext<IUsersState, IRootState>,
|
context: ActionContext<IUsersState, IRootState>,
|
||||||
payload: IAdminUserPayload
|
payload: IAdminUserPayload
|
||||||
): void {
|
): void {
|
||||||
console.log('payload', payload)
|
|
||||||
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
context.commit(ROOT_STORE.MUTATIONS.EMPTY_ERROR_MESSAGES)
|
||||||
authApi
|
authApi
|
||||||
.patch(`users/${payload.username}`, { admin: payload.admin })
|
.patch(`users/${payload.username}`, { admin: payload.admin })
|
||||||
|
@ -7,7 +7,7 @@ import {
|
|||||||
|
|
||||||
import { USERS_STORE } from '@/store/constants'
|
import { USERS_STORE } from '@/store/constants'
|
||||||
import { IRootState } from '@/store/modules/root/types'
|
import { IRootState } from '@/store/modules/root/types'
|
||||||
import { IPagination, IPaginationPayload } from '@/types/api'
|
import { IPagination, TPaginationPayload } from '@/types/api'
|
||||||
import { IAdminUserPayload, IUserProfile } from '@/types/user'
|
import { IAdminUserPayload, IUserProfile } from '@/types/user'
|
||||||
|
|
||||||
export interface IUsersState {
|
export interface IUsersState {
|
||||||
@ -19,7 +19,7 @@ export interface IUsersState {
|
|||||||
export interface IUsersActions {
|
export interface IUsersActions {
|
||||||
[USERS_STORE.ACTIONS.GET_USERS](
|
[USERS_STORE.ACTIONS.GET_USERS](
|
||||||
context: ActionContext<IUsersState, IRootState>,
|
context: ActionContext<IUsersState, IRootState>,
|
||||||
payload: IPaginationPayload
|
payload: TPaginationPayload
|
||||||
): void
|
): void
|
||||||
[USERS_STORE.ACTIONS.UPDATE_USER](
|
[USERS_STORE.ACTIONS.UPDATE_USER](
|
||||||
context: ActionContext<IUsersState, IRootState>,
|
context: ActionContext<IUsersState, IRootState>,
|
||||||
|
@ -6,7 +6,8 @@ export interface IPagination {
|
|||||||
total: number
|
total: number
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IPaginationPayload {
|
export type TPaginationPayload = {
|
||||||
|
[key: string]: string | number
|
||||||
order: string
|
order: string
|
||||||
order_by: string
|
order_by: string
|
||||||
per_page: number
|
per_page: number
|
||||||
|
Loading…
Reference in New Issue
Block a user