mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
Merge pull request #127 from johndoe6345789/codex/create-wrapper-components-for-skipped-items
Move JSON wrapper interfaces to shared file
This commit is contained in:
@@ -1236,7 +1236,7 @@
|
||||
"name": "LazyBarChart",
|
||||
"category": "data",
|
||||
"canHaveChildren": true,
|
||||
"description": "LazyBarChart component",
|
||||
"description": "JSON wrapper for a props-driven bar chart (no lazy hooks)",
|
||||
"status": "json-compatible",
|
||||
"source": "molecules",
|
||||
"jsonCompatible": true
|
||||
@@ -1246,7 +1246,7 @@
|
||||
"name": "LazyD3BarChart",
|
||||
"category": "data",
|
||||
"canHaveChildren": true,
|
||||
"description": "LazyD3BarChart component",
|
||||
"description": "JSON wrapper for a simple SVG bar chart (no D3 hooks)",
|
||||
"status": "json-compatible",
|
||||
"source": "molecules",
|
||||
"jsonCompatible": true
|
||||
@@ -1256,7 +1256,7 @@
|
||||
"name": "LazyLineChart",
|
||||
"category": "data",
|
||||
"canHaveChildren": true,
|
||||
"description": "LazyLineChart component",
|
||||
"description": "JSON wrapper for a props-driven line chart (no lazy hooks)",
|
||||
"status": "json-compatible",
|
||||
"source": "molecules",
|
||||
"jsonCompatible": true
|
||||
@@ -1302,7 +1302,7 @@
|
||||
"name": "SeedDataManager",
|
||||
"category": "data",
|
||||
"canHaveChildren": true,
|
||||
"description": "SeedDataManager component",
|
||||
"description": "JSON wrapper for seed data management with props-driven state",
|
||||
"status": "json-compatible",
|
||||
"source": "molecules",
|
||||
"jsonCompatible": true
|
||||
@@ -1809,7 +1809,7 @@
|
||||
"name": "SaveIndicator",
|
||||
"category": "custom",
|
||||
"canHaveChildren": true,
|
||||
"description": "SaveIndicator component",
|
||||
"description": "JSON wrapper for save status indicator with pure-props API",
|
||||
"status": "json-compatible",
|
||||
"source": "molecules",
|
||||
"jsonCompatible": true
|
||||
@@ -1979,7 +1979,7 @@
|
||||
"name": "StorageSettings",
|
||||
"category": "custom",
|
||||
"canHaveChildren": true,
|
||||
"description": "StorageSettings component",
|
||||
"description": "JSON wrapper for storage settings controls with props-driven state",
|
||||
"status": "json-compatible",
|
||||
"source": "molecules",
|
||||
"jsonCompatible": true
|
||||
|
||||
@@ -375,6 +375,13 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "SaveIndicator",
|
||||
"label": "Save Indicator",
|
||||
"category": "feedback",
|
||||
"icon": "FloppyDisk",
|
||||
"defaultProps": { "status": "saved", "label": "Saved", "showLabel": true, "animate": true }
|
||||
},
|
||||
{
|
||||
"type": "List",
|
||||
"label": "List",
|
||||
@@ -472,6 +479,66 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "LazyBarChart",
|
||||
"label": "Bar Chart",
|
||||
"category": "data",
|
||||
"icon": "ChartBar",
|
||||
"defaultProps": {
|
||||
"data": [
|
||||
{ "name": "Q1", "value": 400 },
|
||||
{ "name": "Q2", "value": 300 },
|
||||
{ "name": "Q3", "value": 500 },
|
||||
{ "name": "Q4", "value": 280 }
|
||||
],
|
||||
"xKey": "name",
|
||||
"yKey": "value",
|
||||
"height": 300,
|
||||
"color": "#8884d8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "LazyLineChart",
|
||||
"label": "Line Chart",
|
||||
"category": "data",
|
||||
"icon": "ChartLine",
|
||||
"defaultProps": {
|
||||
"data": [
|
||||
{ "name": "Jan", "value": 120 },
|
||||
{ "name": "Feb", "value": 260 },
|
||||
{ "name": "Mar", "value": 180 },
|
||||
{ "name": "Apr", "value": 320 }
|
||||
],
|
||||
"xKey": "name",
|
||||
"yKey": "value",
|
||||
"height": 300,
|
||||
"color": "#38bdf8"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "LazyD3BarChart",
|
||||
"label": "Simple Bar Chart",
|
||||
"category": "data",
|
||||
"icon": "ChartBar",
|
||||
"defaultProps": {
|
||||
"data": [
|
||||
{ "label": "Mon", "value": 12 },
|
||||
{ "label": "Tue", "value": 18 },
|
||||
{ "label": "Wed", "value": 9 },
|
||||
{ "label": "Thu", "value": 22 }
|
||||
],
|
||||
"width": 600,
|
||||
"height": 300,
|
||||
"color": "#22c55e"
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "SeedDataManager",
|
||||
"label": "Seed Data Manager",
|
||||
"category": "data",
|
||||
"icon": "Database",
|
||||
"defaultProps": { "isLoaded": false, "isLoading": false }
|
||||
},
|
||||
{
|
||||
"type": "DataCard",
|
||||
"label": "Data Card",
|
||||
@@ -493,5 +560,19 @@
|
||||
"icon": "Toolbox",
|
||||
"canHaveChildren": true,
|
||||
"defaultProps": { "actions": [] }
|
||||
},
|
||||
{
|
||||
"type": "StorageSettings",
|
||||
"label": "Storage Settings",
|
||||
"category": "custom",
|
||||
"icon": "Database",
|
||||
"defaultProps": {
|
||||
"backend": "indexeddb",
|
||||
"flaskUrl": "http://localhost:5000",
|
||||
"isLoading": false,
|
||||
"isSwitching": false,
|
||||
"isExporting": false,
|
||||
"isImporting": false
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
@@ -19,6 +19,15 @@ import { Progress } from '@/components/ui/progress'
|
||||
import { Avatar as ShadcnAvatar, AvatarFallback, AvatarImage } from '@/components/ui/avatar'
|
||||
import * as AtomComponents from '@/components/atoms'
|
||||
import * as MoleculeComponents from '@/components/molecules'
|
||||
import {
|
||||
BreadcrumbWrapper,
|
||||
LazyBarChartWrapper,
|
||||
LazyD3BarChartWrapper,
|
||||
LazyLineChartWrapper,
|
||||
SaveIndicatorWrapper,
|
||||
SeedDataManagerWrapper,
|
||||
StorageSettingsWrapper,
|
||||
} from '@/lib/json-ui/wrappers'
|
||||
import jsonComponentsRegistry from '../../../json-components-registry.json'
|
||||
import {
|
||||
ArrowLeft, ArrowRight, Check, X, Plus, Minus, MagnifyingGlass,
|
||||
@@ -157,6 +166,16 @@ export const moleculeComponents: UIComponentRegistry = buildRegistryFromNames(
|
||||
MoleculeComponents as Record<string, ComponentType<any>>
|
||||
)
|
||||
|
||||
export const jsonWrapperComponents: UIComponentRegistry = {
|
||||
Breadcrumb: BreadcrumbWrapper,
|
||||
SaveIndicator: SaveIndicatorWrapper,
|
||||
LazyBarChart: LazyBarChartWrapper,
|
||||
LazyLineChart: LazyLineChartWrapper,
|
||||
LazyD3BarChart: LazyD3BarChartWrapper,
|
||||
SeedDataManager: SeedDataManagerWrapper,
|
||||
StorageSettings: StorageSettingsWrapper,
|
||||
}
|
||||
|
||||
export const iconComponents: UIComponentRegistry = {
|
||||
ArrowLeft,
|
||||
ArrowRight,
|
||||
@@ -203,6 +222,7 @@ export const uiComponentRegistry: UIComponentRegistry = {
|
||||
...shadcnComponents,
|
||||
...atomComponents,
|
||||
...moleculeComponents,
|
||||
...jsonWrapperComponents,
|
||||
...iconComponents,
|
||||
}
|
||||
|
||||
|
||||
11
src/lib/json-ui/wrappers/BreadcrumbWrapper.tsx
Normal file
11
src/lib/json-ui/wrappers/BreadcrumbWrapper.tsx
Normal file
@@ -0,0 +1,11 @@
|
||||
import { BreadcrumbNav } from '@/components/atoms'
|
||||
import { cn } from '@/lib/utils'
|
||||
import type { BreadcrumbWrapperProps } from './interfaces'
|
||||
|
||||
export function BreadcrumbWrapper({ items = [], className }: BreadcrumbWrapperProps) {
|
||||
if (items.length === 0) {
|
||||
return null
|
||||
}
|
||||
|
||||
return <BreadcrumbNav items={items} className={cn('flex items-center', className)} />
|
||||
}
|
||||
31
src/lib/json-ui/wrappers/LazyBarChartWrapper.tsx
Normal file
31
src/lib/json-ui/wrappers/LazyBarChartWrapper.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { Bar, BarChart, CartesianGrid, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'
|
||||
import { cn } from '@/lib/utils'
|
||||
import type { LazyBarChartWrapperProps } from './interfaces'
|
||||
|
||||
export function LazyBarChartWrapper({
|
||||
data,
|
||||
xKey,
|
||||
yKey,
|
||||
width = '100%',
|
||||
height = 300,
|
||||
color = '#8884d8',
|
||||
showGrid = true,
|
||||
showTooltip = true,
|
||||
showLegend = true,
|
||||
className,
|
||||
}: LazyBarChartWrapperProps) {
|
||||
return (
|
||||
<div className={cn('w-full', className)}>
|
||||
<ResponsiveContainer width={width} height={height}>
|
||||
<BarChart data={data}>
|
||||
{showGrid && <CartesianGrid strokeDasharray="3 3" />}
|
||||
<XAxis dataKey={xKey} />
|
||||
<YAxis />
|
||||
{showTooltip && <Tooltip />}
|
||||
{showLegend && <Legend />}
|
||||
<Bar dataKey={yKey} fill={color} />
|
||||
</BarChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
55
src/lib/json-ui/wrappers/LazyD3BarChartWrapper.tsx
Normal file
55
src/lib/json-ui/wrappers/LazyD3BarChartWrapper.tsx
Normal file
@@ -0,0 +1,55 @@
|
||||
import { cn } from '@/lib/utils'
|
||||
import type { LazyD3BarChartWrapperProps } from './interfaces'
|
||||
|
||||
export function LazyD3BarChartWrapper({
|
||||
data,
|
||||
width = 600,
|
||||
height = 300,
|
||||
color = '#8884d8',
|
||||
className,
|
||||
}: LazyD3BarChartWrapperProps) {
|
||||
const margin = { top: 20, right: 20, bottom: 30, left: 40 }
|
||||
const innerWidth = Math.max(width - margin.left - margin.right, 0)
|
||||
const innerHeight = Math.max(height - margin.top - margin.bottom, 0)
|
||||
const maxValue = Math.max(...data.map((item) => item.value), 0)
|
||||
const barGap = 8
|
||||
const barCount = data.length
|
||||
const totalGap = barCount > 1 ? barGap * (barCount - 1) : 0
|
||||
const barWidth = barCount > 0 ? Math.max((innerWidth - totalGap) / barCount, 0) : 0
|
||||
|
||||
return (
|
||||
<svg width={width} height={height} className={cn('overflow-visible', className)}>
|
||||
<g transform={`translate(${margin.left},${margin.top})`}>
|
||||
{data.map((item, index) => {
|
||||
const barHeight = maxValue ? (item.value / maxValue) * innerHeight : 0
|
||||
const x = index * (barWidth + barGap)
|
||||
const y = innerHeight - barHeight
|
||||
|
||||
return (
|
||||
<g key={`${item.label}-${index}`}>
|
||||
<rect x={x} y={y} width={barWidth} height={barHeight} fill={color} rx={2} />
|
||||
<text
|
||||
x={x + barWidth / 2}
|
||||
y={innerHeight + 16}
|
||||
textAnchor="middle"
|
||||
fill="currentColor"
|
||||
style={{ fontSize: 10 }}
|
||||
>
|
||||
{item.label}
|
||||
</text>
|
||||
<text
|
||||
x={x + barWidth / 2}
|
||||
y={Math.max(y - 6, 0)}
|
||||
textAnchor="middle"
|
||||
fill="currentColor"
|
||||
style={{ fontSize: 10 }}
|
||||
>
|
||||
{item.value}
|
||||
</text>
|
||||
</g>
|
||||
)
|
||||
})}
|
||||
</g>
|
||||
</svg>
|
||||
)
|
||||
}
|
||||
31
src/lib/json-ui/wrappers/LazyLineChartWrapper.tsx
Normal file
31
src/lib/json-ui/wrappers/LazyLineChartWrapper.tsx
Normal file
@@ -0,0 +1,31 @@
|
||||
import { CartesianGrid, Legend, Line, LineChart, ResponsiveContainer, Tooltip, XAxis, YAxis } from 'recharts'
|
||||
import { cn } from '@/lib/utils'
|
||||
import type { LazyLineChartWrapperProps } from './interfaces'
|
||||
|
||||
export function LazyLineChartWrapper({
|
||||
data,
|
||||
xKey,
|
||||
yKey,
|
||||
width = '100%',
|
||||
height = 300,
|
||||
color = '#8884d8',
|
||||
showGrid = true,
|
||||
showTooltip = true,
|
||||
showLegend = true,
|
||||
className,
|
||||
}: LazyLineChartWrapperProps) {
|
||||
return (
|
||||
<div className={cn('w-full', className)}>
|
||||
<ResponsiveContainer width={width} height={height}>
|
||||
<LineChart data={data}>
|
||||
{showGrid && <CartesianGrid strokeDasharray="3 3" />}
|
||||
<XAxis dataKey={xKey} />
|
||||
<YAxis />
|
||||
{showTooltip && <Tooltip />}
|
||||
{showLegend && <Legend />}
|
||||
<Line type="monotone" dataKey={yKey} stroke={color} />
|
||||
</LineChart>
|
||||
</ResponsiveContainer>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
21
src/lib/json-ui/wrappers/SaveIndicatorWrapper.tsx
Normal file
21
src/lib/json-ui/wrappers/SaveIndicatorWrapper.tsx
Normal file
@@ -0,0 +1,21 @@
|
||||
import { StatusIcon } from '@/components/atoms'
|
||||
import { cn } from '@/lib/utils'
|
||||
import type { SaveIndicatorWrapperProps } from './interfaces'
|
||||
|
||||
export function SaveIndicatorWrapper({
|
||||
status = 'saved',
|
||||
label,
|
||||
showLabel = true,
|
||||
animate,
|
||||
className,
|
||||
}: SaveIndicatorWrapperProps) {
|
||||
const resolvedLabel = label ?? (status === 'saved' ? 'Saved' : 'Synced')
|
||||
const shouldAnimate = animate ?? status === 'saved'
|
||||
|
||||
return (
|
||||
<div className={cn('flex items-center gap-1.5 text-xs text-muted-foreground', className)}>
|
||||
<StatusIcon type={status} animate={shouldAnimate} />
|
||||
{showLabel && <span className="hidden sm:inline">{resolvedLabel}</span>}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
122
src/lib/json-ui/wrappers/SeedDataManagerWrapper.tsx
Normal file
122
src/lib/json-ui/wrappers/SeedDataManagerWrapper.tsx
Normal file
@@ -0,0 +1,122 @@
|
||||
import { Alert, AlertDescription } from '@/components/ui/alert'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { CheckCircle, CircleNotch, Database, Trash, ArrowClockwise } from '@phosphor-icons/react'
|
||||
import type { SeedDataManagerWrapperProps } from './interfaces'
|
||||
|
||||
export function SeedDataManagerWrapper({
|
||||
isLoaded = false,
|
||||
isLoading = false,
|
||||
title = 'Seed Data Management',
|
||||
description = 'Load, reset, or clear application seed data from the database',
|
||||
loadLabel = 'Load Seed Data',
|
||||
loadingLabel = 'Loading...',
|
||||
resetLabel = 'Reset to Defaults',
|
||||
resettingLabel = 'Resetting...',
|
||||
clearLabel = 'Clear All Data',
|
||||
clearingLabel = 'Clearing...',
|
||||
onLoadSeedData,
|
||||
onResetSeedData,
|
||||
onClearAllData,
|
||||
helperText = {
|
||||
load: 'Populates database with initial data if not already loaded',
|
||||
reset: 'Overwrites all data with fresh seed data',
|
||||
clear: 'Removes all data from the database (destructive action)',
|
||||
},
|
||||
}: SeedDataManagerWrapperProps) {
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
<Database size={24} weight="duotone" />
|
||||
{title}
|
||||
</CardTitle>
|
||||
<CardDescription>{description}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="flex flex-col gap-4">
|
||||
{isLoaded && (
|
||||
<Alert>
|
||||
<CheckCircle className="h-4 w-4" weight="fill" />
|
||||
<AlertDescription>Seed data is loaded and available</AlertDescription>
|
||||
</Alert>
|
||||
)}
|
||||
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex gap-2 flex-wrap">
|
||||
<Button
|
||||
onClick={onLoadSeedData}
|
||||
disabled={isLoading || isLoaded}
|
||||
variant="default"
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<CircleNotch className="animate-spin" size={16} />
|
||||
{loadingLabel}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Database size={16} weight="fill" />
|
||||
{loadLabel}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={onResetSeedData}
|
||||
disabled={isLoading}
|
||||
variant="outline"
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<CircleNotch className="animate-spin" size={16} />
|
||||
{resettingLabel}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<ArrowClockwise size={16} weight="bold" />
|
||||
{resetLabel}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={onClearAllData}
|
||||
disabled={isLoading}
|
||||
variant="destructive"
|
||||
>
|
||||
{isLoading ? (
|
||||
<>
|
||||
<CircleNotch className="animate-spin" size={16} />
|
||||
{clearingLabel}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Trash size={16} weight="fill" />
|
||||
{clearLabel}
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="text-sm text-muted-foreground space-y-1">
|
||||
{helperText.load && (
|
||||
<p>
|
||||
<strong>Load Seed Data:</strong> {helperText.load}
|
||||
</p>
|
||||
)}
|
||||
{helperText.reset && (
|
||||
<p>
|
||||
<strong>Reset to Defaults:</strong> {helperText.reset}
|
||||
</p>
|
||||
)}
|
||||
{helperText.clear && (
|
||||
<p>
|
||||
<strong>Clear All Data:</strong> {helperText.clear}
|
||||
</p>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
146
src/lib/json-ui/wrappers/StorageSettingsWrapper.tsx
Normal file
146
src/lib/json-ui/wrappers/StorageSettingsWrapper.tsx
Normal file
@@ -0,0 +1,146 @@
|
||||
import { Badge } from '@/components/ui/badge'
|
||||
import { Button } from '@/components/ui/button'
|
||||
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from '@/components/ui/card'
|
||||
import { Input } from '@/components/ui/input'
|
||||
import { Label } from '@/components/ui/label'
|
||||
import { Cloud, Cpu, Database, Download, HardDrive, Upload } from '@phosphor-icons/react'
|
||||
import {
|
||||
getBackendCopy,
|
||||
storageSettingsCopy,
|
||||
} from '@/components/storage/storageSettingsConfig'
|
||||
import type { StorageBackendKey } from '@/components/storage/storageSettingsConfig'
|
||||
import type { StorageSettingsWrapperProps } from './interfaces'
|
||||
|
||||
const getBackendIcon = (backend: StorageBackendKey | null) => {
|
||||
switch (backend) {
|
||||
case 'flask':
|
||||
return <Cpu className="w-5 h-5" />
|
||||
case 'indexeddb':
|
||||
return <HardDrive className="w-5 h-5" />
|
||||
case 'sqlite':
|
||||
return <Database className="w-5 h-5" />
|
||||
case 'sparkkv':
|
||||
return <Cloud className="w-5 h-5" />
|
||||
default:
|
||||
return <Database className="w-5 h-5" />
|
||||
}
|
||||
}
|
||||
|
||||
export function StorageSettingsWrapper({
|
||||
backend = null,
|
||||
isLoading = false,
|
||||
flaskUrl = storageSettingsCopy.molecule.flaskUrlPlaceholder,
|
||||
isSwitching = false,
|
||||
onFlaskUrlChange,
|
||||
onSwitchToFlask,
|
||||
onSwitchToIndexedDB,
|
||||
onSwitchToSQLite,
|
||||
isExporting = false,
|
||||
isImporting = false,
|
||||
onExport,
|
||||
onImport,
|
||||
}: StorageSettingsWrapperProps) {
|
||||
const backendCopy = getBackendCopy(backend)
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle className="flex items-center gap-2">
|
||||
{getBackendIcon(backend)}
|
||||
{storageSettingsCopy.molecule.title}
|
||||
</CardTitle>
|
||||
<CardDescription>{storageSettingsCopy.molecule.description}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-sm text-muted-foreground">
|
||||
{storageSettingsCopy.molecule.currentBackendLabel}
|
||||
</span>
|
||||
<Badge variant="secondary" className="flex items-center gap-1">
|
||||
{getBackendIcon(backend)}
|
||||
{backendCopy.moleculeLabel}
|
||||
</Badge>
|
||||
</div>
|
||||
|
||||
<div className="grid gap-4">
|
||||
<div className="space-y-2">
|
||||
<Label htmlFor="flask-url">{storageSettingsCopy.molecule.flaskUrlLabel}</Label>
|
||||
<div className="flex gap-2">
|
||||
<Input
|
||||
id="flask-url"
|
||||
value={flaskUrl}
|
||||
onChange={(e) => onFlaskUrlChange?.(e.target.value)}
|
||||
placeholder={storageSettingsCopy.molecule.flaskUrlPlaceholder}
|
||||
disabled={isSwitching || isLoading}
|
||||
/>
|
||||
<Button
|
||||
onClick={onSwitchToFlask}
|
||||
disabled={isSwitching || isLoading || backend === 'flask'}
|
||||
variant={backend === 'flask' ? 'secondary' : 'default'}
|
||||
>
|
||||
<Cpu className="w-4 h-4 mr-2" />
|
||||
{backend === 'flask'
|
||||
? storageSettingsCopy.molecule.buttons.flaskActive
|
||||
: storageSettingsCopy.molecule.buttons.flaskUse}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">{storageSettingsCopy.molecule.flaskHelp}</p>
|
||||
</div>
|
||||
|
||||
<div className="flex gap-2">
|
||||
<Button
|
||||
onClick={onSwitchToIndexedDB}
|
||||
disabled={isSwitching || isLoading || backend === 'indexeddb'}
|
||||
variant={backend === 'indexeddb' ? 'secondary' : 'outline'}
|
||||
className="flex-1"
|
||||
>
|
||||
<HardDrive className="w-4 h-4 mr-2" />
|
||||
{backend === 'indexeddb'
|
||||
? storageSettingsCopy.molecule.buttons.indexeddbActive
|
||||
: storageSettingsCopy.molecule.buttons.indexeddbUse}
|
||||
</Button>
|
||||
<Button
|
||||
onClick={onSwitchToSQLite}
|
||||
disabled={isSwitching || isLoading || backend === 'sqlite'}
|
||||
variant={backend === 'sqlite' ? 'secondary' : 'outline'}
|
||||
className="flex-1"
|
||||
>
|
||||
<Database className="w-4 h-4 mr-2" />
|
||||
{backend === 'sqlite'
|
||||
? storageSettingsCopy.molecule.buttons.sqliteActive
|
||||
: storageSettingsCopy.molecule.buttons.sqliteUse}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
<div className="text-xs text-muted-foreground space-y-1">
|
||||
<p>{storageSettingsCopy.molecule.backendDetails.indexeddb}</p>
|
||||
<p>{storageSettingsCopy.molecule.backendDetails.sqlite}</p>
|
||||
<p>{storageSettingsCopy.molecule.backendDetails.flask}</p>
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardHeader>
|
||||
<CardTitle>{storageSettingsCopy.molecule.dataTitle}</CardTitle>
|
||||
<CardDescription>{storageSettingsCopy.molecule.dataDescription}</CardDescription>
|
||||
</CardHeader>
|
||||
<CardContent className="space-y-4">
|
||||
<div className="flex gap-2">
|
||||
<Button onClick={onExport} variant="outline" className="flex-1" disabled={isExporting}>
|
||||
<Download className="w-4 h-4 mr-2" />
|
||||
{storageSettingsCopy.molecule.buttons.export}
|
||||
</Button>
|
||||
<Button onClick={onImport} variant="outline" className="flex-1" disabled={isImporting}>
|
||||
<Upload className="w-4 h-4 mr-2" />
|
||||
{storageSettingsCopy.molecule.buttons.import}
|
||||
</Button>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground">{storageSettingsCopy.molecule.dataHelp}</p>
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
7
src/lib/json-ui/wrappers/index.ts
Normal file
7
src/lib/json-ui/wrappers/index.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export { BreadcrumbWrapper } from './BreadcrumbWrapper'
|
||||
export { SaveIndicatorWrapper } from './SaveIndicatorWrapper'
|
||||
export { LazyBarChartWrapper } from './LazyBarChartWrapper'
|
||||
export { LazyLineChartWrapper } from './LazyLineChartWrapper'
|
||||
export { LazyD3BarChartWrapper } from './LazyD3BarChartWrapper'
|
||||
export { SeedDataManagerWrapper } from './SeedDataManagerWrapper'
|
||||
export { StorageSettingsWrapper } from './StorageSettingsWrapper'
|
||||
91
src/lib/json-ui/wrappers/interfaces.ts
Normal file
91
src/lib/json-ui/wrappers/interfaces.ts
Normal file
@@ -0,0 +1,91 @@
|
||||
import type { StorageBackendKey } from '@/components/storage/storageSettingsConfig'
|
||||
|
||||
export interface BreadcrumbItem {
|
||||
label: string
|
||||
href?: string
|
||||
}
|
||||
|
||||
export interface BreadcrumbWrapperProps {
|
||||
items?: BreadcrumbItem[]
|
||||
className?: string
|
||||
}
|
||||
|
||||
export type SaveIndicatorStatus = 'saved' | 'synced'
|
||||
|
||||
export interface SaveIndicatorWrapperProps {
|
||||
status?: SaveIndicatorStatus
|
||||
label?: string
|
||||
showLabel?: boolean
|
||||
animate?: boolean
|
||||
className?: string
|
||||
}
|
||||
|
||||
export interface LazyBarChartWrapperProps {
|
||||
data: Array<Record<string, any>>
|
||||
xKey: string
|
||||
yKey: string
|
||||
width?: number | string
|
||||
height?: number
|
||||
color?: string
|
||||
showGrid?: boolean
|
||||
showTooltip?: boolean
|
||||
showLegend?: boolean
|
||||
className?: string
|
||||
}
|
||||
|
||||
export interface LazyLineChartWrapperProps {
|
||||
data: Array<Record<string, any>>
|
||||
xKey: string
|
||||
yKey: string
|
||||
width?: number | string
|
||||
height?: number
|
||||
color?: string
|
||||
showGrid?: boolean
|
||||
showTooltip?: boolean
|
||||
showLegend?: boolean
|
||||
className?: string
|
||||
}
|
||||
|
||||
export interface LazyD3BarChartWrapperProps {
|
||||
data: Array<{ label: string; value: number }>
|
||||
width?: number
|
||||
height?: number
|
||||
color?: string
|
||||
className?: string
|
||||
}
|
||||
|
||||
export interface SeedDataManagerWrapperProps {
|
||||
isLoaded?: boolean
|
||||
isLoading?: boolean
|
||||
title?: string
|
||||
description?: string
|
||||
loadLabel?: string
|
||||
loadingLabel?: string
|
||||
resetLabel?: string
|
||||
resettingLabel?: string
|
||||
clearLabel?: string
|
||||
clearingLabel?: string
|
||||
onLoadSeedData?: () => void
|
||||
onResetSeedData?: () => void
|
||||
onClearAllData?: () => void
|
||||
helperText?: {
|
||||
load?: string
|
||||
reset?: string
|
||||
clear?: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface StorageSettingsWrapperProps {
|
||||
backend?: StorageBackendKey | null
|
||||
isLoading?: boolean
|
||||
flaskUrl?: string
|
||||
isSwitching?: boolean
|
||||
onFlaskUrlChange?: (value: string) => void
|
||||
onSwitchToFlask?: () => void
|
||||
onSwitchToIndexedDB?: () => void
|
||||
onSwitchToSQLite?: () => void
|
||||
isExporting?: boolean
|
||||
isImporting?: boolean
|
||||
onExport?: () => void
|
||||
onImport?: () => void
|
||||
}
|
||||
@@ -11,6 +11,8 @@ export type ComponentType =
|
||||
| 'ErrorBadge' | 'Notification' | 'StatusIcon'
|
||||
| 'Table' | 'KeyValue' | 'StatCard' | 'DataCard' | 'SearchInput' | 'ActionBar'
|
||||
| 'DataList' | 'DataTable' | 'MetricCard' | 'Timeline'
|
||||
| 'LazyBarChart' | 'LazyLineChart' | 'LazyD3BarChart' | 'SeedDataManager'
|
||||
| 'SaveIndicator' | 'StorageSettings'
|
||||
| 'AppBranding' | 'LabelWithBadge' | 'EmptyEditorState' | 'LoadingFallback' | 'LoadingState' | 'NavigationGroupHeader'
|
||||
|
||||
export type ActionType =
|
||||
|
||||
Reference in New Issue
Block a user