feat: implement field locking and unlocking functionality, including UI, backend logic, and i18n. (#10573)

Signed-off-by: Denis Bykhov <bykhov.denis@gmail.com>
This commit is contained in:
Denis Bykhov
2026-03-01 00:42:00 +05:00
committed by GitHub
parent 33d8d500f3
commit e778a2748b
26 changed files with 350 additions and 22 deletions
@@ -556,11 +556,11 @@ export async function LockSection (
const rollback: Tx[] = []
const card = await control.client.findOne(cardPlugin.class.Card, { _id: execution.card })
if (card === undefined) throw processError(process.error.ObjectNotFound, { _id: execution.card })
const readonlySections = card.readonlySections ?? []
const readonlySections = new Set(card.readonlySections ?? [])
const target = params._id as Ref<MasterTag>
readonlySections.push(target)
readonlySections.add(target)
const tx = control.client.txFactory.createTxUpdateDoc(cardPlugin.class.Card, execution.space, execution.card, {
readonlySections
readonlySections: [...readonlySections]
})
res.push(tx)
rollback.push(
@@ -601,8 +601,10 @@ export async function UnlockSection (
const card = await control.client.findOne(cardPlugin.class.Card, { _id: execution.card })
if (card === undefined) throw processError(process.error.ObjectNotFound, { _id: execution.card })
const target = params._id as Ref<MasterTag>
const readonlySections = new Set(card.readonlySections ?? [])
readonlySections.delete(target)
const tx = control.client.txFactory.createTxUpdateDoc(cardPlugin.class.Card, execution.space, execution.card, {
$pull: { readonlySections: target }
readonlySections: [...readonlySections]
})
res.push(tx)
rollback.push(
@@ -613,6 +615,69 @@ export async function UnlockSection (
return { txes: res, rollback, context: [] }
}
export async function LockField (
params: Record<string, any>,
execution: Execution,
control: ProcessControl
): Promise<ExecuteResult> {
if (params.value === undefined) throw processError(process.error.RequiredParamsNotProvided, { params: 'value' })
const res: Tx[] = []
const rollback: Tx[] = []
const card = await control.client.findOne(cardPlugin.class.Card, { _id: execution.card })
if (card === undefined) throw processError(process.error.ObjectNotFound, { _id: execution.card })
const oldReadonlyFields = card.readonlyFields ?? []
const readonlyFields = [...oldReadonlyFields]
const targets = Array.isArray(params.value) ? params.value : [params.value]
let changed = false
for (const target of targets) {
if (!readonlyFields.includes(target)) {
readonlyFields.push(target)
changed = true
}
}
if (!changed) {
return { txes: [], rollback: [], context: [] }
}
const tx = control.client.txFactory.createTxUpdateDoc(cardPlugin.class.Card, execution.space, execution.card, {
readonlyFields
})
res.push(tx)
rollback.push(
control.client.txFactory.createTxUpdateDoc(cardPlugin.class.Card, execution.space, execution.card, {
readonlyFields: oldReadonlyFields
})
)
return { txes: res, rollback, context: [] }
}
export async function UnlockField (
params: Record<string, any>,
execution: Execution,
control: ProcessControl
): Promise<ExecuteResult> {
if (params.value === undefined) throw processError(process.error.RequiredParamsNotProvided, { params: 'value' })
const res: Tx[] = []
const rollback: Tx[] = []
const card = await control.client.findOne(cardPlugin.class.Card, { _id: execution.card })
if (card === undefined) throw processError(process.error.ObjectNotFound, { _id: execution.card })
const oldReadonlyFields = card.readonlyFields ?? []
const targets = Array.isArray(params.value) ? params.value : [params.value]
const readonlyFields = oldReadonlyFields.filter((f: string) => !targets.includes(f))
if (readonlyFields.length === oldReadonlyFields.length) {
return { txes: [], rollback: [], context: [] }
}
const tx = control.client.txFactory.createTxUpdateDoc(cardPlugin.class.Card, execution.space, execution.card, {
readonlyFields
})
res.push(tx)
rollback.push(
control.client.txFactory.createTxUpdateDoc(cardPlugin.class.Card, execution.space, execution.card, {
readonlyFields: oldReadonlyFields
})
)
return { txes: res, rollback, context: [] }
}
export async function CreateToDo (
params: MethodParams<ProcessToDo>,
execution: Execution,
@@ -112,7 +112,9 @@ import {
LockCard,
LockSection,
UnlockCard,
UnlockSection
UnlockSection,
LockField,
UnlockField
} from './functions'
import { FieldChangedRollback, ToDoCancellRollback, ToDoCloseRollback } from './rollback'
@@ -599,7 +601,9 @@ export default async () => ({
LockCard,
LockSection,
UnlockCard,
UnlockSection
UnlockSection,
LockField,
UnlockField
},
transform: {
CurrentDate,