File size: 2,815 Bytes
ef4c917
 
 
 
 
 
 
 
 
e0e4431
f277792
e0e4431
ef4c917
 
 
 
 
 
 
 
 
 
 
 
 
 
e0e4431
f277792
e0e4431
ef4c917
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f277792
 
 
e0e4431
 
ef4c917
 
e0e4431
 
 
 
 
 
 
 
f277792
e0e4431
 
f277792
ef4c917
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import type { InteractionMode } from '../types';
import { NODE_TYPES, NODE_COLORS, NODE_TYPE_LABELS } from '../constants';

interface Props {
  mode: InteractionMode;
  addNodeType: string;
  onAddNodeTypeChange: (type: string) => void;
  onSetMode: (mode: InteractionMode) => void;
  onUndo: () => void;
  onRedo: () => void;
  undoCount: number;
  redoCount: number;
}

const HINTS: Partial<Record<InteractionMode, string>> = {
  'add-node': 'Click an empty spot on the graph to drop a node.',
  'add-edge': 'Click one node, then another, to connect them.',
  delete: 'Click any node or edge to remove it.',
};

export default function EditPanel({
  mode,
  addNodeType,
  onAddNodeTypeChange,
  onSetMode,
  onUndo,
  onRedo,
  undoCount,
  redoCount,
}: Props) {
  const tool = (m: InteractionMode, label: string) => (
    <button
      className={`edit-tool${mode === m ? ' active' : ''}`}
      onClick={() => onSetMode(mode === m ? 'idle' : m)}
    >
      {label}
    </button>
  );

  return (
    <div className="panel">
      <h3>Edit Graph</h3>
      <p className="route-hint">
        Fix extraction defects by hand. Add or remove nodes and edges directly on
        the canvas.
      </p>

      <div className="edit-tools">
        {tool('add-node', 'Add Node')}
        {tool('add-edge', 'Add Edge')}
        {tool('delete', 'Delete')}
      </div>

      {mode === 'add-node' && (
        <div className="edit-nodetype">
          <label className="stage-label">New node type</label>
          <div className="nodetype-grid">
            {NODE_TYPES.map((t) => (
              <button
                key={t}
                className={`nodetype-chip${addNodeType === t ? ' active' : ''}`}
                onClick={() => onAddNodeTypeChange(t)}
              >
                <span className="type-swatch" style={{ backgroundColor: NODE_COLORS[t] }} />
                {NODE_TYPE_LABELS[t]}
              </button>
            ))}
          </div>
        </div>
      )}

      {HINTS[mode] && <div className="edit-hint">{HINTS[mode]}</div>}

      <div className="route-buttons" style={{ marginTop: 10 }}>
        <button className="btn" onClick={onUndo} disabled={undoCount === 0}>
          Undo{undoCount > 0 ? ` (${undoCount})` : ''}
        </button>
        <button className="btn" onClick={onRedo} disabled={redoCount === 0}>
          Redo{redoCount > 0 ? ` (${redoCount})` : ''}
        </button>
      </div>
      <button
        className="btn btn-block"
        style={{ marginTop: 8 }}
        onClick={() => onSetMode('idle')}
        disabled={mode === 'idle'}
      >
        Done Editing
      </button>
      <p className="edit-undo-note">
        Every change is undoable and redoable, all the way back to the originally
        extracted graph.
      </p>
    </div>
  );
}