Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

remove state.pods; fix runtime & results #451

Merged
merged 1 commit into from
Aug 14, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 0 additions & 27 deletions ui/src/components/Canvas.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -56,31 +56,6 @@ const edgeTypes = {
floating: FloatingEdge,
};

function useInitNodes() {
const store = useContext(RepoContext)!;
const provider = useStore(store, (state) => state.provider);
const [loading, setLoading] = useState(true);
const updateView = useStore(store, (state) => state.updateView);
const adjustLevel = useStore(store, (state) => state.adjustLevel);
useEffect(() => {
const init = () => {
// adjust level and update view
adjustLevel();
updateView();
setLoading(false);
};

if (!provider) return;
if (provider.synced) {
init();
} else {
provider.once("synced", init);
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [provider]);
return { loading };
}

function getBestNode(
nodes: Node[],
from,
Expand Down Expand Up @@ -860,8 +835,6 @@ function CanvasImpl() {
}

export function Canvas() {
const { loading } = useInitNodes();
if (loading) return <div>Loading...</div>;
return (
<ReactFlowProvider>
<CanvasImplWrap />
Expand Down
10 changes: 4 additions & 6 deletions ui/src/components/MyMonaco.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -396,12 +396,13 @@ export const MyMonaco = memo<MyMonacoProps>(function MyMonaco({
const showLineNumbers = useStore(store, (state) => state.showLineNumbers);
const clearResults = useStore(store, (s) => s.clearResults);
const wsRun = useStore(store, (state) => state.wsRun);
const setPodFocus = useStore(store, (state) => state.setPodFocus);
const focusedEditor = useStore(store, (state) => state.focusedEditor);
const setFocusedEditor = useStore(store, (state) => state.setFocusedEditor);
const setPodBlur = useStore(store, (state) => state.setPodBlur);
const setCursorNode = useStore(store, (state) => state.setCursorNode);
const annotations = useStore(store, (state) => state.pods[id]?.annotations);
const annotations = useStore(
store,
(state) => state.parseResult[id]?.annotations
);
const showAnnotations = useStore(store, (state) => state.showAnnotations);
const scopedVars = useStore(store, (state) => state.scopedVars);
const updateView = useStore(store, (state) => state.updateView);
Expand Down Expand Up @@ -470,11 +471,9 @@ export const MyMonaco = memo<MyMonacoProps>(function MyMonaco({
// onLayout(`${contentHeight}px`);
};
editor.onDidBlurEditorText(() => {
setPodBlur(id);
setFocusedEditor(undefined);
});
editor.onDidFocusEditorText(() => {
setPodFocus(id);
if (resetSelection()) updateView();
});
editor.onDidContentSizeChange(updateHeight);
Expand All @@ -497,7 +496,6 @@ export const MyMonaco = memo<MyMonacoProps>(function MyMonaco({
run: () => {
if (document.activeElement) {
(document.activeElement as any).blur();
setPodBlur(id);
setCursorNode(id);
setFocusedEditor(undefined);
selectPod(id, true);
Expand Down
58 changes: 35 additions & 23 deletions ui/src/components/Sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ import HelpOutlineOutlinedIcon from "@mui/icons-material/HelpOutlineOutlined";
import Typography from "@mui/material/Typography";
import { useSnackbar, VariantType } from "notistack";

import { Node as ReactflowNode } from "reactflow";

import { gql, useQuery, useMutation, useApolloClient } from "@apollo/client";
import { useStore } from "zustand";
import { MyKBar } from "./MyKBar";
Expand Down Expand Up @@ -876,7 +878,10 @@ function ExportJupyterNB() {
const store = useContext(RepoContext);
if (!store) throw new Error("Missing BearContext.Provider in the tree");
const repoName = useStore(store, (state) => state.repoName);
const pods = useStore(store, (state) => state.pods);
const nodesMap = useStore(store, (state) => state.getNodesMap());
const nodes = Array.from<ReactflowNode>(nodesMap.values());
const podResults = useStore(store, (state) => state.podResults);
const codeMap = useStore(store, (state) => state.getCodeMap());
Comment on lines +883 to +884
Copy link
Collaborator

@senwang86 senwang86 Aug 14, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the podResults not synced with YJS by design? @lihebi

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be saved to Yjs. It's on my TODO list.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should be saved to Yjs. It's on my TODO list.

Is there any concern to append podResults to codeMap?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's an option; I'm thinking about it.

const filename = `${
repoName || "Untitled"
}-${new Date().toISOString()}.ipynb`;
Expand All @@ -895,44 +900,50 @@ function ExportJupyterNB() {
}[] = [];

// Queue to sort the pods geographically
let q = new Array();
let q = new Array<[ReactflowNode, string]>();
// adjacency list for podId -> parentId mapping
let adj = {};
q.push([pods["ROOT"], "0.0"]);
// get the top-level nodes
let toplevels = nodes.filter((x) => !x.parentNode);
toplevels.forEach((n) => {
q.push([n, "0.0"]);
});

while (q.length > 0) {
let [curPod, curScore] = q.shift();
let [curPod, curScore] = q.shift()!;

// sort the pods geographically(top-down, left-right)
let sortedChildren = curPod.children
const children = nodes.filter((n) => n.parentNode === curPod.id);
let sortedChildren = children
.map((x) => x.id)
.sort((id1, id2) => {
let pod1 = pods[id1];
let pod2 = pods[id2];
if (pod1 && pod2) {
if (pod1.y === pod2.y) {
return pod1.x - pod2.x;
let node1 = nodesMap.get(id1);
let node2 = nodesMap.get(id2);
if (node1 && node2) {
if (node1.position.y === node2.position.y) {
return node1.position.x - node2.position.x;
} else {
return pod1.y - pod2.y;
return node1.position.y - node2.position.y;
}
} else {
return 0;
}
});

for (let i = 0; i < sortedChildren.length; i++) {
let pod = pods[sortedChildren[i]];
const pod = nodesMap.get(sortedChildren[i])!;
let geoScore = curScore + `${i + 1}`;
adj[pod.id] = {
name: pod.name,
parentId: pod.parent,
name: pod.data.name,
parentId: pod.parentNode,
geoScore: geoScore,
};

if (pod.type == "SCOPE") {
q.push([pod, geoScore.substring(0, 2) + "0" + geoScore.substring(2)]);
} else if (pod.type == "CODE") {
let podOutput: any[] = [];
for (const result of pod.result!) {
for (const result of podResults[pod.id].result!) {
switch (result.type) {
case "execute_result":
podOutput.push({
Expand All @@ -942,7 +953,7 @@ function ExportJupyterNB() {
.split(/\r?\n/)
.map((line) => line + "\n") || [""],
},
execution_count: pod.exec_count,
execution_count: podResults[pod.id].exec_count,
});
break;
case "display_data":
Expand Down Expand Up @@ -978,28 +989,29 @@ function ExportJupyterNB() {
break;
}
}
if (pod.error) {
const error = podResults[pod.id].error;
if (error) {
podOutput.push({
output_type: "error",
ename: pod.error?.ename,
evalue: pod.error?.evalue,
traceback: pod.error?.stacktrace,
ename: error.ename,
evalue: error.evalue,
traceback: error.stacktrace,
});
}
jupyterCellList.push({
cell_type: "code",
execution_count: pod.exec_count,
execution_count: podResults[pod.id].exec_count,
// TODO: expand other Codepod related-metadata fields, or run a real-time search in database when importing.
metadata: { id: pod.id, geoScore: Number(geoScore) },
source: [pod.content || ""],
source: [codeMap.get(pod.id)?.toString() || ""],
outputs: podOutput,
});
} else if (pod.type == "RICH") {
jupyterCellList.push({
cell_type: "markdown",
// TODO: expand other Codepod related-metadata fields, or run a real-time search in database when importing.
metadata: { id: pod.id, geoScore: Number(geoScore) },
source: [pod.richContent || ""],
source: ["TODO"], // [pod.richContent || ""],
});
}
}
Expand Down
31 changes: 18 additions & 13 deletions ui/src/components/nodes/Code.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -85,11 +85,17 @@ function Timer({ lastExecutedAt }) {

export const ResultBlock = memo<any>(function ResultBlock({ id, layout }) {
const store = useContext(RepoContext)!;
const results = useStore(store, (state) => state.pods[id]?.result);
const error = useStore(store, (state) => state.pods[id]?.error);
const stdout = useStore(store, (state) => state.pods[id]?.stdout);
const running = useStore(store, (state) => state.pods[id]?.running || false);
const exec_count = useStore(store, (state) => state.pods[id]?.exec_count);
const results = useStore(store, (state) => state.podResults[id]?.result);
const error = useStore(store, (state) => state.podResults[id]?.error);
const stdout = useStore(store, (state) => state.podResults[id]?.stdout);
const running = useStore(
store,
(state) => state.podResults[id]?.running || false
);
const exec_count = useStore(
store,
(state) => state.podResults[id]?.exec_count
);
const autoLayoutROOT = useStore(store, (state) => state.autoLayoutROOT);
const autoRunLayout = useStore(store, (state) => state.autoRunLayout);

Expand All @@ -105,17 +111,17 @@ export const ResultBlock = memo<any>(function ResultBlock({ id, layout }) {

const lastExecutedAt = useStore(
store,
(state) => state.pods[id]?.lastExecutedAt
(state) => state.podResults[id]?.lastExecutedAt
);
const [showOutput, setShowOutput] = useState(true);
const hasResult = useStore(
store,
(state) =>
state.pods[id]?.running ||
state.pods[id]?.result ||
state.pods[id]?.error ||
state.pods[id]?.stdout ||
state.pods[id]?.stderr
state.podResults[id]?.running ||
state.podResults[id]?.result ||
state.podResults[id]?.error ||
state.podResults[id]?.stdout ||
state.podResults[id]?.stderr
);
const [resultScroll, setResultScroll] = useState(false);
const [showMenu, setShowMenu] = useState(false);
Expand Down Expand Up @@ -574,12 +580,11 @@ export const CodeNode = memo<NodeProps>(function ({
const cursorNode = useStore(store, (state) => state.cursorNode);
const focusedEditor = useStore(store, (state) => state.focusedEditor);
const setFocusedEditor = useStore(store, (state) => state.setFocusedEditor);
const isPodFocused = useStore(store, (state) => state.pods[id]?.focus);
const inputRef = useRef<HTMLInputElement>(null);
const updateView = useStore(store, (state) => state.updateView);
const exec_count = useStore(
store,
(state) => state.pods[id]?.exec_count || " "
(state) => state.podResults[id]?.exec_count || " "
);
const isCutting = useStore(store, (state) => state.cuttingIds.has(id));

Expand Down
6 changes: 0 additions & 6 deletions ui/src/components/nodes/Rich.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -257,13 +257,11 @@ function HotkeyControl({ id }) {
const store = useContext(RepoContext);
if (!store) throw new Error("Missing BearContext.Provider in the tree");
const setCursorNode = useStore(store, (state) => state.setCursorNode);
const setPodBlur = useStore(store, (state) => state.setPodBlur);
const focusedEditor = useStore(store, (state) => state.focusedEditor);
const setFocusedEditor = useStore(store, (state) => state.setFocusedEditor);
const selectPod = useStore(store, (state) => state.selectPod);

useKeymap("Escape", () => {
setPodBlur(id);
setCursorNode(id);
setFocusedEditor(undefined);
selectPod(id, true);
Expand Down Expand Up @@ -292,11 +290,9 @@ const MyEditor = ({
const store = useContext(RepoContext);
if (!store) throw new Error("Missing BearContext.Provider in the tree");
const isGuest = useStore(store, (state) => state.role === "GUEST");
const setPodFocus = useStore(store, (state) => state.setPodFocus);
// the Yjs extension for Remirror
const provider = useStore(store, (state) => state.provider)!;

const setPodBlur = useStore(store, (state) => state.setPodBlur);
const focusedEditor = useStore(store, (state) => state.focusedEditor);
const setFocusedEditor = useStore(store, (state) => state.setFocusedEditor);
const resetSelection = useStore(store, (state) => state.resetSelection);
Expand Down Expand Up @@ -402,12 +398,10 @@ const MyEditor = ({
<Box
className="remirror-theme"
onFocus={() => {
setPodFocus(id);
setFocusedEditor(id);
if (resetSelection()) updateView();
}}
onBlur={() => {
setPodBlur(id);
setFocusedEditor(undefined);
}}
sx={{
Expand Down
2 changes: 2 additions & 0 deletions ui/src/lib/nodes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ export function useYjsObserver() {
updateView();
};

// FIXME need to observe edgesMap as well
// FIXME need to observe resultMap as well
nodesMap.observe(observer);

return () => {
Expand Down
24 changes: 4 additions & 20 deletions ui/src/lib/store/canvasSlice.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -652,8 +652,8 @@ export const createCanvasSlice: StateCreator<MyState, [], [], CanvasSlice> = (

// clear the temporary nodes and the pasting/cutting state
set(
produce((state) => {
state.pastingNode = undefined;
produce((state: MyState) => {
state.pastingNodes = undefined;
state.headPastingNodes = new Set();
state.pastingNodes = [];
state.mousePos = undefined;
Expand All @@ -663,19 +663,6 @@ export const createCanvasSlice: StateCreator<MyState, [], [], CanvasSlice> = (
);

pastingNodes.forEach((node) => {
set(
produce((state) => {
let pod = state.pods[node!.id];
if (leadingNodes?.has(node.id)) {
pod.x = position.x;
pod.y = position.y;
}
pod.dirty = true;
// this flag triggers the addPods call when updating all dirty pods
pod.pending = true;
})
);

// insert all nodes to the yjs map
nodesMap.set(node.id, {
...(leadingNodes?.has(node.id) ? { ...node, position } : node),
Expand Down Expand Up @@ -703,15 +690,12 @@ export const createCanvasSlice: StateCreator<MyState, [], [], CanvasSlice> = (
cancelPaste: (cutting = false) => {
const pastingNodes = get().pastingNodes || [];
set(
produce((state) => {
produce((state: MyState) => {
// Remove pastingNode from store.
state.pastingNodes = [];
state.headPastingNodes = new Set();
pastingNodes.forEach((node) => {
delete state.pods[node!.id];
});
// Clear pasting data and update view.
state.pastingNode = undefined;
state.pastingNodes = undefined;
state.mousePos = undefined;
if (cutting) state.isCutting = false;
else state.isPasting = false;
Expand Down
Loading