diff --git a/web/components/interface/navigation/nav-side-menu.tsx b/web/components/interface/navigation/nav-side-menu.tsx
index 8872183..213c139 100644
--- a/web/components/interface/navigation/nav-side-menu.tsx
+++ b/web/components/interface/navigation/nav-side-menu.tsx
@@ -113,6 +113,11 @@ function PanelContent({
useState(false);
const tabItems: TabItem[] = [
+ {
+ name: "Projects",
+ description: "List of projects",
+ icon: "folder",
+ },
{
name: "Apps",
description: "List of apps",
@@ -145,27 +150,6 @@ function PanelContent({
);
}
- // Pick project if no project is opened
- else if (!editorContext?.editorStates.project) {
- return (
-
-
View Projects
-
-
-
-
- );
- }
return (
@@ -187,10 +171,27 @@ function PanelContent({
{tabItems[selectedTabIndex]?.name === "Apps" ? (
- ) : (
+ ) : tabItems[selectedTabIndex]?.name === "Workspace" ? (
+ ) : (
+
+
View Projects
+
+
+
)}
+
);
}
diff --git a/web/components/views/canvas/canvas-node-control.tsx b/web/components/views/canvas/canvas-node-control.tsx
deleted file mode 100644
index 4c72217..0000000
--- a/web/components/views/canvas/canvas-node-control.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import Icon from "@/components/misc/icon";
-import { isMobile } from "@/lib/platform-api/platform-checker";
-import { Button } from "@heroui/react";
-import { NodeResizeControl } from "@xyflow/react";
-
-export default function CanvasNodeControl({
- controlActions,
- setIsResizing,
- isShowingWorkflowConnector,
- setIsShowingWorkflowConnector,
-}: {
- controlActions: Record void) | undefined>;
- setIsResizing: (resizing: boolean) => void;
- isShowingWorkflowConnector: boolean;
- setIsShowingWorkflowConnector: (showing: boolean) => void;
-}) {
- return (
- <>
-
-
-
-
-
-
- {/* Popover is interfering with the drag area... */}
-
setIsResizing(true)}
- onResizeEnd={isMobile() ? undefined : () => setIsResizing(false)}
- autoScale={false}
- >
-
-
-
-
-
-
- >
- );
-}
diff --git a/web/components/views/canvas/canvas-node-view-layout.tsx b/web/components/views/canvas/canvas-node-view-layout.tsx
deleted file mode 100644
index 8f08c1d..0000000
--- a/web/components/views/canvas/canvas-node-view-layout.tsx
+++ /dev/null
@@ -1,98 +0,0 @@
-import { isMobile } from "@/lib/platform-api/platform-checker";
-import { Popover, PopoverContent, PopoverTrigger } from "@heroui/react";
-import { NodeResizer } from "@xyflow/react";
-import { useState } from "react";
-import CanvasNodeControl from "./canvas-node-control";
-
-export default function CanvasNodeViewLayout({
- height = "100%",
- width = "100%",
- children,
- controlActions = {},
-}: {
- height?: string;
- width?: string;
- children: React.ReactNode;
- controlActions?: Record void) | undefined>;
-}) {
- const [isShowingMenu, setIsShowingMenu] = useState(false);
- const [isResizing, setIsResizing] = useState(false);
- const [isShowingWorkflowConnector, setIsShowingWorkflowConnector] =
- useState(false);
-
- return (
-
-
-
{
- e.preventDefault();
- setIsShowingMenu((prev) => !prev);
- }}
- >
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- {isShowingWorkflowConnector && (
- <>
- {/* Input Area */}
-
-
- {/* Output Area */}
-
- >
- )}
-
-
setIsResizing(true)}
- onResizeEnd={isMobile() ? undefined : () => setIsResizing(false)}
- lineStyle={{
- borderColor: "transparent",
- borderWidth: 6,
- }}
- handleStyle={{
- background: "transparent",
- borderColor: "transparent",
- width: 12,
- height: 12,
- zIndex: 40,
- }}
- />
-
-
- {
- // Add a temporary div overlay to prevent interaction while resizing
- isResizing && (
-
- )
- }
- {children}
-
-
- );
-}
diff --git a/web/components/views/canvas/canvas-view.tsx b/web/components/views/canvas/canvas-view.tsx
index 046e326..92720a0 100644
--- a/web/components/views/canvas/canvas-view.tsx
+++ b/web/components/views/canvas/canvas-view.tsx
@@ -6,35 +6,23 @@ import {
addEdge,
applyEdgeChanges,
applyNodeChanges,
+ Background,
+ BackgroundVariant,
+ Connection,
EdgeChange,
NodeChange,
ReactFlow,
Edge as ReactFlowEdge,
Node as ReactFlowNode,
+ reconnectEdge,
useReactFlow,
useViewport,
} from "@xyflow/react";
import "@xyflow/react/dist/style.css";
import { useCallback, useEffect, useRef, useState } from "react";
import Icon from "../../misc/icon";
-import AppNode from "./nodes/app-node";
-
-// const initialNodes = [
-// {
-// id: "n1",
-// position: { x: 200, y: 0 },
-// data: {
-// label: "Node 1",
-// config: {
-// viewId: v4(),
-// app: "https://cdn.pulse-editor.com/extension/spin_wheel/0.0.1/",
-// },
-// },
-// type: "appNode",
-// },
-// { id: "n2", position: { x: 0, y: 100 }, data: { label: "Node 2" } },
-// ];
-// const initialEdges = [{ id: "n1-n2", source: "n1", target: "n2" }];
+import AppNode from "./nodes/app-node/app-node";
+import "./theme.css";
const appInfo: AppInfoModalContent = {
name: "Pulse Editor",
@@ -71,8 +59,10 @@ export default function CanvasView({ config }: { config?: CanvasViewConfig }) {
setNodes((nodesSnapshot) => applyNodeChanges(changes, nodesSnapshot));
}, []);
const onEdgesChange = useCallback(
- (changes: EdgeChange<{ id: string; source: string; target: string }>[]) =>
- setEdges((edgesSnapshot) => applyEdgeChanges(changes, edgesSnapshot)),
+ (changes: EdgeChange<{ id: string; source: string; target: string }>[]) => {
+ console.log("Edge changes:", changes);
+ setEdges((edgesSnapshot) => applyEdgeChanges(changes, edgesSnapshot));
+ },
[],
);
const onConnect = useCallback(
@@ -80,7 +70,13 @@ export default function CanvasView({ config }: { config?: CanvasViewConfig }) {
setEdges((edgesSnapshot) => addEdge(params, edgesSnapshot)),
[],
);
+ const onReconnect = useCallback(
+ (oldEdge: ReactFlowEdge, newConnection: Connection) =>
+ setEdges((els) => reconnectEdge(oldEdge, newConnection, els)),
+ [],
+ );
+ /* Node creator functions */
const createAppNode = useCallback((props: any) => {
return ;
}, []);
@@ -221,7 +217,7 @@ export default function CanvasView({ config }: { config?: CanvasViewConfig }) {
return (
+ deleteKeyCode={["Delete", "Backspace"]}
+ onReconnect={onReconnect}
+ defaultEdgeOptions={{
+ markerEnd: {
+ type: "arrowclosed",
+ width: 20,
+ height: 20,
+ },
+ }}
+ >
+
+
);
}
+
+function AppControl() {
+ return <>>;
+}
diff --git a/web/components/views/standalone-app/standalone-app-view.tsx b/web/components/views/standalone-app/standalone-app-view.tsx
index 0cd8c8d..df72adf 100644
--- a/web/components/views/standalone-app/standalone-app-view.tsx
+++ b/web/components/views/standalone-app/standalone-app-view.tsx
@@ -1,6 +1,6 @@
import { AppViewConfig } from "@/lib/types";
import BaseAppView from "../base/base-app-view";
-import AppViewLayout from "./app-view-layout";
+import AppViewLayout from "./layout";
export default function StandaloneAppView({
config,
diff --git a/web/components/views/view-area.tsx b/web/components/views/view-area.tsx
index 39d9013..7e24fa9 100644
--- a/web/components/views/view-area.tsx
+++ b/web/components/views/view-area.tsx
@@ -157,40 +157,47 @@ export default function ViewArea() {
No view selected
) : (
{isShowTabs && (
-
-
{
- const index = tabItems.findIndex(
- (tab) => tab.name === item?.name,
- );
- selectTab(index !== -1 ? index : 0);
- }}
- isShowPagination={true}
- onTabClose={(item) => {
- const index = tabItems.findIndex(
- (tab) => tab.name === item?.name,
- );
- if (index !== -1) {
- closeTabView(tabViews[index]);
+
+
+
+ setSelectedItem={(item) => {
+ const index = tabItems.findIndex(
+ (tab) => tab.name === item?.name,
+ );
+ selectTab(index !== -1 ? index : 0);
+ }}
+ isShowPagination={true}
+ onTabClose={(item) => {
+ const index = tabItems.findIndex(
+ (tab) => tab.name === item?.name,
+ );
+ if (index !== -1) {
+ closeTabView(tabViews[index]);
+ }
+ }}
+ />
+
)}
-
+
{tabViews.map((tabView, idx) => (
{tabView.type === ViewModeEnum.App ? (