2022-01-11 09:09:52 +00:00
|
|
|
import type { TxViewlet } from '@anticrm/activity'
|
2022-02-16 09:02:31 +00:00
|
|
|
import core, { AttachedDoc, Class, Collection, Doc, Ref, TxCUD, TxOperations } from '@anticrm/core'
|
2022-02-08 09:05:12 +00:00
|
|
|
import { Asset, IntlString, translate } from '@anticrm/platform'
|
2022-01-11 09:09:52 +00:00
|
|
|
import { AnyComponent, AnySvelteComponent } from '@anticrm/ui'
|
|
|
|
import { AttributeModel } from '@anticrm/view'
|
|
|
|
import { buildModel, getObjectPresenter } from '@anticrm/view-resources'
|
|
|
|
import { ActivityKey, activityKey, DisplayTx } from '../activity'
|
2022-02-16 09:02:31 +00:00
|
|
|
import activity from '../plugin'
|
2022-01-11 09:09:52 +00:00
|
|
|
|
|
|
|
export type TxDisplayViewlet =
|
2022-02-08 09:05:12 +00:00
|
|
|
| (Pick<TxViewlet, 'icon' | 'label' | 'display' | 'editable' | 'hideOnRemove' | 'labelComponent' | 'labelParams'> & {
|
2022-01-11 09:09:52 +00:00
|
|
|
component?: AnyComponent | AnySvelteComponent
|
|
|
|
})
|
|
|
|
| undefined
|
|
|
|
|
|
|
|
async function createPseudoViewlet (
|
2022-01-13 09:06:50 +00:00
|
|
|
client: TxOperations,
|
2022-01-11 09:09:52 +00:00
|
|
|
dtx: DisplayTx,
|
2022-02-08 09:05:12 +00:00
|
|
|
label: IntlString
|
2022-01-11 09:09:52 +00:00
|
|
|
): Promise<TxDisplayViewlet> {
|
|
|
|
const doc = dtx.doc
|
|
|
|
if (doc === undefined) {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
const docClass: Class<Doc> = client.getModel().getObject(doc._class)
|
|
|
|
|
2022-02-16 09:02:31 +00:00
|
|
|
let trLabel = await translate(docClass.label, {})
|
|
|
|
if (dtx.collectionAttribute !== undefined) {
|
|
|
|
const itemLabel = (dtx.collectionAttribute.type as Collection<AttachedDoc>).itemLabel
|
|
|
|
if (itemLabel !== undefined) {
|
|
|
|
trLabel = await translate(itemLabel, {})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Check if it is attached doc and collection have title override.
|
2022-01-11 09:09:52 +00:00
|
|
|
const presenter = await getObjectPresenter(client, doc._class, { key: 'doc-presenter' })
|
|
|
|
if (presenter !== undefined) {
|
|
|
|
return {
|
|
|
|
display: 'inline',
|
|
|
|
icon: docClass.icon ?? activity.icon.Activity,
|
2022-02-08 09:05:12 +00:00
|
|
|
label: label,
|
2022-02-28 04:32:44 +00:00
|
|
|
labelParams: { _class: trLabel, collection: dtx.collectionAttribute?.label !== undefined ? await translate(dtx.collectionAttribute?.label, {}) : '' },
|
2022-01-11 09:09:52 +00:00
|
|
|
component: presenter.presenter
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-02-28 04:32:44 +00:00
|
|
|
export function getDTxProps (dtx: DisplayTx): any {
|
|
|
|
return { tx: dtx.tx, value: dtx.doc, dtx }
|
|
|
|
}
|
|
|
|
|
2022-01-11 09:09:52 +00:00
|
|
|
export async function updateViewlet (
|
2022-01-13 09:06:50 +00:00
|
|
|
client: TxOperations,
|
2022-01-11 09:09:52 +00:00
|
|
|
viewlets: Map<ActivityKey, TxViewlet>,
|
|
|
|
dtx: DisplayTx
|
|
|
|
): Promise<{
|
|
|
|
viewlet: TxDisplayViewlet
|
|
|
|
id: Ref<TxCUD<Doc>>
|
|
|
|
model: AttributeModel[]
|
|
|
|
props: any
|
|
|
|
modelIcon: Asset | undefined
|
|
|
|
}> {
|
|
|
|
const key = activityKey(dtx.tx.objectClass, dtx.tx._class)
|
|
|
|
let viewlet: TxDisplayViewlet = viewlets.get(key)
|
|
|
|
|
2022-02-28 04:32:44 +00:00
|
|
|
const props = getDTxProps(dtx)
|
2022-01-11 09:09:52 +00:00
|
|
|
let model: AttributeModel[] = []
|
|
|
|
let modelIcon: Asset | undefined
|
|
|
|
|
|
|
|
if (viewlet === undefined) {
|
|
|
|
;({ viewlet, model } = await checkInlineViewlets(dtx, viewlet, client, model))
|
|
|
|
if (model !== undefined) {
|
|
|
|
// Check for State attribute
|
|
|
|
for (const a of model) {
|
|
|
|
if (a.icon !== undefined) {
|
|
|
|
modelIcon = a.icon
|
|
|
|
break
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return { viewlet, id: dtx.tx._id, model, props, modelIcon }
|
|
|
|
}
|
|
|
|
|
|
|
|
async function checkInlineViewlets (
|
|
|
|
dtx: DisplayTx,
|
|
|
|
viewlet: TxDisplayViewlet,
|
2022-01-13 09:06:50 +00:00
|
|
|
client: TxOperations,
|
2022-01-11 09:09:52 +00:00
|
|
|
model: AttributeModel[]
|
|
|
|
): Promise<{ viewlet: TxDisplayViewlet, model: AttributeModel[] }> {
|
2022-02-28 04:32:44 +00:00
|
|
|
if (dtx.collectionAttribute !== undefined && dtx.txes.length > 0) {
|
|
|
|
// Check if we have a class presenter we could have a pseudo viewlet based on class presenter.
|
|
|
|
viewlet = await createPseudoViewlet(client, dtx, activity.string.CollectionUpdated)
|
|
|
|
} else if (dtx.tx._class === core.class.TxCreateDoc) {
|
2022-01-11 09:09:52 +00:00
|
|
|
// Check if we have a class presenter we could have a pseudo viewlet based on class presenter.
|
2022-02-08 09:05:12 +00:00
|
|
|
viewlet = await createPseudoViewlet(client, dtx, activity.string.DocCreated)
|
2022-02-28 04:32:44 +00:00
|
|
|
} else if (dtx.tx._class === core.class.TxRemoveDoc) {
|
2022-02-08 09:05:12 +00:00
|
|
|
viewlet = await createPseudoViewlet(client, dtx, activity.string.DocDeleted)
|
2022-02-28 04:32:44 +00:00
|
|
|
} else if (dtx.tx._class === core.class.TxUpdateDoc) {
|
2022-01-11 09:09:52 +00:00
|
|
|
model = await createUpdateModel(dtx, client, model)
|
|
|
|
}
|
|
|
|
return { viewlet, model }
|
|
|
|
}
|
|
|
|
|
|
|
|
async function createUpdateModel (
|
|
|
|
dtx: DisplayTx,
|
2022-01-13 09:06:50 +00:00
|
|
|
client: TxOperations,
|
2022-01-11 09:09:52 +00:00
|
|
|
model: AttributeModel[]
|
|
|
|
): Promise<AttributeModel[]> {
|
|
|
|
if (dtx.updateTx !== undefined) {
|
|
|
|
const _class = dtx.updateTx.objectClass
|
|
|
|
const ops = {
|
|
|
|
client,
|
|
|
|
_class,
|
|
|
|
keys: Object.keys(dtx.updateTx.operations).filter((id) => !id.startsWith('$')),
|
|
|
|
ignoreMissing: true
|
|
|
|
}
|
|
|
|
const hiddenAttrs = getHiddenAttrs(client, _class)
|
|
|
|
model = (await buildModel(ops)).filter((x) => !hiddenAttrs.has(x.key))
|
|
|
|
} else if (dtx.mixinTx !== undefined) {
|
|
|
|
const _class = dtx.mixinTx.mixin
|
|
|
|
const ops = {
|
|
|
|
client,
|
|
|
|
_class,
|
|
|
|
keys: Object.keys(dtx.mixinTx.attributes).filter((id) => !id.startsWith('$')),
|
|
|
|
ignoreMissing: true
|
|
|
|
}
|
|
|
|
const hiddenAttrs = getHiddenAttrs(client, _class)
|
|
|
|
model = (await buildModel(ops)).filter((x) => !hiddenAttrs.has(x.key))
|
|
|
|
}
|
|
|
|
return model
|
|
|
|
}
|
|
|
|
|
2022-01-13 09:06:50 +00:00
|
|
|
function getHiddenAttrs (client: TxOperations, _class: Ref<Class<Doc>>): Set<string> {
|
2022-01-11 09:09:52 +00:00
|
|
|
return new Set(
|
|
|
|
[...client.getHierarchy().getAllAttributes(_class).entries()]
|
|
|
|
.filter(([, attr]) => attr.hidden === true)
|
|
|
|
.map(([k]) => k)
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2022-01-13 09:06:50 +00:00
|
|
|
export async function getValue (client: TxOperations, m: AttributeModel, utx: any): Promise<any> {
|
2022-01-11 09:09:52 +00:00
|
|
|
const val = utx[m.key]
|
|
|
|
|
|
|
|
if (client.getHierarchy().isDerived(m._class, core.class.Doc) && typeof val === 'string') {
|
|
|
|
// We have an reference, we need to find a real object to pass for presenter
|
|
|
|
return await client.findOne(m._class, { _id: val as Ref<Doc> })
|
|
|
|
}
|
|
|
|
return val
|
|
|
|
}
|