Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@

async function runProcess (): Promise<void> {
if (process === undefined || card === undefined) return
await createExecution(card._id, process, card.space)
const tx = await createExecution(card._id, process, card.space, client.txFactory)
if (tx) await client.tx(tx)
dispatch('close')
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,8 @@
async function runProcess (_id: Ref<Process>): Promise<void> {
if (!value) return
for (const element of values) {
await createExecution(element._id, _id, element.space)
const tx = await createExecution(element._id, _id, element.space, client.txFactory)
if (tx) await client.tx(tx)
}
dispatch('close')
}
Expand Down
133 changes: 94 additions & 39 deletions plugins/process-resources/src/middleware.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,14 +13,17 @@

import cardPlugin, { type Card } from '@hcengineering/card'
import core, {
generateId,
getCurrentAccount,
SortingOrder,
TxOperations,
TxProcessor,
type Client,
type Doc,
type Tx,
type TxApplyIf,
type TxCreateDoc,
type TxCUD,
type TxMixin,
type TxResult,
type TxUpdateDoc
Expand Down Expand Up @@ -50,27 +53,47 @@ export class ProcessMiddleware extends BasePresentationMiddleware implements Pre
return new ProcessMiddleware(client, next)
}

private readonly txFactory = new TxOperations(this.client, getCurrentAccount().primarySocialId).txFactory

async tx (tx: Tx): Promise<TxResult> {
await this.handleTx(tx)
const preTx: Array<TxCUD<Doc>> = []
const postTx: Array<TxCUD<Doc>> = []
await this.handleTx(preTx, postTx, tx)

if (preTx.length > 0 || postTx.length > 0) {
if (TxProcessor.isExtendsCUD(tx._class)) {
const applyIf = this.txFactory.createTxApplyIf(
core.space.Tx,
generateId(),
[],
[],
[...preTx, tx as TxCUD<Doc>, ...postTx],
'process',
true
)
return await this.provideTx(applyIf)
}
}

return await this.provideTx(tx)
}

private async handleTx (...txes: Tx[]): Promise<void> {
private async handleTx (preTx: Array<TxCUD<Doc>>, postTx: Array<TxCUD<Doc>>, ...txes: Tx[]): Promise<void> {
for (const etx of txes) {
if (etx._class === core.class.TxApplyIf) {
const applyIf = etx as TxApplyIf
await this.handleTx(...applyIf.txes)
await this.handleTx(preTx, postTx, ...applyIf.txes)
}

await this.handleCardCreate(etx)
await this.handleCardUpdate(etx)
await this.handleTagAdd(etx)
await this.handleToDoDone(etx)
await this.handleApproveRequest(etx)
await this.handleCardCreate(postTx, etx)
await this.handleCardUpdate(preTx, etx)
await this.handleTagAdd(postTx, etx)
await this.handleToDoDone(preTx, etx)
await this.handleApproveRequest(preTx, etx)
}
}

private async handleCardUpdate (etx: Tx): Promise<void> {
private async handleCardUpdate (preTx: Array<TxCUD<Doc>>, etx: Tx): Promise<void> {
if (etx._class === core.class.TxUpdateDoc || etx._class === core.class.TxMixin) {
const updateTx = etx as TxUpdateDoc<Card> | TxMixin<Card, Card>
const hierarchy = this.client.getHierarchy()
Expand All @@ -97,21 +120,26 @@ export class ProcessMiddleware extends BasePresentationMiddleware implements Pre
},
{ sort: { rank: SortingOrder.Ascending } }
)
const transition = await pickTransition(this.client, execution, transitions, {
const inputContext = {
...execution.context,
card: updated,
operations: isUpdateTx(updateTx) ? updateTx.operations : updateTx.attributes
})
}
const transition = await pickTransition(this.client, execution, transitions, inputContext)
if (transition === undefined) return
const context = await getNextStateUserInput(execution, transition, execution.context)
const txop = new TxOperations(this.client, getCurrentAccount().primarySocialId)
await txop.update(execution, {
context
})
const result = await getNextStateUserInput(execution, transition, execution.context, inputContext)
if (result?.changed === true) {
preTx.push(
this.txFactory.createTxUpdateDoc(execution._class, execution.space, execution._id, {
context: result.context
})
)
}
}
}
}

private async handleCardCreate (etx: Tx): Promise<void> {
private async handleCardCreate (postTx: Array<TxCUD<Doc>>, etx: Tx): Promise<void> {
if (etx._class === core.class.TxCreateDoc) {
const createTx = etx as TxCreateDoc<Card>
const doc = TxProcessor.createDoc2Doc(createTx)
Expand All @@ -130,12 +158,13 @@ export class ProcessMiddleware extends BasePresentationMiddleware implements Pre
autoStart: true
})
for (const proc of processes) {
await createExecution(createTx.objectId, proc._id, createTx.objectSpace)
const res = await createExecution(createTx.objectId, proc._id, createTx.objectSpace, this.txFactory)
if (res !== undefined) postTx.push(res)
}
}
}

