diff --git a/plugins/activity-resources/src/activityMessagesUtils.ts b/plugins/activity-resources/src/activityMessagesUtils.ts index 9fbcd5815e..c9287c59aa 100644 --- a/plugins/activity-resources/src/activityMessagesUtils.ts +++ b/plugins/activity-resources/src/activityMessagesUtils.ts @@ -21,6 +21,7 @@ import core, { type Doc, groupByArray, type Hierarchy, + type Mixin, type Ref, SortingOrder, type Timestamp @@ -70,7 +71,13 @@ export async function getAttributeValues (client: Client, values: any[], attrCla const docIds = docs.map(({ _id }) => _id) const missedIds = values.filter((value) => !docIds.includes(value)) const removedDocs = await Promise.all(missedIds.map(async (value) => await buildRemovedDoc(client, value, attrClass))) - return [...docs, ...removedDocs].filter((doc) => !(doc == null)) + const allDocs = [...docs, ...removedDocs].filter((doc) => !(doc == null)) + + if (allDocs.length > 0) { + return allDocs + } + + return values } export function getCollectionAttribute ( @@ -94,6 +101,19 @@ export function getCollectionAttribute ( return undefined } +async function getAttributePresenterSafe ( + client: Client, + _class: Ref<Class<Doc>>, + attrKey: string, + mixin?: Ref<Mixin<Doc>> +): Promise<AttributeModel | undefined> { + try { + return await getAttributePresenter(client, _class, attrKey, { key: attrKey }, mixin) + } catch (e) { + console.error(e) + } +} + export async function getAttributeModel ( client: Client, attributeUpdates: DocAttributeUpdates | undefined, @@ -105,28 +125,24 @@ export async function getAttributeModel ( const hierarchy = client.getHierarchy() - try { - const { attrKey, attrClass, isMixin } = attributeUpdates - let attrObjectClass = objectClass + const { attrKey, attrClass, isMixin } = attributeUpdates + let attrObjectClass = objectClass - if (isMixin) { - const keyedAttribute = getFiltredKeys(hierarchy, attrClass, []).find(({ key }) => key === attrKey) - if (keyedAttribute === undefined) { - return undefined - } - attrObjectClass = keyedAttribute.attr.attributeOf + if (isMixin) { + const keyedAttribute = getFiltredKeys(hierarchy, attrClass, []).find(({ key }) => key === attrKey) + if (keyedAttribute === undefined) { + return undefined } - - return await getAttributePresenter( - client, - attrObjectClass, - attrKey, - { key: attrKey }, - view.mixin.ActivityAttributePresenter - ) - } catch (e) { - // ignore error + attrObjectClass = keyedAttribute.attr.attributeOf } + + const model = await getAttributePresenterSafe(client, attrObjectClass, attrKey, view.mixin.ActivityAttributePresenter) + + if (model !== undefined) { + return model + } + + return await getAttributePresenterSafe(client, attrObjectClass, attrKey) } export function activityMessagesComparator (message1: ActivityMessage, message2: ActivityMessage): number { diff --git a/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessageContent.svelte b/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessageContent.svelte index cc17e09bca..deb12f2b0e 100644 --- a/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessageContent.svelte +++ b/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessageContent.svelte @@ -26,16 +26,12 @@ export let viewlet: DocUpdateMessageViewlet | undefined export let objectName: IntlString export let collectionName: IntlString | undefined - export let objectClass: Ref<Class<Doc>> export let collectionAttribute: Attribute<Collection<AttachedDoc>> | undefined = undefined const client = getClient() const hierarchy = client.getHierarchy() const clazz = hierarchy.getClass(message.objectClass) - const objectPanel = hierarchy.classHierarchyMixin(objectClass, view.mixin.ObjectPanel) - const objectPresenter = hierarchy.classHierarchyMixin(objectClass, view.mixin.ObjectPresenter) - const isOwn = message.objectId === message.attachedTo let valueMessages: DocUpdateMessage[] = [] @@ -71,8 +67,6 @@ {#each createMessages as valueMessage, index} <DocUpdateMessageObjectValue message={valueMessage} - {objectPresenter} - {objectPanel} {viewlet} withIcon={index === 0} hasSeparator={createMessages.length > 1 && index !== createMessages.length - 1} @@ -81,8 +75,6 @@ {#each removeMessages as valueMessage, index} <DocUpdateMessageObjectValue message={valueMessage} - {objectPresenter} - {objectPanel} {viewlet} withIcon={index === 0} hasSeparator={removeMessages.length > 1 && index !== removeMessages.length - 1} @@ -92,8 +84,6 @@ {#each valueMessages as valueMessage, index} <DocUpdateMessageObjectValue message={valueMessage} - {objectPresenter} - {objectPanel} {viewlet} hasSeparator={valueMessages.length > 1 && index !== valueMessages.length - 1} /> diff --git a/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessageObjectValue.svelte b/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessageObjectValue.svelte index d8f23e3402..60332226dc 100644 --- a/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessageObjectValue.svelte +++ b/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessageObjectValue.svelte @@ -22,16 +22,18 @@ export let message: DisplayDocUpdateMessage export let viewlet: DocUpdateMessageViewlet | undefined - export let objectPanel: ObjectPanel | undefined - export let objectPresenter: ObjectPresenter | undefined export let withIcon: boolean = false export let hasSeparator: boolean = false const client = getClient() + const hierarchy = client.getHierarchy() const objectQuery = createQuery() let object: Doc | undefined = undefined + $: objectPanel = hierarchy.classHierarchyMixin(message.objectClass, view.mixin.ObjectPanel) + $: objectPresenter = hierarchy.classHierarchyMixin(message.objectClass, view.mixin.ObjectPresenter) + async function getValue (object: Doc): Promise<string | undefined> { if (viewlet?.valueAttr) { return (object as any)[viewlet.valueAttr] diff --git a/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessagePresenter.svelte b/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessagePresenter.svelte index 916fd1adb2..b1f7ac66ff 100644 --- a/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessagePresenter.svelte +++ b/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessagePresenter.svelte @@ -83,7 +83,7 @@ .getModel() .findAllSync(activity.class.DocUpdateMessageViewlet, { action: value.action, objectClass: value.objectClass }) - $: void getAttributeModel(client, value.attributeUpdates, value.attachedToClass).then((model) => { + $: void getAttributeModel(client, value.attributeUpdates, value.objectClass).then((model) => { attributeModel = model }) @@ -197,14 +197,7 @@ </ShowMore> {:else if value.action === 'create' || value.action === 'remove'} <ShowMore> - <DocUpdateMessageContent - objectClass={value.objectClass} - message={value} - {viewlet} - {objectName} - {collectionName} - {collectionAttribute} - /> + <DocUpdateMessageContent message={value} {viewlet} {objectName} {collectionName} {collectionAttribute} /> </ShowMore> {:else if value.attributeUpdates && attributeModel} <DocUpdateMessageAttributes attributeUpdates={value.attributeUpdates} {attributeModel} {viewlet} /> diff --git a/server-plugins/activity-resources/src/index.ts b/server-plugins/activity-resources/src/index.ts index 7c77b31bd5..d8c73de9d2 100644 --- a/server-plugins/activity-resources/src/index.ts +++ b/server-plugins/activity-resources/src/index.ts @@ -186,7 +186,7 @@ async function pushDocUpdateMessages ( ) } - if (attributesUpdates.length === 0) { + if (attributesUpdates.length === 0 && rawMessage.action !== 'update') { res.push(getDocUpdateMessageTx(control, originTx, object, rawMessage, modifiedBy)) } @@ -254,14 +254,12 @@ export async function generateDocUpdateMessages ( case core.class.TxCollectionCUD: { const actualTx = TxProcessor.extractTx(tx) as TxCUD<Doc> res = await generateDocUpdateMessages(actualTx, control, res, tx, objectCache) - if ([core.class.TxCreateDoc, core.class.TxRemoveDoc].includes(actualTx._class)) { + if ([core.class.TxCreateDoc, core.class.TxRemoveDoc, core.class.TxUpdateDoc].includes(actualTx._class)) { let doc = objectCache?.docs?.get(tx.objectId) if (doc === undefined) { doc = (await control.findAll(tx.objectClass, { _id: tx.objectId }, { limit: 1 }))[0] } - if (doc !== undefined) { - return await pushDocUpdateMessages(control, res, doc ?? undefined, originTx ?? tx, undefined, objectCache) - } + return await pushDocUpdateMessages(control, res, doc ?? undefined, originTx ?? tx, undefined, objectCache) } return res } diff --git a/server-plugins/activity-resources/src/utils.ts b/server-plugins/activity-resources/src/utils.ts index 18123fc43d..31c2e67920 100644 --- a/server-plugins/activity-resources/src/utils.ts +++ b/server-plugins/activity-resources/src/utils.ts @@ -189,6 +189,17 @@ export async function getTxAttributesUpdates ( return [] } + let updateObject = object + + if (updateObject._id !== tx.objectId) { + updateObject = + objectCache?.docs?.get(tx.objectId) ?? (await control.findAll(tx.objectClass, { _id: tx.objectId }))[0] + } + + if (updateObject === undefined) { + return [] + } + const hierarchy = control.hierarchy const keys = getAvailableAttributesKeys(tx, hierarchy) @@ -201,7 +212,14 @@ export async function getTxAttributesUpdates ( const isMixin = hierarchy.isDerived(tx._class, core.class.TxMixin) const mixin = isMixin ? (tx as TxMixin<Doc, Doc>).mixin : undefined - const { doc, prevDoc } = await getDocDiff(control, object._class, object._id, originTx._id, mixin, objectCache) + const { doc, prevDoc } = await getDocDiff( + control, + updateObject._class, + updateObject._id, + originTx._id, + mixin, + objectCache + ) for (const key of keys) { let attrValue = modifiedAttributes[key] @@ -212,7 +230,7 @@ export async function getTxAttributesUpdates ( let attrClass: Ref<Class<Doc>> | undefined = mixin - const clazz = hierarchy.findAttribute(object._class, key) + const clazz = hierarchy.findAttribute(updateObject._class, key) if (clazz !== undefined && 'to' in clazz.type) { attrClass = clazz.type.to as Ref<Class<Doc>> @@ -247,10 +265,18 @@ export async function getTxAttributesUpdates ( } } + let setAttr = [] + + if (Array.isArray(attrValue)) { + setAttr = attrValue + } else if (key in modifiedAttributes) { + setAttr = [attrValue] + } + result.push({ attrKey: key, attrClass, - set: Array.isArray(attrValue) ? attrValue : [attrValue], + set: setAttr, added, removed, prevValue, diff --git a/server-plugins/notification-resources/src/index.ts b/server-plugins/notification-resources/src/index.ts index 439b990cc8..0e92b28fd9 100644 --- a/server-plugins/notification-resources/src/index.ts +++ b/server-plugins/notification-resources/src/index.ts @@ -748,7 +748,7 @@ async function collectionCollabDoc ( const actualTx = TxProcessor.extractTx(tx) as TxCUD<Doc> let res = await createCollaboratorNotifications(actualTx, control, activityMessages, tx) - if (![core.class.TxCreateDoc, core.class.TxRemoveDoc].includes(actualTx._class)) { + if (![core.class.TxCreateDoc, core.class.TxRemoveDoc, core.class.TxUpdateDoc].includes(actualTx._class)) { return res }