From ed1c29573f3adb75120ad0ed5b4ff700263fd133 Mon Sep 17 00:00:00 2001 From: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> Date: Tue, 5 Apr 2022 12:19:18 +0600 Subject: [PATCH] Chunter last views (#1273) Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> --- models/server-chunter/src/index.ts | 4 + packages/theme/styles/_layouts.scss | 1 + plugins/chunter-assets/lang/en.json | 3 +- plugins/chunter-assets/lang/ru.json | 3 +- plugins/chunter-resources/package.json | 1 + .../src/components/Channel.svelte | 53 +++++++++-- .../src/components/ChannelSeparator.svelte | 14 ++- .../src/components/ChannelView.svelte | 16 +--- .../src/components/DateSeparator.svelte | 82 ++++++++++++++++ .../src/components/Message.svelte | 55 +++++------ .../src/components/ThreadComment.svelte | 50 +++++----- .../src/components/ThreadView.svelte | 93 ++++++++++++------- plugins/chunter-resources/src/plugin.ts | 3 +- .../src/components/Workbench.svelte | 4 +- server-plugins/chunter-resources/package.json | 1 + server-plugins/chunter-resources/src/index.ts | 38 +++++++- server-plugins/chunter/src/index.ts | 4 + 17 files changed, 317 insertions(+), 108 deletions(-) create mode 100644 plugins/chunter-resources/src/components/DateSeparator.svelte diff --git a/models/server-chunter/src/index.ts b/models/server-chunter/src/index.ts index e7c487fe7c..d2bd550571 100644 --- a/models/server-chunter/src/index.ts +++ b/models/server-chunter/src/index.ts @@ -33,4 +33,8 @@ export function createModel (builder: Builder): void { builder.mixin, ObjectDDParticipant>(chunter.class.Comment, core.class.Class, serverCore.mixin.ObjectDDParticipant, { collectDocs: serverChunter.function.CommentRemove }) + + builder.createDoc(serverCore.class.Trigger, core.space.Model, { + trigger: serverChunter.trigger.CommentCreate + }) } diff --git a/packages/theme/styles/_layouts.scss b/packages/theme/styles/_layouts.scss index 68962c2cde..aad35cd93a 100644 --- a/packages/theme/styles/_layouts.scss +++ b/packages/theme/styles/_layouts.scss @@ -304,6 +304,7 @@ p:last-child { margin-block-end: 0; } .mb-2 { margin-bottom: .5rem; } .mb-3 { margin-bottom: .75rem; } .mb-4 { margin-bottom: 1rem; } +.mb-6 { margin-bottom: 1.5rem; } .mx-1 { margin: 0 .25rem; } .mx-2 { margin: 0 .5rem; } .mx-3 { margin: 0 .75rem; } diff --git a/plugins/chunter-assets/lang/en.json b/plugins/chunter-assets/lang/en.json index 3337c7a7d1..ae622639e5 100644 --- a/plugins/chunter-assets/lang/en.json +++ b/plugins/chunter-assets/lang/en.json @@ -24,6 +24,7 @@ "Replies": "Replies", "LastReply": "Last reply", "RepliesCount": "{replies, plural, =1 {# reply} other {# replies}}", - "Thread": "Thread" + "Thread": "Thread", + "New": "New" } } \ No newline at end of file diff --git a/plugins/chunter-assets/lang/ru.json b/plugins/chunter-assets/lang/ru.json index 6923516310..dad190d8af 100644 --- a/plugins/chunter-assets/lang/ru.json +++ b/plugins/chunter-assets/lang/ru.json @@ -24,6 +24,7 @@ "Replies": "Ответы", "LastReply": "Последний ответ", "RepliesCount": "{replies, plural, =1 {# ответ} =2 {# ответа} =3 {# ответа} =4 {# ответа} other {# ответов}}", - "Thread": "Обсуждение" + "Thread": "Обсуждение", + "New": "Новое" } } \ No newline at end of file diff --git a/plugins/chunter-resources/package.json b/plugins/chunter-resources/package.json index c03e60ea0f..edc8df5e21 100644 --- a/plugins/chunter-resources/package.json +++ b/plugins/chunter-resources/package.json @@ -41,6 +41,7 @@ "@anticrm/text-editor": "~0.6.0", "@anticrm/contact": "~0.6.5", "@anticrm/contact-resources": "~0.6.0", + "@anticrm/notification-resources": "~0.6.0", "@anticrm/attachment": "~0.6.1", "@anticrm/attachment-resources": "~0.6.0", "@anticrm/view-resources": "~0.6.0", diff --git a/plugins/chunter-resources/src/components/Channel.svelte b/plugins/chunter-resources/src/components/Channel.svelte index 36f4ed1c5d..6365dfe2fa 100644 --- a/plugins/chunter-resources/src/components/Channel.svelte +++ b/plugins/chunter-resources/src/components/Channel.svelte @@ -14,20 +14,37 @@ --> -
+
{#if messages} - {#each messages as message} + {#each messages as message, i (message._id)} + {#if newMessagesPos === i} + + {/if} {/each} {/if} @@ -57,6 +97,7 @@ diff --git a/plugins/chunter-resources/src/components/ChannelSeparator.svelte b/plugins/chunter-resources/src/components/ChannelSeparator.svelte index 039ca9d702..6994a8240d 100644 --- a/plugins/chunter-resources/src/components/ChannelSeparator.svelte +++ b/plugins/chunter-resources/src/components/ChannelSeparator.svelte @@ -20,12 +20,13 @@ export let title: IntlString export let line: boolean = false export let params: any = undefined - + export let reverse: boolean = false + export let isNew: boolean = false -
+
diff --git a/plugins/chunter-resources/src/components/ChannelView.svelte b/plugins/chunter-resources/src/components/ChannelView.svelte index f06817d806..6e602b5dc4 100644 --- a/plugins/chunter-resources/src/components/ChannelView.svelte +++ b/plugins/chunter-resources/src/components/ChannelView.svelte @@ -17,6 +17,7 @@ import { AttachmentRefInput } from '@anticrm/attachment-resources' import { Message } from '@anticrm/chunter' import { generateId,getCurrentAccount,Ref,Space, TxFactory } from '@anticrm/core' + import { NotificationClientImpl } from '@anticrm/notification-resources' import { getClient } from '@anticrm/presentation' import { getCurrentLocation,navigate } from '@anticrm/ui' import { createBacklinks } from '../backlinks' @@ -28,6 +29,7 @@ const client = getClient() const _class = chunter.class.Message let _id = generateId() as Ref + const notificationClient = NotificationClientImpl.getClient() async function onMessage (event: CustomEvent) { const { message, attachments } = event.detail @@ -40,10 +42,12 @@ attachments }, _id) tx.attributes.createOn = tx.modifiedOn + await notificationClient.updateLastView(space, chunter.class.Channel, tx.modifiedOn, true) await client.tx(tx) // Create an backlink to document await createBacklinks(client, space, chunter.class.Channel, _id, message) + _id = generateId() } @@ -55,22 +59,12 @@ -
- { openThread(e.detail) }} /> -
+ { openThread(e.detail) }} />
diff --git a/plugins/chunter-resources/src/components/Message.svelte b/plugins/chunter-resources/src/components/Message.svelte index ed00a488f9..c8e879e428 100644 --- a/plugins/chunter-resources/src/components/Message.svelte +++ b/plugins/chunter-resources/src/components/Message.svelte @@ -14,10 +14,11 @@ -->
- {#await getEmployee(message.createBy) then employee} -
-
-
- {#if employee}{formatName(employee.name)}{/if} - {getTime(message.createOn)} -
-
- {#if message.attachments}
{/if} - {#if (reactions || message.replies)} - - {/if} +
+
+
+ {#if employee}{formatName(employee.name)}{/if} + {getTime(message.createOn)}
- {/await} +
+ {#if message.attachments}
{/if} + {#if (reactions || message.replies)} + + {/if} +
{ showMenu(e) }}/>
{#if !thread} diff --git a/plugins/chunter-resources/src/components/ThreadComment.svelte b/plugins/chunter-resources/src/components/ThreadComment.svelte index 13855bee17..f53edee738 100644 --- a/plugins/chunter-resources/src/components/ThreadComment.svelte +++ b/plugins/chunter-resources/src/components/ThreadComment.svelte @@ -14,10 +14,11 @@ -->
- {#await getEmployee(comment.modifiedBy) then employee} -
-
-
- {#if employee}{formatName(employee.name)}{/if} - {getTime(comment.modifiedOn)} -
-
- {#if comment.attachments}
{/if} - {#if reactions} - - {/if} +
+
+
+ {#if employee}{formatName(employee.name)}{/if} + {getTime(comment.modifiedOn)}
- {/await} +
+ {#if comment.attachments}
{/if} + {#if reactions} + + {/if} +
{ showMenu(e) }}/>
diff --git a/plugins/chunter-resources/src/components/ThreadView.svelte b/plugins/chunter-resources/src/components/ThreadView.svelte index ad59ba42ba..0a63bb42df 100644 --- a/plugins/chunter-resources/src/components/ThreadView.svelte +++ b/plugins/chunter-resources/src/components/ThreadView.svelte @@ -16,11 +16,12 @@ import attachment from '@anticrm/attachment' import { AttachmentRefInput } from '@anticrm/attachment-resources' import type { Comment,Message } from '@anticrm/chunter' - import contact,{ Employee, EmployeeAccount } from '@anticrm/contact' - import { Class,generateId,getCurrentAccount,Lookup,Ref, Space } from '@anticrm/core' + import contact,{ Employee,EmployeeAccount } from '@anticrm/contact' + import core,{ generateId,getCurrentAccount,Ref,Space,TxFactory } from '@anticrm/core' + import { NotificationClientImpl } from '@anticrm/notification-resources' import { createQuery,getClient } from '@anticrm/presentation' import { IconClose,Label } from '@anticrm/ui' - import { createEventDispatcher } from 'svelte' + import { afterUpdate,beforeUpdate,createEventDispatcher } from 'svelte' import { createBacklinks } from '../backlinks' import chunter from '../plugin' import ChannelSeparator from './ChannelSeparator.svelte' @@ -37,8 +38,23 @@ let message: Message | undefined let commentId = generateId() + let div: HTMLDivElement | undefined + let autoscroll: boolean = false + + beforeUpdate(() => { + autoscroll = div !== undefined && (div.offsetHeight + div.scrollTop) > (div.scrollHeight - 20) + }) + + afterUpdate(() => { + if (div && autoscroll) div.scrollTo(0, div.scrollHeight) + }) + + const notificationClient = NotificationClientImpl.getClient() + const lastViews = notificationClient.getLastViews() + const lookup = { - _id: { attachments: attachment.class.Attachment } + _id: { attachments: attachment.class.Attachment }, + modifiedBy: core.class.Account } $: updateQueries(_id) @@ -47,12 +63,19 @@ messageQuery.query(chunter.class.Message, { _id: id }, (res) => message = res[0], { - lookup + lookup: { + _id: { attachments: attachment.class.Attachment }, + createBy: core.class.Account + } }) query.query(chunter.class.Comment, { attachedTo: id - }, (res) => comments = res, { + }, (res) => { + comments = res + newMessagesPos = newMessagesStart(comments) + notificationClient.updateLastView(id, chunter.class.Message) + }, { lookup }) } @@ -64,8 +87,9 @@ async function onMessage (event: CustomEvent) { const { message, attachments } = event.detail - const employee = (getCurrentAccount() as EmployeeAccount).employee - await client.createDoc(chunter.class.Comment, space, { + const me = getCurrentAccount()._id + const txFactory = new TxFactory(me) + const tx = txFactory.createTxCreateDoc(chunter.class.Comment, space, { attachedTo: _id, attachedToClass: chunter.class.Message, collection: 'replies', @@ -73,39 +97,49 @@ attachments }, commentId) - await client.updateDoc(chunter.class.Message, space, _id, { - $push: { replies: employee }, - lastReply: new Date().getTime() - }) + await notificationClient.updateLastView(_id, chunter.class.Message, tx.modifiedOn, true) + await client.tx(tx) // Create an backlink to document await createBacklinks(client, space, chunter.class.Channel, commentId, message) + commentId = generateId() } let comments: Comment[] = [] + + function newMessagesStart (comments: Comment[]): number { + const lastView = $lastViews.get(_id) + if (lastView === undefined) return -1 + for (let index = 0; index < comments.length; index++) { + const comment = comments[index] + if (comment.modifiedOn > lastView) return index + } + return -1 + } + + let newMessagesPos: number = -1
{ dispatch('close') }}>
-
-
- {#if message} -
- - {#if comments.length} - - {/if} - {#each comments as comment} - - {/each} -
+
+ {#if message} + + {#if comments.length} + {/if} -
-
- -
+ {#each comments as comment, i (comment._id)} + {#if newMessagesPos === i} + + {/if} + + {/each} + {/if} +
+
+