Commit 2de6e2d2 authored by Antony Chazapis's avatar Antony Chazapis
Browse files

Merge branch 'cloudbar'

parents 2fb50a75 9b25b9a9
......@@ -31,7 +31,9 @@
# interpreted as representing official policies, either expressed
# or implied, of GRNET S.A.
from astakos.im.settings import IM_MODULES, INVITATIONS_ENABLED, IM_STATIC_URL
from astakos.im.settings import IM_MODULES, INVITATIONS_ENABLED, IM_STATIC_URL, \
COOKIE_NAME
from django.conf import settings
def im_modules(request):
return {'im_modules': IM_MODULES}
......@@ -48,3 +50,15 @@ def invitations(request):
def media(request):
return {'IM_STATIC_URL' : IM_STATIC_URL}
def cloudbar(request):
"""
Cloudbar configuration
"""
CB_LOCATION = getattr(settings, 'CLOUDBAR_LOCATION', IM_STATIC_URL + 'cloudbar/')
CB_COOKIE_NAME = getattr(settings, 'CLOUDBAR_COOKIE_NAME', COOKIE_NAME)
CB_ACTIVE_SERVICE = getattr(settings, 'CLOUDBAR_ACTIVE_SERVICE', 'cloud')
return {'CLOUDBAR_LOC': CB_LOCATION,
'CLOUDBAR_COOKIE_NAME': CB_COOKIE_NAME,
'ACTIVE_SERVICE': CB_ACTIVE_SERVICE}
Cloudbar
========
Cloudbar is a project to provide common navigation user experience
between services that share common authentication mechanism and user
entries but get deployed on different domains and may not share
common frontend themes/templates.
The project consists of a javascript file which once imported in a
html page handles the automatic creation and styling of a bar that
is placed on top of the page (first body element absolutely
positioned on top). Since the addition of the bar may break the
current layout of the site once imported the script tries to load an
additional css located in the same url as the script itself named by
the ``CLOUDBAR_ACTIVE_SERVICE`` configuration and prefixed by *service_* so
that css changes can be applied without touching the page native styles.
The bar contains links to the refered services application urls, and
depending on if the user is authenticated links to account pages
(login, change profile, logout etc.).
To identify if a user is authenticated the script checks of a
specific cookie which can be configured using ``CLOUDBAR_COOKIE_NAME`` setting
contains valid data which should match the following format::
<username or email>|<authentication token>
Usage
-----
Each page that wants to display the navigation bar should:
- Include one of the latest jquery builds.
- Set the ``CLOUDBAR_COOKIE_NAME`` variable containing info about the username
and the authentication status of the current visitor of the page.
- Set the ``CLOUDBAR_ACTIVE_SERVICE`` to the id of the service the current
page refers to so that script cat set the appropriate active styles to
the services menu for services ids see ``SERVICES_LINK``
object in cloudbar.js.
- Set the ``CLOUDBAR_LOCATION`` to the url where bar files are served from.
- Include the servicesbar.js script.
Example
*******
.. codeblock:: javascript
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>
<script>
var CLOUDBAR_COOKIE_NAME = '_pithos2_a';
var CLOUDBAR_ACTIVE_SERVICE = 'cloud';
var CLOUDBAR_LOCATION = "http://accounts.cloud.grnet.gr/cloudbar/";
$(document).ready(function(){
$.getScript(CLOUDBAR_LOC + 'cloudbar.js');
})
</script>
Build styles
------------
Cloudbar uses `less-css <http://www.lesscss.org>`_ for css styles
definitions. To build the less file you need the bootstrap less files
available on
`bootstrap github repository <https://github.com/twitter/bootstrap/>`.
You can build the styles using the following command::
$ lessc --include-path=<path/to/bootstrap> cloudbar.less > cloudbar.css
/*!
* Bootstrap @VERSION
*
* Copyright 2011 Twitter, Inc
* Licensed under the Apache License v2.0
* http://www.apache.org/licenses/LICENSE-2.0
*
* Designed and built with all the love in the world @twitter by @mdo and @fat.
* Date: @DATE
*/
/* Variables.less
* Variables to customize the look and feel of Bootstrap
* ----------------------------------------------------- */
/* Mixins.less
* Snippets of reusable CSS to develop faster and keep code readable
* ----------------------------------------------------------------- */
.servicesbar {
font-family: arial, sans-serif;
font-size: 13px !important;
line-height: 13px;
letter-spacing: 0px;
zoom: 1;
color: #ccc;
z-index: 1000;
border-bottom: 1px solid #444;
background-color: #000000;
position: relative;
}
.servicesbar ol, .servicesbar ul {
list-style: none;
margin: 0;
padding: 0;
}
.servicesbar li {
margin: 0;
padding: 0;
}
.servicesbar:before, .servicesbar:after {
display: table;
content: "";
zoom: 1;
}
.servicesbar:after {
clear: both;
}
.servicesbar a {
border: none !important;
font-size: inherit !important;
color: #e6e6e6;
text-decoration: none;
display: block;
float: left;
padding: 11px;
height: 13px;
}
.servicesbar a:hover {
background-color: #444;
}
.servicesbar a.active {
font-weight: bold;
background-color: #333;
}
.servicesbar .services {
zoom: 1;
}
.servicesbar .services:before, .servicesbar .services:after {
display: table;
content: "";
zoom: 1;
}
.servicesbar .services:after {
clear: both;
}
.servicesbar .profile {
margin-top: -35px;
zoom: 1;
text-align: right;
min-width: 200px;
background-color: #000000;
zoom: 1;
position: absolute;
right: 0;
float: right;
}
.servicesbar .profile:before, .servicesbar .profile:after {
display: table;
content: "";
zoom: 1;
}
.servicesbar .profile:after {
clear: both;
}
.servicesbar .profile a {
float: none;
}
.servicesbar .profile ul {
display: none;
}
.servicesbar .profile ul li {
width: 100%;
border-bottom: 1px solid #444;
background-color: #333;
}
.servicesbar .profile ul li a {
float: none;
display: block;
}
.servicesbar .profile:hover {
background-color: #222;
}
.servicesbar .profile:hover ul {
display: block;
}
.servicesbar .profile:before, .servicesbar .profile:after {
display: table;
content: "";
zoom: 1;
}
.servicesbar .profile:after {
clear: both;
}
$(document).ready(function(){
/*
* LINKS CONFIGURATION
*/
var PROFILE_URL = "https://accounts.cloud.grnet.gr";
var SERVICES_LINKS = window.CLOUDBAR_SERVICES_LINKS || {
'cloud': { url:'http://pithos.dev.grnet.gr/im/', name:'grnet cloud', id:'cloud', icon:'home-icon.png' },
'okeanos': { url:'http://staging.okeanos.grnet.gr/ui/', name:'~okeanos', id:'okeanos' },
'pithos': { url:'http://pithos.dev.grnet.gr/ui/', name:'pithos+', id:'pithos' }
};
var PROFILE_LINKS = window.CLOUDBAR_PROFILE_LINKS || {
'login': { url: '/im/login?next=' + window.location.toString(), auth:false, name: "login...", visible:false },
'profile': { url: '/im/profile', auth:true, name: "change your profile..." },
'invitations': { url: '/im/invite', auth:true, name: "invite some friends..." },
'feedback': { url: '/im/feedback', auth:true, name: "feedback..." },
'logout': { url: '/im/logout', auth:true, name: "logout..." }
};
// cookie plugin https://raw.github.com/carhartl/jquery-cookie/master/jquery.cookie.js
// * Copyright (c) 2010 Klaus Hartl, @carhartl
// * Dual licensed under the MIT and GPL licenses
var cookie=function(key,value,options){if(arguments.length>1&&(!/Object/.test(Object.prototype.toString.call(value))||value===null||value===undefined)){options=$.extend({},options);if(value===null||value===undefined){options.expires=-1}if(typeof options.expires==='number'){var days=options.expires,t=options.expires=new Date();t.setDate(t.getDate()+days)}value=String(value);return(document.cookie=[encodeURIComponent(key),'=',options.raw?value:encodeURIComponent(value),options.expires?'; expires='+options.expires.toUTCString():'',options.path?'; path='+options.path:'',options.domain?'; domain='+options.domain:'',options.secure?'; secure':''].join(''))}options=value||{};var decode=options.raw?function(s){return s}:decodeURIComponent;var pairs=document.cookie.split('; ');for(var i=0,pair;pair=pairs[i]&&pairs[i].split('=');i++){if(decode(pair[0])===key)return decode(pair[1]||'')}return null};
var ACTIVE_MENU = window.CLOUDBAR_ACTIVE_SERVICE || 'cloud';
var USER_DATA = window.CLOUDBAR_USER_DATA || {'user': 'Not logged in', 'logged_in': false};
var COOKIE_NAME = window.CLOUDBAR_COOKIE_NAME || '_pithos2_a';
var cssloc = window.CLOUDBAR_LOCATION || "http://127.0.0.1:8989/";
// load css
var css = $("<link />");
css.attr({rel:'stylesheet', type:'text/css', href:cssloc + 'cloudbar.css'});
$("head").append(css);
// load service specific css
var SKIP_ADDITIONAL_CSS = window.SKIP_ADDITIONAL_CSS == undefined ? false : window.SKIP_ADDITIONAL_CSS;
if (!SKIP_ADDITIONAL_CSS) {
var css = $("<link />");
css.attr({rel:'stylesheet', type:'text/css', href:cssloc + 'service_' + ACTIVE_MENU + '.css'});
$("head").append(css);
}
var root = $('body');
var bar = $('<div class="servicesbar"></div>');
var services = $('<div class="services"></div>');
var profile = $('<div class="profile"></div>');
// create services links and set the active class to the current service
$.each(SERVICES_LINKS, function(i, el){
var slink = $("<a>");
if (el.icon) {
slink.append($('<img src="'+cssloc+el.icon+'"/>'));
} else {
slink.text(el.name);
}
slink.attr('href', el.url);
slink.attr('title', el.name);
services.append(slink);
if (el.id == ACTIVE_MENU) {
slink.addClass("active");
}
});
var USERNAME, LOGGED_IN;
var authcookie = cookie(COOKIE_NAME);
var anonymous = {'user': 'Login...', 'logged_in': false};
if (authcookie && authcookie.indexOf("|") > -1) {
USER_DATA.logged_in = true;
USER_DATA.user = authcookie.split("|")[0];
} else {
USER_DATA = anonymous;
}
USERNAME = USER_DATA.user;
LOGGED_IN = USER_DATA.logged_in;
// clear username
USERNAME = USERNAME.replace(/\\'/g,'');
USERNAME = USERNAME.replace(/\"/g,'');
var user = $('<div class="user"></div>');
var username = $('<a href="#"></a>');
username.text(USERNAME);
// create profile links
var usermenu = $("<ul>");
$.each(PROFILE_LINKS, function(i,el) {
if (!LOGGED_IN && el.auth) { return }
if (LOGGED_IN && !el.auth) { return }
var li = $("<li />");
var link = $("<a />");
link.text(el.name);
link.attr({href:el.url});
li.append(link);
if (el.visible == false) {
li.hide();
}
usermenu.append(li);
});
//profile.filter(".user a").attr("href",
//profile.find("li a").get(0).attr("href"))
user.append(username);
user.append(usermenu);
profile.append(user);
bar.append(services).append(profile);
root.prepend(bar);
var firstlink = profile.find("ul li:first-child a").attr("href");
profile.find(".user > a").attr("href", firstlink);
});
@import "less/bootstrap.less";
@toolbarBg: #222;
@toolbarColor: darken(@white, 10%);
@toolbarHeight: 30px;
.servicesbar {
// mini reset
ol, ul { list-style:none; margin:0; padding:0;}
li {margin:0; padding:0;}
font-family: arial, sans-serif;
font-size: 13px !important;
line-height: 13px;
letter-spacing: 0px;
.clearfix();
color: #ccc;
z-index: 1000;
border-bottom: 1px solid #444;
background-color: darken(@toolbarBg, 40%);
a {
border: none !important;
font-size: inherit !important;
color: @toolbarColor;
text-decoration: none;
display: block;
float: left;
padding: 11px;
height: 13px;
&:hover {
background-color: #444;
}
&.active {
font-weight: bold;
background-color: #333;
}
}
.services {
.clearfix();
}
position: relative;
.profile {
margin-top: -35px;
.clearfix();
text-align: right;
min-width: 200px;
a {
float: none;
}
ul {
display: none;
li {
width: 100%;
border-bottom: 1px solid #444;
background-color: #333;
a {
float: none;
display: block;
}
}
}
&:hover {
background-color: #222;
ul {
display: block;
}
}
background-color: @black;
.clearfix();
position: absolute;
right: 0;
float: right;
}
}
body {
background-color: #4085A5;
background-position: 20px 34px;
}
.gwt-HTML.pithos-logo {
top: 65px !important;
}
.pithos-usernameMenu {
display: none;
}
......@@ -60,11 +60,12 @@
})
</script>
<script>
var CLOUDBAR_LOC = "http://docs.dev.grnet.gr/cloudbar/";
var CLOUDBAR_ACTIVE_SERVICE = 'accounts';
var CLOUDBAR_LOCATION = "{{ CLOUDBAR_LOC }}";
var CLOUDBAR_COOKIE_NAME = "{{ CLOUDBAR_COOKIE_NAME }}";
var CLOUDBAR_ACTIVE_SERVICE = '{{ CLOUDBAR_ACTIVE_SERVICE }}';
$(document).ready(function(){
$.getScript(CLOUDBAR_LOC + 'servicesbar.js');
$.getScript(CLOUDBAR_LOCATION + 'cloudbar.js');
})
</script>
</head>
......
......@@ -90,6 +90,7 @@ TEMPLATE_CONTEXT_PROCESSORS = (
'django.core.context_processors.media',
'django.core.context_processors.request',
'astakos.im.context_processors.media',
'astakos.im.context_processors.cloudbar',
'astakos.im.context_processors.im_modules',
'astakos.im.context_processors.next',
'astakos.im.context_processors.code',
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment