End-user UI for SP Portal
authorRob Crittenden <rcritten@redhat.com>
Wed, 2 Sep 2015 20:55:56 +0000 (16:55 -0400)
committerPatrick Uiterwijk <puiterwijk@redhat.com>
Fri, 4 Sep 2015 02:50:27 +0000 (04:50 +0200)
Update the root page to include the list of SAML2
Service Providers in a dynamic layout with a
filter which can search on SP name and description.

Hide providers that the admin does not want visible.

https://fedorahosted.org/ipsilon/ticket/148

Signed-off-by: Rob Crittenden <rcritten@redhat.com>
Reviewed-by: Patrick Uiterwijk <puiterwijk@redhat.com>
ipsilon/providers/common.py
ipsilon/providers/saml2idp.py
ipsilon/root.py
templates/index.html
templates/master-admin.html
templates/master.html

index c4d6658..caa2be5 100644 (file)
@@ -61,6 +61,9 @@ class ProviderBase(ConfigHelper, PluginObject):
     def on_disable(self):
         self._root.del_subtree(self.name)
 
+    def get_providers(self):
+        return []
+
 
 class ProviderPageBase(Page):
 
index 4c2639f..2e6f346 100644 (file)
@@ -285,6 +285,9 @@ Provides SAML 2.0 authentication infrastructure. """
             logger.addHandler(lh)
             logger.setLevel(logging.DEBUG)
 
+    def get_providers(self):
+        return self.admin.providers
+
     @property
     def allow_self_registration(self):
         return self.get_config_value('allow self registration')
index daef90f..d701616 100644 (file)
@@ -51,5 +51,11 @@ class Root(Page):
 
     def root(self):
         self.debug(self.html_heads)
+        providers = []
+        for plugin in self._site['provider_config'].enabled:
+            # pylint: disable=no-member,protected-access
+            obj = self.admin.providers._get_plugin_obj(plugin)
+            providers.extend(obj.get_providers())
+        providers = sorted(providers, key=lambda provider: provider.name)
         return self._template('index.html', title='Ipsilon',
-                              heads=self.html_heads)
+                              providers=providers, heads=self.html_heads)
index 7d368cb..cf54fc4 100644 (file)
@@ -1,9 +1,56 @@
-{% extends "master.html" %}
-{% block main %}
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>Ipsilon</title>
+    <meta charset="utf-8" /> 
+    <meta name="viewport" content="width=device-width, initial-scale=1.0">
+    <link href="{{ basepath }}/ui/css/patternfly.css" rel="stylesheet" media="screen, print">
+    <link href="{{ basepath }}/ui/css/styles.css" rel="stylesheet" media="screen, print">
+  </head>
+
+  <body class="cards-pf">
+    <nav class="navbar navbar-default navbar-pf navbar-pf-lg" role="navigation">
+      <div class="navbar-header">
+        <button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse-1">
+          <span class="sr-only">Toggle navigation</span>
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+          <span class="icon-bar"></span>
+        </button>
+        <a class="navbar-brand" href="{{ basepath }}/">
+          <img type="image/svg+xml" src="{{ basepath }}/ui/img/brand.png" alt="Ipsilon" width="auto" height="10px" />
+        </a>
+      </div>
+      <div class="collapse navbar-collapse navbar-collapse-1">
+        {% if user.name %}
+        <ul class="nav navbar-nav navbar-utility">
+          <li class="dropdown">
+              <a href="#" class="dropdown-toggle" data-toggle="dropdown">
+                <span class="pficon pficon-user"></span>
+                {{ user.fullname }}<b class="caret"></b>
+              </a>
+            <ul class="dropdown-menu">
+              <li>
+                <a href="{{ basepath }}/logout" id="logout">Log Out</a>
+              </li>
+            </ul>
+          </li>
+        </ul>
+        {% endif %}
+      </div>
+    </nav>
+
 <div class="col-sm-12">
+  <p></p>
   <div id="welcome">
     {% if user.name %}
       <p>Welcome {{ user.fullname }}!</p>
+      <p>Select a Service Provider
+      {% if user.is_admin %}
+          or go to the 
+          <a href="{{ basepath }}/admin" id="admin">Administration Console</a>
+      {% endif %}
+      .</p>
     {% endif %}
   </div>
   <div id="content">
   </div>
   <div id="authenticated">
     {% if user.name %}
-      <p>
-        {% if user.is_admin %}
-          <a href="{{ basepath }}/admin" id="admin">Administration</a> |
+    <div class="container-fluid">
+      
+      <div class="header">
+                
+        <form role="form" class="search-pf has-button">
+          <div class="form-group has-clear">
+            <div class="search-pf-input-group">
+              <label for="search1" class="sr-only">Search</label>
+              <input id="search1" type="search" class="form-control div-filter" placeholder="Search" providers="providers">
+              <button type="button" class="clear" aria-hidden="true"><span class
+="pficon pficon-close"></span></button>
+            </div>
+          </div>
+          <div class="form-group">
+            <button class="btn btn-default" type="button"><span class="fa fa-search"></span></button>
+          </div>
+        </form>
+      </div><!-- header -->
+
+      <div class="row thumbnails providers" id="providers">
+      {% for p in providers %}
+        {% if p.visible == '1' %}
+        <div class="col-sm-4 col-md-3 provider">
+          <a
+             {% if p.splink or 0 %}
+               href="{{ p.splink }}"
+             {% else %}
+               href="#"
+             {% endif %}
+             class="thumbnail" data-toggle="tooltip" data-placement="top" title="{{ p.description }}" name="{{ p.name }}">
+            {% if p.imageurl or 0 %}
+              <img src="{{ p.imageurl }}" height=100 width=200>
+            {% else %}
+              <span class="name">
+                <span class="name-icon">{{ p.name[0] }}</span>
+                {{ p.name }}
+              </span>
+            {% endif %}
+          </a>
+        </div>
         {% endif %}
-        <a href="{{ basepath }}/logout" id="logout">Log Out</a>
-      </p>
+      {% endfor %}
+
+      </div><!-- row -->
+
+    
+    </div><!-- /container -->
+
     {% endif %}
   </div>
 </div>
-{% endblock %}
\ No newline at end of file
+
+    <!-- JS -->
+    <script src="{{ basepath }}/ui/js/jquery.js"></script>
+    <script src="{{ basepath }}/ui/js/bootstrap.js"></script>
+    <script src="{{ basepath }}/ui/js/patternfly.js"></script>
+    <script src="{{ basepath }}/ui/js/divfilter.js"></script>
+
+    <script>
+      (function($) {
+        $(document).ready(function() {
+          // Hide the clear button if the search input is empty
+          $(".search-pf .has-clear .clear").each(function() {
+            if (!$(this).prev('.form-control').val()) {
+              $(this).hide();
+            }
+          });
+          // Show the clear button upon entering text in the search input
+          $(".search-pf .has-clear .form-control").keyup(function () {
+            var t = $(this);
+            t.next('button').toggle(Boolean(t.val()));
+          });
+          // Upon clicking the clear button, empty the entered text and hide the clear button
+          $(".search-pf .has-clear .clear").click(function () {
+            $(this).prev('.form-control').val('').focus();
+            $(this).hide();
+          });
+        });    
+        
+        $(function () {
+      $('[data-toggle="tooltip"]').tooltip()
+    })
+        
+      })(jQuery);
+    </script>      
+
+  </body>
+</html>
index 8987df9..f7cd163 100644 (file)
@@ -6,6 +6,7 @@
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <link href="{{ basepath }}/ui/css/admin.css" rel="stylesheet" media="screen, print">
+    <link href="{{ basepath }}/ui/css/styles.css" rel="stylesheet" media="screen, print">
     <script src="{{ basepath }}/ui/js/jquery.js"></script>
     <script src="{{ basepath }}/ui/js/bootstrap.js"></script>
     <script src="{{ basepath }}/ui/js/patternfly.js"></script>
index cf1275a..49103d0 100644 (file)
@@ -8,6 +8,7 @@
     <meta charset="UTF-8">
     <meta name="viewport" content="width=device-width, initial-scale=1.0">
     <link href="{{ basepath }}/ui/css/ipsilon.css" rel="stylesheet" media="screen, print">
+    <link href="{{ basepath }}/ui/css/styles.css" rel="stylesheet" media="screen, print">
     {%- if heads %}
       {%- for group, value in heads.items() %}
         {%- for head in value %}