cpee 2.1.1 → 2.1.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) 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/properties/executionhandler.rng +1 -1
  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 +7 -7
  41. metadata +10 -6
  42. data/lib/instantiation.xml +0 -125
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b954fb6ff9aa92c7bd21f89333033b125c5a0e98a80d3790bc11e64a9b4897c7
4
- data.tar.gz: d595b12d073fb81f8da205fad06536457fcdb8eef5ef7978e234cd5d3e2873f8
3
+ metadata.gz: 9723d9a647c3d39f739c125cbc6112254172a59b61c24d498c1ec4d53f9a6998
4
+ data.tar.gz: 8945918c7a22d82a7936f1f76a322734f233e7ab701fa670f9a182ccbcd5c80b
5
5
  SHA512:
6
- metadata.gz: b206450ff31331811ea38ef50696cbe3266104e3ce84269760deedcfc9df251b507b65d3b75b3d7ce6d7c1e7c878ff14bee8eeae03617ca331490b09887344fc
7
- data.tar.gz: 0e2feeae09f44385eb3b3c50807d4a5adb18388225ccc6d840b0a1ee668263fba34119e04a31bf5b776944fff76392b0511c194c6f38bf77deed22ec785245a3
6
+ metadata.gz: 7d7cb7f744225804de94c56b348c22e61cc2501aba291bddadcef2c1ae725f5280eeb9700065467d3b9289ec2fd15c3200708d557e3b94ffd03b190abd72c492
7
+ data.tar.gz: 731e6e16864401821398d2274c230512abca96af46f74ff0c665bc90a4a9db00141972f52084ce4b84c076532507ca4f9e0bee8635a2913bf4533d4f5a2b56fb
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');