aboutsummaryrefslogtreecommitdiff
path: root/src/components/moderation_tools
diff options
context:
space:
mode:
authoreugenijm <eugenijm@protonmail.com>2019-02-18 17:49:32 +0300
committereugenijm <eugenijm@protonmail.com>2019-04-01 23:30:06 +0300
commit6b6878bde06b375b1e715a3557f153acc73a8af0 (patch)
treeba97b5f4a364c05122cd657140d9fa34ca6f1616 /src/components/moderation_tools
parentac28e8c2f981b6584f0103e10b0a5f5b025fcaae (diff)
Added moderation menu
Diffstat (limited to 'src/components/moderation_tools')
-rw-r--r--src/components/moderation_tools/moderation_tools.js106
-rw-r--r--src/components/moderation_tools/moderation_tools.vue158
2 files changed, 264 insertions, 0 deletions
diff --git a/src/components/moderation_tools/moderation_tools.js b/src/components/moderation_tools/moderation_tools.js
new file mode 100644
index 00000000..3eedeaa1
--- /dev/null
+++ b/src/components/moderation_tools/moderation_tools.js
@@ -0,0 +1,106 @@
+import DialogModal from '../dialog_modal/dialog_modal.vue'
+import Popper from 'vue-popperjs/src/component/popper.js.vue'
+
+const FORCE_NSFW = 'mrf_tag:media-force-nsfw'
+const STRIP_MEDIA = 'mrf_tag:media-strip'
+const FORCE_UNLISTED = 'mrf_tag:force-unlisted'
+const DISABLE_REMOTE_SUBSCRIPTION = 'mrf_tag:disable-remote-subscription'
+const DISABLE_ANY_SUBSCRIPTION = 'mrf_tag:disable-any-subscription'
+const SANDBOX = 'mrf_tag:sandbox'
+const QUARANTINE = 'mrf_tag:quarantine'
+
+const ModerationTools = {
+ props: [
+ 'user'
+ ],
+ data () {
+ return {
+ showDropDown: false,
+ tags: {
+ FORCE_NSFW,
+ STRIP_MEDIA,
+ FORCE_UNLISTED,
+ DISABLE_REMOTE_SUBSCRIPTION,
+ DISABLE_ANY_SUBSCRIPTION,
+ SANDBOX,
+ QUARANTINE
+ },
+ showDeleteUserDialog: false
+ }
+ },
+ components: {
+ DialogModal,
+ Popper
+ },
+ computed: {
+ tagsSet () {
+ return new Set(this.user.tags)
+ },
+ hasTagPolicy () {
+ return this.$store.state.instance.tagPolicyAvailable
+ }
+ },
+ methods: {
+ toggleMenu () {
+ this.showDropDown = !this.showDropDown
+ },
+ hasTag (tagName) {
+ return this.tagsSet.has(tagName)
+ },
+ toggleTag (tag) {
+ const store = this.$store
+ if (this.tagsSet.has(tag)) {
+ store.state.api.backendInteractor.untagUser(this.user, tag).then(response => {
+ if (!response.ok) { return }
+ store.commit('untagUser', {user: this.user, tag})
+ })
+ } else {
+ store.state.api.backendInteractor.tagUser(this.user, tag).then(response => {
+ if (!response.ok) { return }
+ store.commit('tagUser', {user: this.user, tag})
+ })
+ }
+ },
+ toggleRight (right) {
+ const store = this.$store
+ if (this.user.rights[right]) {
+ store.state.api.backendInteractor.deleteRight(this.user, right).then(response => {
+ if (!response.ok) { return }
+ store.commit('updateRight', {user: this.user, right: right, value: false})
+ })
+ } else {
+ store.state.api.backendInteractor.addRight(this.user, right).then(response => {
+ if (!response.ok) { return }
+ store.commit('updateRight', {user: this.user, right: right, value: true})
+ })
+ }
+ },
+ toggleActivationStatus () {
+ const store = this.$store
+ const status = !!this.user.deactivated
+ store.state.api.backendInteractor.setActivationStatus(this.user, status).then(response => {
+ if (!response.ok) { return }
+ store.commit('updateActivationStatus', {user: this.user, status: status})
+ })
+ },
+ deleteUserDialog (show) {
+ this.showDeleteUserDialog = show
+ },
+ deleteUser () {
+ const store = this.$store
+ const user = this.user
+ const {id, name} = user
+ store.state.api.backendInteractor.deleteUser(user)
+ .then(e => {
+ this.$store.dispatch('markStatusesAsDeleted', status => user.id === status.user.id)
+ const isProfile = this.$route.name === 'external-user-profile' || this.$route.name === 'user-profile'
+ const isTargetUser = this.$route.params.name === name || this.$route.params.id === id
+ if (isProfile && isTargetUser) {
+ window.history.back()
+ }
+ })
+ }
+ }
+}
+
+export default ModerationTools
diff --git a/src/components/moderation_tools/moderation_tools.vue b/src/components/moderation_tools/moderation_tools.vue
new file mode 100644
index 00000000..c24a2280
--- /dev/null
+++ b/src/components/moderation_tools/moderation_tools.vue
@@ -0,0 +1,158 @@
+<template>
+<div class='block' style='position: relative'>
+ <Popper
+ trigger="click"
+ @hide='showDropDown = false'
+ append-to-body
+ :options="{
+ placement: 'bottom-end',
+ modifiers: {
+ arrow: { enabled: true },
+ offset: { offset: '0, 5px' },
+ }
+ }">
+ <div class="popper-wrapper">
+ <div class="dropdown-menu">
+ <span v-if='user.is_local'>
+ <button class="dropdown-item" @click='toggleRight("admin")'>
+ {{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }}
+ </button>
+ <button class="dropdown-item" @click='toggleRight("moderator")'>
+ {{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }}
+ </button>
+ <div role="separator" class="dropdown-divider"></div>
+ </span>
+ <button class="dropdown-item" @click='toggleActivationStatus()'>
+ {{ $t(!!user.deactivated ? 'user_card.admin_menu.activate_account' : 'user_card.admin_menu.deactivate_account') }}
+ </button>
+ <button class="dropdown-item" @click='deleteUserDialog(true)'>
+ {{ $t('user_card.admin_menu.delete_account') }}
+ </button>
+ <div role="separator" class="dropdown-divider" v-if='hasTagPolicy'></div>
+ <span v-if='hasTagPolicy'>
+ <button class="dropdown-item" @click='toggleTag(tags.FORCE_NSFW)'>
+ {{ $t('user_card.admin_menu.force_nsfw') }}
+ <span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_NSFW) }"></span>
+ </button>
+ <button class="dropdown-item" @click='toggleTag(tags.STRIP_MEDIA)'>
+ {{ $t('user_card.admin_menu.strip_media') }}
+ <span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.STRIP_MEDIA) }"></span>
+ </button>
+ <button class="dropdown-item" @click='toggleTag(tags.FORCE_UNLISTED)'>
+ {{ $t('user_card.admin_menu.force_unlisted') }}
+ <span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_UNLISTED) }"></span>
+ </button>
+ <button class="dropdown-item" @click='toggleTag(tags.SANDBOX)'>
+ {{ $t('user_card.admin_menu.sandbox') }}
+ <span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.SANDBOX) }"></span>
+ </button>
+ <button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)'>
+ {{ $t('user_card.admin_menu.disable_remote_subscription') }}
+ <span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_REMOTE_SUBSCRIPTION) }"></span>
+ </button>
+ <button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)'>
+ {{ $t('user_card.admin_menu.disable_any_subscription') }}
+ <span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_ANY_SUBSCRIPTION) }"></span>
+ </button>
+ <button class="dropdown-item" v-if='user.is_local' @click='toggleTag(tags.QUARANTINE)'>
+ {{ $t('user_card.admin_menu.quarantine') }}
+ <span class="menu-checkbox" v-bind:class="{ 'menu-checkbox-checked': hasTag(tags.QUARANTINE) }"></span>
+ </button>
+ </span>
+ </div>
+ </div>
+ <button slot="reference" v-bind:class="{ pressed: showDropDown }" @click='toggleMenu'>
+ {{ $t('user_card.admin_menu.moderation') }}
+ </button>
+ </Popper>
+ <DialogModal v-if="showDeleteUserDialog" :onCancel='deleteUserDialog.bind(this, false)'>
+ <span slot="header">{{ $t('user_card.admin_menu.delete_user') }}</span>
+ <p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
+ <span slot="footer">
+ <button @click='deleteUserDialog(false)'>
+ {{ $t('general.cancel') }}
+ </button>
+ <button class="danger" @click='deleteUser()'>
+ {{ $t('user_card.admin_menu.delete_user') }}
+ </button>
+ </span>
+ </DialogModal>
+</div>
+</template>
+
+<script src="./moderation_tools.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+@import '../popper/popper.scss';
+
+.dropdown-menu {
+ display: block;
+ padding: .5rem 0;
+ font-size: 1rem;
+ text-align: left;
+ list-style: none;
+ max-width: 100vw;
+ z-index: 10;
+ box-shadow: 1px 1px 4px rgba(0,0,0,.6);
+ box-shadow: var(--panelShadow);
+ border: none;
+ border-radius: $fallback--btnRadius;
+ border-radius: var(--btnRadius, $fallback--btnRadius);
+ background-color: $fallback--bg;
+ background-color: var(--bg, $fallback--bg);
+
+ .dropdown-divider {
+ height: 0;
+ margin: .5rem 0;
+ overflow: hidden;
+ border-top: 1px solid $fallback--border;
+ border-top: 1px solid var(--border, $fallback--border);
+ }
+
+ .dropdown-item {
+ line-height: 21px;
+ margin-right: 5px;
+ overflow: auto;
+ display: block;
+ padding: .25rem 1.0rem .25rem 1.5rem;
+ clear: both;
+ font-weight: 400;
+ text-align: inherit;
+ white-space: normal;
+ border: none;
+ border-radius: 0px;
+ background-color: transparent;
+ box-shadow: none;
+ width: 100%;
+ height: 100%;
+
+ &:hover {
+ // TODO: improve the look on breeze themes
+ background-color: $fallback--fg;
+ background-color: var(--btn, $fallback--fg);
+ box-shadow: none;
+ }
+ }
+}
+
+.menu-checkbox {
+ float: right;
+ min-width: 22px;
+ max-width: 22px;
+ min-height: 22px;
+ max-height: 22px;
+ line-height: 22px;
+ text-align: center;
+ border-radius: 0px;
+ background-color: $fallback--fg;
+ background-color: var(--input, $fallback--fg);
+ box-shadow: 0px 0px 2px black inset;
+ box-shadow: var(--inputShadow);
+
+ &.menu-checkbox-checked::after {
+ content: '✔';
+ }
+}
+
+</style>