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 %} &nbsp;[<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 %} &nbsp;[<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 }} &nbsp;[<a href="/edit_computing_conf?type=user&computing_uuid={{ computing.uuid}}">Edit</a>]</td>
+        <td>{{ data.computing.user_conf_data_json }} &nbsp;[<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>
-        &nbsp; <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">&nbsp;<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}}">&nbsp;&nbsp;&nbsp;&nbsp;</span> <br/>
             <b>Computing:</b> {{ task.computing.name }} <span style="font-size:14px; background-color:{{task.computing.color}}">&nbsp;&nbsp;&nbsp;&nbsp;</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> &gt; {{ 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> &gt;  {{ 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