cpee 2.1.2 → 2.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (43) hide show
  1. checksums.yaml +4 -4
  2. data/cockpit/config.json +1 -1
  3. data/cockpit/css/ui.css +14 -7
  4. data/cockpit/edit.html +27 -23
  5. data/cockpit/graph.html +1 -0
  6. data/cockpit/index.html +26 -22
  7. data/cockpit/js/edit.js +8 -1
  8. data/cockpit/js/instance.js +103 -39
  9. data/cockpit/js/modifiers.js +188 -0
  10. data/cockpit/model.html +1 -8
  11. data/cockpit/themes/compact/rngs/call.rng +17 -8
  12. data/cockpit/themes/compact/rngs/callmanipulate.rng +18 -9
  13. data/cockpit/themes/compact/rngs/start.rng +9 -9
  14. data/cockpit/themes/compact/theme.js +1 -1
  15. data/cockpit/themes/control/rngs/call.rng +17 -8
  16. data/cockpit/themes/control/rngs/callmanipulate.rng +18 -9
  17. data/cockpit/themes/control/rngs/start.rng +9 -9
  18. data/cockpit/themes/default/rngs/call.rng +17 -8
  19. data/cockpit/themes/default/rngs/callmanipulate.rng +18 -9
  20. data/cockpit/themes/default/rngs/start.rng +9 -9
  21. data/cockpit/themes/extended/rngs/call.rng +17 -8
  22. data/cockpit/themes/extended/rngs/callmanipulate.rng +18 -9
  23. data/cockpit/themes/extended/rngs/start.rng +9 -9
  24. data/cockpit/themes/extended/theme.js +1 -1
  25. data/cockpit/themes/packed/rngs/call.rng +17 -8
  26. data/cockpit/themes/packed/rngs/callmanipulate.rng +18 -9
  27. data/cockpit/themes/packed/rngs/start.rng +9 -9
  28. data/cockpit/themes/packed/theme.js +1 -1
  29. data/cockpit/themes/preset/rngs/call.rng +17 -8
  30. data/cockpit/themes/preset/rngs/callmanipulate.rng +18 -9
  31. data/cockpit/themes/preset/rngs/start.rng +9 -9
  32. data/cockpit/track.html +1 -0
  33. data/cpee.gemspec +2 -2
  34. data/lib/cpee/implementation_notifications.rb +5 -5
  35. data/lib/cpee/redis.rb +13 -6
  36. data/server/routing/end.pid +1 -0
  37. data/server/routing/forward-events.pid +1 -0
  38. data/server/routing/forward-votes.pid +1 -0
  39. data/server/routing/persist.pid +1 -0
  40. data/tools/cpee +36 -8
  41. data/tools/cpee.sic +306 -0
  42. metadata +10 -5
  43. data/lib/instantiation.xml +0 -125
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 325b18f98e4911371489cf481eb0e020cb73367127313a6f16d6f9baee7a0854
4
- data.tar.gz: c4ba38576d13cf199b64f92de3c7112710dff8390b459194f605cc38946e3d1b
3
+ metadata.gz: bdfedecb98660aba343a39fb374f7d54cd535c44e2093fb6c78d2ee7a5767cb6
4
+ data.tar.gz: 3efbefd7f8230e85bbf7cc2dd79b1a62a78c9ac755eab581b5b8f23b7c99bb55
5
5
  SHA512:
6
- metadata.gz: 0dbf0ae5fdd6853c247fd608a5bb35975309453e4542183a7a9dec0438554a67e70060d72718b519e9ff4e34143869f0014589d3dfe5f32924144ac9d0157220
7
- data.tar.gz: b9e39b3aa0dde5051be9313dc4d4a25907f7f6d2299c53f7ddb95110118859e7f17fd78283a5ac1cae9e8a87f5524fcbacfb328d3e43a69ffc521109a4715748
6
+ metadata.gz: d23d6b7600162555d0ce52666c31df60534710867143a218d241cfc0cd4d764b82a1f3e10e13000936001bab2ee45cd06135a5bb93c551e88343e53e3fe2471d
7
+ data.tar.gz: 1c01c6bd32cb8697b659bcaf4fc72834d029467c37929906c0a23894e31144533d70de01cc8ab56c7226e89e2a20c6bea0c261400d735ab4450e9b2d9cfa9b8a
data/cockpit/config.json CHANGED
@@ -1,3 +1,3 @@
1
1
  {
2
- "res-url": "https://cpee.org/flow/resources/"
2
+ "res-url": "https://tango.wst.univie.ac.at/flow/resources/"
3
3
  }
