mirror of
https://github.com/hcengineering/platform.git
synced 2026-09-10 03:37:43 +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:
@@ -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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user