Revert "Merge branch 'feature/edit-tags-manually' into 'develop'"

This reverts commit fd9f0542ce17e26fa7459ad816b7b20c003786ef, reversing
changes made to acfe0dd6a3e600eaf0bb2000ccca6202542c9144.
This commit is contained in:
Angelina Filippova 2020-11-13 02:11:52 +03:00
parent 0fda46954e
commit f5b4845aa2
11 changed files with 290 additions and 348 deletions

View file

@ -20,7 +20,6 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
- Hide Tag actions on Users tab if MRF TagPolicy is disabled. Add ability to enable TagPolicy from Moderation menu
- Move `:restrict_unauthenticated` settings from Authentication tab to Instance tab
- Replace regular inputs with textareas for setting welcome messages in the Settings section
- Move tag moderation from Moderation menu to separate column in the Users table, add ability to add custom tags
### Fixed

View file

@ -121,10 +121,6 @@ export async function deleteUsers(nicknames, authHost, token) {
})
}
export async function listAllTags(authHost, token) {
return Promise.resolve({ data: ['verify', 'mrf_tag:media-force-nsfw'] })
}
export async function tagUser(nickname, tag, authHost, token) {
return Promise.resolve()
}

View file

@ -22,35 +22,6 @@ export async function addRight(nicknames, right, authHost, token) {
})
}
export async function fetchUserChats(id, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${id}/chats`,
method: 'get',
headers: authHeaders(token)
})
}
export async function approveUserAccount(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/users/approve',
method: 'patch',
headers: authHeaders(token),
data: { nicknames }
})
}
export async function confirmUserEmail(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/users/confirm_email',
method: 'patch',
headers: authHeaders(token),
data: { nicknames }
})
}
export async function createNewAccount(nickname, email, password, authHost, token) {
return await request({
baseURL: baseName(authHost),
@ -110,6 +81,25 @@ export async function fetchUser(id, authHost, token) {
})
}
export async function fetchUserCredentials(nickname, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${nickname}/credentials`,
method: 'get',
headers: authHeaders(token)
})
}
export async function updateUserCredentials(nickname, credentials, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${nickname}/credentials`,
method: 'patch',
headers: authHeaders(token),
data: credentials
})
}
export async function fetchUsers(filters, actorTypeFilters, authHost, token, page = 1) {
const url = actorTypeFilters.length === 0
? `/api/pleroma/admin/users?page=${page}&filters=${filters}`
@ -126,34 +116,6 @@ export async function fetchUsers(filters, actorTypeFilters, authHost, token, pag
})
}
export async function fetchUserCredentials(nickname, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${nickname}/credentials`,
method: 'get',
headers: authHeaders(token)
})
}
export async function fetchUserStatuses(id, authHost, godmode, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${id}/statuses?godmode=${godmode}`,
method: 'get',
headers: authHeaders(token)
})
}
export async function forcePasswordReset(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/force_password_reset`,
method: 'patch',
headers: authHeaders(token),
data: { nicknames }
})
}
export async function getPasswordResetToken(nickname, authHost, token) {
return await request({
baseURL: baseName(authHost),
@ -163,19 +125,10 @@ export async function getPasswordResetToken(nickname, authHost, token) {
})
}
export async function listAllTags(authHost, token) {
export async function forcePasswordReset(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/tag`,
method: 'get',
headers: authHeaders(token)
})
}
export async function resendConfirmationEmail(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/users/resend_confirmation_email',
url: `/api/pleroma/admin/users/force_password_reset`,
method: 'patch',
headers: authHeaders(token),
data: { nicknames }
@ -218,13 +171,51 @@ export async function untagUser(nicknames, tags, authHost, token) {
})
}
export async function updateUserCredentials(nickname, credentials, authHost, token) {
export async function fetchUserStatuses(id, authHost, godmode, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${nickname}/credentials`,
url: `/api/pleroma/admin/users/${id}/statuses?godmode=${godmode}`,
method: 'get',
headers: authHeaders(token)
})
}
export async function fetchUserChats(id, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: `/api/pleroma/admin/users/${id}/chats`,
method: 'get',
headers: authHeaders(token)
})
}
export async function approveUserAccount(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/users/approve',
method: 'patch',
headers: authHeaders(token),
data: credentials
data: { nicknames }
})
}
export async function confirmUserEmail(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/users/confirm_email',
method: 'patch',
headers: authHeaders(token),
data: { nicknames }
})
}
export async function resendConfirmationEmail(nicknames, authHost, token) {
return await request({
baseURL: baseName(authHost),
url: '/api/pleroma/admin/users/resend_confirmation_email',
method: 'patch',
headers: authHeaders(token),
data: { nicknames }
})
}

