refactor attachments

Signed-off-by: Andrey Platov <andrey@hardcoreeng.com>
This commit is contained in:
Andrey Platov 2021-10-23 16:03:37 +02:00
parent 7cdaaf9224
commit b3e88daf3c
No known key found for this signature in database
GPG Key ID: C8787EFEB4B64AF0
15 changed files with 1022 additions and 942 deletions
dev
server-chunter-resources/src
storage/src
tool/src
models
chunter/src
demo/src
recruit/src
server-chunter/src
packages/core/src
plugins
chunter-resources/src/components
chunter/src
recruit-resources/src/components
recruit/src
server
chunter-resources/src
chunter/src
workspace/src

View File

@ -14,8 +14,9 @@
// limitations under the License.
//
import type { Tx, TxCreateDoc, Data, Ref, Doc, TxFactory } from '@anticrm/core'
import type { Message, Backlink } from '@anticrm/chunter'
import type { Tx, TxCreateDoc, Data, Ref, Doc, TxFactory, Class } from '@anticrm/core'
import type { FindAll } from '@anticrm/server-core'
import type { Message, Backlink, Attachment } from '@anticrm/chunter'
import core from '@anticrm/core'
import chunter from '@anticrm/chunter'
@ -26,6 +27,7 @@ function extractBacklinks (backlinkId: Ref<Doc>, message: string, kids: NodeList
if (kid.nodeName === 'span') {
result.push({
attachedTo: kid.getAttribute('data-id') as Ref<Doc>,
attachedToClass: kid.getAttribute('data-class') as Ref<Class<Doc>>,
backlinkId,
backlinkClass: chunter.class.Message,
message
@ -57,9 +59,30 @@ export async function OnMessage (tx: Tx, txFactory: TxFactory): Promise<Tx[]> {
return []
}
interface WithAttachements extends Doc {
attachments: number
}
/**
* @public
*/
export async function OnAttachment (tx: Tx, txFactory: TxFactory, findAll: FindAll<Doc>): Promise<Tx[]> {
if (tx._class === core.class.TxCreateDoc) {
const createTx = tx as TxCreateDoc<Attachment>
if (createTx.objectClass === chunter.class.Attachment) {
const _id = createTx.attributes.attachedTo as Ref<WithAttachements>
const _class = createTx.attributes.attachedToClass as Ref<Class<WithAttachements>>
const attachedTo = (await findAll(_class, { _id }))[0]
return [txFactory.createTxUpdateDoc(_class, attachedTo.space, _id, { $inc: { attachments: 1 } })]
}
}
return []
}
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export default async () => ({
trigger: {
OnMessage
OnMessage,
OnAttachment
}
})

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -17,7 +17,7 @@ import type { IntlString } from '@anticrm/platform'
import { Builder, Model, Prop, UX, TypeString, Index } from '@anticrm/model'
import type { Ref, Doc, Class, Domain } from '@anticrm/core'
import { IndexKind } from '@anticrm/core'
import core, { TSpace, TDoc, TObj } from '@anticrm/model-core'
import core, { TSpace, TDoc } from '@anticrm/model-core'
import type { Backlink, Channel, Message, Comment, Attachment } from '@anticrm/chunter'
import type { AnyComponent } from '@anticrm/ui'
@ -44,6 +44,7 @@ export class TMessage extends TDoc implements Message {
@Model(chunter.class.Comment, core.class.Doc, DOMAIN_COMMENT)
export class TComment extends TDoc implements Comment {
attachedTo!: Ref<Doc>
attachedToClass!: Ref<Class<Doc>>
@Prop(TypeString(), 'Message' as IntlString)
@Index(IndexKind.FullText)
message!: string
@ -55,8 +56,10 @@ export class TBacklink extends TComment implements Backlink {
backlinkClass!: Ref<Class<Doc>>
}
@Model(chunter.class.Attachment, core.class.Obj, DOMAIN_ATTACHMENT)
export class TAttachment extends TObj implements Attachment {
@Model(chunter.class.Attachment, core.class.Doc, DOMAIN_ATTACHMENT)
export class TAttachment extends TDoc implements Attachment {
attachedTo!: Ref<Doc>
attachedToClass!: Ref<Class<Doc>>
name!: string
file!: string
size!: number

View File

@ -44,8 +44,7 @@ export function createDemo (builder: Builder): void {
provider: contact.channelProvider.Email,
value: 'andrey@hc.engineering'
}
],
attachments: {}
]
})
builder.createDoc(recruit.class.Candidate, recruit.space.CandidatesPublic, {
@ -57,8 +56,7 @@ export function createDemo (builder: Builder): void {
provider: contact.channelProvider.Email,
value: 'marina@hc.engineering'
}
],
attachments: {}
]
})
builder.createDoc(recruit.class.Candidate, recruit.space.CandidatesPublic, {
@ -70,7 +68,6 @@ export function createDemo (builder: Builder): void {
provider: contact.channelProvider.Email,
value: 'alex@hc.engineering'
}
],
attachments: {}
]
})
}

