From 48b3f3facc7a6b01be61b892e36048d671ba2bb1 Mon Sep 17 00:00:00 2001 From: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> Date: Sat, 2 Apr 2022 10:08:37 +0600 Subject: [PATCH] Threads (#1246) Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> --- models/chunter/package.json | 1 + models/chunter/src/index.ts | 20 +- models/chunter/src/migration.ts | 17 +- models/chunter/src/plugin.ts | 7 +- packages/ui/src/index.ts | 2 +- plugins/chunter-assets/lang/en.json | 6 +- plugins/chunter-assets/lang/ru.json | 6 +- .../src/components/Channel.svelte | 31 +++- .../src/components/ChannelSeparator.svelte | 52 +----- .../src/components/ChannelView.svelte | 32 +++- .../src/components/Message.svelte | 158 +++++++++------- .../src/components/Replies.svelte | 77 +++++--- .../src/components/ThreadComment.svelte | 174 ++++++++++++++++++ .../src/components/ThreadView.svelte | 146 +++++++++++++++ .../src/components/icons/Thread.svelte | 13 ++ plugins/chunter-resources/src/index.ts | 4 +- plugins/chunter-resources/src/plugin.ts | 6 +- plugins/chunter/package.json | 1 + plugins/chunter/src/index.ts | 7 +- .../src/components/SpaceHeader.svelte | 2 +- .../src/components/Workbench.svelte | 50 +++-- plugins/workbench/src/index.ts | 1 + 22 files changed, 636 insertions(+), 177 deletions(-) create mode 100644 plugins/chunter-resources/src/components/ThreadComment.svelte create mode 100644 plugins/chunter-resources/src/components/ThreadView.svelte create mode 100644 plugins/chunter-resources/src/components/icons/Thread.svelte diff --git a/models/chunter/package.json b/models/chunter/package.json index 05845c5653..d5e6910d89 100644 --- a/models/chunter/package.json +++ b/models/chunter/package.json @@ -30,6 +30,7 @@ "@anticrm/ui": "~0.6.0", "@anticrm/view": "~0.6.0", "@anticrm/model-attachment": "~0.6.0", + "@anticrm/contact": "~0.6.5", "@anticrm/chunter": "~0.6.1", "@anticrm/chunter-resources": "~0.6.0", "@anticrm/platform": "~0.6.5", diff --git a/models/chunter/src/index.ts b/models/chunter/src/index.ts index 3403035c74..7dcc088cef 100644 --- a/models/chunter/src/index.ts +++ b/models/chunter/src/index.ts @@ -15,14 +15,15 @@ import activity from '@anticrm/activity' import type { Backlink, Channel, Comment, Message } from '@anticrm/chunter' -import type { Class, Doc, Domain, Ref } from '@anticrm/core' +import type { Account, Class, Doc, Domain, Ref, Timestamp } from '@anticrm/core' import { IndexKind } from '@anticrm/core' -import { Builder, Collection, Index, Model, Prop, TypeMarkup, UX } from '@anticrm/model' +import { ArrOf, Builder, Collection, Index, Model, Prop, TypeMarkup, TypeRef, TypeTimestamp, UX } from '@anticrm/model' import attachment from '@anticrm/model-attachment' import core, { TAttachedDoc, TDoc, TSpace } from '@anticrm/model-core' import view from '@anticrm/model-view' import workbench from '@anticrm/model-workbench' import chunter from './plugin' +import contact, { Employee } from '@anticrm/contact' export const DOMAIN_CHUNTER = 'chunter' as Domain export const DOMAIN_COMMENT = 'comment' as Domain @@ -39,6 +40,18 @@ export class TMessage extends TDoc implements Message { @Prop(Collection(attachment.class.Attachment), attachment.string.Attachments) attachments?: number + + @Prop(ArrOf(TypeRef(contact.class.Employee)), chunter.string.Replies) + replies?: Ref[] + + @Prop(TypeTimestamp(), chunter.string.LastReply) + lastReply?: Timestamp + + @Prop(TypeRef(core.class.Account), chunter.string.CreateBy) + createBy!: Ref + + @Prop(TypeTimestamp(), chunter.string.Create) + createOn!: Timestamp } @Model(chunter.class.Comment, core.class.AttachedDoc, DOMAIN_COMMENT) @@ -95,7 +108,8 @@ export function createModel (builder: Builder): void { addSpaceLabel: chunter.string.CreateChannel, createComponent: chunter.component.CreateChannel } - ] + ], + aside: chunter.component.ThreadView } }, chunter.app.Chunter) diff --git a/models/chunter/src/migration.ts b/models/chunter/src/migration.ts index 6cdcb12a57..c12302d6f3 100644 --- a/models/chunter/src/migration.ts +++ b/models/chunter/src/migration.ts @@ -13,7 +13,8 @@ // limitations under the License. // -import type { Client } from '@anticrm/core' +import { Message } from '@anticrm/chunter' +import type { Client, Ref } from '@anticrm/core' import core, { TxOperations } from '@anticrm/core' import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model' import chunter from './plugin' @@ -55,6 +56,19 @@ export async function createRandom (tx: TxOperations): Promise { } } +export async function setCreate (client: TxOperations): Promise { + const messages = (await client.findAll(chunter.class.Message, { })).filter((m) => m.createBy === undefined).map((m) => m._id) + if (messages.length === 0) return + const txes = await client.findAll(core.class.TxCreateDoc, { objectId: { $in: messages } }) + const promises = txes.map(async (tx) => { + await client.updateDoc(chunter.class.Message, tx.objectSpace, tx.objectId as Ref, { + createBy: tx.modifiedBy, + createOn: tx.modifiedOn + }) + }) + await Promise.all(promises) +} + export const chunterOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise { }, @@ -62,5 +76,6 @@ export const chunterOperation: MigrateOperation = { const tx = new TxOperations(client, core.account.System) await createGeneral(tx) await createRandom(tx) + await setCreate(tx) } } diff --git a/models/chunter/src/plugin.ts b/models/chunter/src/plugin.ts index d41ab378e6..1dda3ce0df 100644 --- a/models/chunter/src/plugin.ts +++ b/models/chunter/src/plugin.ts @@ -25,7 +25,8 @@ import type { ViewletDescriptor } from '@anticrm/view' export default mergeIds(chunterId, chunter, { component: { CommentPresenter: '' as AnyComponent, - ChannelPresenter: '' as AnyComponent + ChannelPresenter: '' as AnyComponent, + ThreadView: '' as AnyComponent }, string: { ApplicationLabelChunter: '' as IntlString, @@ -35,7 +36,9 @@ export default mergeIds(chunterId, chunter, { Comment: '' as IntlString, Message: '' as IntlString, Reference: '' as IntlString, - Chat: '' as IntlString + Chat: '' as IntlString, + CreateBy: '' as IntlString, + Create: '' as IntlString }, viewlet: { Chat: '' as Ref diff --git a/packages/ui/src/index.ts b/packages/ui/src/index.ts index dc132354a2..5611df32c5 100644 --- a/packages/ui/src/index.ts +++ b/packages/ui/src/index.ts @@ -20,7 +20,7 @@ import { readable } from 'svelte/store' import Root from './components/internal/Root.svelte' -export type { AnyComponent, AnySvelteComponent, Action, LabelAndProps, TooltipAligment, AnySvelteComponentWithProps } from './types' +export type { AnyComponent, AnySvelteComponent, Action, LabelAndProps, TooltipAligment, AnySvelteComponentWithProps, Location } from './types' // export { applicationShortcutKey } from './utils' export { getCurrentLocation, locationToUrl, navigate, location } from './location' diff --git a/plugins/chunter-assets/lang/en.json b/plugins/chunter-assets/lang/en.json index 4adc89b6d0..3337c7a7d1 100644 --- a/plugins/chunter-assets/lang/en.json +++ b/plugins/chunter-assets/lang/en.json @@ -20,6 +20,10 @@ "Message": "Message", "Reference": "Reference", "Chat": "Chat", - "In": "In" + "In": "In", + "Replies": "Replies", + "LastReply": "Last reply", + "RepliesCount": "{replies, plural, =1 {# reply} other {# replies}}", + "Thread": "Thread" } } \ No newline at end of file diff --git a/plugins/chunter-assets/lang/ru.json b/plugins/chunter-assets/lang/ru.json index 87c81ea3c6..6923516310 100644 --- a/plugins/chunter-assets/lang/ru.json +++ b/plugins/chunter-assets/lang/ru.json @@ -20,6 +20,10 @@ "Message": "Сообщение", "Reference": "Ссылка", "Chat": "Чат", - "In": "в" + "In": "в", + "Replies": "Ответы", + "LastReply": "Последний ответ", + "RepliesCount": "{replies, plural, =1 {# ответ} =2 {# ответа} =3 {# ответа} =4 {# ответа} other {# ответов}}", + "Thread": "Обсуждение" } } \ No newline at end of file diff --git a/plugins/chunter-resources/src/components/Channel.svelte b/plugins/chunter-resources/src/components/Channel.svelte index 3e028c5cb7..36f4ed1c5d 100644 --- a/plugins/chunter-resources/src/components/Channel.svelte +++ b/plugins/chunter-resources/src/components/Channel.svelte @@ -14,26 +14,43 @@ -->
{#if messages} {#each messages as message} - + {/each} {/if}
diff --git a/plugins/chunter-resources/src/components/ChannelSeparator.svelte b/plugins/chunter-resources/src/components/ChannelSeparator.svelte index aed03c7a0c..039ca9d702 100644 --- a/plugins/chunter-resources/src/components/ChannelSeparator.svelte +++ b/plugins/chunter-resources/src/components/ChannelSeparator.svelte @@ -15,56 +15,24 @@ -
-
{title}
+
+
diff --git a/plugins/chunter-resources/src/components/ChannelView.svelte b/plugins/chunter-resources/src/components/ChannelView.svelte index 9b62250b6c..f06817d806 100644 --- a/plugins/chunter-resources/src/components/ChannelView.svelte +++ b/plugins/chunter-resources/src/components/ChannelView.svelte @@ -14,35 +14,49 @@ -->
- + { openThread(e.detail) }} />
diff --git a/plugins/chunter-resources/src/components/Message.svelte b/plugins/chunter-resources/src/components/Message.svelte index d68e0f0bf1..ed00a488f9 100644 --- a/plugins/chunter-resources/src/components/Message.svelte +++ b/plugins/chunter-resources/src/components/Message.svelte @@ -1,72 +1,107 @@
-
-
-
- {#await getUser(client, message.modifiedBy) then user} - {#if user}{formatName(user.name)}{/if} - {/await} - {getTime(message.modifiedOn)} -
-
-
- {#if (reactions || replies) && !thread} - \ No newline at end of file diff --git a/plugins/chunter-resources/src/components/ThreadComment.svelte b/plugins/chunter-resources/src/components/ThreadComment.svelte new file mode 100644 index 0000000000..13855bee17 --- /dev/null +++ b/plugins/chunter-resources/src/components/ThreadComment.svelte @@ -0,0 +1,174 @@ + + + + +
+ {#await getEmployee(comment.modifiedBy) then employee} +
+
+
+ {#if employee}{formatName(employee.name)}{/if} + {getTime(comment.modifiedOn)} +
+
+ {#if comment.attachments}
{/if} + {#if reactions} + + {/if} +
+ {/await} +
+
{ showMenu(e) }}/>
+
+ +
+
+
+ + \ No newline at end of file diff --git a/plugins/chunter-resources/src/components/ThreadView.svelte b/plugins/chunter-resources/src/components/ThreadView.svelte new file mode 100644 index 0000000000..ad59ba42ba --- /dev/null +++ b/plugins/chunter-resources/src/components/ThreadView.svelte @@ -0,0 +1,146 @@ + + + +
+
+
{ dispatch('close') }}>
+
+
+
+ {#if message} +
+ + {#if comments.length} + + {/if} + {#each comments as comment} + + {/each} +
+ {/if} +
+
+ +
+
+ + diff --git a/plugins/chunter-resources/src/components/icons/Thread.svelte b/plugins/chunter-resources/src/components/icons/Thread.svelte new file mode 100644 index 0000000000..b9948c1e39 --- /dev/null +++ b/plugins/chunter-resources/src/components/icons/Thread.svelte @@ -0,0 +1,13 @@ + + + + + + + + diff --git a/plugins/chunter-resources/src/index.ts b/plugins/chunter-resources/src/index.ts index d450b73060..c31843e0f7 100644 --- a/plugins/chunter-resources/src/index.ts +++ b/plugins/chunter-resources/src/index.ts @@ -23,6 +23,7 @@ import CommentInput from './components/CommentInput.svelte' import CommentPresenter from './components/CommentPresenter.svelte' import CommentsPresenter from './components/CommentsPresenter.svelte' import CreateChannel from './components/CreateChannel.svelte' +import ThreadView from './components/ThreadView.svelte' export { CommentsPresenter } @@ -33,7 +34,8 @@ export default async (): Promise => ({ ChannelView, CommentPresenter, CommentsPresenter, - ChannelPresenter + ChannelPresenter, + ThreadView }, activity: { TxCommentCreate, diff --git a/plugins/chunter-resources/src/plugin.ts b/plugins/chunter-resources/src/plugin.ts index f04de49c63..4c06f51687 100644 --- a/plugins/chunter-resources/src/plugin.ts +++ b/plugins/chunter-resources/src/plugin.ts @@ -32,6 +32,10 @@ export default mergeIds(chunterId, chunter, { ChannelDescription: '' as IntlString, MakePrivate: '' as IntlString, MakePrivateDescription: '' as IntlString, - In: '' as IntlString + In: '' as IntlString, + Replies: '' as IntlString, + Thread: '' as IntlString, + RepliesCount: '' as IntlString, + LastReply: '' as IntlString } }) diff --git a/plugins/chunter/package.json b/plugins/chunter/package.json index 18456e4695..6dfdb1b440 100644 --- a/plugins/chunter/package.json +++ b/plugins/chunter/package.json @@ -28,6 +28,7 @@ "dependencies": { "@anticrm/platform": "~0.6.5", "@anticrm/ui": "~0.6.0", + "@anticrm/contact": "~0.6.5", "@anticrm/core": "~0.6.16" } } diff --git a/plugins/chunter/src/index.ts b/plugins/chunter/src/index.ts index 7e53545452..f96a7e5031 100644 --- a/plugins/chunter/src/index.ts +++ b/plugins/chunter/src/index.ts @@ -13,7 +13,8 @@ // limitations under the License. // -import type { AttachedDoc, Class, Doc, Ref, Space } from '@anticrm/core' +import type { Account, AttachedDoc, Class, Doc, Ref, Space, Timestamp } from '@anticrm/core' +import type { Employee } from '@anticrm/contact' import type { Asset, Plugin } from '@anticrm/platform' import { IntlString, plugin } from '@anticrm/platform' import { AnyComponent } from '@anticrm/ui' @@ -29,6 +30,10 @@ export interface Channel extends Space {} export interface Message extends Doc { content: string attachments?: number + replies?: Ref[] + lastReply?: Timestamp + createBy: Ref + createOn: Timestamp } /** diff --git a/plugins/workbench-resources/src/components/SpaceHeader.svelte b/plugins/workbench-resources/src/components/SpaceHeader.svelte index 7627e93100..a078db3a73 100644 --- a/plugins/workbench-resources/src/components/SpaceHeader.svelte +++ b/plugins/workbench-resources/src/components/SpaceHeader.svelte @@ -84,7 +84,7 @@ {/each}
- {/if} + {/if} { dispatch('search', search) }}/> diff --git a/plugins/workbench-resources/src/components/Workbench.svelte b/plugins/workbench-resources/src/components/Workbench.svelte index 7cfc95c509..7857c90338 100644 --- a/plugins/workbench-resources/src/components/Workbench.svelte +++ b/plugins/workbench-resources/src/components/Workbench.svelte @@ -25,6 +25,7 @@ closeTooltip, Component, getCurrentLocation, location, + Location, navigate, PanelInstance, Popup, @@ -60,6 +61,8 @@ let createItemLabel: IntlString | undefined let navigatorModel: NavigatorModel | undefined + let asideId: string | undefined + onDestroy( location.subscribe(async (loc) => { closeTooltip() @@ -89,22 +92,14 @@ if (spaceId === currentSpace) { // Check if we need update location. const loc = getCurrentLocation() - if (loc.path[3] !== spaceSpecial) { + if (spaceSpecial !== currentSpecial && spaceSpecial !== asideId) { if (spaceSpecial !== undefined) { - loc.path[3] = spaceSpecial - loc.path.length = 4 - } else { - loc.path.length = 3 - } - if (spaceSpecial !== undefined) { - loc.path[3] = spaceSpecial - loc.path.length = 4 - specialComponent = getSpecialComponent(spaceSpecial) - currentSpecial = spaceSpecial + setSpaceSpecial(loc, spaceSpecial) } else { loc.path.length = 3 spaceSpecial = undefined currentSpecial = undefined + asideId = undefined } navigate(loc) } @@ -129,19 +124,33 @@ loc.path[2] = spaceId loc.path.length = 3 if (spaceSpecial !== undefined) { - loc.path[3] = spaceSpecial - currentSpecial = spaceSpecial - loc.path.length = 4 - specialComponent = getSpecialComponent(spaceSpecial) + setSpaceSpecial(loc, spaceSpecial) } navigate(loc) } else { + asideId = undefined currentView = undefined createItemDialog = undefined createItemLabel = undefined } } + function setSpaceSpecial (loc: Location, spaceSpecial: string): void { + loc.path[3] = spaceSpecial + loc.path.length = 4 + specialComponent = getSpecialComponent(spaceSpecial) + if (specialComponent !== undefined) { + currentSpecial = spaceSpecial + asideId = undefined + } else if (navigatorModel?.aside !== undefined) { + asideId = spaceSpecial + } else { + loc.path.length = 3 + currentSpecial = undefined + asideId = undefined + } + } + function selectSpecial (id: string): void { specialComponent = getSpecialComponent(id) if (specialComponent !== undefined) { @@ -247,6 +256,13 @@ limit: 1 } ) + + function closeAside () { + const loc = getCurrentLocation() + loc.path.length = 3 + navigate(loc) + asideId = undefined + } {#if client} @@ -346,7 +362,9 @@ {/if}
- + {#if asideId && navigatorModel?.aside !== undefined} +
+ {/if}
diff --git a/plugins/workbench/src/index.ts b/plugins/workbench/src/index.ts index 771eecd103..38ab48742b 100644 --- a/plugins/workbench/src/index.ts +++ b/plugins/workbench/src/index.ts @@ -54,6 +54,7 @@ export interface SpacesNavModel { export interface NavigatorModel { spaces: SpacesNavModel[] specials?: SpecialNavModel[] + aside?: AnyComponent } /**