diff --git a/src/components/ConversationSettings/BanSettings/BannedItem.vue b/src/components/ConversationSettings/BanSettings/BannedItem.vue
index cddd48399db..2ffde1a5171 100644
--- a/src/components/ConversationSettings/BanSettings/BannedItem.vue
+++ b/src/components/ConversationSettings/BanSettings/BannedItem.vue
@@ -6,7 +6,7 @@
-
-
+ -
+ {{ item.label }}
+ {{ item.value }}
+
@@ -54,12 +56,12 @@ export default {
computed: {
banInfo() {
return [
- t('spreed', 'Banned by: {actor}', { actor: this.ban.actorId },
- undefined, { escape: false, sanitize: false }),
- t('spreed', 'Date: {date}', { date: moment(this.ban.bannedTime * 1000).format('lll') },
- undefined, { escape: false, sanitize: false }),
- t('spreed', 'Note: {note}', { note: this.ban.internalNote },
- undefined, { escape: false, sanitize: false }),
+ // TRANSLATORS name of a moderator who banned a participant
+ { label: t('spreed', 'Banned by:'), value: this.ban.moderatorDisplayName },
+ // TRANSLATORS Date and time of ban creation
+ { label: t('spreed', 'Date:'), value: moment(this.ban.bannedTime * 1000).format('lll') },
+ // TRANSLATORS Internal note for moderators, usually a reason for this ban
+ { label: t('spreed', 'Note:'), value: this.ban.internalNote },
]
},
},
diff --git a/src/components/RightSidebar/Participants/Participant.spec.js b/src/components/RightSidebar/Participants/Participant.spec.js
index b69bad0e19f..bd2689f1621 100644
--- a/src/components/RightSidebar/Participants/Participant.spec.js
+++ b/src/components/RightSidebar/Participants/Participant.spec.js
@@ -17,7 +17,7 @@ import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'
import NcInputField from '@nextcloud/vue/dist/Components/NcInputField.js'
-import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
+import NcTextArea from '@nextcloud/vue/dist/Components/NcTextArea.js'
import Participant from './Participant.vue'
import AvatarWrapper from '../../AvatarWrapper/AvatarWrapper.vue'
@@ -113,7 +113,7 @@ describe('Participant.vue', () => {
NcCheckboxRadioSwitch,
NcDialog,
NcInputField,
- NcTextField,
+ NcTextArea,
},
directives: {
tooltip: tooltipMock,
@@ -676,10 +676,10 @@ describe('Participant.vue', () => {
const checkbox = dialog.findComponent(NcCheckboxRadioSwitch)
await checkbox.find('input').trigger('change')
- const input = dialog.findComponent(NcTextField)
- expect(input.exists()).toBeTruthy()
- input.find('input').setValue(internalNote)
- await input.find('input').trigger('change')
+ const textarea = dialog.findComponent(NcTextArea)
+ expect(textarea.exists()).toBeTruthy()
+ textarea.find('textarea').setValue(internalNote)
+ await textarea.find('textarea').trigger('change')
const button = findNcButton(dialog, 'Remove')
await button.find('button').trigger('click')
@@ -766,12 +766,19 @@ describe('Participant.vue', () => {
await testCannotRemove()
})
- test('allows a moderator to ban a moderator', async () => {
+ test('allows a moderator to ban a user', async () => {
conversation.participantType = PARTICIPANT.TYPE.MODERATOR
participant.participantType = PARTICIPANT.TYPE.USER
await testCanBan()
})
+ test('allows a moderator to ban a federated user', async () => {
+ conversation.participantType = PARTICIPANT.TYPE.MODERATOR
+ participant.actorType = ATTENDEE.ACTOR_TYPE.FEDERATED_USERS
+ participant.participantType = PARTICIPANT.TYPE.USER
+ await testCanBan()
+ })
+
test('allows a moderator to ban a guest', async () => {
conversation.participantType = PARTICIPANT.TYPE.MODERATOR
participant.participantType = PARTICIPANT.TYPE.GUEST
diff --git a/src/components/RightSidebar/Participants/Participant.vue b/src/components/RightSidebar/Participants/Participant.vue
index 921258c3c02..835874cd1e3 100644
--- a/src/components/RightSidebar/Participants/Participant.vue
+++ b/src/components/RightSidebar/Participants/Participant.vue
@@ -318,17 +318,20 @@
{{ t('spreed', 'Also ban from this conversation') }}
-
-
+
{{ t('spreed', 'Dismiss') }}
-
+
{{ t('spreed', 'Remove') }}
@@ -376,7 +379,7 @@ import NcActionText from '@nextcloud/vue/dist/Components/NcActionText.js'
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcCheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch.js'
import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'
-import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
+import NcTextArea from '@nextcloud/vue/dist/Components/NcTextArea.js'
import Tooltip from '@nextcloud/vue/dist/Directives/Tooltip.js'
import ParticipantPermissionsEditor from './ParticipantPermissionsEditor.vue'
@@ -411,7 +414,7 @@ export default {
NcButton,
NcCheckboxRadioSwitch,
NcDialog,
- NcTextField,
+ NcTextArea,
ParticipantPermissionsEditor,
// Icons
Account,
@@ -488,6 +491,7 @@ export default {
isBanParticipant: false,
internalNote: '',
disabled: false,
+ isLoading: false,
}
},
@@ -796,10 +800,21 @@ export default {
return this.canBeModerated
&& !this.isModerator
&& (this.participant.actorType === ATTENDEE.ACTOR_TYPE.USERS
+ || this.participant.actorType === ATTENDEE.ACTOR_TYPE.FEDERATED_USERS
|| this.participant.actorType === ATTENDEE.ACTOR_TYPE.GUESTS
|| this.participant.actorType === ATTENDEE.ACTOR_TYPE.EMAILS)
},
+ maxLengthWarning() {
+ if (this.internalNote.length <= 4000) {
+ return ''
+ }
+ return t('spreed', 'The text must be less than or equal to {maxLength} characters long. Your current text is {charactersCount} characters long.', {
+ maxLength: 4000,
+ charactersCount: this.internalNote.length,
+ })
+ },
+
removeParticipantLabel() {
switch (this.participant.actorType) {
case ATTENDEE.ACTOR_TYPE.GROUPS:
@@ -995,15 +1010,22 @@ export default {
},
async removeParticipant() {
- await this.$store.dispatch('removeParticipant', {
- token: this.token,
- attendeeId: this.attendeeId,
- banParticipant: this.isBanParticipant,
- internalNote: this.internalNote,
- })
- this.isBanParticipant = false
- this.internalNote = ''
- this.isRemoveDialogOpen = false
+ this.isLoading = true
+ try {
+ await this.$store.dispatch('removeParticipant', {
+ token: this.token,
+ attendeeId: this.attendeeId,
+ banParticipant: this.isBanParticipant,
+ internalNote: this.internalNote,
+ })
+ this.isBanParticipant = false
+ this.internalNote = ''
+ this.isRemoveDialogOpen = false
+ } catch (error) {
+ console.error('Error while removing the participant: ', error)
+ } finally {
+ this.isLoading = false
+ }
},
grantAllPermissions() {
diff --git a/src/store/participantsStore.js b/src/store/participantsStore.js
index 05da627ad1b..514d50573b4 100644
--- a/src/store/participantsStore.js
+++ b/src/store/participantsStore.js
@@ -581,7 +581,7 @@ const actions = {
showSuccess(t('spreed', 'Participant is banned successfully'))
} catch (error) {
showError(t('spreed', 'Error while banning the participant'))
- console.error('Error while banning the participant: ', error)
+ throw error
}
}
await removeAttendeeFromConversation(token, attendeeId)
diff --git a/src/views/ForbiddenView.vue b/src/views/ForbiddenView.vue
index d44e077d291..69fbd099260 100644
--- a/src/views/ForbiddenView.vue
+++ b/src/views/ForbiddenView.vue
@@ -5,7 +5,7 @@
+ :description="t('spreed', 'Join a different conversation or start a new one.')">