data/cockpit/css/ui.css CHANGED
@@ -129,11 +129,13 @@ ui-tabbed ui-tabbar ui-behind button {
129
129
  #areaendpoints button.relaxngui_control { display: none; }
130
130
  #areaattributes button.relaxngui_control { display: none; }
131
131
 
132
+ #areainstance { height: 100%; }
133
+ #areainstance > div { display: flex; height: 100%; }
132
134
  #areainstance input[type=file] { display: none; }
133
- #areainstance div.section { display: table-cell; vertical-align: middle; }
134
- #areainstance div.section:nth-child(1) { padding: 0 0.5em 0 0; white-space: nowrap; }
135
- #areainstance div.section:nth-child(2) { border-left: 1px solid var(--x-ui-border-color); padding: 0 0.5em; white-space: nowrap; }
136
- #areainstance div.section:nth-child(3) { border-left: 1px solid var(--x-ui-border-color); padding: 0 0 0 0.5em; white-space: nowrap; }
135
+ #areainstance div.section { vertical-align: middle; height: 100%; }
136
+ #areainstance div.section:nth-child(1) { flex: 0 0 auto; padding: 0 0.5em 0 0; white-space: nowrap; }
137
+ #areainstance div.section:nth-child(2) { flex: 0 0 auto; border-left: 1px solid var(--x-ui-border-color); padding: 0 0.5em; white-space: nowrap; }
138
+ #areainstance div.section:nth-child(3) { flex: 1 1 auto; border-left: 1px solid var(--x-ui-border-color); padding: 0 0 0 0.5em; white-space: nowrap; }
137
139
 
138
140
  #areainstance div.section:nth-child(1) > div:nth-child(2) { white-space: normal; text-align: right; }
139
141
 
@@ -144,9 +146,14 @@ ui-tabbed ui-tabbar ui-behind button {
144
146
  #areainstance div.section:nth-child(1) button[name=loadtestsetfile] { white-space: normal; width: 10em; height: 3.5em; margin-left: 0.2em; }
145
147
  #areainstance div.section:nth-child(1) button[name=loadmodelfile] { white-space: normal; width: 10em; height: 2em; margin-top: 0.2em; }
146
148
 
147
- #areainstance div.section:nth-child(2) button { white-space: normal; width: 6em; height: 4.5em; vertical-align: middle; margin: 0; padding: 0; }
148
- #areainstance div.section:nth-child(3) div { white-space: normal; vertical-align: middle; margin: 0; padding: 0; }
149
- #areainstance div.section:nth-child(3) button[name=loadmodeltype] { white-space: normal; width: 10em; height: 2em; }
149
+ #areainstance div.section:nth-child(2) button { white-space: normal; width: 6em; height: 5.7em; vertical-align: middle; margin: 0; padding: 0; }
150
+
151
+ #areainstance div.section:nth-child(3) { overflow-y: scroll; }
152
+ #areainstance div.section:nth-child(3) strong { margin:0; padding:0; white-space: normal; font-size: 0.7em; }
153
+ #areainstance div.section:nth-child(3) > div:not(:first-child) { padding-top: 0.2em; }
154
+ #areainstance div.section:nth-child(3) > div { padding-bottom: 0em; }
155
+ #areainstance div.section:nth-child(3) select { margin-left: 1em; }
156
+ #areainstance div.section:nth-child(3) div.additional { margin: 0 1em; font-size: 0.9em; }
150
157
 
151
158
  #areaexecution input { padding: 0; margin:0; }
152
159
  #areaexecution table.x-ui-compact { width: 100%; }
data/cockpit/edit.html CHANGED
@@ -54,6 +54,7 @@
54
54
  <script type="text/javascript" src="js/details.js"></script>
55
55
  <script type="text/javascript" src="js/parameters.js"></script>
56
56
  <script type="text/javascript" src="js/edit.js"></script>
57
+ <script type="text/javascript" src="js/modifiers.js"></script>
57
58
  <link rel="stylesheet" href="css/ui.css" type="text/css"/>
58
59
  <link rel="stylesheet" href="/global_ui/uicpee.css" type="text/css"/>
59
60
  <style>
@@ -144,29 +145,32 @@
144
145
  </table>
145
146
  </ui-area> <!--}}}-->
