mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-25 14:14:57 +00:00
Remove duplicate components, prefer JSON versions
Co-authored-by: johndoe6345789 <224850594+johndoe6345789@users.noreply.github.com>
This commit is contained in:
@@ -1 +0,0 @@
|
||||
export { JSONComponentTreeManager as ComponentTreeManager } from './JSONComponentTreeManager'
|
||||
@@ -1 +0,0 @@
|
||||
export { JSONFlaskDesigner as FlaskDesigner } from './JSONFlaskDesigner'
|
||||
@@ -1 +0,0 @@
|
||||
export { JSONLambdaDesigner as LambdaDesigner } from './JSONLambdaDesigner'
|
||||
@@ -1 +0,0 @@
|
||||
export { JSONModelDesigner as ModelDesigner } from './JSONModelDesigner'
|
||||
@@ -1,389 +0,0 @@
|
||||
import { useState } from 'react'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Sheet, SheetContent, SheetHeader, SheetTitle, SheetTrigger } from '@/components/ui/sheet'
|
||||
import { ScrollArea } from '@/components/ui/scroll-area'
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Collapsible, CollapsibleContent, CollapsibleTrigger } from '@/components/ui/collapsible'
|
||||
import {
|
||||
List,
|
||||
ChartBar,
|
||||
Code,
|
||||
Database,
|
||||
Tree,
|
||||
FlowArrow,
|
||||
PaintBrush,
|
||||
Flask,
|
||||
Play,
|
||||
BookOpen,
|
||||
Cube,
|
||||
Wrench,
|
||||
FileText,
|
||||
Gear,
|
||||
DeviceMobile,
|
||||
Image,
|
||||
Faders,
|
||||
CaretDown,
|
||||
CaretDoubleDown,
|
||||
CaretDoubleUp,
|
||||
Cloud,
|
||||
Lightbulb,
|
||||
} from '@phosphor-icons/react'
|
||||
import { FeatureToggles } from '@/types/project'
|
||||
|
||||
interface NavigationGroup {
|
||||
id: string
|
||||
label: string
|
||||
items: NavigationItem[]
|
||||
}
|
||||
|
||||
interface NavigationItem {
|
||||
id: string
|
||||
label: string
|
||||
icon: React.ReactNode
|
||||
value: string
|
||||
badge?: number
|
||||
featureKey?: keyof FeatureToggles
|
||||
}
|
||||
|
||||
interface NavigationMenuProps {
|
||||
activeTab: string
|
||||
onTabChange: (tab: string) => void
|
||||
featureToggles: FeatureToggles
|
||||
errorCount?: number
|
||||
}
|
||||
|
||||
export function NavigationMenu({
|
||||
activeTab,
|
||||
onTabChange,
|
||||
featureToggles,
|
||||
errorCount = 0,
|
||||
}: NavigationMenuProps) {
|
||||
const [open, setOpen] = useState(false)
|
||||
const [expandedGroups, setExpandedGroups] = useState<Set<string>>(
|
||||
new Set(['overview', 'development', 'automation', 'design', 'backend', 'testing', 'tools'])
|
||||
)
|
||||
|
||||
const navigationGroups: NavigationGroup[] = [
|
||||
{
|
||||
id: 'overview',
|
||||
label: 'Overview',
|
||||
items: [
|
||||
{
|
||||
id: 'dashboard',
|
||||
label: 'Dashboard',
|
||||
icon: <ChartBar size={18} />,
|
||||
value: 'dashboard',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'development',
|
||||
label: 'Development',
|
||||
items: [
|
||||
{
|
||||
id: 'code',
|
||||
label: 'Code Editor',
|
||||
icon: <Code size={18} />,
|
||||
value: 'code',
|
||||
featureKey: 'codeEditor',
|
||||
},
|
||||
{
|
||||
id: 'models',
|
||||
label: 'Models',
|
||||
icon: <Database size={18} />,
|
||||
value: 'models',
|
||||
featureKey: 'models',
|
||||
},
|
||||
{
|
||||
id: 'components',
|
||||
label: 'Components',
|
||||
icon: <Tree size={18} />,
|
||||
value: 'components',
|
||||
featureKey: 'components',
|
||||
},
|
||||
{
|
||||
id: 'component-trees',
|
||||
label: 'Component Trees',
|
||||
icon: <Tree size={18} />,
|
||||
value: 'component-trees',
|
||||
featureKey: 'componentTrees',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'automation',
|
||||
label: 'Automation',
|
||||
items: [
|
||||
{
|
||||
id: 'workflows',
|
||||
label: 'Workflows',
|
||||
icon: <FlowArrow size={18} />,
|
||||
value: 'workflows',
|
||||
featureKey: 'workflows',
|
||||
},
|
||||
{
|
||||
id: 'lambdas',
|
||||
label: 'Lambdas',
|
||||
icon: <Code size={18} />,
|
||||
value: 'lambdas',
|
||||
featureKey: 'lambdas',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'design',
|
||||
label: 'Design & Styling',
|
||||
items: [
|
||||
{
|
||||
id: 'styling',
|
||||
label: 'Styling',
|
||||
icon: <PaintBrush size={18} />,
|
||||
value: 'styling',
|
||||
featureKey: 'styling',
|
||||
},
|
||||
{
|
||||
id: 'sass',
|
||||
label: 'Sass Styles',
|
||||
icon: <PaintBrush size={18} />,
|
||||
value: 'sass',
|
||||
featureKey: 'sassStyles',
|
||||
},
|
||||
{
|
||||
id: 'favicon',
|
||||
label: 'Favicon Designer',
|
||||
icon: <Image size={18} />,
|
||||
value: 'favicon',
|
||||
featureKey: 'faviconDesigner',
|
||||
},
|
||||
{
|
||||
id: 'ideas',
|
||||
label: 'Feature Ideas',
|
||||
icon: <Lightbulb size={18} />,
|
||||
value: 'ideas',
|
||||
featureKey: 'ideaCloud',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'backend',
|
||||
label: 'Backend',
|
||||
items: [
|
||||
{
|
||||
id: 'flask',
|
||||
label: 'Flask API',
|
||||
icon: <Flask size={18} />,
|
||||
value: 'flask',
|
||||
featureKey: 'flaskApi',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'testing',
|
||||
label: 'Testing',
|
||||
items: [
|
||||
{
|
||||
id: 'playwright',
|
||||
label: 'Playwright',
|
||||
icon: <Play size={18} />,
|
||||
value: 'playwright',
|
||||
featureKey: 'playwright',
|
||||
},
|
||||
{
|
||||
id: 'storybook',
|
||||
label: 'Storybook',
|
||||
icon: <BookOpen size={18} />,
|
||||
value: 'storybook',
|
||||
featureKey: 'storybook',
|
||||
},
|
||||
{
|
||||
id: 'unit-tests',
|
||||
label: 'Unit Tests',
|
||||
icon: <Cube size={18} />,
|
||||
value: 'unit-tests',
|
||||
featureKey: 'unitTests',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
id: 'tools',
|
||||
label: 'Tools & Configuration',
|
||||
items: [
|
||||
{
|
||||
id: 'errors',
|
||||
label: 'Error Repair',
|
||||
icon: <Wrench size={18} />,
|
||||
value: 'errors',
|
||||
badge: errorCount,
|
||||
featureKey: 'errorRepair',
|
||||
},
|
||||
{
|
||||
id: 'docs',
|
||||
label: 'Documentation',
|
||||
icon: <FileText size={18} />,
|
||||
value: 'docs',
|
||||
featureKey: 'documentation',
|
||||
},
|
||||
{
|
||||
id: 'settings',
|
||||
label: 'Settings',
|
||||
icon: <Gear size={18} />,
|
||||
value: 'settings',
|
||||
},
|
||||
{
|
||||
id: 'pwa',
|
||||
label: 'PWA',
|
||||
icon: <DeviceMobile size={18} />,
|
||||
value: 'pwa',
|
||||
},
|
||||
{
|
||||
id: 'features',
|
||||
label: 'Features',
|
||||
icon: <Faders size={18} />,
|
||||
value: 'features',
|
||||
},
|
||||
],
|
||||
},
|
||||
]
|
||||
|
||||
const handleItemClick = (value: string) => {
|
||||
onTabChange(value)
|
||||
setOpen(false)
|
||||
}
|
||||
|
||||
const toggleGroup = (groupId: string) => {
|
||||
setExpandedGroups((prev) => {
|
||||
const newSet = new Set(prev)
|
||||
if (newSet.has(groupId)) {
|
||||
newSet.delete(groupId)
|
||||
} else {
|
||||
newSet.add(groupId)
|
||||
}
|
||||
return newSet
|
||||
})
|
||||
}
|
||||
|
||||
const isItemVisible = (item: NavigationItem) => {
|
||||
if (!item.featureKey) return true
|
||||
return featureToggles[item.featureKey]
|
||||
}
|
||||
|
||||
const getVisibleItemsCount = (group: NavigationGroup) => {
|
||||
return group.items.filter(isItemVisible).length
|
||||
}
|
||||
|
||||
const handleExpandAll = () => {
|
||||
const allGroupIds = navigationGroups
|
||||
.filter((group) => getVisibleItemsCount(group) > 0)
|
||||
.map((group) => group.id)
|
||||
setExpandedGroups(new Set(allGroupIds))
|
||||
}
|
||||
|
||||
const handleCollapseAll = () => {
|
||||
setExpandedGroups(new Set())
|
||||
}
|
||||
|
||||
return (
|
||||
<Sheet open={open} onOpenChange={setOpen}>
|
||||
<SheetTrigger asChild>
|
||||
<Button variant="outline" size="icon" className="shrink-0">
|
||||
<List size={20} weight="bold" />
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent side="left" className="w-80">
|
||||
<SheetHeader>
|
||||
<SheetTitle>Navigation</SheetTitle>
|
||||
</SheetHeader>
|
||||
<div className="flex gap-2 mt-4">
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleExpandAll}
|
||||
className="flex-1"
|
||||
>
|
||||
<CaretDoubleDown size={16} className="mr-2" />
|
||||
Expand All
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
size="sm"
|
||||
onClick={handleCollapseAll}
|
||||
className="flex-1"
|
||||
>
|
||||
<CaretDoubleUp size={16} className="mr-2" />
|
||||
Collapse All
|
||||
</Button>
|
||||
</div>
|
||||
<ScrollArea className="h-[calc(100vh-12rem)] mt-4">
|
||||
<div className="space-y-2">
|
||||
{navigationGroups.map((group) => {
|
||||
const visibleItemsCount = getVisibleItemsCount(group)
|
||||
if (visibleItemsCount === 0) return null
|
||||
|
||||
const isExpanded = expandedGroups.has(group.id)
|
||||
|
||||
return (
|
||||
<Collapsible
|
||||
key={group.id}
|
||||
open={isExpanded}
|
||||
onOpenChange={() => toggleGroup(group.id)}
|
||||
>
|
||||
<CollapsibleTrigger className="w-full flex items-center gap-2 px-2 py-2 rounded-lg hover:bg-muted transition-colors group">
|
||||
<CaretDown
|
||||
size={16}
|
||||
weight="bold"
|
||||
className={`text-muted-foreground transition-transform ${
|
||||
isExpanded ? 'rotate-0' : '-rotate-90'
|
||||
}`}
|
||||
/>
|
||||
<h3 className="flex-1 text-left text-xs font-semibold text-muted-foreground uppercase tracking-wider">
|
||||
{group.label}
|
||||
</h3>
|
||||
<span className="text-xs text-muted-foreground">
|
||||
{visibleItemsCount}
|
||||
</span>
|
||||
</CollapsibleTrigger>
|
||||
<CollapsibleContent className="mt-1">
|
||||
<div className="space-y-1 pl-2">
|
||||
{group.items.map((item) => {
|
||||
if (!isItemVisible(item)) return null
|
||||
|
||||
const isActive = activeTab === item.value
|
||||
|
||||
return (
|
||||
<button
|
||||
key={item.id}
|
||||
onClick={() => handleItemClick(item.value)}
|
||||
className={`w-full flex items-center gap-3 px-3 py-2 rounded-lg transition-colors ${
|
||||
isActive
|
||||
? 'bg-primary text-primary-foreground'
|
||||
: 'hover:bg-muted text-foreground'
|
||||
}`}
|
||||
>
|
||||
<span className={isActive ? 'text-primary-foreground' : 'text-muted-foreground'}>
|
||||
{item.icon}
|
||||
</span>
|
||||
<span className="flex-1 text-left text-sm font-medium">
|
||||
{item.label}
|
||||
</span>
|
||||
{item.badge !== undefined && item.badge > 0 && (
|
||||
<Badge
|
||||
variant={isActive ? 'secondary' : 'destructive'}
|
||||
className="ml-auto"
|
||||
>
|
||||
{item.badge}
|
||||
</Badge>
|
||||
)}
|
||||
</button>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</CollapsibleContent>
|
||||
</Collapsible>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</ScrollArea>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
)
|
||||
}
|
||||
@@ -1,151 +0,0 @@
|
||||
import {
|
||||
ChartBar,
|
||||
Code,
|
||||
Database,
|
||||
Tree,
|
||||
FlowArrow,
|
||||
PaintBrush,
|
||||
Flask,
|
||||
Play,
|
||||
BookOpen,
|
||||
Cube,
|
||||
Wrench,
|
||||
FileText,
|
||||
Gear,
|
||||
DeviceMobile,
|
||||
Image,
|
||||
Faders,
|
||||
Lightbulb,
|
||||
} from '@phosphor-icons/react'
|
||||
|
||||
interface PageHeaderProps {
|
||||
activeTab: string
|
||||
}
|
||||
|
||||
const tabInfo: Record<string, { title: string; icon: React.ReactNode; description?: string }> = {
|
||||
dashboard: {
|
||||
title: 'Dashboard',
|
||||
icon: <ChartBar size={24} weight="duotone" />,
|
||||
description: 'Project overview and statistics',
|
||||
},
|
||||
code: {
|
||||
title: 'Code Editor',
|
||||
icon: <Code size={24} weight="duotone" />,
|
||||
description: 'Edit project files',
|
||||
},
|
||||
models: {
|
||||
title: 'Models',
|
||||
icon: <Database size={24} weight="duotone" />,
|
||||
description: 'Define Prisma data models',
|
||||
},
|
||||
components: {
|
||||
title: 'Components',
|
||||
icon: <Tree size={24} weight="duotone" />,
|
||||
description: 'Create React components',
|
||||
},
|
||||
'component-trees': {
|
||||
title: 'Component Trees',
|
||||
icon: <Tree size={24} weight="duotone" />,
|
||||
description: 'Manage component hierarchies',
|
||||
},
|
||||
workflows: {
|
||||
title: 'Workflows',
|
||||
icon: <FlowArrow size={24} weight="duotone" />,
|
||||
description: 'Design automation workflows',
|
||||
},
|
||||
lambdas: {
|
||||
title: 'Lambdas',
|
||||
icon: <Code size={24} weight="duotone" />,
|
||||
description: 'Serverless functions',
|
||||
},
|
||||
styling: {
|
||||
title: 'Styling',
|
||||
icon: <PaintBrush size={24} weight="duotone" />,
|
||||
description: 'Theme and design tokens',
|
||||
},
|
||||
sass: {
|
||||
title: 'Sass Styles',
|
||||
icon: <PaintBrush size={24} weight="duotone" />,
|
||||
description: 'Custom Sass stylesheets',
|
||||
},
|
||||
favicon: {
|
||||
title: 'Favicon Designer',
|
||||
icon: <Image size={24} weight="duotone" />,
|
||||
description: 'Design app icons',
|
||||
},
|
||||
flask: {
|
||||
title: 'Flask API',
|
||||
icon: <Flask size={24} weight="duotone" />,
|
||||
description: 'Backend API configuration',
|
||||
},
|
||||
playwright: {
|
||||
title: 'Playwright',
|
||||
icon: <Play size={24} weight="duotone" />,
|
||||
description: 'E2E test scenarios',
|
||||
},
|
||||
storybook: {
|
||||
title: 'Storybook',
|
||||
icon: <BookOpen size={24} weight="duotone" />,
|
||||
description: 'Component documentation',
|
||||
},
|
||||
'unit-tests': {
|
||||
title: 'Unit Tests',
|
||||
icon: <Cube size={24} weight="duotone" />,
|
||||
description: 'Unit test suites',
|
||||
},
|
||||
errors: {
|
||||
title: 'Error Repair',
|
||||
icon: <Wrench size={24} weight="duotone" />,
|
||||
description: 'Automated error detection and fixing',
|
||||
},
|
||||
docs: {
|
||||
title: 'Documentation',
|
||||
icon: <FileText size={24} weight="duotone" />,
|
||||
description: 'Project guides and references',
|
||||
},
|
||||
settings: {
|
||||
title: 'Settings',
|
||||
icon: <Gear size={24} weight="duotone" />,
|
||||
description: 'Project configuration',
|
||||
},
|
||||
pwa: {
|
||||
title: 'PWA',
|
||||
icon: <DeviceMobile size={24} weight="duotone" />,
|
||||
description: 'Progressive Web App settings',
|
||||
},
|
||||
features: {
|
||||
title: 'Features',
|
||||
icon: <Faders size={24} weight="duotone" />,
|
||||
description: 'Toggle feature modules',
|
||||
},
|
||||
ideas: {
|
||||
title: 'Feature Ideas',
|
||||
icon: <Lightbulb size={24} weight="duotone" />,
|
||||
description: 'Brainstorm and organize feature ideas',
|
||||
},
|
||||
}
|
||||
|
||||
export function PageHeader({ activeTab }: PageHeaderProps) {
|
||||
const info = tabInfo[activeTab] || {
|
||||
title: 'Unknown',
|
||||
icon: <Code size={24} weight="duotone" />,
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="border-b border-border bg-card px-4 sm:px-6 py-3 sm:py-4">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="w-10 h-10 rounded-lg bg-gradient-to-br from-primary/20 to-accent/20 flex items-center justify-center text-primary shrink-0">
|
||||
{info.icon}
|
||||
</div>
|
||||
<div className="min-w-0">
|
||||
<h2 className="text-lg sm:text-xl font-bold truncate">{info.title}</h2>
|
||||
{info.description && (
|
||||
<p className="text-xs sm:text-sm text-muted-foreground hidden sm:block">
|
||||
{info.description}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { ProjectDashboard } from './ProjectDashboard'
|
||||
@@ -1,45 +0,0 @@
|
||||
import { useEffect, useState } from 'react'
|
||||
import { CheckCircle, CloudCheck } from '@phosphor-icons/react'
|
||||
import { formatDistanceToNow } from 'date-fns'
|
||||
|
||||
interface SaveIndicatorProps {
|
||||
lastSaved: number | null
|
||||
}
|
||||
|
||||
export function SaveIndicator({ lastSaved }: SaveIndicatorProps) {
|
||||
const [timeAgo, setTimeAgo] = useState<string>('')
|
||||
|
||||
useEffect(() => {
|
||||
if (!lastSaved) return
|
||||
|
||||
const updateTimeAgo = () => {
|
||||
const distance = formatDistanceToNow(lastSaved, { addSuffix: true })
|
||||
setTimeAgo(distance)
|
||||
}
|
||||
|
||||
updateTimeAgo()
|
||||
const interval = setInterval(updateTimeAgo, 10000)
|
||||
|
||||
return () => clearInterval(interval)
|
||||
}, [lastSaved])
|
||||
|
||||
if (!lastSaved) return null
|
||||
|
||||
const isRecent = Date.now() - lastSaved < 3000
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-1.5 text-xs text-muted-foreground">
|
||||
{isRecent ? (
|
||||
<>
|
||||
<CheckCircle size={14} weight="fill" className="text-accent animate-in zoom-in duration-200" />
|
||||
<span className="hidden sm:inline">Saved</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<CloudCheck size={14} weight="duotone" />
|
||||
<span className="hidden sm:inline">{timeAgo}</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
import { useState } from 'react'
|
||||
import { storageConfig, setFlaskAPI, disableFlaskAPI } from '@/lib/storage-service'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Switch } from '@/components/ui/switch'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { toast } from 'sonner'
|
||||
|
||||
export function StorageSettings() {
|
||||
const [useFlask, setUseFlask] = useState(storageConfig.useFlaskAPI)
|
||||
const [flaskURL, setFlaskURL] = useState(storageConfig.flaskAPIURL || '')
|
||||
const [testing, setTesting] = useState(false)
|
||||
|
||||
const handleToggle = (enabled: boolean) => {
|
||||
setUseFlask(enabled)
|
||||
if (enabled && flaskURL) {
|
||||
setFlaskAPI(flaskURL)
|
||||
toast.success('Flask API enabled')
|
||||
} else {
|
||||
disableFlaskAPI()
|
||||
toast.info('Using IndexedDB storage')
|
||||
}
|
||||
}
|
||||
|
||||
const handleURLChange = (url: string) => {
|
||||
setFlaskURL(url)
|
||||
if (useFlask && url) {
|
||||
setFlaskAPI(url)
|
||||
}
|
||||
}
|
||||
|
||||
const testConnection = async () => {
|
||||
if (!flaskURL) {
|
||||
toast.error('Please enter a Flask API URL')
|
||||
return
|
||||
}
|
||||
|
||||
setTesting(true)
|
||||
try {
|
||||
const response = await fetch(`${flaskURL}/api/health`, {
|
||||
method: 'GET',
|
||||
headers: { 'Content-Type': 'application/json' }
|
||||
})
|
||||
|
||||
if (response.ok) {
|
||||
toast.success('Flask API connection successful!')
|
||||
setFlaskAPI(flaskURL)
|
||||
setUseFlask(true)
|
||||
} else {
|
||||
throw new Error(`HTTP ${response.status}`)
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Flask API test failed:', error)
|
||||
toast.error('Failed to connect to Flask API. Using IndexedDB instead.')
|
||||
disableFlaskAPI()
|
||||
setUseFlask(false)
|
||||
} finally {
|
||||
setTesting(false)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>Storage Settings</CardTitle>
|
||||
<CardDescription>
|
||||
Choose between local IndexedDB storage or Flask API backend
|
||||
</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="space-y-0.5">
|
||||
<Label htmlFor="flask-toggle">Use Flask API Backend</Label>
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Store data on a remote Flask server instead of locally
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
id="flask-toggle"
|
||||
checked={useFlask}
|
||||
onCheckedChange={handleToggle}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{useFlask && (
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="flask-url">Flask API URL</Label>
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
id="flask-url"
|
||||
type="url"
|
||||
placeholder="https://api.example.com"
|
||||
value={flaskURL}
|
||||
onChange={(e) => handleURLChange(e.target.value)}
|
||||
/>
|
||||
<Button
|
||||
variant="outline"
|
||||
onClick={testConnection}
|
||||
disabled={testing || !flaskURL}
|
||||
>
|
||||
{testing ? 'Testing...' : 'Test'}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">
|
||||
If the Flask API fails, the app will automatically fall back to IndexedDB
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{!useFlask && (
|
||||
<div className="rounded-md bg-muted p-3">
|
||||
<p className="text-sm text-muted-foreground">
|
||||
Currently using IndexedDB for local browser storage. Data is stored securely in your browser.
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
export { JSONStyleDesigner as StyleDesigner } from './JSONStyleDesigner'
|
||||
@@ -1 +0,0 @@
|
||||
export { JSONWorkflowDesigner as WorkflowDesigner } from './JSONWorkflowDesigner'
|
||||
@@ -1,4 +1,3 @@
|
||||
export * from './atoms'
|
||||
export * from './molecules'
|
||||
export * from './organisms'
|
||||
export { StorageSettings } from './StorageSettings'
|
||||
|
||||
Reference in New Issue
Block a user