moved requests to management
authorCiro Scognamiglio <ciro.scognamiglio@cslash.net>
Thu, 3 Jul 2014 15:54:59 +0000 (17:54 +0200)
committerCiro Scognamiglio <ciro.scognamiglio@cslash.net>
Thu, 3 Jul 2014 15:54:59 +0000 (17:54 +0200)
myslice/urls.py
portal/static/css/onelab.css
portal/templates/onelab/onelab_institution.html
portal/templates/onelab/onelab_management-tab-requests.html [new file with mode: 0644]
portal/templates/onelab/onelab_widget-topmenu.html
portal/templates/slicerequest_view.html
portal/templates/supportview.html
portal/validationview.py

index a49156e..403db6a 100644 (file)
@@ -31,6 +31,8 @@ import portal.slicetabtestbeds
 import portal.slicetabusers
 import portal.slicetabmeasurements 
 
+import portal.managementtabrequests
+
 #### high level choices
 # main entry point (set to the / URL)
 # beware that if this view is broken you end up in an endless cycle...
@@ -90,6 +92,9 @@ urls = [
     (r'^testbeds/(?P<slicename>[^/]+)/?$', portal.slicetabtestbeds.SliceTabTestbeds.as_view()),
     (r'^measurements/(?P<slicename>[^/]+)/?$', portal.slicetabmeasurements.SliceTabMeasurements.as_view()),
     (r'^experiment/(?P<slicename>[^/]+)/?$', portal.slicetabexperiment.ExperimentView.as_view()),
+    #
+    (r'^management/requests/?$', portal.managementtabrequests.ManagementRequestsView.as_view()),
+    #
     url(r'^portal/', include('portal.urls')),
 
     # SLA
index d658262..0d97f92 100644 (file)
@@ -32,27 +32,73 @@ h3 {
     font-size:13pt;
     color:#201E62;
 }
-
-div.wrapper {
-    width:980px;
-    margin:0 auto;
-    position:relative;
-}
-div.container {
-    /*width:980px;
-    margin:25px auto;*/
-}
-div.wide {
-    margin:25px auto;
-    padding:0 25px;
-}
-
 span.label {
     font-size:11pt;
     color:gray;
     font-weight:normal;
     padding:0;
 }
+div.el {
+    padding-bottom:15px;
+}
+/* buttons */
+button.btn {
+    padding:6px 10px;
+    border-radius:5px;
+    font-size:10pt;
+    font-weight:normal;
+}
+button.btn span.glyphicon {
+    margin-right:6px;
+}
+button.btn-default {
+    border-bottom:3px solid #cccccc;
+}
+button.btn-default:hover {
+    background-color:white;
+    border:1px solid #ADADAD;
+    border-bottom:3px solid #ADADAD;
+}
+button.btn-default:active {
+    background-color:white;
+    border:1px solid #ADADAD;
+    border-bottom:1px solid #ADADAD;
+    box-shadow:none;
+}
+button.btn-primary {
+    border-bottom:3px solid #3071A9;
+}
+button.btn-primary:hover {
+    border-bottom:3px solid #3071A9;
+}
+button.btn-primary:active {
+    box-shadow:none;
+}
+button.btn-danger {
+    border-bottom:2px solid #FF7394;
+}
+button.btn-danger:hover {
+    border-bottom:2px solid #D2322D;
+}
+button.btn-danger:active {
+    border:1px solid #D2322D;
+    box-shadow:none;
+}
+button.btn-onelab {
+    border:0;
+    border-bottom:2px solid #540086;
+    background-color:#302562;
+    color:white;
+}
+button.btn-onelab:hover {
+    border:0;
+    border-bottom:2px solid #540086;
+    background-color:#302562;
+    color:#FFFFCC;
+}
+button.btn-primary:active {
+    box-shadow:none;
+}
 /***** Notifications *****/
 .warning {
     border: 1px solid red;
@@ -143,15 +189,6 @@ div#home-dashboard div#home-slice-list li {
 div.well {
 }
 /**/
-/* BUTTON */
-.btn.btn-default {
-    font-weight: bold;
-}
-
-.btn.btn-default:hover {
-    font-weight: bold;
-}
-/**/
 /* TABLE */
 table.table {
     margin:0;
@@ -371,6 +408,7 @@ div.dataTables_filter label{
   -webkit-box-shadow: 0 0 1px rgba(82,82,82,0.6);
   box-shadow:         0 0 1px rgba(82,82,82,0.6);
   height:61px;
+  margin-bottom:15px;
   background-color:white;
 }
 div.navigation {
index 409c13f..7fea635 100644 (file)
                                <li class="active"><a href="#info"><img src="{{ STATIC_URL }}icons/authority-xs.png" alt="Institution" /> Institution {{user_details.parent_authority}}</a></li>
                                <li><a href="#users">Users</a></li>
                                <li><a href="#slices">Slices</a></li>
+                               <li><a href="#requests">Requests</a></li>
                        </ul>
            </div>
        </div>
 </div>
 <div class="container tab-content">
        <div class="tab-pane active row" id="info">
-               <div class="col-md-12">
+               <div class="col-md-12 el">
                        <div id="authority-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Authority" /></div>
                    <div id="authority-tab-loaded" style="display:none;">
                        <div id="authority-data" style="float:left; width:50%;"></div>
        </div>
        
        <div class="tab-pane row" id="users" data-authority="{{user_details.parent_authority}}">
-               <div class="col-md-12">
+               <div class="col-md-12 el">
                        <div id="user-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
                                <div id="user-tab-loaded" style="display:none;">
-                               <table id="user-tab">
+                               <table id="user-tab" class="table">
                                        <tr>
                                        <th>+/-</th>
-                                       <th>email</th>
-                                       <th>user_hrn</th>
-                                       <th>first name</th>
-                                       <th>last name</th>
-                                       <th>enabled</th>
+                                       <th>Email</th>
+                                       <th>User hrn</th>
+                                       <th>First name</th>
+                                       <th>Last name</th>
+                                       <th>Enabled</th>
                                        </tr>
                                </table>
-                               {%if 'is_pi'  in pi %}  
-                               <div>
-                                       <button id="deleteusers" type="button" class="btn btn-default"><span class="glyphicon glyphicon-remove"></span> Delete Users</button>
-                               </div>
-                               {%endif%}
+                               
                        </div>
+                       {%if 'is_pi'  in pi %}  
+                       <div>
+                               <button id="deleteusers" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete selected users</button>
+                       </div>
+                       {% endif %}
                </div>
        </div>
 
        <div class="tab-pane row" id="slices">
-               {%if 'is_pi'  in pi %}
-               <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> create slice</button>
-               {%else%}
-               <button id="createslice" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> request slice</button>
-               {%endif%}
+               <div class="col-md-12 el">
+               {% if 'is_pi'  in pi %}
+               <button id="createslice" type="button" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create slice</button>
+               {% else %}
+               <button id="createslice" type="button" class="btn btn-onelab"><span class="glyphicon glyphicon-plus"></span> Request slice</button>
+               {% endif %}
+               <br /><br />
            <div id="slice-tab-loading"><img src="{{ STATIC_URL }}img/loading.gif" alt="Loading Slices" /></div>
            <div id="slice-tab-loaded" style="display:none;">
-               <table id="slice-tab">
+               <table id="slice-tab" class="table">
                    <tr>
                        <th>+/-</th>
-                       <th>slice_hrn</th>
-                       <th>users</th>
-                       <th>url</th>
+                       <th>Slice hrn</th>
+                       <th>Users</th>
+                       <th>Url</th>
                        <!-- <th>nodes</th> -->
-                       <th>expiration</th>
+                       <th>Expiration</th>
                    </tr>
-               </table>
-               <br>
-                       {%if 'is_pi'  in pi %}
-               <div>
-                   <button id="renewslices" type="button" class="btn btn-default"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
-                   <button id="deleteslices" type="button" class="btn btn-default"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
-               </div>
-                       {%endif%} 
+               </table>                        
            </div>
+       {% if 'is_pi'  in pi %}
+        <div>
+            <button id="renewslices" type="button" class="btn btn-primary"><span class="glyphicon glyphicon-refresh"></span> Renew Slices</button>
+            <button id="deleteslices" type="button" class="btn btn-danger"><span class="glyphicon glyphicon-remove"></span> Delete Slices</button>
+        </div>
+               {% endif %} 
+          </div>
+       </div>
+       <div class="tab-pane row" id="requests">
        </div>
 </div>
 <script>
@@ -213,5 +219,15 @@ $(document).ready(function() {
     {% endif %}
 
 }); // End document.ready
+
+$(document).ready(function() {
+       $('.nav-tabs a').click(function (e) {
+               e.preventDefault();
+               $(this).tab('show');
+       var id = $(this).attr('href').substr(1);
+       if (id == 'requests') 
+               $("#" + id).load('/management/' + id);
+       });
+});
 </script>
 {% endblock %}
diff --git a/portal/templates/onelab/onelab_management-tab-requests.html b/portal/templates/onelab/onelab_management-tab-requests.html
new file mode 100644 (file)
index 0000000..8db652f
--- /dev/null
@@ -0,0 +1,228 @@
+<script type="text/javascript">
+       $(document).ready(function() {
+               $("li#nav-request").addClass("active");
+       });
+       function on_click_event() {
+               var ids = []; 
+               $('.portal__validate__checkbox').each(function(i, el) {
+                       if ($(el).prop('checked')) {
+                               // portal__validate__checkbox__slice__2
+                               var id_array = $(el).attr('id').split('__');
+                               // push(slice__2)
+                               ids.push(id_array[3] + '__' + id_array[4]);
+                       }
+               });
+               if (ids.length > 0) {
+                       var id_str = ids.join('/');
+
+                       // XXX spinner
+
+                       $.getJSON('/portal/validate_action/' + id_str,
+                               function(status) {
+                                       $.each(status, function(request_type__id, request_status) {
+                                               // request_status: NAME -> dict (status, description)
+                                               var status_str = '';
+                                               $.each(request_status, function(name, result) {
+                                                       if (status_str != '')
+                                                               status_str += ' -- ';
+
+                                                       if (result.status) {
+                                                               status_str += '<font color="green">OK</font>';
+                                                               $('#portal__validate__checkbox__' + request_type__id).hide();
+                                                       } else {
+                                                               status_str += '<font color="red">ERROR: ' + result.description + '</font>';
+                                                       }
+                                               });
+                                               $('#portal__status__' + request_type__id).html(status_str);
+
+
+                                       });
+                               }
+                       );
+               }
+       }
+</script>
+
+<div class="col-md-12">
+       <h2>Authorities</h2>
+</div>
+{% if my_authorities %}
+       
+       {% for authority, requests in my_authorities.items %}
+       
+       <div class="col-md-12">
+               <h2>{{authority}}</h2>
+       </div>
+       
+    <table class="table">
+      <th>
+        <td>Type</td>
+        <td>Id</td>
+        <td>Details</td>
+        <td>Timestamp</td>
+        <td>Status</td>
+      </th>
+    {% for request in requests %}
+
+         <tr>
+               <td>
+               {% if request.allowed == 'allowed' %}
+               <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
+               {% else %}
+                       {% if request.allowed == 'expired' %}
+                               expired
+                       {% else %} {# denied #}
+                               denied
+                       {% endif %}
+               {% endif %}
+               </td>
+               <td>{{ request.type }}</td>
+               <td>{{ request.id }}</td>
+               <td>
+        {% if request.type == 'user' %}
+        Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
+        {% else %}
+            {% if request.type == 'slice' %}
+        Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+            {% else %} {# authority #}
+        Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
+            {% endif %}
+        {% endif %}
+               </td>
+               <td>{{ request.timestamp }}</td>
+               
+               <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
+
+    <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
+         </tr>
+
+    {% endfor %}
+       </table>
+       </div>
+       {% endfor %}
+
+{% else %}
+       <div class="col-md-12">
+               <i>There is no pending request waiting for validation.</i>
+       </div>
+{% endif %}
+
+<div class="col-md-12">
+       <h2>Sub-Authorities</h2>
+</div>
+{% if sub_authorities %}
+       
+       {% for authority, requests in sub_authorities.items %}
+       <div class="col-md-12">
+       <h3>{{authority}}</h3>
+           <table class="table">
+             <th>
+               <td>Type</td>
+               <td>Id</td>
+               <td>Details</td>
+               <td>Timestamp</td>
+               <td>Status</td>
+             </th>
+           {% for request in requests %}
+                 <tr>
+                       <td>
+                       {% if request.allowed == 'allowed' %}
+                       <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
+                       {% else %}
+                               {% if request.allowed == 'expired' %}
+                                       expired
+                               {% else %} {# denied #}
+                                       denied
+                               {% endif %}
+                       {% endif %}
+                       </td>
+                       <td>{{ request.type }}</td>
+                       <td>{{ request.id }}</td>
+                       <td>
+               {% if request.type == 'user' %}
+               Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
+               {% else %}
+                   {% if request.type == 'slice' %}
+               Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+                   {% else %} {# authority #}
+               Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
+                   {% endif %}
+               {% endif %}
+                       </td>
+                       <td>{{ request.timestamp }}</td>
+                       
+                       <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
+       
+           <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
+                 </tr>
+           {% endfor %}
+           </table>
+       </div>
+       {% endfor %}
+{% else %}
+<div class="col-md-12">
+       <i>There is no pending request waiting for validation.</i>
+</div>
+{% endif %}
+
+<div class="col-md-12">
+       <h2>Authorities with delegation</h2>
+</div>
+
+{% if delegation_authorities %}
+       
+       {% for authority, requests in delegation_authorities.items %}
+       <div class="col-md-12">
+               <h3>{{authority}}</h3>
+                   <table class="table">
+                     <th>
+                       <td>Type</td>
+                       <td>Id</td>
+                       <td>Details</td>
+                       <td>Timestamp</td>
+                       <td>Status</td>
+                     </th>
+                   {% for request in requests %}
+                         <tr>
+                               <td>
+                               {% if request.allowed == 'allowed' %}
+                               <input class='portal__validate__checkbox' id='portal__validate__checkbox__{{request.type}}__{{request.id}}' type='checkbox'/>
+                               {% else %}
+                                       {% if request.allowed == 'expired' %}
+                                               expired
+                                       {% else %} {# denied #}
+                                               denied
+                                       {% endif %}
+                               {% endif %}
+                               </td>
+                               <td>{{ request.type }}</td>
+                               <td>{{ request.id }}</td>
+                               <td>
+                       {% if request.type == 'user' %}
+                       Login: {{request.login}} -- First name: {{request.first_name}} -- Last name: {{request.last_name}} -- Email: {{request.email}}
+                       {% else %}
+                           {% if request.type == 'slice' %}
+                       Slice name: {{request.slice_name}} -- Number of nodes: {{request.number_of_nodes}} -- Type of nodes: {{request.type_of_nodes}} -- Purpose: {{request.purpose}}
+                           {% else %} {# authority #}
+                       Authority name: {{request.site_name}} -- authority_hrn: {{request.site_authority}} -- City: {{request.address_city}} -- Country: {{request.address_country}}
+                           {% endif %}
+                      {% endif %}
+                               </td>
+                               <td>{{ request.timestamp }}</td>
+                               
+                               <td><span id='portal__status__{{request.type}}__{{request.id}}'></span></td>
+               
+                   <!--<div class='portal_validate_request {{request.type}} {% if forloop.counter|divisibleby:2 %}even{% else %}odd{% endif %}'> -->
+                         </tr>
+                   {% endfor %}
+                   </table>
+               </div>
+               {% endfor %}
+{% else %}
+<div class="col-md-12">
+       <i>There is no pending request waiting for validation.</i>
+</div>
+{% endif %}
+<div class="col-md-12">
+       <button class="btn btn-onelab" type="button" id="portal__validate" onclick="on_click_event();">Validate</button>
+</div>
index 23492ce..dcde2ca 100644 (file)
@@ -6,7 +6,7 @@
                        <a href="/"><img src="{{ STATIC_URL }}img/onelab-portal.png" alt="OneLab Portal - Future Internet Testbeds" /></a>
                </div>
                {% if username %}
-               <div class="col-sm-5 col-md-5 navigation">
+               <div class="col-sm-4 col-md-4 navigation">
                        <ul>
                                <li>
                                        <a class="dropdown-toggle" data-toggle="dropdown" href="#">
                                </li>
                                {%if 'is_pi'  in pi %}  
                                <li id="nav-institution" class=""><a href="/portal/institution">MANAGEMENT</a></li>
-                               <li id="nav-request"><a href="/portal/validate">REQUESTS</a></li>
                                 {%endif%}
                                <li><a href="/portal/support/">SUPPORT</a></li>
-                               
-                               
-
                        </ul>
                </div>
                {% else %}
-               <div class="col-sm-5 col-md-5 navigation">
+               <div class="col-sm-4 col-md-4 navigation">
                </div>
                {% endif %}
-               <div class="col-sm-4 col-md-4 secondary">
+               <div class="col-sm-5 col-md-5 secondary">
                        <ul>
-                               
                                <li><a href="/news">News</a></li>
                                <li><a href="/portal/about">About</a></li>
                                <li><a target="_blank" href="http://www.onelab.eu">Public Website</a></li>
index 9bbc22b..a9e536d 100644 (file)
@@ -3,24 +3,25 @@
 
 {% block content %}
        <div class="row">
-               <div class="col-md-12">
-               <h1><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="Request a Slice" /> Request a new Slice</h1>
+               <div class="col-md-12 el">
+                       <h1><img src="{{ STATIC_URL }}icons/slices-xs.png" alt="Request a Slice" /> Request a new Slice</h1>
                </div>
        </div>
 
        {% if errors %}
-       <ul>
-         {% for error in errors %}
-         <li>{{ error }}</li>
-         {% endfor %}
-       </ul>
-       {% endif %}
        <div class="row">
-               <div class="col-md-12">&nbsp;</div>
+               <div class="col-md-12 el">
+               <ul>
+                 {% for error in errors %}
+                 <li>{{ error }}</li>
+                 {% endfor %}
+               </ul>
+               </div>
        </div>
+       {% endif %}
+       
        <div class="row">
-               <div class="col-md-2"></div>
-               <div class="col-md-8">
+               <div class="col-md-8 col-md-offset-2 el">
                        <form role="form" method="post">
                        {% csrf_token %}
                          <div class="form-group">
@@ -52,7 +53,7 @@
                                <textarea id="purpose" name="purpose" class="form-control" rows="6" placeholder="Experiment Purpose" required="required">{{ purpose }}</textarea>
                            <p class="help-block">Purpose of your experiment (informative)</p>
                          </div>
-                         <button type="submit" class="btn btn-default">Request Slice</button>
+                         <button type="submit" class="btn btn-default btn-onelab">Request Slice</button>
                        </form>
        
                </div>
index ff51376..ce6b9fd 100644 (file)
@@ -18,7 +18,7 @@
                <div class="col-md-12">
                        <h2>Report a Bug</h2>
                        <p>If you have found a bug or having difficulties accesing some features or found some anomalies, please report it using our ticketing system.</p>
-                       <button id="ticketbtn" type="button" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> Create Ticket</button>
+                       <button id="ticketbtn" type="button" class="btn btn-default btn-onelab"><span class="glyphicon glyphicon-plus"></span> Create Ticket</button>
 <!--                   <h3>Unresolved Tickets</h3>
                        <table class="mytable table table-bordered table-hover">
                        <tr>
index 65506e3..b8454f0 100644 (file)
@@ -50,6 +50,7 @@ class ValidatePendingView(LoginRequiredAutoLogoutView, ThemeView):
     template_name = "validate_pending.html"
 
     def get_context_data(self, **kwargs):
+        pi = ""
         # We might have slices on different registries with different user accounts 
         # We note that this portal could be specific to a given registry, to which we register users, but i'm not sure that simplifies things
         # Different registries mean different identities, unless we identify via SFA HRN or have associated the user email to a single hrn
@@ -257,24 +258,6 @@ class ValidatePendingView(LoginRequiredAutoLogoutView, ThemeView):
                 if not auth_hrn in dest:
                     dest[auth_hrn] = []
                 dest[auth_hrn].append(request)
-                
-                ## check user is pi or not
-                platform_query  = Query().get('local:platform').select('platform_id','platform','gateway_type','disabled')
-                account_query  = Query().get('local:account').select('user_id','platform_id','auth_type','config')
-                platform_details = execute_query(self.request, platform_query)
-                account_details = execute_query(self.request, account_query)
-                for platform_detail in platform_details:
-                    for account_detail in account_details:
-                        if platform_detail['platform_id'] == account_detail['platform_id']:
-                            if 'config' in account_detail and account_detail['config'] is not '':
-                                account_config = json.loads(account_detail['config'])
-                                if 'myslice' in platform_detail['platform']:
-                                    acc_auth_cred = account_config.get('delegated_authority_credentials','N/A')
-                # assigning values
-                if acc_auth_cred == {}:
-                    pi = "is_not_pi"
-                else:
-                    pi = "is_pi" 
         
         context = super(ValidatePendingView, self).get_context_data(**kwargs)
         context['my_authorities']   = ctx_my_authorities
@@ -288,7 +271,7 @@ class ValidatePendingView(LoginRequiredAutoLogoutView, ThemeView):
         context['topmenu_items'] = topmenu_items_live('Validation', page) 
         # so we can sho who is logged
         context['username'] = the_user(self.request) 
-        context['pi'] = pi       
+        context['pi'] = "is_pi"       
         context['theme'] = self.theme
         context['section'] = "Requests"
         # XXX We need to prepare the page for queries