caixanegra 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4296a7a3ef7cd55657a83b6fd6f4cf9389c8ba731a539191a6e6c16e853b6848
4
- data.tar.gz: 8805ae26d4cbb6a37c98a22b5fba5b11a3f14a88de9fa685d313bfc58d22e4ed
3
+ metadata.gz: c291dfc1c33d2c17e87093eff1bceff3c061ef8c7230a561ace088cd9e23f279
4
+ data.tar.gz: e812c3f4c1d202902f926115162c0b9b46885b35af56db52db3aa94ab8e53ac8
5
5
  SHA512:
6
- metadata.gz: c866e8d7614824e7a82bd8fe26dc0a434be293a6e317142169724c24a00f5c60b7e4ff804836053a0f75a865f6df1943464ae5c5dbfad8c2500ce31ea820b306
7
- data.tar.gz: 0d12dc642122961304bb47ec2840560e6da603f83c575b8e3e0604e5527743a54ce43c950ca372763018658da8f9a9ba2a06e88da6a31bb62bb18e45e128e7e3
6
+ metadata.gz: c6276bd14d36c832729b8a717a15ad5a8c6b9e6223343d6169fa1c153dc0389d0d0ef73ed61b0eb4f19a9dfc1936683b59b80e994b740df4cc670958fbc21833
7
+ data.tar.gz: 70059940599beff0f5cf09bbb73defa53fc31e336166a15a0262902f194862cd318b5bb8fb7bcb22a7934960411c7dce14f997816a0430fc943ba6d0dceddb88
data/README.md CHANGED
@@ -51,7 +51,7 @@ uid = Caixanegra::Manager.handler(my_flow || {})
51
51
  You can then safely navigate to the designer.
52
52
 
53
53
  ```ruby
54
- link_to "Some flow", "/caixanegra/design/#{@uid}?unit_scope=optional_scope", target: :blank
54
+ link_to "Some flow", "/caixanegra/design/#{@uid}?unit_scope=optional_scope,another_optional_scope", target: :_blank
55
55
  ```
56
56
 
57
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:
@@ -63,7 +63,7 @@ persist_flow(updated_flow) # your own persistence or transport solution. It's a
63
63
 
64
64
  **NOTE:** There's currently no managed way to set callbacks on save actions from the designer. Working on it
65
65
 
