mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 21:54:56 +00:00
Merge branch 'main' into codex/extract-logic-into-custom-hooks
This commit is contained in:
@@ -2,25 +2,7 @@ import { ClockCounterClockwise, X } from '@phosphor-icons/react'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { CommandGroup, CommandItem, CommandSeparator } from '@/components/ui/command'
|
||||
|
||||
interface SearchHistoryItem {
|
||||
id: string
|
||||
query: string
|
||||
timestamp: number
|
||||
resultId?: string
|
||||
resultTitle?: string
|
||||
resultCategory?: string
|
||||
}
|
||||
|
||||
interface SearchResult {
|
||||
id: string
|
||||
title: string
|
||||
subtitle?: string
|
||||
category: string
|
||||
icon: React.ReactNode
|
||||
action: () => void
|
||||
tags?: string[]
|
||||
}
|
||||
import type { SearchHistoryItem, SearchResult } from './types'
|
||||
|
||||
interface RecentSearchesProps {
|
||||
recentSearches: Array<{ historyItem: SearchHistoryItem; result?: SearchResult }>
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { CommandGroup, CommandItem, CommandSeparator } from '@/components/ui/command'
|
||||
|
||||
interface SearchResult {
|
||||
id: string
|
||||
title: string
|
||||
subtitle?: string
|
||||
category: string
|
||||
icon: React.ReactNode
|
||||
action: () => void
|
||||
tags?: string[]
|
||||
}
|
||||
import type { SearchResult } from './types'
|
||||
|
||||
interface SearchResultsProps {
|
||||
groupedResults: Record<string, SearchResult[]>
|
||||
|
||||
18
src/components/global-search/types.ts
Normal file
18
src/components/global-search/types.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
export interface SearchResult {
|
||||
id: string
|
||||
title: string
|
||||
subtitle?: string
|
||||
category: string
|
||||
icon: React.ReactNode
|
||||
action: () => void
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
export interface SearchHistoryItem {
|
||||
id: string
|
||||
query: string
|
||||
timestamp: number
|
||||
resultId?: string
|
||||
resultTitle?: string
|
||||
resultCategory?: string
|
||||
}
|
||||
@@ -33,25 +33,7 @@ import {
|
||||
Workflow,
|
||||
} from '@/types/project'
|
||||
import navigationData from '@/data/global-search.json'
|
||||
|
||||
export interface SearchResult {
|
||||
id: string
|
||||
title: string
|
||||
subtitle?: string
|
||||
category: string
|
||||
icon: React.ReactNode
|
||||
action: () => void
|
||||
tags?: string[]
|
||||
}
|
||||
|
||||
export interface SearchHistoryItem {
|
||||
id: string
|
||||
query: string
|
||||
timestamp: number
|
||||
resultId?: string
|
||||
resultTitle?: string
|
||||
resultCategory?: string
|
||||
}
|
||||
import type { SearchHistoryItem, SearchResult } from './types'
|
||||
|
||||
const navigationIconMap = {
|
||||
BookOpen,
|
||||
|
||||
@@ -23,8 +23,9 @@ export function ComponentBindingDialog({
|
||||
}: ComponentBindingDialogProps) {
|
||||
const { editingComponent, handleSave, updateBindings } = useComponentBindingDialog({
|
||||
component,
|
||||
onSave,
|
||||
open,
|
||||
onOpenChange,
|
||||
onSave,
|
||||
})
|
||||
|
||||
if (!editingComponent) return null
|
||||
|
||||
@@ -6,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'
|
||||
import { useDataSourceEditor } from '@/hooks/use-data-source-editor'
|
||||
|
||||
@@ -29,16 +30,16 @@ export function DataSourceEditorDialog({
|
||||
updateField,
|
||||
addDependency,
|
||||
removeDependency,
|
||||
handleSave,
|
||||
availableDeps,
|
||||
selectedDeps,
|
||||
unselectedDeps,
|
||||
} = useDataSourceEditor({
|
||||
dataSource,
|
||||
allDataSources,
|
||||
onSave,
|
||||
onOpenChange,
|
||||
})
|
||||
} = useDataSourceEditor(dataSource, allDataSources)
|
||||
|
||||
const handleSave = () => {
|
||||
if (!editingSource) return
|
||||
onSave(editingSource)
|
||||
onOpenChange(false)
|
||||
}
|
||||
|
||||
if (!editingSource) return null
|
||||
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { NextJsConfig } from '@/types/project'
|
||||
import projectSettingsCopy from '@/data/project-settings.json'
|
||||
|
||||
interface NextJsApplicationCardProps {
|
||||
nextjsConfig: NextJsConfig
|
||||
onNextjsConfigChange: (config: NextJsConfig | ((current: NextJsConfig) => NextJsConfig)) => void
|
||||
}
|
||||
import { NextJsConfigSectionProps } from '@/components/project-settings/types'
|
||||
|
||||
export function NextJsApplicationCard({
|
||||
nextjsConfig,
|
||||
onNextjsConfigChange,
|
||||
}: NextJsApplicationCardProps) {
|
||||
}: NextJsConfigSectionProps) {
|
||||
const { application } = projectSettingsCopy.nextjs
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,16 +1,11 @@
|
||||
import { NextJsConfig } from '@/types/project'
|
||||
import { NextJsApplicationCard } from '@/components/project-settings/NextJsApplicationCard'
|
||||
import { NextJsFeaturesCard } from '@/components/project-settings/NextJsFeaturesCard'
|
||||
|
||||
interface NextJsConfigTabProps {
|
||||
nextjsConfig: NextJsConfig
|
||||
onNextjsConfigChange: (config: NextJsConfig | ((current: NextJsConfig) => NextJsConfig)) => void
|
||||
}
|
||||
import { NextJsConfigSectionProps } from '@/components/project-settings/types'
|
||||
|
||||
export function NextJsConfigTab({
|
||||
nextjsConfig,
|
||||
onNextjsConfigChange,
|
||||
}: NextJsConfigTabProps) {
|
||||
}: NextJsConfigSectionProps) {
|
||||
return (
|
||||
<div className="max-w-2xl space-y-6">
|
||||
<NextJsApplicationCard
|
||||
|
||||
@@ -1,18 +1,13 @@
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { NextJsConfig } from '@/types/project'
|
||||
import projectSettingsCopy from '@/data/project-settings.json'
|
||||
|
||||
interface NextJsFeaturesCardProps {
|
||||
nextjsConfig: NextJsConfig
|
||||
onNextjsConfigChange: (config: NextJsConfig | ((current: NextJsConfig) => NextJsConfig)) => void
|
||||
}
|
||||
import { NextJsConfigSectionProps } from '@/components/project-settings/types'
|
||||
|
||||
export function NextJsFeaturesCard({
|
||||
nextjsConfig,
|
||||
onNextjsConfigChange,
|
||||
}: NextJsFeaturesCardProps) {
|
||||
}: NextJsConfigSectionProps) {
|
||||
const { features } = projectSettingsCopy.nextjs
|
||||
|
||||
return (
|
||||
|
||||
6
src/components/project-settings/types.ts
Normal file
6
src/components/project-settings/types.ts
Normal file
@@ -0,0 +1,6 @@
|
||||
import { NextJsConfig } from '@/types/project'
|
||||
|
||||
export type NextJsConfigSectionProps = {
|
||||
nextjsConfig: NextJsConfig
|
||||
onNextjsConfigChange: (config: NextJsConfig | ((current: NextJsConfig) => NextJsConfig)) => void
|
||||
}
|
||||
58
src/hooks/data/use-data-source-editor.ts
Normal file
58
src/hooks/data/use-data-source-editor.ts
Normal 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,
|
||||
}
|
||||
}
|
||||
@@ -1,28 +1,29 @@
|
||||
import { useCallback, useEffect, useState } from 'react'
|
||||
import { UIComponent } from '@/types/json-ui'
|
||||
|
||||
interface UseComponentBindingDialogParams {
|
||||
interface UseComponentBindingDialogOptions {
|
||||
component: UIComponent | null
|
||||
onSave: (component: UIComponent) => void
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
onSave: (component: UIComponent) => void
|
||||
}
|
||||
|
||||
export function useComponentBindingDialog({
|
||||
component,
|
||||
onSave,
|
||||
open,
|
||||
onOpenChange,
|
||||
}: UseComponentBindingDialogParams) {
|
||||
onSave,
|
||||
}: UseComponentBindingDialogOptions) {
|
||||
const [editingComponent, setEditingComponent] = useState<UIComponent | null>(component)
|
||||
|
||||
useEffect(() => {
|
||||
setEditingComponent(component)
|
||||
}, [component])
|
||||
if (open) {
|
||||
setEditingComponent(component)
|
||||
}
|
||||
}, [component, open])
|
||||
|
||||
const updateBindings = useCallback((bindings: Record<string, any>) => {
|
||||
setEditingComponent((prev) => {
|
||||
if (!prev) return prev
|
||||
return { ...prev, bindings }
|
||||
})
|
||||
setEditingComponent(prev => (prev ? { ...prev, bindings } : prev))
|
||||
}, [])
|
||||
|
||||
const handleSave = useCallback(() => {
|
||||
@@ -33,7 +34,7 @@ export function useComponentBindingDialog({
|
||||
|
||||
return {
|
||||
editingComponent,
|
||||
updateBindings,
|
||||
handleSave,
|
||||
updateBindings,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user