Skip to content

Commit

Permalink
feat(fe): dock mode (#562)
Browse files Browse the repository at this point in the history
Co-authored-by: Hu Yueh-Wei <[email protected]>
  • Loading branch information
shczhen and halajohn authored Jan 20, 2025
1 parent 34e2672 commit 66c3778
Show file tree
Hide file tree
Showing 26 changed files with 2,190 additions and 847 deletions.
Binary file modified core/src/ten_manager/designer_frontend/bun.lockb
Binary file not shown.
645 changes: 371 additions & 274 deletions core/src/ten_manager/designer_frontend/package-lock.json

Large diffs are not rendered by default.

30 changes: 17 additions & 13 deletions core/src/ten_manager/designer_frontend/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,58 +11,62 @@
},
"dependencies": {
"@monaco-editor/react": "^4.6.0",
"@radix-ui/react-context-menu": "^2.2.4",
"@radix-ui/react-dialog": "^1.1.4",
"@radix-ui/react-dropdown-menu": "^2.1.4",
"@radix-ui/react-navigation-menu": "^1.2.3",
"@radix-ui/react-slot": "^1.1.1",
"@radix-ui/react-tabs": "^1.1.2",
"@radix-ui/react-tooltip": "^1.1.6",
"@tanstack/react-table": "^8.20.6",
"@xterm/addon-attach": "^0.11.0",
"@xterm/addon-fit": "^0.10.0",
"@xterm/addon-unicode11": "^0.8.0",
"@xterm/addon-web-links": "^0.11.0",
"@xterm/xterm": "^5.5.0",
"@xyflow/react": "^12.3.6",
"@xyflow/react": "^12.4.1",
"class-variance-authority": "^0.7.1",
"clsx": "^2.1.1",
"dagre": "^0.8.5",
"i18next": "^24.2.1",
"i18next-browser-languagedetector": "^8.0.2",
"i18next-http-backend": "^3.0.1",
"lucide-react": "^0.469.0",
"lucide-react": "^0.473.0",
"monaco-editor": "^0.52.2",
"next-themes": "^0.4.4",
"pino": "^9.6.0",
"react": "^18.3.1",
"react-dom": "^18.3.1",
"react-i18next": "^15.4.0",
"react-icons": "^5.4.0",
"sonner": "^1.7.1",
"react-resizable-panels": "^2.1.7",
"sonner": "^1.7.2",
"swr": "^2.3.0",
"tailwind-merge": "^2.6.0",
"tailwindcss-animate": "^1.0.7",
"zod": "^3.24.1"
"zod": "^3.24.1",
"zustand": "^5.0.3"
},
"devDependencies": {
"@eslint/js": "^9.17.0",
"@eslint/js": "^9.18.0",
"@types/dagre": "^0.7.52",
"@types/node": "^22.10.5",
"@types/node": "^22.10.7",
"@types/react": "^18.3.18",
"@types/react-dom": "^18.3.5",
"@vitejs/plugin-react-swc": "^3.7.2",
"autoprefixer": "^10.4.20",
"esbuild": "^0.24.2",
"eslint": "^9.17.0",
"eslint": "^9.18.0",
"eslint-plugin-react-hooks": "^5.1.0",
"eslint-plugin-react-refresh": "^0.4.16",
"eslint-plugin-react-refresh": "^0.4.18",
"globals": "^15.14.0",
"pino-pretty": "^13.0.0",
"postcss": "^8.4.49",
"postcss": "^8.5.1",
"prettier": "^3.4.2",
"prettier-plugin-tailwindcss": "^0.6.9",
"prettier-plugin-tailwindcss": "^0.6.10",
"tailwindcss": "^3.4.17",
"typescript": "~5.7.2",
"typescript-eslint": "^8.19.1",
"vite": "^6.0.7"
"typescript": "~5.7.3",
"typescript-eslint": "^8.20.0",
"vite": "^6.0.9"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,39 @@
},
"officialSite": "Official site",
"poweredBy": "Powered by",
"poweredBy2": "Powered by",
"poweredByTenFramework": "Powered by <0></0>",
"github": "GitHub"
},
"action": {
"edit": "Edit",
"delete": "Delete",
"pinToDock": "Pin to Dock",
"save": "Save",
"discard": "Discard",
"launchTerminal": "Launch terminal",
"ok": "OK",
"cancel": "Cancel",
"selected": "Selected",
"autoStart": "Auto Start",
"confirm": "Confirm",
"upstream": "Upstream",
"downstream": "Downstream"
"downstream": "Downstream",
"popout": "Popout",
"close": "Close",
"closeAllTabs": "Close All Tabs",
"unsaved": "unsaved"
},
"toast": {
"saveFileSuccess": "File saved successfully",
"saveFileFailed": "Failed to save file"
"saveFileFailed": "Failed to save file",
"fetchFileContentFailed": "Failed to fetch file content"
},
"popup": {
"editor": {
"confirmSaveFile": "Are you sure you want to save the file?"
"confirmSaveFile": "Are you sure you want to save the file?",
"confirmSaveChanges": "Do you want to save the changes?",
"confirmCloseAllTabs": "Are you sure you want to close all tabs? All unsaved changes will be lost.",
"confirmChangePosition": "Are you sure you want to change the position? All unsaved changes will be lost."
},
"selectGraph": {
"title": "Select a Graph"
Expand All @@ -52,6 +63,13 @@
"title": "Connection"
}
},
"dock": {
"notSelected": "Not Tab Selected",
"dockSide": "Dock Side",
"left": "Left",
"right": "Right",
"bottom": "Bottom"
},
"dataTable": {
"no": "No.",
"upstream": "Upstream",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,28 +20,39 @@
},
"officialSite": "官方网站",
"poweredBy": "技术支持",
"poweredBy2": "Powered by",
"poweredByTenFramework": "由 <0></0> 提供支持",
"github": "GitHub"
},
"action": {
"edit": "编辑",
"delete": "删除",
"pinToDock": "固定到 Dock",
"save": "保存",
"discard": "丢弃",
"launchTerminal": "启动终端",
"ok": "确定",
"cancel": "取消",
"selected": "已选择",
"autoStart": "自动启动",
"confirm": "确认",
"upstream": "上游",
"downstream": "下游"
"downstream": "下游",
"popout": "弹出",
"close": "关闭",
"closeAllTabs": "关闭所有标签页",
"unsaved": "未保存"
},
"toast": {
"saveFileSuccess": "文件保存成功",
"saveFileFailed": "文件保存失败"
"saveFileFailed": "文件保存失败",
"fetchFileContentFailed": "文件内容获取失败"
},
"popup": {
"editor": {
"confirmSaveFile": "确定要保存文件吗?"
"confirmSaveFile": "确定要保存文件吗?",
"confirmSaveChanges": "确定要保存更改吗?",
"confirmCloseAllTabs": "确定要关闭所有标签页吗?所有未保存的更改将会丢失。",
"confirmChangePosition": "确定要更改 Dock 位置吗?所有未保存的更改将会丢失。"
},
"selectGraph": {
"title": "选择图表"
Expand All @@ -52,6 +63,13 @@
"title": "连接"
}
},
"dock": {
"notSelected": "未选择标签页",
"dockSide": "停靠位置",
"left": "左侧",
"right": "右侧",
"bottom": "底部"
},
"dataTable": {
"no": "序号",
"upstream": "上游",
Expand Down
138 changes: 98 additions & 40 deletions core/src/ten_manager/designer_frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,37 @@ import {
import Popup from "@/components/Popup/Popup";
import type { IGraph } from "@/types/graphs";
import { ReactFlowDataContext } from "@/context/ReactFlowDataContext";
import {
ResizableHandle,
ResizablePanel,
ResizablePanelGroup,
} from "@/components/ui/Resizable";
import { GlobalDialogs } from "@/components/GlobalDialogs";
import Dock from "@/components/Dock";
import { useWidgetStore } from "@/store/widget";
import { EWidgetDisplayType } from "@/types/widgets";

const App: React.FC = () => {
const [graphs, setGraphs] = useState<IGraph[]>([]);
const [showGraphSelection, setShowGraphSelection] = useState<boolean>(false);
const [nodes, setNodes] = useState<CustomNodeType[]>([]);
const [edges, setEdges] = useState<CustomEdgeType[]>([]);
const [resizablePanelMode, setResizablePanelMode] = useState<
"left" | "bottom" | "right"
>("bottom");

// Get the version of tman.
const { version } = useVersion();
const { t } = useTranslation();
const { widgets } = useWidgetStore();

const dockWidgetsMemo = React.useMemo(
() =>
widgets.filter(
(widget) => widget.display_type === EWidgetDisplayType.Dock
),
[widgets]
);

const handleOpenExistingGraph = useCallback(async () => {
try {
Expand Down Expand Up @@ -153,46 +174,83 @@ const App: React.FC = () => {

return (
<ThemeProvider defaultTheme="dark" storageKey="vite-ui-theme">
<ReactFlowDataContext.Provider value={{ nodes, edges }}>
<AppBar
version={version}
onAutoLayout={performAutoLayout}
onOpenExistingGraph={handleOpenExistingGraph}
onSetBaseDir={handleSetBaseDir}
/>
<FlowCanvas
nodes={nodes}
edges={edges}
onNodesChange={handleNodesChange}
onEdgesChange={handleEdgesChange}
onConnect={(connection) => {
setEdges((eds) => addEdge(connection, eds));
}}
/>
{showGraphSelection && (
<Popup
title={t("popup.selectGraph.title")}
onClose={() => setShowGraphSelection(false)}
resizable={false}
initialWidth={400}
initialHeight={300}
onCollapseToggle={() => {}}
>
<ul>
{graphs.map((graph) => (
<li
key={graph.name}
style={{ cursor: "pointer", padding: "5px 0" }}
onClick={() => handleSelectGraph(graph.name)}
>
{graph.name}{" "}
{graph.auto_start ? `(${t("action.autoStart")})` : ""}
</li>
))}
</ul>
</Popup>
)}
</ReactFlowDataContext.Provider>
<ResizablePanelGroup
direction={resizablePanelMode === "bottom" ? "vertical" : "horizontal"}
className="w-screen h-screen min-h-screen min-w-screen"
>
<ReactFlowDataContext.Provider value={{ nodes, edges }}>
{resizablePanelMode === "left" && dockWidgetsMemo.length > 0 && (
<>
<ResizablePanel defaultSize={40}>
<Dock
position={resizablePanelMode}
onPositionChange={
setResizablePanelMode as (position: string) => void
}
/>
</ResizablePanel>
<ResizableHandle />
</>
)}
<ResizablePanel defaultSize={60}>
<AppBar
version={version}
onAutoLayout={performAutoLayout}
onOpenExistingGraph={handleOpenExistingGraph}
onSetBaseDir={handleSetBaseDir}
/>
<FlowCanvas
nodes={nodes}
edges={edges}
onNodesChange={handleNodesChange}
onEdgesChange={handleEdgesChange}
onConnect={(connection) => {
setEdges((eds) => addEdge(connection, eds));
}}
className="w-full h-[calc(100%-40px)]"
/>
</ResizablePanel>
{resizablePanelMode !== "left" && dockWidgetsMemo.length > 0 && (
<>
<ResizableHandle />
<ResizablePanel defaultSize={40}>
<Dock
position={resizablePanelMode}
onPositionChange={
setResizablePanelMode as (position: string) => void
}
/>
</ResizablePanel>
</>
)}
{showGraphSelection && (
<Popup
title={t("popup.selectGraph.title")}
onClose={() => setShowGraphSelection(false)}
resizable={false}
initialWidth={400}
initialHeight={300}
onCollapseToggle={() => {}}
>
<ul>
{graphs.map((graph) => (
<li
key={graph.name}
style={{ cursor: "pointer", padding: "5px 0" }}
onClick={() => handleSelectGraph(graph.name)}
>
{graph.name}{" "}
{graph.auto_start ? `(${t("action.autoStart")})` : ""}
</li>
))}
</ul>
</Popup>
)}

{/* Global dialogs. */}
<GlobalDialogs />
</ReactFlowDataContext.Provider>
</ResizablePanelGroup>
</ThemeProvider>
);
};
Expand Down
Loading

0 comments on commit 66c3778

Please sign in to comment.