forked from AkkomaGang/admin-fe
Merge branch 'feature/add-filters' into 'master'
Add more users filters Closes #9 See merge request pleroma/admin-fe!10
This commit is contained in:
commit
75182336c7
8 changed files with 291 additions and 117 deletions
|
@ -1,11 +1,27 @@
|
||||||
const users = [
|
const users = [
|
||||||
{ deactivated: false, id: '2', nickname: 'allis', local: true, roles: { admin: true, moderator: false }, tags: [] },
|
{ active: true, deactivated: false, id: '2', nickname: 'allis', local: true, external: false, roles: { admin: true, moderator: false }, tags: [] },
|
||||||
{ deactivated: false, id: '10', nickname: 'bob', local: false, roles: { admin: false, moderator: true }, tags: ['sandbox'] },
|
{ active: true, deactivated: false, id: '10', nickname: 'bob', local: false, external: true, roles: { admin: false, moderator: true }, tags: ['sandbox'] },
|
||||||
{ deactivated: true, id: 'abc', nickname: 'john', local: true, roles: { admin: false, moderator: false }, tags: ['strip_media'] }
|
{ active: false, deactivated: true, id: 'abc', nickname: 'john', local: true, external: false, roles: { admin: false, moderator: false }, tags: ['strip_media'] }
|
||||||
]
|
]
|
||||||
|
|
||||||
export async function fetchUsers(showLocalUsersOnly, authHost, token, page = 1) {
|
const filterUsers = (str) => {
|
||||||
const filteredUsers = showLocalUsersOnly ? users.filter(user => user.local) : users
|
const filters = str.split(',').filter(item => item.length > 0)
|
||||||
|
if (filters.length === 0) {
|
||||||
|
return users
|
||||||
|
}
|
||||||
|
const applyFilters = (acc, filters, users) => {
|
||||||
|
if (filters.length === 0) {
|
||||||
|
return acc
|
||||||
|
}
|
||||||
|
const filteredUsers = users.filter(user => user[filters[0]])
|
||||||
|
const newAcc = [...filteredUsers]
|
||||||
|
return applyFilters(newAcc, filters.slice(1), filteredUsers)
|
||||||
|
}
|
||||||
|
return applyFilters([], filters, users)
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function fetchUsers(filters, authHost, token, page = 1) {
|
||||||
|
const filteredUsers = filterUsers(filters)
|
||||||
return Promise.resolve({ data: {
|
return Promise.resolve({ data: {
|
||||||
users: filteredUsers,
|
users: filteredUsers,
|
||||||
count: filteredUsers.length,
|
count: filteredUsers.length,
|
||||||
|
@ -18,8 +34,8 @@ export async function toggleUserActivation(nickname, authHost, token) {
|
||||||
return Promise.resolve({ data: { ...response, deactivated: !response.deactivated }})
|
return Promise.resolve({ data: { ...response, deactivated: !response.deactivated }})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function searchUsers(query, showLocalUsersOnly, authHost, token, page = 1) {
|
export async function searchUsers(query, filters, authHost, token, page = 1) {
|
||||||
const filteredUsers = showLocalUsersOnly ? users.filter(user => user.local) : users
|
const filteredUsers = filterUsers(filters)
|
||||||
const response = filteredUsers.filter(user => user.nickname === query)
|
const response = filteredUsers.filter(user => user.nickname === query)
|
||||||
return Promise.resolve({ data: {
|
return Promise.resolve({ data: {
|
||||||
users: response,
|
users: response,
|
||||||
|
|
|
@ -2,10 +2,10 @@ import request from '@/utils/request'
|
||||||
import { getToken } from '@/utils/auth'
|
import { getToken } from '@/utils/auth'
|
||||||
import { baseName } from './utils'
|
import { baseName } from './utils'
|
||||||
|
|
||||||
export async function fetchUsers(showLocalUsersOnly, authHost, token, page = 1) {
|
export async function fetchUsers(filters, authHost, token, page = 1) {
|
||||||
return await request({
|
return await request({
|
||||||
baseURL: baseName(authHost),
|
baseURL: baseName(authHost),
|
||||||
url: `/api/pleroma/admin/users?page=${page}&local_only=${showLocalUsersOnly}`,
|
url: `/api/pleroma/admin/users?page=${page}&filters=${filters}`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
headers: authHeaders(token)
|
headers: authHeaders(token)
|
||||||
})
|
})
|
||||||
|
@ -20,10 +20,10 @@ export async function toggleUserActivation(nickname, authHost, token) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function searchUsers(query, showLocalUsersOnly, authHost, token, page = 1) {
|
export async function searchUsers(query, filters, authHost, token, page = 1) {
|
||||||
return await request({
|
return await request({
|
||||||
baseURL: baseName(authHost),
|
baseURL: baseName(authHost),
|
||||||
url: `/api/pleroma/admin/users?query=${query}&page=${page}&local_only=${showLocalUsersOnly}`,
|
url: `/api/pleroma/admin/users?query=${query}&page=${page}&filters=${filters}`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
headers: authHeaders(token)
|
headers: authHeaders(token)
|
||||||
})
|
})
|
||||||
|
|
|
@ -189,5 +189,14 @@ export default {
|
||||||
sandbox: 'Force posts to be followers-only',
|
sandbox: 'Force posts to be followers-only',
|
||||||
disableRemoteSubscription: 'Disallow following user from remote instances',
|
disableRemoteSubscription: 'Disallow following user from remote instances',
|
||||||
disableAnySubscription: 'Disallow following user at all'
|
disableAnySubscription: 'Disallow following user at all'
|
||||||
|
},
|
||||||
|
usersFilter: {
|
||||||
|
inputPlaceholder: 'Select filter',
|
||||||
|
byUserType: 'By user type',
|
||||||
|
local: 'Local',
|
||||||
|
external: 'External',
|
||||||
|
byStatus: 'By status',
|
||||||
|
active: 'Active',
|
||||||
|
deactivated: 'Deactivated'
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,12 @@ const users = {
|
||||||
searchQuery: '',
|
searchQuery: '',
|
||||||
totalUsersCount: 0,
|
totalUsersCount: 0,
|
||||||
currentPage: 1,
|
currentPage: 1,
|
||||||
showLocalUsersOnly: false
|
filters: {
|
||||||
|
local: false,
|
||||||
|
external: false,
|
||||||
|
active: false,
|
||||||
|
deactivated: false
|
||||||
|
}
|
||||||
},
|
},
|
||||||
mutations: {
|
mutations: {
|
||||||
SET_USERS: (state, users) => {
|
SET_USERS: (state, users) => {
|
||||||
|
@ -37,13 +42,14 @@ const users = {
|
||||||
SET_SEARCH_QUERY: (state, query) => {
|
SET_SEARCH_QUERY: (state, query) => {
|
||||||
state.searchQuery = query
|
state.searchQuery = query
|
||||||
},
|
},
|
||||||
SET_LOCAL_USERS_FILTER: (state, value) => {
|
SET_USERS_FILTERS: (state, filters) => {
|
||||||
state.showLocalUsersOnly = value
|
state.filters = filters
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
actions: {
|
actions: {
|
||||||
async FetchUsers({ commit, state, getters }, { page }) {
|
async FetchUsers({ commit, state, getters }, { page }) {
|
||||||
const response = await fetchUsers(state.showLocalUsersOnly, getters.authHost, getters.token, page)
|
const filters = Object.keys(state.filters).filter(filter => state.filters[filter]).join()
|
||||||
|
const response = await fetchUsers(filters, getters.authHost, getters.token, page)
|
||||||
|
|
||||||
commit('SET_LOADING', true)
|
commit('SET_LOADING', true)
|
||||||
|
|
||||||
|
@ -62,13 +68,25 @@ const users = {
|
||||||
commit('SET_LOADING', true)
|
commit('SET_LOADING', true)
|
||||||
commit('SET_SEARCH_QUERY', query)
|
commit('SET_SEARCH_QUERY', query)
|
||||||
|
|
||||||
const response = await searchUsers(query, state.showLocalUsersOnly, getters.authHost, getters.token, page)
|
const filters = Object.keys(state.filters).filter(filter => state.filters[filter]).join()
|
||||||
|
const response = await searchUsers(query, filters, getters.authHost, getters.token, page)
|
||||||
|
|
||||||
loadUsers(commit, page, response.data)
|
loadUsers(commit, page, response.data)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
async ToggleLocalUsersFilter({ commit, dispatch, state }, value) {
|
async ToggleUsersFilter({ commit, dispatch, state }, filters) {
|
||||||
commit('SET_LOCAL_USERS_FILTER', value)
|
const defaultFilters = {
|
||||||
|
local: false,
|
||||||
|
external: false,
|
||||||
|
active: false,
|
||||||
|
deactivated: false
|
||||||
|
}
|
||||||
|
const currentFilters = { ...defaultFilters, ...filters }
|
||||||
|
commit('SET_USERS_FILTERS', currentFilters)
|
||||||
|
dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
|
||||||
|
},
|
||||||
|
async ClearFilters({ commit, dispatch, state }) {
|
||||||
|
commit('CLEAR_USERS_FILTERS')
|
||||||
dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
|
dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
|
||||||
},
|
},
|
||||||
async ToggleRight({ commit, getters }, { user, right }) {
|
async ToggleRight({ commit, getters }, { user, right }) {
|
||||||
|
|
72
src/views/users/components/UsersFilter.vue
Normal file
72
src/views/users/components/UsersFilter.vue
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
<template>
|
||||||
|
<el-select
|
||||||
|
v-model="value"
|
||||||
|
:clearable="isDesktop"
|
||||||
|
:placeholder="$t('usersFilter.inputPlaceholder')"
|
||||||
|
multiple
|
||||||
|
class="select-field"
|
||||||
|
@change="toggleFilters">
|
||||||
|
<el-option-group :label="$t('usersFilter.byUserType')">
|
||||||
|
<el-option value="local">{{ $t('usersFilter.local') }}</el-option>
|
||||||
|
<el-option value="external">{{ $t('usersFilter.external') }}</el-option>
|
||||||
|
</el-option-group>
|
||||||
|
<el-option-group :label="$t('usersFilter.byStatus')">
|
||||||
|
<el-option value="active">{{ $t('usersFilter.active') }}</el-option>
|
||||||
|
<el-option value="deactivated">{{ $t('usersFilter.deactivated') }}</el-option>
|
||||||
|
</el-option-group>
|
||||||
|
</el-select>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
value: []
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
isDesktop() {
|
||||||
|
return this.$store.state.app.device === 'desktop'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
removeOppositeFilters() {
|
||||||
|
const filtersQuantity = Object.keys(this.$store.state.users.filters).length
|
||||||
|
const currentFilters = this.$data.value.slice()
|
||||||
|
const indexOfLocal = currentFilters.indexOf('local')
|
||||||
|
const indexOfExternal = currentFilters.indexOf('external')
|
||||||
|
const indexOfActive = currentFilters.indexOf('active')
|
||||||
|
const indexOfDeactivated = currentFilters.indexOf('deactivated')
|
||||||
|
if (currentFilters.length === filtersQuantity) {
|
||||||
|
return []
|
||||||
|
} else if (indexOfLocal > -1 && indexOfExternal > -1) {
|
||||||
|
const filterToRemove = indexOfLocal > indexOfExternal ? indexOfExternal : indexOfLocal
|
||||||
|
currentFilters.splice(filterToRemove, 1)
|
||||||
|
} else if (indexOfActive > -1 && indexOfDeactivated > -1) {
|
||||||
|
const filterToRemove = indexOfActive > indexOfDeactivated ? indexOfDeactivated : indexOfActive
|
||||||
|
currentFilters.splice(filterToRemove, 1)
|
||||||
|
}
|
||||||
|
return currentFilters
|
||||||
|
},
|
||||||
|
toggleFilters() {
|
||||||
|
this.$data.value = this.removeOppositeFilters()
|
||||||
|
const currentFilters = this.$data.value.reduce((acc, filter) => ({ ...acc, [filter]: true }), {})
|
||||||
|
this.$store.dispatch('ToggleUsersFilter', currentFilters)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style rel='stylesheet/scss' lang='scss' scoped>
|
||||||
|
.select-field {
|
||||||
|
width: 350px;
|
||||||
|
}
|
||||||
|
@media
|
||||||
|
only screen and (max-width: 760px),
|
||||||
|
(min-device-width: 768px) and (max-device-width: 1024px) {
|
||||||
|
.select-field {
|
||||||
|
width: 100%;
|
||||||
|
margin-bottom: 5px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
|
@ -2,7 +2,7 @@
|
||||||
<div class="users-container">
|
<div class="users-container">
|
||||||
<h1>{{ $t('users.users') }}</h1>
|
<h1>{{ $t('users.users') }}</h1>
|
||||||
<div class="search-container">
|
<div class="search-container">
|
||||||
<el-checkbox :value="showLocalUsersOnly" @change="handleLocalUsersCheckbox">{{ $t('users.localUsersOnly') }}</el-checkbox>
|
<users-filter/>
|
||||||
<el-input :placeholder="$t('users.search')" class="search" @input="handleDebounceSearchInput"/>
|
<el-input :placeholder="$t('users.search')" class="search" @input="handleDebounceSearchInput"/>
|
||||||
</div>
|
</div>
|
||||||
<el-table v-loading="loading" :data="users" style="width: 100%">
|
<el-table v-loading="loading" :data="users" style="width: 100%">
|
||||||
|
@ -37,41 +37,65 @@
|
||||||
<i v-if="isDesktop" class="el-icon-arrow-down el-icon--right"/>
|
<i v-if="isDesktop" class="el-icon-arrow-down el-icon--right"/>
|
||||||
</span>
|
</span>
|
||||||
<el-dropdown-menu slot="dropdown">
|
<el-dropdown-menu slot="dropdown">
|
||||||
<el-dropdown-item v-if="showAdminAction(scope.row)" @click.native="toggleUserRight(scope.row, 'admin')">
|
<el-dropdown-item
|
||||||
|
v-if="showAdminAction(scope.row)"
|
||||||
|
@click.native="toggleUserRight(scope.row, 'admin')">
|
||||||
{{ scope.row.roles.admin ? $t('users.revokeAdmin') : $t('users.grantAdmin') }}
|
{{ scope.row.roles.admin ? $t('users.revokeAdmin') : $t('users.grantAdmin') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item v-if="showAdminAction(scope.row)" @click.native="toggleUserRight(scope.row, 'moderator')">
|
<el-dropdown-item
|
||||||
|
v-if="showAdminAction(scope.row)"
|
||||||
|
@click.native="toggleUserRight(scope.row, 'moderator')">
|
||||||
{{ scope.row.roles.moderator ? $t('users.revokeModerator') : $t('users.grantModerator') }}
|
{{ scope.row.roles.moderator ? $t('users.revokeModerator') : $t('users.grantModerator') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item v-if="showDeactivatedButton(scope.row.id)" :divided="showAdminAction(scope.row)" @click.native="handleDeactivation(scope.row)">
|
<el-dropdown-item
|
||||||
|
v-if="showDeactivatedButton(scope.row.id)"
|
||||||
|
:divided="showAdminAction(scope.row)"
|
||||||
|
@click.native="handleDeactivation(scope.row)">
|
||||||
{{ scope.row.deactivated ? $t('users.activateAccount') : $t('users.deactivateAccount') }}
|
{{ scope.row.deactivated ? $t('users.activateAccount') : $t('users.deactivateAccount') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item v-if="showDeactivatedButton(scope.row.id)" @click.native="handleDeletion(scope.row)">
|
<el-dropdown-item
|
||||||
|
v-if="showDeactivatedButton(scope.row.id)"
|
||||||
|
@click.native="handleDeletion(scope.row)">
|
||||||
{{ $t('users.deleteAccount') }}
|
{{ $t('users.deleteAccount') }}
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item :divided="showAdminAction(scope.row)" @click.native="toggleTag(scope.row, 'force_nsfw')">
|
<el-dropdown-item
|
||||||
|
:divided="showAdminAction(scope.row)"
|
||||||
|
:class="{ 'active-tag': scope.row.tags.includes('force_nsfw') }"
|
||||||
|
@click.native="toggleTag(scope.row, 'force_nsfw')">
|
||||||
{{ $t('users.forceNsfw') }}
|
{{ $t('users.forceNsfw') }}
|
||||||
<i v-if="scope.row.tags.includes('force_nsfw')" class="el-icon-circle-check"/>
|
<i v-if="scope.row.tags.includes('force_nsfw')" class="el-icon-check"/>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item @click.native="toggleTag(scope.row, 'strip_media')">
|
<el-dropdown-item
|
||||||
|
:class="{ 'active-tag': scope.row.tags.includes('strip_media') }"
|
||||||
|
@click.native="toggleTag(scope.row, 'strip_media')">
|
||||||
{{ $t('users.stripMedia') }}
|
{{ $t('users.stripMedia') }}
|
||||||
<i v-if="scope.row.tags.includes('strip_media')" class="el-icon-circle-check"/>
|
<i v-if="scope.row.tags.includes('strip_media')" class="el-icon-check"/>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item @click.native="toggleTag(scope.row, 'force_unlisted')">
|
<el-dropdown-item
|
||||||
|
:class="{ 'active-tag': scope.row.tags.includes('force_unlisted') }"
|
||||||
|
@click.native="toggleTag(scope.row, 'force_unlisted')">
|
||||||
{{ $t('users.forceUnlisted') }}
|
{{ $t('users.forceUnlisted') }}
|
||||||
<i v-if="scope.row.tags.includes('force_unlisted')" class="el-icon-circle-check"/>
|
<i v-if="scope.row.tags.includes('force_unlisted')" class="el-icon-check"/>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item @click.native="toggleTag(scope.row, 'sandbox')">
|
<el-dropdown-item
|
||||||
|
:class="{ 'active-tag': scope.row.tags.includes('sandbox') }"
|
||||||
|
@click.native="toggleTag(scope.row, 'sandbox')">
|
||||||
{{ $t('users.sandbox') }}
|
{{ $t('users.sandbox') }}
|
||||||
<i v-if="scope.row.tags.includes('sandbox')" class="el-icon-circle-check"/>
|
<i v-if="scope.row.tags.includes('sandbox')" class="el-icon-check"/>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item v-if="scope.row.local" @click.native="toggleTag(scope.row, 'disable_remote_subscription')">
|
<el-dropdown-item
|
||||||
|
v-if="scope.row.local"
|
||||||
|
:class="{ 'active-tag': scope.row.tags.includes('disable_remote_subscription') }"
|
||||||
|
@click.native="toggleTag(scope.row, 'disable_remote_subscription')">
|
||||||
{{ $t('users.disableRemoteSubscription') }}
|
{{ $t('users.disableRemoteSubscription') }}
|
||||||
<i v-if="scope.row.tags.includes('disable_remote_subscription')" class="el-icon-circle-check"/>
|
<i v-if="scope.row.tags.includes('disable_remote_subscription')" class="el-icon-check"/>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
<el-dropdown-item v-if="scope.row.local" @click.native="toggleTag(scope.row, 'disable_any_subscription')">
|
<el-dropdown-item
|
||||||
|
v-if="scope.row.local"
|
||||||
|
:class="{ 'active-tag': scope.row.tags.includes('disable_any_subscription') }"
|
||||||
|
@click.native="toggleTag(scope.row, 'disable_any_subscription')">
|
||||||
{{ $t('users.disableAnySubscription') }}
|
{{ $t('users.disableAnySubscription') }}
|
||||||
<i v-if="scope.row.tags.includes('disable_any_subscription')" class="el-icon-circle-check"/>
|
<i v-if="scope.row.tags.includes('disable_any_subscription')" class="el-icon-check"/>
|
||||||
</el-dropdown-item>
|
</el-dropdown-item>
|
||||||
</el-dropdown-menu>
|
</el-dropdown-menu>
|
||||||
</el-dropdown>
|
</el-dropdown>
|
||||||
|
@ -93,9 +117,13 @@
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import debounce from 'lodash.debounce'
|
import debounce from 'lodash.debounce'
|
||||||
|
import UsersFilter from './components/UsersFilter'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Users',
|
name: 'Users',
|
||||||
|
components: {
|
||||||
|
UsersFilter
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
loading() {
|
loading() {
|
||||||
return this.$store.state.users.loading
|
return this.$store.state.users.loading
|
||||||
|
@ -112,9 +140,6 @@ export default {
|
||||||
currentPage() {
|
currentPage() {
|
||||||
return this.$store.state.users.currentPage
|
return this.$store.state.users.currentPage
|
||||||
},
|
},
|
||||||
showLocalUsersOnly() {
|
|
||||||
return this.$store.state.users.showLocalUsersOnly
|
|
||||||
},
|
|
||||||
isDesktop() {
|
isDesktop() {
|
||||||
return this.$store.state.app.device === 'desktop'
|
return this.$store.state.app.device === 'desktop'
|
||||||
},
|
},
|
||||||
|
@ -151,9 +176,6 @@ export default {
|
||||||
showAdminAction({ local, id }) {
|
showAdminAction({ local, id }) {
|
||||||
return local && this.showDeactivatedButton(id)
|
return local && this.showDeactivatedButton(id)
|
||||||
},
|
},
|
||||||
handleLocalUsersCheckbox(e) {
|
|
||||||
this.$store.dispatch('ToggleLocalUsersFilter', e)
|
|
||||||
},
|
|
||||||
activationIcon(status) {
|
activationIcon(status) {
|
||||||
return status ? 'el-icon-error' : 'el-icon-success'
|
return status ? 'el-icon-error' : 'el-icon-success'
|
||||||
},
|
},
|
||||||
|
@ -174,9 +196,18 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style rel='stylesheet/scss' lang='scss' scoped>
|
<style rel='stylesheet/scss' lang='scss' scoped>
|
||||||
|
.active-tag {
|
||||||
|
color: #409EFF;
|
||||||
|
font-weight: 700;
|
||||||
|
.el-icon-check {
|
||||||
|
color: #409EFF;
|
||||||
|
float: right;
|
||||||
|
margin: 7px 0 0 15px;
|
||||||
|
}
|
||||||
|
}
|
||||||
.users-container {
|
.users-container {
|
||||||
h1 {
|
h1 {
|
||||||
margin-left: 15px;
|
margin: 22px 0 0 15px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.pagination {
|
.pagination {
|
||||||
|
@ -185,16 +216,15 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.search {
|
.search {
|
||||||
width: 300px;
|
width: 350px;
|
||||||
margin-bottom: 21.5px;
|
|
||||||
margin-right: 15px;
|
|
||||||
float: right;
|
float: right;
|
||||||
}
|
}
|
||||||
.search-container {
|
.search-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
height: 36px;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
align-items: baseline;
|
align-items: center;
|
||||||
margin-left: 15px;
|
margin: 22px 15px 22px 15px
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@media
|
@media
|
||||||
|
@ -202,7 +232,7 @@ only screen and (max-width: 760px),
|
||||||
(min-device-width: 768px) and (max-device-width: 1024px) {
|
(min-device-width: 768px) and (max-device-width: 1024px) {
|
||||||
.users-container {
|
.users-container {
|
||||||
h1 {
|
h1 {
|
||||||
margin-left: 7px;
|
margin: 7px 10px 7px 10px;
|
||||||
}
|
}
|
||||||
.el-dropdown-link {
|
.el-dropdown-link {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
@ -212,16 +242,13 @@ only screen and (max-width: 760px),
|
||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
.search {
|
.search {
|
||||||
width: 50%;
|
width: 100%;
|
||||||
margin-bottom: 21.5px;
|
|
||||||
margin-right: 7px;
|
|
||||||
float: right;
|
|
||||||
}
|
}
|
||||||
.search-container {
|
.search-container {
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
height: 82px;
|
||||||
align-items: baseline;
|
flex-direction: column;
|
||||||
margin-left: 7px;
|
margin: 0 10px 7px 10px
|
||||||
}
|
}
|
||||||
.el-tag {
|
.el-tag {
|
||||||
width: 30px;
|
width: 30px;
|
||||||
|
|
|
@ -6,6 +6,8 @@ import storeConfig from './store.conf'
|
||||||
import { cloneDeep } from 'lodash'
|
import { cloneDeep } from 'lodash'
|
||||||
|
|
||||||
config.mocks["$t"] = () => {}
|
config.mocks["$t"] = () => {}
|
||||||
|
config.stubs['users-filter'] = '<div />'
|
||||||
|
|
||||||
|
|
||||||
const localVue = createLocalVue()
|
const localVue = createLocalVue()
|
||||||
localVue.use(Vuex)
|
localVue.use(Vuex)
|
||||||
|
@ -43,8 +45,7 @@ describe('Search and filter users', () => {
|
||||||
|
|
||||||
await wrapper.vm.$nextTick()
|
await wrapper.vm.$nextTick()
|
||||||
expect(wrapper.vm.usersCount).toEqual(3)
|
expect(wrapper.vm.usersCount).toEqual(3)
|
||||||
|
const input = wrapper.find('.search input.el-input__inner')
|
||||||
const input = wrapper.find('input.el-input__inner')
|
|
||||||
input.element.value = 'bob'
|
input.element.value = 'bob'
|
||||||
input.trigger('input')
|
input.trigger('input')
|
||||||
await wrapper.vm.$nextTick()
|
await wrapper.vm.$nextTick()
|
||||||
|
@ -57,66 +58,6 @@ describe('Search and filter users', () => {
|
||||||
|
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('shows local users on checkbox click', async (done) => {
|
|
||||||
const wrapper = mount(Users, {
|
|
||||||
store,
|
|
||||||
localVue
|
|
||||||
})
|
|
||||||
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.vm.usersCount).toEqual(3)
|
|
||||||
|
|
||||||
const input = wrapper.find('input.el-checkbox__original')
|
|
||||||
input.trigger('click')
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.vm.usersCount).toEqual(2)
|
|
||||||
|
|
||||||
input.trigger('click')
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.vm.usersCount).toEqual(3)
|
|
||||||
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('shows local users with search query', async (done) => {
|
|
||||||
const wrapper = mount(Users, {
|
|
||||||
store,
|
|
||||||
localVue
|
|
||||||
})
|
|
||||||
|
|
||||||
wrapper.vm.handleDebounceSearchInput = (query) => {
|
|
||||||
store.dispatch('SearchUsers', { query, page: 1 })
|
|
||||||
}
|
|
||||||
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.vm.usersCount).toEqual(3)
|
|
||||||
|
|
||||||
const checkboxInput = wrapper.find('input.el-checkbox__original')
|
|
||||||
checkboxInput.trigger('click')
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
const searchInput = wrapper.find('input.el-input__inner')
|
|
||||||
searchInput.element.value = 'bob'
|
|
||||||
searchInput.trigger('input')
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.vm.usersCount).toEqual(0)
|
|
||||||
|
|
||||||
searchInput.element.value = 'allis'
|
|
||||||
searchInput.trigger('input')
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.vm.usersCount).toEqual(1)
|
|
||||||
|
|
||||||
searchInput.element.value = ''
|
|
||||||
searchInput.trigger('input')
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.vm.usersCount).toEqual(2)
|
|
||||||
|
|
||||||
checkboxInput.trigger('click')
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
expect(wrapper.vm.usersCount).toEqual(3)
|
|
||||||
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
|
|
||||||
describe('Users actions', () => {
|
describe('Users actions', () => {
|
||||||
|
|
91
test/views/users/usersFilters.test.js
Normal file
91
test/views/users/usersFilters.test.js
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
import Vuex from 'vuex'
|
||||||
|
import { mount, createLocalVue, config } from '@vue/test-utils'
|
||||||
|
import Element from 'element-ui'
|
||||||
|
import Filters from '@/views/users/components/UsersFilter'
|
||||||
|
import storeConfig from './store.conf'
|
||||||
|
import { cloneDeep } from 'lodash'
|
||||||
|
import flushPromises from 'flush-promises'
|
||||||
|
|
||||||
|
config.mocks["$t"] = () => {}
|
||||||
|
config.stubs.transition = false
|
||||||
|
|
||||||
|
const localVue = createLocalVue()
|
||||||
|
localVue.use(Vuex)
|
||||||
|
localVue.use(Element)
|
||||||
|
|
||||||
|
jest.mock('@/api/users')
|
||||||
|
|
||||||
|
describe('Filters users', () => {
|
||||||
|
let store
|
||||||
|
|
||||||
|
beforeEach(async() => {
|
||||||
|
store = new Vuex.Store(cloneDeep(storeConfig))
|
||||||
|
store.dispatch('FetchUsers', { page: 1 })
|
||||||
|
await flushPromises()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows local users when "Local" filter is applied', async (done) => {
|
||||||
|
const wrapper = mount(Filters, {
|
||||||
|
store,
|
||||||
|
localVue
|
||||||
|
})
|
||||||
|
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(3)
|
||||||
|
|
||||||
|
const filter = wrapper.find(`li.el-select-dropdown__item:nth-child(${1})`)
|
||||||
|
filter.trigger('click')
|
||||||
|
await flushPromises()
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(2)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows users with applied filter and search query', async (done) => {
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(3)
|
||||||
|
|
||||||
|
store.dispatch('ToggleUsersFilter', { active: true })
|
||||||
|
await flushPromises()
|
||||||
|
store.dispatch('SearchUsers', { query: 'john', page: 1 })
|
||||||
|
await flushPromises()
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(0)
|
||||||
|
|
||||||
|
store.dispatch('SearchUsers', { query: 'allis', page: 1 })
|
||||||
|
await flushPromises()
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(1)
|
||||||
|
|
||||||
|
store.dispatch('SearchUsers', { query: '', page: 1 })
|
||||||
|
await flushPromises()
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(2)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('applies two filters', async (done) => {
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(3)
|
||||||
|
|
||||||
|
store.dispatch('ToggleUsersFilter', { active: true, local: true })
|
||||||
|
await flushPromises()
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(1)
|
||||||
|
expect(store.state.users.fetchedUsers[0].nickname).toEqual('allis')
|
||||||
|
|
||||||
|
store.dispatch('ToggleUsersFilter', { deactivated: true, external: true })
|
||||||
|
await flushPromises()
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(0)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows all users after removing filters', async (done) => {
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(3)
|
||||||
|
|
||||||
|
store.dispatch('ToggleUsersFilter', { deactivated: true })
|
||||||
|
await flushPromises()
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(1)
|
||||||
|
|
||||||
|
store.dispatch('ToggleUsersFilter', {})
|
||||||
|
await flushPromises()
|
||||||
|
expect(store.state.users.totalUsersCount).toEqual(3)
|
||||||
|
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
Loading…
Reference in a new issue