diff options
Diffstat (limited to 'src/static/js/dashboard.js')
-rw-r--r-- | src/static/js/dashboard.js | 300 |
1 files changed, 255 insertions, 45 deletions
diff --git a/src/static/js/dashboard.js b/src/static/js/dashboard.js index 84c3703..8e1250a 100644 --- a/src/static/js/dashboard.js +++ b/src/static/js/dashboard.js @@ -1,3 +1,190 @@ +/////////////////// +// Global Variables +/////////////////// + +form_submission_callbacks = []; //all runnables will be executed before form submission + +/////////////////// +// Global Functions +/////////////////// +function update_page(response) { + if( response.redirect ) + { + window.location.replace(response.redirect); + return; + } + draw_breadcrumbs(response.meta); + update_exit_button(response.meta); + update_side_buttons(response.meta); + $("#formContainer").html(response.content); +} + +function update_side_buttons(meta) { + const step = meta.active; + const page_count = meta.steps.length; + + const back_button = document.getElementById("gob"); + if (step == 0) { + back_button.classList.add("disabled"); + back_button.disabled = true; + } else { + back_button.classList.remove("disabled"); + back_button.disabled = false; + } + + const forward_btn = document.getElementById("gof"); + if (step == page_count - 1) { + forward_btn.classList.add("disabled"); + forward_btn.disabled = true; + } else { + forward_btn.classList.remove("disabled"); + forward_btn.disabled = false; + } +} + +function update_exit_button(meta) { + if (meta.workflow_count == 1) { + document.getElementById("cancel_btn").innerText = "Exit Workflow"; + } else { + document.getElementById("cancel_btn").innerText = "Return to Parent"; + } +} + +function draw_breadcrumbs(meta) { + $("#topPagination").children().not(".page-control").remove(); + + for (const i in meta.steps) { + const step_btn = create_step(meta.steps[i], i == meta["active"]); + $("#topPagination li:last-child").before(step_btn); + } +} + +function create_step(step_json, active) { + const step_dom = document.createElement("li"); + // First create the dom object depending on active or not + step_dom.className = "topcrumb"; + if (active) { + step_dom.classList.add("active"); + } + $(step_dom).html(`<span class="d-flex align-items-center justify-content-center text-capitalize w-100">${step_json['title']}</span>`) + + const code = step_json.valid; + + let stat = ""; + let msg = ""; + if (code < 100) { + $(step_dom).children().first().append("<i class='ml-2 far fa-square'></i>") + stat = ""; + msg = ""; + } else if (code < 200) { + $(step_dom).children().first().append("<i class='ml-2 fas fa-minus-square'></i>") + stat = "invalid"; + msg = step_json.message; + } else if (code < 300) { + $(step_dom).children().first().append("<i class='ml-2 far fa-check-square'></i>") + stat = "valid"; + msg = step_json.message; + } + + if (step_json.enabled == false) { + step_dom.classList.add("disabled"); + } + if (active) { + update_message(msg, stat); + } + + return step_dom; +} + +function update_description(title, desc) { + document.getElementById("view_title").innerText = title; + document.getElementById("view_desc").innerText = desc; +} + +function update_message(message, stepstatus) { + document.getElementById("view_message").innerText = message; + document.getElementById("view_message").className = "step_message"; + document.getElementById("view_message").classList.add("message_" + stepstatus); +} + +function submitStepForm(next_step = "current"){ + run_form_callbacks(); + const step_form_data = $("#step_form").serialize(); + const form_data = $.param({ + "step": next_step, + "step_form": step_form_data, + "csrfmiddlewaretoken": $("[name=csrfmiddlewaretoken]").val() + }); + $.post( + '/workflow/manager/', + form_data, + (data) => update_page(data), + 'json' + ).fail(() => alert("failure")); +} + +function run_form_callbacks(){ + for(f of form_submission_callbacks) + f(); + form_submission_callbacks = []; +} + +function create_workflow(type) { + $.ajax({ + type: "POST", + url: "/workflow/create/", + data: { + "workflow_type": type + }, + headers: { + "X-CSRFToken": $('input[name="csrfmiddlewaretoken"]').val() + } + }).done(function (data, textStatus, jqXHR) { + window.location = "/workflow/"; + }).fail(function (jqxHR, textstatus) { + alert("Something went wrong..."); + }); +} + +function add_workflow(type) { + data = $.ajax({ + type: "POST", + url: "/workflow/add/", + data: { + "workflow_type": type + }, + headers: { + "X-CSRFToken": $('input[name="csrfmiddlewaretoken"]').val() + } + }).done(function (data, textStatus, jqXHR) { + update_page(data); + }).fail(function (jqxHR, textstatus) { + alert("Something went wrong..."); + }); +} + +function pop_workflow() { + data = $.ajax({ + type: "POST", + url: "/workflow/pop/", + headers: { + "X-CSRFToken": $('input[name="csrfmiddlewaretoken"]').val() + } + }).done(function (data, textStatus, jqXHR) { + update_page(data); + }).fail(function (jqxHR, textstatus) { + alert("Something went wrong..."); + }); +} + +function continue_workflow() { + window.location.replace("/workflow/"); +} + +/////////////////// +//Class Definitions +/////////////////// + class MultipleSelectFilterWidget { constructor(neighbors, items, initial) { @@ -98,7 +285,7 @@ class MultipleSelectFilterWidget { select(node) { const elem = document.getElementById(node['id']); node['selected'] = true; - elem.classList.remove('disabled_node', 'cleared_node'); + elem.classList.remove('bg-white', 'not-allowed', 'bg-light'); elem.classList.add('selected_node'); } @@ -106,16 +293,16 @@ class MultipleSelectFilterWidget { const elem = document.getElementById(node['id']); node['selected'] = false; node['selectable'] = true; - elem.classList.add('cleared_node') - elem.classList.remove('disabled_node', 'selected_node'); + elem.classList.add('bg-white') + elem.classList.remove('not-allowed', 'bg-light', 'selected_node'); } disable_node(node) { const elem = document.getElementById(node['id']); node['selected'] = false; node['selectable'] = false; - elem.classList.remove('cleared_node', 'selected_node'); - elem.classList.add('disabled_node'); + elem.classList.remove('bg-white', 'selected_node'); + elem.classList.add('not-allowed', 'bg-light'); } processClick(id){ @@ -173,7 +360,7 @@ class MultipleSelectFilterWidget { const button = document.createElement("BUTTON"); button.type = "button"; button.appendChild(document.createTextNode("Remove")); - button.classList.add("btn", "btn-danger"); + button.classList.add("btn", "btn-danger", "d-inline-block"); const that = this; button.onclick = function(){ that.remove_dropdown(div.id, node.id); } return button; @@ -183,6 +370,7 @@ class MultipleSelectFilterWidget { const input = document.createElement("INPUT"); input.type = node.form.type; input.name = node.id + node.form.name + input.classList.add("form-control", "w-auto", "d-inline-block"); input.pattern = "(?=^.{1,253}$)(^([A-Za-z0-9-_]{1,62}\.)*[A-Za-z0-9-_]{1,63})"; input.title = "Only alphanumeric characters (a-z, A-Z, 0-9), underscore(_), and hyphen (-) are allowed" input.placeholder = node.form.placeholder; @@ -198,13 +386,18 @@ class MultipleSelectFilterWidget { add_item_prepopulate(node, prepopulate){ const div = document.createElement("DIV"); div.id = "dropdown_" + this.dropdown_count; - div.classList.add("dropdown_item"); + div.classList.add("card", "flex-row", "d-flex", "mb-2"); this.dropdown_count++; const label = document.createElement("H5") label.appendChild(document.createTextNode(node['name'])) + label.classList.add("p-1", "m-1"); div.appendChild(label); - div.appendChild(this.make_input(div, node, prepopulate)); - div.appendChild(this.make_remove_button(div, node)); + let input = this.make_input(div, node, prepopulate); + input.classList.add("flex-grow-1", "p-1", "m-1"); + div.appendChild(input); + let remove_btn = this.make_remove_button(div, node); + remove_btn.classList.add("p-1", "m-1"); + div.appendChild(remove_btn); document.getElementById("dropdown_wrapper").appendChild(div); return div; } @@ -756,21 +949,28 @@ class NetworkStep { } makeSidebarNetwork(net_name, color, net_id){ - const newNet = document.createElement("li"); const colorBlob = document.createElement("div"); - colorBlob.className = "colorblob"; - const textContainer = document.createElement("p"); - textContainer.className = "network_innertext"; - newNet.id = net_id; + colorBlob.className = "square-20 rounded-circle"; + colorBlob.style['background'] = color; + + const textContainer = document.createElement("span"); + textContainer.className = "ml-2"; + textContainer.appendChild(document.createTextNode(net_name)); + + const timesIcon = document.createElement("i"); + timesIcon.classList.add("fas", "fa-times"); + const deletebutton = document.createElement("button"); - deletebutton.className = "btn btn-danger"; - deletebutton.style = "float: right; height: 20px; line-height: 8px; vertical-align: middle; width: 20px; padding-left: 5px;"; - deletebutton.appendChild(document.createTextNode("X")); + deletebutton.className = "btn btn-danger ml-auto square-20 p-0 d-flex justify-content-center"; + deletebutton.appendChild(timesIcon); deletebutton.addEventListener("click", function() { this.createDeleteDialog(net_id); }.bind(this), false); - textContainer.appendChild(document.createTextNode(net_name)); - colorBlob.style['background'] = color; + + const newNet = document.createElement("li"); + newNet.classList.add("list-group-item", "d-flex", "bg-light"); + newNet.id = net_id; newNet.appendChild(colorBlob); newNet.appendChild(textContainer); + if( net_name != "public" ) { newNet.appendChild(deletebutton); } @@ -818,16 +1018,9 @@ class NetworkStep { this.graph.refresh(host); } - submitForm() { - const form = document.getElementById("xml_form"); + prepareForm() { const input_elem = document.getElementById("hidden_xml_input"); input_elem.value = this.encodeGraph(this.graph); - const req = new XMLHttpRequest(); - req.open("POST", "/wf/workflow/", false); - req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded"); - req.onerror = function() { alert("problem with form submission"); } - const formData = $("#xml_form").serialize(); - req.send(formData); } } @@ -1048,18 +1241,19 @@ class SearchableSelectMultipleWidget { for( const id in ids ) { - const result_entry = document.createElement("li"); - const result_button = document.createElement("a"); const obj = this.items[id]; const result_text = this.generate_element_text(obj); - result_button.appendChild(document.createTextNode(result_text)); - result_button.onclick = function() { searchable_select_multiple_widget.select_item(obj.id); }; + const result_entry = document.createElement("a"); + result_entry.href = "#"; + result_entry.innerText = result_text; + result_entry.title = result_text; + result_entry.classList.add("list-group-item", "list-group-item-action", "overflow-ellipsis", "flex-shrink-0"); + result_entry.onclick = function() { searchable_select_multiple_widget.select_item(obj.id); }; const tooltip = document.createElement("span"); const tooltiptext = document.createTextNode(result_text); tooltip.appendChild(tooltiptext); - tooltip.setAttribute('class', 'entry_tooltip'); - result_button.appendChild(tooltip); - result_entry.appendChild(result_button); + tooltip.classList.add("d-none"); + result_entry.appendChild(tooltip); drop.appendChild(result_entry); } @@ -1112,23 +1306,39 @@ class SearchableSelectMultipleWidget { added_list.removeChild(added_list.firstChild); } - let list_html = ""; + const list_html = document.createElement("div"); + list_html.classList.add("list-group"); for( const item_id of this.added_items ) { - const item = this.items[item_id]; + const times = document.createElement("li"); + times.classList.add("fas", "fa-times"); + + const deleteButton = document.createElement("a"); + deleteButton.href = "#"; + deleteButton.innerHTML = "<i class='fas fa-times'></i>" + // Setting .onclick/.addEventListener does not work, + // which is why I took the setAttribute approach + // If anyone knows why, please let me know :] + deleteButton.setAttribute("onclick", `searchable_select_multiple_widget.remove_item(${item_id});`); + deleteButton.classList.add("btn"); + const deleteColumn = document.createElement("div"); + deleteColumn.classList.add("col-auto"); + deleteColumn.append(deleteButton); + const item = this.items[item_id]; const element_entry_text = this.generate_element_text(item); + const textColumn = document.createElement("div"); + textColumn.classList.add("col", "overflow-ellipsis"); + textColumn.innerText = element_entry_text; + textColumn.title = element_entry_text; + + const itemRow = document.createElement("div"); + itemRow.classList.add("list-group-item", "d-flex", "p-0", "align-items-center"); + itemRow.append(textColumn, deleteColumn); - list_html += '<div class="list_entry">' - + '<p class="added_entry_text">' - + element_entry_text - + '</p>' - + '<button onclick="searchable_select_multiple_widget.remove_item(' - + item_id - + ')" class="btn-remove btn">remove</button>'; - list_html += '</div>'; + list_html.append(itemRow); } - added_list.innerHTML = list_html; + added_list.innerHTML = list_html.innerHTML; } } |