Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat:select existing talk room for conversations on calendar events #6595

Merged
merged 1 commit into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
257 changes: 257 additions & 0 deletions src/components/Editor/AddTalkModal.vue
GretaD marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
@@ -0,0 +1,257 @@
<!--
- SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
- SPDX-License-Identifier: AGPL-3.0-or-later
-->

<template>
<NcModal size="normal"
class="modal"
:name="t('calendar', 'Select a Talk Room')"
@close="$emit('close', $event)">
<div class="modal-content">
<h2>{{ t('calendar', 'Add Talk conversation') }}</h2>
<div class="talk-room-list">
<NcEmptyContent v-if="loading"
icon="icon-loading"

Check warning on line 15 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L11-L15

Added lines #L11 - L15 were not covered by tests
class="modal__content__loading"
:description="t('calendar','Fetching Talk rooms...')" />
<NcEmptyContent v-else-if="talkConversations.length === 0"
:description="t('calendar','No Talk room available')" />
<ul v-else>
<li v-for="conversation in talkConversations"
:key="conversation.id"
:class="{ selected: selectedRoom && selectedRoom.id === conversation.id }"
class="talk-room-list__item"
@click="selectRoom(conversation)">
<NcAvatar :url="avatarUrl(conversation)"
:size="28"
:disable-tooltip="true" />
<span>{{ conversation.displayName }}</span>
</li>
</ul>
</div>
<div class="sticky-footer">
<NcButton class="talk_new-room" :disabled="creatingTalkRoom" @click="createTalkRoom">
<template #icon>
<IconAdd :size="20" />

Check warning on line 36 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L35-L36

Added lines #L35 - L36 were not covered by tests
</template>
{{ t('calendar', 'Create a new conversation') }}
</NcButton>
<NcButton type="primary"
class="talk_select-room"
:disabled="!selectedRoom"
@click="selectConversation(selectedRoom)">
{{ t('calendar', 'Select conversation') }}
</NcButton>
</div>
</div>
</NcModal>

Check warning on line 48 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L47-L48

Added lines #L47 - L48 were not covered by tests
</template>

<script>
import {

Check warning on line 52 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L51-L52

Added lines #L51 - L52 were not covered by tests
NcButton,
NcModal,
NcAvatar,
NcEmptyContent,
} from '@nextcloud/vue'
import axios from '@nextcloud/axios'

Check warning on line 58 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L56-L58

Added lines #L56 - L58 were not covered by tests
import { createTalkRoom, generateURLForToken } from '../../services/talkService.js'
import { showError, showSuccess } from '@nextcloud/dialogs'
import { generateOcsUrl } from '@nextcloud/router'
import IconAdd from 'vue-material-design-icons/Plus.vue'

Check warning on line 62 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L61-L62

Added lines #L61 - L62 were not covered by tests
import useCalendarObjectInstanceStore from '../../store/calendarObjectInstance.js'
import { mapStores } from 'pinia'

Check warning on line 64 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L64

Added line #L64 was not covered by tests

// Ref https://github.com/nextcloud/spreed/blob/main/docs/constants.md
const CONVERSATION_TYPE_GROUP = 2
const CONVERSATION_TYPE_PUBLIC = 3

Check warning on line 68 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L67-L68

Added lines #L67 - L68 were not covered by tests
const CONVERSATION_OBJECT_TYPE_VIDEO_VERIFICATION = 'share:password'
const PARTICIPANT_TYPE_OWNER = 1
const PARTICIPANT_TYPE_MODERATOR = 2

Check warning on line 72 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L70-L72

