wuhp commited on
Commit
8a42480
·
verified ·
1 Parent(s): d9c10f8

Update components/PropertiesPanel.tsx

Browse files
Files changed (1) hide show
  1. components/PropertiesPanel.tsx +70 -9
components/PropertiesPanel.tsx CHANGED
@@ -1,31 +1,92 @@
1
 
 
2
  import React from 'react';
3
  import { Node } from 'reactflow';
4
- import { NodeData, LayerDefinition } from '../types';
5
  import { LAYER_DEFINITIONS } from '../constants';
6
- import { X, Trash2 } from 'lucide-react';
7
 
8
  interface PropertiesPanelProps {
9
  selectedNode: Node<NodeData> | null;
10
  onChange: (id: string, newData: Partial<NodeData>) => void;
11
  onDelete: (id: string) => void;
12
  onClose: () => void;
 
13
  }
14
 
15
- const PropertiesPanel: React.FC<PropertiesPanelProps> = ({ selectedNode, onChange, onDelete, onClose }) => {
16
  if (!selectedNode) {
17
  return (
18
- <div className="w-80 bg-slate-900 border-l border-slate-800 p-6 flex flex-col items-center justify-center text-slate-500 h-full">
19
- <div className="w-16 h-16 rounded-full bg-slate-800 mb-4 flex items-center justify-center">
20
- <span className="text-2xl opacity-50">⚡</span>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
  </div>
22
- <p className="text-sm text-center">Select a node on the canvas to configure parameters.</p>
23
  </div>
24
  );
25
  }
26
 
27
- const definition: LayerDefinition = LAYER_DEFINITIONS[selectedNode.data.type];
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  const handleParamChange = (name: string, value: any, type: string) => {
30
  let parsedValue = value;
31
  if (type === 'number') parsedValue = Number(value);
@@ -141,4 +202,4 @@ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({ selectedNode, onChang
141
  );
142
  };
143
 
144
- export default PropertiesPanel;
 
1
 
2
+
3
  import React from 'react';
4
  import { Node } from 'reactflow';
5
+ import { NodeData, LayerDefinition, LogEntry } from '../types';
6
  import { LAYER_DEFINITIONS } from '../constants';
7
+ import { X, Trash2, Activity, Info, CheckCircle, AlertTriangle, AlertOctagon } from 'lucide-react';
8
 
9
  interface PropertiesPanelProps {
10
  selectedNode: Node<NodeData> | null;
11
  onChange: (id: string, newData: Partial<NodeData>) => void;
12
  onDelete: (id: string) => void;
13
  onClose: () => void;
14
+ logs?: LogEntry[];
15
  }
16
 
17
+ const PropertiesPanel: React.FC<PropertiesPanelProps> = ({ selectedNode, onChange, onDelete, onClose, logs = [] }) => {
18
  if (!selectedNode) {
19
  return (
20
+ <div className="w-80 bg-slate-900 border-l border-slate-800 flex flex-col h-full">
21
+ <div className="p-4 border-b border-slate-800 flex items-center gap-2">
22
+ <Activity size={18} className="text-blue-400"/>
23
+ <h2 className="text-sm font-bold text-slate-200 uppercase tracking-wider">System Activity</h2>
24
+ </div>
25
+
26
+ <div className="flex-1 overflow-y-auto p-4 space-y-3 scrollbar-thin scrollbar-thumb-slate-700">
27
+ {logs.length === 0 ? (
28
+ <div className="flex flex-col items-center justify-center text-slate-500 h-64">
29
+ <div className="w-12 h-12 rounded-full bg-slate-800 mb-3 flex items-center justify-center">
30
+ <Activity size={24} className="opacity-20"/>
31
+ </div>
32
+ <p className="text-xs text-center">No activity recorded yet.</p>
33
+ </div>
34
+ ) : (
35
+ logs.map(log => (
36
+ <div key={log.id} className="bg-slate-800/50 rounded border border-slate-800 p-3 animate-in fade-in slide-in-from-top-1 duration-300">
37
+ <div className="flex justify-between items-start mb-1">
38
+ <div className="flex items-center gap-2">
39
+ {log.type === 'info' && <Info size={12} className="text-blue-400" />}
40
+ {log.type === 'success' && <CheckCircle size={12} className="text-emerald-400" />}
41
+ {log.type === 'warning' && <AlertTriangle size={12} className="text-amber-400" />}
42
+ {log.type === 'error' && <AlertOctagon size={12} className="text-red-400" />}
43
+ <span className="text-[10px] font-bold text-slate-500 uppercase">{log.type}</span>
44
+ </div>
45
+ <span className="text-[10px] text-slate-600 font-mono">
46
+ {log.timestamp.toLocaleTimeString([], { hour: '2-digit', minute: '2-digit', second: '2-digit' })}
47
+ </span>
48
+ </div>
49
+ <p className="text-xs text-slate-300 leading-relaxed">{log.message}</p>
50
+ </div>
51
+ ))
52
+ )}
53
+
54
+ <div className="pt-4 text-center">
55
+ <p className="text-[10px] text-slate-600">
56
+ Select a node on the canvas to configure parameters.
57
+ </p>
58
+ </div>
59
  </div>
 
60
  </div>
61
  );
62
  }
63
 
64
+ const definition: LayerDefinition | undefined = LAYER_DEFINITIONS[selectedNode.data.type];
65
 
66
+ if (!definition) {
67
+ return (
68
+ <div className="w-80 bg-slate-900 border-l border-slate-800 flex flex-col h-full">
69
+ <div className="p-4 border-b border-slate-800 flex justify-between items-center">
70
+ <h2 className="text-lg font-bold text-slate-100">Unknown Layer</h2>
71
+ <button onClick={onClose}><X size={18} className="text-slate-500 hover:text-white"/></button>
72
+ </div>
73
+ <div className="p-4 flex-1">
74
+ <div className="bg-red-500/10 border border-red-500/20 text-red-400 p-3 rounded text-sm mb-4">
75
+ Error: Layer definition not found for type "{selectedNode.data.type}".
76
+ This may happen if an imported template uses deprecated types.
77
+ </div>
78
+ <button
79
+ onClick={() => onDelete(selectedNode.id)}
80
+ className="w-full flex items-center justify-center gap-2 bg-red-500/10 hover:bg-red-500/20 text-red-500 py-2 rounded transition-colors text-sm font-medium border border-red-500/20"
81
+ >
82
+ <Trash2 size={16} />
83
+ Delete Node
84
+ </button>
85
+ </div>
86
+ </div>
87
+ );
88
+ }
89
+
90
  const handleParamChange = (name: string, value: any, type: string) => {
91
  let parsedValue = value;
92
  if (type === 'number') parsedValue = Number(value);
 
202
  );
203
  };
204
 
205
+ export default PropertiesPanel;