mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
Merge branch 'master' into 6443-refactor-create-post-page
This commit is contained in:
commit
7f06d71f6a
@ -25,8 +25,8 @@ export default {
|
||||
chatMessageAdded: {
|
||||
subscribe: withFilter(
|
||||
() => pubsub.asyncIterator(CHAT_MESSAGE_ADDED),
|
||||
(payload, variables) => {
|
||||
return payload.userId === variables.userId
|
||||
(payload, variables, context) => {
|
||||
return payload.userId === context.user?.id
|
||||
},
|
||||
),
|
||||
},
|
||||
|
||||
@ -7,8 +7,8 @@ export default {
|
||||
notificationAdded: {
|
||||
subscribe: withFilter(
|
||||
() => pubsub.asyncIterator(NOTIFICATION_ADDED),
|
||||
(payload, variables) => {
|
||||
return payload.notificationAdded.to.id === variables.userId
|
||||
(payload, variables, context) => {
|
||||
return payload.notificationAdded.to.id === context.user?.id
|
||||
},
|
||||
),
|
||||
},
|
||||
|
||||
@ -20,8 +20,8 @@ export default {
|
||||
roomCountUpdated: {
|
||||
subscribe: withFilter(
|
||||
() => pubsub.asyncIterator(ROOM_COUNT_UPDATED),
|
||||
(payload, variables) => {
|
||||
return payload.userId === variables.userId
|
||||
(payload, variables, context) => {
|
||||
return payload.userId === context.user?.id
|
||||
},
|
||||
),
|
||||
},
|
||||
|
||||
@ -46,5 +46,5 @@ type Query {
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
chatMessageAdded(userId: ID!): Message
|
||||
chatMessageAdded: Message
|
||||
}
|
||||
|
||||
@ -38,5 +38,5 @@ type Mutation {
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
notificationAdded(userId: ID!): NOTIFIED
|
||||
notificationAdded: NOTIFIED
|
||||
}
|
||||
|
||||
@ -8,6 +8,7 @@
|
||||
# TODO change this to last message date
|
||||
enum _RoomOrdering {
|
||||
lastMessageAt_desc
|
||||
createdAt_desc
|
||||
}
|
||||
|
||||
type Room {
|
||||
@ -57,5 +58,5 @@ type Query {
|
||||
}
|
||||
|
||||
type Subscription {
|
||||
roomCountUpdated(userId: ID!): Int
|
||||
roomCountUpdated: Int
|
||||
}
|
||||
|
||||
@ -31,4 +31,7 @@
|
||||
chatMessageTimestamp: $chat-message-timestamp;
|
||||
chatMessageCheckmarkSeen: $chat-message-checkmark-seen;
|
||||
chatMessageCheckmark: $chat-message-checkmark;
|
||||
|
||||
chatRoomBackgroundCounterBadge: $chat-room-background-counter-badge;
|
||||
chatRoomColorCounterBadge: $chat-room-color-counter-badge;
|
||||
}
|
||||
@ -420,3 +420,5 @@ $chat-new-message-color: $color-secondary-active;
|
||||
$chat-message-timestamp: $text-color-soft;
|
||||
$chat-message-checkmark-seen: $text-color-secondary;
|
||||
$chat-message-checkmark: $text-color-soft;
|
||||
$chat-room-color-counter-badge: $text-color-inverse;
|
||||
$chat-room-background-counter-badge: $color-secondary;
|
||||
|
||||
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>
|
||||
@ -4,7 +4,7 @@
|
||||
<vue-advanced-chat
|
||||
:theme="theme"
|
||||
:current-user-id="currentUser.id"
|
||||
:room-id="!singleRoom ? roomId : null"
|
||||
:room-id="computedRoomId"
|
||||
:template-actions="JSON.stringify(templatesText)"
|
||||
:menu-actions="JSON.stringify(menuActions)"
|
||||
:text-messages="JSON.stringify(textMessages)"
|
||||
@ -19,18 +19,37 @@
|
||||
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 slot="menu-icon" @click.prevent.stop="$emit('close-single-room', true)">
|
||||
<div v-if="singleRoom">
|
||||
<ds-icon name="close"></ds-icon>
|
||||
</div>
|
||||
<div
|
||||
v-if="selectedRoom && selectedRoom.roomId"
|
||||
slot="room-options"
|
||||
class="chat-room-options"
|
||||
>
|
||||
<ds-flex v-if="singleRoom">
|
||||
<ds-flex-item centered class="single-chat-bubble">
|
||||
<nuxt-link :to="{ name: 'chat' }">
|
||||
<base-icon name="chat-bubble" />
|
||||
</nuxt-link>
|
||||
</ds-flex-item>
|
||||
<ds-flex-item centered>
|
||||
<div
|
||||
class="vac-svg-button vac-room-options"
|
||||
@click="$emit('close-single-room', true)"
|
||||
>
|
||||
<slot name="menu-icon">
|
||||
<ds-icon name="close" />
|
||||
</slot>
|
||||
</div>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</div>
|
||||
|
||||
<div slot="room-header-avatar">
|
||||
@ -89,11 +108,6 @@ export default {
|
||||
data() {
|
||||
return {
|
||||
menuActions: [
|
||||
// NOTE: if menuActions is empty, the related slot is not shown
|
||||
{
|
||||
name: 'dummyItem',
|
||||
title: 'Just a dummy item',
|
||||
},
|
||||
/*
|
||||
{
|
||||
name: 'inviteUser',
|
||||
@ -159,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()
|
||||
}
|
||||
@ -182,9 +181,6 @@ export default {
|
||||
// Subscriptions
|
||||
const observer = this.$apollo.subscribe({
|
||||
query: chatMessageAdded(),
|
||||
variables: {
|
||||
userId: this.currentUser.id,
|
||||
},
|
||||
})
|
||||
|
||||
observer.subscribe({
|
||||
@ -197,10 +193,24 @@ export default {
|
||||
computed: {
|
||||
...mapGetters({
|
||||
currentUser: 'auth/user',
|
||||
getStoreRoomId: 'chat/roomID',
|
||||
}),
|
||||
computedChatStyle() {
|
||||
return chatStyle.STYLE.light
|
||||
},
|
||||
computedRoomId() {
|
||||
let roomId = null
|
||||
|
||||
if (!this.singleRoom) {
|
||||
roomId = this.roomId
|
||||
|
||||
if (this.getStoreRoomId.roomId) {
|
||||
roomId = this.getStoreRoomId.roomId
|
||||
}
|
||||
}
|
||||
|
||||
return roomId
|
||||
},
|
||||
textMessages() {
|
||||
return {
|
||||
ROOMS_EMPTY: this.$t('chat.roomsEmpty'),
|
||||
@ -221,10 +231,12 @@ export default {
|
||||
methods: {
|
||||
...mapMutations({
|
||||
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 },
|
||||
@ -242,17 +254,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)
|
||||
}
|
||||
})
|
||||
@ -262,6 +264,13 @@ export default {
|
||||
this.roomsLoaded = true
|
||||
}
|
||||
this.roomPage += 1
|
||||
|
||||
if (this.singleRoom && this.rooms.length > 0) {
|
||||
this.commitRoomIdFromSingleRoom(this.rooms[0].roomId)
|
||||
} else if (this.getStoreRoomId.roomId) {
|
||||
// reset store room id
|
||||
this.commitRoomIdFromSingleRoom(null)
|
||||
}
|
||||
} catch (error) {
|
||||
this.rooms = []
|
||||
this.$toast.error(error.message)
|
||||
@ -366,6 +375,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)
|
||||
@ -380,6 +393,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>
|
||||
@ -408,4 +473,8 @@ body {
|
||||
transform: translate(-50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
.ds-flex-item.single-chat-bubble {
|
||||
margin-right: 1em;
|
||||
}
|
||||
</style>
|
||||
|
||||
@ -44,11 +44,6 @@ export default {
|
||||
},
|
||||
subscribeToMore: {
|
||||
document: roomCountUpdated(),
|
||||
variables() {
|
||||
return {
|
||||
userId: this.user.id,
|
||||
}
|
||||
},
|
||||
updateQuery: (previousResult, { subscriptionData }) => {
|
||||
return { UnreadRooms: subscriptionData.data.roomCountUpdated }
|
||||
},
|
||||
|
||||
@ -8,7 +8,6 @@
|
||||
:disabled="disabled && !update"
|
||||
@click="handleCancel"
|
||||
data-test="cancel-button"
|
||||
danger
|
||||
>
|
||||
{{ $t('actions.cancel') }}
|
||||
</base-button>
|
||||
|
||||
@ -58,14 +58,14 @@ export default {
|
||||
routes.push({
|
||||
label: this.$t('group.contentMenu.visitGroupPage'),
|
||||
icon: 'home',
|
||||
name: 'group-id-slug',
|
||||
path: `/groups/${this.group.id}`,
|
||||
params: { id: this.group.id, slug: this.group.slug },
|
||||
})
|
||||
}
|
||||
if (this.group.myRole === 'owner') {
|
||||
routes.push({
|
||||
label: this.$t('admin.settings.name'),
|
||||
path: `/group/edit/${this.group.id}`,
|
||||
path: `/groups/edit/${this.group.id}`,
|
||||
icon: 'edit',
|
||||
})
|
||||
}
|
||||
|
||||
@ -173,12 +173,7 @@
|
||||
</ds-flex-item>
|
||||
<ds-flex-item width="0.15" />
|
||||
<ds-flex-item class="action-buttons-group" width="2">
|
||||
<base-button
|
||||
data-test="cancel-button"
|
||||
:disabled="loading"
|
||||
@click="$router.back()"
|
||||
danger
|
||||
>
|
||||
<base-button data-test="cancel-button" :disabled="loading" @click="$router.back()">
|
||||
{{ $t('actions.cancel') }}
|
||||
</base-button>
|
||||
<base-button type="submit" icon="check" :loading="loading" :disabled="errors" filled>
|
||||
|
||||
@ -28,10 +28,10 @@ import { replace, build } from 'xregexp/xregexp-all.js'
|
||||
|
||||
import * as key from '../../constants/keycodes'
|
||||
import { HASHTAG, MENTION } from '../../constants/editor'
|
||||
import defaultExtensions from './defaultExtensions.js'
|
||||
import EventHandler from './plugins/eventHandler.js'
|
||||
import Hashtag from './nodes/Hashtag.js'
|
||||
import Mention from './nodes/Mention.js'
|
||||
import defaultExtensions from './defaultExtensions'
|
||||
import EventHandler from './plugins/eventHandler'
|
||||
import Hashtag from './nodes/Hashtag'
|
||||
import Mention from './nodes/Mention'
|
||||
import MenuBar from './MenuBar'
|
||||
import ContextMenu from './ContextMenu'
|
||||
import SuggestionList from './SuggestionList'
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<nuxt-link
|
||||
class="group-teaser"
|
||||
:to="{ name: 'group-id-slug', params: { id: group.id, slug: group.slug } }"
|
||||
:to="{ name: 'groups-id-slug', params: { id: group.id, slug: group.slug } }"
|
||||
>
|
||||
<base-card
|
||||
:class="{
|
||||
|
||||
@ -9,7 +9,7 @@
|
||||
<p class="description">{{ $t(`notifications.reason.${notification.reason}`) }}</p>
|
||||
<nuxt-link
|
||||
class="link"
|
||||
:to="{ name: isGroup ? 'group-id-slug' : 'post-id-slug', params, ...hashParam }"
|
||||
:to="{ name: isGroup ? 'groups-id-slug' : 'post-id-slug', params, ...hashParam }"
|
||||
@click.native="$emit('read')"
|
||||
>
|
||||
<base-card wideContent>
|
||||
|
||||
@ -137,11 +137,6 @@ export default {
|
||||
},
|
||||
subscribeToMore: {
|
||||
document: notificationAdded(),
|
||||
variables() {
|
||||
return {
|
||||
userId: this.user.id,
|
||||
}
|
||||
},
|
||||
updateQuery: (previousResult, { subscriptionData }) => {
|
||||
const {
|
||||
data: { notificationAdded: newNotification },
|
||||
|
||||
@ -65,7 +65,7 @@
|
||||
class="notification-mention-post"
|
||||
:class="{ 'notification-status': notification.read }"
|
||||
:to="{
|
||||
name: isGroup(notification.from) ? 'group-id-slug' : 'post-id-slug',
|
||||
name: isGroup(notification.from) ? 'groups-id-slug' : 'post-id-slug',
|
||||
params: params(notification.from),
|
||||
hash: hashParam(notification.from),
|
||||
}"
|
||||
|
||||
@ -96,7 +96,7 @@ export default {
|
||||
groupLink() {
|
||||
const { id, slug } = this.group
|
||||
if (!(id && slug)) return ''
|
||||
return { name: 'group-id-slug', params: { slug, id } }
|
||||
return { name: 'groups-id-slug', params: { slug, id } }
|
||||
},
|
||||
groupSlug() {
|
||||
const { slug } = this.group || {}
|
||||
|
||||
@ -56,7 +56,7 @@
|
||||
>
|
||||
{{ isEditing ? $t('actions.save') : texts.addButton }}
|
||||
</base-button>
|
||||
<base-button v-if="isEditing" id="cancel" danger @click="handleCancel()">
|
||||
<base-button v-if="isEditing" id="cancel" @click="handleCancel()">
|
||||
{{ $t('actions.cancel') }}
|
||||
</base-button>
|
||||
</ds-space>
|
||||
|
||||
@ -148,7 +148,7 @@ export default {
|
||||
case 'User':
|
||||
return 'profile-id-slug'
|
||||
case 'Group':
|
||||
return 'group-id-slug'
|
||||
return 'groups-id-slug'
|
||||
default:
|
||||
return null
|
||||
}
|
||||
|
||||
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>
|
||||
@ -109,8 +109,8 @@ const STYLE = {
|
||||
colorTimestamp: '#a2aeb8',
|
||||
colorStateOnline: '#4caf50',
|
||||
colorStateOffline: '#9ca6af',
|
||||
backgroundCounterBadge: '#0696c7',
|
||||
colorCounterBadge: '#fff',
|
||||
backgroundCounterBadge: styleData.chatRoomBackgroundCounterBadge,
|
||||
colorCounterBadge: styleData.chatRoomColorCounterBadge,
|
||||
},
|
||||
|
||||
emoji: {
|
||||
|
||||
@ -54,8 +54,8 @@ export const messageQuery = () => {
|
||||
|
||||
export const chatMessageAdded = () => {
|
||||
return gql`
|
||||
subscription chatMessageAdded($userId: ID!) {
|
||||
chatMessageAdded(userId: $userId) {
|
||||
subscription chatMessageAdded {
|
||||
chatMessageAdded {
|
||||
_id
|
||||
id
|
||||
indexId
|
||||
|
||||
@ -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
|
||||
@ -52,8 +66,8 @@ export const unreadRoomsQuery = () => {
|
||||
|
||||
export const roomCountUpdated = () => {
|
||||
return gql`
|
||||
subscription roomCountUpdated($userId: ID!) {
|
||||
roomCountUpdated(userId: $userId)
|
||||
subscription roomCountUpdated {
|
||||
roomCountUpdated
|
||||
}
|
||||
`
|
||||
}
|
||||
|
||||
@ -245,8 +245,8 @@ export const notificationAdded = () => {
|
||||
${postFragment}
|
||||
${groupFragment}
|
||||
|
||||
subscription notifications($userId: ID!) {
|
||||
notificationAdded(userId: $userId) {
|
||||
subscription notifications {
|
||||
notificationAdded {
|
||||
id
|
||||
read
|
||||
reason
|
||||
|
||||
@ -78,6 +78,7 @@
|
||||
}
|
||||
},
|
||||
"chat": {
|
||||
"addRoomHeadline": "Suche Nutzer für neuen Chat",
|
||||
"cancelSelectMessage": "Abbrechen",
|
||||
"conversationStarted": "Unterhaltung startete am:",
|
||||
"isOnline": "online",
|
||||
@ -901,7 +902,7 @@
|
||||
"Tag": "Hashtag ::: Hashtags",
|
||||
"User": "Nutzer ::: Nutzer"
|
||||
},
|
||||
"hint": "Wonach suchst Du? Nutze !… für Beiträge, @… für Mitglieder, &… für Gruppen, #… für Hashtags",
|
||||
"hint": "!... sucht Beiträge, @... sucht Nutzer, &... sucht Gruppen, #… sucht Hashtags",
|
||||
"no-results": "Keine Ergebnisse für \"{search}\" gefunden. Versuch' es mit einem anderen Begriff!",
|
||||
"page": "Seite",
|
||||
"placeholder": "Suchen",
|
||||
|
||||
@ -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"
|
||||
@ -901,7 +902,7 @@
|
||||
"Tag": "Hashtag ::: Hashtags",
|
||||
"User": "User ::: Users"
|
||||
},
|
||||
"hint": "What are you searching for? Use !… for posts, @… for users, &… for groups, #… for hashtags.",
|
||||
"hint": "!... searches posts, @... searches users, &... searches groups, #… searches hashtags",
|
||||
"no-results": "No results found for \"{search}\". Try a different search term!",
|
||||
"page": "Page",
|
||||
"placeholder": "Search",
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -24,7 +24,7 @@ const options = {
|
||||
}
|
||||
`,
|
||||
message: 'error-pages.group-not-found',
|
||||
path: 'group',
|
||||
path: 'groups',
|
||||
}
|
||||
const persistentLinks = PersistentLinks(options)
|
||||
|
||||
@ -59,7 +59,7 @@ export default {
|
||||
})
|
||||
this.$toast.success(this.$t('group.groupCreated'))
|
||||
this.$router.history.push({
|
||||
name: 'group-id-slug',
|
||||
name: 'groups-id-slug',
|
||||
params: { id: responseId, slug: responseSlug },
|
||||
})
|
||||
} catch (error) {
|
||||
@ -33,11 +33,11 @@ export default {
|
||||
return [
|
||||
{
|
||||
name: this.$t('group.general'),
|
||||
path: `/group/edit/${this.group.id}`,
|
||||
path: `/groups/edit/${this.group.id}`,
|
||||
},
|
||||
{
|
||||
name: this.$t('group.members'),
|
||||
path: `/group/edit/${this.group.id}/members`,
|
||||
path: `/groups/edit/${this.group.id}/members`,
|
||||
},
|
||||
]
|
||||
},
|
||||
@ -60,7 +60,7 @@ export default {
|
||||
})
|
||||
this.$toast.success(this.$t('group.updatedGroup'))
|
||||
this.$router.history.push({
|
||||
name: 'group-id-slug',
|
||||
name: 'groups-id-slug',
|
||||
params: { id: responseId, slug: responseSlug },
|
||||
})
|
||||
} catch (error) {
|
||||
@ -1,5 +1,5 @@
|
||||
import { mount } from '@vue/test-utils'
|
||||
import groups from './groups.vue'
|
||||
import groups from './index.vue'
|
||||
|
||||
const localVue = global.localVue
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<ds-space>
|
||||
<!-- create group -->
|
||||
<ds-space centered>
|
||||
<nuxt-link :to="{ name: 'group-create' }">
|
||||
<nuxt-link :to="{ name: 'groups-create' }">
|
||||
<base-button
|
||||
class="group-add-button"
|
||||
icon="plus"
|
||||
@ -14,6 +14,9 @@ export const mutations = {
|
||||
UPDATE_ROOM_COUNT(state, count) {
|
||||
state.unreadRoomCount = count
|
||||
},
|
||||
UPDATE_ROOM_ID(state, roomid) {
|
||||
state.roomId = roomid || null
|
||||
},
|
||||
}
|
||||
|
||||
export const getters = {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user