darabos commited on
Commit
c4b5e4b
·
1 Parent(s): 44d07e8

Resizing possibly works.

Browse files
server/crdt.py CHANGED
@@ -130,17 +130,21 @@ async def workspace_changed(name, changes, ws_crdt):
130
  from . import workspace
131
 
132
  ws_pyd = workspace.Workspace.model_validate(ws_crdt.to_py())
 
 
133
  clean_input(ws_pyd)
134
  if ws_pyd == last_known_versions.get(name):
135
  return
136
  last_known_versions[name] = ws_pyd.model_copy(deep=True)
 
 
137
  if name in delayed_executions:
138
  delayed_executions[name].cancel()
139
  delay = min(
140
  change.keys.get("__execution_delay", {}).get("newValue", 0)
141
  for change in changes
142
  )
143
- if delay > 0:
144
  task = asyncio.create_task(execute(ws_crdt, ws_pyd, delay))
145
  delayed_executions[name] = task
146
  else:
 
130
  from . import workspace
131
 
132
  ws_pyd = workspace.Workspace.model_validate(ws_crdt.to_py())
133
+ # Do not trigger execution for superficial changes.
134
+ # This is a quick solution until we build proper caching.
135
  clean_input(ws_pyd)
136
  if ws_pyd == last_known_versions.get(name):
137
  return
138
  last_known_versions[name] = ws_pyd.model_copy(deep=True)
139
+ # Frontend changes that result from typing are delayed to avoid
140
+ # rerunning the workspace for every keystroke.
141
  if name in delayed_executions:
142
  delayed_executions[name].cancel()
143
  delay = min(
144
  change.keys.get("__execution_delay", {}).get("newValue", 0)
145
  for change in changes
146
  )
147
+ if delay:
148
  task = asyncio.create_task(execute(ws_crdt, ws_pyd, delay))
149
  delayed_executions[name] = task
150
  else:
web/src/index.css CHANGED
@@ -259,3 +259,36 @@ body {
259
  margin: 10px;
260
  }
261
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
259
  margin: 10px;
260
  }
261
  }
262
+
263
+
264
+ path.react-flow__edge-path {
265
+ stroke-width: 2;
266
+ stroke: black;
267
+ }
268
+ .react-flow__edge.selected path.react-flow__edge-path {
269
+ outline: var(--xy-selection-border, var(--xy-selection-border-default));
270
+ outline-offset: 10px;
271
+ border-radius: 1px;
272
+ }
273
+ .react-flow__handle {
274
+ border-color: black;
275
+ background: white;
276
+ width: 10px;
277
+ height: 10px;
278
+ }
279
+ .react-flow__arrowhead * {
280
+ stroke: none;
281
+ fill: black;
282
+ }
283
+ // We want the area node to be above the sub-flow node if its inside the sub-flow.
284
+ // This will need some more thinking for a general solution.
285
+ .react-flow__node-sub_flow {
286
+ z-index: -20 !important;
287
+ }
288
+ .react-flow__node-area {
289
+ z-index: -10 !important;
290
+ }
291
+ .selected .lynxkite-node {
292
+ outline: var(--xy-selection-border, var(--xy-selection-border-default));
293
+ outline-offset: 7.5px;
294
+ }
web/src/workspace/Workspace.tsx CHANGED
@@ -97,15 +97,16 @@ function LynxKiteFlow() {
97
  });
98
  } else if (ch.type === 'select') {
99
  } else if (ch.type === 'dimensions') {
 
100
  } else if (ch.type === 'replace') {
101
  // Ideally we would only update the parameter that changed. But ReactFlow does not give us that detail.
102
- getYjsDoc(state).transact(() => {
103
- Object.assign(node.data, {
104
- collapsed: ch.item.data.collapsed,
105
- params: { ...ch.item.data.params },
106
- __execution_delay: ch.item.data.__execution_delay,
107
- });
108
- });
109
  } else {
110
  console.log('Unknown node change', ch);
111
  }
 
97
  });
98
  } else if (ch.type === 'select') {
99
  } else if (ch.type === 'dimensions') {
100
+ getYjsDoc(state).transact(() => Object.assign(node, ch.dimensions));
101
  } else if (ch.type === 'replace') {
102
  // Ideally we would only update the parameter that changed. But ReactFlow does not give us that detail.
103
+ const u = {
104
+ collapsed: ch.item.data.collapsed,
105
+ // The "..." expansion on a Y.map returns an empty object. Copying with fromEntries/entries instead.
106
+ params: { ...Object.fromEntries(Object.entries(ch.item.data.params)) },
107
+ __execution_delay: ch.item.data.__execution_delay,
108
+ };
109
+ getYjsDoc(state).transact(() => Object.assign(node.data, u));
110
  } else {
111
  console.log('Unknown node change', ch);
112
  }
web/src/workspace/nodes/LynxKiteNode.tsx CHANGED
@@ -73,17 +73,15 @@ export default function LynxKiteNode(props: LynxKiteNodeProps) {
73
  {handles.map(handle => (
74
  <Handle
75
  key={handle.name}
76
- id={handle.name} type={handle.type} position={Position[handle.position as keyof typeof Position]}
77
  style={{ [handleOffsetDirection[handle.position]]: handle.offsetPercentage + '%' }}>
78
  {handle.showLabel && <span className="handle-name">{handle.name.replace(/_/g, " ")}</span>}
79
- </Handle>
80
  ))}
81
  <NodeResizeControl
82
  minWidth={100}
83
  minHeight={50}
84
  style={{ 'background': 'transparent', 'border': 'none' }}
85
- onResizeStart={() => reactFlow.updateNodeData(props.id, { beingResized: true })}
86
- onResizeEnd={() => reactFlow.updateNodeData(props.id, { beingResized: false })}
87
  >
88
  <ChevronDownRight className="node-resizer" />
89
  </NodeResizeControl>
 
73
  {handles.map(handle => (
74
  <Handle
75
  key={handle.name}
76
+ id={handle.name} type={handle.type} position={handle.position as Position}
77
  style={{ [handleOffsetDirection[handle.position]]: handle.offsetPercentage + '%' }}>
78
  {handle.showLabel && <span className="handle-name">{handle.name.replace(/_/g, " ")}</span>}
79
+ </Handle >
80
  ))}
81
  <NodeResizeControl
82
  minWidth={100}
83
  minHeight={50}
84
  style={{ 'background': 'transparent', 'border': 'none' }}
 
 
85
  >
86
  <ChevronDownRight className="node-resizer" />
87
  </NodeResizeControl>