summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorDorraJaouad <dorra.jaoued7@gmail.com>2023-07-07 12:27:53 +0200
committerMaksim Sukharev <antreesy.web@gmail.com>2023-08-03 08:28:06 +0200
commitde304d1e3971e248bb6ed7705f9bfa320bdc4055 (patch)
tree22069486965cb1277731ee418cc84c4144f08116 /src
parentdb952ee33d672335942d83edf483b194ab4f6680 (diff)
Add open conv list dialog
Signed-off-by: DorraJaouad <dorra.jaoued7@gmail.com> Improve the open conv list component and fix tests Signed-off-by: DorraJaouad <dorra.jaoued7@gmail.com>
Diffstat (limited to 'src')
-rw-r--r--src/components/LeftSidebar/LeftSidebar.spec.js10
-rw-r--r--src/components/LeftSidebar/LeftSidebar.vue65
-rw-r--r--src/components/LeftSidebar/NewGroupConversation/NewGroupConversation.vue14
-rw-r--r--src/components/LeftSidebar/OpenConversationsList/OpenConversationsList.vue82
-rw-r--r--src/views/RoomSelector.spec.js15
-rw-r--r--src/views/RoomSelector.vue57
6 files changed, 197 insertions, 46 deletions
diff --git a/src/components/LeftSidebar/LeftSidebar.spec.js b/src/components/LeftSidebar/LeftSidebar.spec.js
index ea73f4faa..ace133521 100644
--- a/src/components/LeftSidebar/LeftSidebar.spec.js
+++ b/src/components/LeftSidebar/LeftSidebar.spec.js
@@ -13,7 +13,7 @@ import router from '../../__mocks__/router.js'
import { searchPossibleConversations, searchListedConversations } from '../../services/conversationsService.js'
import { EventBus } from '../../services/EventBus.js'
import storeConfig from '../../store/storeConfig.js'
-import { findNcListItems } from '../../test-helpers.js'
+import { findNcListItems, findNcActionButton } from '../../test-helpers.js'
jest.mock('@nextcloud/initial-state', () => ({
loadState: jest.fn(),
@@ -709,16 +709,16 @@ describe('LeftSidebar.vue', () => {
loadStateSettings.start_conversations = true
const wrapper = mountComponent()
- const buttonEl = wrapper.findComponent({ name: 'NewGroupConversation' })
- expect(buttonEl.exists()).toBeTruthy()
+ const newConversationbutton = findNcActionButton(wrapper, 'Create a new conversation')
+ expect(newConversationbutton.exists()).toBeTruthy()
})
test('does not show new conversation button if user cannot start conversations', () => {
loadStateSettings.start_conversations = false
const wrapper = mountComponent()
- const buttonEl = wrapper.findComponent({ name: 'NewGroupConversation' })
- expect(buttonEl.exists()).toBeFalsy()
+ const newConversationbutton = findNcActionButton(wrapper, 'Create a new conversation')
+ expect(newConversationbutton.exists()).toBeFalsy()
})
})
diff --git a/src/components/LeftSidebar/LeftSidebar.vue b/src/components/LeftSidebar/LeftSidebar.vue
index 1d1b67a2c..3f10a2660 100644
--- a/src/components/LeftSidebar/LeftSidebar.vue
+++ b/src/components/LeftSidebar/LeftSidebar.vue
@@ -35,8 +35,8 @@
@keydown.enter.native="handleEnter"
@abort-search="abortSearch" />
- <!-- Options -->
- <div class="options"
+ <!-- Filters -->
+ <div class="filters"
:class="{'hidden-visually': isFocused}">
<NcActions class="filter-actions"
:primary="isFiltered !== null">
@@ -75,10 +75,36 @@
</NcActions>
</div>
- <!-- New Conversation -->
- <NewGroupConversation v-if="canStartConversations"
- ref="newGroupConversation"
- class="new-conversation__button" />
+ <!-- Actions -->
+ <div class="actions">
+ <NcActions class="conversations-actions">
+ <template #icon>
+ <DotsVertical :size="20" />
+ </template>
+ <NcActionButton close-after-click
+ @click="showModalListConversations">
+ <template #icon>
+ <List :size="20" />
+ </template>
+ {{ t('spreed','Join open conversations') }}
+ </NcActionButton>
+
+ <NcActionButton v-if="canStartConversations"
+ close-after-click
+ @click="showModalNewConversation">
+ <template #icon>
+ <Plus :size="20" />
+ </template>
+ {{ t('spreed','Create a new conversation') }}
+ </NcActionButton>
+ </NcActions>
+ </div>
+
+ <!-- All open conversations list -->
+ <OpenConversationsList ref="openConversationsList" />
+
+ <!-- New Conversation dialog-->
+ <NewGroupConversation ref="newGroupConversation" />
</div>
<template #list>
@@ -96,7 +122,7 @@
<LoadingPlaceholder type="conversations" />
</template>
<Hint v-else-if="noMatchFound"
- :hint="t('spreed', 'No matches')" />
+ :hint="t('spreed', 'No matches found')" />
<template v-if="isSearching">
<template v-if="!listedConversationsLoading && searchResultsListedConversations.length > 0">
<NcAppNavigationCaption :title="t('spreed', 'Open conversations')" />
@@ -182,9 +208,12 @@
import debounce from 'debounce'
import AtIcon from 'vue-material-design-icons/At.vue'
+import DotsVertical from 'vue-material-design-icons/DotsVertical.vue'
import FilterIcon from 'vue-material-design-icons/Filter.vue'
import FilterRemoveIcon from 'vue-material-design-icons/FilterRemove.vue'
+import List from 'vue-material-design-icons/FormatListBulleted.vue'
import MessageBadge from 'vue-material-design-icons/MessageBadge.vue'
+import Plus from 'vue-material-design-icons/Plus.vue'
import { showError } from '@nextcloud/dialogs'
import { emit } from '@nextcloud/event-bus'
@@ -203,6 +232,7 @@ import Hint from '../Hint.vue'
import LoadingPlaceholder from '../LoadingPlaceholder.vue'
import Conversation from './ConversationsList/Conversation.vue'
import NewGroupConversation from './NewGroupConversation/NewGroupConversation.vue'
+import OpenConversationsList from './OpenConversationsList/OpenConversationsList.vue'
import SearchBox from './SearchBox/SearchBox.vue'
import { CONVERSATION } from '../../constants.js'
@@ -225,6 +255,7 @@ export default {
Hint,
SearchBox,
NewGroupConversation,
+ OpenConversationsList,
Conversation,
LoadingPlaceholder,
NcListItem,
@@ -235,6 +266,9 @@ export default {
MessageBadge,
FilterIcon,
FilterRemoveIcon,
+ Plus,
+ List,
+ DotsVertical,
},
mixins: [
@@ -383,6 +417,15 @@ export default {
getFocusableList() {
return this.$el.querySelectorAll('li.acli_wrapper .acli')
},
+
+ showModalNewConversation() {
+ this.$refs.newGroupConversation.showModal()
+ },
+
+ showModalListConversations() {
+ this.$refs.openConversationsList.showModal()
+ },
+
setIsFocused(event) {
if (event.relatedTarget?.className.includes('input-field__clear-button') || this.searchText !== '') {
return
@@ -757,19 +800,19 @@ export default {
}
-.options{
+.filters {
position: absolute;
right : 52px; // New conversation button's width
display: flex;
height: var(--default-clickable-area);
}
-.new-conversation__button{
+.actions {
position: absolute;
- right: 1px;
+ right: 5px;
}
-.filter-actions__button--active{
+.filter-actions__button--active {
background-color: var(--color-primary-element-light);
border-radius: 6px;
:deep(.action-button__longtext){
diff --git a/src/components/LeftSidebar/NewGroupConversation/NewGroupConversation.vue b/src/components/LeftSidebar/NewGroupConversation/NewGroupConversation.vue
index 3a5a02958..c6e93eb4d 100644
--- a/src/components/LeftSidebar/NewGroupConversation/NewGroupConversation.vue
+++ b/src/components/LeftSidebar/NewGroupConversation/NewGroupConversation.vue
@@ -21,15 +21,6 @@
<template>
<div class="wrapper">
- <NcButton type="tertiary"
- class="toggle"
- :aria-label="t('spreed', 'Create a new group conversation')"
- :title="t('spreed', 'Create a new group conversation')"
- @click="showModal">
- <template #icon>
- <Plus :size="20" />
- </template>
- </NcButton>
<!-- New group form -->
<NcModal v-if="modal"
:container="container"
@@ -169,8 +160,6 @@
<script>
-import Plus from 'vue-material-design-icons/Plus.vue'
-
import { getCapabilities } from '@nextcloud/capabilities'
import { showError } from '@nextcloud/dialogs'
@@ -218,7 +207,6 @@ export default {
NcModal,
NcPasswordField,
NcTextField,
- Plus,
SetContacts,
},
@@ -305,7 +293,7 @@ export default {
})
},
},
- expose: ['showModalForItem'],
+ expose: ['showModalForItem','showModal'],
methods: {
showModal() {
diff --git a/src/components/LeftSidebar/OpenConversationsList/OpenConversationsList.vue b/src/components/LeftSidebar/OpenConversationsList/OpenConversationsList.vue
new file mode 100644
index 000000000..e9b68a9bb
--- /dev/null
+++ b/src/components/LeftSidebar/OpenConversationsList/OpenConversationsList.vue
@@ -0,0 +1,82 @@
+<!--
+ - @copyright Copyright (c) 2023
+ -
+ - @license GNU AGPL version 3 or any later version
+ -
+ - This program is free software: you can redistribute it and/or modify
+ - it under the terms of the GNU Affero General Public License as
+ - published by the Free Software Foundation, either version 3 of the
+ - License, or (at your option) any later version.
+ -
+ - This program is distributed in the hope that it will be useful,
+ - but WITHOUT ANY WARRANTY; without even the implied warranty of
+ - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ - GNU Affero General Public License for more details.
+ -
+ - You should have received a copy of the GNU Affero General Public License
+ - along with this program. If not, see <http://www.gnu.org/licenses/>.
+-->
+
+<template>
+ <RoomSelector v-if="modal"
+ :container="container"
+ list-open-conversations
+ show-postable-only
+ :dialog-title="dialogTitle"
+ @close="closeModal"
+ @select="openConversation" />
+</template>
+
+<script>
+
+import RoomSelector from '../../../views/RoomSelector.vue'
+
+export default {
+
+ name: 'OpenConversationsList',
+
+ components: {
+ RoomSelector,
+ },
+
+ data() {
+ return {
+ modal: false,
+ }
+ },
+
+ computed: {
+ container() {
+ return this.$store.getters.getMainContainerSelector()
+ },
+
+ dialogTitle() {
+ return t('spreed', 'Open conversations')
+ },
+
+ },
+
+ methods: {
+ showModal() {
+ this.modal = true
+ },
+
+ closeModal() {
+ this.modal = false
+ },
+
+ openConversation(token) {
+ this.$router.push({
+ name: 'conversation',
+ params: {
+ token: `${token}`,
+ },
+ }).catch(err => console.debug(`Error while pushing the new conversation's route: ${err}`))
+
+ this.closeModal()
+ },
+ },
+
+}
+
+</script>
diff --git a/src/views/RoomSelector.spec.js b/src/views/RoomSelector.spec.js
index e1124d445..3524fc9a0 100644
--- a/src/views/RoomSelector.spec.js
+++ b/src/views/RoomSelector.spec.js
@@ -1,4 +1,5 @@
import { shallowMount } from '@vue/test-utils'
+import flushPromises from 'flush-promises'
import axios from '@nextcloud/axios'
import { generateOcsUrl } from '@nextcloud/router'
@@ -85,10 +86,12 @@ describe('RoomSelector.vue', () => {
const wrapper = shallowMount(RoomSelector)
expect(axios.get).toHaveBeenCalledWith(
- generateOcsUrl('/apps/spreed/api/v4/room')
+ generateOcsUrl('/apps/spreed/api/v4/room'),
+ { params: { includeStatus: true } }
)
// need to wait for re-render, otherwise the list is not rendered yet
+ await flushPromises()
await wrapper.vm.$nextTick()
const list = wrapper.findAll('li')
@@ -103,12 +106,13 @@ describe('RoomSelector.vue', () => {
showPostableOnly: true,
},
})
-
expect(axios.get).toHaveBeenCalledWith(
- generateOcsUrl('/apps/spreed/api/v4/room')
+ generateOcsUrl('/apps/spreed/api/v4/room'),
+ { params: { includeStatus: true } }
)
// need to wait for re-render, otherwise the list is not rendered yet
+ await flushPromises()
await wrapper.vm.$nextTick()
const list = wrapper.findAll('li')
@@ -120,9 +124,10 @@ describe('RoomSelector.vue', () => {
const wrapper = shallowMount(RoomSelector)
expect(axios.get).toHaveBeenCalledWith(
- generateOcsUrl('/apps/spreed/api/v4/room')
+ generateOcsUrl('/apps/spreed/api/v4/room'),
+ { params: { includeStatus: true } }
)
-
+ await flushPromises()
await wrapper.vm.$nextTick()
const eventHandler = jest.fn()
diff --git a/src/views/RoomSelector.vue b/src/views/RoomSelector.vue
index c392ebf6f..b1ab2cbbb 100644
--- a/src/views/RoomSelector.vue
+++ b/src/views/RoomSelector.vue
@@ -53,8 +53,13 @@
<span>{{ room.displayName }}</span>
</li>
</ul>
- <div v-else-if="!loading">
- {{ t('spreed', 'No conversations found') }}
+ <div v-else-if="!loading" class="no-match-message">
+ <h2 class="no-match-title">
+ {{ noMatchFoundTitle }}
+ </h2>
+ <p v-if="noMatchFoundSubtitle" class="subtitle">
+ {{ noMatchFoundSubtitle }}
+ </p>
</div>
</div>
<div id="modal-buttons">
@@ -73,9 +78,6 @@
<script>
import Magnify from 'vue-material-design-icons/Magnify.vue'
-import axios from '@nextcloud/axios'
-import { generateOcsUrl } from '@nextcloud/router'
-
import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
import NcModal from '@nextcloud/vue/dist/Components/NcModal.js'
import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
@@ -83,6 +85,7 @@ import NcTextField from '@nextcloud/vue/dist/Components/NcTextField.js'
import ConversationIcon from '../components/ConversationIcon.vue'
import { CONVERSATION } from '../constants.js'
+import { searchListedConversations, fetchConversations } from '../services/conversationsService.js'
export default {
name: 'RoomSelector',
@@ -108,6 +111,7 @@ export default {
type: String,
default: '',
},
+
/**
* Whether to only show conversations to which
* the user can post messages.
@@ -116,6 +120,11 @@ export default {
type: Boolean,
default: false,
},
+
+ listOpenConversations: {
+ type: Boolean,
+ default: false,
+ },
},
emits: ['close', 'select'],
data() {
@@ -142,20 +151,34 @@ export default {
return roomsTemp.filter(room => room.displayName.toLowerCase().includes(this.searchText.toLowerCase()))
}
},
+
+ noMatchFoundTitle() {
+ return this.listOpenConversations
+ ? t('spreed', 'No open conversations found')
+ : t('spreed', 'No conversations found')
+ },
+
+ noMatchFoundSubtitle() {
+ return this.listOpenConversations
+ ? t('spreed', 'Either there are no open conversations or you joined all of them.')
+ : t('spreed', 'Check spelling or use complete words.')
+ },
},
- beforeMount() {
- this.fetchRooms()
+ async beforeMount() {
+ await this.fetchRooms()
const $store = OCA.Talk?.instance?.$store
if ($store) {
this.currentRoom = $store.getters.getToken()
}
},
methods: {
- fetchRooms() {
- axios.get(generateOcsUrl('/apps/spreed/api/v4/room')).then((response) => {
- this.rooms = response.data.ocs.data.sort(this.sortConversations)
- this.loading = false
- })
+ async fetchRooms() {
+ const response = this.listOpenConversations
+ ? await searchListedConversations({ searchText: '' }, {})
+ : await fetchConversations({})
+
+ this.rooms = response.data.ocs.data.sort(this.sortConversations)
+ this.loading = false
},
sortConversations(conversation1, conversation2) {
if (conversation1.isFavorite !== conversation2.isFavorite) {
@@ -221,6 +244,16 @@ export default {
height: 100%;
}
+.no-match-message{
+ padding: 40px 0;
+ text-align: center;
+
+}
+
+.no-match-title{
+ font-weight: normal;
+}
+
li {
padding: 6px;
border: 1px solid transparent;