darabos commited on
Commit
408ef2b
·
1 Parent(s): dbf89c5

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
- add_crdt_bindings(ws_pyd, ws_crdt)
 
 
 
 
 
 
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 className="title bg-primary" onClick={titleClicked}>
 
 
 
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)))