caixanegra 0.2.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c291dfc1c33d2c17e87093eff1bceff3c061ef8c7230a561ace088cd9e23f279
4
- data.tar.gz: e812c3f4c1d202902f926115162c0b9b46885b35af56db52db3aa94ab8e53ac8
3
+ metadata.gz: 376caa1d1fc64e8cafb870bbf592dad26520daee9c0ecdb84c3a6d47df67d5c6
4
+ data.tar.gz: a97853cb0e8e23d05d998a8d10f515784d1699396ee58604f05ce666ebe7d5ee
5
5
  SHA512:
6
- metadata.gz: c6276bd14d36c832729b8a717a15ad5a8c6b9e6223343d6169fa1c153dc0389d0d0ef73ed61b0eb4f19a9dfc1936683b59b80e994b740df4cc670958fbc21833
7
- data.tar.gz: 70059940599beff0f5cf09bbb73defa53fc31e336166a15a0262902f194862cd318b5bb8fb7bcb22a7934960411c7dce14f997816a0430fc943ba6d0dceddb88
6
+ metadata.gz: cf857f517da162fa54b11aac3e196448b308d7a6dc32776309b37668419af810ea1e62396467a78c96dbd8a6e6b6f9bb6067df6e4c7ea144b6ec757cdd4c7ee1
7
+ data.tar.gz: 620f9bc6def64b148bfbcfdf0d27a010c75d788275fdfbfe00842a080a60203623db804c0f9951f13b76d516435548f6d966450b4cd1ac3bae9743bf5d42eb5c
data/README.md CHANGED
@@ -16,8 +16,8 @@ or
16
16
  bundler add caixanegra
17
17
  ```
18
18
  # Getting Started
19
- **caixanegra** implements a self-contained designer, which only requires Redis to be able to receive and report back flow descriptors.
20
- To get started, the only thing you need is to point to your Redis instance and point which classes on your codebase should represent units.
19
+ **caixanegra** implements a self-contained flow designer and executor.
20
+ To get started, the only thing you need is to point to your [transient store](https://github.com/sergiorribeiro/caixanegra/wiki/The-Transient-Store) implementation and point out which classes on your codebase should represent units.
21
21
 
22
22
  First, mount the engine. Add the line below to `routes.rb` file:
23
23
 
@@ -29,19 +29,17 @@ Then, let's create a `caixanegra.rb` initializer (or any name you prefer)
29
29
 
30
30
  ```ruby
31
31
  Caixanegra.setup do |config|
32
- config.units = {
33
- awesome_unit: Caixanegra::Units::AU,
34
- another_awesome_unit: Some::Other::Namespace::AAU,
35
- you_can_also: {
36
- scope_units: Caixanegra::Units::ScopedUnit,
37
- },
38
- }
39
- config.redis = Redis.new
32
+ config.units = [
33
+ Caixanegra::Units::AwesomeUnit,
34
+ Some::Other::Namespace::AnotherAwesomeUnit,
35
+ Caixanegra::Units::SuperUnit,
36
+ ]
37
+ config.transient_store = GreatTransientStore.new
40
38
  end
41
39
  ```
42
40
 
43
41
  With the designer configured, you can use `Caixanegra::Manager` to handle the previously stored definition (or an empty one).
44
- This will give you the UID that **caixanegra** designer will understand.
42
+ This will give you the UID that **caixanegra** designer will understand, using transient store.
45
43
 
46
44
  ```ruby
47
45
  my_flow = somewhere.get_flow # get from your own persistence or transport solution
@@ -54,15 +52,13 @@ You can then safely navigate to the designer.
54
52
  link_to "Some flow", "/caixanegra/design/#{@uid}?unit_scope=optional_scope,another_optional_scope", target: :_blank
55
53
  ```
56
54
 
57
- Saved changes will update the flow definition on Redis, and you must then persist them. You can get the flow definition for any specified **caixanegra** handled UID:
55
+ Saved changes will update the flow definition through the transient store, and you must then persist them. You can get the flow definition for any specified **caixanegra** handled UID, given that the transient store is able to correctly sort them out:
58
56
 
59
57
  ```ruby
60
58
  updated_flow = Caixanegra::Manager.get(my_uid)
61
59
  persist_flow(updated_flow) # your own persistence or transport solution. It's a JSON
