diff options
-rw-r--r-- | src/api/views.py | 2 | ||||
-rw-r--r-- | src/booking/forms.py | 14 | ||||
-rw-r--r-- | src/booking/quick_deployer.py | 2 | ||||
-rw-r--r-- | src/booking/views.py | 3 | ||||
-rw-r--r-- | src/dashboard/actions.py | 47 | ||||
-rw-r--r-- | src/dashboard/views.py | 2 | ||||
-rw-r--r-- | src/resource_inventory/models.py | 3 | ||||
-rw-r--r-- | src/resource_inventory/urls.py | 5 | ||||
-rw-r--r-- | src/resource_inventory/views.py | 17 | ||||
-rw-r--r-- | src/templates/booking/booking_table.html | 14 | ||||
-rw-r--r-- | src/templates/booking/quick_deploy.html | 41 | ||||
-rw-r--r-- | src/templates/booking/steps/booking_meta.html | 9 | ||||
-rw-r--r-- | src/templates/config_bundle/steps/config_software.html | 36 | ||||
-rw-r--r-- | src/templates/dashboard/lab_detail.html | 2 | ||||
-rw-r--r-- | src/templates/dashboard/lab_list.html | 103 | ||||
-rw-r--r-- | src/templates/dashboard/multiple_select_filter_widget.html | 60 | ||||
-rw-r--r-- | src/templates/resource/hostprofile_detail.html | 116 | ||||
-rw-r--r-- | src/templates/resource/hosts.html | 2 | ||||
-rw-r--r-- | src/templates/resource/steps/meta_info.html | 22 | ||||
-rw-r--r-- | src/templates/workflow/viewport-base.html | 29 |
20 files changed, 376 insertions, 153 deletions
diff --git a/src/api/views.py b/src/api/views.py index a56dcfe..2ae1ac5 100644 --- a/src/api/views.py +++ b/src/api/views.py @@ -101,6 +101,8 @@ def specific_task(request, lab_name="", job_id="", task_id=""): task.status = request.POST.get('status') if 'message' in request.POST: task.message = request.POST.get('message') + if 'lab_token' in request.POST: + task.lab_token = request.POST.get('lab_token') task.save() NotificationHandler.task_updated(task) d = {} diff --git a/src/booking/forms.py b/src/booking/forms.py index 7ba5af0..9349ac1 100644 --- a/src/booking/forms.py +++ b/src/booking/forms.py @@ -8,7 +8,6 @@ ############################################################################## import django.forms as forms from django.forms.widgets import NumberInput -from django.db.models import Q from workflow.forms import ( SearchableSelectMultipleWidget, @@ -22,7 +21,6 @@ from resource_inventory.models import Image, Installer, Scenario class QuickBookingForm(forms.Form): purpose = forms.CharField(max_length=1000) project = forms.CharField(max_length=400) - image = forms.ModelChoiceField(queryset=Image.objects.all()) hostname = forms.CharField(max_length=400) installer = forms.ModelChoiceField(queryset=Installer.objects.all(), required=False) @@ -40,14 +38,14 @@ class QuickBookingForm(forms.Form): elif data and "users" in data: chosen_users = data.getlist("users") - if user: - self.image = forms.ModelChoiceField(queryset=Image.objects.filter( - Q(public=True) | Q(owner=user)), required=False) - else: - self.image = forms.ModelChoiceField(queryset=Image.objects.all(), required=False) - super(QuickBookingForm, self).__init__(data=data, **kwargs) + self.fields["image"] = forms.ModelChoiceField( + queryset=Image.objects.difference( + Image.objects.filter(public=False).difference(Image.objects.filter(owner=user)) + ) + ) + self.fields['users'] = forms.CharField( widget=SearchableSelectMultipleWidget( attrs=self.build_search_widget_attrs(chosen_users, default_user=default_user) diff --git a/src/booking/quick_deployer.py b/src/booking/quick_deployer.py index f8dc9ff..cc593fa 100644 --- a/src/booking/quick_deployer.py +++ b/src/booking/quick_deployer.py @@ -119,7 +119,7 @@ def check_available_matching_host(lab, hostprofile): available_host_types = ResourceManager.getInstance().getAvailableHostTypes(lab) if hostprofile not in available_host_types: # TODO: handle deleting generic resource in this instance along with grb - raise HostNotAvailable("Could not book selected host due to changed availability. Try again later") + raise HostNotAvailable('Requested host type is not available. Please try again later. Host availability can be viewed in the "Hosts" tab to the left.') hostset = Host.objects.filter(lab=lab, profile=hostprofile).filter(booked=False).filter(working=True) if not hostset.exists(): diff --git a/src/booking/views.py b/src/booking/views.py index 1e14b8e..8211a0c 100644 --- a/src/booking/views.py +++ b/src/booking/views.py @@ -62,8 +62,7 @@ def quick_create(request): try: create_from_form(form, request) except Exception as e: - messages.error(request, "Whoops, looks like an error occurred. " - "Let the admins know that you got the following message: " + str(e)) + messages.error(request, "Whoops, an error occurred: " + str(e)) return render(request, 'workflow/exit_redirect.html', context) messages.success(request, "We've processed your request. " diff --git a/src/dashboard/actions.py b/src/dashboard/actions.py new file mode 100644 index 0000000..44b1fdd --- /dev/null +++ b/src/dashboard/actions.py @@ -0,0 +1,47 @@ +############################################################################## +# Copyright (c) 2019 Parker Berberian, Sawyer Bergeron, and others. +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 +############################################################################## + +from resource_inventory.models import Host, Vlan +from account.models import Lab +from booking.models import Booking +from datetime import timedelta +from django.utils import timezone + + +def free_leaked_hosts(free_old_bookings=False, old_booking_age=timedelta(days=1)): + bundles = [booking.resource for booking in Booking.objects.filter(end__gt=timezone.now())] + active_hosts = set() + for bundle in bundles: + active_hosts.update([host for host in bundle.hosts.all()]) + + marked_hosts = set(Host.objects.filter(booked=True)) + + for host in (marked_hosts - active_hosts): + host.booked = False + host.save() + + +def free_leaked_public_vlans(): + booked_host_interfaces = [] + + for lab in Lab.objects.all(): + + for host in Host.objects.filter(booked=True).filter(lab=lab): + for interface in host.interfaces.all(): + booked_host_interfaces.append(interface) + + in_use_vlans = Vlan.objects.filter(public=True).distinct('vlan_id').filter(interface__in=booked_host_interfaces) + + manager = lab.vlan_manager + + for vlan in Vlan.objects.all(): + if vlan not in in_use_vlans: + if vlan.public: + manager.release_public_vlan(vlan.vlan_id) + manager.release_vlans(vlan) diff --git a/src/dashboard/views.py b/src/dashboard/views.py index c4a6685..aaad7ab 100644 --- a/src/dashboard/views.py +++ b/src/dashboard/views.py @@ -46,7 +46,7 @@ def lab_detail_view(request, lab_name): 'title': "Lab Overview", 'lab': lab, 'hostprofiles': lab.hostprofiles.all(), - 'images': images + 'images': images, } ) diff --git a/src/resource_inventory/models.py b/src/resource_inventory/models.py index 0b7b24c..d3f47d4 100644 --- a/src/resource_inventory/models.py +++ b/src/resource_inventory/models.py @@ -190,6 +190,9 @@ class ResourceBundle(models.Model): return "Resource bundle " + str(self.id) + " with no template" return "instance of " + str(self.template) + def get_host(self, role="Jumphost"): + return Host.objects.filter(bundle=self, config__opnfvRole__name=role).first() + class GenericInterface(models.Model): id = models.AutoField(primary_key=True) diff --git a/src/resource_inventory/urls.py b/src/resource_inventory/urls.py index 4e159ba..a72871b 100644 --- a/src/resource_inventory/urls.py +++ b/src/resource_inventory/urls.py @@ -25,10 +25,11 @@ Including another URLconf 2. Add a URL to urlpatterns: url(r'^blog/', include('blog.urls')) """ from django.conf.urls import url -from resource_inventory.views import HostView +from resource_inventory.views import HostView, hostprofile_detail_view app_name = "resource" urlpatterns = [ - url(r'^hosts$', HostView.as_view(), name='hosts') + url(r'^hosts$', HostView.as_view(), name='hosts'), + url(r'^profiles/(?P<hostprofile_id>.+)/$', hostprofile_detail_view, name='host_detail'), ] diff --git a/src/resource_inventory/views.py b/src/resource_inventory/views.py index 2937bd7..8c3d899 100644 --- a/src/resource_inventory/views.py +++ b/src/resource_inventory/views.py @@ -9,8 +9,10 @@ from django.views.generic import TemplateView +from django.shortcuts import get_object_or_404 +from django.shortcuts import render -from resource_inventory.models import Host +from resource_inventory.models import HostProfile, Host class HostView(TemplateView): @@ -21,3 +23,16 @@ class HostView(TemplateView): hosts = Host.objects.filter(working=True) context.update({'hosts': hosts, 'title': "Hardware Resources"}) return context + + +def hostprofile_detail_view(request, hostprofile_id): + hostprofile = get_object_or_404(HostProfile, id=hostprofile_id) + + return render( + request, + "resource/hostprofile_detail.html", + { + 'title': "Host Type: " + str(hostprofile.name), + 'hostprofile': hostprofile + } + ) diff --git a/src/templates/booking/booking_table.html b/src/templates/booking/booking_table.html index 5e82645..e0c5f49 100644 --- a/src/templates/booking/booking_table.html +++ b/src/templates/booking/booking_table.html @@ -5,11 +5,10 @@ <tr> <th>Owner</th> <th>Purpose</th> + <th>Project</th> <th>Start</th> <th>End</th> <th>Operating System</th> - <th>Installer</th> - <th>Scenario</th> </tr> </thead> <tbody> @@ -22,19 +21,16 @@ {{ booking.purpose }} </td> <td> - {{ booking.start }} - </td> - <td> - {{ booking.end }} + {{ booking.project }} </td> <td> - {{ booking.opsys }} + {{ booking.start }} </td> <td> - {{ booking.installer }} + {{ booking.end }} </td> <td> - {{ booking.scenario }} + {{ booking.resource.get_host.config.image.os.name }} </td> </tr> {% endfor %} diff --git a/src/templates/booking/quick_deploy.html b/src/templates/booking/quick_deploy.html index 3837315..38294b2 100644 --- a/src/templates/booking/quick_deploy.html +++ b/src/templates/booking/quick_deploy.html @@ -26,6 +26,14 @@ .grid_element_2third { grid-column-start: span 8; } + #id_length { + -moz-appearance: none; + border: none; + box-shadow: none; + } + input[type=range]::-moz-range-track { + background: #cccccc; + } </style> {% bootstrap_form_errors form type='non_fields' %} <form id="quick_booking_form" action="/booking/quick/" method="POST" class="form"> @@ -33,7 +41,7 @@ <div class="grid_container"> <div class="grid_element host_select_pane grid_element_wide"> <p>Please select a host type you wish to book. Only available types are shown.</p> -{% bootstrap_field form.filter_field %} +{% bootstrap_field form.filter_field show_label=False %} </div> <div class="grid_element booking_info_pane grid_element_1third"> {% bootstrap_field form.purpose %} @@ -49,11 +57,16 @@ <label>Collaborators</label> {{ form.users }} </div> -<div class="grid_element configuration_pane grid_element_1third"> - {% bootstrap_field form.hostname %} - {% bootstrap_field form.image %} - {% bootstrap_field form.installer %} - {% bootstrap_field form.scenario %} +<div class="grid_element_1third"> + <div class="configuration_pane grid_element"> + {% bootstrap_field form.hostname %} + {% bootstrap_field form.image %} + </div> + <div class="configuration_pane grid_element"> + <strong>OPNFV: (Optional)</strong> + {% bootstrap_field form.installer %} + {% bootstrap_field form.scenario %} + </div> </div> </div> <script type="text/javascript"> @@ -103,6 +116,12 @@ $('#id_image').children().hide(); + for( var i = 0; i < drop.childNodes.length; i++ ) + { + drop.childNodes[i].disabled = true; // closest we can get on safari to hiding it outright + } + + var empty_map = {} for ( var i=0; i < drop.childNodes.length; i++ ) @@ -125,12 +144,13 @@ if( image_object.host_profile == host_pk && image_object.lab == lab_pk ) { drop.childNodes[i].style.display = "inherit"; + drop.childNodes[i].disabled = false; } } } } - $('#id_image').children().hide(); + imageHider(); $('#id_installer').children().hide(); $('#id_scenario').children().hide(); @@ -160,7 +180,13 @@ } targ_id = "#" + target; + $(targ_id).children().hide(); + + for (var i = 0; i < document.getElementById(target).childNodes.length; i++) + { + document.getElementById(target).childNodes[i].disabled = true; + } var drop = document.getElementById(master); var opts = target_filter[drop.options[drop.selectedIndex].value]; if (!opts) { @@ -177,6 +203,7 @@ for (var i = 0; i < document.getElementById(target).childNodes.length; i++) { if (document.getElementById(target).childNodes[i].value in opts && !(document.getElementById(target).childNodes[i].value in emptyMap) ) { document.getElementById(target).childNodes[i].style.display = "inherit"; + document.getElementById(target).childNodes[i].disabled = false; } } } diff --git a/src/templates/booking/steps/booking_meta.html b/src/templates/booking/steps/booking_meta.html index e4881ae..fe43f53 100644 --- a/src/templates/booking/steps/booking_meta.html +++ b/src/templates/booking/steps/booking_meta.html @@ -21,6 +21,15 @@ grid-template-columns: 45% 10% 45%; border: none; } + + #id_length { + -moz-appearance: none; + border: none; + box-shadow: none; + } + input[type=range]::-moz-range-track { + background: #cccccc; + } </style> {% bootstrap_form_errors form type='non_fields' %} diff --git a/src/templates/config_bundle/steps/config_software.html b/src/templates/config_bundle/steps/config_software.html index ca15c77..e1f9541 100644 --- a/src/templates/config_bundle/steps/config_software.html +++ b/src/templates/config_bundle/steps/config_software.html @@ -12,23 +12,25 @@ <p>And a description:</p> {{ form.description }} - <p>Install OPNFV?</p> - {{ form.opnfv }} - <p>Choose your:</p> - <table> - <thead> - <tr> - <th>Installer</th> - <th>Scenario</th> - </tr> - </thead> - <tbody> - <tr> - <td>{{form.installer}}</td> - <td>{{form.scenario}}</td> - </tr> - </tbody> - </table> + <div id="hidden" style="display:none;"> + <p>Install OPNFV?</p> + {{ form.opnfv }} + <p>Choose your:</p> + <table> + <thead> + <tr> + <th>Installer</th> + <th>Scenario</th> + </tr> + </thead> + <tbody> + <tr> + <td>{{form.installer}}</td> + <td>{{form.scenario}}</td> + </tr> + </tbody> + </table> + </div> </form> diff --git a/src/templates/dashboard/lab_detail.html b/src/templates/dashboard/lab_detail.html index 4c06245..7938e86 100644 --- a/src/templates/dashboard/lab_detail.html +++ b/src/templates/dashboard/lab_detail.html @@ -62,7 +62,7 @@ <tr> <td>{{profile.name}}</td> <td>{{profile.description}}</td> - <td>{{profile.labs}}</td> + <td><a href="/resource/profiles/{{ profile.id }}" class="btn btn-primary">Profile</a></td> </tr> {% endfor %} </table> diff --git a/src/templates/dashboard/lab_list.html b/src/templates/dashboard/lab_list.html index a86f7f4..c459dd9 100644 --- a/src/templates/dashboard/lab_list.html +++ b/src/templates/dashboard/lab_list.html @@ -1,87 +1,26 @@ {% extends "base.html" %} -{% load staticfiles %} - -{% block extrahead %} - {{block.super}} - <script src="https://cdn.rawgit.com/google/code-prettify/master/loader/run_prettify.js?lang=yaml"></script> -{% endblock %} - {% block content %} - <style> - .grid-item-container { - padding: 10px; - } - - .grid-item { - cursor: pointer; - border:2px; - border-style:none; - border-color:black; - border-radius: 5px; - padding: 7px; - color: inherit; - - box-shadow: 0px 0px 7px 0px rgba(0,0,0,0.75); - transition-property: box-shadow, background-color; - transition-duration: .2s; - } - - .grid-item-text - { - color: inherit; - text-decoration: none; - } - .grid-item-text:hover - { - color: #121212; - text-decoration: none; - } - - .grid-item:hover { - box-shadow: 0px 0px 14px 0px rgba(0,0,0,0.75); - transition-property: box-shadow; - transition-duration: .2s; - - } - - .selected_node { - box-shadow: 0px 0px 14px 0px rgba(0,0,0,0.75); - background-color: #CCECD7; - transition-property: background-color; - transition-duration: .2s; - } - - .disabled_node { - cursor: not-allowed; - background-color: #EFEFEF; - box-shadow: 0px 0px 1px 0px rgba(0,0,0,0.75); - transition-property: box-shadow; - transition-duration: .2s; - } - - .disabled_node:hover { - box-shadow: 0px 0px 1px 0px rgba(0,0,0,0.75); - } - - </style> - <div class="container-fluid"> - <div class="row"> - - <div class="listgrid"> - {% for lab in labs %} - <div class="grid-item-container col-lg-2 col-mid-4 col-sm-6"> - - <a href="{{ lab.name }}" class="grid-item-text"> - - <div class="grid-item"> - <h4 class="grid-item-header">{{ lab.name }}</h4> - <p class="grid-item-description">{{ lab.description }}</p> + <h2>Labs</h2> + <div class="card_container"> + {% for lab in labs %} + <div class="detail_card"> + <div> + <h3>{{lab.name}}</h3> + <ul class="list-group"> + <li class="list-group-item">name: {{lab.name}}</li> + <li class="list-group-item">description: {{lab.description}}</li> + <li class="list-group-item">location: {{lab.location}}</li> + {% if lab.status == 0 %} + <li class="list-group-item">status: Up</li> + {% elif lab.status == 100 %} + <li class="list-group-item">status: Down for Maintenance</li> + {% elif lab.status == 200 %} + <li class="list-group-item">status: Down</li> + {% endif %} + </ul> </div> - </a> + <a class="btn btn-primary" href="/lab/{{lab.name}}/">Details</a> </div> - {% endfor %} - </div> + {% endfor %} </div> - </div> - -{% endblock content %} +{% endblock %} diff --git a/src/templates/dashboard/multiple_select_filter_widget.html b/src/templates/dashboard/multiple_select_filter_widget.html index 4e47ce0..628fd95 100644 --- a/src/templates/dashboard/multiple_select_filter_widget.html +++ b/src/templates/dashboard/multiple_select_filter_widget.html @@ -6,12 +6,16 @@ } .class_grid_wrapper { border: 0px; - border-left: 1px; + text-align: center; border-right: 1px; border-style: solid; border-color: grey; - text-align: center; } + +.class_grid_wrapper:last-child { + border-right: none; +} + .grid_wrapper { display: grid; grid-template-columns: 1fr 1fr; @@ -67,6 +71,45 @@ margin-top: 10px; } +#dropdown_wrapper > div > h5 { + margin: 12px; + display: inline-block; + vertical-align: middle; +} + +#dropdown_wrapper > div > button { + padding: 7px; + margin: 2px; + float: right; + width: 80px; +} +#dropdown_wrapper > div > input { + padding: 7px; + margin: 2px; + float: right; + width: 300px; + width: calc(100% - 240px); +} + +#dropdown_wrapper > div { + border:2px; + border-style:none; + border-color:black; + border-radius: 5px; + margin:20px; + padding: 2px; + box-shadow: 0px 0px 7px 0px rgba(0,0,0,0.75); + transition-property: box-shadow, background-color; + transition-duration: .2s; + display: inline-block; + vertical-align: middle; +} + +#dropdown_wrapper { + display: grid; + grid-template-columns: 3fr 5fr; +} + </style> <input name="filter_field" id="filter_field" type="hidden"/> <div id="grid_wrapper" class="grid_wrapper"> @@ -305,9 +348,14 @@ function add_item_prepopulate(node, prepopulate){ div.id = "dropdown_" + dropdown_count; dropdown_count++; var label = document.createElement("H5"); - label.style['display'] = 'inline'; label.appendChild(document.createTextNode(node['name'])); div.appendChild(label); + button = document.createElement("BUTTON"); + button.type = "button"; + button.appendChild(document.createTextNode("Remove")); + button.classList.add("btn-danger"); + button.classList.add("btn"); + div.appendChild(button); for(var i=0; i<node['forms'].length; i++){ form = node['forms'][i]; var input = document.createElement("INPUT"); @@ -330,14 +378,12 @@ function add_item_prepopulate(node, prepopulate){ hiddenInput.name = "class"; hiddenInput.value = node['id']; div.appendChild(hiddenInput); - button = document.createElement("BUTTON"); button.onclick = function(){ remove_dropdown(div.id); } - button.type = "button"; - button.appendChild(document.createTextNode("Remove")); - div.appendChild(button); document.getElementById("dropdown_wrapper").appendChild(div); + var linebreak = document.createElement("BR"); + document.getElementById("dropdown_wrapper").appendChild(linebreak); updateObjectResult(div); return div; } diff --git a/src/templates/resource/hostprofile_detail.html b/src/templates/resource/hostprofile_detail.html new file mode 100644 index 0000000..0776b9e --- /dev/null +++ b/src/templates/resource/hostprofile_detail.html @@ -0,0 +1,116 @@ +{% extends "base.html" %} +{% load staticfiles %} + +{% block content %} +<div class="row"> + <div class="col-lg-6"> + <div class="panel panel-default"> + <div class="panel-heading clearfix"> + <h4 style="display: inline;">Available at</h4> + <a data-toggle="collapse" data-target="#panel_overview" class="btn pull-right" style="line-height: 1;" >Expand</a> + </div> + <div class="panel-body" id="panel_overview"> + <table class="table"> + <tr> + <td> + <ul> + {% for lab in hostprofile.labs.all %} + <li>{{lab.name}}</li> + {% endfor %} + </ul> + </td> + </tr> + </table> + </div> + </div> + <div class="panel panel-default"> + <div class="panel-heading clearfix"> + <h4 style="display: inline;">RAM</h4> + <a data-toggle="collapse" data-target="#panel_overview" class="btn pull-right" style="line-height: 1;" >Expand</a> + </div> + <div class="panel-body" id="panel_overview"> + <table class="table"> + <tr> + <td>{{hostprofile.ramprofile.first.amount}}G, + {{hostprofile.ramprofile.first.channels}} channels</td> + </tr> + </table> + </div> + </div> + <div class="panel panel-default"> + <div class="panel-heading clearfix"> + <h4 style="display: inline;">CPU</h4> + <a data-toggle="collapse" data-target="#panel_overview" class="btn pull-right" style="line-height: 1;" >Expand</a> + </div> + <div class="panel-body" id="panel_overview"> + <table class="table"> + <tr> + <td>Arch:</td> + <td>{{hostprofile.cpuprofile.first.architecture}}</td> + </tr> + <tr> + <td>Cores:</td> + <td>{{hostprofile.cpuprofile.first.cores}}</td> + </tr> + <tr> + <td>Sockets:</td> + <td>{{hostprofile.cpuprofile.first.cpus}}</td> + </tr> + </table> + </div> + </div> + </div> + <div class="col-lg-6"> + <div class="panel panel-default"> + <div class="panel-heading clearfix"> + <h4 style="display: inline;">Interfaces</h4> + <a data-toggle="collapse" data-target="#panel_overview" class="btn pull-right" style="line-height: 1;" >Expand</a> + </div> + <div class="panel-body" id="panel_overview"> + <table class="table"> + {% for intprof in hostprofile.interfaceprofile.all %} + <tr> + <td> + <table class="table borderless"> + <tr> + <td>Name:</td> + <td>{{intprof.name}}</td> + </tr> + <tr> + <td>Speed:</td> + <td>{{intprof.speed}}</td> + </tr> + </table> + </td> + </tr> + {% endfor %} + </table> + </div> + </div> + </div> + <div class="col-lg-6"> + <div class="panel panel-default"> + <div class="panel-heading clearfix"> + <h4 style="display: inline;">Disk</h4> + <a data-toggle="collapse" data-target="#panel_overview" class="btn pull-right" style="line-height: 1;" >Expand</a> + </div> + <div class="panel-body" id="panel_overview"> + <table class="table"> + <tr> + <td>Size:</td> + <td>{{hostprofile.storageprofile.first.size}} GiB</td> + </tr> + <tr> + <td>Type:</td> + <td>{{hostprofile.storageprofile.first.media_type}}</td> + </tr> + <tr> + <td>Mount Point:</td> + <td>{{hostprofile.storageprofile.first.name}}</td> + </tr> + </table> + </div> + </div> + </div> +</div> +{% endblock content %} diff --git a/src/templates/resource/hosts.html b/src/templates/resource/hosts.html index 4bf64e0..69b7231 100644 --- a/src/templates/resource/hosts.html +++ b/src/templates/resource/hosts.html @@ -17,7 +17,7 @@ {{ host.name }} </td> <td> - {{ host.profile }} + <a href="profiles/{{ host.profile.id }}">{{ host.profile }}</a> </td> <td> {{ host.booked }} diff --git a/src/templates/resource/steps/meta_info.html b/src/templates/resource/steps/meta_info.html index b458842..7a1b56a 100644 --- a/src/templates/resource/steps/meta_info.html +++ b/src/templates/resource/steps/meta_info.html @@ -5,6 +5,28 @@ {% block content %} +<style> +#resource_meta_form { + margin: 80px; + display: grid; +} + +#resource_meta_form td > * { + width: 100%; + margin-bottom: 20px; + margin-top: 20px; +} + +#resource_meta_form > table > tbody > tr { + border-bottom: 1px solid #cccccc; +} + +#resource_meta_form > table > tbody > tr:last-child { + border-bottom: none; +} + +</style> + <form id="resource_meta_form" method="post" action="/wf/workflow/"> {% csrf_token %} <table> diff --git a/src/templates/workflow/viewport-base.html b/src/templates/workflow/viewport-base.html index f78bc01..1329595 100644 --- a/src/templates/workflow/viewport-base.html +++ b/src/templates/workflow/viewport-base.html @@ -84,12 +84,19 @@ background: #0FD57D; } - #viewport-iframe - { - height: calc(100vh - 450); - } - + .iframe_div { + width: calc(100% - 450px); + margin-left: 70px; + height: calc(100vh - 155px); + position: absolute; + border: none; + } + .iframe_elem { + width: 100%; + height: calc(100vh - 155px); + border: none; + } </style> <button id="gof" onclick="go(step+1)" class="btn go_btn go_forward">Go Forward</button> @@ -415,15 +422,7 @@ document.getElementById("view_message").className = "step_message"; document.getElementById("view_message").classList.add("message_" + stepstatus); } - function resize_iframe(){ - var page_rect = document.getElementById("wrapper").getBoundingClientRect(); - var title_rect = document.getElementById("iframe_header").getBoundingClientRect(); - var iframe_height = page_rect.bottom - title_rect.bottom; - document.getElementById("viewport-iframe").height = iframe_height; - } - window.addEventListener('load', resize_iframe); - window.addEventListener('resize', resize_iframe); </script> <!-- /.col-lg-12 --> </div> @@ -433,5 +432,7 @@ </form> </div> -<iframe src="/wf/workflow" style="position: absolute; left: 351px; right: 105px; width: calc(100% - 450px); border-style: none; border-width: 1px; border-color: #888888;" scrolling="yes" id="viewport-iframe" onload="resize_iframe();"></iframe> +<div class="iframe_div"> + <iframe src="/wf/workflow" class="iframe_elem" scrolling="yes" id="viewport-iframe"></iframe> +</div> {% endblock content %} |