From 24c547ab3927e7674441817077fb6b28e7b8c3f7 Mon Sep 17 00:00:00 2001 From: Denis Bunakalya <denis.bunakalya@xored.com> Date: Tue, 12 Apr 2022 18:45:06 +0300 Subject: [PATCH] Chunter: Delete message (#1336) Signed-off-by: Denis Bunakalya <denis.bunakalya@xored.com> --- plugins/chunter-assets/lang/en.json | 3 +- plugins/chunter-assets/lang/ru.json | 3 +- .../src/components/Message.svelte | 24 ++++++++-- .../src/components/ThreadComment.svelte | 10 +++- plugins/chunter-resources/src/plugin.ts | 3 +- server-plugins/chunter-resources/src/index.ts | 47 +++++++++++++++++-- 6 files changed, 77 insertions(+), 13 deletions(-) diff --git a/plugins/chunter-assets/lang/en.json b/plugins/chunter-assets/lang/en.json index c1f6497a98..725ebbbc8b 100644 --- a/plugins/chunter-assets/lang/en.json +++ b/plugins/chunter-assets/lang/en.json @@ -30,6 +30,7 @@ "New": "New", "MarkUnread": "Mark unread", "GetNewReplies": "Get notified about new replies", - "TurnOffReplies": "Turn off notifications for replies" + "TurnOffReplies": "Turn off notifications for replies", + "DeleteMessage": "Delete message" } } \ No newline at end of file diff --git a/plugins/chunter-assets/lang/ru.json b/plugins/chunter-assets/lang/ru.json index 130b6eb1b8..eccff39861 100644 --- a/plugins/chunter-assets/lang/ru.json +++ b/plugins/chunter-assets/lang/ru.json @@ -29,6 +29,7 @@ "New": "Новое", "MarkUnread": "Отметить как непрочитанное", "GetNewReplies": "Получать уведомления о новых ответах", - "TurnOffReplies": "Выключить уведомления об ответах" + "TurnOffReplies": "Выключить уведомления об ответах", + "DeleteMessage": "Удалить сообщение" } } \ No newline at end of file diff --git a/plugins/chunter-resources/src/components/Message.svelte b/plugins/chunter-resources/src/components/Message.svelte index 3bd4ef242a..9f13f9871f 100644 --- a/plugins/chunter-resources/src/components/Message.svelte +++ b/plugins/chunter-resources/src/components/Message.svelte @@ -17,11 +17,11 @@ import { AttachmentList } from '@anticrm/attachment-resources' import type { Message } from '@anticrm/chunter' import { Employee, EmployeeAccount, formatName } from '@anticrm/contact' - import { Ref, WithLookup } from '@anticrm/core' + import { Ref, WithLookup, getCurrentAccount } from '@anticrm/core' import { NotificationClientImpl } from '@anticrm/notification-resources' import { getResource } from '@anticrm/platform' import { Avatar, getClient, MessageViewer } from '@anticrm/presentation' - import { ActionIcon, IconMoreH, Menu, showPopup } from '@anticrm/ui' + import { ActionIcon, IconMoreH, Menu, showPopup, getCurrentLocation, navigate } from '@anticrm/ui' import { Action } from '@anticrm/view' import { getActions } from '@anticrm/view-resources' import { createEventDispatcher } from 'svelte' @@ -59,6 +59,21 @@ action: chunter.actionImpl.SubscribeMessage } as Action) + async function deleteMessage () { + await client.remove(message) + const loc = getCurrentLocation() + + if (loc.path[3] === message._id) { + loc.path.length = 3 + navigate(loc) + } + } + + const deleteAction = { + label: chunter.string.DeleteMessage, + action: deleteMessage + } + const showMenu = async (ev: Event): Promise<void> => { const actions = await getActions(client, message, chunter.class.Message) actions.push(subscribeAction) @@ -73,7 +88,8 @@ const impl = await getResource(a.action) await impl(message) } - })) + })), + ...(getCurrentAccount()._id === message.createBy ? [deleteAction] : []) ] }, ev.target as HTMLElement @@ -108,7 +124,7 @@ </div> {#if !thread} <div> - {#if message.replies}<Replies + {#if message.replies?.length}<Replies replies={message.replies} lastReply={message.lastReply} on:click={openThread} diff --git a/plugins/chunter-resources/src/components/ThreadComment.svelte b/plugins/chunter-resources/src/components/ThreadComment.svelte index 22affdaeba..4003b7bbf7 100644 --- a/plugins/chunter-resources/src/components/ThreadComment.svelte +++ b/plugins/chunter-resources/src/components/ThreadComment.svelte @@ -17,7 +17,7 @@ import { AttachmentList } from '@anticrm/attachment-resources' import type { ThreadMessage } from '@anticrm/chunter' import { Employee, EmployeeAccount, formatName } from '@anticrm/contact' - import { Ref, WithLookup } from '@anticrm/core' + import { Ref, WithLookup, getCurrentAccount } from '@anticrm/core' import { NotificationClientImpl } from '@anticrm/notification-resources' import { getResource } from '@anticrm/platform' import { Avatar, getClient, MessageViewer } from '@anticrm/presentation' @@ -53,6 +53,11 @@ action: chunter.actionImpl.SubscribeComment } as Action) + const deleteAction = { + label: chunter.string.DeleteMessage, + action: async () => await client.removeDoc(message._class, message.space, message._id) + } + const showMenu = async (ev: Event): Promise<void> => { const actions = await getActions(client, message, chunter.class.ThreadMessage) actions.push(subscribeAction) @@ -67,7 +72,8 @@ const impl = await getResource(a.action) await impl(message) } - })) + })), + ...(getCurrentAccount()._id === message.createBy ? [deleteAction] : []) ] }, ev.target as HTMLElement diff --git a/plugins/chunter-resources/src/plugin.ts b/plugins/chunter-resources/src/plugin.ts index e08dbcf25e..cba353810e 100644 --- a/plugins/chunter-resources/src/plugin.ts +++ b/plugins/chunter-resources/src/plugin.ts @@ -50,6 +50,7 @@ export default mergeIds(chunterId, chunter, { LastReply: '' as IntlString, New: '' as IntlString, GetNewReplies: '' as IntlString, - TurnOffReplies: '' as IntlString + TurnOffReplies: '' as IntlString, + DeleteMessage: '' as IntlString } }) diff --git a/server-plugins/chunter-resources/src/index.ts b/server-plugins/chunter-resources/src/index.ts index 1784ccf069..fbc79374e6 100644 --- a/server-plugins/chunter-resources/src/index.ts +++ b/server-plugins/chunter-resources/src/index.ts @@ -13,9 +13,9 @@ // limitations under the License. // -import chunter, { Channel, Comment, Message } from '@anticrm/chunter' +import chunter, { Channel, Comment, Message, ThreadMessage } from '@anticrm/chunter' import { EmployeeAccount } from '@anticrm/contact' -import core, { Class, Doc, DocumentQuery, FindOptions, FindResult, Hierarchy, Ref, Tx, TxCreateDoc, TxProcessor, TxUpdateDoc } from '@anticrm/core' +import core, { Class, Doc, DocumentQuery, FindOptions, FindResult, Hierarchy, Ref, Tx, TxCreateDoc, TxProcessor, TxUpdateDoc, TxRemoveDoc } from '@anticrm/core' import login from '@anticrm/login' import { getMetadata } from '@anticrm/platform' import { TriggerControl } from '@anticrm/server-core' @@ -58,7 +58,7 @@ export async function CommentCreate (tx: Tx, control: TriggerControl): Promise<T const hierarchy = control.hierarchy if (tx._class !== core.class.TxCreateDoc) return [] const doc = TxProcessor.createDoc2Doc(tx as TxCreateDoc<Doc>) - if (!hierarchy.isDerived(doc._class, chunter.class.Comment)) { + if (!hierarchy.isDerived(doc._class, chunter.class.ThreadMessage)) { return [] } @@ -80,6 +80,44 @@ export async function CommentCreate (tx: Tx, control: TriggerControl): Promise<T return result } +/** + * @public + */ +export async function CommentDelete (tx: Tx, control: TriggerControl): Promise<Tx[]> { + const hierarchy = control.hierarchy + if (tx._class !== core.class.TxRemoveDoc) return [] + + const rmTx = tx as TxRemoveDoc<ThreadMessage> + if (!hierarchy.isDerived(rmTx.objectClass, chunter.class.ThreadMessage)) { + return [] + } + const createTx = (await control.findAll(core.class.TxCreateDoc, { + objectId: rmTx.objectId + }, { limit: 1 }))[0] + + const comment = TxProcessor.createDoc2Doc(createTx as TxCreateDoc<ThreadMessage>) + + const comments = await control.findAll(chunter.class.ThreadMessage, { + attachedTo: comment.attachedTo + }) + const updateTx = control.txFactory.createTxUpdateDoc<Message>( + chunter.class.Message, + comment.space, + comment.attachedTo, + { + replies: + comments + .map(comm => (control.modelDb.getObject(comm.createBy) as EmployeeAccount).employee), + lastReply: + comments.length > 0 + ? Math.max(...comments.map(comm => comm.createOn)) + : undefined + } + ) + + return [updateTx] +} + /** * @public */ @@ -112,7 +150,8 @@ export async function MessageCreate (tx: Tx, control: TriggerControl): Promise<T export async function ChunterTrigger (tx: Tx, control: TriggerControl): Promise<Tx[]> { const promises = [ MessageCreate(tx, control), - CommentCreate(tx, control) + CommentCreate(tx, control), + CommentDelete(tx, control) ] const res = await Promise.all(promises) return res.flat()