mirror of
https://github.com/bunny-lab-io/Borealis.git
synced 2025-09-11 07:48:43 -06:00
feat: replace workflow ellipsis with context menu
This commit is contained in:
@@ -231,29 +231,33 @@ export default function App() {
|
||||
[setTabs]
|
||||
);
|
||||
|
||||
const handleSaveFlow = useCallback(async () => {
|
||||
const tab = tabs.find((t) => t.id === activeTabId);
|
||||
if (!tab) return;
|
||||
const name = window.prompt("Enter workflow name", tab.tab_name || "workflow");
|
||||
if (!name) return;
|
||||
const payload = {
|
||||
name,
|
||||
workflow: {
|
||||
tab_name: tab.tab_name,
|
||||
nodes: tab.nodes,
|
||||
edges: tab.edges
|
||||
const handleSaveFlow = useCallback(
|
||||
async (name) => {
|
||||
const tab = tabs.find((t) => t.id === activeTabId);
|
||||
if (!tab || !name) return;
|
||||
const payload = {
|
||||
path: tab.folderPath ? `${tab.folderPath}/${name}` : name,
|
||||
workflow: {
|
||||
tab_name: tab.tab_name,
|
||||
nodes: tab.nodes,
|
||||
edges: tab.edges
|
||||
}
|
||||
};
|
||||
try {
|
||||
await fetch("/api/storage/save_workflow", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
setTabs((prev) =>
|
||||
prev.map((t) => (t.id === activeTabId ? { ...t, tab_name: name } : t))
|
||||
);
|
||||
} catch (err) {
|
||||
console.error("Failed to save workflow:", err);
|
||||
}
|
||||
};
|
||||
try {
|
||||
await fetch("/api/storage/save_workflow", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify(payload)
|
||||
});
|
||||
} catch (err) {
|
||||
console.error("Failed to save workflow:", err);
|
||||
}
|
||||
}, [tabs, activeTabId]);
|
||||
},
|
||||
[tabs, activeTabId]
|
||||
);
|
||||
|
||||
const renderMainContent = () => {
|
||||
switch (currentPage) {
|
||||
@@ -266,9 +270,13 @@ export default function App() {
|
||||
case "workflows":
|
||||
return (
|
||||
<WorkflowList
|
||||
onOpenWorkflow={async (workflow) => {
|
||||
onOpenWorkflow={async (workflow, folderPath, name) => {
|
||||
const newId = "flow_" + Date.now();
|
||||
if (workflow && workflow.rel_path) {
|
||||
const folder = workflow.rel_path
|
||||
.split("/")
|
||||
.slice(0, -1)
|
||||
.join("/");
|
||||
try {
|
||||
const resp = await fetch(
|
||||
`/api/storage/load_workflow?path=${encodeURIComponent(
|
||||
@@ -283,17 +291,32 @@ export default function App() {
|
||||
tab_name:
|
||||
data.tab_name || workflow.name || workflow.file_name || "Workflow",
|
||||
nodes: data.nodes || [],
|
||||
edges: data.edges || []
|
||||
edges: data.edges || [],
|
||||
folderPath: folder
|
||||
}
|
||||
]);
|
||||
} catch (err) {
|
||||
console.error("Failed to load workflow:", err);
|
||||
setTabs([
|
||||
{ id: newId, tab_name: workflow?.name || "Workflow", nodes: [], edges: [] }
|
||||
{
|
||||
id: newId,
|
||||
tab_name: workflow?.name || "Workflow",
|
||||
nodes: [],
|
||||
edges: [],
|
||||
folderPath: folder
|
||||
}
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
setTabs([{ id: newId, tab_name: `Flow`, nodes: [], edges: [] }]);
|
||||
setTabs([
|
||||
{
|
||||
id: newId,
|
||||
tab_name: name || "Flow",
|
||||
nodes: [],
|
||||
edges: [],
|
||||
folderPath: folderPath || ""
|
||||
}
|
||||
]);
|
||||
}
|
||||
setActiveTabId(newId);
|
||||
setCurrentPage("workflow-editor");
|
||||
@@ -316,6 +339,7 @@ export default function App() {
|
||||
handleOpenCloseAllDialog={() => setConfirmCloseOpen(true)}
|
||||
fileInputRef={fileInputRef}
|
||||
onFileInputChange={onFileInputChange}
|
||||
currentTabName={tabs.find((t) => t.id === activeTabId)?.tab_name}
|
||||
/>
|
||||
<Box sx={{ display: "flex", flexDirection: "column", flexGrow: 1, overflow: "hidden" }}>
|
||||
<FlowTabs
|
||||
|
@@ -132,10 +132,18 @@ export function RenameWorkflowDialog({ open, value, onChange, onCancel, onSave }
|
||||
);
|
||||
}
|
||||
|
||||
export function RenameFolderDialog({ open, value, onChange, onCancel, onSave }) {
|
||||
export function RenameFolderDialog({
|
||||
open,
|
||||
value,
|
||||
onChange,
|
||||
onCancel,
|
||||
onSave,
|
||||
title = "Folder Name",
|
||||
confirmText = "Save"
|
||||
}) {
|
||||
return (
|
||||
<Dialog open={open} onClose={onCancel} PaperProps={{ sx: { bgcolor: "#121212", color: "#fff" } }}>
|
||||
<DialogTitle>Folder Name</DialogTitle>
|
||||
<DialogTitle>{title}</DialogTitle>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
autoFocus
|
||||
@@ -157,6 +165,72 @@ export function RenameFolderDialog({ open, value, onChange, onCancel, onSave })
|
||||
}}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onCancel} sx={{ color: "#58a6ff" }}>Cancel</Button>
|
||||
<Button onClick={onSave} sx={{ color: "#58a6ff" }}>{confirmText}</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export function NewWorkflowDialog({ open, value, onChange, onCancel, onCreate }) {
|
||||
return (
|
||||
<Dialog open={open} onClose={onCancel} PaperProps={{ sx: { bgcolor: "#121212", color: "#fff" } }}>
|
||||
<DialogTitle>New Workflow</DialogTitle>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin="dense"
|
||||
label="Workflow Name"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
sx={{
|
||||
"& .MuiOutlinedInput-root": {
|
||||
backgroundColor: "#2a2a2a",
|
||||
color: "#ccc",
|
||||
"& fieldset": { borderColor: "#444" },
|
||||
"&:hover fieldset": { borderColor: "#666" }
|
||||
},
|
||||
label: { color: "#aaa" },
|
||||
mt: 1
|
||||
}}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onCancel} sx={{ color: "#58a6ff" }}>Cancel</Button>
|
||||
<Button onClick={onCreate} sx={{ color: "#58a6ff" }}>Create</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export function SaveWorkflowDialog({ open, value, onChange, onCancel, onSave }) {
|
||||
return (
|
||||
<Dialog open={open} onClose={onCancel} PaperProps={{ sx: { bgcolor: "#121212", color: "#fff" } }}>
|
||||
<DialogTitle>Save Workflow</DialogTitle>
|
||||
<DialogContent>
|
||||
<TextField
|
||||
autoFocus
|
||||
margin="dense"
|
||||
label="Workflow Name"
|
||||
fullWidth
|
||||
variant="outlined"
|
||||
value={value}
|
||||
onChange={(e) => onChange(e.target.value)}
|
||||
sx={{
|
||||
"& .MuiOutlinedInput-root": {
|
||||
backgroundColor: "#2a2a2a",
|
||||
color: "#ccc",
|
||||
"& fieldset": { borderColor: "#444" },
|
||||
"&:hover fieldset": { borderColor: "#666" }
|
||||
},
|
||||
label: { color: "#aaa" },
|
||||
mt: 1
|
||||
}}
|
||||
/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onCancel} sx={{ color: "#58a6ff" }}>Cancel</Button>
|
||||
<Button onClick={onSave} sx={{ color: "#58a6ff" }}>Save</Button>
|
||||
@@ -165,6 +239,21 @@ export function RenameFolderDialog({ open, value, onChange, onCancel, onSave })
|
||||
);
|
||||
}
|
||||
|
||||
export function ConfirmDeleteDialog({ open, message, onCancel, onConfirm }) {
|
||||
return (
|
||||
<Dialog open={open} onClose={onCancel} PaperProps={{ sx: { bgcolor: "#121212", color: "#fff" } }}>
|
||||
<DialogTitle>Confirm Delete</DialogTitle>
|
||||
<DialogContent>
|
||||
<DialogContentText sx={{ color: "#ccc" }}>{message}</DialogContentText>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<Button onClick={onCancel} sx={{ color: "#58a6ff" }}>Cancel</Button>
|
||||
<Button onClick={onConfirm} sx={{ color: "#58a6ff" }}>Confirm</Button>
|
||||
</DialogActions>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export function DeleteDeviceDialog({ open, onCancel, onConfirm }) {
|
||||
return (
|
||||
<Dialog open={open} onClose={onCancel} PaperProps={{ sx: { bgcolor: "#121212", color: "#fff" } }}>
|
||||
|
@@ -21,6 +21,7 @@ import {
|
||||
ChevronLeft as ChevronLeftIcon,
|
||||
ChevronRight as ChevronRightIcon
|
||||
} from "@mui/icons-material";
|
||||
import { SaveWorkflowDialog } from "./Dialogs";
|
||||
|
||||
export default function NodeSidebar({
|
||||
categorizedNodes,
|
||||
@@ -29,10 +30,13 @@ export default function NodeSidebar({
|
||||
handleSaveFlow,
|
||||
handleOpenCloseAllDialog,
|
||||
fileInputRef,
|
||||
onFileInputChange
|
||||
onFileInputChange,
|
||||
currentTabName
|
||||
}) {
|
||||
const [expandedCategory, setExpandedCategory] = useState(null);
|
||||
const [collapsed, setCollapsed] = useState(false);
|
||||
const [saveOpen, setSaveOpen] = useState(false);
|
||||
const [saveName, setSaveName] = useState("");
|
||||
|
||||
const handleAccordionChange = (category) => (_, isExpanded) => {
|
||||
setExpandedCategory(isExpanded ? category : null);
|
||||
@@ -79,7 +83,15 @@ export default function NodeSidebar({
|
||||
</Button>
|
||||
</Tooltip>
|
||||
<Tooltip title="Save Current Flow to Workflows Folder" placement="right" arrow>
|
||||
<Button fullWidth startIcon={<SaveIcon />} onClick={handleSaveFlow} sx={buttonStyle}>
|
||||
<Button
|
||||
fullWidth
|
||||
startIcon={<SaveIcon />}
|
||||
onClick={() => {
|
||||
setSaveName(currentTabName || "workflow");
|
||||
setSaveOpen(true);
|
||||
}}
|
||||
sx={buttonStyle}
|
||||
>
|
||||
Save Workflow
|
||||
</Button>
|
||||
</Tooltip>
|
||||
@@ -213,6 +225,16 @@ export default function NodeSidebar({
|
||||
{collapsed ? <ChevronRightIcon /> : <ChevronLeftIcon />}
|
||||
</Box>
|
||||
</Tooltip>
|
||||
<SaveWorkflowDialog
|
||||
open={saveOpen}
|
||||
value={saveName}
|
||||
onChange={setSaveName}
|
||||
onCancel={() => setSaveOpen(false)}
|
||||
onSave={() => {
|
||||
setSaveOpen(false);
|
||||
handleSaveFlow(saveName);
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
@@ -1,26 +1,17 @@
|
||||
import React, { useState, useEffect, useCallback } from "react";
|
||||
import {
|
||||
Paper,
|
||||
Box,
|
||||
Typography,
|
||||
Button,
|
||||
IconButton,
|
||||
Menu,
|
||||
MenuItem
|
||||
} from "@mui/material";
|
||||
import {
|
||||
PlayCircle as PlayCircleIcon,
|
||||
MoreVert as MoreVertIcon,
|
||||
Folder as FolderIcon,
|
||||
Description as DescriptionIcon,
|
||||
CreateNewFolder as CreateNewFolderIcon
|
||||
} from "@mui/icons-material";
|
||||
import { Paper, Box, Typography, Menu, MenuItem } from "@mui/material";
|
||||
import { Folder as FolderIcon, Description as DescriptionIcon } from "@mui/icons-material";
|
||||
import {
|
||||
SimpleTreeView,
|
||||
TreeItem,
|
||||
useTreeViewApiRef
|
||||
} from "@mui/x-tree-view";
|
||||
import { RenameWorkflowDialog, RenameFolderDialog } from "./Dialogs";
|
||||
import {
|
||||
RenameWorkflowDialog,
|
||||
RenameFolderDialog,
|
||||
NewWorkflowDialog,
|
||||
ConfirmDeleteDialog
|
||||
} from "./Dialogs";
|
||||
|
||||
function buildTree(workflows, folders) {
|
||||
const map = {};
|
||||
@@ -88,11 +79,15 @@ function buildTree(workflows, folders) {
|
||||
export default function WorkflowList({ onOpenWorkflow }) {
|
||||
const [tree, setTree] = useState([]);
|
||||
const [nodeMap, setNodeMap] = useState({});
|
||||
const [menuAnchor, setMenuAnchor] = useState(null);
|
||||
const [contextMenu, setContextMenu] = useState(null);
|
||||
const [selectedNode, setSelectedNode] = useState(null);
|
||||
const [renameValue, setRenameValue] = useState("");
|
||||
const [renameOpen, setRenameOpen] = useState(false);
|
||||
const [renameFolderOpen, setRenameFolderOpen] = useState(false);
|
||||
const [folderDialogMode, setFolderDialogMode] = useState("rename");
|
||||
const [newWorkflowOpen, setNewWorkflowOpen] = useState(false);
|
||||
const [newWorkflowName, setNewWorkflowName] = useState("");
|
||||
const [deleteOpen, setDeleteOpen] = useState(false);
|
||||
const apiRef = useTreeViewApiRef();
|
||||
const [dragNode, setDragNode] = useState(null);
|
||||
|
||||
@@ -136,50 +131,57 @@ export default function WorkflowList({ onOpenWorkflow }) {
|
||||
loadTree();
|
||||
}, [loadTree]);
|
||||
|
||||
const openMenu = (e, node) => {
|
||||
e.stopPropagation();
|
||||
setMenuAnchor(e.currentTarget);
|
||||
const handleContextMenu = (e, node) => {
|
||||
e.preventDefault();
|
||||
setSelectedNode(node);
|
||||
setContextMenu(
|
||||
contextMenu === null
|
||||
? {
|
||||
mouseX: e.clientX - 2,
|
||||
mouseY: e.clientY - 4
|
||||
}
|
||||
: null
|
||||
);
|
||||
};
|
||||
|
||||
const closeMenu = () => setMenuAnchor(null);
|
||||
|
||||
const handleRename = () => {
|
||||
closeMenu();
|
||||
setContextMenu(null);
|
||||
if (!selectedNode) return;
|
||||
setRenameValue(selectedNode.label);
|
||||
if (selectedNode.isFolder) setRenameFolderOpen(true);
|
||||
else setRenameOpen(true);
|
||||
if (selectedNode.isFolder) {
|
||||
setFolderDialogMode("rename");
|
||||
setRenameFolderOpen(true);
|
||||
} else setRenameOpen(true);
|
||||
};
|
||||
|
||||
const handleEdit = () => {
|
||||
closeMenu();
|
||||
setContextMenu(null);
|
||||
if (selectedNode && !selectedNode.isFolder && onOpenWorkflow) {
|
||||
onOpenWorkflow(selectedNode.workflow);
|
||||
}
|
||||
};
|
||||
|
||||
const handleDeleteWorkflow = async () => {
|
||||
closeMenu();
|
||||
const handleDelete = () => {
|
||||
setContextMenu(null);
|
||||
if (!selectedNode) return;
|
||||
try {
|
||||
await fetch("/api/storage/delete_workflow", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ path: selectedNode.path })
|
||||
});
|
||||
loadTree();
|
||||
} catch (err) {
|
||||
console.error("Failed to delete workflow:", err);
|
||||
}
|
||||
setDeleteOpen(true);
|
||||
};
|
||||
|
||||
const handleCreateFolder = () => {
|
||||
closeMenu();
|
||||
const handleNewFolder = () => {
|
||||
if (!selectedNode) return;
|
||||
setContextMenu(null);
|
||||
setFolderDialogMode("create");
|
||||
setRenameValue("");
|
||||
setRenameFolderOpen(true);
|
||||
};
|
||||
|
||||
const handleNewWorkflow = () => {
|
||||
if (!selectedNode) return;
|
||||
setContextMenu(null);
|
||||
setNewWorkflowName("");
|
||||
setNewWorkflowOpen(true);
|
||||
};
|
||||
|
||||
const saveRenameWorkflow = async () => {
|
||||
if (!selectedNode) return;
|
||||
try {
|
||||
@@ -197,7 +199,7 @@ export default function WorkflowList({ onOpenWorkflow }) {
|
||||
|
||||
const saveRenameFolder = async () => {
|
||||
try {
|
||||
if (selectedNode && selectedNode.isFolder) {
|
||||
if (folderDialogMode === "rename" && selectedNode) {
|
||||
await fetch("/api/storage/rename_folder", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
@@ -226,6 +228,29 @@ export default function WorkflowList({ onOpenWorkflow }) {
|
||||
}
|
||||
};
|
||||
|
||||
const confirmDelete = async () => {
|
||||
if (!selectedNode) return;
|
||||
try {
|
||||
if (selectedNode.isFolder) {
|
||||
await fetch("/api/storage/delete_folder", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ path: selectedNode.path })
|
||||
});
|
||||
} else {
|
||||
await fetch("/api/storage/delete_workflow", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ path: selectedNode.path })
|
||||
});
|
||||
}
|
||||
loadTree();
|
||||
} catch (err) {
|
||||
console.error("Failed to delete:", err);
|
||||
}
|
||||
setDeleteOpen(false);
|
||||
};
|
||||
|
||||
const renderItems = (nodes) =>
|
||||
nodes.map((n) => (
|
||||
<TreeItem
|
||||
@@ -243,6 +268,7 @@ export default function WorkflowList({ onOpenWorkflow }) {
|
||||
e.preventDefault();
|
||||
handleDrop(n);
|
||||
}}
|
||||
onContextMenu={(e) => handleContextMenu(e, n)}
|
||||
>
|
||||
{n.isFolder ? (
|
||||
<FolderIcon sx={{ mr: 1, color: "#0475c2" }} />
|
||||
@@ -250,13 +276,6 @@ export default function WorkflowList({ onOpenWorkflow }) {
|
||||
<DescriptionIcon sx={{ mr: 1, color: "#0475c2" }} />
|
||||
)}
|
||||
<Typography sx={{ flexGrow: 1, color: "#e6edf3" }}>{n.label}</Typography>
|
||||
<IconButton
|
||||
size="small"
|
||||
onClick={(e) => openMenu(e, n)}
|
||||
sx={{ color: "#ccc" }}
|
||||
>
|
||||
<MoreVertIcon fontSize="small" />
|
||||
</IconButton>
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
@@ -283,41 +302,7 @@ export default function WorkflowList({ onOpenWorkflow }) {
|
||||
Manage workflow folders and files.
|
||||
</Typography>
|
||||
</Box>
|
||||
<Box>
|
||||
<Button
|
||||
startIcon={<CreateNewFolderIcon />}
|
||||
sx={{
|
||||
mr: 1,
|
||||
color: "#0475c2",
|
||||
borderColor: "#0475c2",
|
||||
textTransform: "none",
|
||||
border: "1px solid #0475c2",
|
||||
backgroundColor: "#1e1e1e",
|
||||
"&:hover": { backgroundColor: "#1b1b1b" }
|
||||
}}
|
||||
onClick={() => {
|
||||
setSelectedNode(null);
|
||||
setRenameValue("");
|
||||
setRenameFolderOpen(true);
|
||||
}}
|
||||
>
|
||||
New Folder
|
||||
</Button>
|
||||
<Button
|
||||
startIcon={<PlayCircleIcon />}
|
||||
sx={{
|
||||
color: "#0475c2",
|
||||
borderColor: "#0475c2",
|
||||
textTransform: "none",
|
||||
border: "1px solid #0475c2",
|
||||
backgroundColor: "#1e1e1e",
|
||||
"&:hover": { backgroundColor: "#1b1b1b" }
|
||||
}}
|
||||
onClick={() => onOpenWorkflow && onOpenWorkflow()}
|
||||
>
|
||||
New Workflow
|
||||
</Button>
|
||||
</Box>
|
||||
<Box />
|
||||
</Box>
|
||||
<Box
|
||||
sx={{ p: 2 }}
|
||||
@@ -339,21 +324,30 @@ export default function WorkflowList({ onOpenWorkflow }) {
|
||||
</SimpleTreeView>
|
||||
</Box>
|
||||
<Menu
|
||||
anchorEl={menuAnchor}
|
||||
open={Boolean(menuAnchor)}
|
||||
onClose={closeMenu}
|
||||
open={contextMenu !== null}
|
||||
onClose={() => setContextMenu(null)}
|
||||
anchorReference="anchorPosition"
|
||||
anchorPosition=
|
||||
{contextMenu ? { top: contextMenu.mouseY, left: contextMenu.mouseX } : undefined}
|
||||
PaperProps={{ sx: { bgcolor: "#1e1e1e", color: "#fff", fontSize: "13px" } }}
|
||||
>
|
||||
{selectedNode?.isFolder && (
|
||||
<MenuItem onClick={handleCreateFolder}>New Folder</MenuItem>
|
||||
)}
|
||||
{selectedNode && selectedNode.id !== "root" && (
|
||||
<MenuItem onClick={handleRename}>Rename</MenuItem>
|
||||
<>
|
||||
<MenuItem onClick={handleNewWorkflow}>New Workflow</MenuItem>
|
||||
<MenuItem onClick={handleNewFolder}>New Subfolder</MenuItem>
|
||||
{selectedNode.id !== "root" && (
|
||||
<MenuItem onClick={handleRename}>Rename</MenuItem>
|
||||
)}
|
||||
{selectedNode.id !== "root" && (
|
||||
<MenuItem onClick={handleDelete}>Delete</MenuItem>
|
||||
)}
|
||||
</>
|
||||
)}
|
||||
{!selectedNode?.isFolder && (
|
||||
<>
|
||||
<MenuItem onClick={handleEdit}>Edit</MenuItem>
|
||||
<MenuItem onClick={handleDeleteWorkflow}>Delete</MenuItem>
|
||||
<MenuItem onClick={handleRename}>Rename</MenuItem>
|
||||
<MenuItem onClick={handleDelete}>Delete</MenuItem>
|
||||
</>
|
||||
)}
|
||||
</Menu>
|
||||
@@ -370,6 +364,24 @@ export default function WorkflowList({ onOpenWorkflow }) {
|
||||
onChange={setRenameValue}
|
||||
onCancel={() => setRenameFolderOpen(false)}
|
||||
onSave={saveRenameFolder}
|
||||
title={folderDialogMode === "rename" ? "Rename Folder" : "New Folder"}
|
||||
confirmText={folderDialogMode === "rename" ? "Save" : "Create"}
|
||||
/>
|
||||
<NewWorkflowDialog
|
||||
open={newWorkflowOpen}
|
||||
value={newWorkflowName}
|
||||
onChange={setNewWorkflowName}
|
||||
onCancel={() => setNewWorkflowOpen(false)}
|
||||
onCreate={() => {
|
||||
setNewWorkflowOpen(false);
|
||||
onOpenWorkflow && onOpenWorkflow(null, selectedNode.path, newWorkflowName);
|
||||
}}
|
||||
/>
|
||||
<ConfirmDeleteDialog
|
||||
open={deleteOpen}
|
||||
message="If you delete this, there is no undo button, are you sure you want to proceed?"
|
||||
onCancel={() => setDeleteOpen(false)}
|
||||
onConfirm={confirmDelete}
|
||||
/>
|
||||
</Paper>
|
||||
);
|
||||
|
Reference in New Issue
Block a user