private async handleTagAdd (tx: Tx): Promise<void> {
private async handleTagAdd (postTx: Array<TxCUD<Doc>>, tx: Tx): Promise<void> {
if (tx._class !== core.class.TxMixin) return
const mixinTx = tx as TxMixin<Card, Card>
const hierarchy = this.client.getHierarchy()
Expand All @@ -146,11 +175,12 @@ export class ProcessMiddleware extends BasePresentationMiddleware implements Pre
.getModel()
.findAllSync(process.class.Process, { masterTag: mixinTx.mixin, autoStart: true })
for (const proc of processes) {
await createExecution(mixinTx.objectId, proc._id, mixinTx.objectSpace)
const res = await createExecution(mixinTx.objectId, proc._id, mixinTx.objectSpace, this.txFactory)
if (res !== undefined) postTx.push(res)
}
}

private async handleApproveRequest (etx: Tx): Promise<void> {
private async handleApproveRequest (preTx: Array<TxCUD<Doc>>, etx: Tx): Promise<void> {
if (etx._class === core.class.TxUpdateDoc) {
const cud = etx as TxUpdateDoc<ApproveRequest>
if (cud.objectClass !== process.class.ApproveRequest) return
Expand All @@ -163,7 +193,6 @@ export class ProcessMiddleware extends BasePresentationMiddleware implements Pre
_id: approveRequest.execution
})
if (execution === undefined) return
const txop = new TxOperations(this.client, getCurrentAccount().primarySocialId)
const transitions = this.client.getModel().findAllSync(
process.class.Transition,
{
Expand All @@ -176,18 +205,24 @@ export class ProcessMiddleware extends BasePresentationMiddleware implements Pre
{ sort: { rank: SortingOrder.Ascending } }
)
const updatedApproveRequest = TxProcessor.updateDoc2Doc(approveRequest, cud)
const transition = await pickTransition(this.client, execution, transitions, {
const inputContext = {
...execution.context,
todo: updatedApproveRequest
})
}
const transition = await pickTransition(this.client, execution, transitions, inputContext)
if (transition === undefined) return
const context = await getNextStateUserInput(execution, transition, execution.context)
await txop.update(execution, {
context
})
const result = await getNextStateUserInput(execution, transition, execution.context, inputContext)
if (result?.changed === true) {
preTx.push(
this.txFactory.createTxUpdateDoc(execution._class, execution.space, execution._id, {
context: result.context
})
)
}
}
}

private async handleToDoDone (etx: Tx): Promise<void> {
private async handleToDoDone (preTx: Array<TxCUD<Doc>>, etx: Tx): Promise<void> {
if (etx._class === core.class.TxUpdateDoc) {
const cud = etx as TxUpdateDoc<ProcessToDo>
if (cud.objectClass !== process.class.ProcessToDo) return
Expand All @@ -200,22 +235,42 @@ export class ProcessMiddleware extends BasePresentationMiddleware implements Pre
_id: todo.execution
})
if (execution === undefined) return
const txop = new TxOperations(this.client, getCurrentAccount().primarySocialId)
await requestResult(txop, execution, todo.results, execution.context)

const context = await requestResult(execution, todo.results, execution.context)

const transitions = this.client.getModel().findAllSync(process.class.Transition, {
process: execution.process,
from: execution.currentState,
trigger: process.trigger.OnToDoClose
})
const transition = await pickTransition(this.client, execution, transitions, {
const inputContext = {
...(context ?? execution.context),
todo
})
if (transition === undefined) return
const context = await getNextStateUserInput(execution, transition, execution.context)
if (context !== undefined) {
await txop.update(execution, {
context
})
}
const transition = await pickTransition(this.client, execution, transitions, inputContext)
if (transition === undefined) {
if (context !== undefined) {
preTx.push(
this.txFactory.createTxUpdateDoc(execution._class, execution.space, execution._id, {
context
})
)
}
return
}
const finalResult = await getNextStateUserInput(execution, transition, context ?? execution.context, inputContext)
if (finalResult?.changed === true) {
preTx.push(
this.txFactory.createTxUpdateDoc(execution._class, execution.space, execution._id, {
context: finalResult.context
})
)
} else if (context !== undefined) {
preTx.push(
this.txFactory.createTxUpdateDoc(execution._class, execution.space, execution._id, {
context
})
)
}
}
}
Expand Down
Loading
Loading