Added lines #L70 - L72 were not covered by tests
export default {
name: 'AddTalkModal',
components: {

Check warning on line 75 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L74-L75

Added lines #L74 - L75 were not covered by tests
NcButton,
NcModal,
IconAdd,

Check warning on line 78 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L78

Added line #L78 was not covered by tests
NcAvatar,
NcEmptyContent,
},
props: {
calendarObjectInstance: {
type: Object,

Check warning on line 84 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L82-L84

Added lines #L82 - L84 were not covered by tests
required: true,
},

Check warning on line 86 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L86

Added line #L86 was not covered by tests
conversations: {
type: Array,
required: true,
},

Check warning on line 90 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L90

Added line #L90 was not covered by tests
},
data() {

Check warning on line 92 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L92

Added line #L92 was not covered by tests
return {
talkConversations: [],
selectedConversation: null,

Check warning on line 95 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L94-L95

Added lines #L94 - L95 were not covered by tests
creatingTalkRoom: false,
selectedRoom: false,

Check warning on line 97 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L97

Added line #L97 was not covered by tests
loading: true,
}
},
computed: {
...mapStores(useCalendarObjectInstanceStore, ['calendarObjectInstance']),
},
async mounted() {

Check warning on line 104 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L100-L104

Added lines #L100 - L104 were not covered by tests
await this.fetchTalkConversations()
},

Check warning on line 106 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L106

Added line #L106 was not covered by tests
methods: {
avatarUrl(conversation) {
return generateOcsUrl('apps/spreed/api/v1/room/{token}/avatar', {
token: conversation.token,
})

Check warning on line 111 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L109-L111

Added lines #L109 - L111 were not covered by tests
},
async fetchTalkConversations() {
try {

Check warning on line 114 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L113-L114

Added lines #L113 - L114 were not covered by tests
const response = await axios.get(generateOcsUrl('apps/spreed/api/v4/room'))
this.talkConversations = response.data.ocs.data.filter(conversation =>
(conversation.participantType === PARTICIPANT_TYPE_OWNER
|| conversation.participantType === PARTICIPANT_TYPE_MODERATOR)

Check warning on line 118 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L117-L118

Added lines #L117 - L118 were not covered by tests
&& (conversation.type === CONVERSATION_TYPE_GROUP
|| (conversation.type === CONVERSATION_TYPE_PUBLIC

Check warning on line 120 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L120

Added line #L120 was not covered by tests
&& conversation.objectType !== CONVERSATION_OBJECT_TYPE_VIDEO_VERIFICATION)),
)
} catch (error) {
console.error('Error fetching Talk conversations:', error)

Check warning on line 124 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L123-L124

Added lines #L123 - L124 were not covered by tests
showError(this.$t('calendar', 'Error fetching Talk conversations.'))
} finally {
this.loading = false
}
},
selectRoom(conversation) {
this.selectedRoom = conversation
},

Check warning on line 132 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L129-L132

Added lines #L129 - L132 were not covered by tests

async selectConversation(conversation) {
try {
const url = generateURLForToken(conversation.token)

if (!url) {
showError(this.$t('calendar', 'Conversation does not have a valid URL.'))

Check warning on line 139 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L138-L139

Added lines #L138 - L139 were not covered by tests
return
}

if ((this.calendarObjectInstance.location ?? '').trim() === '') {
this.calendarObjectInstanceStore.changeLocation({
calendarObjectInstance: this.calendarObjectInstance,
location: url,
})
showSuccess(this.$t('calendar', 'Successfully added Talk room link to location.'))
} else {
const NEW_LINE = '\r\n'
const updatedDescription = this.calendarObjectInstance.description
? this.calendarObjectInstance.description + NEW_LINE + NEW_LINE + url

Check warning on line 152 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L152

Added line #L152 was not covered by tests
: url

this.calendarObjectInstanceStore.changeDescription({
calendarObjectInstance: this.calendarObjectInstance,
description: updatedDescription,
})
showSuccess(this.$t('calendar', 'Successfully added Talk room link to description.'))
}

Check warning on line 160 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L160

Added line #L160 was not covered by tests

this.selectedConversation = conversation
} catch (error) {
console.error('Error applying conversation to event:', error)
showError(this.$t('calendar', 'Failed to apply Talk room.'))

Check warning on line 165 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L165

Added line #L165 was not covered by tests
} finally {
this.closeModal()
}

Check warning on line 168 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L167-L168

Added lines #L167 - L168 were not covered by tests
},

async createTalkRoom() {
const NEW_LINE = '\r\n'
try {
this.creatingTalkRoom = true
const url = await createTalkRoom(
this.calendarObjectInstance.title,

Check warning on line 176 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L176

Added line #L176 was not covered by tests
this.calendarObjectInstance.description,
)

if (!url) {

Check warning on line 180 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L179-L180

Added lines #L179 - L180 were not covered by tests
throw new Error('No URL returned from createTalkRoom')
}

if ((this.calendarObjectInstance.location ?? '').trim() === '') {
this.$emit('update-location', url)
showSuccess(this.$t('calendar', 'Successfully added Talk room link to location.'))
} else {
const newDescription = this.calendarObjectInstance.description
? this.calendarObjectInstance.description + NEW_LINE + NEW_LINE + url + NEW_LINE
: url

this.$emit('update-description', newDescription)
showSuccess(this.$t('calendar', 'Successfully added Talk room link to description.'))
}
} catch (error) {
console.error('Error creating Talk room:', error)
showError(this.$t('calendar', 'Error creating Talk room.'))
} finally {
this.creatingTalkRoom = false
}
},
closeModal() {
this.$emit('close')
},
},
}
</script>

<style lang="scss" scoped>
.talk-room-list {
flex: 1;
overflow-y: auto;
padding: 10px;
font-weight: 600;

&__item {
display: flex;
gap: calc(var(--default-grid-baseline) * 2);

Check warning on line 218 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L217-L218

Added lines #L217 - L218 were not covered by tests
align-items: center;
padding: 6px 6px 6px 9px;
height: 34px;
&:hover {
background-color: var(--color-background-hover);
border-radius: var(--border-radius-large);

}
&.selected {
background-color: var(--color-primary-element);
border-radius: var(--border-radius-large);
color: white;
}
}
}

.sticky-footer {
position: sticky;
bottom: 0;
padding: 16px;
text-align: right;
display: flex;

Check warning on line 240 in src/components/Editor/AddTalkModal.vue

View check run for this annotation

Codecov / codecov/patch

src/components/Editor/AddTalkModal.vue#L239-L240

Added lines #L239 - L240 were not covered by tests
}
.talk_new-room {
margin-right: auto;
}

.talk_select-room {
margin-left: auto;
}

h2 {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
height: 30px;
}
</style>
2 changes: 1 addition & 1 deletion src/services/talkService.js
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@
* @param {string} token The token to the call room
* @return {string}
*/
function generateURLForToken(token = '') {
export function generateURLForToken(token = '') {

Check warning on line 129 in src/services/talkService.js

View check run for this annotation

Codecov / codecov/patch

src/services/talkService.js#L129

Added line #L129 was not covered by tests
return window.location.protocol + '//' + window.location.host + generateUrl('/call/' + token)
}

Expand Down
2 changes: 1 addition & 1 deletion src/store/calendarObjectInstance.js
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ export default defineStore('calendarObjectInstance', {
* @param {string=} data.language Preferred language of the attendee
* @param {string=} data.timezoneId Preferred timezone of the attendee
* @param {object=} data.organizer Principal of the organizer to be set if not present
* @param {string|array} data.member Group membership(s)
* @param {string | Array} data.member Group membership(s)
*/
addAttendee({
calendarObjectInstance,
Expand Down
Loading
Loading