146
147
  <ui-area data-belongs-to-tab="instance" id="areainstance" class="inactive"> <!--{{{-->
147
- <div class='section'>
148
- <div>
149
- <form id='fuckchrome'>
150
- <input type='file' name='testsetfile' id='testsetfile'/>
151
- </form>
152
- <button title='save a testset includes various settings, subscriptions and a model' name="save" disabled=""><div>save</div><div class="hidden" id='lastsavedline'>(last: <span id="lastsaved"></span>)</div></button>
153
- <button title='a testset includes various settings, subscriptions or a model' name="loadtestsetfile">load testset</button>
154
- </div>
155
- <div>
156
- <input type='file' name='modelfile' id='modelfile'/>
157
- <button title='a standalone process model is only loadable if the currently loaded testset sucessfully prepared the current instance for the type of model' name="loadmodelfile">load model</button>
158
- </div>
159
- </div><div class='section'>
160
- <a id="savetestsetfile" href="" download=""></a>
161
- <a id="savesvgfile" href="" download=""></a>
162
- <button title='a testset includes various settings, subscriptions and a model' name="savetestsetfile">save testset</button>
163
- <button title='a testset includes various settings, subscriptions and a model' name="savesvgfile">save svg graph</button>
164
- </div><div class='section'>
165
- <div>
166
- Current model: <span id='currentmodel'></span>
167
- </div>
168
- <div>
169
- <button title='a testset includes various settings, subscriptions and a model' name="loadmodeltype">set model type</button>
148
+ <div>
149
+ <div class='section'>
150
+ <div>
151
+ <form id='fuckchrome'>
152
+ <input type='file' name='testsetfile' id='testsetfile'/>
153
+ </form>
154
+ <button title='save a testset includes various settings, subscriptions and a model' name="save" disabled=""><div>save</div><div class="hidden" id='lastsavedline'>(last: <span id="lastsaved"></span>)</div></button>
155
+ <button title='a testset includes various settings, subscriptions or a model' name="loadtestsetfile">load testset</button>
156
+ </div>
157
+ <div>
158
+ <input type='file' name='modelfile' id='modelfile'/>
159
+ <button title='a standalone process model is only loadable if the currently loaded testset sucessfully prepared the current instance for the type of model' name="loadmodelfile">load model</button>
160
+ </div>
161
+ </div><div class='section'>
162
+ <a id="savetestsetfile" href="" download=""></a>
163
+ <a id="savesvgfile" href="" download=""></a>
164
+ <button title='a testset includes various settings, subscriptions and a model' name="savetestsetfile">save testset</button>
165
+ <button title='a testset includes various settings, subscriptions and a model' name="savesvgfile">save svg graph</button>
166
+ </div><div class='section' id='modifiers'>
167
+ <template id="item">
168
+ <div>
169
+ <div class='title'><strong></strong></div>
170
+ <div class='select'><select></select></div>
171
+ <div class='additional'></div>
172
+ </div>
173
+ </template>
170
174
  </div>
171
175
  </div>
172
176
  </ui-area> <!--}}}-->
data/cockpit/graph.html CHANGED
@@ -54,6 +54,7 @@
54
54
  <script type="text/javascript" src="js/instance.js"></script>
55
55
  <script type="text/javascript" src="js/details.js"></script>
56
56
  <script type="text/javascript" src="js/parameters.js"></script>
