Files
huly-platform/plugins/activity-resources/src/components/doc-update-message/DocUpdateMessagePresenter.svelte
T
2024-09-27 01:34:25 +07:00

254 lines
8.3 KiB
Svelte

<!--
// Copyright © 2023 Hardcore Engineering Inc.
//
// Licensed under the Eclipse Public License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License. You may
// obtain a copy of the License at https://www.eclipse.org/legal/epl-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
//
// See the License for the specific language governing permissions and
// limitations under the License.
-->
<script lang="ts">
import activity, {
ActivityMessage,
ActivityMessageViewType,
DisplayActivityMessage,
DisplayDocUpdateMessage,
DocUpdateMessage,
DocUpdateMessageViewlet
} from '@hcengineering/activity'
import { Person, PersonAccount } from '@hcengineering/contact'
import { personAccountByIdStore, personByIdStore } from '@hcengineering/contact-resources'
import { Account, AttachedDoc, Class, Collection, Doc, Ref, Space } from '@hcengineering/core'
import { IntlString } from '@hcengineering/platform'
import { createQuery, getClient } from '@hcengineering/presentation'
import { Action, Component, ShowMore } from '@hcengineering/ui'
import { AttributeModel } from '@hcengineering/view'
import { buildRemovedDoc, checkIsObjectRemoved } from '@hcengineering/view-resources'
import ActivityMessageTemplate from '../activity-message/ActivityMessageTemplate.svelte'
import DocUpdateMessageAttributes from './DocUpdateMessageAttributes.svelte'
import DocUpdateMessageContent from './DocUpdateMessageContent.svelte'
import DocUpdateMessageHeader from './DocUpdateMessageHeader.svelte'
import { getAttributeModel, getCollectionAttribute } from '../../activityMessagesUtils'
import { getIsTextType } from '../../utils'
export let value: DisplayDocUpdateMessage
export let doc: Doc | undefined = undefined
export let showNotify: boolean = false
export let isHighlighted: boolean = false
export let isSelected: boolean = false
export let shouldScroll: boolean = false
export let embedded: boolean = false
export let withActions: boolean = true
export let showEmbedded = false
export let hideFooter = false
export let actions: Action[] = []
export let skipLabel = false
export let hoverable = true
export let hoverStyles: 'borderedHover' | 'filledHover' = 'borderedHover'
export let hideLink = false
export let type: ActivityMessageViewType = 'default'
export let readonly = false
export let space: Ref<Space> | undefined = undefined
export let onClick: (() => void) | undefined = undefined
const client = getClient()
const hierarchy = client.getHierarchy()
const objectQuery = createQuery()
const parentObjectQuery = createQuery()
let objectName: IntlString | undefined = undefined
let collectionName: IntlString | undefined = undefined
$: collectionAttribute = getCollectionAttribute(hierarchy, value.attachedToClass, value.updateCollection)
$: clazz = hierarchy.getClass(value.objectClass)
$: objectName = (collectionAttribute?.type as Collection<AttachedDoc>)?.itemLabel ?? clazz.label
$: collectionName = collectionAttribute?.label
let person: Person | undefined = undefined
let viewlet: DocUpdateMessageViewlet | undefined
let attributeModel: AttributeModel | undefined = undefined
let parentMessage: DisplayActivityMessage | undefined = undefined
let parentObject: Doc | undefined
let object: Doc | undefined
let isObjectRemoved: boolean = false
$: [viewlet] = client
.getModel()
.findAllSync(activity.class.DocUpdateMessageViewlet, { action: value.action, objectClass: value.objectClass })
$: void getAttributeModel(client, value.attributeUpdates, value.objectClass).then((model) => {
attributeModel = model
})
async function getParentMessage (
_class: Ref<Class<Doc>>,
_id: Ref<Doc>,
space: Ref<Space>
): Promise<ActivityMessage | undefined> {
if (hierarchy.isDerived(_class, activity.class.ActivityMessage)) {
return await client.findOne(activity.class.ActivityMessage, { _id: _id as Ref<ActivityMessage>, space })
}
}
$: void getParentMessage(value.attachedToClass, value.attachedTo, value.space).then((res) => {
parentMessage = res as DisplayActivityMessage
})
$: person = getPerson(value.createdBy, $personAccountByIdStore, $personByIdStore)
function getPerson (
_id: Ref<Account> | undefined,
accountById: Map<Ref<PersonAccount>, PersonAccount>,
personById: Map<Ref<Person>, Person>
): Person | undefined {
if (_id === undefined) {
return undefined
}
const personAccount = accountById.get(_id as Ref<PersonAccount>)
if (personAccount === undefined) {
return undefined
}
return personById.get(personAccount.person)
}
$: void loadObject(value.objectId, value.objectClass, doc)
$: void loadParentObject(value, parentMessage, doc)
async function loadObject (_id: Ref<Doc>, _class: Ref<Class<Doc>>, doc?: Doc): Promise<void> {
if (doc !== undefined && doc._id === _id) {
object = doc
isObjectRemoved = false
return
}
isObjectRemoved = await checkIsObjectRemoved(client, _id, _class)
if (isObjectRemoved) {
object = await buildRemovedDoc(client, _id, _class)
} else {
objectQuery.query(_class, { _id }, (res) => {
object = res[0]
})
}
}
async function loadParentObject (
message: Pick<DocUpdateMessage, 'attachedTo' | 'attachedToClass' | 'objectId' | 'space'>,
parentMessage?: Pick<ActivityMessage, 'attachedTo' | 'space' | 'attachedToClass'>,
doc?: Doc
): Promise<void> {
if (parentMessage === undefined && message.objectId === message.attachedTo) {
return
}
const _id = parentMessage !== undefined ? parentMessage.attachedTo : message.attachedTo
const _class = parentMessage !== undefined ? parentMessage.attachedToClass : message.attachedToClass
const space = parentMessage !== undefined ? parentMessage.space : message.space
if (doc !== undefined && doc._id === _id) {
parentObject = doc
return
}
const isRemoved = await checkIsObjectRemoved(client, _id, _class)
if (isRemoved) {
parentObject = await buildRemovedDoc(client, _id, _class)
return
}
parentObjectQuery.query(_class, { _id, space }, (res) => {
parentObject = res[0]
})
}
$: if (object != null && value.objectClass !== object._class) {
object = undefined
}
</script>
<ActivityMessageTemplate
message={value}
{parentMessage}
{person}
{showNotify}
{isHighlighted}
{isSelected}
{shouldScroll}
{embedded}
{withActions}
{viewlet}
{showEmbedded}
{hideFooter}
{actions}
{skipLabel}
{hoverable}
{hoverStyles}
{readonly}
type={viewlet?.label || getIsTextType(attributeModel) ? 'default' : type}
showDatePreposition={hideLink}
{onClick}
>
<svelte:fragment slot="header">
<DocUpdateMessageHeader message={value} {object} {parentObject} {viewlet} {person} {attributeModel} {hideLink} />
</svelte:fragment>
<svelte:fragment slot="content">
{#if viewlet?.component && object}
<ShowMore>
<div class="customContent">
{#each value?.previousMessages ?? [] as msg}
<Component
is={viewlet.component}
props={{ message: msg, _id: msg.objectId, _class: msg.objectClass, onClick }}
/>
{/each}
<Component
is={viewlet.component}
props={{ message: value, _id: value.objectId, _class: value.objectClass, value: object, onClick }}
/>
</div>
</ShowMore>
{:else if value.action === 'create' || value.action === 'remove'}
<ShowMore>
<DocUpdateMessageContent
message={value}
{viewlet}
{objectName}
{collectionName}
objectIcon={collectionAttribute?.icon ?? clazz.icon}
/>
</ShowMore>
{:else if value.attributeUpdates && attributeModel}
<DocUpdateMessageAttributes
attributeUpdates={value.attributeUpdates}
{attributeModel}
{viewlet}
{space}
{object}
message={value}
/>
{/if}
</svelte:fragment>
</ActivityMessageTemplate>
<style lang="scss">
.customContent {
display: flex;
flex-wrap: wrap;
column-gap: 0.625rem;
row-gap: 0.625rem;
}
</style>