From 78df5012f3291dce6e6d514914eb6b8c76e2a28b Mon Sep 17 00:00:00 2001 From: Stefano Alberto Russo <stefano.russo@gmail.com> Date: Wed, 6 May 2020 13:34:41 +0200 Subject: [PATCH] Several UI/UX improvements. --- .../rosetta/core_app/computing_managers.py | 2 +- .../management/commands/core_app_populate.py | 12 +++- .../webapp/code/rosetta/core_app/models.py | 13 ++++ .../core_app/static/css/stylish-portfolio.css | 15 ++++- .../core_app/static/img/docker-logo.svg | 1 + .../core_app/static/img/singularity-logo.svg | 23 +++++++ .../templates/components/computing.html | 62 ++++++++++++++----- .../templates/components/container.html | 18 +++--- .../core_app/templates/components/task.html | 62 ++++++++++++++----- .../core_app/templates/computings.html | 2 +- .../core_app/templates/containers.html | 2 + .../core_app/templates/create_task.html | 4 +- .../rosetta/core_app/templates/task_log.html | 2 +- .../webapp/code/rosetta/core_app/views.py | 52 +++++++++++----- 14 files changed, 209 insertions(+), 61 deletions(-) create mode 100644 services/webapp/code/rosetta/core_app/static/img/docker-logo.svg create mode 100644 services/webapp/code/rosetta/core_app/static/img/singularity-logo.svg diff --git a/services/webapp/code/rosetta/core_app/computing_managers.py b/services/webapp/code/rosetta/core_app/computing_managers.py index 89d2ae1..22134d4 100644 --- a/services/webapp/code/rosetta/core_app/computing_managers.py +++ b/services/webapp/code/rosetta/core_app/computing_managers.py @@ -117,7 +117,7 @@ class LocalComputingManager(ComputingManager): task.tid = task_tid task.status = TaskStatuses.running task.ip = task_ip - task.port = int(task.container.default_ports.split(',')[0]) + task.port = int(task.container.ports.split(',')[0]) # Save task.save() diff --git a/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py b/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py index 8f04ffe..de09b00 100644 --- a/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py +++ b/services/webapp/code/rosetta/core_app/management/commands/core_app_populate.py @@ -114,7 +114,9 @@ class Command(BaseCommand): type = 'local', requires_sys_conf = False, requires_user_conf = False, - requires_user_keys = False) + requires_user_keys = False, + supports_docker = True, + supports_singularity = False) #============================== @@ -125,7 +127,9 @@ class Command(BaseCommand): type = 'remote', requires_sys_conf = True, requires_user_conf = True, - requires_user_keys = True) + requires_user_keys = True, + supports_docker = True, + supports_singularity = True) ComputingSysConf.objects.create(computing = demo_remote_auth_computing, data = {'host': 'slurmclusterworker-one'}) @@ -143,7 +147,9 @@ class Command(BaseCommand): type = 'slurm', requires_sys_conf = True, requires_user_conf = True, - requires_user_keys = True) + requires_user_keys = True, + supports_docker = False, + supports_singularity = True) # Create demo slurm sys computing conf ComputingSysConf.objects.create(computing = demo_slurm_computing, diff --git a/services/webapp/code/rosetta/core_app/models.py b/services/webapp/code/rosetta/core_app/models.py index aa06992..0a8b110 100644 --- a/services/webapp/code/rosetta/core_app/models.py +++ b/services/webapp/code/rosetta/core_app/models.py @@ -88,6 +88,10 @@ class Container(models.Model): supports_pass_auth = models.BooleanField(default=False) + class Meta: + ordering = ['name'] + + def __str__(self): return str('Container of type "{}" with image "{}" and ports "{}" from registry "{}" of user "{}"'.format(self.type, self.image, self.ports, self.registry, self.user)) @@ -102,6 +106,8 @@ class Container(models.Model): color_map_index = string_int_hash % len(color_map) return color_map[color_map_index] + + #========================= # Computing resources #========================= @@ -123,6 +129,10 @@ class Computing(models.Model): supports_singularity = models.BooleanField(default=False) + class Meta: + ordering = ['name'] + + def __str__(self): if self.user: return str('Computing "{}" of user "{}"'.format(self.name, self.user)) @@ -247,6 +257,9 @@ class Task(models.Model): # Computing options computing_options = JSONField(blank=True, null=True) + class Meta: + ordering = ['-created'] + def save(self, *args, **kwargs): try: diff --git a/services/webapp/code/rosetta/core_app/static/css/stylish-portfolio.css b/services/webapp/code/rosetta/core_app/static/css/stylish-portfolio.css index ce18de9..b69a79b 100644 --- a/services/webapp/code/rosetta/core_app/static/css/stylish-portfolio.css +++ b/services/webapp/code/rosetta/core_app/static/css/stylish-portfolio.css @@ -86,7 +86,20 @@ body { .btn-connect:hover { color: #fff; - background-color: rgba(0,95,144,1.0); + /*background-color: rgba(0,135,184,1.0);*/ + background-color: rgba(0,145,194,1.0); +} + +.btn-action { + border-radius: 0; + color: rgba(0,95,144,0.8); + border: #c0c0c0 1px solid; + background-color: rgba(250,248,250,1.0); +} + +.btn-action:hover { + color: rgba(0,95,144,0.9); + background-color: rgba(255,255,255,1.0); } .btn-disabled:hover { diff --git a/services/webapp/code/rosetta/core_app/static/img/docker-logo.svg b/services/webapp/code/rosetta/core_app/static/img/docker-logo.svg new file mode 100644 index 0000000..2043cd9 --- /dev/null +++ b/services/webapp/code/rosetta/core_app/static/img/docker-logo.svg @@ -0,0 +1 @@ +<?xml version="1.0" ?><svg enable-background="new 0 0 24 24" id="Layer_1" version="1.1" viewBox="0 0 24 24" xml:space="preserve" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"><g><rect fill="#0175BC" height="2.5" id="XMLID_1489_" width="2.5" x="11" y="3"/><rect fill="#010101" height="0.25" opacity="0.1" width="2.5" x="11" y="5.25"/><rect fill="#FFFFFF" height="0.25" opacity="0.2" width="2.5" x="11" y="3"/><rect fill="#0175BC" height="2.5" id="XMLID_1314_" width="2.5" x="11" y="6"/><rect fill="#010101" height="0.25" opacity="0.1" width="2.5" x="11" y="8.25"/><rect fill="#FFFFFF" height="0.25" opacity="0.2" width="2.5" x="11" y="6"/><rect fill="#0175BC" height="2.5" id="XMLID_1315_" width="2.5" x="11" y="9"/><rect fill="#010101" height="0.25" opacity="0.1" width="2.5" x="11" y="11.25"/><rect fill="#FFFFFF" height="0.25" opacity="0.2" width="2.5" x="11" y="9"/><rect fill="#0175BC" height="2.5" id="XMLID_1307_" width="2.5" x="8" y="6"/><rect fill="#010101" height="0.25" opacity="0.1" width="2.5" x="8" y="8.25"/><rect fill="#FFFFFF" height="0.25" opacity="0.2" width="2.5" x="8" y="6"/><rect fill="#0175BC" height="2.5" id="XMLID_1306_" width="2.5" x="8" y="9"/><rect fill="#010101" height="0.25" opacity="0.1" width="2.5" x="8" y="11.25"/><rect fill="#FFFFFF" height="0.25" opacity="0.2" width="2.5" x="8" y="9"/><rect fill="#0175BC" height="2.5" id="XMLID_1317_" width="2.5" x="5" y="6"/><rect fill="#010101" height="0.25" opacity="0.1" width="2.5" x="5" y="8.25"/><rect fill="#FFFFFF" height="0.25" opacity="0.2" width="2.5" x="5" y="6"/><rect fill="#0175BC" height="2.5" id="XMLID_1316_" width="2.5" x="5" y="9"/><rect fill="#010101" height="0.25" opacity="0.1" width="2.5" x="5" y="11.25"/><rect fill="#FFFFFF" height="0.25" opacity="0.2" width="2.5" x="5" y="9"/><rect fill="#0175BC" height="2.5" id="XMLID_1318_" width="2.5" x="2" y="9"/><rect fill="#010101" height="0.25" opacity="0.1" width="2.5" x="2" y="11.25"/><rect fill="#FFFFFF" height="0.25" opacity="0.2" width="2.5" x="2" y="9"/><rect fill="#0175BC" height="2.5" id="XMLID_1305_" width="2.5" x="14" y="9"/><rect fill="#010101" height="0.25" opacity="0.1" width="2.5" x="14" y="11.25"/><rect fill="#FFFFFF" height="0.25" opacity="0.2" width="2.5" x="14" y="9"/><path d="M23.5947266,11.223134c-0.0693359-0.0449219-1.4980469-0.9472656-2.8486328-0.7324219 c-0.3271484-1.3691406-1.5830078-2.2216797-1.6445313-2.2626953l-0.3476563-0.2314453c0,0-0.2175694,0.2255478-0.2900391,0.3007813 c-0.026474,0.027482-0.0946941,0.1059952-0.1760216,0.2478724c-0.2248478,0.3922462-0.5498848,1.268816-0.3698769,2.8903217 c0.0175781,0.1523438-0.0283203,0.3027344-0.1259766,0.4111328C17.7041016,11.9453125,17.5820313,12,17.4482422,12H0v0.5 C0,20.171875,5.5947266,21,8,21c6.1933594,0,10.4980469-3.7617188,12.3769531-7.0771484 c2.4755859-0.3945313,3.3330078-1.9497175,3.3779297-2.0239363L24,11.4838762L23.5947266,11.223134z" fill="#0175BC"/><path d="M17.4482422,12H0v0.25h17.4482422c0.1337891,0,0.2558594-0.0546875,0.34375-0.1533203 c0.0976563-0.1083984,0.1435547-0.2587891,0.1259766-0.4111328c-0.0057373-0.0515747-0.0048218-0.0927734-0.0095215-0.1428833 c-0.0093384,0.1130981-0.0423584,0.2217407-0.1164551,0.3040161C17.7041016,11.9453125,17.5820313,12,17.4482422,12z" fill="#FFFFFF" opacity="0.2"/><path d="M23.5947266,11.2231445c-0.0693359-0.0449219-1.4980469-0.9472656-2.8486328-0.7324219 c-0.3271484-1.3691406-1.5830078-2.2216797-1.6445313-2.2626953L18.7539063,7.996582c0,0-0.2175713,0.2255449-0.2900391,0.3007813 c-0.0198631,0.0206213-0.0630627,0.0702648-0.1175747,0.1540194c-0.1881866,0.2891331-0.5111847,0.9847698-0.4742222,2.296176 c0.0114746-1.5025024,0.5079956-2.1130981,0.5917969-2.2001953l0.2900391-0.3007813l0.3476563,0.2314453 c0.0615234,0.0410156,1.3173828,0.8935547,1.6445313,2.2626953C22.0966797,10.5258789,24,11.4838867,24,11.4838867 L23.5947266,11.2231445z" fill="#FFFFFF" opacity="0.2"/><path d="M23.7548828,11.6489258c-0.0449219,0.0742188-0.9023438,1.6293945-3.3779297,2.0239258 C18.4980469,16.9882813,14.1933594,20.75,8,20.75c-2.4052734,0-8-0.828125-8-8.5v0.25C0,20.171875,5.5947266,21,8,21 c6.1933594,0,10.4980469-3.7617188,12.3769531-7.0771484c2.4755859-0.3945313,3.3330078-1.949707,3.3779297-2.0239258 L24,11.4838867l-0.1069946-0.0688477L23.7548828,11.6489258z" fill="#010101" opacity="0.1"/><linearGradient gradientUnits="userSpaceOnUse" id="SVGID_1_" x1="1.7255629" x2="21.2413311" y1="8.2995186" y2="17.3998699"><stop offset="0" style="stop-color:#FFFFFF;stop-opacity:0.2"/><stop offset="1" style="stop-color:#FFFFFF;stop-opacity:0"/></linearGradient><path d="M13.5,6H11v2.5h2.5V6z M13.5,9H11v2.5h2.5V9z M16.5,9H14v2.5h2.5V9z M13.5,3H11v2.5h2.5V3z M10.5,6 H8v2.5h2.5V6z M4.5,9H2v2.5h2.5V9z M23.5947266,11.2231445c-0.0693359-0.0449219-1.4980469-0.9472656-2.8486328-0.7324219 c-0.3271484-1.3691406-1.5830078-2.2216797-1.6445313-2.2626953L18.7539063,7.996582c0,0-0.2175903,0.2255249-0.2900391,0.3007813 c-0.0264893,0.0274658-0.0946655,0.105957-0.1760254,0.2478638c-0.2248535,0.3922119-0.5498657,1.2687988-0.369873,2.8903198 c0.0175781,0.1523438-0.0283203,0.3027344-0.1259766,0.4111328C17.7041016,11.9453125,17.5820313,12,17.4482422,12H0v0.5 C0,20.171875,5.5947266,21,8,21c6.1933594,0,10.4980469-3.7617188,12.3769531-7.0771484 c2.4755859-0.3945313,3.3330078-1.949707,3.3779297-2.0239258L24,11.4838867L23.5947266,11.2231445z M10.5,9H8v2.5h2.5V9z M7.5,6H5 v2.5h2.5V6z M7.5,9H5v2.5h2.5V9z" fill="url(#SVGID_1_)"/></g><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/><g/></svg> \ No newline at end of file diff --git a/services/webapp/code/rosetta/core_app/static/img/singularity-logo.svg b/services/webapp/code/rosetta/core_app/static/img/singularity-logo.svg new file mode 100644 index 0000000..229bf86 --- /dev/null +++ b/services/webapp/code/rosetta/core_app/static/img/singularity-logo.svg @@ -0,0 +1,23 @@ +<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="360" height="360" viewBox="0 0 360 360"> + <defs> + <filter id="Ellipse_2" x="0" y="0" width="360" height="360" filterUnits="userSpaceOnUse"> + <feOffset dy="1" input="SourceAlpha"/> + <feGaussianBlur stdDeviation="3" result="blur"/> + <feFlood flood-opacity="0.349"/> + <feComposite operator="in" in2="blur"/> + <feComposite in="SourceGraphic"/> + </filter> + </defs> + <g id="singularity-logo" transform="translate(-3757.012 -1045.683)"> + <g transform="matrix(1, 0, 0, 1, 3757.01, 1045.68)" filter="url(#Ellipse_2)"> + <circle id="Ellipse_2-2" data-name="Ellipse 2" cx="171" cy="171" r="171" transform="translate(9 8)" fill="#fff"/> + </g> + <g id="Group_50" data-name="Group 50" transform="translate(0 0.673)"> + <path id="Path_135" data-name="Path 135" d="M3936.318,1066.01c-85.064.255-153.98,70.708-154.306,157.708h31.851c.326-68.779,55-124.451,122.454-124.621Z" fill="#21a1da"/> + <path id="Path_136" data-name="Path 136" d="M4304,1066.473v33.133c64.438,3.591,115.645,57.874,115.96,124.432h32.161C4451.8,1139.156,4386.194,1070.027,4304,1066.473Z" transform="translate(-360.57 -0.32)" fill="#8ac13f"/> + <path id="Path_137" data-name="Path 137" d="M3936.629,1718.436c-65.424-.165-118.82-52.535-122.278-118.436h-31.888c3.477,84.13,71.128,151.274,154.166,151.523Z" transform="translate(-0.311 -368.86)" fill="#bcbdc0"/> + <path id="Path_138" data-name="Path 138" d="M4419.784,1600c-3.343,63.707-53.354,114.768-115.784,118.247v33.133c80.189-3.467,144.591-69.348,147.981-151.38Z" transform="translate(-360.57 -368.86)" fill="#f3931e"/> + <path id="Path_139" data-name="Path 139" d="M4140.016,1369.155s-7.421-2.783-18.554-7.422c-14.843-6.185-12.06-12.679-12.06-12.679s3.092-10.823,21.337-7.112c19.036,3.872,33.088,23.811,33.088,23.811l18.245-52.261c-28.141-11.442-70.365-11.985-88.442-10.2-40.819,4.02-57.827,28.078-57.827,52.416,0,18.634,6.8,32.315,22.72,41.011,18.942,11.825,36.179,12.8,40.982,21.61,6.36,11.661-8.658,13.916-8.658,13.916-24.739,1.855-43.912-25.667-43.912-25.667L4029,1461.308c69.578,23.5,117.51,7.422,117.51,7.422,21.956-7.422,38.964-22.574,38.964-48.241C4185.474,1395.212,4170.94,1380.288,4140.016,1369.155Z" transform="translate(-170.61 -163.373)" fill="#1d315f"/> + </g> + </g> +</svg> diff --git a/services/webapp/code/rosetta/core_app/templates/components/computing.html b/services/webapp/code/rosetta/core_app/templates/components/computing.html index 8945613..44ef020 100644 --- a/services/webapp/code/rosetta/core_app/templates/components/computing.html +++ b/services/webapp/code/rosetta/core_app/templates/components/computing.html @@ -1,65 +1,97 @@ + {% if data.computing %} + <div style="float:left; width:500px; margin:10px; margin-bottom:20px"> <table class="dashboard" style="width:100%"> <tr> - <td colspan="2" style="background:{{ computing.color }}; height:30px"> + <td colspan="2" style="background:{{ data.computing.color }}; height:25px"> </td> </tr> <tr> <td><b>Name</b></td> - <td>{{ computing.name }}</td> + <td>{{ data.computing.name }}</td> </tr> <tr> <td width="110px"><b>ID</b></td> - <td>{{ computing.id }}</a></td> + <td>{{ data.computing.id }}</a></td> </tr> <tr> <td><b>Type</b></td> - <td>{{ computing.type }}</td> + <td>{{ data.computing.type }}</td> </tr> <tr> <td><b>Owner</b></td> - <td>{% if computing.user %}{{ computing.user }}{% else %}platform{% endif %}</td> + <td>{% if data.computing.user %}{{ data.computing.user }}{% else %}platform{% endif %}</td> </tr> <tr> <td><b>Require</b></td> <td> - Sys conf: {{ computing.requires_sys_conf }} <br/> - User conf: {{ computing.requires_user_conf }} <br/> - User keys: {{ computing.requires_user_keys }} + Sys conf: {{ data.computing.requires_sys_conf }} <br/> + User conf: {{ data.computing.requires_user_conf }} <br/> + User keys: {{ data.computing.requires_user_keys }} </td> </tr> <tr> <td><b>Supports</b></td> <td> - Docker: {{ computing.supports_docker }} <br/> - Singularity: {{ computing.supports_singularity }} + Docker: {{ data.computing.supports_docker }} <br/> + Singularity: {{ data.computing.supports_singularity }} </td> </tr> <tr> <td><b>Sys Conf</b></td> - <td>{{ computing.sys_conf_data_json }} {% if request.user.is_superuser %} [<a href="/edit_computing_conf?type=sys&computing_uuid={{ computing.uuid}}">Edit</a>] {% endif %}</td> + <td>{{ data.computing.sys_conf_data_json }} {% if request.user.is_superuser %} [<a href="/edit_computing_conf?type=sys&computing_uuid={{ data.computing.uuid}}">Edit</a>] {% endif %}</td> </tr> <tr> <td><b>User Conf</b></td> - <td>{{ computing.user_conf_data_json }} [<a href="/edit_computing_conf?type=user&computing_uuid={{ computing.uuid}}">Edit</a>]</td> + <td>{{ data.computing.user_conf_data_json }} [<a href="/edit_computing_conf?type=user&computing_uuid={{ data.computing.uuid}}">Edit</a>]</td> </tr> - {% if computing.user %} + {% if data.computing.user %} <tr> <td><b>Operations</b></td> - <td><a href="?action=delete&uuid={{ computing.uuid }}">Delete</a></td> + <td><a href="?action=delete&uuid={{ data.computing.uuid }}">Delete</a></td> </tr> {% endif %} </table> - </div> \ No newline at end of file + </div> + + {% else %} + + <div style="width:300px; float:left; border: #e0e0e0 solid 1px; margin:10px; background:#f8f8f8; margin-bottom:15px"> + <div style="background:{{computing.color}}; height:24px"></div> + + <div style="padding:10px; margin-top:5px; text-align:center; border-bottom: #e0e0e0 solid 1px; "> + <a href="?uuid={{ computing.uuid }}&details=True">{{ computing.name }}</a> + </div> + + <div style="padding:10px;"> + <b>Type:</b> {{ computing.type.title }}<br/> + <b>Owner:</b> {% if computing.user %}{{ data.computing.user }}{% else %}Platform{% endif %}<br/> + <b>Supports:</b> + {% if computing.supports_docker %}Docker <img src="/static/img/docker-logo.svg" style="height:18px; width:18px; margin-bottom:2px" />{% endif %} + {% if computing.supports_singularity %}Singularity <img src="/static/img/singularity-logo.svg" style="height:18px; width:18px; margin-bottom:2px" />{% endif %} + </div> + + + + + + </div> + + + + {% endif %} + + + \ No newline at end of file diff --git a/services/webapp/code/rosetta/core_app/templates/components/container.html b/services/webapp/code/rosetta/core_app/templates/components/container.html index 352a5de..ec9c7f6 100644 --- a/services/webapp/code/rosetta/core_app/templates/components/container.html +++ b/services/webapp/code/rosetta/core_app/templates/components/container.html @@ -87,21 +87,25 @@ {% else %} - <div style="width:300px; float:left; border: #e0e0e0 solid 1px; margin:10px; background:#f8f8f8; margin-bottom:20px"> - <div style="background:{{container.color}}; height:24px"></div> + <div style="width:300px; float:left; border: #e0e0e0 solid 1px; margin:10px; background:#f8f8f8; margin-bottom:15px"> + <div style="background:{{container.color}}; height:24px;"> + </div> - <div style="padding:10px; text-align:center; border-bottom: #e0e0e0 solid 1px; "> + <div style="padding:10px; margin-top:5px; text-align:center; border-bottom: #e0e0e0 solid 1px; "> <a href="?uuid={{ container.uuid }}">{{ container.name }}</a> - <a href="/create_task?container_uuid={{ container.uuid }}"><i class="fa fa-play" style="color:green"></i></a> </div> <div style="padding:10px;"> - Type: {{ container.type }}<br/> - Image: {{ container.image }} + <b>Type:</b> {{ container.type.title }} + {% if container.type == 'docker' %}<img src="/static/img/docker-logo.svg" style="height:18px; width:18px; margin-bottom:2px" />{% endif %} + {% if container.type == 'singularity' %}<img src="/static/img/singularity-logo.svg" style="height:18px; width:18px; margin-bottom:2px" />{% endif %} + + <br/> + <b>Image:</b> {{ container.image }} </div> <div style="margin-bottom:10px; text-align:center"> - + <a href="/create_task?container_uuid={{ container.uuid }}" class="btn btn-light" style="border: #c0c0c0 1px solid"> <i class="fa fa-play" style="color:green"></i></a> </div> diff --git a/services/webapp/code/rosetta/core_app/templates/components/task.html b/services/webapp/code/rosetta/core_app/templates/components/task.html index c0920e4..73d3970 100644 --- a/services/webapp/code/rosetta/core_app/templates/components/task.html +++ b/services/webapp/code/rosetta/core_app/templates/components/task.html @@ -1,10 +1,20 @@ - {% if details %} + {% if data.task %} <table class="dashboard"> + <!-- <tr> + <td colspan="2"> + <div> + <div style="background:{{task.container.color}}; height:24px; width:149px; float:left"></div> + <div style="background:{{task.computing.color}}; height:24px; width:149px; float:left"></div> + </div> + </td> + </tr> + --> + <tr> <td><b>Name</b></td> <td>{{ task.name }}</td> @@ -92,43 +102,65 @@ {% else %} <div style="width:300px; float:left; border: #e0e0e0 solid 1px; margin:10px; background:#f8f8f8; margin-bottom:20px"> - <!-- <div> - <div style="background:{{task.container.color}}; height:24px; width:149px; float:left"></div> - <div style="background:{{task.computing.color}}; height:24px; width:149px; float:left"></div> - </div> --> + + <!-- <div style="background:{{task.color}}; height:24px;"></div> --> - <div style="padding:10px; text-align:center; border-bottom: #e0e0e0 solid 1px; "> + <div style="margin-top:5px; padding:10px; text-align:center; border-bottom: #e0e0e0 solid 1px; "> <a href="?uuid={{ task.uuid }}"><b>{{ task.name }}</b></a> </div> + + <!-- <div style="background:{{ task.container.color }}; height:14px;"></div> --> + + <!-- <div style="margin-bottom:15px; margin-top:0px"> + <div style="background:{{task.container.color}}; height:14px; width:149px; float:left"></div> + <div style="background:{{task.computing.color}}; height:14px; width:149px; float:left"></div> + </div> --> + <div style="padding:10px;"> <!-- <b>Container:</b> {{ task.container.name }} <span style="font-size:14px; background-color:{{task.container.color}}"> </span> <br/> <b>Computing:</b> {{ task.computing.name }} <span style="font-size:14px; background-color:{{task.computing.color}}"> </span><br/> --> - <b>Container:</b> {{ task.container.name }} - <a href="/containers/?uuid={{ task.container.uuid }}" style="color:{{task.container.color}}"><i class="fa fa-external-link" ></i></a> <br/> + <b>Container:</b> + {{ task.container.name }} + {% if task.container.type == 'docker' %}<img src="/static/img/docker-logo.svg" style="height:18px; width:18px; margin-bottom:4px" />{% endif %} + {% if task.container.type == 'singularity' %}<img src="/static/img/singularity-logo.svg" style="height:18px; width:18px; margin-bottom:4px" />{% endif %} + <a href="/containers/?uuid={{ task.container.uuid }}" style="color:{{task.container.color}}"><i class="fa fa-external-link" ></i></a> + <br/> <b>Computing:</b> {{ task.computing.name }} - <a href="/computings/" style="color:{{task.computing.color}}"><i class="fa fa-external-link" ></i></a><br/> - + <a href="/computings/?uuid={{ task.computing.uuid }}" style="color:{{task.computing.color}}"><i class="fa fa-external-link" ></i></a><br/> + <div style="margin-top:2px"> {% if task.status == "running" %} <b>Status:</b> <font color="green">running</font> {% else %} <b>Status:</b> {{ task.status }} {% endif %} </div> - + </div> + <div style="margin-bottom:10px; text-align:center; padding:5px"> + + <!-- Stop / Delete --> + {% if task.status == "stopped" %} + <a href="?uuid={{task.uuid}}&action=delete&fromlist=True" class="btn btn-action">Delete</a> + {% else %} + <a href="?uuid={{task.uuid}}&action=stop&fromlist=True" class="btn btn-action">Stop</a> + {% endif %} + + <!-- Connect --> {% if task.status == "running" %} <a href="?uuid={{task.uuid}}&action=connect" class="btn btn-connect">Connect</a> {% else %} - <a href="?uuid={{task.uuid}}&action=connect" class="btn btn-disabled">Connect</a> - {% endif %} - - + <a href="" class="btn btn-disabled">Connect</a> + {% endif %} + + <!-- View log --> + <a href="/task_log/?uuid={{task.uuid}}&action=viewlog" class="btn btn-action">Logs</a> + </div> diff --git a/services/webapp/code/rosetta/core_app/templates/computings.html b/services/webapp/code/rosetta/core_app/templates/computings.html index efaa389..01dee2d 100644 --- a/services/webapp/code/rosetta/core_app/templates/computings.html +++ b/services/webapp/code/rosetta/core_app/templates/computings.html @@ -10,7 +10,7 @@ <div class="span8 offset2"> {% if data.computing %} - <h1><a href="/computings">Computing</a> > {{ data.computing.id }} </h1> + <h1><a href="/computings">Computing</a> <span style="font-size:18px"> / {{ data.computing.name }}</span></h1> {% else %} <h1>Computing</h1> {% endif %} diff --git a/services/webapp/code/rosetta/core_app/templates/containers.html b/services/webapp/code/rosetta/core_app/templates/containers.html index 5ed6480..e9ff0f1 100644 --- a/services/webapp/code/rosetta/core_app/templates/containers.html +++ b/services/webapp/code/rosetta/core_app/templates/containers.html @@ -26,9 +26,11 @@ {% endif %} </div> + {% if not data.container %} <div class="row" style="padding:10px; padding-left:15px"> <a href="/add_container">Add new...</a> </div> + {% endif %} <br/> <br/> diff --git a/services/webapp/code/rosetta/core_app/templates/create_task.html b/services/webapp/code/rosetta/core_app/templates/create_task.html index 84545a0..ead1b8d 100644 --- a/services/webapp/code/rosetta/core_app/templates/create_task.html +++ b/services/webapp/code/rosetta/core_app/templates/create_task.html @@ -36,12 +36,12 @@ <td><b>Task container</b></td><td> {% if data.container %} <select name="task_container_uuid"> - <option value="{{data.container.uuid}}" selected>{{data.container.name}} ({{data.container.type}})</option> + <option value="{{data.container.uuid}}" selected>{{data.container.name}} ({{data.container.type.title}})</option> </select> {% else %} <select name="task_container_uuid" > {% for container in data.containers %} - <option value="{{container.uuid}}">{{container.name}} ({{container.type}})</option> + <option value="{{container.uuid}}">{{container.name}} ({{container.type.title}})</option> {% endfor %} </select> {% endif %} diff --git a/services/webapp/code/rosetta/core_app/templates/task_log.html b/services/webapp/code/rosetta/core_app/templates/task_log.html index 071f285..2a842cb 100644 --- a/services/webapp/code/rosetta/core_app/templates/task_log.html +++ b/services/webapp/code/rosetta/core_app/templates/task_log.html @@ -9,7 +9,7 @@ <div class="dashboard"> <div class="span8 offset2"> - <h1><a href="/tasks/">Task List</a> > {{ data.task.id }} Log</h1> + <h1><a href="/tasks">Tasks</a> <span style="font-size:18px"> / <a href="/tasks/?uuid={{data.task.uuid}}">{{ data.task.name }}</a> / Log</span></h1> <hr> diff --git a/services/webapp/code/rosetta/core_app/views.py b/services/webapp/code/rosetta/core_app/views.py index 07b87b6..9d6a91f 100644 --- a/services/webapp/code/rosetta/core_app/views.py +++ b/services/webapp/code/rosetta/core_app/views.py @@ -211,12 +211,8 @@ def entrypoint(request): @public_view def main_view(request): - # Get action - action = request.POST.get('action', None) - - # Set data + # Set data & render data = {} - data['action'] = action return render(request, 'main.html', {'data': data}) @@ -316,10 +312,9 @@ def tasks(request): # Get action if any action = request.GET.get('action', None) uuid = request.GET.get('uuid', None) + fromlist = request.GET.get('fromlist', False) details = booleanize(request.GET.get('details', None)) - # Setting var - standby_supported = False # Do we have to operate on a specific task? if uuid: @@ -416,6 +411,17 @@ def tasks(request): logger.error('Error in getting the task with uuid="{}" or performing the required action: "{}"'.format(uuid, e)) return render(request, 'error.html', {'data': data}) + # Ok, redirect if there was an action + if action: + if fromlist: + return redirect('/tasks') + else: + if not task.uuid: + # it has just been deleted + return redirect('/tasks') + else: + return redirect('/tasks/?uuid={}'.format(task.uuid)) + # Do we have to list all the tasks? if not uuid or (uuid and not details): @@ -643,8 +649,8 @@ def containers(request): data['profile'] = Profile.objects.get(user=request.user) # Get action if any - action = request.GET.get('action', None) uuid = request.GET.get('uuid', None) + action = request.GET.get('action', None) # Do we have to operate on a specific container? if uuid: @@ -788,14 +794,29 @@ def computings(request): data['profile'] = Profile.objects.get(user=request.user) data['title'] = 'Computing resources' data['name'] = request.POST.get('name',None) - - data['computings'] = list(Computing.objects.filter(user=None)) + list(Computing.objects.filter(user=request.user)) - # Attach user conf in any - for computing in data['computings']: - computing.attach_user_conf_data(request.user) - computing.user_conf_data_json = json.dumps(computing.user_conf_data) - computing.sys_conf_data_json = json.dumps(computing.sys_conf_data) + # Get action/details if any + uuid = request.GET.get('uuid', None) + action = request.GET.get('action', None) + details = booleanize(request.GET.get('details', None)) + computing_uuid = request.GET.get('uuid', None) + data['details'] = details + data['action'] = action + + if details and computing_uuid: + try: + data['computing'] = Computing.objects.get(uuid=computing_uuid, user=request.user) + except Computing.DoesNotExist: + data['computing'] = Computing.objects.get(uuid=computing_uuid, user=None) + + else: + data['computings'] = list(Computing.objects.filter(user=None)) + list(Computing.objects.filter(user=request.user)) + # Attach user conf in any + for computing in data['computings']: + computing.attach_user_conf_data(request.user) + computing.user_conf_data_json = json.dumps(computing.user_conf_data) + computing.sys_conf_data_json = json.dumps(computing.sys_conf_data) + return render(request, 'computings.html', {'data': data}) @@ -898,6 +919,7 @@ def edit_computing_conf(request): computingUserConf.data = new_conf_data computingUserConf.save() data['saved'] = True + return HttpResponseRedirect('/computings') # Dump conf data for the webpage if computingUserConf.data: -- GitLab