57
+ <script type="text/javascript" src="js/modifiers.js"></script>
57
58
  <link rel="stylesheet" href="css/ui.css" type="text/css"/>
58
59
  </head>
59
60
  <body data-base-port="8298" data-res-port="9303" data-theme-base="themes" is="x-ui-">
data/cockpit/index.html CHANGED
@@ -53,6 +53,7 @@
53
53
  <script type="text/javascript" src="js/instance.js"></script>
54
54
  <script type="text/javascript" src="js/details.js"></script>
55
55
  <script type="text/javascript" src="js/parameters.js"></script>
56
+ <script type="text/javascript" src="js/modifiers.js"></script>
56
57
  <link rel="stylesheet" href="css/ui.css" type="text/css"/>
57
58
  <link rel="stylesheet" href="/global_ui/uicpee.css" type="text/css"/>
58
59
  <style>
@@ -146,28 +147,31 @@
146
147
  </table>
147
148
  </ui-area> <!--}}}-->
148
149
  <ui-area data-belongs-to-tab="instance" id="areainstance" class="inactive"> <!--{{{-->
149
- <div class='section'>
150
- <div>
151
- <form id='fuckchrome'>
152
- <input type='file' name='testsetfile' id='testsetfile'/>
153
- </form>
154
- <button title='a template includes various settings, subscriptions or a (partial) model' name="loadtestset">load template</button><button title='a testset includes various settings, subscriptions or a model' name="loadtestsetfile">load testset</button>
155
- </div>
156
- <div>
157
- <input type='file' name='modelfile' id='modelfile'/>
158
- <button title='a standalone process model is only loadable if the currently loaded testset sucessfully prepared the current instance for the type of model' name="loadmodelfile">load model</button>
159
- </div>
160
- </div><div class='section'>
161
- <a id="savetestsetfile" href="" download=""></a>
162
- <a id="savesvgfile" href="" download=""></a>
163
- <button title='a testset includes various settings, subscriptions and a model' name="savetestsetfile">save testset</button>
164
- <button title='a testset includes various settings, subscriptions and a model' name="savesvgfile">save svg graph</button>
165
- </div><div class='section'>
166
- <div>
167
- Current model: <span id='currentmodel'></span>
168
- </div>
169
- <div>
170
- <button title='a testset includes various settings, subscriptions and a model' name="loadmodeltype">set model type</button>
150
+ <div>
151
+ <div class='section'>
152
+ <div>
153
+ <form id='fuckchrome'>
154
+ <input type='file' name='testsetfile' id='testsetfile'/>
155
+ </form>
156
+ <button title='a template includes various settings, subscriptions or a (partial) model' name="loadtestset">load template</button><button title='a testset includes various settings, subscriptions or a model' name="loadtestsetfile">load testset</button>
157
+ </div>
158
+ <div>
159
+ <input type='file' name='modelfile' id='modelfile'/>
160
+ <button title='a standalone process model is only loadable if the currently loaded testset sucessfully prepared the current instance for the type of model' name="loadmodelfile">load model</button>
161
+ </div>
162
+ </div><div class='section'>
163
+ <a id="savetestsetfile" href="" download=""></a>
164
+ <a id="savesvgfile" href="" download=""></a>
165
+ <button title='a testset includes various settings, subscriptions and a model' name="savetestsetfile">save testset</button>
166
+ <button title='a testset includes various settings, subscriptions and a model' name="savesvgfile">save svg graph</button>
167
+ </div><div class='section' id='modifiers'>
168
+ <template id="item">
169
+ <div>
170
+ <div class='title'><strong></strong></div>
171
+ <div class='select'><select></select></div>
172
+ <div class='additional'></div>
173
+ </div>
174
+ </template>
171
175
  </div>
172
176
  </div>
173
177
  </ui-area> <!--}}}-->
