aboutsummaryrefslogtreecommitdiff
path: root/src/components/moderation_tools
diff options
context:
space:
mode:
Diffstat (limited to 'src/components/moderation_tools')
-rw-r--r--src/components/moderation_tools/moderation_tools.js101
-rw-r--r--src/components/moderation_tools/moderation_tools.vue193
2 files changed, 294 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..8aadc8c5
--- /dev/null
+++ b/src/components/moderation_tools/moderation_tools.js
@@ -0,0 +1,101 @@
+import DialogModal from '../dialog_modal/dialog_modal.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
+ },
+ computed: {
+ tagsSet () {
+ return new Set(this.user.tags)
+ },
+ hasTagPolicy () {
+ return this.$store.state.instance.tagPolicyAvailable
+ }
+ },
+ methods: {
+ 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..d97ca3aa
--- /dev/null
+++ b/src/components/moderation_tools/moderation_tools.vue
@@ -0,0 +1,193 @@
+<template>
+ <div>
+ <v-popover
+ trigger="click"
+ class="moderation-tools-popover"
+ :container="false"
+ placement="bottom-end"
+ :offset="5"
+ @show="showDropDown = true"
+ @hide="showDropDown = false"
+ >
+ <div slot="popover">
+ <div class="dropdown-menu">
+ <span v-if="user.is_local">
+ <button
+ class="dropdown-item"
+ @click="toggleRight(&quot;admin&quot;)"
+ >
+ {{ $t(!!user.rights.admin ? 'user_card.admin_menu.revoke_admin' : 'user_card.admin_menu.grant_admin') }}
+ </button>
+ <button
+ class="dropdown-item"
+ @click="toggleRight(&quot;moderator&quot;)"
+ >
+ {{ $t(!!user.rights.moderator ? 'user_card.admin_menu.revoke_moderator' : 'user_card.admin_menu.grant_moderator') }}
+ </button>
+ <div
+ role="separator"
+ class="dropdown-divider"
+ />
+ </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
+ v-if="hasTagPolicy"
+ role="separator"
+ class="dropdown-divider"
+ />
+ <span v-if="hasTagPolicy">
+ <button
+ class="dropdown-item"
+ @click="toggleTag(tags.FORCE_NSFW)"
+ >
+ {{ $t('user_card.admin_menu.force_nsfw') }}
+ <span
+ class="menu-checkbox"
+ :class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_NSFW) }"
+ />
+ </button>
+ <button
+ class="dropdown-item"
+ @click="toggleTag(tags.STRIP_MEDIA)"
+ >
+ {{ $t('user_card.admin_menu.strip_media') }}
+ <span
+ class="menu-checkbox"
+ :class="{ 'menu-checkbox-checked': hasTag(tags.STRIP_MEDIA) }"
+ />
+ </button>
+ <button
+ class="dropdown-item"
+ @click="toggleTag(tags.FORCE_UNLISTED)"
+ >
+ {{ $t('user_card.admin_menu.force_unlisted') }}
+ <span
+ class="menu-checkbox"
+ :class="{ 'menu-checkbox-checked': hasTag(tags.FORCE_UNLISTED) }"
+ />
+ </button>
+ <button
+ class="dropdown-item"
+ @click="toggleTag(tags.SANDBOX)"
+ >
+ {{ $t('user_card.admin_menu.sandbox') }}
+ <span
+ class="menu-checkbox"
+ :class="{ 'menu-checkbox-checked': hasTag(tags.SANDBOX) }"
+ />
+ </button>
+ <button
+ v-if="user.is_local"
+ class="dropdown-item"
+ @click="toggleTag(tags.DISABLE_REMOTE_SUBSCRIPTION)"
+ >
+ {{ $t('user_card.admin_menu.disable_remote_subscription') }}
+ <span
+ class="menu-checkbox"
+ :class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_REMOTE_SUBSCRIPTION) }"
+ />
+ </button>
+ <button
+ v-if="user.is_local"
+ class="dropdown-item"
+ @click="toggleTag(tags.DISABLE_ANY_SUBSCRIPTION)"
+ >
+ {{ $t('user_card.admin_menu.disable_any_subscription') }}
+ <span
+ class="menu-checkbox"
+ :class="{ 'menu-checkbox-checked': hasTag(tags.DISABLE_ANY_SUBSCRIPTION) }"
+ />
+ </button>
+ <button
+ v-if="user.is_local"
+ class="dropdown-item"
+ @click="toggleTag(tags.QUARANTINE)"
+ >
+ {{ $t('user_card.admin_menu.quarantine') }}
+ <span
+ class="menu-checkbox"
+ :class="{ 'menu-checkbox-checked': hasTag(tags.QUARANTINE) }"
+ />
+ </button>
+ </span>
+ </div>
+ </div>
+ <button
+ class="btn btn-default btn-block"
+ :class="{ pressed: showDropDown }"
+ >
+ {{ $t('user_card.admin_menu.moderation') }}
+ </button>
+ </v-popover>
+ <portal to="modal">
+ <DialogModal
+ v-if="showDeleteUserDialog"
+ :on-cancel="deleteUserDialog.bind(this, false)"
+ >
+ <template slot="header">
+ {{ $t('user_card.admin_menu.delete_user') }}
+ </template>
+ <p>{{ $t('user_card.admin_menu.delete_user_confirmation') }}</p>
+ <template slot="footer">
+ <button
+ class="btn btn-default"
+ @click="deleteUserDialog(false)"
+ >
+ {{ $t('general.cancel') }}
+ </button>
+ <button
+ class="btn btn-default danger"
+ @click="deleteUser()"
+ >
+ {{ $t('user_card.admin_menu.delete_user') }}
+ </button>
+ </template>
+ </DialogModal>
+ </portal>
+ </div>
+</template>
+
+<script src="./moderation_tools.js"></script>
+
+<style lang="scss">
+@import '../../_variables.scss';
+@import '../popper/popper.scss';
+
+.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: '✔';
+ }
+}
+
+.moderation-tools-popover {
+ height: 100%;
+ .trigger {
+ display: flex !important;
+ height: 100%;
+ }
+}
+</style>