caixanegra 0.4.0 → 0.4.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: 002efa6f5c1a220426d102e5f055b50eff9fb55e5742d6c2c33d6474f890fd8a
4
- data.tar.gz: 03c265dbfa950af4d043bfc56711593b2cb1661f76fc2ca40327fbc7a7f5e309
3
+ metadata.gz: 182cc119673359db756adcca903e137025ed5283bdae367d7d6c662fc5fdc061
4
+ data.tar.gz: f075d702d2f361678a7775d286cb7f3b9ec1cb556778b22c4180588efe32d830
5
5
  SHA512:
6
- metadata.gz: da48c854b8646515af968b7c685cece267a5bed236f1f58d5331de39a2d75bded3f0896b84d09de7cbe70c0fad7f388ef5891684bc04f45995e0b1afdc9d1784
7
- data.tar.gz: 28b98d23640368db0f32475c4cd6209fb39648e723e63d70ae2fd814e88c05ca6c9033dccc1accfa3c2c331413569fb54e1b52f115cc26841703019dec4fa0a2
6
+ metadata.gz: 29c0edd8fab4949cab99f6d513b987cda6c87b2fb29fbeb33e447616ff580c0a9fbd3413a2fe4281828f28a8ac1123942fcecbdbeedf7511c64cb000384bd797
7
+ data.tar.gz: 23e9e398d71b3900759d8a944f20ddf1920ac1f38bb5961d3e36a34d112e36a488301d3c4709de8c9cfc48a8a9f995869ebfea90ed20acf72915b6c61ac48345
@@ -66,4 +66,20 @@ window.Caixanegra.API = class {
66
66
  request.send(JSON.stringify(initialCarryOver));
67
67
  });
68
68
  }
69
+
70
+ evaluateRegex(expression, sample) {
71
+ return new Promise((resolve, reject) => {
72
+ const request = new XMLHttpRequest();
73
+
74
+ request.addEventListener("load", (event) => {
75
+ resolve(JSON.parse(event.target.response));
76
+ });
77
+ request.addEventListener("error", () => {
78
+ reject();
79
+ });
80
+
81
+ request.open("GET", `${this.mountedPath()}/api/designer/inputs/evaluate_regex?expression=${encodeURIComponent(expression)}&sample=${encodeURIComponent(sample)}`);
82
+ request.send();
83
+ });
84
+ }
69
85
  }
