diff options
author | Maksim Sukharev <antreesy.web@gmail.com> | 2024-06-19 13:43:44 +0200 |
---|---|---|
committer | Maksim Sukharev <antreesy.web@gmail.com> | 2024-06-19 14:31:36 +0200 |
commit | c3c27d75789fa211fbb8cd7d43c8ab210e25cb00 (patch) | |
tree | 7ea199872ac3237c9a00998b71b3b5d5f5610c54 /src | |
parent | db3a2edf9757d494b89e9e2a0231b7883ad6269c (diff) |
feat(ban): list existing bans per conversation
Signed-off-by: Maksim Sukharev <antreesy.web@gmail.com>
Diffstat (limited to 'src')
3 files changed, 240 insertions, 0 deletions
diff --git a/src/components/ConversationSettings/BanSettings/BanSettings.vue b/src/components/ConversationSettings/BanSettings/BanSettings.vue new file mode 100644 index 000000000..cc40d4487 --- /dev/null +++ b/src/components/ConversationSettings/BanSettings/BanSettings.vue @@ -0,0 +1,132 @@ +<!-- + - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + - SPDX-License-Identifier: AGPL-3.0-or-later +--> + +<template> + <div class="conversation-ban__settings"> + <h4 class="app-settings-section__subtitle"> + {{ t('spreed', 'Banned users') }} + </h4> + <div class="app-settings-section__hint"> + {{ t('spreed', 'Manage the list of banned users in this conversation.') }} + </div> + <NcButton @click="modal = true"> + {{ t('spreed', 'Manage bans') }} + </NcButton> + + <NcModal v-if="modal" + container=".conversation-ban__settings" + @close="modal = false"> + <div class="conversation-ban__content"> + <h2 class="conversation-ban__title"> + {{ t('spreed', 'Banned users') }} + </h2> + + <ul v-if="banList.length" class="conversation-ban__list"> + <BannedItem v-for="ban in banList" + :key="ban.id" + :ban="ban" + @unban-participant="handleUnban(ban.id)" /> + </ul> + + <NcEmptyContent v-else> + <template #icon> + <NcLoadingIcon v-if="isLoading" /> + <AccountCancel v-else /> + </template> + + <template #description> + <p>{{ isLoading ? t('spreed', 'Loading …') : t('spreed', 'No banned users') }}</p> + </template> + </NcEmptyContent> + </div> + </NcModal> + </div> +</template> + +<script> +import AccountCancel from 'vue-material-design-icons/AccountCancel.vue' + +import { t } from '@nextcloud/l10n' + +import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' +import NcEmptyContent from '@nextcloud/vue/dist/Components/NcEmptyContent.js' +import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js' +import NcModal from '@nextcloud/vue/dist/Components/NcModal.js' + +import BannedItem from './BannedItem.vue' + +import { getConversationBans, unbanActor } from '../../../services/banService.ts' + +export default { + name: 'BanSettings', + + components: { + NcButton, + NcEmptyContent, + NcLoadingIcon, + NcModal, + BannedItem, + // Icons + AccountCancel, + }, + + props: { + token: { + type: String, + required: true, + }, + }, + + data() { + return { + banList: [], + isLoading: true, + modal: false, + } + }, + + watch: { + modal(value) { + if (value) { + this.getList() + } + } + }, + + methods: { + t, + + async getList() { + this.isLoading = true + const response = await getConversationBans(this.token) + this.banList = response.data.ocs.data + this.isLoading = false + }, + + async handleUnban(id) { + await unbanActor(this.token, id) + this.banList = this.banList.filter(ban => ban.id !== id) + } + }, +} +</script> + +<style lang="scss" scoped> +.conversation-ban { + &__content { + min-height: 250px; + } + + &__title { + text-align: center; + } + + &__list { + overflow: auto; + height: calc(100% - 45px - 12px); + padding: calc(var(--default-grid-baseline) * 2); + } +} +</style> diff --git a/src/components/ConversationSettings/BanSettings/BannedItem.vue b/src/components/ConversationSettings/BanSettings/BannedItem.vue new file mode 100644 index 000000000..cddd48399 --- /dev/null +++ b/src/components/ConversationSettings/BanSettings/BannedItem.vue @@ -0,0 +1,101 @@ +<!-- + - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors + - SPDX-License-Identifier: AGPL-3.0-or-later +--> + +<template> + <li :key="ban.id" class="ban-item"> + <div class="ban-item__header"> + <span class="ban-item__caption">{{ ban.bannedId }}</span> + <div class="ban-item__buttons"> + <NcButton type="tertiary" @click="showDetails = !showDetails"> + {{ showDetails ? t('spreed', 'Hide details') : t('spreed', 'Show details') }} + </NcButton> + <NcButton @click="$emit('unban-participant')"> + {{ t('spreed', 'Unban') }} + </NcButton> + </div> + </div> + <ul v-if="showDetails" class="ban-item__hint"> + <!-- eslint-disable-next-line vue/no-v-html --> + <li v-for="(item, index) in banInfo" :key="index" v-html="item" /> + </ul> + </li> +</template> + +<script> +import { t } from '@nextcloud/l10n' +import moment from '@nextcloud/moment' + +import NcButton from '@nextcloud/vue/dist/Components/NcButton.js' + +export default { + name: 'BannedItem', + + components: { + NcButton, + }, + + props: { + ban: { + type: Object, + required: true, + }, + }, + + emits: ['unban-participant'], + + data() { + return { + showDetails: false, + } + }, + + computed: { + banInfo() { + return [ + t('spreed', '<strong>Banned by:</strong> {actor}', { actor: this.ban.actorId }, + undefined, { escape: false, sanitize: false }), + t('spreed', '<strong>Date:</strong> {date}', { date: moment(this.ban.bannedTime * 1000).format('lll') }, + undefined, { escape: false, sanitize: false }), + t('spreed', '<strong>Note:</strong> {note}', { note: this.ban.internalNote }, + undefined, { escape: false, sanitize: false }), + ] + }, + }, + + methods: { + t, + }, +} +</script> + +<style lang="scss" scoped> + +.ban-item { + padding: 4px 0; + &:not(:last-child) { + border-bottom: 1px solid var(--color-border); + } + + &__header { + display: flex; + justify-content: space-between; + align-items: center; + } + + &__caption { + font-weight: bold; + } + + &__hint { + word-wrap: break-word; + color: var(--color-text-maxcontrast); + margin-bottom: 4px; + } + + &__buttons { + display: flex; + } +} +</style> diff --git a/src/components/ConversationSettings/ConversationSettingsDialog.vue b/src/components/ConversationSettings/ConversationSettingsDialog.vue index 3720cc789..782e9b869 100644 --- a/src/components/ConversationSettings/ConversationSettingsDialog.vue +++ b/src/components/ConversationSettings/ConversationSettingsDialog.vue @@ -40,6 +40,7 @@ <LinkShareSettings v-if="!isNoteToSelf" :token="token" :can-moderate="canFullModerate" /> <RecordingConsentSettings v-if="!isNoteToSelf && recordingConsentAvailable" :token="token" :can-moderate="selfIsOwnerOrModerator" /> <ExpirationSettings :token="token" :can-moderate="selfIsOwnerOrModerator" /> + <BanSettings v-if="supportBanV1 && canFullModerate" :token="token" /> </NcAppSettingsSection> <!-- Meeting: lobby and sip --> @@ -100,6 +101,7 @@ import NcAppSettingsDialog from '@nextcloud/vue/dist/Components/NcAppSettingsDia import NcAppSettingsSection from '@nextcloud/vue/dist/Components/NcAppSettingsSection.js' import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js' +import BanSettings from './BanSettings/BanSettings.vue' import BasicInfo from './BasicInfo.vue' import BotsSettings from './BotsSettings.vue' import BreakoutRoomsSettings from './BreakoutRoomsSettings.vue' @@ -123,6 +125,7 @@ export default { name: 'ConversationSettingsDialog', components: { + BanSettings, BasicInfo, BotsSettings, BreakoutRoomsSettings, @@ -180,6 +183,10 @@ export default { return (!hasTalkFeature(this.token, 'federation-v1') || !this.conversation.remoteServer) }, + supportBanV1() { + return hasTalkFeature(this.token, 'ban-v1') + }, + showMediaSettings() { return this.settingsStore.getShowMediaSettings(this.token) }, |