66
- Please, refer to [the wiki](https://github.com/sergiorribeiro/caixanegra/wiki) to get to know more about [creating your units](https://github.com/sergiorribeiro/caixanegra/wiki/Creating-units).
66
+ 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
67
 
68
68
  # License
69
69
  **caixanegra** is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -166,9 +166,9 @@ window.Caixanegra.Designer = {
166
166
  ctx.beginPath();
167
167
  ctx.moveTo(this.#drawValues.position.x + this.size.x, exit.markerY);
168
168
  ctx.lineTo(this.#drawValues.position.x + this.size.x + 25, exit.markerY);
169
-
169
+
170
170
  if (this.connectingExit === exit && context.mouse.move) {
171
- ctx.lineTo(context.mouse.move.x, context.mouse.move.y);
171
+ ctx.lineTo(context.mouse.move.x + context.referential.x, context.mouse.move.y + context.referential.y);
172
172
  } else if (exit.reference.target) {
173
173
  const targetCenter = exit.reference.target.getCenter(context.referential);
174
174
  ctx.lineTo(targetCenter.x, targetCenter.y);
@@ -382,10 +382,10 @@ window.Caixanegra.Designer = {
382
382
  }
383
383
 
384
384
  deleteUnit() {
385
- this.removeUnit(this.selectedUnit.oid);
386
- this.toggleDeleteConfirmation();
387
385
  this.unitDetailPane.classList.remove("-open");
388
386
  this.unitDebugHitsPane.classList.remove("-open");
387
+ this.removeUnit(this.selectedUnit.oid);
388
+ this.toggleDeleteConfirmation();
389
389
  }
390
390
 
391
391
  flushToConsole(entries) {
@@ -522,33 +522,63 @@ window.Caixanegra.Designer = {
522
522
  this.#catalog = response;
523
523
  const unitMenu = document.querySelector("#unitMenu");
524
524
  unitMenu.innerHTML = "";
525
- this.#catalog.forEach((unitData) => {
526
- const item = document.createElement("div");
527
- const content = document.createElement("div");
528
- const colorCode = document.createElement("div");
529
- const header = document.createElement("div");
530
- const name = document.createElement("span");
531
- const type = document.createElement("span");
532
- const description = document.createElement("div");
533
- description.classList.add("description");
534
- item.classList.add("unit");
535
- header.classList.add("header");
536
- content.classList.add("content");
537
- colorCode.classList.add("color-code");
538
- name.classList.add("name");
539
- type.classList.add("type");
540
-
541
- name.innerHTML = unitData.title;
542
- type.innerHTML = unitData.type;
543
- description.innerHTML = unitData.description;
544
- colorCode.style.backgroundColor = Caixanegra.Designer.typeColor(unitData.type);
545
-
546
- header.append(name, type);
547
- content.append(header, description);
548
- item.append(colorCode, content);
549
- item.addEventListener("click", this.createUnit.bind(this, unitData));
550
- unitMenu.appendChild(item);
525
+
526
+ const scopes = [];
527
+
528
+ this.#catalog.forEach(unit => {
529
+ if (unit.hasOwnProperty("scope") && Array.isArray(unit.scope)) {
530
+ scopes.push(...unit.scope);
531
+ } else {
532
+ scopes.push("_unscoped");
533
+ }
534
+ });
535
+
536
+ [...new Set(scopes)].sort().forEach(scope => {
537
+ const scopeWrapper = document.createElement("div");
538
+ const scopeTitle = document.createElement("div");
539
+ const scopeUnits = document.createElement("div");
540
+
541
+ scopeWrapper.classList.add("unit-wrapper");
542
+ scopeTitle.classList.add("title");
543
+
544
+ scopeTitle.innerHTML = scope === "_unscoped" ? "unscoped" : scope.replace(/_/g, " ");
545
+ scopeWrapper.appendChild(scopeTitle);
546
+ scopeWrapper.appendChild(scopeUnits);
547
+
548
+ const filteredUnits = this.#catalog.filter(unit => {
549
+ return (unit.scope === null && scope === "_unscoped") || (unit.scope || []).includes(scope)
550
+ });
551
+
552
+ filteredUnits.forEach((unitData) => {
553
+ const item = document.createElement("div");
554
+ const content = document.createElement("div");
555
+ const colorCode = document.createElement("div");
556
+ const header = document.createElement("div");
557
+ const name = document.createElement("span");
558
+ const type = document.createElement("span");
559
+ const description = document.createElement("div");
560
+ description.classList.add("description");
561
+ item.classList.add("unit");
562
+ header.classList.add("header");
563
+ content.classList.add("content");
564
+ colorCode.classList.add("color-code");
565
+ name.classList.add("name");
566
+ type.classList.add("type");
567
+
568
+ name.innerHTML = unitData.title;
569
+ type.innerHTML = unitData.type;
570
+ description.innerHTML = unitData.description;
571
+ colorCode.style.backgroundColor = Caixanegra.Designer.typeColor(unitData.type);
572
+
573
+ header.append(name, type);
574
+ content.append(header, description);
575
+ item.append(colorCode, content);
576
+ item.addEventListener("click", this.createUnit.bind(this, unitData));
577
+ scopeUnits.appendChild(item);
578
+ });
579
+ unitMenu.appendChild(scopeWrapper);
551
580
  });
581
+
552
582
  this.#loadedComponents.catalog = true;
553
583
  this.#reveal();
554
584
  });
@@ -119,6 +119,15 @@ $accent-contrast-color: darken($accent-color, 20%);
119
119
  transform: translateY(0%);
120
120
  }
121
121
 
