Enforce step validity when going forward
[pharos-tools.git] / dashboard / src / templates / workflow / viewport-base.html
1 {% extends "base.html" %}
2 {% load staticfiles %}
3
4 {% load bootstrap3 %}
5
6 {% block content %}
7
8 <style>
9     .go_btn{
10
11         position: absolute;
12         width: 100px;
13         top: 170px;
14         height: calc(100% - 170px);
15
16     }
17     .go_btn_disabled{
18             background-color: #ffffff;
19     }
20     .go_forward{
21         right: 0px;
22         border-left: none;
23     }
24
25     .go_back{
26         left: 251px;
27         border-right: none;
28     }
29
30
31     .btn_wrapper{
32         text-align: center;
33         margin-bottom: 5px;
34
35     }
36
37     {% if DEBUG %}
38
39     .add_btn_wrapper{
40         right: 130px;
41         top: 10px;
42         position: absolute;
43     }
44     {% endif %}
45
46
47
48     .options{
49         position: absolute;
50         top: 60px;
51         right: 20px;
52     }
53
54     #breadcrumbs {
55         margin-bottom: 0;
56     }
57
58     .btn_wrapper {
59         margin: 0;
60     }
61
62     .step{
63         display: inline;
64         padding: 7px;
65         margin: 1px;
66         font-size: 14pt;
67         cursor: default;
68     }
69     .step:active {
70         -webkit-box-shadow: inherit;
71         box-shadow: inherit;
72     }
73     .step_active:active {
74         -webkit-box-shadow: inherit;
75         box-shadow: inherit;
76     }
77
78     .step_active{
79         display: inline;
80         padding: 7px;
81         margin: 1px;
82         cursor: default;
83         font-size: 14pt;
84         padding-bottom: 4px !important;
85         border-bottom: 4px solid #41ba78 !important;
86     }
87
88     .step_hidden
89     {
90         background: #EFEFEF;
91         color: #999999;
92     }
93
94     .step_invalid::after
95     {
96         content: " \2612";
97         color: #CC3300;
98     }
99
100     .step_valid::after
101     {
102         content: " \2611";
103         color: #41ba78;
104     }
105
106     .step_untouched::after
107     {
108         content: " \2610";
109     }
110
111     .iframe_div {
112         width: calc(100% - 450px);
113         margin-left: 70px;
114         height: calc(100vh - 155px);
115         position: absolute;
116         border: none;
117     }
118
119     .iframe_elem {
120         width: 100%;
121         height: calc(100vh - 155px);
122         border: none;
123     }
124
125     #breadcrumbs {
126         background-color: inherit;
127     }
128
129     #breadcrumbs.breadcrumb > li {
130         border: 1px solid #cccccc;
131         border-left: none;
132     }
133     #breadcrumbs.breadcrumb > li:first-child {
134         border-left: 1px solid #cccccc;
135     }
136     #breadcrumbs.breadcrumb > li + li:before {
137         content: "";
138         width: 0;
139         margin: 0;
140         padding: 0;
141     }
142 </style>
143
144 <button id="gof" onclick="go('next')" class="btn go_btn go_forward">Go Forward</button>
145 <button id="gob" onclick="go('prev')" class="btn go_btn go_back">Go Back</button>
146
147 <div class="options">
148     <button id="cancel_btn" class="btn btn-primary" onclick="cancel_wf()">Cancel</button>
149 </div>
150 <div class="btn_wrapper">
151 <ol id="breadcrumbs" class="btn-group breadcrumb">
152 </ol>
153 </div>
154 {% csrf_token %}
155
156 <script type="text/javascript">
157
158
159     update_context();
160     var step = 0;
161     var page_count = 0;
162     var context_data = false;
163
164     function go(to)
165     {
166         step_on_leave();
167         request_leave(to);
168     }
169
170     function request_leave(to)
171     {
172         $.ajax({
173             type: "GET",
174             url: "/wf/manager/",
175             beforeSend: function(request) {
176                 request.setRequestHeader("X-CSRFToken",
177                 $('input[name="csrfmiddlewaretoken"]').val());
178             },
179             success: function (data) {
180                 confirm_permission(to, data);
181                 update_page(data);
182             }
183         });
184     }
185
186     function confirm_permission(to, data)
187     {
188         if( errors_exist(data) )
189         {
190             if( to != "prev" )
191             {
192                 return;
193             }
194         }
195
196         var problem = function() {
197             alert("There was a problem");
198         }
199         //makes an asynch request
200         req = new XMLHttpRequest();
201         url = "/wf/workflow/?step=" + to;
202         req.open("GET", url, true);
203         req.onload = function(e) {
204             if(req.readyState === 4){
205                 if(req.status < 300){
206                     document.getElementById("viewport-iframe").srcdoc = this.responseText;
207                 } else { problem(); }
208             } else { problem(); }
209         }
210         req.onerror = problem;
211         req.send();
212     }
213
214     function step_on_leave()
215     {
216         document.getElementById("viewport-iframe").contentWindow.step_on_leave();
217     }
218
219     function errors_exist(data)
220     {
221         var stat = data['steps'][data['active']]['valid'];
222         if( stat >= 100 && stat < 200 )
223         {
224             return true;
225         }
226         else
227         {
228             return false;
229         }
230     }
231
232     function update_context() {
233         $.ajax({
234             type: "GET",
235             url: "/wf/manager/",
236             beforeSend: function(request) {
237                 request.setRequestHeader("X-CSRFToken",
238                 $('input[name="csrfmiddlewaretoken"]').val());
239             },
240             success: function (data) {
241                 update_page(data);
242             }
243         });
244     }
245
246     function update_page(data)
247     {
248         context_data = data;
249         update_breadcrumbs(data);
250         if(data["workflow_count"] == 1)
251         {
252                 document.getElementById("cancel_btn").innerText = "Exit Workflow";
253         }
254         else
255         {
256                 document.getElementById("cancel_btn").innerText = "Return to Parent";
257         }
258     }
259
260     function update_breadcrumbs(meta_json) {
261         step = meta_json['active'];
262         page_count = meta_json['steps'].length;
263         if( step == 0 )
264         {
265                 var btn = document.getElementById("gob");
266                 btn.classList.add("go_btn_disabled");
267                 btn.disabled = true;
268         }
269         else
270         {
271                 var btn = document.getElementById("gob");
272                 btn.classList.remove("go_btn_disabled");
273                 btn.disabled = false;
274         }
275         if( step == page_count - 1 )
276         {
277                 var btn = document.getElementById("gof");
278                 btn.classList.add("go_btn_disabled");
279                 btn.disabled = true;
280         }
281         else
282         {
283                 var btn = document.getElementById("gof");
284                 btn.classList.remove("go_btn_disabled");
285                 btn.disabled = false;
286         }
287         //remove all children of breadcrumbs so we can redraw
288         var container = document.getElementById("breadcrumbs");
289         while(container.firstChild){
290             container.removeChild(container.firstChild);
291         }
292
293         draw_steps(meta_json);
294     }
295
296     function draw_steps(meta_json){
297         for( var i = 0; i < meta_json["steps"].length; i++ )
298         {
299             meta_json["steps"][i]["index"] = i;
300             var step_btn = create_step(meta_json["steps"][i], i == meta_json["active"]);
301             document.getElementById("breadcrumbs").appendChild(step_btn);
302         }
303     }
304
305     function create_step(step_json, active){
306         var step_dom = document.createElement("li");
307         if(active){
308             step_dom.className = "step_active";
309
310         } else{
311             step_dom.className = "step";
312         }
313         step_dom.appendChild(document.createTextNode(step_json['title']));
314         var code = step_json['valid'];
315         stat = "";
316         msg = "";
317         if( code < 100 )
318         {
319             step_dom.classList.add("step_untouched");
320
321             stat = "";
322             msg = "";
323         }
324         else if( code < 200 )
325         {
326             step_dom.classList.add("step_invalid");
327             stat = "invalid";
328             msg = step_json['message'];
329         }
330         else if( code < 300 )
331         {
332             step_dom.classList.add("step_valid");
333             stat = "valid";
334             msg = step_json['message'];
335         }
336         if( step_json['enabled'] == false )
337         {
338             step_dom.classList.add("step_hidden");
339         }
340         if(active)
341         {
342             update_message(msg, stat);
343         }
344         step_dom.classList.add("btn");
345
346         var step_number = step_json['index'];
347         return step_dom;
348     }
349
350     function cancel_wf(){
351         var form = $("#workflow_pop_form");
352         var formData = form.serialize();
353         var req = new XMLHttpRequest();
354         req.open("POST", "/wf/workflow/finish/", false);
355         req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
356         req.onerror = function() { alert("problem occurred while trying to cancel current workflow"); }
357         req.onreadystatechange = function() { if(req.readyState === 4){
358             refresh_iframe();
359         }};
360         req.send(formData);
361     }
362
363     function refresh_iframe() {
364         req = new XMLHttpRequest();
365         url = "/wf/workflow/";
366         req.open("GET", url, true);
367         req.onload = function(e) {
368             var doc = document.getElementById("viewport-iframe").contentWindow.document;
369             doc.open(); doc.write(this.responseText); doc.close();
370         }
371         req.send();
372     }
373
374     function write_iframe(contents)
375     {
376         document.getElementById("viewport-iframe").contentWindow.document.innerHTML= contents;
377     }
378
379     function redirect_root()
380     {
381         window.location.replace('/wf/');
382     }
383
384     function add_wf(type){
385         add_wf_internal(type, false);
386     }
387
388     function add_edit_wf(type, target){
389         add_wf_internal(type, target);
390     }
391
392     function add_wf_internal(type, itemid){
393         data = {"add": type};
394         if(itemid){
395             data['target'] = itemid;
396         }
397         $.ajax({
398             type: "POST",
399             url: "/wf/manager/",
400             data: data,
401             beforeSend: function(request) {
402                 request.setRequestHeader("X-CSRFToken",
403                 $('input[name="csrfmiddlewaretoken"]').val()
404                 );
405             },
406             success: refresh_wf_iframe()
407         });
408     }
409
410     function refresh_wf_iframe() {
411         window.location=window.location;
412     }
413 </script>
414 <div id="iframe_header" class="row view-header">
415     <div class="col-lg-12 step_header">
416         <h1 class="step_title" id="view_title"></h1>
417         <p class="description" id="view_desc"></p>
418         <p class="step_message" id="view_message"></p>
419     </div>
420     <style>
421         #view_desc{
422             margin-bottom: 15px;
423             margin-top: 5px;
424             margin-left: 30px;
425             display: inline;
426         }
427         #view_title{
428             margin-top: 5px;
429             margin-bottom: 0px;
430             display: inline;
431         }
432         #view_message{
433             margin-top: 10px;
434             margin-bottom: 5px;
435             float: right;
436         }
437         .message_invalid{
438             color: #ff4400;
439         }
440         .message_valid{
441             color: #44cc00;
442         }
443         .step_header{
444             border-bottom: 1px solid #eee;
445             border-top: 1px solid #eee;
446             left: 101px;
447             width: calc(100% - 202px);
448         }
449     </style>
450     <script>
451         function update_description(title, desc){
452             document.getElementById("view_title").innerText = title;
453             document.getElementById("view_desc").innerText = desc;
454         }
455         function update_message(message, stepstatus){
456             document.getElementById("view_message").innerText = message;
457             document.getElementById("view_message").className = "step_message";
458             document.getElementById("view_message").classList.add("message_" + stepstatus);
459         }
460
461     </script>
462     <!-- /.col-lg-12 -->
463 </div>
464 <div style="display: none;" id="workflow_pop_form_div">
465 <form id="workflow_pop_form" action="/wf/workflow/finish/" method="post">
466     {% csrf_token %}
467 </form>
468 </div>
469
470 <div class="iframe_div">
471         <iframe src="/wf/workflow" class="iframe_elem" scrolling="yes" id="viewport-iframe"></iframe>
472 </div>
473 {% endblock content %}