Merge branch 'feature/add-users-actions' into 'master'
Add actions to moderation menu Closes #4 See merge request pleroma/admin-fe!7
This commit is contained in:
commit
76736c795b
7 changed files with 356 additions and 113 deletions
|
@ -1,7 +1,7 @@
|
||||||
const users = [
|
const users = [
|
||||||
{ deactivated: false, id: '1', nickname: 'john', local: true },
|
{ deactivated: false, id: '2', nickname: 'allis', local: true, roles: { admin: true, moderator: false }, tags: [] },
|
||||||
{ deactivated: false, id: '2', nickname: 'bob', local: false },
|
{ deactivated: false, id: '10', nickname: 'bob', local: false, roles: { admin: false, moderator: true }, tags: ['sandbox'] },
|
||||||
{ deactivated: true, id: '3', nickname: 'allis', local: true }
|
{ deactivated: true, id: 'abc', nickname: 'john', local: true, roles: { admin: false, moderator: false }, tags: ['strip_media'] }
|
||||||
]
|
]
|
||||||
|
|
||||||
export async function fetchUsers(showLocalUsersOnly, token, page = 1) {
|
export async function fetchUsers(showLocalUsersOnly, token, page = 1) {
|
||||||
|
@ -27,3 +27,29 @@ export async function searchUsers(query, showLocalUsersOnly, token, page = 1) {
|
||||||
page_size: 50
|
page_size: 50
|
||||||
}})
|
}})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function addRight(nickname, right, token) {
|
||||||
|
return Promise.resolve({ data:
|
||||||
|
{ [`is_${right}`]: true }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteRight(nickname, right, token) {
|
||||||
|
return Promise.resolve({ data:
|
||||||
|
{ [`is_${right}`]: false }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteUser(nickname, token) {
|
||||||
|
return Promise.resolve({ data:
|
||||||
|
nickname
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function tagUser(nickname, tag, token) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function untagUser(nickname, tag, token) {
|
||||||
|
return Promise.resolve()
|
||||||
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ export async function fetchUsers(showLocalUsersOnly, token, page = 1) {
|
||||||
return await request({
|
return await request({
|
||||||
url: `/api/pleroma/admin/users?page=${page}&local_only=${showLocalUsersOnly}`,
|
url: `/api/pleroma/admin/users?page=${page}&local_only=${showLocalUsersOnly}`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
headers: token ? { 'Authorization': `Bearer ${getToken()}` } : {}
|
headers: authHeaders(token)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ export async function toggleUserActivation(nickname, token) {
|
||||||
return await request({
|
return await request({
|
||||||
url: `/api/pleroma/admin/users/${nickname}/toggle_activation`,
|
url: `/api/pleroma/admin/users/${nickname}/toggle_activation`,
|
||||||
method: 'patch',
|
method: 'patch',
|
||||||
headers: token ? { 'Authorization': `Bearer ${getToken()}` } : {}
|
headers: authHeaders(token)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,7 +21,50 @@ export async function searchUsers(query, showLocalUsersOnly, token, page = 1) {
|
||||||
return await request({
|
return await request({
|
||||||
url: `/api/pleroma/admin/users?query=${query}&page=${page}&local_only=${showLocalUsersOnly}`,
|
url: `/api/pleroma/admin/users?query=${query}&page=${page}&local_only=${showLocalUsersOnly}`,
|
||||||
method: 'get',
|
method: 'get',
|
||||||
headers: token ? { 'Authorization': `Bearer ${getToken()}` } : {}
|
headers: authHeaders(token)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export async function addRight(nickname, right, token) {
|
||||||
|
return await request({
|
||||||
|
url: `/api/pleroma/admin/permission_group/${nickname}/${right}`,
|
||||||
|
method: 'post',
|
||||||
|
headers: authHeaders(token)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteRight(nickname, right, token) {
|
||||||
|
return await request({
|
||||||
|
url: `/api/pleroma/admin/permission_group/${nickname}/${right}`,
|
||||||
|
method: 'delete',
|
||||||
|
headers: authHeaders(token)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function deleteUser(nickname, token) {
|
||||||
|
return await request({
|
||||||
|
url: `/api/pleroma/admin/user.json?nickname=${nickname}`,
|
||||||
|
method: 'delete',
|
||||||
|
headers: authHeaders(token)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function tagUser(nickname, tag, token) {
|
||||||
|
return await request({
|
||||||
|
url: '/api/pleroma/admin/users/tag',
|
||||||
|
method: 'put',
|
||||||
|
headers: authHeaders(token),
|
||||||
|
data: { nicknames: [nickname], tags: [tag] }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function untagUser(nickname, tag, token) {
|
||||||
|
return await request({
|
||||||
|
url: '/api/pleroma/admin/users/tag',
|
||||||
|
method: 'delete',
|
||||||
|
headers: authHeaders(token),
|
||||||
|
data: { nicknames: [nickname], tags: [tag] }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
const authHeaders = (token) => token ? { 'Authorization': `Bearer ${getToken()}` } : {}
|
||||||
|
|
|
@ -87,29 +87,11 @@ const user = {
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
|
||||||
// 第三方验证登录
|
|
||||||
// LoginByThirdparty({ commit, state }, code) {
|
|
||||||
// return new Promise((resolve, reject) => {
|
|
||||||
// commit('SET_CODE', code)
|
|
||||||
// loginByThirdparty(state.status, state.email, state.code).then(response => {
|
|
||||||
// commit('SET_TOKEN', response.data.token)
|
|
||||||
// setToken(response.data.token)
|
|
||||||
// resolve()
|
|
||||||
// }).catch(error => {
|
|
||||||
// reject(error)
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// },
|
|
||||||
|
|
||||||
// 登出
|
|
||||||
LogOut({ commit }) {
|
LogOut({ commit }) {
|
||||||
commit('SET_TOKEN', '')
|
commit('SET_TOKEN', '')
|
||||||
commit('SET_ROLES', [])
|
commit('SET_ROLES', [])
|
||||||
removeToken()
|
removeToken()
|
||||||
},
|
},
|
||||||
|
|
||||||
// 前端 登出
|
|
||||||
FedLogOut({ commit }) {
|
FedLogOut({ commit }) {
|
||||||
return new Promise(resolve => {
|
return new Promise(resolve => {
|
||||||
commit('SET_TOKEN', '')
|
commit('SET_TOKEN', '')
|
||||||
|
@ -117,24 +99,6 @@ const user = {
|
||||||
resolve()
|
resolve()
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// 动态修改权限
|
|
||||||
// ChangeRoles({ commit, dispatch }, role) {
|
|
||||||
// return new Promise(resolve => {
|
|
||||||
// commit('SET_TOKEN', role)
|
|
||||||
// setToken(role)
|
|
||||||
// getUserInfo(role).then(response => {
|
|
||||||
// const data = response.data
|
|
||||||
// commit('SET_ROLES', data.roles)
|
|
||||||
// commit('SET_NAME', data.name)
|
|
||||||
// commit('SET_ID', data.id)
|
|
||||||
// commit('SET_AVATAR', data.avatar)
|
|
||||||
// commit('SET_INTRODUCTION', data.introduction)
|
|
||||||
// dispatch('GenerateRoutes', data) // 动态修改权限后 重绘侧边菜单
|
|
||||||
// resolve()
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { fetchUsers, toggleUserActivation, searchUsers } from '@/api/users'
|
import { addRight, fetchUsers, deleteRight, deleteUser, searchUsers, tagUser, toggleUserActivation, untagUser } from '@/api/users'
|
||||||
|
|
||||||
const users = {
|
const users = {
|
||||||
state: {
|
state: {
|
||||||
|
@ -22,7 +22,7 @@ const users = {
|
||||||
})
|
})
|
||||||
|
|
||||||
state.fetchedUsers = [...usersWithoutSwapped, user].sort((a, b) =>
|
state.fetchedUsers = [...usersWithoutSwapped, user].sort((a, b) =>
|
||||||
a.id.localeCompare(b.id)
|
a.nickname.localeCompare(b.nickname)
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
SET_COUNT: (state, count) => {
|
SET_COUNT: (state, count) => {
|
||||||
|
@ -70,6 +70,30 @@ const users = {
|
||||||
async ToggleLocalUsersFilter({ commit, dispatch, state }, value) {
|
async ToggleLocalUsersFilter({ commit, dispatch, state }, value) {
|
||||||
commit('SET_LOCAL_USERS_FILTER', value)
|
commit('SET_LOCAL_USERS_FILTER', value)
|
||||||
dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
|
dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
|
||||||
|
},
|
||||||
|
async ToggleRight({ commit, getters }, { user, right }) {
|
||||||
|
user.roles[right]
|
||||||
|
? await deleteRight(user.nickname, right, getters.token)
|
||||||
|
: await addRight(user.nickname, right, getters.token)
|
||||||
|
|
||||||
|
const updatedUser = { ...user, roles: { ...user.roles, [right]: !user.roles[right] }}
|
||||||
|
commit('SWAP_USER', updatedUser)
|
||||||
|
},
|
||||||
|
async DeleteUser({ commit, getters }, user) {
|
||||||
|
await deleteUser(user.nickname, getters.token)
|
||||||
|
const updatedUser = { ...user, deactivated: true }
|
||||||
|
commit('SWAP_USER', updatedUser)
|
||||||
|
},
|
||||||
|
async ToggleTag({ commit, getters }, { user, tag }) {
|
||||||
|
if (user.tags.includes(tag)) {
|
||||||
|
await untagUser(user.nickname, tag, getters.token)
|
||||||
|
const updatedUser = { ...user, tags: user.tags.filter(userTag => userTag !== tag) }
|
||||||
|
commit('SWAP_USER', updatedUser)
|
||||||
|
} else {
|
||||||
|
await tagUser(user.nickname, tag, getters.token)
|
||||||
|
const updatedUser = { ...user, tags: [...user.tags, tag] }
|
||||||
|
commit('SWAP_USER', updatedUser)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,41 +10,8 @@ const service = axios.create({
|
||||||
// response interceptor
|
// response interceptor
|
||||||
service.interceptors.response.use(
|
service.interceptors.response.use(
|
||||||
response => response,
|
response => response,
|
||||||
/**
|
|
||||||
* 下面的注释为通过在response里,自定义code来标示请求状态
|
|
||||||
* 当code返回如下情况则说明权限有问题,登出并返回到登录页
|
|
||||||
* 如想通过 xmlhttprequest 来状态码标识 逻辑可写在下面error中
|
|
||||||
* 以下代码均为样例,请结合自生需求加以修改,若不需要,则可删除
|
|
||||||
*/
|
|
||||||
// response => {
|
|
||||||
// const res = response.data
|
|
||||||
// if (res.code !== 20000) {
|
|
||||||
// Message({
|
|
||||||
// message: res.message,
|
|
||||||
// type: 'error',
|
|
||||||
// duration: 5 * 1000
|
|
||||||
// })
|
|
||||||
// // 50008:非法的token; 50012:其他客户端登录了; 50014:Token 过期了;
|
|
||||||
// if (res.code === 50008 || res.code === 50012 || res.code === 50014) {
|
|
||||||
// // 请自行在引入 MessageBox
|
|
||||||
// // import { Message, MessageBox } from 'element-ui'
|
|
||||||
// MessageBox.confirm('你已被登出,可以取消继续留在该页面,或者重新登录', '确定登出', {
|
|
||||||
// confirmButtonText: '重新登录',
|
|
||||||
// cancelButtonText: '取消',
|
|
||||||
// type: 'warning'
|
|
||||||
// }).then(() => {
|
|
||||||
// store.dispatch('FedLogOut').then(() => {
|
|
||||||
// location.reload() // 为了重新实例化vue-router对象 避免bug
|
|
||||||
// })
|
|
||||||
// })
|
|
||||||
// }
|
|
||||||
// return Promise.reject('error')
|
|
||||||
// } else {
|
|
||||||
// return response.data
|
|
||||||
// }
|
|
||||||
// },
|
|
||||||
error => {
|
error => {
|
||||||
console.log('err' + error) // for debug
|
console.log('err' + error)
|
||||||
Message({
|
Message({
|
||||||
message: error.message,
|
message: error.message,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
|
|
|
@ -7,24 +7,74 @@
|
||||||
</div>
|
</div>
|
||||||
<el-table v-loading="loading" :data="users" style="width: 100%">
|
<el-table v-loading="loading" :data="users" style="width: 100%">
|
||||||
<el-table-column :min-width="width" prop="id" label="ID"/>
|
<el-table-column :min-width="width" prop="id" label="ID"/>
|
||||||
<el-table-column prop="nickname" label="Name"/>
|
<el-table-column prop="nickname" label="Name">
|
||||||
|
<template slot-scope="scope">
|
||||||
|
{{ scope.row.nickname }}
|
||||||
|
<el-tag v-if="isDesktop" type="info" size="mini">
|
||||||
|
<span>{{ scope.row.local ? 'local' : 'external' }}</span>
|
||||||
|
</el-tag>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
<el-table-column :min-width="width" label="Status">
|
<el-table-column :min-width="width" label="Status">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-tag :type="scope.row.deactivated ? 'danger' : 'success'">
|
<el-tag :type="scope.row.deactivated ? 'danger' : 'success'">
|
||||||
<span v-if="isDesktop">{{ scope.row.deactivated ? 'deactivated' : 'active' }}</span>
|
<span v-if="isDesktop">{{ scope.row.deactivated ? 'deactivated' : 'active' }}</span>
|
||||||
<i v-else :class="activationIcon(scope.row.deactivated)"/>
|
<i v-else :class="activationIcon(scope.row.deactivated)"/>
|
||||||
</el-tag>
|
</el-tag>
|
||||||
|
<el-tag v-if="scope.row.roles.admin">
|
||||||
|
<span>{{ isDesktop ? 'admin' : 'A' }}</span>
|
||||||
|
</el-tag>
|
||||||
|
<el-tag v-if="scope.row.roles.moderator">
|
||||||
|
<span>{{ isDesktop ? 'moderator' : 'M' }}</span>
|
||||||
|
</el-tag>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
<el-table-column fixed="right" label="Actions">
|
<el-table-column fixed="right" label="Actions">
|
||||||
<template slot-scope="scope">
|
<template slot-scope="scope">
|
||||||
<el-button
|
<el-dropdown size="small">
|
||||||
v-if="showDeactivatedButton(scope.row.id)"
|
<span class="el-dropdown-link">
|
||||||
class="toggle-activation"
|
Moderation
|
||||||
type="text"
|
<i v-if="isDesktop" class="el-icon-arrow-down el-icon--right"/>
|
||||||
size="small"
|
</span>
|
||||||
@click="handleDeactivate(scope.row)"
|
<el-dropdown-menu slot="dropdown">
|
||||||
>{{ scope.row.deactivated ? 'Activate' : 'Deactivate' }}</el-button>
|
<el-dropdown-item v-if="showAdminAction(scope.row)" @click.native="toggleUserRight(scope.row, 'admin')">
|
||||||
|
{{ scope.row.roles.admin ? 'Revoke Admin' : 'Grant Admin' }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item v-if="showAdminAction(scope.row)" @click.native="toggleUserRight(scope.row, 'moderator')">
|
||||||
|
{{ scope.row.roles.moderator ? 'Revoke Moderator' : 'Grant Moderator' }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item v-if="showDeactivatedButton(scope.row.id)" :divided="showAdminAction(scope.row)" @click.native="handleDeactivation(scope.row)">
|
||||||
|
{{ scope.row.deactivated ? 'Activate account' : 'Deactivate account' }}
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item v-if="showDeactivatedButton(scope.row.id)" @click.native="handleDeletion(scope.row)">
|
||||||
|
Delete Account
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item :divided="showAdminAction(scope.row)" @click.native="toggleTag(scope.row, 'force_nsfw')">
|
||||||
|
Force posts to be NSFW
|
||||||
|
<i v-if="scope.row.tags.includes('force_nsfw')" class="el-icon-circle-check"/>
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item @click.native="toggleTag(scope.row, 'strip_media')">
|
||||||
|
Force posts not to have media
|
||||||
|
<i v-if="scope.row.tags.includes('strip_media')" class="el-icon-circle-check"/>
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item @click.native="toggleTag(scope.row, 'force_unlisted')">
|
||||||
|
Force posts to be unlisted
|
||||||
|
<i v-if="scope.row.tags.includes('force_unlisted')" class="el-icon-circle-check"/>
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item @click.native="toggleTag(scope.row, 'sandbox')">
|
||||||
|
Force posts to be followers-only
|
||||||
|
<i v-if="scope.row.tags.includes('sandbox')" class="el-icon-circle-check"/>
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item v-if="scope.row.local" @click.native="toggleTag(scope.row, 'disable_remote_subscription')">
|
||||||
|
Disallow following user from remote instances
|
||||||
|
<i v-if="scope.row.tags.includes('disable_remote_subscription')" class="el-icon-circle-check"/>
|
||||||
|
</el-dropdown-item>
|
||||||
|
<el-dropdown-item v-if="scope.row.local" @click.native="toggleTag(scope.row, 'disable_any_subscription')">
|
||||||
|
Disallow following user at all
|
||||||
|
<i v-if="scope.row.tags.includes('disable_any_subscription')" class="el-icon-circle-check"/>
|
||||||
|
</el-dropdown-item>
|
||||||
|
</el-dropdown-menu>
|
||||||
|
</el-dropdown>
|
||||||
</template>
|
</template>
|
||||||
</el-table-column>
|
</el-table-column>
|
||||||
</el-table>
|
</el-table>
|
||||||
|
@ -72,12 +122,7 @@ export default {
|
||||||
return this.$store.state.app.device === 'mobile'
|
return this.$store.state.app.device === 'mobile'
|
||||||
},
|
},
|
||||||
width() {
|
width() {
|
||||||
return this.isMobile ? 60 : false
|
return this.isMobile ? 55 : false
|
||||||
},
|
|
||||||
rowStyle(id) {
|
|
||||||
return {
|
|
||||||
'data-user-id': id
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
@ -89,7 +134,7 @@ export default {
|
||||||
this.$store.dispatch('FetchUsers', { page: 1 })
|
this.$store.dispatch('FetchUsers', { page: 1 })
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
handleDeactivate({ nickname }) {
|
handleDeactivation({ nickname }) {
|
||||||
this.$store.dispatch('ToggleUserActivation', nickname)
|
this.$store.dispatch('ToggleUserActivation', nickname)
|
||||||
},
|
},
|
||||||
handlePageChange(page) {
|
handlePageChange(page) {
|
||||||
|
@ -103,11 +148,23 @@ export default {
|
||||||
showDeactivatedButton(id) {
|
showDeactivatedButton(id) {
|
||||||
return this.$store.state.user.id !== id
|
return this.$store.state.user.id !== id
|
||||||
},
|
},
|
||||||
|
showAdminAction({ local, id }) {
|
||||||
|
return local && this.showDeactivatedButton(id)
|
||||||
|
},
|
||||||
handleLocalUsersCheckbox(e) {
|
handleLocalUsersCheckbox(e) {
|
||||||
this.$store.dispatch('ToggleLocalUsersFilter', 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'
|
||||||
|
},
|
||||||
|
toggleUserRight(user, right) {
|
||||||
|
this.$store.dispatch('ToggleRight', { user, right })
|
||||||
|
},
|
||||||
|
handleDeletion(user) {
|
||||||
|
this.$store.dispatch('DeleteUser', user)
|
||||||
|
},
|
||||||
|
toggleTag(user, tag) {
|
||||||
|
this.$store.dispatch('ToggleTag', { user, tag })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -144,6 +201,13 @@ only screen and (max-width: 760px),
|
||||||
h1 {
|
h1 {
|
||||||
margin-left: 7px;
|
margin-left: 7px;
|
||||||
}
|
}
|
||||||
|
.el-dropdown-link {
|
||||||
|
cursor: pointer;
|
||||||
|
color: #409EFF;
|
||||||
|
}
|
||||||
|
.el-icon-arrow-down {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
.search {
|
.search {
|
||||||
width: 50%;
|
width: 50%;
|
||||||
margin-bottom: 21.5px;
|
margin-bottom: 21.5px;
|
||||||
|
@ -156,6 +220,18 @@ only screen and (max-width: 760px),
|
||||||
align-items: baseline;
|
align-items: baseline;
|
||||||
margin-left: 7px;
|
margin-left: 7px;
|
||||||
}
|
}
|
||||||
|
.el-tag {
|
||||||
|
width: 30px;
|
||||||
|
display: inline-block;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
font-weight: bold;
|
||||||
|
&.el-tag--success {
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
&.el-tag--danger {
|
||||||
|
padding-left: 8px;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
@ -11,7 +11,7 @@ localVue.use(Element)
|
||||||
|
|
||||||
jest.mock('@/api/users')
|
jest.mock('@/api/users')
|
||||||
|
|
||||||
describe('Users', () => {
|
describe('Search and filter users', () => {
|
||||||
let store
|
let store
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
|
@ -29,24 +29,6 @@ describe('Users', () => {
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('toggles activation status on button click', async (done) => {
|
|
||||||
const wrapper = mount(Users, {
|
|
||||||
store,
|
|
||||||
localVue
|
|
||||||
})
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
|
|
||||||
const user = store.state.users.fetchedUsers[1]
|
|
||||||
expect(user.deactivated).toBe(false)
|
|
||||||
|
|
||||||
wrapper.find('.el-table__fixed-body-wrapper table tr:nth-child(2) button').trigger('click')
|
|
||||||
await wrapper.vm.$nextTick()
|
|
||||||
|
|
||||||
const updatedUser = store.state.users.fetchedUsers[1]
|
|
||||||
expect(updatedUser.deactivated).toBe(true)
|
|
||||||
done()
|
|
||||||
})
|
|
||||||
|
|
||||||
it('starts a search on input change', async (done) => {
|
it('starts a search on input change', async (done) => {
|
||||||
const wrapper = mount(Users, {
|
const wrapper = mount(Users, {
|
||||||
store,
|
store,
|
||||||
|
@ -95,7 +77,7 @@ describe('Users', () => {
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
|
|
||||||
it('shows local users with query search', async (done) => {
|
it('shows local users with search query', async (done) => {
|
||||||
const wrapper = mount(Users, {
|
const wrapper = mount(Users, {
|
||||||
store,
|
store,
|
||||||
localVue
|
localVue
|
||||||
|
@ -134,3 +116,164 @@ describe('Users', () => {
|
||||||
done()
|
done()
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
|
describe('Users actions', () => {
|
||||||
|
let store
|
||||||
|
const htmlElement = (trChild, liChild) =>
|
||||||
|
`.el-table__fixed-body-wrapper table tr:nth-child(${trChild}) ul.el-dropdown-menu li:nth-child(${liChild})`
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
store = new Vuex.Store(cloneDeep(storeConfig))
|
||||||
|
})
|
||||||
|
|
||||||
|
it('grants admin and moderator rights to a local user', async (done) => {
|
||||||
|
const wrapper = mount(Users, {
|
||||||
|
store,
|
||||||
|
localVue
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const user = store.state.users.fetchedUsers[2]
|
||||||
|
expect(user.roles.admin).toBe(false)
|
||||||
|
expect(user.roles.moderator).toBe(false)
|
||||||
|
|
||||||
|
wrapper.find(htmlElement(3, 1)).trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
wrapper.find(htmlElement(3, 2)).trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const updatedUser = store.state.users.fetchedUsers[2]
|
||||||
|
expect(updatedUser.roles.admin).toBe(true)
|
||||||
|
expect(updatedUser.roles.moderator).toBe(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not show actions that grant admin and moderator rights to external users', async (done) => {
|
||||||
|
const wrapper = mount(Users, {
|
||||||
|
store,
|
||||||
|
localVue
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const dropdownMenuItem = wrapper.find(htmlElement(2, 1))
|
||||||
|
expect(dropdownMenuItem.text()).toBe('Deactivate account')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('toggles activation status', async (done) => {
|
||||||
|
const wrapper = mount(Users, {
|
||||||
|
store,
|
||||||
|
localVue
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const user = store.state.users.fetchedUsers[1]
|
||||||
|
expect(user.deactivated).toBe(false)
|
||||||
|
|
||||||
|
wrapper.find(htmlElement(2, 1)).trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const updatedUser = store.state.users.fetchedUsers[1]
|
||||||
|
expect(updatedUser.deactivated).toBe(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('deactivates user when Delete action is called', async (done) => {
|
||||||
|
const wrapper = mount(Users, {
|
||||||
|
store,
|
||||||
|
localVue
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const user = store.state.users.fetchedUsers[1]
|
||||||
|
expect(user.deactivated).toBe(false)
|
||||||
|
|
||||||
|
wrapper.find(htmlElement(2, 2)).trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const updatedUser = store.state.users.fetchedUsers[1]
|
||||||
|
expect(updatedUser.deactivated).toBe(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('adds tags', async (done) => {
|
||||||
|
const wrapper = mount(Users, {
|
||||||
|
store,
|
||||||
|
localVue
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const user1 = store.state.users.fetchedUsers[0]
|
||||||
|
const user2 = store.state.users.fetchedUsers[1]
|
||||||
|
expect(user1.tags.length).toBe(0)
|
||||||
|
expect(user2.tags.length).toBe(1)
|
||||||
|
|
||||||
|
wrapper.find(htmlElement(1, 5)).trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
wrapper.find(htmlElement(2, 5)).trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const updatedUser1 = store.state.users.fetchedUsers[0]
|
||||||
|
const updatedUser2 = store.state.users.fetchedUsers[1]
|
||||||
|
expect(updatedUser1.tags.length).toBe(1)
|
||||||
|
expect(updatedUser2.tags.length).toBe(2)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('deletes tags', async (done) => {
|
||||||
|
const wrapper = mount(Users, {
|
||||||
|
store,
|
||||||
|
localVue
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const user = store.state.users.fetchedUsers[1]
|
||||||
|
expect(user.tags.length).toBe(1)
|
||||||
|
|
||||||
|
wrapper.find(htmlElement(2, 6)).trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const updatedUser = store.state.users.fetchedUsers[1]
|
||||||
|
expect(updatedUser.tags.length).toBe(0)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('shows check icon when tag is added', async (done) => {
|
||||||
|
const wrapper = mount(Users, {
|
||||||
|
store,
|
||||||
|
localVue
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
expect(wrapper.find(`${htmlElement(1, 5)} i`).exists()).toBe(false)
|
||||||
|
|
||||||
|
wrapper.find(htmlElement(1, 5)).trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
expect(wrapper.find(`${htmlElement(1, 5)} i`).exists()).toBe(true)
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
|
||||||
|
it('does not change user index in array when tag is added', async (done) => {
|
||||||
|
const wrapper = mount(Users, {
|
||||||
|
store,
|
||||||
|
localVue
|
||||||
|
})
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const firstUserNickname = store.state.users.fetchedUsers[0].nickname
|
||||||
|
const secondUserNickname = store.state.users.fetchedUsers[1].nickname
|
||||||
|
expect(firstUserNickname).toBe('allis')
|
||||||
|
expect(secondUserNickname).toBe('bob')
|
||||||
|
|
||||||
|
wrapper.find(htmlElement(2, 5)).trigger('click')
|
||||||
|
await wrapper.vm.$nextTick()
|
||||||
|
|
||||||
|
const firstUserNicknameAfterToggle = store.state.users.fetchedUsers[0].nickname
|
||||||
|
const secondUserNicknameAfterToggle = store.state.users.fetchedUsers[1].nickname
|
||||||
|
|
||||||
|
expect(firstUserNicknameAfterToggle).toEqual('allis')
|
||||||
|
expect(secondUserNicknameAfterToggle).toEqual('bob')
|
||||||
|
done()
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
Loading…
Reference in a new issue