darabos commited on
Commit
32d4546
·
1 Parent(s): 8e40d73

Code editor. (Not saving edits yet.)

Browse files
examples/word2vec.py CHANGED
@@ -2,8 +2,10 @@ from lynxkite.core.ops import op
2
  import staticvectors
3
  import pandas as pd
4
 
 
5
 
6
- @op("LynxKite Graph Analytics", "Word2vec for the top 1000 words", cache=True)
 
7
  def word2vec_1000():
8
  model = staticvectors.StaticVectors("neuml/word2vec-quantized")
9
  with open("wordlist.txt") as f:
@@ -17,6 +19,6 @@ def word2vec_1000():
17
  return df
18
 
19
 
20
- @op("LynxKite Graph Analytics", "Take first N")
21
  def first_n(df: pd.DataFrame, *, n=10):
22
  return df.head(n)
 
2
  import staticvectors
3
  import pandas as pd
4
 
5
+ ENV = "LynxKite Graph Analytics"
6
 
7
+
8
+ @op(ENV, "Word2vec for the top 1000 words", cache=True)
9
  def word2vec_1000():
10
  model = staticvectors.StaticVectors("neuml/word2vec-quantized")
11
  with open("wordlist.txt") as f:
 
19
  return df
20
 
21
 
22
+ @op(ENV, "Take first N")
23
  def first_n(df: pd.DataFrame, *, n=10):
24
  return df.head(n)
lynxkite-app/src/lynxkite_app/main.py CHANGED
@@ -39,6 +39,15 @@ def get_catalog(workspace: str):
39
  return {k: {op.name: op.model_dump() for op in v.values()} for k, v in ops.CATALOGS.items()}
40
 
41
 
 
 
 
 
 
 
 
 
 
42
  class SaveRequest(workspace.BaseConfig):
43
  path: str
44
  ws: workspace.Workspace
 
39
  return {k: {op.name: op.model_dump() for op in v.values()} for k, v in ops.CATALOGS.items()}
40
 
41
 
42
+ @app.get("/api/getCode")
43
+ def get_code(path: str):
44
+ path = data_path / path
45
+ assert path.is_relative_to(data_path)
46
+ with open(path) as f:
47
+ code = f.read()
48
+ return {"code": code}
49
+
50
+
51
  class SaveRequest(workspace.BaseConfig):
52
  path: str
53
  ws: workspace.Workspace
lynxkite-app/web/package-lock.json CHANGED
@@ -10,6 +10,7 @@
10
  "dependencies": {
11
  "@esbuild/linux-x64": "^0.25.0",
12
  "@iconify-json/tabler": "^1.2.10",
 
13
  "@svgr/core": "^8.1.0",
14
  "@svgr/plugin-jsx": "^8.1.0",
15
  "@swc/core": "^1.10.1",
@@ -1105,6 +1106,29 @@
1105
  "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
1106
  "license": "MIT"
1107
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1108
  "node_modules/@nodelib/fs.scandir": {
1109
  "version": "2.1.5",
1110
  "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
@@ -5436,6 +5460,13 @@
5436
  "ufo": "^1.5.4"
5437
  }
5438
  },
 
 
 
 
 
 
 
5439
  "node_modules/ms": {
5440
  "version": "2.1.3",
5441
  "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
@@ -6437,6 +6468,12 @@
6437
  "url": "https://github.com/sponsors/wooorm"
6438
  }
6439
  },
 
 
 
 
 
 
6440
  "node_modules/string_decoder": {
6441
  "version": "1.3.0",
6442
  "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
 
10
  "dependencies": {
11
  "@esbuild/linux-x64": "^0.25.0",
12
  "@iconify-json/tabler": "^1.2.10",
13
+ "@monaco-editor/react": "^4.7.0",
14
  "@svgr/core": "^8.1.0",
15
  "@svgr/plugin-jsx": "^8.1.0",
16
  "@swc/core": "^1.10.1",
 
1106
  "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
1107
  "license": "MIT"
1108
  },
1109
+ "node_modules/@monaco-editor/loader": {
1110
+ "version": "1.5.0",
1111
+ "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.5.0.tgz",
1112
+ "integrity": "sha512-hKoGSM+7aAc7eRTRjpqAZucPmoNOC4UUbknb/VNoTkEIkCPhqV8LfbsgM1webRM7S/z21eHEx9Fkwx8Z/C/+Xw==",
1113
+ "license": "MIT",
1114
+ "dependencies": {
1115
+ "state-local": "^1.0.6"
1116
+ }
1117
+ },
1118
+ "node_modules/@monaco-editor/react": {
1119
+ "version": "4.7.0",
1120
+ "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz",
1121
+ "integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==",
1122
+ "license": "MIT",
1123
+ "dependencies": {
1124
+ "@monaco-editor/loader": "^1.5.0"
1125
+ },
1126
+ "peerDependencies": {
1127
+ "monaco-editor": ">= 0.25.0 < 1",
1128
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
1129
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
1130
+ }
1131
+ },
1132
  "node_modules/@nodelib/fs.scandir": {
1133
  "version": "2.1.5",
1134
  "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
 
5460
  "ufo": "^1.5.4"
5461
  }
5462
  },
