mirror of
https://github.com/OFFIS-ESC/constellation-analyzer
synced 2026-01-27 07:43:41 +00:00
feat: add quick edit button for relation types in properties panel
Adds a small edit icon button next to the "Relation Type" label in the RightPanel Relation Properties section that opens the EdgeTypeConfigModal directly in edit mode for the selected relation's type. Changes: - Added edit icon button aligned to the right of "Relation Type" label - Opens existing EdgeTypeConfigModal in edit mode for current type - Enhanced EdgeTypeConfigModal to support initialEditingTypeId prop - Modal automatically enters edit mode when opened with a type ID This mirrors the actor type edit button functionality and provides a convenient shortcut for editing relation types without navigating to the settings menu or left panel configuration. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
47957b4188
commit
cfd7a0b76f
2 changed files with 72 additions and 9 deletions
|
|
@ -1,4 +1,4 @@
|
||||||
import { useState } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { useGraphWithHistory } from '../../hooks/useGraphWithHistory';
|
import { useGraphWithHistory } from '../../hooks/useGraphWithHistory';
|
||||||
import { useConfirm } from '../../hooks/useConfirm';
|
import { useConfirm } from '../../hooks/useConfirm';
|
||||||
import { useToastStore } from '../../stores/toastStore';
|
import { useToastStore } from '../../stores/toastStore';
|
||||||
|
|
@ -21,15 +21,29 @@ import type { EdgeTypeConfig, EdgeDirectionality } from '../../types';
|
||||||
interface Props {
|
interface Props {
|
||||||
isOpen: boolean;
|
isOpen: boolean;
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
|
initialEditingTypeId?: string | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const EdgeTypeConfigModal = ({ isOpen, onClose }: Props) => {
|
const EdgeTypeConfigModal = ({ isOpen, onClose, initialEditingTypeId }: Props) => {
|
||||||
const { edgeTypes, addEdgeType, updateEdgeType, deleteEdgeType } = useGraphWithHistory();
|
const { edgeTypes, addEdgeType, updateEdgeType, deleteEdgeType } = useGraphWithHistory();
|
||||||
const { confirm, ConfirmDialogComponent } = useConfirm();
|
const { confirm, ConfirmDialogComponent } = useConfirm();
|
||||||
const { showToast } = useToastStore();
|
const { showToast } = useToastStore();
|
||||||
|
|
||||||
const [editingType, setEditingType] = useState<EdgeTypeConfig | null>(null);
|
const [editingType, setEditingType] = useState<EdgeTypeConfig | null>(null);
|
||||||
|
|
||||||
|
// Set editing type when initialEditingTypeId changes
|
||||||
|
useEffect(() => {
|
||||||
|
if (initialEditingTypeId && isOpen) {
|
||||||
|
const typeToEdit = edgeTypes.find(t => t.id === initialEditingTypeId);
|
||||||
|
if (typeToEdit) {
|
||||||
|
setEditingType(typeToEdit);
|
||||||
|
}
|
||||||
|
} else if (!isOpen) {
|
||||||
|
// Clear editing type when modal closes
|
||||||
|
setEditingType(null);
|
||||||
|
}
|
||||||
|
}, [initialEditingTypeId, isOpen, edgeTypes]);
|
||||||
|
|
||||||
const handleAddType = (type: {
|
const handleAddType = (type: {
|
||||||
label: string;
|
label: string;
|
||||||
color: string;
|
color: string;
|
||||||
|
|
|
||||||
|
|
@ -15,6 +15,7 @@ import { useConfirm } from '../../hooks/useConfirm';
|
||||||
import GraphMetrics from '../Common/GraphMetrics';
|
import GraphMetrics from '../Common/GraphMetrics';
|
||||||
import ConnectionDisplay from '../Common/ConnectionDisplay';
|
import ConnectionDisplay from '../Common/ConnectionDisplay';
|
||||||
import NodeTypeConfigModal from '../Config/NodeTypeConfig';
|
import NodeTypeConfigModal from '../Config/NodeTypeConfig';
|
||||||
|
import EdgeTypeConfigModal from '../Config/EdgeTypeConfig';
|
||||||
import type { Actor, Relation, EdgeDirectionality } from '../../types';
|
import type { Actor, Relation, EdgeDirectionality } from '../../types';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -86,6 +87,10 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
const [showActorTypeModal, setShowActorTypeModal] = useState(false);
|
const [showActorTypeModal, setShowActorTypeModal] = useState(false);
|
||||||
const [editingActorTypeId, setEditingActorTypeId] = useState<string | null>(null);
|
const [editingActorTypeId, setEditingActorTypeId] = useState<string | null>(null);
|
||||||
|
|
||||||
|
// Relation type modal state
|
||||||
|
const [showRelationTypeModal, setShowRelationTypeModal] = useState(false);
|
||||||
|
const [editingRelationTypeId, setEditingRelationTypeId] = useState<string | null>(null);
|
||||||
|
|
||||||
// Update state when selected node changes
|
// Update state when selected node changes
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (selectedNode) {
|
if (selectedNode) {
|
||||||
|
|
@ -223,6 +228,19 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
setEditingActorTypeId(null);
|
setEditingActorTypeId(null);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Handle edit relation type
|
||||||
|
const handleEditRelationType = () => {
|
||||||
|
if (!relationType) return;
|
||||||
|
setEditingRelationTypeId(relationType);
|
||||||
|
setShowRelationTypeModal(true);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Handle close relation type modal
|
||||||
|
const handleCloseRelationTypeModal = () => {
|
||||||
|
setShowRelationTypeModal(false);
|
||||||
|
setEditingRelationTypeId(null);
|
||||||
|
};
|
||||||
|
|
||||||
// Get connections for selected node
|
// Get connections for selected node
|
||||||
const getNodeConnections = () => {
|
const getNodeConnections = () => {
|
||||||
if (!selectedNode) return [];
|
if (!selectedNode) return [];
|
||||||
|
|
@ -249,6 +267,11 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
onClose={handleCloseActorTypeModal}
|
onClose={handleCloseActorTypeModal}
|
||||||
initialEditingTypeId={editingActorTypeId}
|
initialEditingTypeId={editingActorTypeId}
|
||||||
/>
|
/>
|
||||||
|
<EdgeTypeConfigModal
|
||||||
|
isOpen={showRelationTypeModal}
|
||||||
|
onClose={handleCloseRelationTypeModal}
|
||||||
|
initialEditingTypeId={editingRelationTypeId}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -268,6 +291,11 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
onClose={handleCloseActorTypeModal}
|
onClose={handleCloseActorTypeModal}
|
||||||
initialEditingTypeId={editingActorTypeId}
|
initialEditingTypeId={editingActorTypeId}
|
||||||
/>
|
/>
|
||||||
|
<EdgeTypeConfigModal
|
||||||
|
isOpen={showRelationTypeModal}
|
||||||
|
onClose={handleCloseRelationTypeModal}
|
||||||
|
initialEditingTypeId={editingRelationTypeId}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -451,6 +479,11 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
onClose={handleCloseActorTypeModal}
|
onClose={handleCloseActorTypeModal}
|
||||||
initialEditingTypeId={editingActorTypeId}
|
initialEditingTypeId={editingActorTypeId}
|
||||||
/>
|
/>
|
||||||
|
<EdgeTypeConfigModal
|
||||||
|
isOpen={showRelationTypeModal}
|
||||||
|
onClose={handleCloseRelationTypeModal}
|
||||||
|
initialEditingTypeId={editingRelationTypeId}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
@ -495,9 +528,20 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
<div className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-3 space-y-4">
|
<div className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-3 space-y-4">
|
||||||
{/* Relation Type */}
|
{/* Relation Type */}
|
||||||
<div>
|
<div>
|
||||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
<div className="flex items-center justify-between mb-1">
|
||||||
Relation Type
|
<label className="block text-xs font-medium text-gray-700">
|
||||||
</label>
|
Relation Type
|
||||||
|
</label>
|
||||||
|
<Tooltip title="Edit Relation Type">
|
||||||
|
<IconButton
|
||||||
|
size="small"
|
||||||
|
onClick={handleEditRelationType}
|
||||||
|
sx={{ padding: '2px' }}
|
||||||
|
>
|
||||||
|
<EditIcon sx={{ fontSize: 14 }} />
|
||||||
|
</IconButton>
|
||||||
|
</Tooltip>
|
||||||
|
</div>
|
||||||
<select
|
<select
|
||||||
value={relationType}
|
value={relationType}
|
||||||
onChange={(e) => {
|
onChange={(e) => {
|
||||||
|
|
@ -632,10 +676,10 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
{ConfirmDialogComponent}
|
{ConfirmDialogComponent}
|
||||||
<NodeTypeConfigModal
|
<EdgeTypeConfigModal
|
||||||
isOpen={showActorTypeModal}
|
isOpen={showRelationTypeModal}
|
||||||
onClose={handleCloseActorTypeModal}
|
onClose={handleCloseRelationTypeModal}
|
||||||
initialEditingTypeId={editingActorTypeId}
|
initialEditingTypeId={editingRelationTypeId}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
@ -649,6 +693,11 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
||||||
onClose={handleCloseActorTypeModal}
|
onClose={handleCloseActorTypeModal}
|
||||||
initialEditingTypeId={editingActorTypeId}
|
initialEditingTypeId={editingActorTypeId}
|
||||||
/>
|
/>
|
||||||
|
<EdgeTypeConfigModal
|
||||||
|
isOpen={showRelationTypeModal}
|
||||||
|
onClose={handleCloseRelationTypeModal}
|
||||||
|
initialEditingTypeId={editingRelationTypeId}
|
||||||
|
/>
|
||||||
</>
|
</>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue