Skip to content

Commit 724ea5a

Browse files
authored
refactor: node type CODE, SCOPE, RICH in front-end (#241)
1 parent b103fe2 commit 724ea5a

File tree

7 files changed

+57
-70
lines changed

7 files changed

+57
-70
lines changed

ui/src/components/Canvas.tsx

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ import { lowercase, numbers } from "nanoid-dictionary";
3333
import { useStore } from "zustand";
3434

3535
import { RepoContext } from "../lib/store";
36-
import { dbtype2nodetype, nodetype2dbtype } from "../lib/utils";
3736
import { useEdgesYjsObserver, useYjsObserver } from "../lib/nodes";
3837

3938
import { useApolloClient } from "@apollo/client";
@@ -46,7 +45,7 @@ import { YMap } from "yjs/dist/src/types/YMap";
4645
import FloatingEdge from "./nodes/FloatingEdge";
4746
import CustomConnectionLine from "./nodes/CustomConnectionLine";
4847

49-
const nodeTypes = { scope: ScopeNode, code: CodeNode, rich: RichNode };
48+
const nodeTypes = { SCOPE: ScopeNode, CODE: CodeNode, RICH: RichNode };
5049
const edgeTypes = {
5150
floating: FloatingEdge,
5251
};
@@ -62,7 +61,7 @@ function store2nodes(id: string, { getId2children, getPod }) {
6261
if (id !== "ROOT") {
6362
res.push({
6463
id: id,
65-
type: dbtype2nodetype(pod.type),
64+
type: pod.type,
6665
data: {
6766
// label: `ID: ${id}, parent: ${pods[id].parent}, pos: ${pods[id].x}, ${pods[id].y}`,
6867
label: id,
@@ -535,7 +534,7 @@ function CanvasImpl() {
535534
};
536535

537536
const onNodeContextMenu = (event, node) => {
538-
if (node?.type !== "scope") return;
537+
if (node?.type !== "SCOPE") return;
539538

540539
event.preventDefault();
541540
setShowContextMenu(true);
@@ -651,8 +650,8 @@ function CanvasImpl() {
651650
<MiniMap
652651
nodeStrokeColor={(n) => {
653652
if (n.style?.borderColor) return n.style.borderColor;
654-
if (n.type === "code") return "#d6dee6";
655-
if (n.type === "scope") return "#f4f6f8";
653+
if (n.type === "CODE") return "#d6dee6";
654+
if (n.type === "SCOPE") return "#f4f6f8";
656655

657656
return "#d6dee6";
658657
}}
@@ -673,17 +672,17 @@ function CanvasImpl() {
673672
x={points.x}
674673
y={points.y}
675674
addCode={() =>
676-
addNode("code", project({ x: client.x, y: client.y }), parentNode)
675+
addNode("CODE", project({ x: client.x, y: client.y }), parentNode)
677676
}
678677
addScope={() =>
679678
addNode(
680-
"scope",
679+
"SCOPE",
681680
project({ x: client.x, y: client.y }),
682681
parentNode
683682
)
684683
}
685684
addRich={() =>
686-
addNode("rich", project({ x: client.x, y: client.y }), parentNode)
685+
addNode("RICH", project({ x: client.x, y: client.y }), parentNode)
687686
}
688687
onShareClick={() => {
689688
setShareOpen(true);

ui/src/lib/fetch.tsx

Lines changed: 36 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,37 @@ export async function doRemoteLoadRepo(client: ApolloClient<any>, id: string) {
9898
}
9999
}
100100

101+
/**
102+
* For historical reason, the backend DB schema pod.type are "CODE", "DECK",
103+
* "WYSIWYG", while the node types in front-end are "CODE", "SCOPE", "RICH".
104+
*/
105+
106+
function dbtype2nodetype(dbtype: string) {
107+
switch (dbtype) {
108+
case "CODE":
109+
return "CODE";
110+
case "DECK":
111+
return "SCOPE";
112+
case "WYSIWYG":
113+
return "RICH";
114+
default:
115+
throw new Error(`unknown dbtype ${dbtype}`);
116+
}
117+
}
118+
119+
function nodetype2dbtype(nodetype: string) {
120+
switch (nodetype) {
121+
case "CODE":
122+
return "CODE";
123+
case "SCOPE":
124+
return "DECK";
125+
case "RICH":
126+
return "WYSIWYG";
127+
default:
128+
throw new Error(`unknown nodetype ${nodetype}`);
129+
}
130+
}
131+
101132
export function normalize(pods) {
102133
const res: { [key: string]: Pod } = {
103134
ROOT: {
@@ -108,7 +139,7 @@ export function normalize(pods) {
108139
// Adding this to avoid errors
109140
// XXX should I save these to db?
110141
lang: "python",
111-
type: "DECK",
142+
type: "SCOPE",
112143
content: "",
113144
x: 0,
114145
y: 0,
@@ -141,29 +172,20 @@ export function normalize(pods) {
141172
type: res[id].type,
142173
}))
143174
: [];
144-
// change children.id format
145-
// UDPATE Or, I just put {id,type} in the children array
146-
//
147-
// pod.children = pod.children.map(({ id }) => id);
148-
//
149-
// sort according to index
150-
// pod.children.sort((a, b) => res[a.id].index - res[b.id].index);
151-
// if (pod.type === "WYSIWYG" || pod.type === "CODE") {
152-
// pod.content = JSON.parse(pod.content);
153-
// }
154175
pod.content = JSON.parse(pod.content);
155176
pod.staged = JSON.parse(pod.staged);
156177
pod.githead = JSON.parse(pod.githead);
178+
pod.type = dbtype2nodetype(pod.type);
157179
if (pod.result) {
158180
pod.result = JSON.parse(pod.result);
159181
}
160182
if (pod.error) {
161183
pod.error = JSON.parse(pod.error);
162184
}
163185
// DEBUG the deck's content seems to be a long string of escaped \
164-
if (pod.type === "DECK" && pod.content) {
186+
if (pod.type === "SCOPE" && pod.content) {
165187
console.log(
166-
`warning: deck ${pod.id} content is not null, setting to null:`,
188+
`warning: SCOPE ${pod.id} content is not null, setting to null:`,
167189
pod.content
168190
);
169191
pod.content = null;
@@ -195,7 +217,7 @@ function serializePodInput(pod) {
195217
height,
196218
}) => ({
197219
id,
198-
type,
220+
type: nodetype2dbtype(type),
199221
column,
200222
lang,
201223
// stdout,

ui/src/lib/nodes.tsx

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { useCallback, useEffect, useState, useContext } from "react";
22
import { applyNodeChanges, Edge, Node } from "reactflow";
33
import { RepoContext } from "./store";
4-
import { nodetype2dbtype } from "./utils";
54
import { useStore } from "zustand";
65
import { useApolloClient } from "@apollo/client";
76
import { Transaction, YEvent } from "yjs";
@@ -30,7 +29,7 @@ export function useYjsObserver() {
3029
id: node.id,
3130
children: [],
3231
parent: "ROOT",
33-
type: nodetype2dbtype(node.type || ""),
32+
type: node.type as "CODE" | "SCOPE" | "RICH",
3433
lang: "python",
3534
x: node.position.x,
3635
y: node.position.y,

ui/src/lib/store/canvasSlice.tsx

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { Transaction, YEvent } from "yjs";
1515

1616
import { match, P } from "ts-pattern";
1717

18-
import { myNanoId, nodetype2dbtype, dbtype2nodetype } from "../utils";
18+
import { myNanoId } from "../utils";
1919

2020
import {
2121
Connection,
@@ -69,14 +69,14 @@ function createTemporaryNode(pod, position, parent = "ROOT", level = 0): any {
6969
width: pod.width,
7070
};
7171

72-
if (pod.type === "DECK") {
72+
if (pod.type === "SCOPE") {
7373
style["height"] = pod.height!;
7474
style["backgroundColor"] = level2color[level] || level2color["default"];
7575
}
7676

7777
const newNode = {
7878
id,
79-
type: dbtype2nodetype(pod.type),
79+
type: pod.type,
8080
position,
8181
data: {
8282
label: id,
@@ -108,13 +108,13 @@ function createTemporaryNode(pod, position, parent = "ROOT", level = 0): any {
108108
/**
109109
* The new reactflow nodes for context-menu's addXXX items.
110110
*/
111-
function createNewNode(type: "scope" | "code" | "rich", position): Node {
111+
function createNewNode(type: "SCOPE" | "CODE" | "RICH", position): Node {
112112
let id = myNanoId();
113113
const newNode = {
114114
id,
115115
type,
116116
position,
117-
...(type === "scope"
117+
...(type === "SCOPE"
118118
? {
119119
width: 600,
120120
height: 600,
@@ -154,7 +154,7 @@ function getScopeAt(
154154
const scope = nodes.findLast((node) => {
155155
let [x1, y1] = getAbsPos(node, nodesMap);
156156
return (
157-
node.type === "scope" &&
157+
node.type === "SCOPE" &&
158158
x >= x1 &&
159159
!excludes.includes(node.id) &&
160160
x <= x1 + node.width &&
@@ -244,7 +244,7 @@ export interface CanvasSlice {
244244
setPaneBlur: () => void;
245245

246246
addNode: (
247-
type: "code" | "scope" | "rich",
247+
type: "CODE" | "SCOPE" | "RICH",
248248
position: XYPosition,
249249
parent: string
250250
) => void;
@@ -358,7 +358,7 @@ export const createCanvasSlice: StateCreator<MyState, [], [], CanvasSlice> = (
358358
style: {
359359
...node.style,
360360
backgroundColor:
361-
node.type === "scope" ? level2color[node.data.level] : undefined,
361+
node.type === "SCOPE" ? level2color[node.data.level] : undefined,
362362
},
363363
selected: selectedPods.has(node.id),
364364
// className: get().dragHighlight === node.id ? "active" : "",
@@ -392,7 +392,7 @@ export const createCanvasSlice: StateCreator<MyState, [], [], CanvasSlice> = (
392392
id: node.id,
393393
children: [],
394394
parent: "ROOT",
395-
type: nodetype2dbtype(node.type || ""),
395+
type: node.type as "CODE" | "SCOPE" | "RICH",
396396
lang: "python",
397397
x: node.position.x,
398398
y: node.position.y,
@@ -910,7 +910,7 @@ function fitChildren(
910910
node2children,
911911
nodesMap
912912
): null | { x: number; y: number; width: number; height: number } {
913-
if (node.type !== "scope") return null;
913+
if (node.type !== "SCOPE") return null;
914914
// This is a scope node. Get all its children and calculate the x,y,width,height to tightly fit its children.
915915
let children = node2children.get(node.id);
916916
// If no children, nothing is changed.

ui/src/lib/store/index.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ enableMapSet();
1717
export type Pod = {
1818
id: string;
1919
name?: string;
20-
type: string;
20+
type: "CODE" | "SCOPE" | "RICH";
2121
content?: string;
2222
dirty?: boolean;
2323
isSyncing?: boolean;

ui/src/lib/store/runtimeSlice.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,7 @@ export const createRuntimeSlice: StateCreator<MyState, [], [], RuntimeSlice> = (
321321
get().clearResults(id);
322322
get().setRunning(id);
323323
set({ chain: [...get().chain, id] });
324-
} else if (get().pods[id].type === "DECK") {
324+
} else if (get().pods[id].type === "SCOPE") {
325325
// If this pod is a scope, run all pods inside a scope by geographical order.
326326
// get the pods in the scope
327327
let children = get().node2children.get(id);

ui/src/lib/utils.tsx

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -36,37 +36,4 @@ export function getUpTime(startedAt: string) {
3636
return prettyTime;
3737
}
3838

39-
/**
40-
* For historical reason, the state.pod.type and DB schema pod.type are "CODE",
41-
* "DECK", "WYSIWYG", while the node types in react-flow are "code", "scope",
42-
* "rich". These two functions document this and handle the conversion.
43-
* @param dbtype
44-
* @returns
45-
*/
46-
export function dbtype2nodetype(dbtype: string) {
47-
switch (dbtype) {
48-
case "CODE":
49-
return "code";
50-
case "DECK":
51-
return "scope";
52-
case "WYSIWYG":
53-
return "rich";
54-
default:
55-
throw new Error(`unknown dbtype ${dbtype}`);
56-
}
57-
}
58-
59-
export function nodetype2dbtype(nodetype: string) {
60-
switch (nodetype) {
61-
case "code":
62-
return "CODE";
63-
case "scope":
64-
return "DECK";
65-
case "rich":
66-
return "WYSIWYG";
67-
default:
68-
throw new Error(`unknown nodetype ${nodetype}`);
69-
}
70-
}
71-
7239
export const myNanoId = customAlphabet(lowercase + numbers, 20);

0 commit comments

Comments
 (0)