mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-13 07:46:06 +00:00
Merge branch 'master' into fix-message-me-color
This commit is contained in:
commit
6ab4b016ea
@ -8,6 +8,7 @@
|
||||
# TODO change this to last message date
|
||||
enum _RoomOrdering {
|
||||
lastMessageAt_desc
|
||||
createdAt_desc
|
||||
}
|
||||
|
||||
type Room {
|
||||
|
||||
67
webapp/components/Chat/AddChatRoomByUserSearch.vue
Normal file
67
webapp/components/Chat/AddChatRoomByUserSearch.vue
Normal file
@ -0,0 +1,67 @@
|
||||
<template>
|
||||
<div class="add-chat-room-by-user-search">
|
||||
<ds-flex class="headline">
|
||||
<h2 class="title">{{ $t('chat.addRoomHeadline') }}</h2>
|
||||
<base-button class="close-button" icon="close" circle @click="closeUserSearch" />
|
||||
</ds-flex>
|
||||
<ds-space margin-bottom="small" />
|
||||
<ds-space>
|
||||
<select-user-search :id="id" ref="selectUserSearch" @select-user="selectUser" />
|
||||
</ds-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import SelectUserSearch from '~/components/generic/SelectUserSearch/SelectUserSearch'
|
||||
|
||||
export default {
|
||||
name: 'AddChatRoomByUserSearch',
|
||||
components: {
|
||||
SelectUserSearch,
|
||||
},
|
||||
props: {
|
||||
// chatRooms: {
|
||||
// type: Array,
|
||||
// default: [],
|
||||
// },
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
id: 'search-user-to-add-to-group',
|
||||
user: {},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
selectUser(user) {
|
||||
this.user = user
|
||||
// if (this.groupMembers.find((member) => member.id === this.user.id)) {
|
||||
// this.$toast.error(this.$t('group.errors.userAlreadyMember', { name: this.user.name }))
|
||||
// this.$refs.selectUserSearch.clear()
|
||||
// return
|
||||
// }
|
||||
this.$refs.selectUserSearch.clear()
|
||||
this.$emit('close-user-search')
|
||||
this.addChatRoom(this.user?.id)
|
||||
},
|
||||
async addChatRoom(userId) {
|
||||
this.$emit('add-chat-room', userId)
|
||||
},
|
||||
closeUserSearch() {
|
||||
this.$emit('close-user-search')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.add-chat-room-by-user-search {
|
||||
background-color: white;
|
||||
padding: $space-base;
|
||||
}
|
||||
.ds-flex.headline {
|
||||
justify-content: space-between;
|
||||
}
|
||||
.ds-flex.headline .close-button {
|
||||
margin-top: -6px;
|
||||
}
|
||||
</style>
|
||||
@ -19,12 +19,13 @@
|
||||
show-audio="false"
|
||||
:styles="JSON.stringify(computedChatStyle)"
|
||||
:show-footer="true"
|
||||
@send-message="sendMessage($event.detail[0])"
|
||||
@fetch-messages="fetchMessages($event.detail[0])"
|
||||
@fetch-more-rooms="fetchRooms"
|
||||
:responsive-breakpoint="responsiveBreakpoint"
|
||||
:single-room="singleRoom"
|
||||
show-reaction-emojis="false"
|
||||
@send-message="sendMessage($event.detail[0])"
|
||||
@fetch-messages="fetchMessages($event.detail[0])"
|
||||
@fetch-more-rooms="fetchRooms"
|
||||
@add-room="toggleUserSearch"
|
||||
@show-demo-options="showDemoOptions = $event"
|
||||
>
|
||||
<div
|
||||
@ -172,22 +173,7 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
if (this.singleRoom) {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: createRoom(),
|
||||
variables: {
|
||||
userId: this.roomId,
|
||||
},
|
||||
})
|
||||
.then(({ data: { CreateRoom } }) => {
|
||||
this.fetchRooms({ room: CreateRoom })
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$toast.error(error)
|
||||
})
|
||||
.finally(() => {
|
||||
// this.loading = false
|
||||
})
|
||||
this.newRoom(this.roomId)
|
||||
} else {
|
||||
this.fetchRooms()
|
||||
}
|
||||
@ -250,9 +236,10 @@ export default {
|
||||
commitUnreadRoomCount: 'chat/UPDATE_ROOM_COUNT',
|
||||
commitRoomIdFromSingleRoom: 'chat/UPDATE_ROOM_ID',
|
||||
}),
|
||||
async fetchRooms({ room, options = {} } = {}) {
|
||||
this.roomsLoaded = options.refetch ? this.roomsLoaded : false
|
||||
const offset = (options.refetch ? 0 : this.roomPage) * this.roomPageSize
|
||||
|
||||
async fetchRooms({ room } = {}) {
|
||||
this.roomsLoaded = false
|
||||
const offset = this.roomPage * this.roomPageSize
|
||||
try {
|
||||
const {
|
||||
data: { Room },
|
||||
@ -270,17 +257,7 @@ export default {
|
||||
const rmsIds = []
|
||||
;[...Room, ...this.rooms].forEach((r) => {
|
||||
if (!rmsIds.find((v) => v === r.id)) {
|
||||
rms.push({
|
||||
...r,
|
||||
index: r.lastMessage?.date,
|
||||
lastMessage: {
|
||||
...r.lastMessage,
|
||||
content: r.lastMessage?.content.trim().substring(0, 30),
|
||||
},
|
||||
users: r.users.map((u) => {
|
||||
return { ...u, username: u.name, avatar: u.avatar?.url }
|
||||
}),
|
||||
})
|
||||
rms.push(this.fixRoomObject(r))
|
||||
rmsIds.push(r.id)
|
||||
}
|
||||
})
|
||||
@ -401,6 +378,10 @@ export default {
|
||||
const changedRoom = { ...this.rooms[roomIndex] }
|
||||
changedRoom.lastMessage = createdMessage
|
||||
changedRoom.lastMessage.content = changedRoom.lastMessage.content.trim().substring(0, 30)
|
||||
// move current room to top (not 100% working)
|
||||
// const rooms = [...this.rooms]
|
||||
// rooms.splice(roomIndex,1)
|
||||
// this.rooms = [changedRoom, ...rooms]
|
||||
this.rooms[roomIndex] = changedRoom
|
||||
} catch (error) {
|
||||
this.$toast.error(error.message)
|
||||
@ -415,6 +396,58 @@ export default {
|
||||
if (!fullname) return
|
||||
return fullname.match(/\b\w/g).join('').substring(0, 3).toUpperCase()
|
||||
},
|
||||
|
||||
toggleUserSearch() {
|
||||
this.$emit('toggle-user-search')
|
||||
},
|
||||
|
||||
fixRoomObject(room) {
|
||||
// This fixes the room object which arrives from the backend
|
||||
const fixedRoom = {
|
||||
...room,
|
||||
index: room.lastMessage ? room.lastMessage.date : room.createdAt,
|
||||
lastMessage: room.lastMessage
|
||||
? {
|
||||
...room.lastMessage,
|
||||
content: room.lastMessage?.content?.trim().substring(0, 30),
|
||||
}
|
||||
: null,
|
||||
users: room.users.map((u) => {
|
||||
return { ...u, username: u.name, avatar: u.avatar?.url }
|
||||
}),
|
||||
}
|
||||
if (!fixedRoom.avatar) {
|
||||
// as long as we cannot query avatar on CreateRoom
|
||||
fixedRoom.avatar = fixedRoom.users.find((u) => u.id !== this.currentUser.id).avatar
|
||||
}
|
||||
return fixedRoom
|
||||
},
|
||||
|
||||
newRoom(userId) {
|
||||
this.$apollo
|
||||
.mutate({
|
||||
mutation: createRoom(),
|
||||
variables: {
|
||||
userId,
|
||||
},
|
||||
})
|
||||
.then(({ data: { CreateRoom } }) => {
|
||||
const roomIndex = this.rooms.findIndex((r) => r.id === CreateRoom.roomId)
|
||||
const room = this.fixRoomObject(CreateRoom)
|
||||
|
||||
if (roomIndex === -1) {
|
||||
this.rooms = [room, ...this.rooms]
|
||||
}
|
||||
this.fetchMessages({ room, options: { refetch: true } })
|
||||
this.$emit('show-chat', CreateRoom.id)
|
||||
})
|
||||
.catch((error) => {
|
||||
this.$toast.error(error.message)
|
||||
})
|
||||
.finally(() => {
|
||||
// this.loading = false
|
||||
})
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@ -3,33 +3,7 @@
|
||||
<h2 class="title">{{ $t('group.addUser') }}</h2>
|
||||
<ds-space margin-bottom="small" />
|
||||
<ds-space>
|
||||
<ds-select
|
||||
type="search"
|
||||
icon="search"
|
||||
label-prop="id"
|
||||
v-model="query"
|
||||
:id="id"
|
||||
:icon-right="null"
|
||||
:options="users"
|
||||
:loading="$apollo.queries.searchUsers.loading"
|
||||
:filter="(item) => item"
|
||||
:no-options-available="$t('group.addUserNoOptions')"
|
||||
:auto-reset-search="true"
|
||||
:placeholder="$t('group.addUserPlaceholder')"
|
||||
@focus.capture.native="onFocus"
|
||||
@input.native="handleInput"
|
||||
@keyup.enter.native="onEnter"
|
||||
@keyup.delete.native="onDelete"
|
||||
@keyup.esc.native="clear"
|
||||
@blur.capture.native="onBlur"
|
||||
@input.exact="onSelect"
|
||||
>
|
||||
<template #option="{ option }">
|
||||
<p>
|
||||
<user-teaser :user="option" :showPopover="false" :linkToProfile="false" />
|
||||
</p>
|
||||
</template>
|
||||
</ds-select>
|
||||
<select-user-search :id="id" ref="selectUserSearch" @select-user="selectUser" />
|
||||
<ds-modal
|
||||
v-if="isOpen"
|
||||
force
|
||||
@ -49,16 +23,15 @@
|
||||
</ds-space>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { changeGroupMemberRoleMutation } from '~/graphql/groups.js'
|
||||
import { searchUsers } from '~/graphql/Search.js'
|
||||
import UserTeaser from '~/components/UserTeaser/UserTeaser.vue'
|
||||
import { isEmpty } from 'lodash'
|
||||
import SelectUserSearch from '~/components/generic/SelectUserSearch/SelectUserSearch'
|
||||
|
||||
export default {
|
||||
name: 'AddGroupMember',
|
||||
components: {
|
||||
UserTeaser,
|
||||
SelectUserSearch,
|
||||
},
|
||||
props: {
|
||||
groupId: {
|
||||
@ -72,62 +45,34 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
users: [],
|
||||
id: 'search-user-to-add-to-group',
|
||||
query: '',
|
||||
user: {},
|
||||
isOpen: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
startSearch() {
|
||||
return this.query && this.query.length > 3
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
cancelModal() {
|
||||
this.clear()
|
||||
this.$refs.selectUserSearch.clear()
|
||||
this.isOpen = false
|
||||
},
|
||||
closeModal() {
|
||||
this.clear()
|
||||
this.$refs.selectUserSearch.clear()
|
||||
this.isOpen = false
|
||||
},
|
||||
confirmModal() {
|
||||
this.addMemberToGroup()
|
||||
this.isOpen = false
|
||||
this.clear()
|
||||
this.$refs.selectUserSearch.clear()
|
||||
},
|
||||
onFocus() {},
|
||||
onBlur() {
|
||||
this.query = ''
|
||||
},
|
||||
handleInput(event) {
|
||||
this.query = event.target ? event.target.value.trim() : ''
|
||||
},
|
||||
onDelete(event) {
|
||||
const value = event.target ? event.target.value.trim() : ''
|
||||
if (isEmpty(value)) {
|
||||
this.clear()
|
||||
} else {
|
||||
this.handleInput(event)
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
this.query = ''
|
||||
this.user = {}
|
||||
this.users = []
|
||||
},
|
||||
onSelect(item) {
|
||||
this.user = item
|
||||
selectUser(user) {
|
||||
this.user = user
|
||||
if (this.groupMembers.find((member) => member.id === this.user.id)) {
|
||||
this.$toast.error(this.$t('group.errors.userAlreadyMember', { name: this.user.name }))
|
||||
this.clear()
|
||||
this.$refs.selectUserSearch.clear()
|
||||
return
|
||||
}
|
||||
this.isOpen = true
|
||||
},
|
||||
onEnter() {},
|
||||
async addMemberToGroup() {
|
||||
const newRole = 'usual'
|
||||
const username = this.user.name
|
||||
@ -148,29 +93,9 @@ export default {
|
||||
}
|
||||
},
|
||||
},
|
||||
apollo: {
|
||||
searchUsers: {
|
||||
query() {
|
||||
return searchUsers
|
||||
},
|
||||
variables() {
|
||||
return {
|
||||
query: this.query,
|
||||
firstUsers: 5,
|
||||
usersOffset: 0,
|
||||
}
|
||||
},
|
||||
skip() {
|
||||
return !this.startSearch
|
||||
},
|
||||
update({ searchUsers }) {
|
||||
this.users = searchUsers.users
|
||||
},
|
||||
fetchPolicy: 'cache-and-network',
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.add-group-member {
|
||||
background-color: white;
|
||||
|
||||
109
webapp/components/generic/SelectUserSearch/SelectUserSearch.vue
Normal file
109
webapp/components/generic/SelectUserSearch/SelectUserSearch.vue
Normal file
@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<ds-select
|
||||
class="select-user-search"
|
||||
type="search"
|
||||
icon="search"
|
||||
label-prop="id"
|
||||
v-model="query"
|
||||
:id="id"
|
||||
:icon-right="null"
|
||||
:options="users"
|
||||
:loading="$apollo.queries.searchUsers.loading"
|
||||
:filter="(item) => item"
|
||||
:no-options-available="$t('group.addUserNoOptions')"
|
||||
:auto-reset-search="true"
|
||||
:placeholder="$t('group.addUserPlaceholder')"
|
||||
@focus.capture.native="onFocus"
|
||||
@input.native="handleInput"
|
||||
@keyup.enter.native="onEnter"
|
||||
@keyup.delete.native="onDelete"
|
||||
@keyup.esc.native="clear"
|
||||
@blur.capture.native="onBlur"
|
||||
@input.exact="onSelect"
|
||||
>
|
||||
<template #option="{ option }">
|
||||
<p>
|
||||
<user-teaser :user="option" :showPopover="false" :linkToProfile="false" />
|
||||
</p>
|
||||
</template>
|
||||
</ds-select>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { isEmpty } from 'lodash'
|
||||
import { searchUsers } from '~/graphql/Search.js'
|
||||
import UserTeaser from '~/components/UserTeaser/UserTeaser.vue'
|
||||
|
||||
export default {
|
||||
name: 'SelectUserSearch',
|
||||
components: {
|
||||
UserTeaser,
|
||||
},
|
||||
props: {
|
||||
id: {
|
||||
type: String,
|
||||
required: true,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
users: [],
|
||||
query: '',
|
||||
user: {},
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
startSearch() {
|
||||
return this.query && this.query.length > 3
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
onFocus() {},
|
||||
onBlur() {
|
||||
this.query = ''
|
||||
},
|
||||
handleInput(event) {
|
||||
this.query = event.target ? event.target.value.trim() : ''
|
||||
},
|
||||
onDelete(event) {
|
||||
const value = event.target ? event.target.value.trim() : ''
|
||||
if (isEmpty(value)) {
|
||||
this.clear()
|
||||
} else {
|
||||
this.handleInput(event)
|
||||
}
|
||||
},
|
||||
clear() {
|
||||
this.query = ''
|
||||
this.user = {}
|
||||
this.users = []
|
||||
},
|
||||
onSelect(item) {
|
||||
this.user = item
|
||||
this.$emit('select-user', this.user)
|
||||
},
|
||||
onEnter() {},
|
||||
},
|
||||
apollo: {
|
||||
searchUsers: {
|
||||
query() {
|
||||
return searchUsers
|
||||
},
|
||||
variables() {
|
||||
return {
|
||||
query: this.query,
|
||||
firstUsers: 5,
|
||||
usersOffset: 0,
|
||||
}
|
||||
},
|
||||
skip() {
|
||||
return !this.startSearch
|
||||
},
|
||||
update({ searchUsers }) {
|
||||
this.users = searchUsers.users
|
||||
},
|
||||
fetchPolicy: 'cache-and-network',
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
@ -5,18 +5,32 @@ export const createRoom = () => gql`
|
||||
CreateRoom(userId: $userId) {
|
||||
id
|
||||
roomId
|
||||
roomName
|
||||
lastMessageAt
|
||||
createdAt
|
||||
unreadCount
|
||||
#avatar
|
||||
users {
|
||||
_id
|
||||
id
|
||||
name
|
||||
avatar {
|
||||
url
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`
|
||||
|
||||
export const roomQuery = () => gql`
|
||||
query Room($first: Int, $offset: Int, $id: ID) {
|
||||
Room(first: $first, offset: $offset, id: $id, orderBy: lastMessageAt_desc) {
|
||||
Room(first: $first, offset: $offset, id: $id, orderBy: [createdAt_desc, lastMessageAt_desc]) {
|
||||
id
|
||||
roomId
|
||||
roomName
|
||||
avatar
|
||||
lastMessageAt
|
||||
createdAt
|
||||
unreadCount
|
||||
lastMessage {
|
||||
_id
|
||||
|
||||
@ -78,6 +78,7 @@
|
||||
}
|
||||
},
|
||||
"chat": {
|
||||
"addRoomHeadline": "Suche Nutzer für neuen Chat",
|
||||
"cancelSelectMessage": "Abbrechen",
|
||||
"conversationStarted": "Unterhaltung startete am:",
|
||||
"isOnline": "online",
|
||||
|
||||
@ -78,6 +78,7 @@
|
||||
}
|
||||
},
|
||||
"chat": {
|
||||
"addRoomHeadline": "Search User for new Chat",
|
||||
"cancelSelectMessage": "Cancel",
|
||||
"conversationStarted": "Conversation started on:",
|
||||
"isOnline": "is online",
|
||||
@ -475,7 +476,7 @@
|
||||
"addMemberToGroupSuccess": "“{name}” was added to the group with the role “{role}”!",
|
||||
"addUser": "Add User",
|
||||
"addUserNoOptions": "No users found!",
|
||||
"addUserPlaceholder": " Username",
|
||||
"addUserPlaceholder": "User name",
|
||||
"allGroups": "All Groups",
|
||||
"button": {
|
||||
"tooltip": "Show groups"
|
||||
|
||||
@ -1,16 +1,36 @@
|
||||
<template>
|
||||
<div>
|
||||
<ds-heading tag="h1">{{ $t('chat.page.headline') }}</ds-heading>
|
||||
<chat :roomId="getShowChat.showChat ? getShowChat.roomID : null" />
|
||||
<add-chat-room-by-user-search
|
||||
v-if="showUserSearch"
|
||||
@add-chat-room="addChatRoom"
|
||||
@close-user-search="showUserSearch = false"
|
||||
/>
|
||||
<ds-space margin-bottom="small" />
|
||||
<chat
|
||||
:roomId="getShowChat.showChat ? getShowChat.roomID : null"
|
||||
ref="chat"
|
||||
@toggle-user-search="showUserSearch = !showUserSearch"
|
||||
:show-room="showRoom"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import AddChatRoomByUserSearch from '~/components/Chat/AddChatRoomByUserSearch'
|
||||
import Chat from '../components/Chat/Chat.vue'
|
||||
|
||||
export default {
|
||||
components: { Chat },
|
||||
components: {
|
||||
AddChatRoomByUserSearch,
|
||||
Chat,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
showUserSearch: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.showChat({ showChat: false, roomID: null })
|
||||
},
|
||||
@ -23,6 +43,12 @@ export default {
|
||||
...mapMutations({
|
||||
showChat: 'chat/SET_OPEN_CHAT',
|
||||
}),
|
||||
addChatRoom(userID) {
|
||||
this.$refs.chat.newRoom(userID)
|
||||
},
|
||||
showRoom(roomId) {
|
||||
this.showChat({ showChat: true, roomID: roomId })
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user