122
+ .unit-wrapper {
123
+ .title {
124
+ font-family: Verdana, Geneva, Tahoma, sans-serif;
125
+ font-size: 0.7em;
126
+ color: rgba(0,0,0,.7);
127
+ margin-bottom: 5px;
128
+ }
129
+ }
130
+
122
131
  .unit {
123
132
  display: flex;
124
133
  flex-direction: row;
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Caixanegra
4
- module API
4
+ module Api
5
5
  module Designer
6
- class FlowsController < ::Caixanegra::APIController
6
+ class FlowsController < ::Caixanegra::ApiController
7
7
  before_action :set_flow, only: %i[show debug_run]
8
8
 
9
9
  def show
@@ -20,7 +20,6 @@ module Caixanegra
20
20
  execution = Caixanegra::Executor.new(
21
21
  initial_carryover: initial_carryover,
22
22
  flow_definition: @flow,
23
- unit_scope: params[:unit_scope],
24
23
  debug_mode: true
25
24
  ).run
26
25
 
@@ -1,9 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Caixanegra
4
- module API
4
+ module Api
5
5
  module Designer
6
- class UnitsController < ::Caixanegra::APIController
6
+ class UnitsController < ::Caixanegra::ApiController
7
7
  def index
8
8
  render json: units
9
9
  end
@@ -15,26 +15,21 @@ module Caixanegra
15
15
  end
16
16
 
17
17
  def units
18
- @units ||= begin
19
- base_units = Caixanegra.units.reject { |_, v| v.is_a? Hash }
20
- scope_units = Caixanegra.units[unit_scope] if unit_scope.present?
21
- all_units = base_units.merge(scope_units || {})
18
+ @units ||= ::Caixanegra::UnitHelper.scoped_units(unit_scope).map do |k, v|
19
+ base = {
20
+ scope: v.scope,
21
+ title: v.unit_name,
22
+ type: v.type,
23
+ description: v.description,
24
+ class: k,
25
+ exits: v.exits&.map { |e| { name: e } },
26
+ inputs: v.inputs,
27
+ assignments: v.assignments
28
+ }
22
29
 
23
- all_units.map do |k, v|
24
- base = {
25
- title: v.name,
26
- type: v.type,
27
- description: v.description,
28
- class: k,
29
- exits: v.exits&.map { |e| { name: e } },
30
- inputs: v.inputs,
31
- assignments: v.assignments
32
- }
30
+ base[:set] = v.set if base[:set]
33
31
 
34
- base[:set] = v.set if base[:set]
35
-
36
- base
37
- end
32
+ base
38
33
  end
39
34
  end
40
35
  end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Caixanegra
4
- class APIController < ActionController::API
4
+ class ApiController < ActionController::API
5
5
  end
6
6
  end
@@ -36,6 +36,12 @@ module Caixanegra
36
36
  }
37
37
  end
38
38
 
39
+ def exit_and_return
40
+ {
41
+ carry_over: @carry_over
42
+ }
43
+ end
44
+
39
45
  def flow
40
46
  exit_through exits.first
41
47
  end
@@ -64,11 +70,18 @@ module Caixanegra
64
70
 
65
71
  input_value = result
66
72
  end
73
+
67
74
  input_value.presence || @inputs[id][:default]
75
+ rescue StandardError
76
+ raise(UnitIOException.new, "Unable to fetch input '#{id}'")
77
+ end
78
+
79
+ def scope
80
+ self.class.scope
68
81
  end
69
82
 
70
- def name
71
- self.class.name
83
+ def unit_name
84
+ self.class.unit_name
72
85
  end
73
86
 
74
87
  def description
@@ -99,12 +112,16 @@ module Caixanegra
99
112
  end
100
113
 
101
114
  class << self
102
- attr_reader :name, :description, :inputs, :exits, :assignments, :type
115
+ attr_reader :unit_name, :description, :inputs, :exits, :assignments, :type, :scope
103
116
 
104
117
  @type = :passthrough
105
118
 
119
+ def configure_scope(value)
120
+ @scope = value
121
+ end
122
+
106
123
  def configure_name(value)
107
- @name = value
124
+ @unit_name = value
108
125
  end
109
126
 
110
127
  def configure_description(value)
@@ -2,4 +2,6 @@
2
2
 
3
3
  module Caixanegra
4
4
  class UnitScopedException < StandardError; end
5
+ class UnitIOException < StandardError; end
6
+ class ContinuityException < StandardError; end
5
7
  end
@@ -5,7 +5,6 @@ module Caixanegra
5
5
  def initialize(params)
6
6
  @initial_carryover = params[:initial_carryover] || {}
7
7
  @flow = (params[:flow_definition] || {}).deep_symbolize_keys
8
- @unit_scope = params[:unit_scope]
9
8
  @debug_mode = params[:debug_mode] == true
10
9
  @execution = { history: [], steps: [] }
11
10
  @storage = {}
@@ -113,6 +112,8 @@ module Caixanegra
113
112
  raise exception
