darabos commited on
Commit
454a221
·
1 Parent(s): f0dd69c

Allow coloring node titles.

Browse files
lynxkite-app/web/src/index.css CHANGED
@@ -104,27 +104,29 @@ body {
104
  background-image: linear-gradient(
105
  to right,
106
  var(--status-color-1),
107
- var(--status-color-2),
 
108
  var(--status-color-3)
109
  );
 
110
  background-size: 180% 180%;
111
- --status-color-1: oklch(75% 0.2 55);
112
- --status-color-2: oklch(75% 0.2 55);
113
- --status-color-3: oklch(75% 0.2 55);
114
  transition: --status-color-1 0.3s, --status-color-2 0.3s, --status-color-3 0.3s;
115
  }
116
 
117
  .lynxkite-node .title.active {
118
- --status-color-1: oklch(75% 0.2 55);
119
- --status-color-2: oklch(90% 0.2 55);
120
- --status-color-3: oklch(75% 0.1 55);
121
- animation: active-node-gradient-animation 2s ease-in-out infinite;
122
  }
123
 
124
  .lynxkite-node .title.planned {
125
- --status-color-1: oklch(75% 0.1 55);
126
- --status-color-2: oklch(75% 0.1 55);
127
- --status-color-3: oklch(75% 0.1 55);
128
  }
129
 
130
  .handle-name {
@@ -405,15 +407,7 @@ body {
405
  }
406
 
407
  @keyframes active-node-gradient-animation {
408
- 0% {
409
- background-position-x: 100%;
410
- }
411
-
412
- 50% {
413
- background-position-x: 0%;
414
- }
415
-
416
- 100% {
417
  background-position-x: 100%;
418
  }
419
  }
 
104
  background-image: linear-gradient(
105
  to right,
106
  var(--status-color-1),
107
+ var(--status-color-2) 40%,
108
+ var(--status-color-2) 60%,
109
  var(--status-color-3)
110
  );
111
+ background-blend-mode: luminosity;
112
  background-size: 180% 180%;
113
+ --status-color-1: #0000;
114
+ --status-color-2: #0000;
115
+ --status-color-3: #0000;
116
  transition: --status-color-1 0.3s, --status-color-2 0.3s, --status-color-3 0.3s;
117
  }
118
 
119
  .lynxkite-node .title.active {
120
+ --status-color-1: #0000;
121
+ --status-color-2: #fff4;
122
+ --status-color-3: #888f;
123
+ animation: active-node-gradient-animation 1.2s alternate ease-in-out infinite;
124
  }
125
 
126
  .lynxkite-node .title.planned {
127
+ --status-color-1: #888f;
128
+ --status-color-2: #888f;
129
+ --status-color-3: #888f;
130
  }
131
 
132
  .handle-name {
 
407
  }
408
 
409
  @keyframes active-node-gradient-animation {
410
+ to {
 
 
 
 
 
 
 
 
411
  background-position-x: 100%;
412
  }
413
  }
lynxkite-app/web/src/workspace/nodes/LynxKiteNode.tsx CHANGED
@@ -43,6 +43,12 @@ function getHandles(inputs: object, outputs: object) {
43
  return handles;
44
  }
45
 
 
 
 
 
 
 
46
  function LynxKiteNodeComponent(props: LynxKiteNodeProps) {
47
  const reactFlow = useReactFlow();
48
  const data = props.data;
@@ -57,7 +63,10 @@ function LynxKiteNodeComponent(props: LynxKiteNodeProps) {
57
  left: "top",
58
  right: "top",
59
  };
60
-
 
 
 
61
  return (
62
  <div
63
  className={`node-container ${expanded ? "expanded" : "collapsed"} `}
@@ -67,7 +76,11 @@ function LynxKiteNodeComponent(props: LynxKiteNodeProps) {
67
  }}
68
  >
69
  <div className="lynxkite-node" style={props.nodeStyle}>
70
- <div className={`title bg-primary ${data.status}`} onClick={titleClicked}>
 
 
 
 
71
  {data.title}
72
  {data.error && <span className="title-icon">⚠️</span>}
73
  {expanded || <span className="title-icon">⋯</span>}
@@ -97,7 +110,7 @@ function LynxKiteNodeComponent(props: LynxKiteNodeProps) {
97
  )}