data/cockpit/js/edit.js CHANGED
@@ -4,6 +4,13 @@ document.addEventListener('graph:changed', function (e) {
4
4
  document.addEventListener('parameters:changed', function (e) {
5
5
  $("button[name=save]").prop("disabled",false);
6
6
  }, false);
7
+ document.addEventListener('modifiers:changed', function (e) {
8
+ $("button[name=save]").prop("disabled",false);
9
+ }, false);
10
+
11
+ function leading_zeros(dt) {
12
+ return (dt < 10 ? '0' : '') + dt;
13
+ }
7
14
 
8
15
  $(document).ready(function() {
9
16
  $("button[name=save]").click(function(){
@@ -19,7 +26,7 @@ $(document).ready(function() {
19
26
  $("button[name=save]").prop("disabled",true);
20
27
  $("#lastsavedline").removeClass('hidden');
21
28
  var dt = new Date();
22
- var time = dt.getHours() + ":" + dt.getMinutes() + ":" + dt.getSeconds();
29
+ var time = leading_zeros(dt.getHours()) + ":" + leading_zeros(dt.getMinutes()) + ":" + leading_zeros(dt.getSeconds());
23
30
  $("#lastsaved").text(time);
24
31
  },
25
32
  error: function() {
@@ -28,6 +28,9 @@ function global_init() {
28
28
  save['details'] = undefined;
29
29
  save['details_target'] = undefined;
30
30
  save['instance_pos'] = [];
31
+ save['modifiers'] = {};
32
+ save['modifiers_active'] = {};
33
+ save['modifiers_additional'] = {};
31
34
  node_state = {};
32
35
  }
33
36
 
@@ -95,6 +98,7 @@ function cockpit() { //{{{
95
98
  $("input[name=votecontinue]").click(check_subscription);
96
99
  $("input[name=testsetfile]").change(load_testsetfile_after);
97
100
  $("input[name=modelfile]").change(load_modelfile_after);
101
+ $("#modifiers").on('change','div.select select',function(e){ modifiers_update(e); });
98
102
 
99
103
  $.ajax({
100
104
  url: $('body').attr('current-templates'),
@@ -276,7 +280,6 @@ function sse() { //{{{
276
280
  break;
277
281
  case 'attributes':
278
282
  monitor_instance_values("attributes");
279
- monitor_instance_transformation();
280
283
  if (!suspended_monitoring) { // or else it would load twice, because dsl changes also trigger
281
284
  if (save['graph_theme'] != data.content.values.theme) {
282
285
  monitor_graph_change(true);
@@ -313,7 +316,6 @@ function sse() { //{{{
313
316
  monitor_instance_values("dataelements");
314
317
  monitor_instance_values("endpoints");
315
318
  monitor_instance_values("attributes");
316
- monitor_instance_transformation();
317
319
  monitor_instance_dsl();
318
320
  monitor_instance_state();
319
321
  } //}}}
@@ -406,12 +408,12 @@ function monitor_instance_values(val) {// {{{
406
408
  $(res).find(" > endpoints > *").each(function(k,v) {
407
409
  save['endpoints_list'][v.localName] = v.lastChild.nodeValue;
408
410
  $.ajax({
409
- url: rep + encodeURIComponent($(v).text()),
411
+ url: rep + 'endpoints/' + encodeURIComponent($(v).text()),
410
412
  success: function() {
411
413
  tmp[v.tagName] = {};
412
414
  var deferreds = [new $.Deferred(), new $.Deferred(), new $.Deferred()];
413
415
  $.ajax({
414
- url: rep + encodeURIComponent($(v).text()) + "/symbol.svg",
416
+ url: rep + 'endpoints/' + encodeURIComponent($(v).text()) + "/symbol.svg",
415
417
  success: function(res) {
416
418
  tmp[v.tagName]['symbol'] = res;
417
419
  deferreds[0].resolve(true);
@@ -419,7 +421,7 @@ function monitor_instance_values(val) {// {{{
419
421
  error: deferreds[0].resolve
420
422
  })
421
423
  $.ajax({
422
- url: rep + encodeURIComponent($(v).text()) + "/schema.rng",
424
+ url: rep + 'endpoints/' + encodeURIComponent($(v).text()) + "/schema.rng",
423
425
  success: function(res) {
424
426
  tmp[v.tagName]['schema'] = res;
425
427
  deferreds[1].resolve(true);
@@ -427,7 +429,7 @@ function monitor_instance_values(val) {// {{{
427
429
  error: deferreds[1].resolve
428
430
  })
429
431
  $.ajax({
430
- url: rep + encodeURIComponent($(v).text()) + "/properties.json",
432
+ url: rep + 'endpoints/' + encodeURIComponent($(v).text()) + "/properties.json",
431
433
  success: function(res) {
432
434
  tmp[v.tagName]['properties'] = res;
433
435
  deferreds[2].resolve(true);
@@ -444,6 +446,11 @@ function monitor_instance_values(val) {// {{{
444
446
  });
445
447
  });
446
448
  } else if(val == "attributes") {
449
+ if ($('#modifiers > div').length == 0) {
450
+ modifiers_display().then(function(){ modifiers_select(); });
451
+ } else {
452
+ modifiers_select();
453
+ }
447
454
  var text = $(" > attributes > info",res).text() + " (" + url.replace(/\/$/,'').split(/[\\/]/).pop() + ")";
448
455
  $('#title').text(text);
449
456
  document.title = text;
@@ -632,19 +639,6 @@ function monitor_instance_state() {// {{{
632
639
  }
633
640
  });
634
641
  }// }}}
635
- function monitor_instance_transformation() {// {{{
636
- var url = $('body').attr('current-instance');
637
- $.ajax({
638
- type: "GET",
639
- url: url + "/properties/attributes/modeltype/",
640
- success: function(res){
641
- $("#currentmodel").text(res);
642
- },
643
- error: function() {
644
- $("#currentmodel").text('???');
645
- }
646
- });
647
- }// }}}
648
642
 
649
643
  function monitor_instance_pos() {// {{{
650
644
  var url = $('body').attr('current-instance');
@@ -731,7 +725,6 @@ function monitor_instance_state_change(notification) { //{{{
731
725
  }
732
726
 
733
727
  if (notification != "ready" && notification != "stopped" && notification != "running") {
734
- console.log('rrr');
735
728
  $('#parameters ui-content ui-area > button').attr('disabled','disabled');
736
729
  $('#state_any').hide();
737
730
  } else {
@@ -845,7 +838,36 @@ function get_testset(deferred) {// {{{
845
838
  ele.removeAttribute('xmlns');
846
839
  }
847
840
  });
848
- deferred.resolve(name,testset);
841
+ $.ajax({
842
+ type: "GET",
843
+ url: url + "/notifications/subscriptions/",
844
+ success: async function(res){
845
+ let values = $("subscriptions > subscription[url]",res);
846
+ let subs = $X('<subscriptions xmlns="http://riddl.org/ns/common-patterns/notifications-producer/2.0"/>');
847
+ let promises = [];
848
+ let scount = 0;
849
+ values.each(function(){
850
+ let sid = $(this).attr('id');
851
+ if (sid.match(/^_/)) {
852
+ scount += 1;
853
+ promises.push(
854
+ $.ajax({
855
+ type: "GET",
856
+ url: url + "/notifications/subscriptions/" + sid,
857
+ error: report_failure
858
+ }).then(function(a) {
859
+ subs.append($(a.documentElement));
860
+ })
861
+ );
862
+ };
863
+ });
864
+ await Promise.all(promises);
865
+ if (scount > 0) { testset.append(subs); }
866
+ deferred.resolve(name,testset);
867
+ },
868
+ error: function() { deferred.reject(); report_failure(); }
869
+ });
870
+
849
871
  },
850
872
  error: function() { deferred.reject(); report_failure(); }
851
873
  });
@@ -919,11 +941,10 @@ async function set_testset(testset,exec) {// {{{
919
941
  url: url + "/notifications/subscriptions/",
920
942
  error: report_failure
921
943
  }).then(async function(res) {
922
- var rcount = 0;
923
944
  var values = $("subscriptions > subscription[url]",res);
924
- var vals = [];
945
+ var vals = {};
925
946
  values.each(function(){
926
- vals.push($(this).attr('url'));
947
+ vals[$(this).attr('url')] = $(this).attr('id');
927
948
  });
928
949
  await load_testset_handlers(url,testset,vals);
929
950
  })
@@ -1083,24 +1104,68 @@ async function load_des(url,model) { //{{{
1083
1104
  error: report_failure
1084
1105
  });
1085
1106
  } //}}}
1107
+
1108
+ function load_testset_extract_handlers(inp,han,suburl) { //{{{
1109
+ inp.push("url="+encodeURIComponent(suburl).replace(/~/,'%7E'));
1110
+ $(">*",han).each(function(_,top){
1111
+ let events = [];
1112
+ let votes = [];
1113
+ $(">*",top).each(function(_,it){
1114
+ if (it.nodeName == 'event') {
1115
+ events.push($(it).text());
1116
+ }
1117
+ if (it.nodeName == 'vote') {
1118
+ votes.push($(it).text());
1119
+ }
1120
+ });
1121
+ if (events.length > 0) {
1122
+ inp.push("topic=" + $(top).attr('id'));
1123
+ inp.push("events=" + events.join(','));
1124
+ }
1125
+ if (votes.length > 0) {
1126
+ inp.push("topic=" + $(top).attr('id'));
1127
+ inp.push("votes=" + votes.join(','));
1128
+ }
1129
+ });
1130
+ return inp;
1131
+ } //}}}
1132
+
1086
1133
  async function load_testset_handlers(url,testset,vals) {// {{{
1087
1134
  var promises = [];
1088
- $("testset > handlers > *",testset).each(async function(){
1089
- var han = this;
1090
- var suburl = $(han).attr('url');
1091
- if ($.inArray(suburl,vals) == -1) {
1092
- var inp = "url="+encodeURIComponent(suburl).replace(/~/,'%7E');
1093
- $("*",han).each(function(){
1094
- inp += "&topic=" + $(this).attr('topic');
1095
- inp += "&" + this.nodeName + "=" + $(this).text();
1096
- });
1097
- promises.push(
1135
+ $("testset > subscriptions > *",testset).each(async function(){
1136
+ let han = this;
1137
+ let sid = $(han).attr('id');
1138
+ let suburl = $(han).attr('url');
1139
+ if (typeof(vals[suburl]) == 'undefined') {
1140
+ if ($("*",han).length > 0) {
1141
+ let inp = [];
1142
+ if (sid) { inp.push("id="+encodeURIComponent(sid)); }
1143
+ inp = load_testset_extract_handlers(inp,han,suburl);
1144
+ promises.push(
1145
+ $.ajax({
1146
+ type: "POST",
1147
+ url: url + "/notifications/subscriptions/",
1148
+ data: inp.join('&')
1149
+ })
1150
+ )
1151
+ }
1152
+ } else {
1153
+ if ($("*",han).length == 0) {
1098
1154
  $.ajax({
1099
- type: "POST",
1100
- url: url + "/notifications/subscriptions/",
1101
- data: inp
1155
+ type: "DELETE",
1156
+ url: url + "/notifications/subscriptions/" + vals[suburl] + '/'
1102
1157
  })
1103
- )
1158
+ delete vals[suburl];
1159
+ } else {
1160
+ let inp = load_testset_extract_handlers([],han,suburl);
1161
+ promises.push(
1162
+ $.ajax({
1163
+ type: "PUT",
1164
+ url: url + "/notifications/subscriptions/" + vals[suburl] + '/',
1165
+ data: inp.join('&')
1166
+ })
1167
+ )
1168
+ }
1104
1169
  }
1105
1170
  });
1106
1171
  return Promise.all(promises);
@@ -1215,7 +1280,6 @@ function format_visual_vote_clear() {//{{{
1215
1280
 
1216
1281
  function format_instance_pos() { //{{{
1217
1282
  $(save['instance_pos']).each(function(){
1218
- console.log(this);
1219
1283
  var taskname = this.nodeName;
1220
1284
  var taskstate = this.textContent;
1221
1285
  format_visual_add(taskname,save['state'] == 'running' ? (taskstate == 'at' ? 'active' : 'passive') : 'passive');