mirror of
https://github.com/johndoe6345789/low-code-react-app-b.git
synced 2026-04-24 13:44:54 +00:00
feat: migrate DockerBuildDebugger to JSON
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"timestamp": "2026-01-21T05:03:24.842Z",
|
||||
"timestamp": "2026-01-21T05:05:25.613Z",
|
||||
"issues": [],
|
||||
"stats": {
|
||||
"totalJsonFiles": 337,
|
||||
"totalTsxFiles": 411,
|
||||
"totalTsxFiles": 364,
|
||||
"registryEntries": 402,
|
||||
"orphanedJson": 0,
|
||||
"duplicates": 0,
|
||||
|
||||
@@ -1394,13 +1394,14 @@
|
||||
"description": "Display component",
|
||||
"status": "supported",
|
||||
"source": "custom",
|
||||
"jsonCompatible": false,
|
||||
"jsonCompatible": true,
|
||||
"metadata": {
|
||||
"conversionDate": "2026-01-18",
|
||||
"autoGenerated": true
|
||||
"conversionDate": "2026-01-21",
|
||||
"phase": "Batch C migration",
|
||||
"autoGenerated": false
|
||||
},
|
||||
"load": {
|
||||
"path": "@/components/DockerBuildDebugger",
|
||||
"path": "@/lib/json-ui/json-components",
|
||||
"export": "DockerBuildDebugger"
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
import { useKV } from '@/hooks/use-kv'
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from '@/components/ui/tabs'
|
||||
import { Terminal, MagnifyingGlass } from '@phosphor-icons/react'
|
||||
import { parseDockerLog } from '@/lib/docker-parser'
|
||||
import { DockerError } from '@/types/docker'
|
||||
import { ErrorList } from '@/components/docker-build-debugger/ErrorList'
|
||||
import { LogAnalyzer } from '@/components/docker-build-debugger/LogAnalyzer'
|
||||
import { KnowledgeBaseView } from '@/components/docker-build-debugger/KnowledgeBaseView'
|
||||
import { toast } from 'sonner'
|
||||
import dockerBuildDebuggerText from '@/data/docker-build-debugger.json'
|
||||
import { useState } from 'react'
|
||||
|
||||
export function DockerBuildDebugger() {
|
||||
const [logInput, setLogInput] = useKV<string>('docker-log-input', '')
|
||||
const [parsedErrors, setParsedErrors] = useState<DockerError[]>([])
|
||||
|
||||
const handleParse = () => {
|
||||
if (!logInput.trim()) {
|
||||
toast.error(dockerBuildDebuggerText.analyzer.emptyLogError)
|
||||
return
|
||||
}
|
||||
|
||||
const errors = parseDockerLog(logInput)
|
||||
|
||||
if (errors.length === 0) {
|
||||
toast.info(dockerBuildDebuggerText.analyzer.noErrorsToast)
|
||||
} else {
|
||||
setParsedErrors(errors)
|
||||
toast.success(
|
||||
dockerBuildDebuggerText.analyzer.errorsFoundToast
|
||||
.replace('{{count}}', String(errors.length))
|
||||
.replace('{{plural}}', errors.length > 1 ? 's' : '')
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const handleCopy = (text: string, label: string) => {
|
||||
navigator.clipboard.writeText(text)
|
||||
toast.success(dockerBuildDebuggerText.errors.copiedToast.replace('{{label}}', label))
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="space-y-6">
|
||||
<Tabs defaultValue="analyzer" className="space-y-6">
|
||||
<TabsList className="grid w-full grid-cols-2 lg:w-auto lg:inline-grid bg-card/50 backdrop-blur-sm">
|
||||
<TabsTrigger value="analyzer" className="gap-2">
|
||||
<Terminal size={16} weight="bold" />
|
||||
<span className="hidden sm:inline">{dockerBuildDebuggerText.tabs.analyzer.label}</span>
|
||||
<span className="sm:hidden">{dockerBuildDebuggerText.tabs.analyzer.shortLabel}</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="knowledge" className="gap-2">
|
||||
<MagnifyingGlass size={16} weight="bold" />
|
||||
<span className="hidden sm:inline">{dockerBuildDebuggerText.tabs.knowledge.label}</span>
|
||||
<span className="sm:hidden">{dockerBuildDebuggerText.tabs.knowledge.shortLabel}</span>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
|
||||
<TabsContent value="analyzer" className="space-y-6">
|
||||
<LogAnalyzer
|
||||
logInput={logInput}
|
||||
onLogChange={setLogInput}
|
||||
onAnalyze={handleParse}
|
||||
onClear={() => {
|
||||
setLogInput('')
|
||||
setParsedErrors([])
|
||||
}}
|
||||
text={dockerBuildDebuggerText.analyzer}
|
||||
/>
|
||||
<ErrorList
|
||||
errors={parsedErrors}
|
||||
onCopy={handleCopy}
|
||||
text={dockerBuildDebuggerText.errors}
|
||||
commonText={dockerBuildDebuggerText.common}
|
||||
/>
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value="knowledge" className="space-y-6">
|
||||
<KnowledgeBaseView
|
||||
onCopy={handleCopy}
|
||||
text={dockerBuildDebuggerText.knowledge}
|
||||
commonText={dockerBuildDebuggerText.common}
|
||||
/>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
19
src/components/json-definitions/docker-build-debugger.json
Normal file
19
src/components/json-definitions/docker-build-debugger.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"id": "docker-build-debugger",
|
||||
"type": "div",
|
||||
"className": "space-y-6",
|
||||
"children": [
|
||||
{
|
||||
"id": "docker-tabs",
|
||||
"type": "Tabs",
|
||||
"defaultValue": "analyzer",
|
||||
"className": "space-y-6",
|
||||
"bindings": {
|
||||
"children": {
|
||||
"source": "tabsContent",
|
||||
"transform": "data"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -46,3 +46,4 @@ export { useDataSourceManagerState } from './use-data-source-manager-state'
|
||||
export { useConflictResolution } from './use-conflict-resolution'
|
||||
export { useConflictCard } from './use-conflict-card'
|
||||
export { useDocumentationView } from './use-documentation-view'
|
||||
export { useDockerBuildDebugger } from './use-docker-build-debugger'
|
||||
|
||||
72
src/hooks/use-conflict-details-dialog.ts
Normal file
72
src/hooks/use-conflict-details-dialog.ts
Normal file
@@ -0,0 +1,72 @@
|
||||
import { useState, useMemo } from 'react'
|
||||
import { ConflictItem } from '@/types/conflicts'
|
||||
|
||||
type ConflictTab = 'local' | 'remote' | 'diff'
|
||||
|
||||
type ConflictDiffItem = {
|
||||
key: string
|
||||
localValue: unknown
|
||||
remoteValue: unknown
|
||||
isDifferent: boolean
|
||||
onlyInLocal: boolean
|
||||
onlyInRemote: boolean
|
||||
}
|
||||
|
||||
function getConflictDiff(conflict: ConflictItem): ConflictDiffItem[] {
|
||||
const localKeys = Object.keys(conflict.localVersion)
|
||||
const remoteKeys = Object.keys(conflict.remoteVersion)
|
||||
const allKeys = Array.from(new Set([...localKeys, ...remoteKeys]))
|
||||
|
||||
return allKeys.map((key) => {
|
||||
const localValue = conflict.localVersion[key]
|
||||
const remoteValue = conflict.remoteVersion[key]
|
||||
const isDifferent = JSON.stringify(localValue) !== JSON.stringify(remoteValue)
|
||||
const onlyInLocal = !(key in conflict.remoteVersion)
|
||||
const onlyInRemote = !(key in conflict.localVersion)
|
||||
|
||||
return {
|
||||
key,
|
||||
localValue,
|
||||
remoteValue,
|
||||
isDifferent,
|
||||
onlyInLocal,
|
||||
onlyInRemote,
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export function useConflictDetailsDialog(conflict: ConflictItem | null) {
|
||||
const [activeTab, setActiveTab] = useState<ConflictTab>('diff')
|
||||
|
||||
const dialogState = useMemo(() => {
|
||||
if (!conflict) {
|
||||
return {
|
||||
activeTab,
|
||||
setActiveTab,
|
||||
isLocalNewer: false,
|
||||
localJson: '',
|
||||
remoteJson: '',
|
||||
diff: [],
|
||||
conflictingKeys: [],
|
||||
}
|
||||
}
|
||||
|
||||
const isLocalNewer = conflict.localTimestamp > conflict.remoteTimestamp
|
||||
const localJson = JSON.stringify(conflict.localVersion, null, 2)
|
||||
const remoteJson = JSON.stringify(conflict.remoteVersion, null, 2)
|
||||
const diff = getConflictDiff(conflict)
|
||||
const conflictingKeys = diff.filter((item) => item.isDifferent)
|
||||
|
||||
return {
|
||||
activeTab,
|
||||
setActiveTab,
|
||||
isLocalNewer,
|
||||
localJson,
|
||||
remoteJson,
|
||||
diff,
|
||||
conflictingKeys,
|
||||
}
|
||||
}, [conflict, activeTab])
|
||||
|
||||
return dialogState
|
||||
}
|
||||
46
src/hooks/use-docker-build-debugger.ts
Normal file
46
src/hooks/use-docker-build-debugger.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import { useCallback, useState } from 'react'
|
||||
import { useKV } from './use-kv'
|
||||
import { DockerError } from '@/types/docker'
|
||||
import { parseDockerLog } from '@/lib/docker-parser'
|
||||
import { toast } from 'sonner'
|
||||
import dockerBuildDebuggerText from '@/data/docker-build-debugger.json'
|
||||
|
||||
export function useDockerBuildDebugger() {
|
||||
const [logInput, setLogInput] = useKV<string>('docker-log-input', '')
|
||||
const [parsedErrors, setParsedErrors] = useState<DockerError[]>([])
|
||||
|
||||
const handleParse = useCallback(() => {
|
||||
if (!logInput.trim()) {
|
||||
toast.error(dockerBuildDebuggerText.analyzer.emptyLogError)
|
||||
return
|
||||
}
|
||||
|
||||
const errors = parseDockerLog(logInput)
|
||||
|
||||
if (errors.length === 0) {
|
||||
toast.info(dockerBuildDebuggerText.analyzer.noErrorsToast)
|
||||
} else {
|
||||
setParsedErrors(errors)
|
||||
toast.success(
|
||||
dockerBuildDebuggerText.analyzer.errorsFoundToast
|
||||
.replace('{{count}}', String(errors.length))
|
||||
.replace('{{plural}}', errors.length > 1 ? 's' : '')
|
||||
)
|
||||
}
|
||||
}, [logInput])
|
||||
|
||||
const handleCopy = useCallback((text: string, label: string) => {
|
||||
navigator.clipboard.writeText(text)
|
||||
toast.success(dockerBuildDebuggerText.errors.copiedToast.replace('{{label}}', label))
|
||||
}, [])
|
||||
|
||||
return {
|
||||
logInput,
|
||||
setLogInput,
|
||||
parsedErrors,
|
||||
setParsedErrors,
|
||||
handleParse,
|
||||
handleCopy,
|
||||
dockerBuildDebuggerText,
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,9 @@ import { useDataSourceManagerState } from '@/hooks/use-data-source-manager-state
|
||||
import { useFormatValue } from '@/hooks/use-format-value'
|
||||
import { useConflictResolution } from '@/hooks/use-conflict-resolution'
|
||||
import { useConflictCard } from '@/hooks/use-conflict-card'
|
||||
import { useConflictDetailsDialog } from '@/hooks/use-conflict-details-dialog'
|
||||
import { useDocumentationView } from '@/hooks/use-documentation-view'
|
||||
import { useDockerBuildDebugger } from '@/hooks/use-docker-build-debugger'
|
||||
|
||||
export interface HookRegistry {
|
||||
[key: string]: (...args: any[]) => any
|
||||
@@ -54,7 +56,9 @@ export const hooksRegistry: HookRegistry = {
|
||||
useFormatValue,
|
||||
useConflictResolution,
|
||||
useConflictCard,
|
||||
useConflictDetailsDialog,
|
||||
useDocumentationView,
|
||||
useDockerBuildDebugger,
|
||||
// Add more hooks here as needed
|
||||
}
|
||||
|
||||
|
||||
9
src/lib/json-ui/interfaces/conflict-details-dialog.ts
Normal file
9
src/lib/json-ui/interfaces/conflict-details-dialog.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
import { ConflictItem } from '@/types/conflicts'
|
||||
|
||||
export interface ConflictDetailsDialogProps {
|
||||
conflict: ConflictItem | null
|
||||
open: boolean
|
||||
onOpenChange: (open: boolean) => void
|
||||
onResolve: (conflictId: string, strategy: 'local' | 'remote' | 'merge') => void
|
||||
isResolving: boolean
|
||||
}
|
||||
4
src/lib/json-ui/interfaces/docker-build-debugger.ts
Normal file
4
src/lib/json-ui/interfaces/docker-build-debugger.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export interface DockerBuildDebuggerProps {
|
||||
// Stateful component with internal state management
|
||||
// No props required
|
||||
}
|
||||
@@ -208,6 +208,7 @@ export * from './pwa-status-bar'
|
||||
export * from './pwa-update-prompt'
|
||||
export * from './pwa-install-prompt'
|
||||
export * from './conflict-card'
|
||||
export * from './conflict-details-dialog'
|
||||
export * from './conflict-indicator'
|
||||
export * from './error-panel'
|
||||
export * from './preview-dialog'
|
||||
@@ -232,3 +233,4 @@ export * from './project-manager'
|
||||
export * from './storage-settings-panel'
|
||||
export * from './feature-toggle-settings'
|
||||
export * from './documentation-view'
|
||||
export * from './docker-build-debugger'
|
||||
|
||||
@@ -251,6 +251,7 @@ import type {
|
||||
StorageSettingsPanelProps,
|
||||
FeatureToggleSettingsProps,
|
||||
DocumentationViewProps,
|
||||
DockerBuildDebuggerProps,
|
||||
} from './interfaces'
|
||||
|
||||
// Import JSON definitions
|
||||
@@ -499,6 +500,7 @@ import projectManagerDef from '@/components/json-definitions/project-manager.jso
|
||||
import storageSettingsPanelDef from '@/components/json-definitions/storage-settings-panel.json'
|
||||
import featureToggleSettingsDef from '@/components/json-definitions/feature-toggle-settings.json'
|
||||
import documentationViewDef from '@/components/json-definitions/documentation-view.json'
|
||||
import dockerBuildDebuggerDef from '@/components/json-definitions/docker-build-debugger.json'
|
||||
|
||||
// Create pure JSON components (no hooks)
|
||||
export const BindingIndicator = createJsonComponent<BindingIndicatorProps>(bindingIndicatorDef)
|
||||
@@ -947,4 +949,13 @@ export const DocumentationView = createJsonComponentWithHooks<DocumentationViewP
|
||||
}
|
||||
})
|
||||
|
||||
export const DockerBuildDebugger = createJsonComponentWithHooks<DockerBuildDebuggerProps>(dockerBuildDebuggerDef, {
|
||||
hooks: {
|
||||
debuggerState: {
|
||||
hookName: 'useDockerBuildDebugger',
|
||||
args: () => []
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
// All components converted to pure JSON! 🎉
|
||||
|
||||
Reference in New Issue
Block a user