mirror of
https://github.com/hcengineering/platform.git
synced 2026-08-17 18:05:42 +02:00
feat: Implement FieldChangedRollback to revert document updates in … (#10572)
Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
@@ -119,7 +119,7 @@ export function defineTriggers (builder: Builder): void {
|
||||
requiredParams: [],
|
||||
checkFunction: process.triggerCheck.FieldChangedCheck,
|
||||
init: false,
|
||||
auto: true
|
||||
auto: false
|
||||
},
|
||||
process.trigger.WhenFieldChanges
|
||||
)
|
||||
|
||||
@@ -66,7 +66,7 @@ export function createModel (builder: Builder): void {
|
||||
})
|
||||
|
||||
builder.mixin(process.trigger.WhenFieldChanges, process.class.Trigger, serverProcess.mixin.TriggerImpl, {
|
||||
preventRollback: true,
|
||||
rollbackFunc: serverProcess.rollbacks.FieldChangedRollback, // set to null for now
|
||||
serverCheckFunc: serverProcess.func.FieldChangedCheck
|
||||
})
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
export let value: string[] = []
|
||||
export let type: ArrOf<string>
|
||||
export let onChange: (value: string[]) => void
|
||||
export let readonly: boolean = false
|
||||
|
||||
export let kind: ButtonKind = 'link'
|
||||
export let size: ButtonSize = 'large'
|
||||
@@ -55,6 +56,7 @@
|
||||
{size}
|
||||
width={'100%'}
|
||||
multiselect
|
||||
disabled={readonly}
|
||||
autoSelect={false}
|
||||
on:selected={(e) => {
|
||||
onChange(e.detail)
|
||||
|
||||
@@ -114,7 +114,7 @@ import {
|
||||
UnlockCard,
|
||||
UnlockSection
|
||||
} from './functions'
|
||||
import { ToDoCancellRollback, ToDoCloseRollback } from './rollback'
|
||||
import { FieldChangedRollback, ToDoCancellRollback, ToDoCloseRollback } from './rollback'
|
||||
|
||||
async function putEventToQueue (value: Omit<ProcessMessage, 'account'>, control: TriggerControl): Promise<void> {
|
||||
if (control.queue === undefined) return
|
||||
@@ -643,7 +643,8 @@ export default async () => ({
|
||||
},
|
||||
rollbacks: {
|
||||
ToDoCloseRollback,
|
||||
ToDoCancellRollback
|
||||
ToDoCancellRollback,
|
||||
FieldChangedRollback
|
||||
},
|
||||
trigger: {
|
||||
OnProcessRemove,
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
// limitations under the License.
|
||||
//
|
||||
|
||||
import { Tx } from '@hcengineering/core'
|
||||
import { Card } from '@hcengineering/card'
|
||||
import { DocumentUpdate, Tx } from '@hcengineering/core'
|
||||
import { ProcessToDo } from '@hcengineering/process'
|
||||
import { ProcessControl } from '@hcengineering/server-process'
|
||||
|
||||
@@ -37,3 +38,70 @@ export function ToDoCancellRollback (context: Record<string, any>, control: Proc
|
||||
todo.modifiedBy
|
||||
)
|
||||
}
|
||||
|
||||
export function FieldChangedRollback (context: Record<string, any>, control: ProcessControl): Tx | undefined {
|
||||
const card = context.card as Card
|
||||
const ops = context.operations as DocumentUpdate<Card>
|
||||
if (card === undefined || ops === undefined) return
|
||||
const antiOps: DocumentUpdate<any> = invertUpdate(ops)
|
||||
return control.client.txFactory.createTxUpdateDoc(card._class, card.space, card._id, antiOps)
|
||||
}
|
||||
|
||||
function invertUpdate (ops: Record<string, any>): Record<string, any> {
|
||||
const antiOps: Record<string, any> = {}
|
||||
for (const [key, value] of Object.entries(ops)) {
|
||||
if (key.startsWith('$')) {
|
||||
const inverted = invertOperator(key, value)
|
||||
if (inverted !== undefined) {
|
||||
for (const [antiKey, antiValue] of Object.entries(inverted)) {
|
||||
antiOps[antiKey] = { ...(antiOps[antiKey] ?? {}), ...antiValue }
|
||||
}
|
||||
}
|
||||
} else {
|
||||
antiOps.$unset = { ...(antiOps.$unset ?? {}), [key]: true }
|
||||
}
|
||||
}
|
||||
return antiOps
|
||||
}
|
||||
|
||||
function invertOperator (name: string, op: any): Record<string, any> | undefined {
|
||||
switch (name) {
|
||||
case '$inc': {
|
||||
const result: Record<string, number> = {}
|
||||
for (const [key, val] of Object.entries(op)) {
|
||||
result[key] = -(val as number)
|
||||
}
|
||||
return { $inc: result }
|
||||
}
|
||||
case '$push': {
|
||||
const result: Record<string, any> = {}
|
||||
for (const [key, val] of Object.entries(op)) {
|
||||
if (typeof val === 'object' && val !== null && '$each' in val) {
|
||||
result[key] = { $in: (val as any).$each }
|
||||
} else {
|
||||
result[key] = val
|
||||
}
|
||||
}
|
||||
return { $pull: result }
|
||||
}
|
||||
case '$pull': {
|
||||
const result: Record<string, any> = {}
|
||||
for (const [key, val] of Object.entries(op)) {
|
||||
if (typeof val === 'object' && val !== null && '$in' in val) {
|
||||
result[key] = { $each: (val as any).$in }
|
||||
} else {
|
||||
result[key] = { $each: [val] }
|
||||
}
|
||||
}
|
||||
return { $push: result }
|
||||
}
|
||||
case '$rename': {
|
||||
const result: Record<string, string> = {}
|
||||
for (const [key, val] of Object.entries(op)) {
|
||||
result[val as string] = key
|
||||
}
|
||||
return { $rename: result }
|
||||
}
|
||||
}
|
||||
return undefined
|
||||
}
|
||||
|
||||
@@ -44,7 +44,8 @@ export default plugin(serverProcessId, {
|
||||
},
|
||||
rollbacks: {
|
||||
ToDoCloseRollback: '' as Resource<RollbackFunc>,
|
||||
ToDoCancellRollback: '' as Resource<RollbackFunc>
|
||||
ToDoCancellRollback: '' as Resource<RollbackFunc>,
|
||||
FieldChangedRollback: '' as Resource<RollbackFunc>
|
||||
},
|
||||
func: {
|
||||
RunSubProcess: '' as Resource<ExecuteFunc>,
|
||||
|
||||
Reference in New Issue
Block a user