Merge branch 'feature/improve-user-profile-interface' into 'master'
Update user profile interface See merge request pleroma/admin-fe!53
This commit is contained in:
commit
01ccb43965
7 changed files with 196 additions and 110 deletions
|
@ -4,6 +4,10 @@ export let users = [
|
|||
{ active: false, deactivated: true, id: 'abc', nickname: 'john', local: true, external: false, roles: { admin: false, moderator: false }, tags: ['strip_media'] }
|
||||
]
|
||||
|
||||
const userProfile = { avatar: 'avatar.jpg', display_name: 'Allis', nickname: 'allis', id: '2', tags: [], roles: { admin: true, moderator: false }, local: true, external: false }
|
||||
|
||||
const userStatuses = []
|
||||
|
||||
const filterUsers = (str) => {
|
||||
const filters = str.split(',').filter(item => item.length > 0)
|
||||
if (filters.length === 0) {
|
||||
|
@ -20,6 +24,10 @@ const filterUsers = (str) => {
|
|||
return applyFilters([], filters, users)
|
||||
}
|
||||
|
||||
export async function fetchUser(id, authHost, token) {
|
||||
return Promise.resolve({ data: userProfile })
|
||||
}
|
||||
|
||||
export async function fetchUsers(filters, authHost, token, page = 1) {
|
||||
const filteredUsers = filterUsers(filters)
|
||||
return Promise.resolve({ data: {
|
||||
|
@ -29,6 +37,10 @@ export async function fetchUsers(filters, authHost, token, page = 1) {
|
|||
}})
|
||||
}
|
||||
|
||||
export async function fetchUserStatuses(id, authHost, godmode, token) {
|
||||
return Promise.resolve({ data: userStatuses })
|
||||
}
|
||||
|
||||
export async function getPasswordResetToken(nickname, authHost, token) {
|
||||
return Promise.resolve({ data: { token: 'g05lxnBJQnL', link: 'http://url/api/pleroma/password_reset/g05lxnBJQnL' }})
|
||||
}
|
||||
|
|
|
@ -236,11 +236,17 @@ export default {
|
|||
tags: 'Tags',
|
||||
moderator: 'Moderator',
|
||||
admin: 'Admin',
|
||||
local: 'Local',
|
||||
local: 'local',
|
||||
external: 'external',
|
||||
localUppercase: 'Local',
|
||||
nickname: 'Nickname',
|
||||
deactivated: 'Deactivated',
|
||||
recentStatuses: 'Recent Statues',
|
||||
showPrivateStatuses: 'Show private statuses'
|
||||
showPrivateStatuses: 'Show private statuses',
|
||||
roles: 'Roles',
|
||||
activeUppercase: 'Active',
|
||||
active: 'active',
|
||||
deactivated: 'deactivated',
|
||||
noStatuses: 'No statuses to show'
|
||||
},
|
||||
usersFilter: {
|
||||
inputPlaceholder: 'Select filter',
|
||||
|
|
|
@ -185,54 +185,56 @@ export default {
|
|||
</script>
|
||||
|
||||
<style rel='stylesheet/scss' lang='scss'>
|
||||
.account {
|
||||
text-decoration: underline;
|
||||
line-height: 26px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.image {
|
||||
width: 20%;
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.show-more-button {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.status-account {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.status-avatar-img {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.status-account-name {
|
||||
margin: 0;
|
||||
height: 22px;
|
||||
}
|
||||
.status-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.status-content {
|
||||
font-size: 15px;
|
||||
line-height: 26px;
|
||||
}
|
||||
.status-card {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.status-deleted {
|
||||
font-style: italic;
|
||||
margin-top: 3px;
|
||||
}
|
||||
.status-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.status-without-content {
|
||||
font-style: italic;
|
||||
.account {
|
||||
text-decoration: underline;
|
||||
line-height: 26px;
|
||||
font-size: 13px;
|
||||
}
|
||||
.image {
|
||||
width: 20%;
|
||||
img {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.show-more-button {
|
||||
margin-left: 5px;
|
||||
}
|
||||
.status-account {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.status-avatar-img {
|
||||
width: 15px;
|
||||
height: 15px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.status-account-name {
|
||||
margin: 0;
|
||||
height: 22px;
|
||||
}
|
||||
.status-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.status-content {
|
||||
font-size: 15px;
|
||||
line-height: 26px;
|
||||
}
|
||||
.status-card {
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
.status-deleted {
|
||||
font-style: italic;
|
||||
margin-top: 3px;
|
||||
}
|
||||
.status-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
.status-without-content {
|
||||
font-style: italic;
|
||||
}
|
||||
}
|
||||
@media
|
||||
only screen and (max-width: 760px),
|
||||
|
|
|
@ -156,9 +156,6 @@
|
|||
</p>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<div v-if="users.length === 0" class="no-users-message">
|
||||
<p>There are no users to display</p>
|
||||
</div>
|
||||
<div v-if="!loading" class="pagination">
|
||||
<el-pagination
|
||||
:total="usersCount"
|
||||
|
|
|
@ -5,60 +5,60 @@
|
|||
<h1>{{ user.display_name }}</h1>
|
||||
</header>
|
||||
<el-row>
|
||||
<el-col :span="6">
|
||||
<div class="el-table el-table--fit el-table--enable-row-hover el-table--enable-row-transition el-table--medium">
|
||||
<table class="el-table__body">
|
||||
<tbody>
|
||||
<tr class="el-table__row">
|
||||
<td class="name-col">ID</td>
|
||||
<td class="value-col">
|
||||
{{ user.id }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.tags') }}</td>
|
||||
<td>
|
||||
<el-tag v-for="tag in user.tags" :key="tag">{{ tag }}</el-tag>
|
||||
<span v-if="user.tags.length === 0">None</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.moderator') }}</td>
|
||||
<td>
|
||||
<el-tag v-if="user.roles.moderator" type="success"><i class="el-icon-check" /></el-tag>
|
||||
<el-tag v-if="!user.roles.moderator" type="danger"><i class="el-icon-error" /></el-tag>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.admin') }}</td>
|
||||
<td>
|
||||
<el-tag v-if="user.roles.admin" type="success"><i class="el-icon-check" /></el-tag>
|
||||
<el-tag v-if="!user.roles.admin" type="danger"><i class="el-icon-error" /></el-tag>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.local') }}</td>
|
||||
<td>
|
||||
<el-tag v-if="user.local" type="success"><i class="el-icon-check" /></el-tag>
|
||||
<el-tag v-if="!user.local" type="danger"><i class="el-icon-error" /></el-tag>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.deactivated') }}</td>
|
||||
<td>
|
||||
<el-tag v-if="user.deactivated" type="success"><i class="el-icon-check" /></el-tag>
|
||||
<el-tag v-if="!user.deactivated" type="danger"><i class="el-icon-error" /></el-tag>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.nickname') }}</td>
|
||||
<td>
|
||||
{{ user.nickname }}
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<el-col :span="8">
|
||||
<el-card class="user-profile-card">
|
||||
<div class="el-table el-table--fit el-table--enable-row-hover el-table--enable-row-transition el-table--medium">
|
||||
<table class="user-profile-table">
|
||||
<tbody>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.nickname') }}</td>
|
||||
<td>
|
||||
{{ user.nickname }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td class="name-col">ID</td>
|
||||
<td class="value-col">
|
||||
{{ user.id }}
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.tags') }}</td>
|
||||
<td>
|
||||
<el-tag v-for="tag in user.tags" :key="tag" class="user-profile-tag">{{ tag }}</el-tag>
|
||||
<span v-if="user.tags.length === 0">—</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.roles') }}</td>
|
||||
<td>
|
||||
<el-tag v-if="user.roles.admin" class="user-profile-tag">
|
||||
{{ $t('users.admin') }}
|
||||
</el-tag>
|
||||
<el-tag v-if="user.roles.moderator" class="user-profile-tag">
|
||||
{{ $t('users.moderator') }}
|
||||
</el-tag>
|
||||
<span v-if="!user.roles.moderator && !user.roles.admin">—</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.localUppercase') }}</td>
|
||||
<td>
|
||||
<el-tag v-if="user.local" type="info">{{ $t('userProfile.local') }}</el-tag>
|
||||
<el-tag v-if="!user.local" type="info">{{ $t('userProfile.external') }}</el-tag>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="el-table__row">
|
||||
<td>{{ $t('userProfile.activeUppercase') }}</td>
|
||||
<td>
|
||||
<el-tag v-if="user.deactivated" type="success">{{ $t('userProfile.active') }}</el-tag>
|
||||
<el-tag v-if="!user.deactivated" type="danger">{{ $t('userProfile.deactivated') }}</el-tag>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</el-card>
|
||||
</el-col>
|
||||
<el-row type="flex" class="row-bg" justify="space-between">
|
||||
<el-col :span="18">
|
||||
|
@ -70,11 +70,12 @@
|
|||
</el-checkbox>
|
||||
</el-col>
|
||||
</el-row>
|
||||
<el-col :span="18">
|
||||
<el-col :span="16">
|
||||
<el-timeline v-if="!statusesLoading" class="statuses">
|
||||
<el-timeline-item v-for="status in statuses" :key="status.id">
|
||||
<status :status="status" :user-id="user.id" :godmode="showPrivate"/>
|
||||
</el-timeline-item>
|
||||
<p v-if="statuses.length === 0" class="no-statuses">{{ $t('userProfile.noStatuses') }}</p>
|
||||
</el-timeline>
|
||||
</el-col>
|
||||
</el-row>
|
||||
|
@ -147,8 +148,16 @@ table {
|
|||
width: 100%;
|
||||
}
|
||||
}
|
||||
.no-statuses {
|
||||
margin-left: 28px;
|
||||
color: #606266;
|
||||
|
||||
}
|
||||
.recent-statuses-header {
|
||||
margin-top: 10px;
|
||||
}
|
||||
.statuses {
|
||||
padding-right: 20px;
|
||||
padding: 0 20px 0 0;
|
||||
}
|
||||
.show-private {
|
||||
text-align: right;
|
||||
|
@ -156,6 +165,16 @@ table {
|
|||
padding-right: 20px;
|
||||
}
|
||||
.recent-statuses {
|
||||
margin-left: 40px;
|
||||
margin-left: 28px;
|
||||
}
|
||||
.user-profile-card {
|
||||
margin-left: 15px;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.user-profile-table {
|
||||
margin: 0;
|
||||
}
|
||||
.user-profile-tag {
|
||||
margin: 0 4px 4px 0;
|
||||
}
|
||||
</style>
|
||||
|
|
48
test/views/users/show.test.js
Normal file
48
test/views/users/show.test.js
Normal file
|
@ -0,0 +1,48 @@
|
|||
import Vuex from 'vuex'
|
||||
import { mount, createLocalVue, config } from '@vue/test-utils'
|
||||
import flushPromises from 'flush-promises'
|
||||
import Element from 'element-ui'
|
||||
import UsersShow from '@/views/users/show'
|
||||
import storeConfig from './store.conf'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
config.mocks["$t"] = () => {}
|
||||
|
||||
const localVue = createLocalVue()
|
||||
localVue.use(Vuex)
|
||||
localVue.use(Element)
|
||||
|
||||
const $route = {
|
||||
params: {
|
||||
id: '2'
|
||||
}
|
||||
}
|
||||
|
||||
jest.mock('@/api/nodeInfo')
|
||||
jest.mock('@/api/users')
|
||||
|
||||
describe('Search and filter users', () => {
|
||||
let store
|
||||
|
||||
beforeEach(() => {
|
||||
store = new Vuex.Store(cloneDeep(storeConfig))
|
||||
})
|
||||
|
||||
it('fetches user profile', async (done) => {
|
||||
const wrapper = mount(UsersShow, {
|
||||
store,
|
||||
localVue,
|
||||
sync: false,
|
||||
stubs: ['router-link'],
|
||||
mocks: {
|
||||
$route
|
||||
}
|
||||
})
|
||||
|
||||
await flushPromises()
|
||||
expect(wrapper.find('.user-profile-card').isVisible()).toBe(true)
|
||||
expect(store.state.userProfile.user.nickname).toBe('allis')
|
||||
expect(store.state.userProfile.user.roles.admin).toBe(true)
|
||||
done()
|
||||
})
|
||||
})
|
|
@ -1,5 +1,6 @@
|
|||
import app from '@/store/modules/app'
|
||||
import user from '@/store/modules/user'
|
||||
import userProfile from '@/store/modules/userProfile'
|
||||
import users from '@/store/modules/users'
|
||||
import getters from '@/store/getters'
|
||||
|
||||
|
@ -7,6 +8,7 @@ export default {
|
|||
modules: {
|
||||
app,
|
||||
user,
|
||||
userProfile,
|
||||
users
|
||||
},
|
||||
getters
|
||||
|
|
Loading…
Reference in a new issue