114
113
  end
115
114
  next_unit = next_unit(result)
115
+ raise(ContinuityException.new, "Unable to choose a valid exit") if next_unit.nil?
116
+
116
117
  log_step_result(result, next_unit)
117
118
  @execution[:steps] += feeder_steps
118
119
  @step_unit = next_unit
@@ -143,11 +144,15 @@ module Caixanegra
143
144
  end
144
145
 
145
146
  def next_unit(result)
147
+ return nil if result.nil?
148
+
146
149
  exit_name = result[:exit_through]
147
150
  metadata = unit_metadata(@step_unit.oid)
148
- log_console_entry "Next unit found through '#{exit_name}': '#{@step_unit.oid}'"
149
151
  exit_metadata = metadata[:exits].find { |ex| ex[:name] == exit_name.to_s }
150
- unit(exit_metadata[:target], map_carry_over(result))
152
+ next_unit = unit(exit_metadata[:target], map_carry_over(result))
153
+ log_console_entry "Next unit found through '#{exit_name}': '#{next_unit.oid}'"
154
+
155
+ next_unit
151
156
  end
152
157
 
153
158
  def process_feeders
@@ -187,15 +192,13 @@ module Caixanegra
187
192
  unit_class = scoped_units[unit_data[:class].to_sym]
188
193
  inputs = unit_class.inputs
189
194
  unit_class.new(unit_data[:oid], inputs, mappings, carry_over, @storage)
195
+ rescue
196
+ log_console_entry "Unable to load unit instance of type '#{unit_data[:class]}'"
197
+ nil
190
198
  end
191
199
 
192
200
  def scoped_units
193
- @scoped_units ||= begin
194
- base_units = Caixanegra.units.reject { |_, v| v.is_a? Hash }
195
- scope_units = Caixanegra.units[@unit_scope] if @unit_scope.present?
196
-
197
- base_units.merge(scope_units || {})
198
- end
201
+ @scoped_units ||= UnitHelper.all_units
199
202
  end
200
203
  end
201
204
  end
@@ -0,0 +1,28 @@
1
+ module Caixanegra
2
+ class UnitHelper
3
+ class << self
4
+ def scoped_units(scope)
5
+ units = {}
6
+
7
+ scopes = (scope || "").split(",").map(&:to_sym)
8
+ Caixanegra.units.each do |unit|
9
+ if unit.scope.nil? || unit.scope.any? { |checking_scope| scopes.include?(checking_scope) }
10
+ units[unit.name.demodulize.underscore.to_sym] = unit
11
+ end
12
+ end
13
+
14
+ units
15
+ end
16
+
17
+ def all_units
18
+ units = {}
19
+
20
+ Caixanegra.units.each do |unit|
21
+ units[unit.name.demodulize.underscore.to_sym] = unit
22
+ end
23
+
24
+ units
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Caixanegra
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/caixanegra.rb CHANGED
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'caixanegra/exceptions'
4
+ require 'caixanegra/unit_helper'
4
5
  require 'caixanegra/engine'
5
6
  require 'caixanegra/version'
6
7
  require 'caixanegra/executor'
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.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - sergiorribeiro
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-03-30 00:00:00.000000000 Z
11
+ date: 2023-06-27 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/helpers/caixanegra/application_helper.rb
65
64
  - app/models/caixanegra/unit.rb
66
65
  - app/views/caixanegra/designer/index.html.erb
67
66
  - app/views/layouts/caixanegra/application.html.erb
@@ -72,6 +71,7 @@ files:
72
71
  - lib/caixanegra/exceptions.rb
73
72
  - lib/caixanegra/executor.rb
74
73
  - lib/caixanegra/manager.rb
74
+ - lib/caixanegra/unit_helper.rb
75
75
  - lib/caixanegra/version.rb
76
76
  - lib/tasks/caixanegra_tasks.rake
77
77
  homepage: https://github.com/sergiorribeiro/caixanegra/wiki
@@ -86,7 +86,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
86
  requirements:
87
87
  - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '0'
89
+ version: 2.7.5
90
90
  required_rubygems_version: !ruby/object:Gem::Requirement
91
91
  requirements:
92
92
  - - ">="
@@ -1,4 +0,0 @@
1
- module Caixanegra
2
- module ApplicationHelper
3
- end
4
- end