View file

@ -192,7 +192,6 @@ export default {
search: 'Search',
id: 'ID',
name: 'Name',
label: 'Label',
status: 'Status',
local: 'Local',
external: 'External',
@ -280,12 +279,9 @@ export default {
registrationReason: 'Registration Reason',
service: 'Service',
person: 'Person',
enableTagPolicy: 'Enable MRF TagPolicy to manage tags',
enableTagPolicy: 'Enable MRF TagPolicy to manage user tags',
confirmEnablingTagPolicy: 'Are you sure you want to add TagPolicy to the list of enabled MRF policies?',
enableTagPolicySuccessMessage: 'MRF TagPolicy was enabled',
customTags: 'Custom Tags',
defaultTags: 'Default Tags',
tags: 'Tags'
enableTagPolicySuccessMessage: 'MRF TagPolicy was enabled'
},
statuses: {
statuses: 'Statuses',

View file

@ -3,21 +3,20 @@ import i18n from '@/lang'
import {
activateUsers,
addRight,
approveUserAccount,
confirmUserEmail,
createNewAccount,
deactivateUsers,
deleteRight,
deleteUsers,
disableMfa,
fetchUsers,
forcePasswordReset,
getPasswordResetToken,
listAllTags,
resendConfirmationEmail,
searchUsers,
tagUser,
untagUser,
forcePasswordReset,
approveUserAccount,
confirmUserEmail,
resendConfirmationEmail,
updateUserCredentials
} from '@/api/users'
import { fetchSettings, updateSettings } from '@/api/settings'
@ -36,8 +35,7 @@ const users = {
passwordResetToken: {
token: '',
link: ''
},
tags: []
}
},
mutations: {
SET_ACTOR_TYPE_FILTERS: (state, actorTypeFilters) => {
@ -83,9 +81,6 @@ const users = {
SET_TAG_POLICY: (state, mrfPolicies) => {
state.mrfPolicies = mrfPolicies
},
SET_TAGS: (state, tags) => {
state.tags = tags
},
SET_USERS_FILTERS: (state, filters) => {
state.filters = filters
}
@ -249,10 +244,6 @@ const users = {
RemovePasswordToken({ commit }) {
commit('SET_PASSWORD_RESET_TOKEN', { link: '', token: '' })
},
async ListTags({ commit, getters }) {
const { data } = await listAllTags(getters.authHost, getters.token)
commit('SET_TAGS', data)
},
async RemoveTag({ dispatch, getters }, { users, tag, _userId, _statusId }) {
const updatedUsers = users.map(user => {
return { ...user, tags: user.tags.filter(userTag => userTag !== tag) }

View file

@ -15,17 +15,49 @@
@click.native="handleDeletion(account)">
{{ $t('users.deleteAccount') }}
</el-dropdown-item>
<el-dropdown-item divided/>
<div v-if="tagPolicyEnabled">
<el-dropdown-item
v-for="option in tags"
:key="option.tag"
:class="{ 'active-tag': account.tags.includes(option.tag) }"
@click.native="toggleTag(account, option.tag)">
{{ option.label }}
<i v-if="account.tags.includes(option.tag)" class="el-icon-check"/>
</el-dropdown-item>
</div>
<el-dropdown-item
v-if="tagPolicyEnabled"
:divided="true"
:class="{ 'active-tag': tags.includes('mrf_tag:media-force-nsfw') }"
@click.native="toggleTag(account, 'mrf_tag:media-force-nsfw')">
{{ $t('users.forceNsfw') }}
<i v-if="tags.includes('mrf_tag:media-force-nsfw')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="tagPolicyEnabled"
:class="{ 'active-tag': tags.includes('mrf_tag:media-strip') }"
@click.native="toggleTag(account, 'mrf_tag:media-strip')">
{{ $t('users.stripMedia') }}
<i v-if="tags.includes('mrf_tag:media-strip')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="tagPolicyEnabled"
:class="{ 'active-tag': tags.includes('mrf_tag:force-unlisted') }"
@click.native="toggleTag(account, 'mrf_tag:force-unlisted')">
{{ $t('users.forceUnlisted') }}
<i v-if="tags.includes('mrf_tag:force-unlisted')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="tagPolicyEnabled"
:class="{ 'active-tag': tags.includes('mrf_tag:sandbox') }"
@click.native="toggleTag(account, 'mrf_tag:sandbox')">
{{ $t('users.sandbox') }}
<i v-if="tags.includes('mrf_tag:sandbox')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="tagPolicyEnabled && account.local"
:class="{ 'active-tag': tags.includes('mrf_tag:disable-remote-subscription') }"
@click.native="toggleTag(account, 'mrf_tag:disable-remote-subscription')">
{{ $t('users.disableRemoteSubscription') }}
<i v-if="tags.includes('mrf_tag:disable-remote-subscription')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="tagPolicyEnabled && account.local"
:class="{ 'active-tag': tags.includes('mrf_tag:disable-any-subscription') }"
@click.native="toggleTag(account, 'mrf_tag:disable-any-subscription')">
{{ $t('users.disableAnySubscription') }}
<i v-if="tags.includes('mrf_tag:disable-any-subscription')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="!tagPolicyEnabled"
divided
@ -55,28 +87,11 @@ export default {
}
},
computed: {
mapTags() {
return {
'mrf_tag:media-force-nsfw': 'Force posts to be NSFW',
'mrf_tag:media-strip': 'Force posts to not have media',
'mrf_tag:force-unlisted': 'Force posts to be unlisted',
'mrf_tag:sandbox': 'Force posts to be followers-only',
'mrf_tag:verified': 'Verified',
'mrf_tag:disable-remote-subscription': 'Disallow following user from remote instances',
'mrf_tag:disable-any-subscription': 'Disallow following user at all'
}
},
tagPolicyEnabled() {
return this.$store.state.users.mrfPolicies.includes('Pleroma.Web.ActivityPub.MRF.TagPolicy')
},
tags() {
return this.$store.state.users.tags.map(tag => {
if (this.mapTags[tag]) {
return { tag, label: this.mapTags[tag] }
} else {
return { tag, label: tag.charAt(0).toUpperCase() + tag.slice(1) }
}
}, {})
return this.account.tags || []
}
},
methods: {

View file

@ -43,7 +43,6 @@ export default {
this.$store.dispatch('NeedReboot')
this.$store.dispatch('FetchTagPolicySetting')
this.$store.dispatch('FetchReports', 1)
this.$store.dispatch('ListTags')
}
}
</script>

View file

@ -67,6 +67,56 @@
@click.native="handleConfirmationResend(user)">
{{ $t('users.resendConfirmation') }}
</el-dropdown-item>
<el-dropdown-item
v-if="tagPolicyEnabled"
:divided="showAdminAction(user)"
:class="{ 'active-tag': user.tags.includes('mrf_tag:media-force-nsfw') }"
@click.native="toggleTag(user, 'mrf_tag:media-force-nsfw')">
{{ $t('users.forceNsfw') }}
<i v-if="user.tags.includes('mrf_tag:media-force-nsfw')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="tagPolicyEnabled"
:class="{ 'active-tag': user.tags.includes('mrf_tag:media-strip') }"
@click.native="toggleTag(user, 'mrf_tag:media-strip')">
{{ $t('users.stripMedia') }}
<i v-if="user.tags.includes('mrf_tag:media-strip')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="tagPolicyEnabled"
:class="{ 'active-tag': user.tags.includes('mrf_tag:force-unlisted') }"
@click.native="toggleTag(user, 'mrf_tag:force-unlisted')">
{{ $t('users.forceUnlisted') }}
<i v-if="user.tags.includes('mrf_tag:force-unlisted')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="tagPolicyEnabled"
:class="{ 'active-tag': user.tags.includes('mrf_tag:sandbox') }"
@click.native="toggleTag(user, 'mrf_tag:sandbox')">
{{ $t('users.sandbox') }}
<i v-if="user.tags.includes('mrf_tag:sandbox')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="user.local && tagPolicyEnabled"
:class="{ 'active-tag': user.tags.includes('mrf_tag:disable-remote-subscription') }"
@click.native="toggleTag(user, 'mrf_tag:disable-remote-subscription')">
{{ $t('users.disableRemoteSubscription') }}
<i v-if="user.tags.includes('mrf_tag:disable-remote-subscription')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="user.local && tagPolicyEnabled"
:class="{ 'active-tag': user.tags.includes('mrf_tag:disable-any-subscription') }"
@click.native="toggleTag(user, 'mrf_tag:disable-any-subscription')">
{{ $t('users.disableAnySubscription') }}
<i v-if="user.tags.includes('mrf_tag:disable-any-subscription')" class="el-icon-check"/>
</el-dropdown-item>
<el-dropdown-item
v-if="!tagPolicyEnabled"
divided
class="no-hover"
@click.native="enableTagPolicy">
{{ $t('users.enableTagPolicy') }}
</el-dropdown-item>
<el-dropdown-item
v-if="user.local"
divided
@ -122,12 +172,35 @@ export default {
},
isDesktop() {
return this.$store.state.app.device === 'desktop'
},
tagPolicyEnabled() {
return this.$store.state.users.mrfPolicies.includes('Pleroma.Web.ActivityPub.MRF.TagPolicy')
}
},
methods: {
disableMfa(nickname) {
this.$store.dispatch('DisableMfa', nickname)
},
enableTagPolicy() {
this.$confirm(
this.$t('users.confirmEnablingTagPolicy'),
{
confirmButtonText: 'Yes',
cancelButtonText: 'Cancel',
type: 'warning'
}).then(() => {
this.$message({
type: 'success',
message: this.$t('users.enableTagPolicySuccessMessage')
})
this.$store.dispatch('EnableTagPolicy')
}).catch(() => {
this.$message({
type: 'info',
message: 'Canceled'
})
})
},
getPasswordResetToken(nickname) {
this.$emit('open-reset-token-dialog')
this.$store.dispatch('GetPasswordResetToken', nickname)
@ -192,6 +265,11 @@ export default {
? this.$store.dispatch('ActivateUsers', { users: [user], _userId: user.id })
: this.$store.dispatch('DeactivateUsers', { users: [user], _userId: user.id })
},
toggleTag(user, tag) {
user.tags.includes(tag)
? this.$store.dispatch('RemoveTag', { users: [user], tag, _userId: user.id, _statusId: this.statusId })
: this.$store.dispatch('AddTag', { users: [user], tag, _userId: user.id, _statusId: this.statusId })
},
toggleUserRight(user, right) {
user.roles[right]
? this.$store.dispatch('DeleteRight', { users: [user], right, _userId: user.id, _statusId: this.statusId })
@ -233,14 +311,8 @@ export default {
}
}
.actor-type-select .el-input.is-focus .el-input__inner {
border-color: transparent;
}
.custom-tags-titile {
padding-left: 20px;
font-size: 12px;
color: #909399;
line-height: 30px;
}
border-color: transparent;
}
.moderate-user-button {
text-align: left;
width: 350px;
@ -252,9 +324,6 @@ export default {
}
.moderation-dropdown-menu {
width: 350px;
.el-dropdown-menu--small .el-dropdown-menu__item.el-dropdown-menu__item--divided {
margin-top: 0;
}
}
@media only screen and (max-width:480px) {
.moderate-user-button {

View file

@ -61,27 +61,83 @@
@click.native="requirePasswordReset">
{{ $t('users.requirePasswordReset') }}
</el-dropdown-item>
<el-dropdown-item v-if="tagPolicyEnabled" divided>
<el-dropdown class="multiple-tags-moderation">
<div>
{{ $t('users.tags') }}<i class="el-icon-arrow-down el-icon--right" />
</div>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item v-for="option in tags" :key="option.tag" class="no-hover">
<div class="tag-container">
<span class="tag-text">{{ option.label }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers(option.tag)">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers(option.tag)">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
<el-dropdown-item v-if="tagPolicyEnabled" divided class="no-hover">
<div class="tag-container">
<span class="tag-text">{{ $t('users.forceNsfw') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('mrf_tag:media-force-nsfw')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('mrf_tag:media-force-nsfw')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
<el-dropdown-item v-if="tagPolicyEnabled" class="no-hover">
<div class="tag-container">
<span class="tag-text">{{ $t('users.stripMedia') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('mrf_tag:media-strip')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('mrf_tag:media-strip')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
<el-dropdown-item v-if="tagPolicyEnabled" class="no-hover">
<div class="tag-container">
<span class="tag-text">{{ $t('users.forceUnlisted') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('mrf_tag:force-unlisted')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('mrf_tag:force-unlisted')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
<el-dropdown-item v-if="tagPolicyEnabled" class="no-hover">
<div class="tag-container">
<span class="tag-text">{{ $t('users.sandbox') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('mrf_tag:sandbox')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('mrf_tag:sandbox')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
<el-dropdown-item v-if="tagPolicyEnabled" class="no-hover">
<div class="tag-container">
<span class="tag-text">{{ $t('users.disableRemoteSubscriptionForMultiple') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('mrf_tag:disable-remote-subscription')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('mrf_tag:disable-remote-subscription')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
<el-dropdown-item v-if="tagPolicyEnabled" class="no-hover">
<div class="tag-container">
<span class="tag-text">{{ $t('users.disableAnySubscriptionForMultiple') }}</span>
<el-button-group class="tag-button-group">
<el-button size="mini" @click.native="addTagForMultipleUsers('mrf_tag:disable-any-subscription')">
{{ $t('users.apply') }}
</el-button>
<el-button size="mini" @click.native="removeTagFromMultipleUsers('mrf_tag:disable-any-subscription')">
{{ $t('users.remove') }}
</el-button>
</el-button-group>
</div>
</el-dropdown-item>
<el-dropdown-item
v-if="!tagPolicyEnabled"
@ -112,31 +168,11 @@ export default {
isDesktop() {
return this.$store.state.app.device === 'desktop'
},
mapTags() {
return {
'mrf_tag:media-force-nsfw': 'NSFW',
'mrf_tag:media-strip': 'Strip Media',
'mrf_tag:force-unlisted': 'Unlisted',
'mrf_tag:sandbox': 'Sandbox',
'mrf_tag:verified': 'Verified',
'mrf_tag:disable-remote-subscription': 'Disable remote subscription',
'mrf_tag:disable-any-subscription': 'Disable any subscription'
}
},
showDropdownForMultipleUsers() {
return this.$props.selectedUsers.length > 0
},
tagPolicyEnabled() {
return this.$store.state.users.mrfPolicies.includes('Pleroma.Web.ActivityPub.MRF.TagPolicy')
},
tags() {
return this.$store.state.users.tags.map(tag => {
if (this.mapTags[tag]) {
return { tag, label: this.mapTags[tag] }
} else {
return { tag, label: tag.charAt(0).toUpperCase() + tag.slice(1) }
}
}, {})
}
},
methods: {
@ -370,14 +406,6 @@ export default {
.el-icon-edit {
margin-right: 5px;
}
.multiple-tags-moderation {
width: 100%;
}
.no-hover:hover {
color: #606266;
background-color: white;
cursor: auto;
}
.tag-container {
display: flex;
justify-content: space-between;
@ -386,4 +414,9 @@ export default {
.tag-text {
padding-right: 20px;
}
.no-hover:hover {
color: #606266;
background-color: white;
cursor: auto;
}
</style>

View file

@ -54,7 +54,7 @@
</el-tag>
</template>
</el-table-column>
<el-table-column :min-width="width" :label="$t('users.status')" width="200px">
<el-table-column :min-width="width" :label="$t('users.status')">
<template slot-scope="scope">
<el-tag v-if="!scope.row.deactivated & !scope.row.approval_pending" type="success">
<span v-if="isDesktop">{{ $t('users.active') }}</span>
@ -83,45 +83,6 @@
</el-tooltip>
</template>
</el-table-column>
<el-table-column :min-width="width" :label="$t('users.tags')">
<template slot-scope="scope">
<el-select
v-if="tagPolicyEnabled"
:value="scope.row.tags"
multiple
filterable
allow-create
placeholder="Add Tags"
size="small"
class="select-tags"
@change="toggleTag($event, scope.row)">
<el-option-group :label="$t('users.defaultTags')">
<el-option
v-for="option in defaultTags(scope.row.local)"
:value="option.tag"
:key="option.tag"
:label="option.label"
:class="{ 'active-tag': scope.row.tags.includes(option.tag) }">
{{ option.label }}
</el-option>
</el-option-group>
<el-option-group :label="$t('users.customTags')">
<el-option
v-for="option in customTags()"
:value="option.tag"
:key="option.tag"
:label="option.label"
:class="{ 'active-tag': scope.row.tags.includes(option.tag) }"
class="capitalize">
{{ option.label }}
</el-option>
</el-option-group>
</el-select>
<el-button v-if="!tagPolicyEnabled" type="text" @click.native.stop="enableTagPolicy">
{{ $t('users.enableTagPolicy') }}
</el-button>
</template>
</el-table-column>
<el-table-column v-if="pendingView && isDesktop" :label="$t('users.registrationReason')">
<template slot-scope="scope">
<el-tooltip
@ -199,6 +160,15 @@ export default {
}
},
computed: {
loading() {
return this.$store.state.users.loading
},
normalizedUsersCount() {
return numeral(this.$store.state.users.totalUsersCount).format('0a')
},
pageSize() {
return this.$store.state.users.pageSize
},
currentPage() {
return this.$store.state.users.currentPage
},
@ -208,41 +178,6 @@ export default {
isMobile() {
return this.$store.state.app.device === 'mobile'
},
loading() {
return this.$store.state.users.loading
},
mapRemoteTags() {
return {
'mrf_tag:media-force-nsfw': 'NSFW',
'mrf_tag:media-strip': 'Strip Media',
'mrf_tag:force-unlisted': 'Unlisted',
'mrf_tag:sandbox': 'Sandbox',
'mrf_tag:verified': 'Verified'
}
},
mapTags() {
return {
'mrf_tag:media-force-nsfw': 'NSFW',
'mrf_tag:media-strip': 'Strip Media',
'mrf_tag:force-unlisted': 'Unlisted',
'mrf_tag:sandbox': 'Sandbox',
'mrf_tag:verified': 'Verified',
'mrf_tag:disable-remote-subscription': 'Disable remote subscription',
'mrf_tag:disable-any-subscription': 'Disable any subscription'
}
},
normalizedUsersCount() {
return numeral(this.$store.state.users.totalUsersCount).format('0a')
},
pageSize() {
return this.$store.state.users.pageSize
},
pendingView() {
return this.$store.state.users.filters['need_approval']
},
tagPolicyEnabled() {
return this.$store.state.users.mrfPolicies.includes('Pleroma.Web.ActivityPub.MRF.TagPolicy')
},
users() {
return this.$store.state.users.fetchedUsers
},
@ -265,7 +200,6 @@ export default {
this.$store.dispatch('NeedReboot')
this.$store.dispatch('FetchTagPolicySetting')
this.$store.dispatch('FetchUsers', { page: 1 })
this.$store.dispatch('ListTags')
},
destroyed() {
this.$store.dispatch('ClearUsersState')
@ -282,44 +216,6 @@ export default {
await this.$store.dispatch('CreateNewAccount', accountData)
this.createAccountDialogOpen = false
},
customTags() {
return this.$store.state.users.tags
.filter(tag => !Object.keys(this.mapTags).includes(tag))
.map(tag => {
return { tag, label: tag.charAt(0).toUpperCase() + tag.slice(1) }
})
},
defaultTags(userLocal) {
const tagsByType = userLocal ? Object.keys(this.mapTags) : Object.keys(this.mapRemoteTags)
return tagsByType.filter(tag => this.$store.state.users.tags.includes(tag))
.map(tag => {
if (userLocal) {
return { tag, label: this.mapTags[tag] }
} else {
return { tag, label: this.mapRemoteTags[tag] }
}
}, {})
},
enableTagPolicy() {
this.$confirm(
this.$t('users.confirmEnablingTagPolicy'),
{
confirmButtonText: 'Yes',
cancelButtonText: 'Cancel',
type: 'warning'
}).then(() => {
this.$message({
type: 'success',
message: this.$t('users.enableTagPolicySuccessMessage')
})
this.$store.dispatch('EnableTagPolicy')
}).catch(() => {
this.$message({
type: 'info',
message: 'Canceled'
})
})
},
getFirstLetter(str) {
return str.charAt(0).toUpperCase()
},
@ -350,11 +246,6 @@ export default {
},
showDeactivatedButton(id) {
return this.$store.state.user.id !== id
},
toggleTag(tags, user) {
tags.length > user.tags.length
? this.$store.dispatch('AddTag', { users: [user], tag: tags.filter(tag => !user.tags.includes(tag))[0] })
: this.$store.dispatch('RemoveTag', { users: [user], tag: user.tags.filter(tag => !tags.includes(tag))[0] })
}
}
}
@ -390,9 +281,6 @@ export default {
color: #bbb;
}
}
.capitalize {
text-transform: capitalize;
}
.el-dropdown-link:hover {
cursor: pointer;
color: #409EFF;
@ -442,10 +330,6 @@ export default {
float: right;
margin-left: 10px;
}
.select-tags {
padding-right: 10px;
width: 100%;
}
.filter-container {
display: flex;
height: 36px;

View file

@ -138,7 +138,7 @@ describe('Users actions', () => {
const dropdownMenuItems = wrapper.findAll(
`.el-table__fixed-body-wrapper table tr:nth-child(3) ul.el-dropdown-menu > li`
)
expect(dropdownMenuItems.length).toBe(3)
expect(dropdownMenuItems.length).toBe(7)
done()
})
@ -198,28 +198,8 @@ describe('Users actions', () => {
expect(user1.tags.length).toBe(0)
expect(user2.tags.length).toBe(1)
wrapper.vm.toggleTag(['test-tag'],
{ active: true,
approval_pending: false,
deactivated: false, id: '2',
nickname: 'allis',
local: true,
external: false,
roles: { admin: true, moderator: false },
tags: [],
actor_type: 'Person' })
wrapper.vm.toggleTag(['test-tag', 'mrf_tag:sandbox'],
{ active: true,
approval_pending: false,
deactivated: false,
id: '10',
nickname: 'bob',
local: true,
external: false,
roles: { admin: false, moderator: false },
tags: ['mrf_tag:sandbox'],
actor_type: 'Person' })
wrapper.find(htmlElement(1, 6)).trigger('click')
wrapper.find(htmlElement(2, 6)).trigger('click')
const updatedUser1 = store.state.users.fetchedUsers[0]
const updatedUser2 = store.state.users.fetchedUsers[1]
@ -241,18 +221,7 @@ describe('Users actions', () => {
const user = store.state.users.fetchedUsers[1]
expect(user.tags.length).toBe(1)
wrapper.vm.toggleTag([],
{ active: true,
approval_pending: false,
deactivated: false,
id: '10',
nickname: 'bob',
local: true,
external: false,
roles: { admin: false, moderator: false },
tags: ['mrf_tag:sandbox'],
actor_type: 'Person' })
wrapper.find(htmlElement(2, 9)).trigger('click')
const updatedUser = store.state.users.fetchedUsers[1]
expect(updatedUser.tags.length).toBe(0)
@ -302,7 +271,7 @@ describe('Users actions', () => {
expect(wrapper.vm.resetPasswordDialogOpen).toBe(false)
expect(store.state.users.passwordResetToken.token).toBe('')
wrapper.find(htmlElement(1, 6)).trigger('click')
wrapper.find(htmlElement(1, 12)).trigger('click')
await flushPromises()
expect(wrapper.vm.resetPasswordDialogOpen).toBe(true)