From 83b28a61e6cd17aaf2cb4936dd0bce9251a5d281 Mon Sep 17 00:00:00 2001 From: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> Date: Wed, 6 Apr 2022 12:16:01 +0600 Subject: [PATCH] Migrate thread messages (#1284) Signed-off-by: Denis Bykhov <80476319+BykhovDenis@users.noreply.github.com> --- models/chunter/src/index.ts | 47 ++++++----- models/chunter/src/migration.ts | 78 ++++++++++++++++++- .../src/components/Channel.svelte | 2 +- .../src/components/ChannelView.svelte | 3 + .../src/components/ThreadComment.svelte | 24 +++--- .../src/components/ThreadView.svelte | 36 +++++---- plugins/chunter-resources/src/index.ts | 8 +- plugins/chunter/src/index.ts | 24 +++++- 8 files changed, 164 insertions(+), 58 deletions(-) diff --git a/models/chunter/src/index.ts b/models/chunter/src/index.ts index babb868241..febfc8e14f 100644 --- a/models/chunter/src/index.ts +++ b/models/chunter/src/index.ts @@ -14,16 +14,16 @@ // import activity from '@anticrm/activity' -import type { Backlink, Channel, Comment, Message } from '@anticrm/chunter' -import type { Account, Class, Doc, Domain, Ref, Timestamp } from '@anticrm/core' +import type { Backlink, Channel, ChunterMessage, Comment, Message, ThreadMessage } from '@anticrm/chunter' +import contact, { Employee } from '@anticrm/contact' +import type { Account, Class, Doc, Domain, Ref, Space, Timestamp } from '@anticrm/core' import { IndexKind } from '@anticrm/core' 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 core, { TAttachedDoc, 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' import notification from '@anticrm/model-notification' export const DOMAIN_CHUNTER = 'chunter' as Domain @@ -36,8 +36,8 @@ export class TChannel extends TSpace implements Channel { lastMessage?: Timestamp } -@Model(chunter.class.Message, core.class.Doc, DOMAIN_CHUNTER) -export class TMessage extends TDoc implements Message { +@Model(chunter.class.ChunterMessage, core.class.AttachedDoc, DOMAIN_CHUNTER) +export class TChunterMessage extends TAttachedDoc implements ChunterMessage { @Prop(TypeMarkup(), chunter.string.Content) @Index(IndexKind.FullText) content!: string @@ -45,12 +45,6 @@ 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 @@ -58,6 +52,26 @@ export class TMessage extends TDoc implements Message { createOn!: Timestamp } +@Model(chunter.class.ThreadMessage, chunter.class.ChunterMessage) +export class TThreadMessage extends TChunterMessage implements ThreadMessage { + declare attachedTo: Ref + + declare attachedToClass: Ref> +} + +@Model(chunter.class.Message, chunter.class.ChunterMessage) +export class TMessage extends TChunterMessage implements Message { + declare attachedTo: Ref + + declare attachedToClass: Ref> + + @Prop(ArrOf(TypeRef(contact.class.Employee)), chunter.string.Replies) + replies?: Ref[] + + @Prop(TypeTimestamp(), chunter.string.LastReply) + lastReply?: Timestamp +} + @Model(chunter.class.Comment, core.class.AttachedDoc, DOMAIN_COMMENT) @UX(chunter.string.Comment) export class TComment extends TAttachedDoc implements Comment { @@ -77,7 +91,7 @@ export class TBacklink extends TComment implements Backlink { } export function createModel (builder: Builder): void { - builder.createModel(TChannel, TMessage, TComment, TBacklink) + builder.createModel(TChannel, TMessage, TThreadMessage, TChunterMessage, TComment, TBacklink) builder.mixin(chunter.class.Channel, core.class.Class, workbench.mixin.SpaceView, { view: { class: chunter.class.Message @@ -130,11 +144,8 @@ export function createModel (builder: Builder): void { }) builder.createDoc(view.class.ActionTarget, core.space.Model, { - target: chunter.class.Comment, - action: chunter.action.MarkCommentUnread, - query: { - attachedToClass: chunter.class.Message - } + target: chunter.class.ThreadMessage, + action: chunter.action.MarkCommentUnread }) builder.createDoc(workbench.class.Application, core.space.Model, { diff --git a/models/chunter/src/migration.ts b/models/chunter/src/migration.ts index c12302d6f3..d4c5acc5ac 100644 --- a/models/chunter/src/migration.ts +++ b/models/chunter/src/migration.ts @@ -13,10 +13,10 @@ // limitations under the License. // -import { Message } from '@anticrm/chunter' -import type { Client, Ref } from '@anticrm/core' -import core, { TxOperations } from '@anticrm/core' +import { Comment, Message, ThreadMessage } from '@anticrm/chunter' +import core, { Client, Doc, DOMAIN_TX, Ref, TxCreateDoc, TxOperations } from '@anticrm/core' import { MigrateOperation, MigrationClient, MigrationUpgradeClient } from '@anticrm/model' +import { DOMAIN_CHUNTER, DOMAIN_COMMENT } from './index' import chunter from './plugin' export async function createDeps (client: Client): Promise { @@ -69,8 +69,80 @@ export async function setCreate (client: TxOperations): Promise { await Promise.all(promises) } +export async function migrateMessages (client: MigrationClient): Promise { + const messages = await client.find(DOMAIN_CHUNTER, { + _class: chunter.class.Message, + attachedTo: { $exists: false } + }) + for (const message of messages) { + await client.update(DOMAIN_CHUNTER, { + _id: message._id + }, { + attachedTo: message.space, + attachedToClass: chunter.class.Channel, + collection: 'messages' + }) + } + + const txes = await client.find>(DOMAIN_TX, { + _class: core.class.TxCreateDoc, + objectClass: chunter.class.Message + }) + for (const tx of txes) { + await client.update(DOMAIN_TX, { + _id: tx._id + }, { + 'attributes.attachedTo': tx.objectSpace, + 'attributes.attachedToClass': chunter.class.Channel, + 'attributes.collection': 'messages' + }) + } +} + +export async function migrateThreadMessages (client: MigrationClient): Promise { + const messages = await client.find(DOMAIN_COMMENT, { + _class: chunter.class.Comment, + attachedToClass: chunter.class.Message + }) + for (const message of messages) { + await client.delete(DOMAIN_COMMENT, message._id) + await client.create(DOMAIN_CHUNTER, { + attachedTo: message.attachedTo as Ref, + attachedToClass: message.attachedToClass, + attachments: message.attachments, + content: message.message, + collection: message.collection, + _class: chunter.class.ThreadMessage, + space: message.space, + modifiedOn: message.modifiedOn, + modifiedBy: message.modifiedBy, + createBy: message.modifiedBy, + createOn: message.modifiedOn, + _id: message._id as string as Ref + }) + } + + const txes = await client.find>(DOMAIN_TX, { + _class: core.class.TxCreateDoc, + objectClass: chunter.class.Comment, + 'attributes.attachedToClass': chunter.class.Message + }) + for (const tx of txes) { + await client.update(DOMAIN_TX, { + _id: tx._id + }, { + objectClass: chunter.class.ThreadMessage, + 'attributes.createBy': tx.modifiedBy, + 'attributes.createOn': tx.modifiedOn, + 'attributes.content': tx.attributes.message + }) + } +} + export const chunterOperation: MigrateOperation = { async migrate (client: MigrationClient): Promise { + await migrateMessages(client) + await migrateThreadMessages(client) }, async upgrade (client: MigrationUpgradeClient): Promise { const tx = new TxOperations(client, core.account.System) diff --git a/plugins/chunter-resources/src/components/Channel.svelte b/plugins/chunter-resources/src/components/Channel.svelte index 3e54ae0856..b71c8dd5a4 100644 --- a/plugins/chunter-resources/src/components/Channel.svelte +++ b/plugins/chunter-resources/src/components/Channel.svelte @@ -97,7 +97,7 @@ function markUnread (lastViews: Map, number>) { if (messages === undefined) return const newPos = newMessagesStart(messages) - if (newPos < newMessagesPos || newMessagesPos === -1) { + if (newPos !== -1 || newMessagesPos === -1) { newMessagesPos = newPos } } diff --git a/plugins/chunter-resources/src/components/ChannelView.svelte b/plugins/chunter-resources/src/components/ChannelView.svelte index 6e602b5dc4..662e8e5175 100644 --- a/plugins/chunter-resources/src/components/ChannelView.svelte +++ b/plugins/chunter-resources/src/components/ChannelView.svelte @@ -36,6 +36,9 @@ const me = getCurrentAccount()._id const txFactory = new TxFactory(me) const tx = txFactory.createTxCreateDoc(_class, space, { + attachedTo: space, + attachedToClass: chunter.class.Channel, + collection: 'messages', content: message, createOn: 0, createBy: me, diff --git a/plugins/chunter-resources/src/components/ThreadComment.svelte b/plugins/chunter-resources/src/components/ThreadComment.svelte index 95108d51cf..22affdaeba 100644 --- a/plugins/chunter-resources/src/components/ThreadComment.svelte +++ b/plugins/chunter-resources/src/components/ThreadComment.svelte @@ -15,7 +15,7 @@