Add data source editor hook

This commit is contained in:
2026-01-18 01:24:36 +00:00
parent a249435105
commit 4ee346c69d
2 changed files with 68 additions and 32 deletions

View File

@@ -1,4 +1,3 @@
import { useEffect, useState } from 'react'
import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle } from '@/components/ui/dialog'
import { Button } from '@/components/ui/button'
import { DataSource } from '@/types/json-ui'
@@ -7,6 +6,7 @@ import { DataSourceIdField } from '@/components/molecules/data-source-editor/Dat
import { KvSourceFields } from '@/components/molecules/data-source-editor/KvSourceFields'
import { StaticSourceFields } from '@/components/molecules/data-source-editor/StaticSourceFields'
import { ComputedSourceFields } from '@/components/molecules/data-source-editor/ComputedSourceFields'
import { useDataSourceEditor } from '@/hooks/data/use-data-source-editor'
import dataSourceEditorCopy from '@/data/data-source-editor-dialog.json'
interface DataSourceEditorDialogProps {
@@ -24,11 +24,15 @@ export function DataSourceEditorDialog({
onOpenChange,
onSave,
}: DataSourceEditorDialogProps) {
const [editingSource, setEditingSource] = useState<DataSource | null>(dataSource)
useEffect(() => {
setEditingSource(dataSource)
}, [dataSource])
const {
editingSource,
updateField,
addDependency,
removeDependency,
availableDeps,
selectedDeps,
unselectedDeps,
} = useDataSourceEditor(dataSource, allDataSources)
const handleSave = () => {
if (!editingSource) return
@@ -36,34 +40,8 @@ export function DataSourceEditorDialog({
onOpenChange(false)
}
const updateField = <K extends keyof DataSource>(field: K, value: DataSource[K]) => {
if (!editingSource) return
setEditingSource({ ...editingSource, [field]: value })
}
const addDependency = (depId: string) => {
if (!editingSource || editingSource.type !== 'computed') return
const deps = editingSource.dependencies || []
if (!deps.includes(depId)) {
updateField('dependencies', [...deps, depId])
}
}
const removeDependency = (depId: string) => {
if (!editingSource || editingSource.type !== 'computed') return
const deps = editingSource.dependencies || []
updateField('dependencies', deps.filter(d => d !== depId))
}
if (!editingSource) return null
const availableDeps = allDataSources.filter(
ds => ds.id !== editingSource.id && ds.type !== 'computed',
)
const selectedDeps = editingSource.dependencies || []
const unselectedDeps = availableDeps.filter(ds => !selectedDeps.includes(ds.id))
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">

View File

@@ -0,0 +1,58 @@
import { useCallback, useEffect, useMemo, useState } from 'react'
import { DataSource } from '@/types/json-ui'
export function useDataSourceEditor(
dataSource: DataSource | null,
allDataSources: DataSource[],
) {
const [editingSource, setEditingSource] = useState<DataSource | null>(dataSource)
useEffect(() => {
setEditingSource(dataSource)
}, [dataSource])
const updateField = useCallback(<K extends keyof DataSource>(field: K, value: DataSource[K]) => {
setEditingSource(prev => (prev ? { ...prev, [field]: value } : prev))
}, [])
const addDependency = useCallback((depId: string) => {
setEditingSource(prev => {
if (!prev || prev.type !== 'computed') return prev
const deps = prev.dependencies || []
if (deps.includes(depId)) return prev
return { ...prev, dependencies: [...deps, depId] }
})
}, [])
const removeDependency = useCallback((depId: string) => {
setEditingSource(prev => {
if (!prev || prev.type !== 'computed') return prev
const deps = prev.dependencies || []
return { ...prev, dependencies: deps.filter(dep => dep !== depId) }
})
}, [])
const availableDeps = useMemo(() => {
if (!editingSource) return []
return allDataSources.filter(
ds => ds.id !== editingSource.id && ds.type !== 'computed',
)
}, [allDataSources, editingSource])
const selectedDeps = useMemo(() => editingSource?.dependencies || [], [editingSource])
const unselectedDeps = useMemo(
() => availableDeps.filter(ds => !selectedDeps.includes(ds.id)),
[availableDeps, selectedDeps],
)
return {
editingSource,
updateField,
addDependency,
removeDependency,
availableDeps,
selectedDeps,
unselectedDeps,
}
}