@@ -307,6 +307,11 @@ window.Caixanegra.Designer = {
307
307
  document.querySelector("#importFlow").addEventListener("click", this.#importFlow.bind(this));
308
308
  document.querySelector("#exportFlow").addEventListener("click", this.#exportFlow.bind(this));
309
309
  document.querySelector("#importFlowFile").addEventListener("change", this.#importFlowFileChanged.bind(this));
310
+ document.querySelector("#regexInput").addEventListener("keyup", this.#updateRegexInput.bind(this));
311
+ document.querySelector("#regexSample").addEventListener("keyup", this.#startRegexEvaluation.bind(this));
312
+ document.querySelector("#addRegexVariables").addEventListener("click", this.#addRegexVariablesRow.bind(this))
313
+ document.querySelector("#regexEditorToggleVars").addEventListener("click", this.#toggleRegexVariables.bind(this));
314
+ document.querySelector("#dismissRegexEditor").addEventListener("click", this.#dismissRegexEditor.bind(this));
310
315
  this.toggleBlocker(true, "loading your flow");
311
316
  window.addEventListener("resize", this.#windowResized.bind(drawingSurface));
312
317
  drawingSurface.addEventListener("update_start", this.#engineUpdate.bind(this));
@@ -319,7 +324,6 @@ window.Caixanegra.Designer = {
319
324
 
320
325
  this.gre.disable();
321
326
  this.getUnits();
322
- this.loadFlow();
323
327
  this.gre.enable();
324
328
  }
325
329
 
@@ -600,7 +604,7 @@ window.Caixanegra.Designer = {
600
604
  });
601
605
 
602
606
  this.#loadedComponents.catalog = true;
603
- this.reveal();
607
+ this.loadFlow();
604
608
  });
605
609
  }
606
610
 
@@ -620,6 +624,10 @@ window.Caixanegra.Designer = {
620
624
  this.#units = [];
621
625
 
622
626
  (flowData?.units || []).forEach((unit) => {
627
+ const catalogUnit = this.#catalog.find((cUnit) => cUnit.class === unit.class);
628
+ if (catalogUnit) {
629
+ unit.color = catalogUnit.color;
630
+ }
623
631
  this.createUnit(unit);
624
632
  });
625
633
 
@@ -1278,9 +1286,10 @@ window.Caixanegra.Designer = {
1278
1286
  case "regex":
1279
1287
  {
1280
1288
  valueInput = document.createElement("input");
1281
- if(matrix.type === "regex") { valueInput.classList.add("-monospace")}
1289
+ if(matrix.type === "regex") { valueInput.classList.add("-regex")}
1282
1290
  valueInput.value = unit.mappings[input]?.value || matrix.default || "";
1283
1291
  valueInput.addEventListener("change", this.#unitInputValueChanged.bind(this));
1292
+ valueInput.addEventListener("click", this.#regexEditor.bind(this));
1284
1293
  }
1285
1294
  break;
1286
1295
  case "dataset":
@@ -1380,6 +1389,125 @@ window.Caixanegra.Designer = {
1380
1389
  this.selectedUnit.mappings[input].value = ev.target.value;
1381
1390
  }
1382
1391
 
1392
+ #toggleRegexVariables() {
1393
+ const target = document.querySelector("#blocker .regexEditor > div:last-child");
1394
+ if(target.classList.contains("-visible")) {
1395
+ target.classList.remove("-visible");
1396
+ } else {
1397
+ target.classList.add("-visible");
1398
+ }
1399
+ }
1400
+
1401
+ #updateRegexInput() {
1402
+ this.blocker.editorListener.value = this.blocker.querySelector("#regexInput").value;
1403
+
1404
+ this.#startRegexEvaluation();
1405
+ }
1406
+
1407
+ #startRegexEvaluation() {
1408
+ window.clearTimeout(this.blocker.evalTimeout);
1409
+ this.blocker.querySelector("#regexResults").innerHTML = "wating input end...";
1410
+ this.blocker.evalTimeout = window.setTimeout(this.#evaluateRegex.bind(this), 1500);
1411
+ }
1412
+
1413
+ #evaluateRegex() {
1414
+ this.blocker.querySelector("#regexResults").innerHTML = "evaluating...";
1415
+ let expression = this.blocker.querySelector("#regexInput").value;
1416
+ const sample = this.blocker.querySelector("#regexSample").value;
1417
+ document.querySelectorAll("#regexVariablesList .regex-variable-entry").forEach((pair) => {
1418
+ const placeholder = pair.querySelector("input.placeholder").value;
1419
+ const value = pair.querySelector("input.value").value;
1420
+ expression = expression.replace(new RegExp(placeholder, "g"), value);
1421
+ });
1422
+
1423
+ this.api.evaluateRegex(expression, sample).then((response) => {
1424
+ const tableEntries = Object.keys(response).length - 2 > 0;
1425
+
1426
+ this.blocker.querySelector("#regexResults").innerHTML = "";
1427
+ const expression = document.createElement("div");
1428
+ const full_match = document.createElement("div");
1429
+ expression.innerHTML = `<strong>Expression: </strong><code>${response["_expression"] || "unable to get expression"}</code>`;
1430
+ full_match.innerHTML = `<strong>Full Match: </strong><code>${response["_full"] || "unable to get full match"}</code>`;
1431
+
1432
+ this.blocker.querySelector("#regexResults").append(expression, full_match);
1433
+
1434
+ if (tableEntries) {
1435
+ const table = document.createElement("table");
1436
+ let tr = document.createElement("tr");
1437
+ let th = document.createElement("th");
1438
+ th.innerHTML = "capture";
1439
+ tr.append(th);
1440
+ th = document.createElement("th");
1441
+ th.innerHTML = "match";
1442
+ tr.append(th);
1443
+ table.append(tr);
1444
+
1445
+ for (const key of Object.keys(response)) {
1446
+ if (key.startsWith("_")) { continue; }
1447
+
1448
+ tr = document.createElement("tr");
1449
+ let td = document.createElement("td");
1450
+ td.innerHTML = key;
1451
+ tr.append(td);
1452
+ td = document.createElement("td");
1453
+ td.innerHTML = response[key];
1454
+ tr.append(td);
1455
+
1456
+ table.append(tr);
1457
+ }
1458
+
1459
+ this.blocker.querySelector("#regexResults").append(table);
1460
+ }
1461
+ }).catch((error) => {
1462
+ this.blocker.querySelector("#regexResults").innerHTML = "unable to evaluate";
1463
+ });
1464
+ }
1465
+
1466
+ #regexEditor(ev) {
1467
+ this.blocker.classList.add("-in-regex-editor");
1468
+ this.blocker.classList.remove("-released");
1469
+ this.blocker.editorListener = ev.target;
1470
+ this.blocker.querySelector("#regexInput").value = ev.target.value;
1471
+
1472
+ this.#startRegexEvaluation();
1473
+ }
1474
+
1475
+ #dismissRegexEditor() {
1476
+ this.blocker.classList.remove("-in-regex-editor");
1477
+ this.blocker.classList.add("-released");
1478
+ }
1479
+
1480
+ #removeRegexVariable() {
1481
+ this.parentElement.remove();
1482
+ }
1483
+
1484
+ #addRegexVariablesRow() {
1485
+ const list = document.querySelector("#regexVariablesList");
1486
+
1487
+ const wrapper = document.createElement("div");
1488
+ const name = document.createElement("input");
1489
+ const value = document.createElement("input");
1490
+ const remove = document.createElement("button");
1491
+
1492
+ name.placeholder = "placeholder";
1493
+ name.classList.add("placeholder");
1494
+ value.classList.add("value");
1495
+ name.autocomplete=false;
1496
+ value.autocomplete=false;
1497
+ value.placeholder = "value";
1498
+ remove.innerHTML = "-";
1499
+
1500
+ remove.addEventListener("click", this.#removeRegexVariable.bind(remove));
1501
+
1502
+ name.addEventListener("keyup", this.#startRegexEvaluation.bind(this));
1503
+ value.addEventListener("keyup", this.#startRegexEvaluation.bind(this));
1504
+
1505
+ wrapper.classList.add("regex-variable-entry");
1506
+
1507
+ wrapper.append(name, value, remove);
1508
+ list.append(wrapper);
1509
+ }
1510
+
1383
1511
  #addUnitExitMapping(ev) {
1384
1512
  const unit = this.selectedUnit;
1385
1513
  const mapping = { use: "", as: "" };
@@ -538,6 +538,7 @@ $accent-contrast-color: darken($accent-color, 20%);
538
538
  }
539
539
 
540
540
  input {
541
+ position: relative;
541
542
  width: 100%;
542
543
  box-sizing: border-box;
543
544
  background-color: $accent-highlight-color;
@@ -545,7 +546,7 @@ $accent-contrast-color: darken($accent-color, 20%);
545
546
  border: none;
546
547
  outline: none;
547
548
 
548
- &.-monospace {
549
+ &.-regex {
549
550
  font-family: monospace;
550
551
  }
551
552
  }
@@ -790,7 +791,7 @@ $accent-contrast-color: darken($accent-color, 20%);
790
791
  left:0;
791
792
  right:0;
792
793
  bottom:0;
793
- background-color: rgb(0,0,0);
794
+ background-color: rgba(0,0,0, .5);
794
795
  transition: opacity 250ms ease-in-out;
795
796
  opacity: 1;
796
797
 
@@ -817,6 +818,155 @@ $accent-contrast-color: darken($accent-color, 20%);
817
818
  }
818
819
  }
819
820
 
821
+ .regexEditor {
822
+ position: absolute;
823
+ top: 50%;
824
+ left: 50%;
825
+ transform: translate(-50%, -50%);
826
+ display: none;
827
+ font-family: Verdana, Geneva, Tahoma, sans-serif;
828
+ min-width: 70%;
829
+ flex-direction: row;
830
+ align-items: center;
831
+ justify-content: center;
832
+
833
+ & > div {
834
+ background-color: $accent-color;
835
+ box-shadow: $accent-shadow;
836
+ border-radius: 5px;
837
+ display: flex;
838
+ flex-direction: column;
839
+ padding: 12px;
840
+ position: relative;
841
+ font-size: 16px;
842
+
843
+ &:first-child {
844
+ margin-right: 15px;
845
+ width: 70%;
846
+ z-index: 10;
847
+ font-size: 0.8em;
848
+ }
849
+
850
+ &:last-child {
851
+ font-size: 0.8em;
852
+ transform: translateX(-200%);
853
+ width: 0;
854
+ box-shadow: 0 0 0 rgba(0,0,0,0);
855
+ z-index: 9;
856
+ overflow: hidden;
857
+ transition: all 250ms ease-in-out;
858
+
859
+ &.-visible {
860
+ transform: translateX(0%);
861
+ width: 30%;
862
+ }
863
+ }
864
+ }
865
+
866
+ label {
867
+ margin-bottom: 4px;
868
+ }
869
+
870
+ input {
871
+ margin-bottom: 6px;
872
+ box-sizing: border-box;
873
+ background-color: #9c9c9c;
874
+ padding: 6px 4px;
875
+ border: none;
876
+ outline: none;
877
+ }
878
+
879
+ #regexInput {
880
+ font-family: monospace;
881
+ font-size: 1.1em;
882
+ }
883
+
884
+ #regexSample {
885
+ font-size: 0.8em;
886
+ }
887
+
888
+ #regexResults {
889
+ padding: 8px;
890
+ background-color:rgb(200, 200, 200);
891
+ color: black;
892
+ max-height: 50vh;
893
+ overflow: auto;
894
+ display: block;
895
+ margin-bottom: 30px;
896
+ font-size: 0.7em;
897
+
898
+ table {
899
+ margin-top: 15px;
900
+ width: 100%;
901
+ border-collapse: collapse;
902
+
903
+ th, td {
904
+ text-align: left;
905
+ border: 1px solid rgba(0,0,0,.3);
906
+ padding: 4px;
907
+ }
908
+
909
+ tr:nth-child(even) {
910
+ background-color: rgba(0,0,0,.15);
911
+ }
912
+ }
913
+ }
914
+
915
+ #regexVariables {
916
+ #regexVariablesList {
917
+ margin-bottom: 15px;
918
+ }
919
+
920
+ .regex-variable-entry {
921
+ display: flex;
922
+ flex-direction: row;
923
+ margin: 2px 0;
924
+ align-items: center;
925
+
926
+ input {
927
+ width: 100%;
928
+ margin-bottom: 0;
929
+
930
+ &:first-child {
931
+ margin-right: 5px;
932
+ }
933
+ }
934
+
935
+ button {
936
+ margin-left: 5px;
937
+ }
938
+ }
939
+ }
940
+
941
+ button {
942
+ background-color: $accent-highlight-color;
943
+ border: 1px solid $accent-color;
944
+ color: black;
945
+ padding: 3px 6px;
946
+ cursor: pointer;
947
+ transition: all 250ms ease-in-out;
948
+
949
+ &:hover {
950
+ background-color: $accent-contrast-color;
951
+ color: $accent-highlight-color;
952
+ }
953
+ }
954
+
955
+ #regexEditorToggleVars {
956
+ float: right;
957
+ }
958
+ }
959
+
960
+ &.-in-regex-editor {
961
+ .information {
962
+ display: none;
963
+ }
964
+
965
+ .regexEditor {
966
+ display: flex;
967
+ }
968
+ }
969
+
820
970
  &.-released {
821
971
  pointer-events: none;
822
972
  opacity: 0;
@@ -0,0 +1,32 @@
1
+ module Caixanegra
2
+ module API
3
+ module Designer
4
+ class InputsController < ::Caixanegra::APIController
5
+ def evaluate_regex
6
+ full_match = sample.match(Regexp.new(expression, Regexp::IGNORECASE))
7
+ direct = { "_full": full_match.to_s, "_expression": expression }
8
+ captures = {}
9
+
10
+ (full_match&.captures || []).each_with_index do |capture, index|
11
+ captures["c#{index}"] = capture
12
+ end
13
+ named_captures = full_match&.named_captures || {}
14
+
15
+ render json: direct.merge(captures).merge(named_captures).symbolize_keys
16
+ rescue RegexpError
17
+ head 422
18
+ end
19
+
20
+ private
21
+
22
+ def expression
23
+ @expression ||= params[:expression]
24
+ end
25
+
26
+ def sample
27
+ @sample ||= params[:sample]
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -108,6 +108,27 @@
108
108
  <div>caixa<span>negra</span></div>
109
109
  <div class="message">loading your flow</div>
110
110
  </div>
111
+ <div class="regexEditor">
112
+ <div>
113
+ <label for="regexInput">Regular Expression</label>
114
+ <input id="regexInput" type="text" />
115
+ <label for="regexSample" placeholder="type sample text here">Sample</label>
116
+ <input id="regexSample" type="text" />
117
+ <label for="regexResults">Result</label>
118
+ <div id="regexResults"></div>
119
+ <div>
120
+ <button id="dismissRegexEditor">dismiss</button>
121
+ <button id="regexEditorToggleVars">vars</button>
122
+ </div>
123
+ </div>
124
+ <div>
125
+ <label for="regexVariables">Variables</label>
126
+ <div id="regexVariables">
127
+ <div id="regexVariablesList"></div>
128
+ <button id="addRegexVariables">add</button>
129
+ </div>
130
+ </div>
131
+ </div>
111
132
  </div>
112
133
  <div id="action_messenger">
113
134
  <div class="icon icon-error">
data/config/routes.rb CHANGED
@@ -9,6 +9,9 @@ Caixanegra::Engine.routes.draw do
9
9
  patch :debug_run
10
10
  end
11
11
  end
12
+ namespace :inputs do
13
+ get :evaluate_regex
14
+ end
12
15
  end
13
16
  end
14
17
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Caixanegra
4
- VERSION = '0.4.0'
4
+ VERSION = '0.4.1'
5
5
  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.4.0
4
+ version: 0.4.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-10-04 00:00:00.000000000 Z
11
+ date: 2023-10-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -57,6 +57,7 @@ files:
57
57
  - app/assets/stylesheets/caixanegra/application.css
58
58
  - app/assets/stylesheets/caixanegra/designer.scss
59
59
  - app/controllers/caixanegra/api/designer/flows_controller.rb
60
+ - app/controllers/caixanegra/api/designer/inputs_controller.rb
60
61
  - app/controllers/caixanegra/api/designer/units_controller.rb
61
62
  - app/controllers/caixanegra/api_controller.rb
62
63
  - app/controllers/caixanegra/application_controller.rb