From 8407c8970927f6119e5f6e53d268ff536f95a5ea Mon Sep 17 00:00:00 2001 From: Denis Bykhov Date: Thu, 20 Apr 2023 13:27:02 +0600 Subject: [PATCH] Use doc update instead lastView (#3027) Signed-off-by: Denis Bykhov --- plugins/activity-resources/src/activity.ts | 13 +- .../src/components/Activity.svelte | 35 +++--- plugins/activity/src/index.ts | 1 + .../activity/ActivityChannelMessage.svelte | 2 +- .../components/NotificationPresenter.svelte | 6 +- plugins/notification-resources/src/utils.ts | 12 ++ plugins/notification/src/index.ts | 1 + .../notification-resources/src/index.ts | 111 ++---------------- 8 files changed, 54 insertions(+), 127 deletions(-) diff --git a/plugins/activity-resources/src/activity.ts b/plugins/activity-resources/src/activity.ts index 8045420961..db54a38b1c 100644 --- a/plugins/activity-resources/src/activity.ts +++ b/plugins/activity-resources/src/activity.ts @@ -278,6 +278,7 @@ class ActivityImpl implements Activity { createDisplayTx (tx: TxCUD, parents: Map, DisplayTx>, isOwnTx: boolean): [DisplayTx, boolean, boolean] { let collectionAttribute: Attribute> | undefined + const originTx = tx if (this.hierarchy.isDerived(tx._class, core.class.TxCollectionCUD)) { const cltx = tx as TxCollectionCUD tx = TxProcessor.extractTx(cltx) as TxCUD @@ -295,7 +296,7 @@ class ActivityImpl implements Activity { } } let firstTx = parents.get(tx.objectId) - const result: DisplayTx = newDisplayTx(tx, this.hierarchy, isOwnTx) + const result: DisplayTx = newDisplayTx(tx, this.hierarchy, isOwnTx, originTx) result.collectionAttribute = collectionAttribute @@ -418,7 +419,12 @@ function getCombineOpFromTx (result: DisplayTx): any { return curUpdate } -export function newDisplayTx (tx: TxCUD, hierarchy: Hierarchy, isOwnTx: boolean): DisplayTx { +export function newDisplayTx ( + tx: TxCUD, + hierarchy: Hierarchy, + isOwnTx: boolean, + originTx: TxCUD = tx +): DisplayTx { const createTx = hierarchy.isDerived(tx._class, core.class.TxCreateDoc) ? (tx as TxCreateDoc) : undefined return { tx, @@ -430,7 +436,8 @@ export function newDisplayTx (tx: TxCUD, hierarchy: Hierarchy, isOwnTx: boo removed: false, mixin: false, mixinTx: hierarchy.isDerived(tx._class, core.class.TxMixin) ? (tx as TxMixin) : undefined, - doc: createTx !== undefined ? TxProcessor.createDoc2Doc(createTx) : undefined + doc: createTx !== undefined ? TxProcessor.createDoc2Doc(createTx) : undefined, + originTx } } diff --git a/plugins/activity-resources/src/components/Activity.svelte b/plugins/activity-resources/src/components/Activity.svelte index b47bde0c8d..bccf8a4fdf 100644 --- a/plugins/activity-resources/src/components/Activity.svelte +++ b/plugins/activity-resources/src/components/Activity.svelte @@ -15,31 +15,34 @@ @@ -108,7 +105,7 @@ {#if filtered} {#each filtered as tx, i} - + {/each} {/if} diff --git a/plugins/activity/src/index.ts b/plugins/activity/src/index.ts index d8d2726bd9..739e39e3ce 100644 --- a/plugins/activity/src/index.ts +++ b/plugins/activity/src/index.ts @@ -91,6 +91,7 @@ export interface DisplayTx { isOwnTx: boolean collectionAttribute?: Attribute> + originTx: TxCUD } /** diff --git a/plugins/contact-resources/src/components/activity/ActivityChannelMessage.svelte b/plugins/contact-resources/src/components/activity/ActivityChannelMessage.svelte index d7df481f08..ee6b8b1881 100644 --- a/plugins/contact-resources/src/components/activity/ActivityChannelMessage.svelte +++ b/plugins/contact-resources/src/components/activity/ActivityChannelMessage.svelte @@ -67,6 +67,6 @@ $: update(filtered, newTxes) function createDisplayTxes (txes: TxCollectionCUD[]): DisplayTx[] { - return txes.map((p) => newDisplayTx(TxProcessor.extractTx(p) as TxCUD, hierarchy, false)) + return txes.map((p) => newDisplayTx(TxProcessor.extractTx(p) as TxCUD, hierarchy, false, p)) } diff --git a/plugins/notification-resources/src/components/NotificationPresenter.svelte b/plugins/notification-resources/src/components/NotificationPresenter.svelte index f6f0e93235..d3dc3bb672 100644 --- a/plugins/notification-resources/src/components/NotificationPresenter.svelte +++ b/plugins/notification-resources/src/components/NotificationPresenter.svelte @@ -21,10 +21,10 @@ export let kind: 'table' | 'block' = 'block' const notificationClient = NotificationClientImpl.getClient() - const lastViews = notificationClient.getLastViews() + const store = notificationClient.docUpdatesStore + $: docUpdate = $store.get(value._id) - $: lastView = (($lastViews as any) ?? {})[value._id] - $: hasNotification = lastView !== undefined && lastView !== -1 && lastView < value.modifiedOn + $: hasNotification = (docUpdate?.txes?.length ?? 0) > 0 {#if hasNotification} diff --git a/plugins/notification-resources/src/utils.ts b/plugins/notification-resources/src/utils.ts index 5829041425..0916ea508c 100644 --- a/plugins/notification-resources/src/utils.ts +++ b/plugins/notification-resources/src/utils.ts @@ -25,6 +25,9 @@ import { get, writable, Writable } from 'svelte/store' export class NotificationClientImpl implements NotificationClient { protected static _instance: NotificationClientImpl | undefined = undefined private readonly lastViewsStore = writable() + readonly docUpdatesStore = writable, DocUpdates>>(new Map()) + + private readonly docUpdatesQuery = createQuery(true) private readonly lastViewQuery = createQuery() private readonly user: Ref @@ -42,6 +45,15 @@ export class NotificationClientImpl implements NotificationClient { void client.tx(u) } }) + this.docUpdatesQuery.query( + notification.class.DocUpdates, + { + user: this.user + }, + (result) => { + this.docUpdatesStore.set(new Map(result.map((p) => [p.attachedTo, p]))) + } + ) } static createClient (): void { diff --git a/plugins/notification/src/index.ts b/plugins/notification/src/index.ts index 9ff757c425..2d0de5def4 100644 --- a/plugins/notification/src/index.ts +++ b/plugins/notification/src/index.ts @@ -151,6 +151,7 @@ export const notificationId = 'notification' as Plugin * @public */ export interface NotificationClient { + docUpdatesStore: Writable, DocUpdates>> getLastViews: () => Writable updateLastView: (_id: Ref, _class: Ref>, time?: Timestamp, force?: boolean) => Promise unsubscribe: (_id: Ref) => Promise diff --git a/server-plugins/notification-resources/src/index.ts b/server-plugins/notification-resources/src/index.ts index 2573afe023..bb5b50955c 100644 --- a/server-plugins/notification-resources/src/index.ts +++ b/server-plugins/notification-resources/src/index.ts @@ -29,7 +29,6 @@ import core, { Ref, RefTo, Space, - Timestamp, Tx, TxCUD, TxCollectionCUD, @@ -56,8 +55,7 @@ import serverNotification, { TextPresenter, createLastViewTx, getEmployeeAccount, - getEmployeeAccountById, - getUpdateLastViewTx + getEmployeeAccountById } from '@hcengineering/server-notification' import { Content } from './types' import { replaceAll } from './utils' @@ -274,52 +272,12 @@ async function getEmailNotificationTx ( } } -async function getUpdateLastViewTxes ( - doc: Doc, - _id: Ref, - _class: Ref>, - modifiedOn: Timestamp, - user: Ref, - control: TriggerControl -): Promise { - const updatedUsers: Set> = new Set>() - const result: Tx[] = [] - const tx = await getUpdateLastViewTx(control.findAll, _id, modifiedOn, user) - if (tx !== undefined) { - updatedUsers.add(user) - result.push(tx) - } - const docClass = control.hierarchy.getClass(doc._class) - const anotherUserNotifications = control.hierarchy.as(docClass, notification.mixin.AnotherUserNotifications) - for (const field of anotherUserNotifications?.fields ?? []) { - const value = (doc as any)[field] - if (value != null) { - for (const employeeId of Array.isArray(value) ? value : [value]) { - const account = await getEmployeeAccount(employeeId, control) - if (account !== undefined) { - if (updatedUsers.has(account._id)) continue - const assigneeTx = await createLastViewTx(control.findAll, _id, account._id) - if (assigneeTx !== undefined) { - updatedUsers.add(account._id) - result.push(assigneeTx) - } - } - } - } - } - return result -} - /** * @public */ export async function UpdateLastView (tx: Tx, control: TriggerControl): Promise { const actualTx = TxProcessor.extractTx(tx) - if ( - ![core.class.TxUpdateDoc, core.class.TxCreateDoc, core.class.TxMixin, core.class.TxRemoveDoc].includes( - actualTx._class - ) - ) { + if (actualTx._class !== core.class.TxRemoveDoc) { return [] } @@ -329,65 +287,16 @@ export async function UpdateLastView (tx: Tx, control: TriggerControl): Promise< const result: Tx[] = [] - switch (actualTx._class) { - case core.class.TxCreateDoc: { - const createTx = actualTx as TxCreateDoc - if (control.hierarchy.isDerived(createTx.objectClass, core.class.AttachedDoc)) { - const doc = TxProcessor.createDoc2Doc(createTx as TxCreateDoc) - if (control.hierarchy.classHierarchyMixin(doc.attachedToClass, notification.mixin.TrackedDoc) !== undefined) { - const attachedTxes = await getUpdateLastViewTxes( - doc, - doc.attachedTo, - doc.attachedToClass, - createTx.modifiedOn, - createTx.modifiedBy, - control - ) - result.push(...attachedTxes) - } + const removeTx = actualTx as TxRemoveDoc + const lastViews = await control.findAll(notification.class.LastView, { [removeTx.objectId]: { $exists: true } }) + for (const lastView of lastViews) { + const clearTx = control.txFactory.createTxUpdateDoc(lastView._class, lastView.space, lastView._id, { + $unset: { + [removeTx.objectId]: '' } - if (control.hierarchy.classHierarchyMixin(createTx.objectClass, notification.mixin.TrackedDoc) !== undefined) { - const doc = TxProcessor.createDoc2Doc(createTx) - const parentTxes = await getUpdateLastViewTxes( - doc, - doc._id, - doc._class, - createTx.modifiedOn, - createTx.modifiedBy, - control - ) - result.push(...parentTxes) - } - return result - } - case core.class.TxUpdateDoc: - case core.class.TxMixin: { - const tx = actualTx as TxCUD - if (control.hierarchy.classHierarchyMixin(tx.objectClass, notification.mixin.TrackedDoc) !== undefined) { - const doc = (await control.findAll(tx.objectClass, { _id: tx.objectId }, { limit: 1 }))[0] - if (doc !== undefined) { - return await getUpdateLastViewTxes(doc, doc._id, doc._class, tx.modifiedOn, tx.modifiedBy, control) - } - } - break - } - case core.class.TxRemoveDoc: { - const tx = actualTx as TxCUD - const lastViews = await control.findAll(notification.class.LastView, { [tx.objectId]: { $exists: true } }) - for (const lastView of lastViews) { - const clearTx = control.txFactory.createTxUpdateDoc(lastView._class, lastView.space, lastView._id, { - $unset: { - [tx.objectId]: '' - } - }) - result.push(clearTx) - } - return result - } - default: - break + }) + result.push(clearTx) } - return result }