Merge branch 'fix/update-pending-status' into 'develop'

Update usage of `need_approval` status

See merge request pleroma/admin-fe!154
This commit is contained in:
Angelina Filippova 2020-08-11 23:04:26 +00:00
commit 51da64c138
6 changed files with 100 additions and 84 deletions

View file

@ -229,13 +229,14 @@ export default {
revokeRightConfirmation: 'Are you sure you want to revoke {right} rights from all selected users?', revokeRightConfirmation: 'Are you sure you want to revoke {right} rights from all selected users?',
activateMultipleUsersConfirmation: 'Are you sure you want to activate accounts of all selected users?', activateMultipleUsersConfirmation: 'Are you sure you want to activate accounts of all selected users?',
deactivateMultipleUsersConfirmation: 'Are you sure you want to deactivate accounts of all selected users?', deactivateMultipleUsersConfirmation: 'Are you sure you want to deactivate accounts of all selected users?',
deleteUsersConfirmation: 'Are you sure you want to delete this account? This action cannot be undone.', deleteUserConfirmation: 'Are you sure you want to delete this account? This action cannot be undone.',
deleteMultipleUsersConfirmation: 'Are you sure you want to delete accounts of all selected users?', rejectAccountConfirmation: 'Are you sure you want to reject this account? This account will be deleted and it cannot be undone.',
deleteMultipleUsersConfirmation: 'Are you sure you want to delete accounts of all selected users? This action cannot be undone.',
addTagForMultipleUsersConfirmation: 'Are you sure you want to apply tag to all selected users?', addTagForMultipleUsersConfirmation: 'Are you sure you want to apply tag to all selected users?',
removeTagFromMultipleUsersConfirmation: 'Are you sure you want to remove tag from all selected users?', removeTagFromMultipleUsersConfirmation: 'Are you sure you want to remove tag from all selected users?',
requirePasswordResetConfirmation: 'Are you sure you want to require password reset for all selected users?', requirePasswordResetConfirmation: 'Are you sure you want to require password reset for all selected users?',
approveAccountsConfirmation: 'Are you sure you want to approve accounts for all selected users?', approveAccountsConfirmation: 'Are you sure you want to approve accounts for all selected users?',
rejectAccountsConfirmation: 'Are you sure you want to reject accounts for all selected users?', rejectAccountsConfirmation: 'Are you sure you want to reject accounts for all selected users? These accounts will be deleted and it cannot be undone.',
confirmAccountsConfirmation: 'Are you sure you want to confirm emails for all selected users?', confirmAccountsConfirmation: 'Are you sure you want to confirm emails for all selected users?',
resendEmailConfirmation: 'Are you sure you want to resend confirmation email for all selected users?', resendEmailConfirmation: 'Are you sure you want to resend confirmation email for all selected users?',
mailerMustBeEnabled: 'To require user\'s password reset you must enable mailer.', mailerMustBeEnabled: 'To require user\'s password reset you must enable mailer.',
@ -268,7 +269,8 @@ export default {
invalidAccount: 'This account has invalid nickname and can\'t be modified', invalidAccount: 'This account has invalid nickname and can\'t be modified',
invalidNickname: 'invalid nickname', invalidNickname: 'invalid nickname',
passwordResetTokenGenerated: 'Password reset token was generated:', passwordResetTokenGenerated: 'Password reset token was generated:',
linkToResetPassword: 'You can also use this link to reset password:' linkToResetPassword: 'You can also use this link to reset password:',
registrationReason: 'Registration Reason'
}, },
statuses: { statuses: {
statuses: 'Statuses', statuses: 'Statuses',
@ -323,7 +325,7 @@ export default {
external: 'External', external: 'External',
byStatus: 'By status', byStatus: 'By status',
active: 'Active', active: 'Active',
pending: 'Pending', pending: 'Pending Approval',
deactivated: 'Deactivated' deactivated: 'Deactivated'
}, },
reports: { reports: {

View file

@ -31,7 +31,7 @@ const users = {
local: false, local: false,
external: false, external: false,
active: false, active: false,
needApproval: false, need_approval: false,
deactivated: false deactivated: false
}, },
passwordResetToken: { passwordResetToken: {
@ -126,14 +126,32 @@ const users = {
dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: _userId, statusId: _statusId }) dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: _userId, statusId: _statusId })
}, },
async ApproveUsersAccount({ dispatch, getters }, { users, _userId, _statusId }) {
const updatedUsers = users.map(user => {
return { ...user, approval_pending: false }
})
const nicknames = users.map(user => user.nickname)
const callApiFn = async() => await approveUserAccount(nicknames, getters.authHost, getters.token)
dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: _userId, statusId: _statusId })
},
ClearUsersState({ commit }) { ClearUsersState({ commit }) {
commit('SET_SEARCH_QUERY', '') commit('SET_SEARCH_QUERY', '')
commit('SET_USERS_FILTERS', { local: false, external: false, active: false, needApproval: false, deactivated: false }) commit('SET_USERS_FILTERS', { local: false, external: false, active: false, need_approval: false, deactivated: false })
}, },
async ClearFilters({ commit, dispatch, state }) { async ClearFilters({ commit, dispatch, state }) {
commit('CLEAR_USERS_FILTERS') commit('CLEAR_USERS_FILTERS')
dispatch('SearchUsers', { query: state.searchQuery, page: 1 }) dispatch('SearchUsers', { query: state.searchQuery, page: 1 })
}, },
async ConfirmUsersEmail({ dispatch, getters }, { users, _userId, _statusId }) {
const updatedUsers = users.map(user => {
return { ...user, confirmation_pending: false }
})
const nicknames = users.map(user => user.nickname)
const callApiFn = async() => await confirmUserEmail(nicknames, getters.authHost, getters.token)
dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: _userId, statusId: _statusId })
},
async CreateNewAccount({ dispatch, getters, state }, { nickname, email, password }) { async CreateNewAccount({ dispatch, getters, state }, { nickname, email, password }) {
try { try {
await createNewAccount(nickname, email, password, getters.authHost, getters.token) await createNewAccount(nickname, email, password, getters.authHost, getters.token)
@ -161,33 +179,6 @@ const users = {
} }
dispatch('SuccessMessage') dispatch('SuccessMessage')
}, },
async ApproveUsersAccount({ dispatch, getters }, { users, _userId, _statusId }) {
const updatedUsers = users.map(user => {
return { ...user, approval_pending: false }
})
const nicknames = users.map(user => user.nickname)
const callApiFn = async() => await approveUserAccount(nicknames, getters.authHost, getters.token)
dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: _userId, statusId: _statusId })
},
async ConfirmUsersEmail({ dispatch, getters }, { users, _userId, _statusId }) {
const updatedUsers = users.map(user => {
return { ...user, confirmation_pending: false }
})
const nicknames = users.map(user => user.nickname)
const callApiFn = async() => await confirmUserEmail(nicknames, getters.authHost, getters.token)
dispatch('ApplyChanges', { updatedUsers, callApiFn, userId: _userId, statusId: _statusId })
},
async ResendConfirmationEmail({ dispatch, getters }, users) {
const usersNicknames = users.map(user => user.nickname)
try {
await resendConfirmationEmail(usersNicknames, getters.authHost, getters.token)
} catch (_e) {
return
}
dispatch('SuccessMessage')
},
async DeleteRight({ dispatch, getters }, { users, right, _userId, _statusId }) { async DeleteRight({ dispatch, getters }, { users, right, _userId, _statusId }) {
const updatedUsers = users.map(user => { const updatedUsers = users.map(user => {
return user.local ? { ...user, roles: { ...user.roles, [right]: false }} : user return user.local ? { ...user, roles: { ...user.roles, [right]: false }} : user
@ -246,6 +237,15 @@ const users = {
} }
dispatch('SuccessMessage') dispatch('SuccessMessage')
}, },
async ResendConfirmationEmail({ dispatch, getters }, users) {
const usersNicknames = users.map(user => user.nickname)
try {
await resendConfirmationEmail(usersNicknames, getters.authHost, getters.token)
} catch (_e) {
return
}
dispatch('SuccessMessage')
},
async SearchUsers({ commit, dispatch, state, getters }, { query, page }) { async SearchUsers({ commit, dispatch, state, getters }, { query, page }) {
if (query.length === 0) { if (query.length === 0) {
commit('SET_SEARCH_QUERY', query) commit('SET_SEARCH_QUERY', query)
@ -271,7 +271,7 @@ const users = {
local: false, local: false,
external: false, external: false,
active: false, active: false,
needApproval: false, need_approval: false,
deactivated: false deactivated: false
} }
const currentFilters = { ...defaultFilters, ...filters } const currentFilters = { ...defaultFilters, ...filters }

View file

@ -155,7 +155,7 @@ export default {
}, },
handleDeletion(user) { handleDeletion(user) {
this.$confirm( this.$confirm(
this.$t('users.deleteUsersConfirmation'), this.$t('users.deleteUserConfirmation'),
{ {
confirmButtonText: 'Delete', confirmButtonText: 'Delete',
cancelButtonText: 'Cancel', cancelButtonText: 'Cancel',
@ -174,9 +174,9 @@ export default {
}, },
handleAccountRejection(user) { handleAccountRejection(user) {
this.$confirm( this.$confirm(
this.$t('users.deleteUsersConfirmation'), this.$t('users.rejectAccountConfirmation'),
{ {
confirmButtonText: 'Delete', confirmButtonText: 'Reject',
cancelButtonText: 'Cancel', cancelButtonText: 'Cancel',
type: 'warning' type: 'warning'
}).then(() => { }).then(() => {
@ -184,7 +184,7 @@ export default {
}).catch(() => { }).catch(() => {
this.$message({ this.$message({
type: 'info', type: 'info',
message: 'Delete canceled' message: 'Reject canceled'
}) })
}) })
}, },

View file

@ -325,7 +325,7 @@ export default {
rejectAccountsForMultipleUsers() { rejectAccountsForMultipleUsers() {
const { remove } = this.mappers() const { remove } = this.mappers()
this.confirmMessage( this.confirmMessage(
this.$t('users.deleteMultipleUsersConfirmation'), this.$t('users.rejectAccountsConfirmation'),
remove remove
) )
}, },

View file

@ -12,7 +12,7 @@
</el-option-group> </el-option-group>
<el-option-group :label="$t('usersFilter.byStatus')"> <el-option-group :label="$t('usersFilter.byStatus')">
<el-option value="active" label="Active">{{ $t('usersFilter.active') }}</el-option> <el-option value="active" label="Active">{{ $t('usersFilter.active') }}</el-option>
<el-option value="needApproval" label="Need Approval">{{ $t('usersFilter.pending') }}</el-option> <el-option value="need_approval" label="Need Approval">{{ $t('usersFilter.pending') }}</el-option>
<el-option value="deactivated" label="Deactivated">{{ $t('usersFilter.deactivated') }}</el-option> <el-option value="deactivated" label="Deactivated">{{ $t('usersFilter.deactivated') }}</el-option>
</el-option-group> </el-option-group>
</el-select> </el-select>
@ -37,20 +37,25 @@ export default {
methods: { methods: {
removeOppositeFilters() { removeOppositeFilters() {
const filtersQuantity = Object.keys(this.$store.state.users.filters).length const filtersQuantity = Object.keys(this.$store.state.users.filters).length
const currentFilters = this.$data.value.slice() const currentFilters = []
const indexOfLocal = currentFilters.indexOf('local') const indexOfLocal = this.$data.value.indexOf('local')
const indexOfExternal = currentFilters.indexOf('external') const indexOfExternal = this.$data.value.indexOf('external')
const indexOfActive = currentFilters.indexOf('active') const indexOfActive = this.$data.value.indexOf('active')
const indexOfDeactivated = currentFilters.indexOf('deactivated') const indexOfDeactivated = this.$data.value.indexOf('deactivated')
if (currentFilters.length === filtersQuantity) { const indexOfPending = this.$data.value.indexOf('need_approval')
if (this.$data.value.length === filtersQuantity) {
return [] 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)
} }
Math.max(indexOfLocal, indexOfExternal) > -1
? currentFilters.push(this.$data.value[Math.max(indexOfLocal, indexOfExternal)])
: currentFilters
Math.max(indexOfActive, indexOfDeactivated, indexOfPending) > -1
? currentFilters.push(this.$data.value[Math.max(indexOfActive, indexOfDeactivated, indexOfPending)])
: currentFilters
return currentFilters return currentFilters
}, },
toggleFilters() { toggleFilters() {

View file

@ -56,10 +56,20 @@
</el-table-column> </el-table-column>
<el-table-column :min-width="width" :label="$t('users.status')"> <el-table-column :min-width="width" :label="$t('users.status')">
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag :type="scope.row.deactivated ? 'danger' : 'success'"> <el-tag v-if="!scope.row.deactivated & !scope.row.approval_pending" type="success">
<span v-if="isDesktop">{{ scope.row.deactivated ? $t('users.deactivated') : $t('users.active') }}</span> <span v-if="isDesktop">{{ $t('users.active') }}</span>
<i v-else :class="activationIcon(scope.row.deactivated)"/> <i v-else class="el-icon-circle-check"/>
</el-tag> </el-tag>
<el-tag v-if="scope.row.deactivated & !scope.row.approval_pending" type="danger">
<span v-if="isDesktop">{{ $t('users.deactivated') }}</span>
<i v-else class="el-icon-circle-close"/>
</el-tag>
<el-tooltip :content="$t('users.unapprovedAccount')" effect="dark">
<el-tag v-if="scope.row.approval_pending" type="info">
<span v-if="isDesktop">{{ $t('users.unapproved') }}</span>
<i v-else class="el-icon-warning-outline"/>
</el-tag>
</el-tooltip>
<el-tag v-if="scope.row.roles.admin"> <el-tag v-if="scope.row.roles.admin">
<span>{{ isDesktop ? $t('users.admin') : getFirstLetter($t('users.admin')) }}</span> <span>{{ isDesktop ? $t('users.admin') : getFirstLetter($t('users.admin')) }}</span>
</el-tag> </el-tag>
@ -71,16 +81,20 @@
{{ isDesktop ? $t('users.unconfirmed') : getFirstLetter($t('users.unconfirmed')) }} {{ isDesktop ? $t('users.unconfirmed') : getFirstLetter($t('users.unconfirmed')) }}
</el-tag> </el-tag>
</el-tooltip> </el-tooltip>
<el-tooltip :content="$t('users.unapprovedAccount')" effect="dark">
<el-tag v-if="scope.row.approval_pending" type="info">
{{ isDesktop ? $t('users.unapproved') : getFirstLetter($t('users.unapproved')) }}
</el-tag>
</el-tooltip>
<div v-if="pendingView && isDesktop" class="reason-text">
"{{ scope.row.registration_reason | truncate(100, '...') }}"
</div>
</template> </template>
</el-table-column>
<el-table-column v-if="pendingView && isDesktop" :label="$t('users.registrationReason')">
<template slot-scope="scope">
<el-tooltip
v-if="regReason(scope.row.registration_reason)"
:content="scope.row.registration_reason"
popper-class="reason-tooltip"
effect="dark">
<span>
"{{ scope.row.registration_reason | truncate(100, '...') }}"
</span>
</el-tooltip>
</template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('users.actions')" fixed="right"> <el-table-column :label="$t('users.actions')" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
@ -134,11 +148,7 @@ export default {
}, },
filters: { filters: {
truncate: function(text, length, suffix) { truncate: function(text, length, suffix) {
if (text.length > length) { return text.length < length ? text : text.substring(0, length) + suffix
return text.substring(0, length) + suffix
} else {
return text
}
} }
}, },
data() { data() {
@ -175,7 +185,7 @@ export default {
return this.$store.state.users.totalUsersCount return this.$store.state.users.totalUsersCount
}, },
pendingView() { pendingView() {
return this.$store.state.users.filters['needApproval'] return this.$store.state.users.filters['need_approval']
}, },
width() { width() {
return this.isMobile ? 55 : false return this.isMobile ? 55 : false
@ -194,9 +204,6 @@ export default {
this.$store.dispatch('ClearUsersState') this.$store.dispatch('ClearUsersState')
}, },
methods: { methods: {
activationIcon(status) {
return status ? 'el-icon-error' : 'el-icon-success'
},
clearSelection() { clearSelection() {
this.$refs.usersTable.clearSelection() this.$refs.usersTable.clearSelection()
}, },
@ -233,6 +240,9 @@ export default {
propertyExists(account, property) { propertyExists(account, property) {
return account[property] return account[property]
}, },
regReason(reason) {
return reason && reason.length > 0
},
showDeactivatedButton(id) { showDeactivatedButton(id) {
return this.$store.state.user.id !== id return this.$store.state.user.id !== id
} }
@ -278,6 +288,9 @@ export default {
.password-reset-token-dialog { .password-reset-token-dialog {
width: 50% width: 50%
} }
.reason-tooltip {
max-width: 450px;
}
.reset-password-link { .reset-password-link {
text-decoration: underline; text-decoration: underline;
} }
@ -291,6 +304,9 @@ export default {
margin: 10px 0 0 15px; margin: 10px 0 0 15px;
height: 40px; height: 40px;
} }
.cell {
word-break: break-word;
}
.el-table__row:hover { .el-table__row:hover {
cursor: pointer; cursor: pointer;
} }
@ -319,9 +335,6 @@ export default {
color: gray; color: gray;
font-size: 28px; font-size: 28px;
} }
.reason-text {
word-break: normal;
}
} }
@media only screen and (max-width:480px) { @media only screen and (max-width:480px) {
@ -355,16 +368,12 @@ export default {
} }
.el-table__row { .el-table__row {
.el-tag { .el-tag {
display: flex;
align-items: center;
justify-content: center;
width: 30px; width: 30px;
display: inline-block;
margin-bottom: 4px; margin-bottom: 4px;
font-weight: bold; font-weight: bold;
&.el-tag--success {
padding-left: 8px;
}
&.el-tag--danger {
padding-left: 8px;
}
} }
} }
.reboot-button { .reboot-button {