diff options
-rw-r--r-- | Makefile | 2 | ||||
-rw-r--r-- | src/static/css/base.css | 17 | ||||
-rw-r--r-- | src/static/js/dashboard.js | 43 | ||||
-rw-r--r-- | src/templates/booking/quick_deploy.html | 26 | ||||
-rw-r--r-- | src/templates/dashboard/multiple_select_filter_widget.html | 27 | ||||
-rw-r--r-- | src/templates/dashboard/searchable_select_multiple.html | 2 | ||||
-rw-r--r-- | src/templates/resource/steps/define_hardware.html | 5 |
7 files changed, 73 insertions, 49 deletions
@@ -1,3 +1,5 @@ +.PHONY: build dev-up dev-start dev-stop up start stop data shell-nginx shell-web shell-db log-nginx log-web log-ps log-rmq log-worker + build: docker-compose -f docker-compose.yml -f docker-compose.override-dev.yml build diff --git a/src/static/css/base.css b/src/static/css/base.css index 1494e77..9fec97e 100644 --- a/src/static/css/base.css +++ b/src/static/css/base.css @@ -66,9 +66,6 @@ a[aria-expanded="true"] > i.rotate { box-shadow: 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(109, 243, 76, 0.6); transition: border-color ease-in-out .1s,box-shadow ease-in-out .1s; } -#grid_wrapper > .row > div:first-child { - border-right: 1px solid gray; -} /* Cursor effects */ .not-allowed { @@ -81,14 +78,18 @@ a[aria-expanded="true"] > i.rotate { top: 0; } -/* Dropdown for collaborators */ -#drop_results { - max-height: 10rem; +.z-2 { z-index: 2; } -#drop_results > li { - word-wrap: anywhere; +.mh-30vh { + max-height: 30vh; +} + +.overflow-ellipsis { + text-overflow: ellipsis; + white-space: nowrap; + overflow: hidden; } /* Graphing for networks */ diff --git a/src/static/js/dashboard.js b/src/static/js/dashboard.js index 7f8a427..b74ead9 100644 --- a/src/static/js/dashboard.js +++ b/src/static/js/dashboard.js @@ -1236,12 +1236,13 @@ 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_entry.classList.add("list-group-item", "list-group-item-action"); + 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); @@ -1300,21 +1301,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="border rounded mt-2 w-100 d-flex align-items-center pl-2">' - + element_entry_text - + '<button onclick="searchable_select_multiple_widget.remove_item(' - + item_id - + ')" class="btn btn-danger ml-auto">Remove</button>'; - list_html += '</div>'; + list_html.append(itemRow); } - added_list.innerHTML = list_html; + added_list.innerHTML = list_html.innerHTML; } } diff --git a/src/templates/booking/quick_deploy.html b/src/templates/booking/quick_deploy.html index 50ec59a..6776980 100644 --- a/src/templates/booking/quick_deploy.html +++ b/src/templates/booking/quick_deploy.html @@ -7,13 +7,13 @@ <form id="quick_booking_form" action="/booking/quick/" method="POST" class="form"> {% csrf_token %} <div class="container-fluid"> - <div class="row"> - <div class="col-12 px-1 my-2"> - <div class="col py-2 rounded border"> - <p>Please select a host type you wish to book. Only available types are shown.</p> - {% bootstrap_field form.filter_field show_label=False %} - </div> + <div class="row mx-0 px-0"> + <div class="col-12 mx-0 px-0 mt-2"> + <p class="my-0">Please select a host type you wish to book. Only available types are shown.</p> + {% bootstrap_field form.filter_field show_label=False %} </div> + </div> + <div class="row"> <div class="col-12 col-lg-3 px-1 my-2"> <div class="col border rounded py-2 h-100"> {% bootstrap_field form.purpose %} @@ -80,11 +80,8 @@ var sup_installer_dict = {{installer_filter | safe}}; var sup_scenario_dict = {{scenario_filter | safe}}; - function imageHider() { + function imageFilter() { var drop = document.getElementById("id_image"); - - hide_dropdown("id_image"); - var lab_pk = get_selected_value("lab"); var host_pk = get_selected_value("host"); @@ -92,21 +89,18 @@ var image_object = sup_image_dict[childNode.value]; if (image_object) //weed out empty option { - if (image_object.host_profile == host_pk && image_object.lab == lab_pk) { - childNode.style.display = "inherit"; - childNode.disabled = false; - } + childNode.disabled = !(image_object.host_profile == host_pk && image_object.lab == lab_pk); } } } - imageHider(); + imageFilter(); $('#id_installer').children().hide(); $('#id_scenario').children().hide(); Array.from(document.getElementsByClassName("grid-item-select-btn")).forEach(function (element) { - element.addEventListener('click', imageHider); + element.addEventListener('click', imageFilter); }); function installerHider() { diff --git a/src/templates/dashboard/multiple_select_filter_widget.html b/src/templates/dashboard/multiple_select_filter_widget.html index e97a41b..ad58ccb 100644 --- a/src/templates/dashboard/multiple_select_filter_widget.html +++ b/src/templates/dashboard/multiple_select_filter_widget.html @@ -1,15 +1,15 @@ <input name="filter_field" id="filter_field" type="hidden"/> -<div id="grid_wrapper" class="container-fluid p-4"> - <div class="row"> - {% for object_class, object_list in display_objects %} - <div class="col-12 col-lg d-flex flex-column pt-2 my-2"> +<div class="row"> + {% for object_class, object_list in display_objects %} + <div class="col-12 col-lg-6 d-flex flex-column pt-2 mx-0 px-1"> + <div class="col mx-0 border rounded py-2 flex-grow-1 d-flex flex-column"> <div class="w-100"> <h4 class="text-capitalize">{{object_class}}</h4> </div> - <div id="{{object_class}}" class="row h-100"> + <div id="{{object_class}}" class="row flex-grow-1"> {% for obj in object_list %} - <div class="col-12 col-md-6 col-xl-4 my-2"> - <div id="{{ obj.id|default:'not_provided' }}" class="card h-100" onclick="multi_filter_widget.processClick('{{obj.id}}');"> + <div class="col-12 col-md-6 col-xl-4 my-2 d-flex flex-grow-1"> + <div id="{{ obj.id|default:'not_provided' }}" class="card flex-grow-1"> <div class="card-header"> <p class="h5 font-weight-bold mt-2">{{obj.name}}</p> </div> @@ -17,15 +17,22 @@ <p class="grid-item-description">{{obj.description}}</p> </div> <div class="card-footer"> - <button type="button" class="btn btn-success grid-item-select-btn w-100">{% if obj.multiple %}Add{% else %}Select{% endif %}</button> + <button type="button" class="btn btn-success grid-item-select-btn w-100 stretched-link" + onclick="multi_filter_widget.processClick('{{obj.id}}');"> + {% if obj.multiple %} + Add + {% else %} + Select + {% endif %} + </button> </div> </div> </div> {% endfor %} </div> </div> - {% endfor %} - </div> + </div> + {% endfor %} </div> <div id="dropdown_wrapper" class="px-3 list-group-flush w-25 mt-2"> diff --git a/src/templates/dashboard/searchable_select_multiple.html b/src/templates/dashboard/searchable_select_multiple.html index 44689da..be51989 100644 --- a/src/templates/dashboard/searchable_select_multiple.html +++ b/src/templates/dashboard/searchable_select_multiple.html @@ -25,7 +25,7 @@ </input> <div id="scroll_restrictor" class="d-flex pb-4 position-relative"> - <ul id="drop_results" class="list-group w-100 overflow-auto position-absolute"></ul> + <div id="drop_results" class="list-group w-100 z-2 overflow-auto position-absolute mh-30vh"></div> </div> </div> diff --git a/src/templates/resource/steps/define_hardware.html b/src/templates/resource/steps/define_hardware.html index 33a7d8e..efd8a09 100644 --- a/src/templates/resource/steps/define_hardware.html +++ b/src/templates/resource/steps/define_hardware.html @@ -7,9 +7,10 @@ <p>Note that not all labs host every kind of machine. As you make your selections, labs and hosts that are not compatible with your current configuration will become unavailable.</p> -<h4>NOTE: Only PTL's are able to create multi-node PODs. See <a href="https://google.com">here</a> +<h4>NOTE: Only PTL's are able to create multi-node PODs. See + <a href="https://wiki.opnfv.org/display/INF/Lab-as-a-Service+at+the+UNH-IOL">here</a> for more details</h4> -<form id="step_form" method="post"> +<form id="step_form" method="post" class="px-3"> {% csrf_token %} {{form.filter_field|default:"<p>No Form</p>"}} </form> |