diff --git a/ui/src/components/Canvas.tsx b/ui/src/components/Canvas.tsx index 8996ad44..b5e1d1d7 100644 --- a/ui/src/components/Canvas.tsx +++ b/ui/src/components/Canvas.tsx @@ -72,6 +72,7 @@ const ScopeNode = memo(({ data, id, isConnectable }) => { const ref = useRef(null); const store = useContext(RepoContext); if (!store) throw new Error("Missing BearContext.Provider in the tree"); + const flow = useReactFlow(); const getPod = useStore(store, (state) => state.getPod); const pod = getPod(id); const setPodName = useStore(store, (state) => state.setPodName); @@ -84,6 +85,19 @@ const ScopeNode = memo(({ data, id, isConnectable }) => { const selected = useStore(store, (state) => state.pods[id]?.selected); const role = useStore(store, (state) => state.role); + const deleteNodeById = useCallback( + (id: string) => { + flow.deleteElements({ + nodes: [ + { + id, + }, + ], + }); + }, + [flow] + ); + const onResize = useCallback(({ width, height, offx, offy }) => { const node = nodesMap.get(id); if (node) { @@ -97,6 +111,7 @@ const ScopeNode = memo(({ data, id, isConnectable }) => { React.useEffect(() => { setTarget(ref.current); }, []); + return ( (({ data, id, isConnectable }) => { }} className="custom-drag-handle" > + + {role !== RoleType.GUEST && ( + + { + e.stopPropagation(); + e.preventDefault(); + deleteNodeById(id); + }} + > + + + + )} + (({ data, id, isConnectable }) => { renderDirections={["e", "s", "se"]} edge={false} zoom={1} - origin={true} + origin={false} padding={{ left: 0, top: 0, right: 0, bottom: 0 }} onResizeStart={(e) => { e.setOrigin(["%", "%"]); @@ -580,11 +624,11 @@ const CodeNode = memo(({ data, id, isConnectable }) => { const nodeTypes = { scope: ScopeNode, code: CodeNode }; const level2color = { - 0: "rgba(255, 0, 0, 0.2)", - 1: "rgba(255, 0, 255, 0.2)", - 2: "rgba(0, 255, 255, 0.2)", - 3: "rgba(0, 255, 0, 0.2)", - 4: "rgba(255, 255, 0, 0.2)", + 0: "rgba(187, 222, 251, 0.5)", + 1: "rgba(144, 202, 249, 0.5)", + 2: "rgba(100, 181, 246, 0.5)", + 3: "rgba(66, 165, 245, 0.5)", + 4: "rgba(33, 150, 243, 0.5)", // default: "rgba(255, 255, 255, 0.2)", default: "rgba(240,240,240,0.25)", }; @@ -993,16 +1037,16 @@ export function Canvas() { { - if (n.style?.background) return n.style.background as string; - if (n.type === "code") return "#0041d0"; - if (n.type === "scope") return "#ff0072"; + if (n.style?.borderColor) return n.style.borderColor; + if (n.type === "code") return "#d6dee6"; + if (n.type === "scope") return "#f4f6f8"; - return "#1a192b"; + return "#d6dee6"; }} nodeColor={(n) => { if (n.style?.backgroundColor) return n.style.backgroundColor; - return "#1a192b"; + return "#f4f6f8"; }} nodeBorderRadius={2} /> diff --git a/ui/src/lib/store.tsx b/ui/src/lib/store.tsx index 72f21c2a..2308beb1 100644 --- a/ui/src/lib/store.tsx +++ b/ui/src/lib/store.tsx @@ -167,9 +167,9 @@ export interface RepoSlice { { parent, index, anchor, shift, id, type, lang, x, y, width, height }: any ) => void; deletePod: ( - client, - { id, toDelete }: { id: string; toDelete: any[] } - ) => void; + client: ApolloClient | null, + { id, toDelete }: { id: string; toDelete: string[] } + ) => Promise; setPodResult: ({ id, content, @@ -325,13 +325,15 @@ const createRepoSlice: StateCreator< } }, deletePod: async ( - client, + client: ApolloClient | null, { id, toDelete }: { id: string; toDelete: string[] } ) => { const pods = get().pods; + // get all ids to delete. Gathering them here is easier than on the server - // TOFIX: check pods[id] exists before deleting + if (!pods[id]) return; + const dfs = (id) => { const pod = pods[id]; if (pod) { @@ -705,8 +707,13 @@ const createRepoSlice: StateCreator< ); }, loadRepo: async (client, id) => { - const { pods, name, error, userId, collaboratorIds } = - await doRemoteLoadRepo({ id, client }); + const { + pods, + name, + error, + userId, + collaboratorIds, + } = await doRemoteLoadRepo({ id, client }); set( produce((state) => { // TODO the children ordered by index