62
60
  ```
63
61
 
64
- **NOTE:** There's currently no managed way to set callbacks on save actions from the designer. Working on it
65
-
66
62
  Please, refer to [the wiki](https://github.com/sergiorribeiro/caixanegra/wiki) to get to know more about [units](https://github.com/sergiorribeiro/caixanegra/wiki/Anatomy-of-a-unit).
67
63
 
68
64
  # License
@@ -3,6 +3,7 @@ window.Caixanegra.Designer = {
3
3
  #drawValues;
4
4
  title;
5
5
  class;
6
+ color;
6
7
  type;
7
8
  exits;
8
9
  mappings;
@@ -20,6 +21,7 @@ window.Caixanegra.Designer = {
20
21
  this.class = params.class || "unspecified";
21
22
  this.exits = params.exits || [];
22
23
  this.mappings = params.mappings || {};
24
+ this.color = params.color;
23
25
  this.#drawValues = {};
24
26
  this.MARGIN = 10;
25
27
  this.SNAP = 10;
@@ -36,7 +38,9 @@ window.Caixanegra.Designer = {
36
38
 
37
39
  this.size.x = this.UNIT_WIDTH;
38
40
  let hCursor = this.#drawValues.position.y;
39
- this.#drawValues.unitBgColor = Caixanegra.Designer.typeColor(this.type);
41
+ const typeColor = Caixanegra.Designer.typeColor(this);
42
+ this.#drawValues.unitBgColor = typeColor.background;
43
+ this.#drawValues.unitFgColor = typeColor.foreground;
40
44
  this.#drawValues.text = {};
41
45
  this.#drawValues.exitRectangles = [];
42
46
 
@@ -83,25 +87,25 @@ window.Caixanegra.Designer = {
83
87
  }
84
88
 
85
89
  update(context) {
86
- if (context.mouse.down &&
90
+ if (context.mouse.down &&
87
91
  context.mouse.down.button === 1 &&
88
- context.mouse.down.cursorAt &&
92
+ context.mouse.down.cursorAt &&
89
93
  context.mouse.down.cursorAt.object.oid === this.oid) {
90
94
  this.#beingDragged = true;
91
95
  } else {
92
96
  this.#beingDragged = false;
93
97
  }
94
98
 
95
- if (context.mouse.move &&
99
+ if (context.mouse.move &&
96
100
  context.mouse.move.button === 1 &&
97
- context.mouse.down &&
98
- context.mouse.down.cursorAt &&
101
+ context.mouse.down &&
102
+ context.mouse.down.cursorAt &&
99
103
  context.mouse.down.cursorAt.object.oid === this.oid) {
100
104
  const intersection = new Sabertooth.Vector2(
101
105
  context.mouse.down.cursorAt.intersection.x,
102
106
  context.mouse.down.cursorAt.intersection.y
103
107
  );
104
-
108
+
105
109
  if (this.connectingExit === null) {
106
110
  for (let eidx = 0; eidx < this.#drawValues.exits.length; eidx++) {
107
111
  if (this.#drawValues.exits[eidx].rectangle.intersectionPoint(intersection)) {
@@ -180,7 +184,7 @@ window.Caixanegra.Designer = {
180
184
  case "extra":
181
185
  ctx.beginPath();
182
186
  ctx.roundRect(this.#drawValues.position.x, this.#drawValues.position.y, this.size.x, this.size.y, 5);
183
- ctx.fillStyle = this.#drawValues.unitBgColor;
187
+ ctx.fillStyle = `rgb(${this.#drawValues.unitBgColor.r}, ${this.#drawValues.unitBgColor.g}, ${this.#drawValues.unitBgColor.b})`;
184
188
  ctx.fill();
185
189
 
186
190
  ctx.beginPath();
@@ -202,18 +206,20 @@ window.Caixanegra.Designer = {
202
206
  );
203
207
  ctx.globalCompositeOperation = gco;
204
208
 
209
+ const rgbString = `${this.#drawValues.unitFgColor.r}, ${this.#drawValues.unitFgColor.g}, ${this.#drawValues.unitFgColor.b}`;
210
+
205
211
  ctx.textBaseline = "top";
206
212
  ctx.textAlign = "center";
207
- ctx.fillStyle = "#000";
213
+ ctx.fillStyle = `rgb(${rgbString})`;
208
214
  ctx.font = "25px Helvetica";
209
215
  ctx.fillText(this.title, this.#drawValues.center.x, this.#drawValues.text.title.y, this.UNIT_WIDTH - this.MARGIN * 2);
210
216
 
211
- ctx.fillStyle = "rgba(0,0,0,0.5)";
217
+ ctx.fillStyle = `rgba(${rgbString},0.5)`;
212
218
  ctx.font = "18px Helvetica";
213
219
  ctx.fillText(this.class, this.#drawValues.center.x, this.#drawValues.text.class.y, this.UNIT_WIDTH - this.MARGIN * 2);
214
220
 
215
221
  ctx.strokeStyle = "#FFF";
216
- ctx.fillStyle = "rgba(0,0,0,0.8)";
222
+ ctx.fillStyle = `rgba(${rgbString},0.8)`;
217
223
  ctx.font = "bold 14px monospace";
218
224
  ctx.textAlign = "right";
219
225
  ctx.lineWidth = 2;
@@ -269,7 +275,7 @@ window.Caixanegra.Designer = {
269
275
  selectedUnit;
270
276
  flowId;
271
277
  unitScope;
272
-
278
+
273
279
  constructor(drawingSurface) {
274
280
  this.flowId = this.#extractFlowId();
275
281
  this.unitScope = this.#extractUnitScope();
@@ -524,7 +530,7 @@ window.Caixanegra.Designer = {
524
530
  unitMenu.innerHTML = "";
525
531
 
526
532
  const scopes = [];
527
-
533
+
528
534
  this.#catalog.forEach(unit => {
529
535
  if (unit.hasOwnProperty("scope") && Array.isArray(unit.scope)) {
530
536
  scopes.push(...unit.scope);
@@ -532,7 +538,7 @@ window.Caixanegra.Designer = {
532
538
  scopes.push("_unscoped");
533
539
  }
534
540
  });
535
-
541
+
536
542
  [...new Set(scopes)].sort().forEach(scope => {
537
543
  const scopeWrapper = document.createElement("div");
538
544
  const scopeTitle = document.createElement("div");
@@ -564,12 +570,13 @@ window.Caixanegra.Designer = {
564
570
  colorCode.classList.add("color-code");
565
571
  name.classList.add("name");
566
572
  type.classList.add("type");
567
-
573
+
568
574
  name.innerHTML = unitData.title;
569
575
  type.innerHTML = unitData.type;
570
576
  description.innerHTML = unitData.description;
571
- colorCode.style.backgroundColor = Caixanegra.Designer.typeColor(unitData.type);
572
-
577
+ const typeColor = Caixanegra.Designer.typeColor(unitData).background;
578
+ colorCode.style.backgroundColor = `rgb(${typeColor.r}, ${typeColor.g}, ${typeColor.b})`;
579
+
573
580
  header.append(name, type);
574
581
  content.append(header, description);
575
582
  item.append(colorCode, content);
@@ -641,7 +648,7 @@ window.Caixanegra.Designer = {
641
648
 
642
649
  this.messenger.querySelector(".message").innerHTML = message;
643
650
  }
644
-
651
+
645
652
  createUnit(params) {
646
653
  this.#sequence++;
647
654
  const newUnit = new Caixanegra.Designer.Unit({
@@ -649,13 +656,14 @@ window.Caixanegra.Designer = {
649
656
  type: params.type,
650
657
  title: params.title,
651
658
  class: params.class,
659
+ color: params.color,
652
660
  zIndex: this.#sequence
653
661
  });
654
662
 
655
663
  if (params.oid) {
656
664
  newUnit.oid = params.oid;
657
665
  newUnit.position = new Sabertooth.Vector2(params.position.x, params.position.y);
658
- newUnit.title = params.title;
666
+ newUnit.title = params.title;
659
667
  }
660
668
 
661
669
  if (params.exits && params.exits.length > 0) {
@@ -687,7 +695,7 @@ window.Caixanegra.Designer = {
687
695
  this.#units.push(newUnit);
688
696
  this.gre.addObject(newUnit);
689
697
  }
690
-
698
+
691
699
  removeUnit(oid) {
692
700
  const killIndex = this.#units.findIndex((unit) => {return unit.oid === oid});
693
701
  this.#units.splice(killIndex, 1);
@@ -796,7 +804,7 @@ window.Caixanegra.Designer = {
796
804
  const endObject = moments.end.cursorAt?.object;
797
805
 
798
806
  if (startObject && endObject &&
799
- startObject?.connectingExit &&
807
+ startObject?.connectingExit &&
800
808
  startObject.oid !== endObject.oid) {
801
809
  startObject.connectingExit.reference.target = moments.end.cursorAt.object;
802
810
  startObject.connectingExit = null;
@@ -902,7 +910,7 @@ window.Caixanegra.Designer = {
902
910
  header.classList.add("hit-header");
903
911
  header.innerHTML = `hit #${idx + 1}`;
904
912
  hitWrapper.append(header);
905
-
913
+
906
914
  let section = this.#buildStepHitFold("in", hit.in);
907
915
  if (section !== null) { hitWrapper.append(section); }
908
916
 
@@ -922,7 +930,8 @@ window.Caixanegra.Designer = {
922
930
  const pane = this.unitDetailPane;
923
931
  const debugPane = this.unitDebugHitsPane;
924
932
  const dynamicContent = pane.querySelector("#dynamicContent");
925
- pane.querySelector(".color-code").style.backgroundColor = Caixanegra.Designer.typeColor(object.type);
933
+ const typeColor = Caixanegra.Designer.typeColor(object).background;
934
+ pane.querySelector(".color-code").style.backgroundColor = `rgb(${typeColor.r}, ${typeColor.g}, ${typeColor.b})`;
926
935
  pane.classList.add("-open");
927
936
 
928
937
  if (object.debugHits.length > 0) {
@@ -932,7 +941,7 @@ window.Caixanegra.Designer = {
932
941
  debugPane.querySelector("#debugData").innerHTML = "";
933
942
  debugPane.classList.remove("-open");
934
943
  }
935
-
944
+
936
945
  pane.querySelector("#unitDetailTitle").value = object.title;
937
946
  pane.querySelector("#unitDetailClass .name").innerHTML = matrix.class;
938
947
  pane.querySelector("#unitDetailDescription").innerHTML = matrix.description;
@@ -1112,7 +1121,7 @@ window.Caixanegra.Designer = {
1112
1121
  });
1113
1122
  typeSelector.addEventListener("change", this.#unitInputTypeChanged.bind(this));
1114
1123
  typeSelectorHeader.append(name, typeSelector);
1115
-
1124
+
1116
1125
  wrapper.appendChild(typeSelectorHeader);
1117
1126
  wrapper.appendChild(fieldDescription);
1118
1127
 
@@ -1144,12 +1153,48 @@ window.Caixanegra.Designer = {
1144
1153
  valueInput.addEventListener("change", this.#unitInputValueChanged.bind(this));
1145
1154
  }
1146
1155
  break;
1156
+ case "boolean":
1157
+ {
1158
+ const trueInput = document.createElement("input");
1159
+ const falseInput = document.createElement("input");
1160
+ const trueInputLabel = document.createElement("label");
1161
+ const falseInputLabel = document.createElement("label");
1162
+ const trueRadioGroup = document.createElement("div");
1163
+ const falseRadioGroup = document.createElement("div");
1164
+ trueRadioGroup.classList.add("radio-group");
1165
+ falseRadioGroup.classList.add("radio-group");
1166
+ trueInput.setAttribute("type", "radio");
1167
+ falseInput.setAttribute("type", "radio");
1168
+ trueInput.setAttribute("value", 1);
1169
+ trueInputLabel.innerHTML = "True";
1170
+ falseInput.setAttribute("value", 0);
1171
+ falseInputLabel.innerHTML = "False";
1172
+ trueInput.setAttribute("name", `b${input}`);
1173
+ falseInput.setAttribute("name", `b${input}`);
1174
+ const value = unit.mappings[input]?.value || matrix.default || "0"
1175
+ if (value === "1") { trueInput.setAttribute("checked", true); }
1176
+ if (value === "0") { falseInput.setAttribute("checked", true); }
1177
+ trueInput.addEventListener("change", this.#unitInputValueChanged.bind(this));
1178
+ falseInput.addEventListener("change", this.#unitInputValueChanged.bind(this));
1179
+
1180
+ trueRadioGroup.appendChild(trueInput);
1181
+ trueRadioGroup.appendChild(trueInputLabel);
1182
+ falseRadioGroup.appendChild(falseInput);
1183
+ falseRadioGroup.appendChild(falseInputLabel);
1184
+
1185
+ valueWrapper.appendChild(trueRadioGroup);
1186
+ valueWrapper.appendChild(falseRadioGroup);
1187
+ }
1188
+ break;
1147
1189
  }
1148
1190
 
1149
1191
  if (unit.mappings[input]?.type !== "user") {
1150
1192
  valueWrapper.classList.add("-disabled");
1151
1193
  }
1152
- valueWrapper.appendChild(valueInput);
1194
+
1195
+ if(valueInput !== null) {
1196
+ valueWrapper.appendChild(valueInput);
1197
+ }
1153
1198
 
1154
1199
  wrapper.append(valueWrapper);
1155
1200
  } else {
@@ -1212,12 +1257,12 @@ window.Caixanegra.Designer = {
1212
1257
  const exitMappings = {};
1213
1258
 
1214
1259
  Array.from(exits).forEach((exit) => {
1215
- exitMappings[exit.dataset.exit] =
1260
+ exitMappings[exit.dataset.exit] =
1216
1261
  Array.from(exit.querySelectorAll(".exit-mapping")).map((mapping) => {
1217
1262
  const useValue = mapping.querySelector("input.use").value;
1218
1263
  const asValue = mapping.querySelector("input.as").value;
1219
1264
  return { use: useValue, as: asValue };
1220
- });
1265
+ });
1221
1266
  });
1222
1267
 
1223
1268
  for(let idx = 0; idx < unit.exits.length; idx++) {
@@ -1262,9 +1307,9 @@ window.Caixanegra.Designer = {
1262
1307
  #engineUpdate(ev) {
1263
1308
  const context = ev.detail;
1264
1309
 
1265
- if (context.mouse.move &&
1310
+ if (context.mouse.move &&
1266
1311
  [1, 2].includes(context.mouse.move.button) &&
1267
- context.mouse.down &&
1312
+ context.mouse.down &&
1268
1313
  context.mouse.down.cursorAt === null) {
1269
1314
  const offset = {
1270
1315
  x: context.mouse.move.internal_x - context.mouse.down.internal_x,
@@ -1273,7 +1318,7 @@ window.Caixanegra.Designer = {
1273
1318
 
1274
1319
  this.gre.worldCenter.x = context.mouse.down.referential.x + offset.x;
1275
1320
  this.gre.worldCenter.y = context.mouse.down.referential.y + offset.y;
1276
-
1321
+
1277
1322
  for (let oidx = 0; oidx < context.objects.length; oidx++) {
1278
1323
  context.objects[oidx].initialize(this.gre.engineContext());
1279
1324
  }
@@ -1288,23 +1333,51 @@ window.Caixanegra.Designer = {
1288
1333
  }
1289
1334
  },
1290
1335
 
1291
- typeColor: (type) => {
1292
- switch (type) {
1293
- case "starter":
1294
- return "#65CCA9";
1295
- case "terminator":
1296
- return "#E44";
1297
- case "blackbox":
1298
- return "#EEE";
1299
- case "passthrough":
1300
- return "#c4c66a";
1301
- case "fork":
1302
- return "#ffcc5c"
1303
- case "feeder":
1304
- return "#5a92d8";
1305
- default:
1306
- return "#FFF";
1336
+ typeColor: (unit) => {
1337
+ let baseColor = unit.color || undefined;
1338
+
1339
+ if (baseColor === undefined) {
1340
+ switch (unit.type) {
1341
+ case "starter":
1342
+ baseColor = "#65CCA9";
1343
+ break;
1344
+ case "terminator":
1345
+ baseColor = "#E44";
1346
+ break;
1347
+ case "blackbox":
1348
+ baseColor = "#EEE";
1349
+ break;
1350
+ case "passthrough":
1351
+ baseColor = "#C4C66A";
1352
+ break;
1353
+ case "fork":
1354
+ baseColor = "#FFCC5C"
1355
+ break;
1356
+ case "feeder":
1357
+ baseColor = "#5A92D8";
1358
+ break;
1359
+ default:
1360
+ baseColor = "#F00";
1361
+ break;
1362
+ }
1363
+ }
1364
+
1365
+ hex = baseColor.replace("#", "");
1366
+
1367
+ if (hex.length === 3) {
1368
+ hex = hex[0] + hex[0] + hex[1] + hex[1] + hex[2] + hex[2];
1307
1369
  }
1370
+
1371
+ const r = parseInt(hex.substring(0, 2), 16);
1372
+ const g = parseInt(hex.substring(2, 4), 16);
1373
+ const b = parseInt(hex.substring(4, 6), 16);
1374
+
1375
+ const luminance = (0.2126 * r + 0.7152 * g + 0.0722 * b) / 255;
1376
+
1377
+ return {
1378
+ background: { r, g, b },
1379
+ foreground: luminance > 0.5 ? { r: 0, g: 0, b: 0 } : { r: 255, g: 255, b: 255 }
1380
+ };
1308
1381
  }
1309
1382
  }
1310
1383
 
@@ -597,6 +597,9 @@ $accent-contrast-color: darken($accent-color, 20%);
597
597
 
598
598
  .unit-input {
599
599
  .unit-input-value {
600
+ display: flex;
601
+ justify-content: center;
602
+
600
603
  &.-disabled {
601
604
  display: none;
602
605
 
@@ -604,6 +607,18 @@ $accent-contrast-color: darken($accent-color, 20%);
604
607
  pointer-events: none;
605
608
  }
606
609
  }
610
+
611
+ .radio-group {
612
+ display: flex;
613
+
614
+ &:first-child {
615
+ margin-right: 20px;
616
+ }
617
+
618
+ input, label {
619
+ display: inline;
620
+ }
621
+ }
607
622
  }
608
623
  }
609
624
 
@@ -24,7 +24,8 @@ module Caixanegra
24
24
  class: k,
25
25
  exits: v.exits&.map { |e| { name: e } },
26
26
  inputs: v.inputs,
27
- assignments: v.assignments
27
+ assignments: v.assignments,
28
+ color: v.color
28
29
  }
29
30
 
30
31
  base[:set] = v.set if base[:set]
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Caixanegra
4
4
  self.mattr_accessor :units
5
- self.mattr_accessor :redis
5
+ self.mattr_accessor :transient_store
6
6
  self.units = []
7
7
 
8
8
  def self.setup(&block)
@@ -1,7 +1,23 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Caixanegra
4
- class UnitScopedException < StandardError; end
5
- class UnitIOException < StandardError; end
4
+ class UnitScopedException < StandardError
5
+ attr_reader :unit
6
+
7
+ def initialize(exception, unit)
8
+ @unit = unit
9
+ super(exception.message)
10
+ end
11
+ end
12
+
13
+ class UnitIOException < StandardError
14
+ attr_reader :unit
15
+
16
+ def initialize(unit)
17
+ @unit = unit
18
+ super
19
+ end
20
+ end
21
+
6
22
  class ContinuityException < StandardError; end
7
23
  end
@@ -29,9 +29,9 @@ module Caixanegra
29
29
  log_console_entry 'Started'
30
30
  set_start_unit
31
31
  format_result(flow_through)
32
- rescue Caixanegra::UnitScopedException => e
32
+ rescue Caixanegra::UnitScopedException, Caixanegra::UnitIOException => e
33
33
  log_step_exception(e)
34
- log_console_entry("Unit error: #{e.message}")
34
+ log_console_entry("Unit '#{e.unit.oid}' error: #{e.message}")
35
35
  format_result(e.message)
36
36
  rescue => e
37
37
  log_console_entry("Error: #{e.message}")
@@ -107,7 +107,7 @@ module Caixanegra
107
107
  @storage.merge! @step_unit.current_storage
108
108
  result
109
109
  rescue => e
110
- exception = Caixanegra::UnitScopedException.new(e)
110
+ exception = Caixanegra::UnitScopedException.new(e, @step_unit)
111
111
  exception.set_backtrace(e.backtrace)
112
112
  raise exception
113
113
  end
@@ -4,28 +4,20 @@ module Caixanegra
4
4
  class Manager
5
5
  class << self
6
6
  def handler(flow_definition = {})
7
- uid = SecureRandom.uuid.gsub('-', '')
7
+ transient_store = Caixanegra.transient_store
8
+ uid = transient_store.new_uid
8
9
 
9
- Caixanegra.redis.multi do |pipeline|
10
- pipeline.hset(:caixanegra, uid, JSON.dump(flow_definition))
11
- pipeline.expire(:caixanegra, 1.hour)
12
- end
10
+ transient_store.hold(uid, flow_definition)
13
11
 
14
12
  uid
15
13
  end
16
14
 
17
- def destroy
18
- Caixanegra.redis.hdel(:caixanegra, key)
19
- end
20
-
21
15
  def get(uid)
22
- value = Caixanegra.redis.hget(:caixanegra, uid)
23
-
24
- JSON.parse(value) if value.present?
16
+ Caixanegra.transient_store.get(uid)
25
17
  end
26
18
 
27
19
  def set(uid, flow_definition)
28
- Caixanegra.redis.hset(:caixanegra, uid, JSON.dump(flow_definition))
20
+ Caixanegra.transient_store.hold(uid, definition: flow_definition)
29
21
  end
30
22
  end
31
23
  end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Caixanegra
4
+ class TransientStore
5
+ def get(uid)
6
+ raise NotImplementedError, "Transient Store needs to implement 'get(uid)'"
7
+ end
8
+
9
+ def hold(uid, definition: {})
10
+ raise NotImplementedError, "Transient Store needs to implement 'hold(uid, definition: {})'"
11
+ end
12
+
13
+ def new_uid
14
+ raise NotImplementedError, "Transient Store needs to implement 'new_uid'"
15
+ end
16
+ end
17
+ end
@@ -73,7 +73,7 @@ module Caixanegra
73
73
 
74
74
  input_value.presence || @inputs[id][:default]
75
75
  rescue StandardError
76
- raise(UnitIOException.new, "Unable to fetch input '#{id}'")
76
+ raise(UnitIOException.new(self), "Unable to fetch input '#{id}'")
77
77
  end
78
78
 
79
79
  def scope
@@ -100,6 +100,10 @@ module Caixanegra
100
100
  self.class.set || []
101
101
  end
102
102
 
103
+ def color
104
+ self.class.color
105
+ end
106
+
103
107
  private
104
108
 
105
109
  def set_mapping_defaults
@@ -112,7 +116,16 @@ module Caixanegra
112
116
  end
113
117
 
114
118
  class << self
115
- attr_reader :unit_name, :description, :inputs, :exits, :assignments, :type, :scope
119
+ attr_reader(
120
+ :unit_name,
121
+ :description,
122
+ :inputs,
123
+ :exits,
124
+ :assignments,
125
+ :type,
126
+ :scope,
127
+ :color
128
+ )
116
129
 
117
130
  @type = :passthrough
118
131
 
@@ -143,6 +156,10 @@ module Caixanegra
143
156
  def configure_assignments(assignments)
144
157
  @assignments = assignments
145
158
  end
159
+
160
+ def configure_color(color)
161
+ @color = color
162
+ end
146
163
  end
147
164
  end
148
165
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Caixanegra
4
- VERSION = '0.2.0'
4
+ VERSION = '0.3.1'
5
5
  end
data/lib/caixanegra.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'caixanegra/exceptions'
4
+ require 'caixanegra/unit'
4
5
  require 'caixanegra/unit_helper'
5
6
  require 'caixanegra/engine'
6
7
  require 'caixanegra/version'
7
8
  require 'caixanegra/executor'
8
9
  require 'caixanegra/manager'
10
+ require 'caixanegra/transient_store'
9
11
 
10
12
  module Caixanegra ; end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: caixanegra
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - sergiorribeiro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-06-27 00:00:00.000000000 Z
11
+ date: 2023-09-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -61,7 +61,6 @@ files:
61
61
  - app/controllers/caixanegra/api_controller.rb
62
62
  - app/controllers/caixanegra/application_controller.rb
63
63
  - app/controllers/caixanegra/designer_controller.rb
64
- - app/models/caixanegra/unit.rb
65
64
  - app/views/caixanegra/designer/index.html.erb
66
65
  - app/views/layouts/caixanegra/application.html.erb
67
66
  - app/views/shared/caixanegra/_js_dependencies.html.erb
@@ -71,6 +70,8 @@ files:
71
70
  - lib/caixanegra/exceptions.rb
72
71
  - lib/caixanegra/executor.rb
73
72
  - lib/caixanegra/manager.rb
73
+ - lib/caixanegra/transient_store.rb
74
+ - lib/caixanegra/unit.rb
74
75
  - lib/caixanegra/unit_helper.rb
75
76
  - lib/caixanegra/version.rb
76
77
  - lib/tasks/caixanegra_tasks.rake