feat: add label management button to property panels

Add quick access edit button next to "Labels" field in both Node Editor
and Edge Editor panels, matching the existing pattern for Actor Type and
Relation Type edit buttons.

Changes:
- Add small edit icon button next to Labels field
- Opens LabelConfigModal for managing label definitions
- Consistent UX with existing type configuration buttons
- Available in both NodeEditorPanel and EdgeEditorPanel

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Jan-Henrik Bruhn 2025-10-17 10:50:01 +02:00
parent 61a13383dc
commit bc8ab6c9c7
2 changed files with 44 additions and 6 deletions

View file

@ -11,6 +11,7 @@ import { useDocumentHistory } from '../../hooks/useDocumentHistory';
import { useConfirm } from '../../hooks/useConfirm'; import { useConfirm } from '../../hooks/useConfirm';
import ConnectionDisplay from '../Common/ConnectionDisplay'; import ConnectionDisplay from '../Common/ConnectionDisplay';
import EdgeTypeConfigModal from '../Config/EdgeTypeConfig'; import EdgeTypeConfigModal from '../Config/EdgeTypeConfig';
import LabelConfigModal from '../Config/LabelConfig';
import AutocompleteLabelSelector from '../Common/AutocompleteLabelSelector'; import AutocompleteLabelSelector from '../Common/AutocompleteLabelSelector';
import type { Relation, EdgeDirectionality } from '../../types'; import type { Relation, EdgeDirectionality } from '../../types';
@ -37,6 +38,9 @@ const EdgeEditorPanel = ({ selectedEdge, onClose }: EdgeEditorPanelProps) => {
const [showRelationTypeModal, setShowRelationTypeModal] = useState(false); const [showRelationTypeModal, setShowRelationTypeModal] = useState(false);
const [editingRelationTypeId, setEditingRelationTypeId] = useState<string | null>(null); const [editingRelationTypeId, setEditingRelationTypeId] = useState<string | null>(null);
// Label modal state
const [showLabelModal, setShowLabelModal] = useState(false);
// Update state when selected edge changes // Update state when selected edge changes
useEffect(() => { useEffect(() => {
if (selectedEdge.data) { if (selectedEdge.data) {
@ -218,9 +222,20 @@ const EdgeEditorPanel = ({ selectedEdge, onClose }: EdgeEditorPanelProps) => {
{/* Labels */} {/* Labels */}
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <div className="flex items-center justify-between mb-1">
Labels (optional) <label className="block text-xs font-medium text-gray-700">
</label> Labels (optional)
</label>
<Tooltip title="Manage Labels">
<IconButton
size="small"
onClick={() => setShowLabelModal(true)}
sx={{ padding: '2px' }}
>
<EditIcon sx={{ fontSize: 14 }} />
</IconButton>
</Tooltip>
</div>
<AutocompleteLabelSelector <AutocompleteLabelSelector
value={relationLabels} value={relationLabels}
onChange={(newLabels) => { onChange={(newLabels) => {
@ -326,6 +341,10 @@ const EdgeEditorPanel = ({ selectedEdge, onClose }: EdgeEditorPanelProps) => {
onClose={handleCloseRelationTypeModal} onClose={handleCloseRelationTypeModal}
initialEditingTypeId={editingRelationTypeId} initialEditingTypeId={editingRelationTypeId}
/> />
<LabelConfigModal
isOpen={showLabelModal}
onClose={() => setShowLabelModal(false)}
/>
</> </>
); );
}; };

View file

@ -6,6 +6,7 @@ import { useGraphWithHistory } from '../../hooks/useGraphWithHistory';
import { useConfirm } from '../../hooks/useConfirm'; import { useConfirm } from '../../hooks/useConfirm';
import ConnectionDisplay from '../Common/ConnectionDisplay'; import ConnectionDisplay from '../Common/ConnectionDisplay';
import NodeTypeConfigModal from '../Config/NodeTypeConfig'; import NodeTypeConfigModal from '../Config/NodeTypeConfig';
import LabelConfigModal from '../Config/LabelConfig';
import AutocompleteLabelSelector from '../Common/AutocompleteLabelSelector'; import AutocompleteLabelSelector from '../Common/AutocompleteLabelSelector';
import type { Actor } from '../../types'; import type { Actor } from '../../types';
@ -32,6 +33,9 @@ const NodeEditorPanel = ({ selectedNode, onClose }: NodeEditorPanelProps) => {
const [showActorTypeModal, setShowActorTypeModal] = useState(false); const [showActorTypeModal, setShowActorTypeModal] = useState(false);
const [editingActorTypeId, setEditingActorTypeId] = useState<string | null>(null); const [editingActorTypeId, setEditingActorTypeId] = useState<string | null>(null);
// Label modal state
const [showLabelModal, setShowLabelModal] = useState(false);
// Update state when selected node changes // Update state when selected node changes
useEffect(() => { useEffect(() => {
setActorType(selectedNode.data?.type || ''); setActorType(selectedNode.data?.type || '');
@ -204,9 +208,20 @@ const NodeEditorPanel = ({ selectedNode, onClose }: NodeEditorPanelProps) => {
{/* Labels */} {/* Labels */}
<div> <div>
<label className="block text-xs font-medium text-gray-700 mb-1"> <div className="flex items-center justify-between mb-1">
Labels (optional) <label className="block text-xs font-medium text-gray-700">
</label> Labels (optional)
</label>
<Tooltip title="Manage Labels">
<IconButton
size="small"
onClick={() => setShowLabelModal(true)}
sx={{ padding: '2px' }}
>
<EditIcon sx={{ fontSize: 14 }} />
</IconButton>
</Tooltip>
</div>
<AutocompleteLabelSelector <AutocompleteLabelSelector
value={actorLabels} value={actorLabels}
onChange={(newLabels) => { onChange={(newLabels) => {
@ -295,6 +310,10 @@ const NodeEditorPanel = ({ selectedNode, onClose }: NodeEditorPanelProps) => {
onClose={handleCloseActorTypeModal} onClose={handleCloseActorTypeModal}
initialEditingTypeId={editingActorTypeId} initialEditingTypeId={editingActorTypeId}
/> />
<LabelConfigModal
isOpen={showLabelModal}
onClose={() => setShowLabelModal(false)}
/>
</> </>
); );
}; };