98
  {handles.map((handle) => (
99
  <Handle
100
- key={handle.name}
101
  id={handle.name}
102
  type={handle.type}
103
  position={handle.position as Position}
 
43
  return handles;
44
  }
45
 
46
+ const OP_COLORS: { [key: string]: string } = {
47
+ orange: "oklch(75% 0.2 55)",
48
+ blue: "oklch(75% 0.2 230)",
49
+ green: "oklch(75% 0.2 130)",
50
+ };
51
+
52
  function LynxKiteNodeComponent(props: LynxKiteNodeProps) {
53
  const reactFlow = useReactFlow();
54
  const data = props.data;
 
63
  left: "top",
64
  right: "top",
65
  };
66
+ const titleStyle: { backgroundColor?: string } = {};
67
+ if (data.meta?.color) {
68
+ titleStyle.backgroundColor = OP_COLORS[data.meta.color] || data.meta.color;
69
+ }
70
  return (
71
  <div
72
  className={`node-container ${expanded ? "expanded" : "collapsed"} `}
 
76
  }}
77
  >
78
  <div className="lynxkite-node" style={props.nodeStyle}>
79
+ <div
80
+ className={`title bg-primary ${data.status}`}
81
+ style={titleStyle}
82
+ onClick={titleClicked}
83
+ >
84
  {data.title}
85
  {data.error && <span className="title-icon">⚠️</span>}
86
  {expanded || <span className="title-icon">⋯</span>}
 
110
  )}
