mirror of
https://github.com/hcengineering/platform.git
synced 2024-11-22 11:42:30 +03:00
[UBER-781] Adding chats to inbox after sending messages (#3621)
Signed-off-by: Oleg Solodkov <oleg.solodkov@xored.com>
This commit is contained in:
parent
77f6b3dfd6
commit
04274d1167
@ -46,10 +46,11 @@ export function createModel (builder: Builder): void {
|
|||||||
})
|
})
|
||||||
|
|
||||||
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
|
||||||
trigger: serverChunter.trigger.OnDmCreate,
|
trigger: serverChunter.trigger.OnMessageSent,
|
||||||
txMatch: {
|
txMatch: {
|
||||||
objectClass: chunter.class.DirectMessage,
|
objectClass: chunter.class.DirectMessage,
|
||||||
_class: core.class.TxCreateDoc
|
_class: core.class.TxCollectionCUD,
|
||||||
|
collection: 'messages'
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -73,6 +73,7 @@
|
|||||||
"ConfigDescription": "Extension to perform text communications",
|
"ConfigDescription": "Extension to perform text communications",
|
||||||
"LastMessage": "Last message",
|
"LastMessage": "Last message",
|
||||||
"You": "You",
|
"You": "You",
|
||||||
"YouHaveStartedAConversation": "You have started a conversation"
|
"YouHaveJoinedTheConversation": "You have joined the conversation",
|
||||||
|
"NoMessages": "There are no messages yet"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -73,6 +73,7 @@
|
|||||||
"ConfigDescription": "Расширение для текстовых переписок",
|
"ConfigDescription": "Расширение для текстовых переписок",
|
||||||
"LastMessage": "Последнее сообщение",
|
"LastMessage": "Последнее сообщение",
|
||||||
"You": "Вы",
|
"You": "Вы",
|
||||||
"YouHaveStartedAConversation": "Вы начали диалог"
|
"YouHaveJoinedTheConversation": "Вы присоединились к диалогу",
|
||||||
|
"NoMessages": "Сообщений пока нет"
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -55,7 +55,7 @@
|
|||||||
<MessagePreview value={message} />
|
<MessagePreview value={message} />
|
||||||
{/each}
|
{/each}
|
||||||
{:else}
|
{:else}
|
||||||
<Label label={chunterResources.string.YouHaveStartedAConversation} />
|
<Label label={chunterResources.string.NoMessages} />
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -89,6 +89,7 @@ export default mergeIds(chunterId, chunter, {
|
|||||||
NoResults: '' as IntlString,
|
NoResults: '' as IntlString,
|
||||||
CopyLink: '' as IntlString,
|
CopyLink: '' as IntlString,
|
||||||
You: '' as IntlString,
|
You: '' as IntlString,
|
||||||
YouHaveStartedAConversation: '' as IntlString
|
YouHaveJoinedTheConversation: '' as IntlString,
|
||||||
|
NoMessages: '' as IntlString
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -190,8 +190,7 @@ export default plugin(chunterId, {
|
|||||||
DMNotification: '' as Ref<NotificationType>,
|
DMNotification: '' as Ref<NotificationType>,
|
||||||
MentionNotification: '' as Ref<NotificationType>,
|
MentionNotification: '' as Ref<NotificationType>,
|
||||||
ThreadNotification: '' as Ref<NotificationType>,
|
ThreadNotification: '' as Ref<NotificationType>,
|
||||||
ChannelNotification: '' as Ref<NotificationType>,
|
ChannelNotification: '' as Ref<NotificationType>
|
||||||
DMCreationNotification: '' as Ref<NotificationType>
|
|
||||||
},
|
},
|
||||||
app: {
|
app: {
|
||||||
Chunter: '' as Ref<Doc>
|
Chunter: '' as Ref<Doc>
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
"Change": "Change",
|
"Change": "Change",
|
||||||
"AddedRemoved": "Added/removed",
|
"AddedRemoved": "Added/removed",
|
||||||
"YouAddedCollaborators": "You have been added to collaborators",
|
"YouAddedCollaborators": "You have been added to collaborators",
|
||||||
"YouHaveStartedAConversation": "You have started a conversation",
|
"YouHaveJoinedTheConversation": "You have joined the conversation",
|
||||||
"ChangeCollaborators": "changed collaborators",
|
"ChangeCollaborators": "changed collaborators",
|
||||||
"Activity": "Activity",
|
"Activity": "Activity",
|
||||||
"People": "People",
|
"People": "People",
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
"Change": "Изменено",
|
"Change": "Изменено",
|
||||||
"AddedRemoved": "Добавлено/удалено",
|
"AddedRemoved": "Добавлено/удалено",
|
||||||
"YouAddedCollaborators": "Вы были добавлены как участник",
|
"YouAddedCollaborators": "Вы были добавлены как участник",
|
||||||
"YouHaveStartedAConversation": "Вы начали диалог",
|
"YouHaveJoinedTheConversation": "Вы присоединились к диалогу",
|
||||||
"ChangeCollaborators": "изменил(а) участники",
|
"ChangeCollaborators": "изменил(а) участники",
|
||||||
"Activity": "Активность",
|
"Activity": "Активность",
|
||||||
"People": "Люди",
|
"People": "Люди",
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
import EmployeeInbox from './EmployeeInbox.svelte'
|
import EmployeeInbox from './EmployeeInbox.svelte'
|
||||||
import Filter from './Filter.svelte'
|
import Filter from './Filter.svelte'
|
||||||
import People from './People.svelte'
|
import People from './People.svelte'
|
||||||
|
import { subscribe } from '../utils'
|
||||||
|
|
||||||
export let visibileNav: boolean
|
export let visibileNav: boolean
|
||||||
let filter: 'all' | 'read' | 'unread' = 'all'
|
let filter: 'all' | 'read' | 'unread' = 'all'
|
||||||
@ -100,6 +101,10 @@
|
|||||||
const personAccount = await client.findOne(contact.class.PersonAccount, { person: employee._id })
|
const personAccount = await client.findOne(contact.class.PersonAccount, { person: employee._id })
|
||||||
if (personAccount !== undefined) {
|
if (personAccount !== undefined) {
|
||||||
const channel = await getDirectChannel(client, me._id as Ref<PersonAccount>, personAccount._id)
|
const channel = await getDirectChannel(client, me._id as Ref<PersonAccount>, personAccount._id)
|
||||||
|
|
||||||
|
// re-subscribing in case DM was removed from notifications
|
||||||
|
await subscribe(chunter.class.DirectMessage, channel)
|
||||||
|
|
||||||
openDM(channel)
|
openDM(channel)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,4 +23,4 @@
|
|||||||
export let value: DirectMessage
|
export let value: DirectMessage
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Label label={notification.string.YouHaveStartedAConversation} />
|
<Label label={notification.string.YouHaveJoinedTheConversation} />
|
||||||
|
@ -30,7 +30,7 @@ export default mergeIds(notificationId, notification, {
|
|||||||
Change: '' as IntlString,
|
Change: '' as IntlString,
|
||||||
AddedRemoved: '' as IntlString,
|
AddedRemoved: '' as IntlString,
|
||||||
YouAddedCollaborators: '' as IntlString,
|
YouAddedCollaborators: '' as IntlString,
|
||||||
YouHaveStartedAConversation: '' as IntlString,
|
YouHaveJoinedTheConversation: '' as IntlString,
|
||||||
ChangeCollaborators: '' as IntlString,
|
ChangeCollaborators: '' as IntlString,
|
||||||
Activity: '' as IntlString,
|
Activity: '' as IntlString,
|
||||||
People: '' as IntlString,
|
People: '' as IntlString,
|
||||||
|
@ -14,7 +14,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import { Account, Class, Doc, getCurrentAccount, Ref } from '@hcengineering/core'
|
import { Account, Class, Doc, DocumentUpdate, getCurrentAccount, Ref, TxOperations } from '@hcengineering/core'
|
||||||
import notification, { Collaborators, DocUpdates, NotificationClient } from '@hcengineering/notification'
|
import notification, { Collaborators, DocUpdates, NotificationClient } from '@hcengineering/notification'
|
||||||
import { createQuery, getClient } from '@hcengineering/presentation'
|
import { createQuery, getClient } from '@hcengineering/presentation'
|
||||||
import { writable } from 'svelte/store'
|
import { writable } from 'svelte/store'
|
||||||
@ -119,29 +119,69 @@ export async function hasntNotifications (object: DocUpdates): Promise<boolean>
|
|||||||
return !object.txes.some((p) => p.isNew)
|
return !object.txes.some((p) => p.isNew)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
enum OpWithMe {
|
||||||
|
Add = 'add',
|
||||||
|
Remove = 'remove'
|
||||||
|
}
|
||||||
|
|
||||||
|
async function updateMeInCollaborators (
|
||||||
|
client: TxOperations,
|
||||||
|
docClass: Ref<Class<Doc>>,
|
||||||
|
docId: Ref<Doc>,
|
||||||
|
op: OpWithMe
|
||||||
|
): Promise<void> {
|
||||||
|
const me = getCurrentAccount()._id
|
||||||
|
const hierarchy = client.getHierarchy()
|
||||||
|
const target = await client.findOne(docClass, { _id: docId })
|
||||||
|
if (target !== undefined) {
|
||||||
|
if (hierarchy.hasMixin(target, notification.mixin.Collaborators)) {
|
||||||
|
const collab = hierarchy.as(target, notification.mixin.Collaborators)
|
||||||
|
let collabUpdate: DocumentUpdate<Collaborators> | undefined
|
||||||
|
|
||||||
|
if (collab.collaborators.includes(me) && op === OpWithMe.Remove) {
|
||||||
|
collabUpdate = {
|
||||||
|
$pull: {
|
||||||
|
collaborators: me
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (!collab.collaborators.includes(me) && op === OpWithMe.Add) {
|
||||||
|
collabUpdate = {
|
||||||
|
$push: {
|
||||||
|
collaborators: me
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (collabUpdate !== undefined) {
|
||||||
|
await client.updateMixin(
|
||||||
|
collab._id,
|
||||||
|
collab._class,
|
||||||
|
collab.space,
|
||||||
|
notification.mixin.Collaborators,
|
||||||
|
collabUpdate
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
export async function unsubscribe (object: DocUpdates): Promise<void> {
|
export async function unsubscribe (object: DocUpdates): Promise<void> {
|
||||||
const me = getCurrentAccount()._id
|
|
||||||
const client = getClient()
|
const client = getClient()
|
||||||
const hierarchy = client.getHierarchy()
|
await updateMeInCollaborators(client, object.attachedToClass, object.attachedTo, OpWithMe.Remove)
|
||||||
const target = await client.findOne(object.attachedToClass, { _id: object.attachedTo })
|
|
||||||
if (target !== undefined) {
|
|
||||||
if (hierarchy.hasMixin(target, notification.mixin.Collaborators)) {
|
|
||||||
const collab = hierarchy.as(target, notification.mixin.Collaborators)
|
|
||||||
if (collab.collaborators.includes(me)) {
|
|
||||||
await client.updateMixin(collab._id, collab._class, collab.space, notification.mixin.Collaborators, {
|
|
||||||
$pull: {
|
|
||||||
collaborators: me
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await client.remove(object)
|
await client.remove(object)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @public
|
||||||
|
*/
|
||||||
|
export async function subscribe (docClass: Ref<Class<Doc>>, docId: Ref<Doc>): Promise<void> {
|
||||||
|
const client = getClient()
|
||||||
|
await updateMeInCollaborators(client, docClass, docId, OpWithMe.Add)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
*/
|
*/
|
||||||
|
@ -13,15 +13,7 @@
|
|||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
//
|
//
|
||||||
|
|
||||||
import chunter, {
|
import chunter, { Backlink, chunterId, ChunterSpace, Comment, Message, ThreadMessage } from '@hcengineering/chunter'
|
||||||
Backlink,
|
|
||||||
chunterId,
|
|
||||||
ChunterSpace,
|
|
||||||
Comment,
|
|
||||||
DirectMessage,
|
|
||||||
Message,
|
|
||||||
ThreadMessage
|
|
||||||
} from '@hcengineering/chunter'
|
|
||||||
import contact, { Employee, PersonAccount } from '@hcengineering/contact'
|
import contact, { Employee, PersonAccount } from '@hcengineering/contact'
|
||||||
import core, {
|
import core, {
|
||||||
Account,
|
Account,
|
||||||
@ -44,7 +36,7 @@ import core, {
|
|||||||
import notification, { Collaborators, NotificationType } from '@hcengineering/notification'
|
import notification, { Collaborators, NotificationType } from '@hcengineering/notification'
|
||||||
import { getMetadata } from '@hcengineering/platform'
|
import { getMetadata } from '@hcengineering/platform'
|
||||||
import serverCore, { TriggerControl } from '@hcengineering/server-core'
|
import serverCore, { TriggerControl } from '@hcengineering/server-core'
|
||||||
import { pushNotification, getDocCollaborators, getMixinTx } from '@hcengineering/server-notification-resources'
|
import { getDocCollaborators, getMixinTx, pushNotification } from '@hcengineering/server-notification-resources'
|
||||||
import { workbenchId } from '@hcengineering/workbench'
|
import { workbenchId } from '@hcengineering/workbench'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -216,29 +208,50 @@ export async function ChunterTrigger (tx: Tx, control: TriggerControl): Promise<
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* @public
|
* @public
|
||||||
|
* Sends notification to the message sender in case when DM
|
||||||
|
* notifications are deleted or hidden. This is required for
|
||||||
|
* the DM to re-appear in the sender's inbox.
|
||||||
*/
|
*/
|
||||||
export async function OnDmCreate (tx: Tx, control: TriggerControl): Promise<Tx[]> {
|
export async function OnMessageSent (tx: Tx, control: TriggerControl): Promise<Tx[]> {
|
||||||
const ptx = tx as TxCreateDoc<DirectMessage>
|
const ptx = TxProcessor.extractTx(tx) as TxCreateDoc<Message>
|
||||||
|
if (ptx._class !== core.class.TxCreateDoc) return []
|
||||||
|
|
||||||
|
const message = TxProcessor.createDoc2Doc(ptx)
|
||||||
|
if (message.createdBy === undefined) return []
|
||||||
|
|
||||||
|
if (!control.hierarchy.isDerived(message.attachedToClass, chunter.class.DirectMessage)) return []
|
||||||
|
|
||||||
|
const channel = (await control.findAll(chunter.class.DirectMessage, { _id: message.attachedTo })).shift()
|
||||||
|
if (channel === undefined || channel.members.length !== 2 || !channel.private) return []
|
||||||
|
|
||||||
const res: Tx[] = []
|
const res: Tx[] = []
|
||||||
|
|
||||||
if (tx.createdBy == null) return []
|
const docUpdates = await control.findAll(notification.class.DocUpdates, { attachedTo: channel._id })
|
||||||
|
|
||||||
const dm = TxProcessor.createDoc2Doc(ptx)
|
// binding notification to the DM creation tx to properly display it in inbox
|
||||||
|
const dmCreationTx = (
|
||||||
|
await control.findAll(core.class.TxCreateDoc, { objectClass: channel._class, objectId: channel._id })
|
||||||
|
).shift()
|
||||||
|
if (dmCreationTx === undefined) return []
|
||||||
|
|
||||||
if (dm.members.length > 2) return []
|
const sender = message.createdBy
|
||||||
|
const docUpdate = docUpdates.find((du) => du.user === sender)
|
||||||
let dmWithPerson: Ref<Account> | undefined
|
if (docUpdate === undefined) {
|
||||||
for (const person of dm.members) {
|
let anotherPerson: Ref<Account> | undefined
|
||||||
if (person !== tx.createdBy) {
|
for (const person of channel.members) {
|
||||||
dmWithPerson = person
|
if (person !== sender) {
|
||||||
break
|
anotherPerson = person
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (anotherPerson == null) return []
|
||||||
|
|
||||||
|
pushNotification(control, res, sender, channel, dmCreationTx, docUpdates, anotherPerson)
|
||||||
|
} else if (docUpdate.hidden) {
|
||||||
|
res.push(control.txFactory.createTxUpdateDoc(docUpdate._class, docUpdate.space, docUpdate._id, { hidden: false }))
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dmWithPerson == null) return []
|
|
||||||
|
|
||||||
pushNotification(control, res, tx.createdBy, dm, ptx, [], dmWithPerson)
|
|
||||||
|
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -309,7 +322,7 @@ export async function IsChannelMessage (
|
|||||||
export default async () => ({
|
export default async () => ({
|
||||||
trigger: {
|
trigger: {
|
||||||
ChunterTrigger,
|
ChunterTrigger,
|
||||||
OnDmCreate
|
OnMessageSent
|
||||||
},
|
},
|
||||||
function: {
|
function: {
|
||||||
CommentRemove,
|
CommentRemove,
|
||||||
|
@ -30,7 +30,7 @@ export const serverChunterId = 'server-chunter' as Plugin
|
|||||||
export default plugin(serverChunterId, {
|
export default plugin(serverChunterId, {
|
||||||
trigger: {
|
trigger: {
|
||||||
ChunterTrigger: '' as Resource<TriggerFunc>,
|
ChunterTrigger: '' as Resource<TriggerFunc>,
|
||||||
OnDmCreate: '' as Resource<TriggerFunc>
|
OnMessageSent: '' as Resource<TriggerFunc>
|
||||||
},
|
},
|
||||||
function: {
|
function: {
|
||||||
CommentRemove: '' as Resource<
|
CommentRemove: '' as Resource<
|
||||||
|
Loading…
Reference in New Issue
Block a user