Signed-off-by: Andrey Sobolev <haiodo@gmail.com>
This commit is contained in:
Andrey Sobolev 2021-11-29 22:19:21 +07:00 committed by GitHub
parent 0800f97f3c
commit c26c92023e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 67 additions and 47 deletions

View File

@ -140,16 +140,14 @@ class ActivityImpl implements Activity {
const parents = new Map<Ref<Doc>, DisplayTx>()
const results: DisplayTx[] = []
let results: DisplayTx[] = []
for (const tx of txCUD) {
const { collectionCUD, updateCUD, result, tx: ntx } = this.createDisplayTx(tx, parents)
// We do not need collection object updates, in main list of displayed transactions.
if (this.isDisplayTxRequired(collectionCUD, updateCUD, ntx, object)) {
// Combine previous update transaction for same field and if same operation and time treshold is ok
this.checkIntegratePreviousTx(results, result)
results.push(result)
results = this.integrateTxWithResults(results, result)
this.updateRemovedState(result, results)
}
}
@ -188,7 +186,7 @@ class ActivityImpl implements Activity {
let updateCUD = false
const hierarchy = this.client.getHierarchy()
if (hierarchy.isDerived(tx._class, core.class.TxCollectionCUD)) {
tx = getCollectionTx((tx as TxCollectionCUD<Doc, AttachedDoc>))
tx = getCollectionTx(tx as TxCollectionCUD<Doc, AttachedDoc>)
collectionCUD = true
}
let firstTx = parents.get(tx.objectId)
@ -237,24 +235,27 @@ class ActivityImpl implements Activity {
}
}
checkIntegratePreviousTx (results: DisplayTx[], result: DisplayTx): void {
if (results.length > 0) {
const prevTx = results[results.length - 1]
integrateTxWithResults (results: DisplayTx[], result: DisplayTx): DisplayTx[] {
const curUpdate = result.tx as unknown as TxUpdateDoc<Doc>
const newResult = results.filter((prevTx) => {
if (this.isSameKindTx(prevTx, result)) {
const prevUpdate = prevTx.tx as unknown as TxUpdateDoc<Doc>
const curUpdate = result.tx as unknown as TxUpdateDoc<Doc>
if (
isEqualOps(prevUpdate.operations, curUpdate.operations) &&
result.tx.modifiedOn - prevUpdate.modifiedOn < combineThreshold
result.tx.modifiedOn - prevUpdate.modifiedOn < combineThreshold &&
isEqualOps(prevUpdate.operations, curUpdate.operations)
) {
// we have same keys, l
// we have same keys,
// Remember previous transactions
result.txes.push(...prevTx.txes, prevTx.tx)
// Remove last item
results.splice(results.length - 1, 1)
return false
}
}
}
return true
})
newResult.push(result)
return newResult
}
isSameKindTx (prevTx: DisplayTx, result: DisplayTx): boolean {

View File

@ -20,7 +20,18 @@
import core, { Class, Doc, Ref, TxCUD, TxUpdateDoc } from '@anticrm/core'
import { getResource, IntlString } from '@anticrm/platform'
import { getClient } from '@anticrm/presentation'
import { AnyComponent, AnySvelteComponent, Component, Icon, IconEdit, IconMoreH, Label, Menu, showPopup, TimeSince } from '@anticrm/ui'
import {
AnyComponent,
AnySvelteComponent,
Component,
Icon,
IconEdit,
IconMoreH,
Label,
Menu,
showPopup,
TimeSince
} from '@anticrm/ui'
import type { Action, AttributeModel } from '@anticrm/view'
import { buildModel, getActions, getObjectPresenter } from '@anticrm/view-resources'
import { activityKey, ActivityKey, DisplayTx } from '../activity'
@ -29,7 +40,9 @@
export let viewlets: Map<ActivityKey, TxViewlet>
type TxDisplayViewlet =
| (Pick<TxViewlet, 'icon' | 'label' | 'display'|'editable' | 'hideOnRemove'> & { component?: AnyComponent | AnySvelteComponent })
| (Pick<TxViewlet, 'icon' | 'label' | 'display' | 'editable' | 'hideOnRemove'> & {
component?: AnyComponent | AnySvelteComponent
})
| undefined
let ptx: DisplayTx | undefined
@ -102,7 +115,7 @@
const ops = {
client,
_class: tx.updateTx.objectClass,
keys: Object.keys(tx.updateTx.operations).filter(id => !id.startsWith('$')),
keys: Object.keys(tx.updateTx.operations).filter((id) => !id.startsWith('$')),
ignoreMissing: true
}
buildModel(ops).then((m) => {
@ -118,24 +131,30 @@
return (utx.operations as any)[key]
}
const showMenu = async (ev: MouseEvent): Promise<void> => {
showPopup(Menu, {
actions: [{
label: activity.string.Edit,
icon: IconEdit,
action: () => {
edit = true
props = { ...props, edit }
}
}, ...actions.map(a => ({
label: a.label,
icon: a.icon,
action: async () => {
const impl = await getResource(a.action)
await impl(tx.doc as Doc)
}
}))
]
}, ev.target as HTMLElement)
showPopup(
Menu,
{
actions: [
{
label: activity.string.Edit,
icon: IconEdit,
action: () => {
edit = true
props = { ...props, edit }
}
},
...actions.map((a) => ({
label: a.label,
icon: a.icon,
action: async () => {
const impl = await getResource(a.action)
await impl(tx.doc as Doc)
}
}))
]
},
ev.target as HTMLElement
)
}
const onCancelEdit = () => {
edit = false
@ -164,23 +183,21 @@
{/if}
</div>
{#if viewlet && viewlet?.editable}
<div class='edited'>
<div class="edited">
{#if viewlet.label}
<Label label={viewlet.label} />
{/if}
{#if tx.updated}
<Label label={activity.string.Edited}/>
<Label label={activity.string.Edited} />
{/if}
<div class="menuOptions" on:click={(ev) => showMenu(ev)}>
<IconMoreH size={'small'} />
</div>
</div>
{:else}
{#if viewlet && viewlet.label}
<div>
<Label label={viewlet.label} />
</div>
{/if}
{:else if viewlet && viewlet.label}
<div>
<Label label={viewlet.label} />
</div>
{/if}
{#if viewlet === undefined && model.length > 0 && tx.updateTx}
{#each model as m}
@ -237,10 +254,12 @@
// :global(.msgactivity-container > *:last-child::after) { content: none; }
.menuOptions {
margin-left: .5rem;
opacity: .6;
margin-left: 0.5rem;
opacity: 0.6;
cursor: pointer;
&:hover { opacity: 1; }
&:hover {
opacity: 1;
}
}
.icon {
flex-shrink: 0;