111
  {handles.map((handle) => (
112
  <Handle
113
+ key={`${handle.name} on ${handle.position}`}
114
  id={handle.name}
115
  type={handle.type}
116
  position={handle.position as Position}
lynxkite-core/src/lynxkite/core/ops.py CHANGED
@@ -168,6 +168,7 @@ class Op(BaseConfig):
168
  outputs: dict[str, Output]
169
  # TODO: Make type an enum with the possible values.
170
  type: str = "basic" # The UI to use for this operation.
 
171
 
172
  def __call__(self, *inputs, **params):
173
  # Convert parameters.
@@ -199,7 +200,16 @@ class Op(BaseConfig):
199
  return res
200
 
201
 
202
- def op(env: str, name: str, *, view="basic", outputs=None, params=None, slow=False):
 
 
 
 
 
 
 
 
 
203
  """Decorator for defining an operation."""
204
 
205
  def decorator(func):
@@ -234,6 +244,7 @@ def op(env: str, name: str, *, view="basic", outputs=None, params=None, slow=Fal
234
  inputs=inputs,
235
  outputs=_outputs,
236
  type=_view,
 
237
  )
238
  CATALOGS.setdefault(env, {})
239
  CATALOGS[env][name] = op
@@ -291,7 +302,7 @@ def no_op(*args, **kwargs):
291
  return None
292
 
293
 
294
- def register_passive_op(env: str, name: str, inputs=[], outputs=["output"], params=[]):
295
  """A passive operation has no associated code."""
296
  op = Op(
297
  func=no_op,
@@ -303,6 +314,7 @@ def register_passive_op(env: str, name: str, inputs=[], outputs=["output"], para
303
  outputs=dict(
304
  (o, Output(name=o, type=None)) if isinstance(o, str) else (o.name, o) for o in outputs
305
  ),
 
306
  )
307
  CATALOGS.setdefault(env, {})
308
  CATALOGS[env][name] = op
 
168
  outputs: dict[str, Output]
169
  # TODO: Make type an enum with the possible values.
170
  type: str = "basic" # The UI to use for this operation.
171
+ color: str = "orange" # The color of the operation in the UI.
172
 
173
  def __call__(self, *inputs, **params):
174
  # Convert parameters.
 
200
  return res
201
 
202
 
203
+ def op(
204
+ env: str,
205
+ name: str,
206
+ *,
207
+ view="basic",
208
+ outputs=None,
209
+ params=None,
210
+ slow=False,
211
+ color=None,
212
+ ):
213
  """Decorator for defining an operation."""
214
 
215
  def decorator(func):
 
244
  inputs=inputs,
245
  outputs=_outputs,
246
  type=_view,
247
+ color=color or "orange",
248
  )
249
  CATALOGS.setdefault(env, {})
250
  CATALOGS[env][name] = op
 
302
  return None
303
 
304
 
305
+ def register_passive_op(env: str, name: str, inputs=[], outputs=["output"], params=[], **kwargs):
306
  """A passive operation has no associated code."""
307
  op = Op(
308
  func=no_op,
 
314
  outputs=dict(
315
  (o, Output(name=o, type=None)) if isinstance(o, str) else (o.name, o) for o in outputs
316
  ),
317
+ **kwargs,
318
  )
319
  CATALOGS.setdefault(env, {})
320
  CATALOGS[env][name] = op
lynxkite-graph-analytics/src/lynxkite_graph_analytics/pytorch/pytorch_core.py CHANGED
@@ -13,7 +13,9 @@ from .. import core
13
  ENV = "PyTorch model"
14
 
15
 
16
- def op(name, **kwargs):
 
 
17
  _op = ops.op(ENV, name, **kwargs)
18
 
19
  def decorator(func):
@@ -28,7 +30,7 @@ def op(name, **kwargs):
28
  return decorator
29
 
30
 
31
- def reg(name, inputs=[], outputs=None, params=[]):
32
  if outputs is None:
33
  outputs = inputs
34
  return ops.register_passive_op(
@@ -37,6 +39,7 @@ def reg(name, inputs=[], outputs=None, params=[]):
37
  inputs=[ops.Input(name=name, position="bottom", type="tensor") for name in inputs],
38
  outputs=[ops.Output(name=name, position="top", type="tensor") for name in outputs],
39
  params=params,
 
40
  )
41
 
42
 
 
13
  ENV = "PyTorch model"
14
 
15
 
16
+ def op(name, weights=False, **kwargs):
17
+ if weights:
18
+ kwargs["color"] = "blue"
19
  _op = ops.op(ENV, name, **kwargs)
20
 
21
  def decorator(func):
 
30
  return decorator
31
 
32
 
33
+ def reg(name, inputs=[], outputs=None, params=[], **kwargs):
34
  if outputs is None:
35
  outputs = inputs
36
  return ops.register_passive_op(
 
39
  inputs=[ops.Input(name=name, position="bottom", type="tensor") for name in inputs],
40
  outputs=[ops.Output(name=name, position="top", type="tensor") for name in outputs],
41
  params=params,
42
+ **kwargs,
43
  )
44
 
45
 
lynxkite-graph-analytics/src/lynxkite_graph_analytics/pytorch/pytorch_ops.py CHANGED
@@ -13,7 +13,7 @@ reg("Input: sequential", outputs=["y"])
13
  reg("Output", inputs=["x"], outputs=["x"], params=[P.basic("name")])
14
 
15
 
16
- @op("LSTM")
17
  def lstm(x, *, input_size=1024, hidden_size=1024, dropout=0.0):
18
  return torch.nn.LSTM(input_size, hidden_size, dropout=0.0)
19
 
@@ -59,7 +59,7 @@ def dropout(x, *, p=0.0):
59
  return torch.nn.Dropout(p)
60
 
61
 
62
- @op("Linear")
63
  def linear(x, *, output_dim=1024):
64
  return pyg_nn.Linear(-1, output_dim)
65
 
@@ -124,6 +124,7 @@ reg(
124
  ),
125
  P.basic("lr", 0.001),
126
  ],
 
127
  )
128
 
129
  ops.register_passive_op(
 
13
  reg("Output", inputs=["x"], outputs=["x"], params=[P.basic("name")])
14
 
15
 
16
+ @op("LSTM", weights=True)
17
  def lstm(x, *, input_size=1024, hidden_size=1024, dropout=0.0):
18
  return torch.nn.LSTM(input_size, hidden_size, dropout=0.0)
19
 
 
59
  return torch.nn.Dropout(p)
60
 
61
 
62
+ @op("Linear", weights=True)
63
  def linear(x, *, output_dim=1024):
64
  return pyg_nn.Linear(-1, output_dim)
65
 
 
124
  ),
125
  P.basic("lr", 0.001),
126
  ],
127
+ color="green",
128
  )
129
 
130
  ops.register_passive_op(