Spaces:
Running
Running
Manage an "in_progress" property on each node.
Browse files
lynxkite-app/src/lynxkite_app/crdt.py
CHANGED
@@ -86,6 +86,7 @@ def clean_input(ws_pyd):
|
|
86 |
for node in ws_pyd.nodes:
|
87 |
node.data.display = None
|
88 |
node.data.error = None
|
|
|
89 |
node.position.x = 0
|
90 |
node.position.y = 0
|
91 |
if node.model_extra:
|
@@ -175,7 +176,6 @@ delayed_executions = {}
|
|
175 |
async def workspace_changed(name: str, changes: pycrdt.MapEvent, ws_crdt: pycrdt.Map):
|
176 |
"""Callback to react to changes in the workspace.
|
177 |
|
178 |
-
|
179 |
Args:
|
180 |
name: Name of the workspace.
|
181 |
changes: Changes performed to the workspace.
|
@@ -224,18 +224,17 @@ async def execute(
|
|
224 |
assert path.is_relative_to(config.DATA_PATH), "Provided workspace path is invalid"
|
225 |
# Save user changes before executing, in case the execution fails.
|
226 |
workspace.save(ws_pyd, path)
|
227 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
228 |
await workspace.execute(ws_pyd)
|
229 |
workspace.save(ws_pyd, path)
|
230 |
|
231 |
|
232 |
-
def add_crdt_bindings(ws_pyd: workspace.Workspace, ws_crdt: pycrdt.Map):
|
233 |
-
for nc, np in zip(ws_crdt["nodes"], ws_pyd.nodes):
|
234 |
-
if "data" not in nc:
|
235 |
-
nc["data"] = pycrdt.Map()
|
236 |
-
np._crdt = nc
|
237 |
-
|
238 |
-
|
239 |
@contextlib.asynccontextmanager
|
240 |
async def lifespan(app):
|
241 |
global websocket_server
|
|
|
86 |
for node in ws_pyd.nodes:
|
87 |
node.data.display = None
|
88 |
node.data.error = None
|
89 |
+
node.data.in_progress = False
|
90 |
node.position.x = 0
|
91 |
node.position.y = 0
|
92 |
if node.model_extra:
|
|
|
176 |
async def workspace_changed(name: str, changes: pycrdt.MapEvent, ws_crdt: pycrdt.Map):
|
177 |
"""Callback to react to changes in the workspace.
|
178 |
|
|
|
179 |
Args:
|
180 |
name: Name of the workspace.
|
181 |
changes: Changes performed to the workspace.
|
|
|
224 |
assert path.is_relative_to(config.DATA_PATH), "Provided workspace path is invalid"
|
225 |
# Save user changes before executing, in case the execution fails.
|
226 |
workspace.save(ws_pyd, path)
|
227 |
+
with ws_crdt.doc.transaction():
|
228 |
+
for nc, np in zip(ws_crdt["nodes"], ws_pyd.nodes):
|
229 |
+
if "data" not in nc:
|
230 |
+
nc["data"] = pycrdt.Map()
|
231 |
+
nc["data"]["in_progress"] = True
|
232 |
+
# Nodes get a reference to their CRDT maps, so they can update them as the results come in.
|
233 |
+
np._crdt = nc
|
234 |
await workspace.execute(ws_pyd)
|
235 |
workspace.save(ws_pyd, path)
|
236 |
|
237 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
238 |
@contextlib.asynccontextmanager
|
239 |
async def lifespan(app):
|
240 |
global websocket_server
|
lynxkite-app/web/src/apiTypes.ts
CHANGED
@@ -41,6 +41,7 @@ export interface WorkspaceNodeData {
|
|
41 |
};
|
42 |
display?: unknown;
|
43 |
error?: string | null;
|
|
|
44 |
[k: string]: unknown;
|
45 |
}
|
46 |
export interface Position {
|
|
|
41 |
};
|
42 |
display?: unknown;
|
43 |
error?: string | null;
|
44 |
+
in_progress?: boolean;
|
45 |
[k: string]: unknown;
|
46 |
}
|
47 |
export interface Position {
|
lynxkite-app/web/src/index.css
CHANGED
@@ -90,11 +90,14 @@ body {
|
|
90 |
}
|
91 |
|
92 |
.lynxkite-node .title {
|
93 |
-
/* background: oklch(75% 0.2 55); */
|
94 |
font-weight: bold;
|
95 |
padding: 8px;
|
96 |
}
|
97 |
|
|
|
|
|
|
|
|
|
98 |
.handle-name {
|
99 |
font-size: 10px;
|
100 |
color: black;
|
|
|
90 |
}
|
91 |
|
92 |
.lynxkite-node .title {
|
|
|
93 |
font-weight: bold;
|
94 |
padding: 8px;
|
95 |
}
|
96 |
|
97 |
+
.lynxkite-node .title.in-progress {
|
98 |
+
background: yellow;
|
99 |
+
}
|
100 |
+
|
101 |
.handle-name {
|
102 |
font-size: 10px;
|
103 |
color: black;
|
lynxkite-app/web/src/workspace/nodes/LynxKiteNode.tsx
CHANGED
@@ -71,7 +71,10 @@ export default function LynxKiteNode(props: LynxKiteNodeProps) {
|
|
71 |
}}
|
72 |
>
|
73 |
<div className="lynxkite-node" style={props.nodeStyle}>
|
74 |
-
<div
|
|
|
|
|
|
|
75 |
{data.title}
|
76 |
{data.error && <span className="title-icon">⚠️</span>}
|
77 |
{expanded || <span className="title-icon">⋯</span>}
|
|
|
71 |
}}
|
72 |
>
|
73 |
<div className="lynxkite-node" style={props.nodeStyle}>
|
74 |
+
<div
|
75 |
+
className={`title bg-primary ${data.in_progress ? "in-progress" : ""}`}
|
76 |
+
onClick={titleClicked}
|
77 |
+
>
|
78 |
{data.title}
|
79 |
{data.error && <span className="title-icon">⚠️</span>}
|
80 |
{expanded || <span className="title-icon">⋯</span>}
|
lynxkite-core/src/lynxkite/core/workspace.py
CHANGED
@@ -26,6 +26,7 @@ class WorkspaceNodeData(BaseConfig):
|
|
26 |
params: dict
|
27 |
display: Optional[object] = None
|
28 |
error: Optional[str] = None
|
|
|
29 |
# Also contains a "meta" field when going out.
|
30 |
# This is ignored when coming back from the frontend.
|
31 |
|
@@ -44,6 +45,7 @@ class WorkspaceNode(BaseConfig):
|
|
44 |
with self._crdt.doc.transaction():
|
45 |
self._crdt["data"]["display"] = result.display
|
46 |
self._crdt["data"]["error"] = result.error
|
|
|
47 |
|
48 |
def publish_error(self, error: Exception | str):
|
49 |
self.publish_result(ops.Result(error=str(error)))
|
|
|
26 |
params: dict
|
27 |
display: Optional[object] = None
|
28 |
error: Optional[str] = None
|
29 |
+
in_progress: bool = False
|
30 |
# Also contains a "meta" field when going out.
|
31 |
# This is ignored when coming back from the frontend.
|
32 |
|
|
|
45 |
with self._crdt.doc.transaction():
|
46 |
self._crdt["data"]["display"] = result.display
|
47 |
self._crdt["data"]["error"] = result.error
|
48 |
+
self._crdt["data"]["in_progress"] = False
|
49 |
|
50 |
def publish_error(self, error: Exception | str):
|
51 |
self.publish_result(ops.Result(error=str(error)))
|