mirror of
https://github.com/OFFIS-ESC/constellation-analyzer
synced 2026-01-27 07:43:41 +00:00
feat: add quick edit button for actor types in properties panel
Adds a small edit icon button next to the "Actor Type" label in the RightPanel Actor Properties section that opens the NodeTypeConfigModal directly in edit mode for the selected actor's type. Changes: - Added edit icon button aligned to the right of "Actor Type" label - Opens existing NodeTypeConfigModal in edit mode for current type - Enhanced NodeTypeConfigModal to support initialEditingTypeId prop - Modal automatically enters edit mode when opened with a type ID - Fixed TypeScript error with showAdvancedByDefault prop This provides a convenient shortcut for editing actor 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
a4db401ff7
commit
47957b4188
3 changed files with 79 additions and 7 deletions
|
|
@ -1,4 +1,4 @@
|
|||
import { useState } from 'react';
|
||||
import { useState, useEffect } from 'react';
|
||||
import { useGraphWithHistory } from '../../hooks/useGraphWithHistory';
|
||||
import { useConfirm } from '../../hooks/useConfirm';
|
||||
import { useToastStore } from '../../stores/toastStore';
|
||||
|
|
@ -23,15 +23,29 @@ import type { NodeTypeConfig, NodeShape } from '../../types';
|
|||
interface Props {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
initialEditingTypeId?: string | null;
|
||||
}
|
||||
|
||||
const NodeTypeConfigModal = ({ isOpen, onClose }: Props) => {
|
||||
const NodeTypeConfigModal = ({ isOpen, onClose, initialEditingTypeId }: Props) => {
|
||||
const { nodeTypes, addNodeType, updateNodeType, deleteNodeType } = useGraphWithHistory();
|
||||
const { confirm, ConfirmDialogComponent } = useConfirm();
|
||||
const { showToast } = useToastStore();
|
||||
|
||||
const [editingType, setEditingType] = useState<NodeTypeConfig | null>(null);
|
||||
|
||||
// Set editing type when initialEditingTypeId changes
|
||||
useEffect(() => {
|
||||
if (initialEditingTypeId && isOpen) {
|
||||
const typeToEdit = nodeTypes.find(t => t.id === initialEditingTypeId);
|
||||
if (typeToEdit) {
|
||||
setEditingType(typeToEdit);
|
||||
}
|
||||
} else if (!isOpen) {
|
||||
// Clear editing type when modal closes
|
||||
setEditingType(null);
|
||||
}
|
||||
}, [initialEditingTypeId, isOpen, nodeTypes]);
|
||||
|
||||
const handleAddType = (type: { name: string; color: string; shape: NodeShape; icon: string; description: string }) => {
|
||||
const id = type.name.toLowerCase().replace(/\s+/g, '-');
|
||||
|
||||
|
|
|
|||
|
|
@ -82,7 +82,6 @@ const QuickAddTypeForm = ({ onAdd }: Props) => {
|
|||
onKeyDown={handleKeyDown}
|
||||
nameInputRef={nameInputRef}
|
||||
autoFocusName={false}
|
||||
showAdvancedByDefault={false}
|
||||
/>
|
||||
|
||||
<button
|
||||
|
|
|
|||
|
|
@ -7,12 +7,14 @@ import SwapHorizIcon from '@mui/icons-material/SwapHoriz';
|
|||
import ArrowForwardIcon from '@mui/icons-material/ArrowForward';
|
||||
import SyncAltIcon from '@mui/icons-material/SyncAlt';
|
||||
import RemoveIcon from '@mui/icons-material/Remove';
|
||||
import EditIcon from '@mui/icons-material/Edit';
|
||||
import { usePanelStore } from '../../stores/panelStore';
|
||||
import { useGraphWithHistory } from '../../hooks/useGraphWithHistory';
|
||||
import { useDocumentHistory } from '../../hooks/useDocumentHistory';
|
||||
import { useConfirm } from '../../hooks/useConfirm';
|
||||
import GraphMetrics from '../Common/GraphMetrics';
|
||||
import ConnectionDisplay from '../Common/ConnectionDisplay';
|
||||
import NodeTypeConfigModal from '../Config/NodeTypeConfig';
|
||||
import type { Actor, Relation, EdgeDirectionality } from '../../types';
|
||||
|
||||
/**
|
||||
|
|
@ -80,6 +82,10 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
|||
const [hasNodeChanges, setHasNodeChanges] = useState(false);
|
||||
const [hasEdgeChanges, setHasEdgeChanges] = useState(false);
|
||||
|
||||
// Actor type modal state
|
||||
const [showActorTypeModal, setShowActorTypeModal] = useState(false);
|
||||
const [editingActorTypeId, setEditingActorTypeId] = useState<string | null>(null);
|
||||
|
||||
// Update state when selected node changes
|
||||
useEffect(() => {
|
||||
if (selectedNode) {
|
||||
|
|
@ -204,6 +210,19 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
|||
setEdges(updatedEdges);
|
||||
};
|
||||
|
||||
// Handle edit actor type
|
||||
const handleEditActorType = () => {
|
||||
if (!actorType) return;
|
||||
setEditingActorTypeId(actorType);
|
||||
setShowActorTypeModal(true);
|
||||
};
|
||||
|
||||
// Handle close actor type modal
|
||||
const handleCloseActorTypeModal = () => {
|
||||
setShowActorTypeModal(false);
|
||||
setEditingActorTypeId(null);
|
||||
};
|
||||
|
||||
// Get connections for selected node
|
||||
const getNodeConnections = () => {
|
||||
if (!selectedNode) return [];
|
||||
|
|
@ -225,6 +244,11 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
|||
</IconButton>
|
||||
</Tooltip>
|
||||
{ConfirmDialogComponent}
|
||||
<NodeTypeConfigModal
|
||||
isOpen={showActorTypeModal}
|
||||
onClose={handleCloseActorTypeModal}
|
||||
initialEditingTypeId={editingActorTypeId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -239,6 +263,11 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
|||
<PanelHeader title="Graph Analysis" onCollapse={collapseRightPanel} />
|
||||
<GraphMetrics nodes={nodes} edges={edges} />
|
||||
{ConfirmDialogComponent}
|
||||
<NodeTypeConfigModal
|
||||
isOpen={showActorTypeModal}
|
||||
onClose={handleCloseActorTypeModal}
|
||||
initialEditingTypeId={editingActorTypeId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -258,9 +287,20 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
|||
<div className="flex-1 overflow-y-auto overflow-x-hidden px-3 py-3 space-y-4">
|
||||
{/* Actor Type */}
|
||||
<div>
|
||||
<label className="block text-xs font-medium text-gray-700 mb-1">
|
||||
<div className="flex items-center justify-between mb-1">
|
||||
<label className="block text-xs font-medium text-gray-700">
|
||||
Actor Type
|
||||
</label>
|
||||
<Tooltip title="Edit Actor Type">
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={handleEditActorType}
|
||||
sx={{ padding: '2px' }}
|
||||
>
|
||||
<EditIcon sx={{ fontSize: 14 }} />
|
||||
</IconButton>
|
||||
</Tooltip>
|
||||
</div>
|
||||
<select
|
||||
value={actorType}
|
||||
onChange={(e) => {
|
||||
|
|
@ -406,6 +446,11 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
|||
)}
|
||||
</div>
|
||||
{ConfirmDialogComponent}
|
||||
<NodeTypeConfigModal
|
||||
isOpen={showActorTypeModal}
|
||||
onClose={handleCloseActorTypeModal}
|
||||
initialEditingTypeId={editingActorTypeId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
|
@ -587,11 +632,25 @@ const RightPanel = ({ selectedNode, selectedEdge, onClose }: Props) => {
|
|||
)}
|
||||
</div>
|
||||
{ConfirmDialogComponent}
|
||||
<NodeTypeConfigModal
|
||||
isOpen={showActorTypeModal}
|
||||
onClose={handleCloseActorTypeModal}
|
||||
initialEditingTypeId={editingActorTypeId}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return null;
|
||||
return (
|
||||
<>
|
||||
{ConfirmDialogComponent}
|
||||
<NodeTypeConfigModal
|
||||
isOpen={showActorTypeModal}
|
||||
onClose={handleCloseActorTypeModal}
|
||||
initialEditingTypeId={editingActorTypeId}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
export default RightPanel;
|
||||
|
|
|
|||
Loading…
Reference in a new issue