feat: drop node onto container node to nest it
Dropping a top-level node over any container_mode node (proxmox, docker_host, ...) now pops a confirm modal that nests it as a child (sets parentId), mirroring the existing drop-onto-group flow. - store: addToContainer(containerId, childId) - CanvasContainer: detect container_mode intersection on drag stop (group still wins if both intersect) - generalize ConfirmAddToGroupModal with a container variant ha-relevant: yes
This commit is contained in:
+16
-2
@@ -43,7 +43,7 @@ const STANDALONE = import.meta.env.VITE_STANDALONE === 'true'
|
||||
const STANDALONE_STORAGE_KEY = 'homelable_canvas'
|
||||
|
||||
export default function App() {
|
||||
const { loadCanvas, markSaved, markUnsaved, selectedNodeId, selectedNodeIds, addNode, updateNode, deleteNode, onConnect, updateEdge, deleteEdge, setProxmoxContainerMode, setNodeZIndex, editingGroupRectId, setEditingGroupRectId, editingTextId, setEditingTextId, nodes, edges, snapshotHistory, undo, redo, addToGroup } = useCanvasStore()
|
||||
const { loadCanvas, markSaved, markUnsaved, selectedNodeId, selectedNodeIds, addNode, updateNode, deleteNode, onConnect, updateEdge, deleteEdge, setProxmoxContainerMode, setNodeZIndex, editingGroupRectId, setEditingGroupRectId, editingTextId, setEditingTextId, nodes, edges, snapshotHistory, undo, redo, addToGroup, addToContainer } = useCanvasStore()
|
||||
const canvasRef = useRef<HTMLDivElement>(null)
|
||||
const { isAuthenticated } = useAuthStore()
|
||||
const { activeTheme, setTheme, customStyle, setCustomStyle } = useThemeStore()
|
||||
@@ -70,6 +70,7 @@ export default function App() {
|
||||
const [editNodeId, setEditNodeId] = useState<string | null>(null)
|
||||
const [pendingConnection, setPendingConnection] = useState<Connection | null>(null)
|
||||
const [pendingGroupAdd, setPendingGroupAdd] = useState<{ nodeId: string; groupId: string } | null>(null)
|
||||
const [pendingContainerAdd, setPendingContainerAdd] = useState<{ nodeId: string; containerId: string } | null>(null)
|
||||
const [editEdgeId, setEditEdgeId] = useState<string | null>(null)
|
||||
const [scanConfigOpen, setScanConfigOpen] = useState(false)
|
||||
const [settingsOpen, setSettingsOpen] = useState(false)
|
||||
@@ -634,6 +635,7 @@ export default function App() {
|
||||
onNodeDoubleClick={handleNodeDoubleClick}
|
||||
onNodeDragStart={snapshotHistory}
|
||||
onRequestAddToGroup={setPendingGroupAdd}
|
||||
onRequestAddToContainer={setPendingContainerAdd}
|
||||
onOpenPending={(deviceId) => openPendingModal(deviceId)}
|
||||
/>
|
||||
</div>
|
||||
@@ -810,7 +812,7 @@ export default function App() {
|
||||
<ConfirmAddToGroupModal
|
||||
open={!!pendingGroupAdd}
|
||||
nodeLabel={pendingGroupAdd ? (nodes.find((n) => n.id === pendingGroupAdd.nodeId)?.data.label ?? '') : ''}
|
||||
groupLabel={pendingGroupAdd ? (nodes.find((n) => n.id === pendingGroupAdd.groupId)?.data.label ?? '') : ''}
|
||||
targetLabel={pendingGroupAdd ? (nodes.find((n) => n.id === pendingGroupAdd.groupId)?.data.label ?? '') : ''}
|
||||
onConfirm={() => {
|
||||
if (pendingGroupAdd) addToGroup(pendingGroupAdd.groupId, pendingGroupAdd.nodeId)
|
||||
setPendingGroupAdd(null)
|
||||
@@ -818,6 +820,18 @@ export default function App() {
|
||||
onCancel={() => setPendingGroupAdd(null)}
|
||||
/>
|
||||
|
||||
<ConfirmAddToGroupModal
|
||||
open={!!pendingContainerAdd}
|
||||
variant="container"
|
||||
nodeLabel={pendingContainerAdd ? (nodes.find((n) => n.id === pendingContainerAdd.nodeId)?.data.label ?? '') : ''}
|
||||
targetLabel={pendingContainerAdd ? (nodes.find((n) => n.id === pendingContainerAdd.containerId)?.data.label ?? '') : ''}
|
||||
onConfirm={() => {
|
||||
if (pendingContainerAdd) addToContainer(pendingContainerAdd.containerId, pendingContainerAdd.nodeId)
|
||||
setPendingContainerAdd(null)
|
||||
}}
|
||||
onCancel={() => setPendingContainerAdd(null)}
|
||||
/>
|
||||
|
||||
{!STANDALONE && (
|
||||
<SettingsModal open={settingsOpen} onClose={() => setSettingsOpen(false)} />
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user