5463
+ "node_modules/monaco-editor": {
5464
+ "version": "0.52.2",
5465
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.2.tgz",
5466
+ "integrity": "sha512-GEQWEZmfkOGLdd3XK8ryrfWz3AIP8YymVXiPHEdewrUq7mh0qrKrfHLNCXcbB6sTnMLnOZ3ztSiKcciFUkIJwQ==",
5467
+ "license": "MIT",
5468
+ "peer": true
5469
+ },
5470
  "node_modules/ms": {
5471
  "version": "2.1.3",
5472
  "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
 
6468
  "url": "https://github.com/sponsors/wooorm"
6469
  }
6470
  },
6471
+ "node_modules/state-local": {
6472
+ "version": "1.0.7",
6473
+ "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
6474
+ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
6475
+ "license": "MIT"
6476
+ },
6477
  "node_modules/string_decoder": {
6478
  "version": "1.3.0",
6479
  "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
lynxkite-app/web/package.json CHANGED
@@ -13,6 +13,7 @@
13
  "dependencies": {
14
  "@esbuild/linux-x64": "^0.25.0",
15
  "@iconify-json/tabler": "^1.2.10",
 
16
  "@svgr/core": "^8.1.0",
17
  "@svgr/plugin-jsx": "^8.1.0",
18
  "@swc/core": "^1.10.1",
 
13
  "dependencies": {
14
  "@esbuild/linux-x64": "^0.25.0",
15
  "@iconify-json/tabler": "^1.2.10",
16
+ "@monaco-editor/react": "^4.7.0",
17
  "@svgr/core": "^8.1.0",
18
  "@svgr/plugin-jsx": "^8.1.0",
19
  "@swc/core": "^1.10.1",
lynxkite-app/web/src/Code.tsx ADDED
@@ -0,0 +1,74 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // Full-page editor for code files.
2
+
3
+ import Editor from "@monaco-editor/react";
4
+ import { loader } from "@monaco-editor/react";
5
+ import { useEffect } from "react";
6
+ import { useParams } from "react-router";
7
+ import useSWR, { type Fetcher } from "swr";
8
+ // @ts-ignore
9
+ import Atom from "~icons/tabler/atom.jsx";
10
+ // @ts-ignore
11
+ import Backspace from "~icons/tabler/backspace.jsx";
12
+ // @ts-ignore
13
+ import Close from "~icons/tabler/x.jsx";
14
+ import favicon from "./assets/favicon.ico";
15
+ import theme from "./code-theme.ts";
16
+
17
+ export default function Code() {
18
+ useEffect(() => {
19
+ const initMonaco = async () => {
20
+ const monaco = await loader.init();
21
+ monaco.editor.defineTheme("lynxkite", theme);
22
+ };
23
+ initMonaco();
24
+ }, []);
25
+ const { path } = useParams();
26
+ const parentDir = path!.split("/").slice(0, -1).join("/");
27
+ const fetcher: Fetcher<{ code: string }> = (resource: string, init?: RequestInit) =>
28
+ fetch(resource, init).then((res) => res.json());
29
+ const code = useSWR(`/api/getCode?path=${path}`, fetcher);
30
+ return (
31
+ <div className="workspace">
32
+ <div className="top-bar bg-neutral">
33
+ <a className="logo" href="">
34
+ <img alt="" src={favicon} />
35
+ </a>
36
+ <div className="ws-name">{path}</div>
37
+ <div className="tools text-secondary">
38
+ <a href="">
39
+ <Atom />
40
+ </a>
41
+ <a href="">
42
+ <Backspace />
43
+ </a>
44
+ <a href={`/dir/${parentDir}`}>
45
+ <Close />
46
+ </a>
47
+ </div>
48
+ </div>
49
+ {code.isLoading && (
50
+ <div className="loading">
51
+ <div className="loading-text">Loading...</div>
52
+ </div>
53
+ )}
54
+ {code.error && (
55
+ <div className="error">
56
+ <div className="error-text">Error: {code.error}</div>
57
+ </div>
58
+ )}
59
+ {code.data && (
60
+ <Editor
61
+ defaultLanguage="python"
62
+ defaultValue={code.data.code}
63
+ theme="lynxkite"
64
+ options={{
65
+ cursorStyle: "block",
66
+ cursorBlinking: "solid",
67
+ minimap: { enabled: false },
68
+ renderLineHighlight: "none",
69
+ }}
70
+ />
71
+ )}
72
+ </div>
73
+ );
74
+ }
lynxkite-app/web/src/code-theme.ts ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ // A simple theme using the LynxKite colors.
2
+
3
+ import type { editor } from "monaco-editor/esm/vs/editor/editor.api";
4
+
5
+ const theme: editor.IStandaloneThemeData = {
6
+ base: "vs-dark",
7
+ inherit: true,
8
+ rules: [
9
+ {
10
+ foreground: "ff8800",
11
+ token: "keyword",
12
+ },
13
+ {
14
+ foreground: "0088ff",
15
+ fontStyle: "italic",
16
+ token: "comment",
17
+ },
18
+ {
19
+ foreground: "39bcf3",
20
+ token: "string",
21
+ },
22
+ {
23
+ foreground: "ffc600",
24
+ token: "",
25
+ },
26
+ ],
27
+ colors: {
28
+ "editor.foreground": "#FFFFFF",
29
+ "editor.background": "#002a4c",
30
+ "editor.selectionBackground": "#0050a4",
31
+ "editor.lineHighlightBackground": "#1f4662",
32
+ "editorCursor.foreground": "#ffc600",
33
+ "editorWhitespace.foreground": "#7f7f7fb2",
34
+ "editorIndentGuide.background": "#3b5364",
35
+ "editorIndentGuide.activeBackground": "#ffc600",
36
+ },
37
+ };
38
+ export default theme;
lynxkite-app/web/src/main.tsx CHANGED
@@ -3,6 +3,7 @@ import { createRoot } from "react-dom/client";
3
  import "@xyflow/react/dist/style.css";
4
  import "./index.css";
5
  import { BrowserRouter, Route, Routes } from "react-router";
 
6
  import Directory from "./Directory.tsx";
7
  import Workspace from "./workspace/Workspace.tsx";
8
 
@@ -14,6 +15,7 @@ createRoot(document.getElementById("root")!).render(
14
  <Route path="/dir" element={<Directory />} />
15
  <Route path="/dir/:path" element={<Directory />} />
16
  <Route path="/edit/:path" element={<Workspace />} />
 
17
  </Routes>
18
  </BrowserRouter>
19
  </StrictMode>,
 
3
  import "@xyflow/react/dist/style.css";
4
  import "./index.css";
5
  import { BrowserRouter, Route, Routes } from "react-router";
6
+ import Code from "./Code.tsx";
7
  import Directory from "./Directory.tsx";
8
  import Workspace from "./workspace/Workspace.tsx";
9
 
 
15
  <Route path="/dir" element={<Directory />} />
16
  <Route path="/dir/:path" element={<Directory />} />
17
  <Route path="/edit/:path" element={<Workspace />} />
18
+ <Route path="/code/:path" element={<Code />} />
19
  </Routes>
20
  </BrowserRouter>
21
  </StrictMode>,
lynxkite-app/web/src/workspace/Workspace.tsx CHANGED
@@ -1,3 +1,5 @@
 
 
1
  import { getYjsDoc, syncedStore } from "@syncedstore/core";
2
  import {
3
  type Connection,
@@ -16,7 +18,6 @@ import {
16
  } from "@xyflow/react";
17
  import axios from "axios";
18
  import { type MouseEvent, useCallback, useEffect, useMemo, useState } from "react";
19
- // The LynxKite workspace editor.
20
  import { useParams } from "react-router";
21
  import useSWR, { type Fetcher } from "swr";
22
  import { WebsocketProvider } from "y-websocket";
 
1
+ // The LynxKite workspace editor.
2
+
3
  import { getYjsDoc, syncedStore } from "@syncedstore/core";
4
  import {
5
  type Connection,
 
18
  } from "@xyflow/react";
19
  import axios from "axios";
20
  import { type MouseEvent, useCallback, useEffect, useMemo, useState } from "react";
 
21
  import { useParams } from "react-router";
22
  import useSWR, { type Fetcher } from "swr";
23
  import { WebsocketProvider } from "y-websocket";