mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
Merge branch 'main' into codex/add-open-dialog-and-close-dialog-cases
This commit is contained in:
@@ -96,6 +96,20 @@ Update a data source with a new value.
|
||||
}
|
||||
```
|
||||
|
||||
**Target-path convention:**
|
||||
To update nested values inside a data source, use a dotted `target` where the prefix is the data source ID and the remainder is the nested path:
|
||||
|
||||
```json
|
||||
{
|
||||
"id": "set-city",
|
||||
"type": "set-value",
|
||||
"target": "profile.address.city",
|
||||
"expression": "event.target.value"
|
||||
}
|
||||
```
|
||||
|
||||
This dotted `target` format works with `set-value`, `update`, `toggle-value`, `increment`, and `decrement`.
|
||||
|
||||
### create
|
||||
Add a new item to an array data source.
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { useState, useCallback, useEffect } from 'react'
|
||||
import { useKV } from '@/hooks/use-kv'
|
||||
import { DataSource } from '@/types/json-ui'
|
||||
import { setNestedValue } from '@/lib/json-ui/utils'
|
||||
|
||||
export function useDataSources(dataSources: DataSource[]) {
|
||||
const [data, setData] = useState<Record<string, any>>({})
|
||||
@@ -86,18 +87,8 @@ export function useDataSources(dataSources: DataSource[]) {
|
||||
return prev
|
||||
}
|
||||
|
||||
const pathParts = path.split('.')
|
||||
const newData = { ...sourceData }
|
||||
let current: any = newData
|
||||
|
||||
for (let i = 0; i < pathParts.length - 1; i++) {
|
||||
if (!(pathParts[i] in current)) {
|
||||
current[pathParts[i]] = {}
|
||||
}
|
||||
current = current[pathParts[i]]
|
||||
}
|
||||
|
||||
current[pathParts[pathParts.length - 1]] = value
|
||||
const newData = Array.isArray(sourceData) ? [...sourceData] : { ...sourceData }
|
||||
setNestedValue(newData, path, value)
|
||||
|
||||
if (source.type === 'kv') {
|
||||
const kvIndex = kvSources.indexOf(source)
|
||||
|
||||
@@ -2,10 +2,18 @@ import { useCallback } from 'react'
|
||||
import { toast } from 'sonner'
|
||||
import { Action, JSONUIContext } from '@/types/json-ui'
|
||||
import { evaluateExpression, evaluateTemplate } from '@/lib/json-ui/expression-evaluator'
|
||||
import { getNestedValue } from '@/lib/json-ui/utils'
|
||||
|
||||
export function useActionExecutor(context: JSONUIContext) {
|
||||
const { data, updateData, updatePath, executeAction: contextExecute } = context
|
||||
|
||||
const getTargetParts = (target?: string) => {
|
||||
if (!target) return null
|
||||
const [sourceId, ...pathParts] = target.split('.')
|
||||
const path = pathParts.join('.')
|
||||
return { sourceId, path: path || undefined }
|
||||
}
|
||||
|
||||
const executeAction = useCallback(async (action: Action, event?: any) => {
|
||||
try {
|
||||
const evaluationContext = { data, event }
|
||||
@@ -67,7 +75,8 @@ export function useActionExecutor(context: JSONUIContext) {
|
||||
}
|
||||
|
||||
case 'update': {
|
||||
if (!action.target) return
|
||||
const targetParts = getTargetParts(action.target)
|
||||
if (!targetParts) return
|
||||
|
||||
let newValue
|
||||
if (action.compute) {
|
||||
@@ -79,8 +88,12 @@ export function useActionExecutor(context: JSONUIContext) {
|
||||
} else {
|
||||
newValue = action.value
|
||||
}
|
||||
|
||||
updateData(action.target, newValue)
|
||||
|
||||
if (targetParts.path) {
|
||||
updatePath(targetParts.sourceId, targetParts.path, newValue)
|
||||
} else {
|
||||
updateData(targetParts.sourceId, newValue)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
@@ -98,7 +111,8 @@ export function useActionExecutor(context: JSONUIContext) {
|
||||
}
|
||||
|
||||
case 'set-value': {
|
||||
if (!action.target) return
|
||||
const targetParts = getTargetParts(action.target)
|
||||
if (!targetParts) return
|
||||
|
||||
let newValue
|
||||
if (action.compute) {
|
||||
@@ -110,31 +124,65 @@ export function useActionExecutor(context: JSONUIContext) {
|
||||
} else {
|
||||
newValue = action.value
|
||||
}
|
||||
|
||||
updateData(action.target, newValue)
|
||||
|
||||
if (targetParts.path) {
|
||||
updatePath(targetParts.sourceId, targetParts.path, newValue)
|
||||
} else {
|
||||
updateData(targetParts.sourceId, newValue)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'toggle-value': {
|
||||
if (!action.target) return
|
||||
const currentValue = data[action.target]
|
||||
updateData(action.target, !currentValue)
|
||||
const targetParts = getTargetParts(action.target)
|
||||
if (!targetParts) return
|
||||
|
||||
const currentValue = targetParts.path
|
||||
? getNestedValue(data[targetParts.sourceId], targetParts.path)
|
||||
: data[targetParts.sourceId]
|
||||
const nextValue = !currentValue
|
||||
|
||||
if (targetParts.path) {
|
||||
updatePath(targetParts.sourceId, targetParts.path, nextValue)
|
||||
} else {
|
||||
updateData(targetParts.sourceId, nextValue)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'increment': {
|
||||
if (!action.target) return
|
||||
const currentValue = data[action.target] || 0
|
||||
const targetParts = getTargetParts(action.target)
|
||||
if (!targetParts) return
|
||||
|
||||
const currentValue = targetParts.path
|
||||
? getNestedValue(data[targetParts.sourceId], targetParts.path)
|
||||
: data[targetParts.sourceId]
|
||||
const amount = action.value || 1
|
||||
updateData(action.target, currentValue + amount)
|
||||
const nextValue = (currentValue || 0) + amount
|
||||
|
||||
if (targetParts.path) {
|
||||
updatePath(targetParts.sourceId, targetParts.path, nextValue)
|
||||
} else {
|
||||
updateData(targetParts.sourceId, nextValue)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
case 'decrement': {
|
||||
if (!action.target) return
|
||||
const currentValue = data[action.target] || 0
|
||||
const targetParts = getTargetParts(action.target)
|
||||
if (!targetParts) return
|
||||
|
||||
const currentValue = targetParts.path
|
||||
? getNestedValue(data[targetParts.sourceId], targetParts.path)
|
||||
: data[targetParts.sourceId]
|
||||
const amount = action.value || 1
|
||||
updateData(action.target, currentValue - amount)
|
||||
const nextValue = (currentValue || 0) - amount
|
||||
|
||||
if (targetParts.path) {
|
||||
updatePath(targetParts.sourceId, targetParts.path, nextValue)
|
||||
} else {
|
||||
updateData(targetParts.sourceId, nextValue)
|
||||
}
|
||||
break
|
||||
}
|
||||
|
||||
|
||||
@@ -147,7 +147,7 @@ export interface PageSchema {
|
||||
export interface JSONUIContext {
|
||||
data: Record<string, any>
|
||||
updateData: (sourceId: string, value: any) => void
|
||||
updatePath?: (sourceId: string, path: string, value: any) => void
|
||||
updatePath: (sourceId: string, path: string, value: any) => void
|
||||
executeAction: (action: Action, event?: any) => Promise<void>
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user