View File

@ -43,8 +43,8 @@ export class TCandidate extends TPerson implements Candidate {
@Prop(TypeString(), 'Title' as IntlString)
title?: string
@Prop(TypeBag(), 'Attachments' as IntlString)
attachments!: Bag<Attachment>
@Prop(TypeString(), 'Attachments' as IntlString)
attachments?: number
@Prop(TypeString(), 'Applications' as IntlString)
applications?: number

View File

@ -24,4 +24,7 @@ export function createModel (builder: Builder): void {
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverChunter.trigger.OnMessage
})
builder.createDoc(serverCore.class.Trigger, core.space.Model, {
trigger: serverChunter.trigger.OnAttachment
})
}

View File

@ -66,6 +66,7 @@ export interface UXObject extends Obj {
*/
export interface AttachedDoc extends Doc {
attachedTo: Ref<Doc>
attachedToClass: Ref<Class<Doc>>
}
/**

View File

@ -15,13 +15,13 @@
-->
<script lang="ts">
import type { Bag } from '@anticrm/core'
import type { Doc } from '@anticrm/core'
import type { Attachment } from '@anticrm/chunter'
import { IconFile, Link, Tooltip, IconAttachment } from '@anticrm/ui'
import { PDFViewer } from '@anticrm/presentation'
import AttachmentPopup from './AttachmentPopup.svelte'
export let value: { attachments: Bag<Attachment> }
export let value: Doc & { attachments?: number }
</script>
@ -33,10 +33,10 @@
</Tooltip>
{/if} -->
{#if value.attachments && Object.keys(value.attachments).length > 0}
<Tooltip label={'Attachments (' + Object.values(value.attachments).length + ')'} component={AttachmentPopup} props={{ files: value.attachments }}>
{#if value.attachments && value.attachments > 0}
<Tooltip label={'Attachments (' + value.attachments + ')'} component={AttachmentPopup} props={{ files: value._id }}>
<div class="sm-tool-icon">
<span class="icon"><IconAttachment size="small"/></span>{Object.keys(value.attachments).length}
<span class="icon"><IconAttachment size="small"/></span>{value.attachments}
</div>
</Tooltip>
{/if}

View File

@ -15,7 +15,7 @@
import { plugin } from '@anticrm/platform'
import type { Asset, Plugin } from '@anticrm/platform'
import type { Space, Obj, Doc, Ref, Class, AttachedDoc } from '@anticrm/core'
import type { Space, Doc, Ref, Class, AttachedDoc } from '@anticrm/core'
/**
* @public
@ -47,7 +47,7 @@ export interface Backlink extends Comment {
/**
* @public
*/
export interface Attachment extends Obj {
export interface Attachment extends AttachedDoc {
name: string
file: string
size: number

View File

@ -26,14 +26,14 @@
import chunter from '@anticrm/chunter'
export let objectId: Ref<Doc & { attachments: Bag<Attachment> }>
export let objectId: Ref<Doc>
export let space: Ref<Space>
export let _class: Ref<Class<Doc & { attachments: Bag<Attachment> }>>
export let _class: Ref<Class<Doc>>
export let object: Doc & { attachments: Bag<Attachment> } | undefined = undefined
let attachments: Attachment[] = []
// const query = createQuery()
// $: query.query(_class, { _id: objectId }, result => { object = result[0] })
const query = createQuery()
$: query.query(chunter.class.Attachment, { attachedTo: objectId }, result => { attachments = result })
let inputFile: HTMLInputElement
let loading = false
@ -45,8 +45,9 @@
try {
const uuid = await uploadFile(space, file, objectId)
console.log('uploaded file uuid', uuid)
client.putBag(_class, space, objectId, 'attachments', encodeURIComponent(uuid), {
_class: chunter.class.Attachment,
client.createDoc(chunter.class.Attachment, space, {
attachedTo: objectId,
attachedToClass: _class,
name: file.name,
file: uuid,
type: file.type,
@ -81,7 +82,6 @@
{/if}
<input bind:this={inputFile} type="file" name="file" id="file" style="display: none" on:change={fileSelected}/>
</div>
{#if object?.attachments !== undefined}
<table class="table-body">
<thead>
<tr class="tr-head">
@ -90,7 +90,7 @@
</tr>
</thead>
<tbody>
{#each Object.values(object.attachments) as file}
{#each attachments as file}
<tr class="tr-body">
<td class="item flex-row-center">
<div class="flex-center file-icon">pdf</div>
@ -104,7 +104,6 @@
{/each}
</tbody>
</table>
{/if}
</div>
<style lang="scss">

View File

@ -34,7 +34,7 @@ export interface Candidates extends Space {}
*/
export interface Candidate extends Person {
title?: string
attachments: Bag<Attachment>
attachments?: number
applications?: number
onsite?: boolean
remote?: boolean

View File

@ -14,8 +14,9 @@
// limitations under the License.
//
import type { Tx, TxCreateDoc, Data, Ref, Doc, TxFactory } from '@anticrm/core'
import type { Message, Backlink } from '@anticrm/chunter'
import type { Tx, TxCreateDoc, Data, Ref, Doc, TxFactory, Class } from '@anticrm/core'
import type { FindAll } from '@anticrm/server-core'
import type { Message, Backlink, Attachment } from '@anticrm/chunter'
import { parse, Node, HTMLElement } from 'node-html-parser'
import core from '@anticrm/core'
@ -27,6 +28,7 @@ function extractBacklinks (backlinkId: Ref<Doc>, message: string, kids: Node[]):
if ((kid as HTMLElement).localName === 'span') {
result.push({
attachedTo: (kid as HTMLElement).getAttribute('data-id') as Ref<Doc>,
attachedToClass: (kid as HTMLElement).getAttribute('data-class') as Ref<Class<Doc>>,
backlinkId,
backlinkClass: chunter.class.Message,
message
@ -57,9 +59,30 @@ export async function OnMessage (tx: Tx, txFactory: TxFactory): Promise<Tx[]> {
return []
}
interface WithAttachements extends Doc {
attachments: number
}
/**
* @public
*/
export async function OnAttachment (tx: Tx, txFactory: TxFactory, findAll: FindAll<Doc>): Promise<Tx[]> {
if (tx._class === core.class.TxCreateDoc) {
const createTx = tx as TxCreateDoc<Attachment>
if (createTx.objectClass === chunter.class.Attachment) {
const _id = createTx.attributes.attachedTo as Ref<WithAttachements>
const _class = createTx.attributes.attachedToClass as Ref<Class<WithAttachements>>
const attachedTo = (await findAll(_class, { _id }))[0]
return [txFactory.createTxUpdateDoc(_class, attachedTo.space, _id, { $inc: { attachments: 1 } })]
}
}
return []
}
// eslint-disable-next-line @typescript-eslint/explicit-function-return-type
export default async () => ({
trigger: {
OnMessage
OnMessage,
OnAttachment
}
})

View File

@ -28,6 +28,7 @@ export const serverChunterId = 'server-chunter' as Plugin
*/
export default plugin(serverChunterId, {
trigger: {
OnMessage: '' as Resource<TriggerFunc>
OnMessage: '' as Resource<TriggerFunc>,
OnAttachment: '' as Resource<TriggerFunc>
}
})

File diff suppressed because it is too large Load Diff