diff --git a/app/assets/fonts/FontAwesome.otf b/app/assets/fonts/FontAwesome.otf
new file mode 100755
index 00000000..64049bf2
Binary files /dev/null and b/app/assets/fonts/FontAwesome.otf differ
diff --git a/app/assets/fonts/fontawesome-webfont.eot b/app/assets/fonts/fontawesome-webfont.eot
new file mode 100755
index 00000000..7d81019e
Binary files /dev/null and b/app/assets/fonts/fontawesome-webfont.eot differ
diff --git a/app/assets/fonts/fontawesome-webfont.svg b/app/assets/fonts/fontawesome-webfont.svg
new file mode 100755
index 00000000..ba0afe5e
--- /dev/null
+++ b/app/assets/fonts/fontawesome-webfont.svg
@@ -0,0 +1,284 @@
+
+
+
\ No newline at end of file
diff --git a/app/assets/fonts/fontawesome-webfont.ttf b/app/assets/fonts/fontawesome-webfont.ttf
new file mode 100755
index 00000000..d4617247
Binary files /dev/null and b/app/assets/fonts/fontawesome-webfont.ttf differ
diff --git a/app/assets/fonts/fontawesome-webfont.woff b/app/assets/fonts/fontawesome-webfont.woff
new file mode 100755
index 00000000..3c89ae09
Binary files /dev/null and b/app/assets/fonts/fontawesome-webfont.woff differ
diff --git a/app/assets/javascripts/backbone/helpers/channels.js.coffee b/app/assets/javascripts/backbone/helpers/channels.js.coffee
index 72d509c1..81fab196 100644
--- a/app/assets/javascripts/backbone/helpers/channels.js.coffee
+++ b/app/assets/javascripts/backbone/helpers/channels.js.coffee
@@ -126,8 +126,12 @@ class Kandan.Helpers.Channels
.append(@newActivityView(activityAttributes).render().el)
@flushActivities(activityAttributes.channel_id)
- if not local
- Kandan.Helpers.Utils.notifyInTitleIfRequired(activityAttributes)
+
+ if not local and @getActiveChannelId() == activityAttributes.channel_id and activityAttributes.action == "message" and Kandan.Helpers.Utils.browserTabFocused != true
+ Kandan.Helpers.Utils.notifyInTitle()
+ Kandan.Plugins.Notifications.playAudioNotification()
+ Kandan.Plugins.Notifications.displayNotification(activityAttributes.user.username || activityAttributes.user.email, activityAttributes.content)
+
@setPaginationData(activityAttributes.channel_id)
diff --git a/app/assets/javascripts/backbone/helpers/utils.js.coffee b/app/assets/javascripts/backbone/helpers/utils.js.coffee
index 6dfee5ae..2f6f52cc 100644
--- a/app/assets/javascripts/backbone/helpers/utils.js.coffee
+++ b/app/assets/javascripts/backbone/helpers/utils.js.coffee
@@ -3,14 +3,9 @@ class Kandan.Helpers.Utils
@browserTabFocused: true
- @notifyInTitleIfRequired: (activityAttributes) ->
- console.log(activityAttributes)
-
- if Kandan.Data.Channels.activeChannelId() == activityAttributes.channel_id and activityAttributes.action == "message" and @browserTabFocused != true
- Kandan.Plugins.MusicPlayer.playAudioNotice()
- @unreadActivities += 1
- $(document).attr('title', "(#{@unreadActivities}) Kandan")
-
+ @notifyInTitle: ()->
+ @unreadActivities += 1
+ $(document).attr('title', "(#{@unreadActivities}) Kandan")
@months: [
"January"
diff --git a/app/assets/javascripts/backbone/kandan.js.coffee.erb b/app/assets/javascripts/backbone/kandan.js.coffee.erb
index 66140423..c2df9653 100644
--- a/app/assets/javascripts/backbone/kandan.js.coffee.erb
+++ b/app/assets/javascripts/backbone/kandan.js.coffee.erb
@@ -28,6 +28,7 @@ window.Kandan =
registerPlugins: ->
plugins = [
"UserList"
+ ,"Notifications"
,"MusicPlayer"
,"YouTubeEmbed"
,"VimeoEmbed"
diff --git a/app/assets/javascripts/backbone/plugins/notifications.js.coffee b/app/assets/javascripts/backbone/plugins/notifications.js.coffee
new file mode 100644
index 00000000..8cce2320
--- /dev/null
+++ b/app/assets/javascripts/backbone/plugins/notifications.js.coffee
@@ -0,0 +1,124 @@
+class Kandan.Plugins.Notifications
+
+ @widget_title: "Notifications"
+ @widget_icon_url: "/assets/people_icon.png"
+ @pluginNamespace: "Kandan.Plugins.Notifications"
+
+ @popup_notifications_template: _.template '
'
+ @enable_popup_notifications_template = _.template ''
+ @disable_popup_notifications_template = _.template ''
+
+ @sound_notifications_template: _.template ''
+ @enable_sound_notifications_template = _.template ' Sounds'
+ @disable_sound_notifications_template = _.template ' Sounds'
+
+ @render: ($el)->
+ $notifications = $("")
+ $el.next().hide();
+
+ @initPopupsNotificationsButtons()
+
+ $el.html($notifications)
+
+ @initWebkitNotifications($notifications)
+ @initSoundNotifications($notifications)
+
+ return
+
+
+ @init: ()->
+ Kandan.Widgets.register @pluginNamespace
+
+ # HTML 5 Popups
+ @initPopupsNotificationsButtons: ()->
+ $(document).on 'click', '.enable-popup-notifications', => @enablePopupNotifications()
+ $(document).on 'click', '.disable-popup-notifications', => @disablePopupNotifications()
+ return
+
+ @initWebkitNotifications: (container)->
+ if Modernizr.notification
+ container.append(@popup_notifications_template())
+
+ if @webkitNotificationsEnabled()
+ @enablePopupNotifications()
+ else
+ @disablePopupNotifications()
+
+ @enablePopupNotifications: ()->
+ if @webkitNotificationsEnabled()
+ @popups_notifications_enabled = true
+ $(".popup-notifications .enable-popup-notifications").remove()
+ $(".notification.popup-notifications").append(@disable_popup_notifications_template())
+ else
+ if @webkitNotificationsDenied()
+ # If the notifications have been denied we need to let the user know because there is nothing else we can do
+ alert("It looks like notifications are denied for this page.\n\nUse your browser settings to allow notifications for this page.")
+ else
+ window.webkitNotifications.requestPermission(=> @onPopupNotificationsEnabled())
+
+ return
+
+ @disablePopupNotifications: ()->
+ @popups_notifications_enabled = false
+
+ $(".popup-notifications .disable-popup-notifications").remove()
+ $(".notification.popup-notifications").append(@enable_popup_notifications_template())
+ return
+
+ # Returns true if notifications are enabled for this page.
+ @webkitNotificationsEnabled: ()->
+ window.webkitNotifications.checkPermission() == 0
+
+ @webkitNotificationsDenied: ()->
+ window.webkitNotifications.checkPermission() == 2
+
+ # Callback when notifiactions are enabled for the first time
+ @onPopupNotificationsEnabled: ()->
+ if @webkitNotificationsEnabled()
+ @enablePopupNotifications()
+
+ return
+
+ # If you are wondering why the kandan icon is not displayed on OS X this is the reason:
+ # If you try notifying users on MacOS Mountain Lion, using a custom notification icon, don't be surprised that the Web browser icon overrides the icon you defined.
+ # Apple locked notification icons to the app icons (for instance Chrome icon).
+ @displayNotification: (sender, message)->
+ if @popups_notifications_enabled && @webkitNotificationsEnabled()
+ notification = window.webkitNotifications.createNotification('/assets/kandanlogo.png', "#{sender} says:", message);
+ notification.onclick = ->
+ window.focus()
+ @cancel()
+ return
+
+ notification.show();
+
+ # HTML 5 sounds
+ @initSoundNotifications: ($container)->
+ if Modernizr.audio
+ $container.append(@sound_notifications_template())
+ @enableSoundNotifications()
+ @initSoundNotificationsButtons()
+
+ @initSoundNotificationsButtons: ()->
+ $(document).on 'click', '.enable-sound-notifications', => @enableSoundNotifications()
+ $(document).on 'click', '.disable-sound-notifications', => @disableSoundNotifications()
+ return
+
+ @enableSoundNotifications: ()->
+ @sound_notifications_enabled = true
+ $(".sound-notifications .enable-sound-notifications").remove()
+ $(".notification.sound-notifications").append(@disable_sound_notifications_template())
+
+ return
+
+ @disableSoundNotifications: ()->
+ @sound_notifications_enabled = false
+
+ $(".sound-notifications .disable-sound-notifications").remove()
+ $(".notification.sound-notifications").append(@enable_sound_notifications_template())
+ return
+
+ @playAudioNotification: ()->
+ if @sound_notifications_enabled
+ Kandan.Plugins.MusicPlayer.playAudioNotice()
+ return
\ No newline at end of file
diff --git a/app/assets/javascripts/lib/modernizr.js b/app/assets/javascripts/lib/modernizr.js
new file mode 100644
index 00000000..333581b1
--- /dev/null
+++ b/app/assets/javascripts/lib/modernizr.js
@@ -0,0 +1,457 @@
+/* Modernizr 2.6.2 (Custom Build) | MIT & BSD
+ * Build: http://modernizr.com/download/#-draganddrop-audio-shiv-prefixed-testprop-testallprops-hasevent-domprefixes-notification
+ */
+;
+
+
+
+window.Modernizr = (function( window, document, undefined ) {
+
+ var version = '2.6.2',
+
+ Modernizr = {},
+
+
+ docElement = document.documentElement,
+
+ mod = 'modernizr',
+ modElem = document.createElement(mod),
+ mStyle = modElem.style,
+
+ inputElem ,
+
+
+ toString = {}.toString, omPrefixes = 'Webkit Moz O ms',
+
+ cssomPrefixes = omPrefixes.split(' '),
+
+ domPrefixes = omPrefixes.toLowerCase().split(' '),
+
+
+ tests = {},
+ inputs = {},
+ attrs = {},
+
+ classes = [],
+
+ slice = classes.slice,
+
+ featureName,
+
+ isEventSupported = (function() {
+
+ var TAGNAMES = {
+ 'select': 'input', 'change': 'input',
+ 'submit': 'form', 'reset': 'form',
+ 'error': 'img', 'load': 'img', 'abort': 'img'
+ };
+
+ function isEventSupported( eventName, element ) {
+
+ element = element || document.createElement(TAGNAMES[eventName] || 'div');
+ eventName = 'on' + eventName;
+
+ var isSupported = eventName in element;
+
+ if ( !isSupported ) {
+ if ( !element.setAttribute ) {
+ element = document.createElement('div');
+ }
+ if ( element.setAttribute && element.removeAttribute ) {
+ element.setAttribute(eventName, '');
+ isSupported = is(element[eventName], 'function');
+
+ if ( !is(element[eventName], 'undefined') ) {
+ element[eventName] = undefined;
+ }
+ element.removeAttribute(eventName);
+ }
+ }
+
+ element = null;
+ return isSupported;
+ }
+ return isEventSupported;
+ })(),
+
+
+ _hasOwnProperty = ({}).hasOwnProperty, hasOwnProp;
+
+ if ( !is(_hasOwnProperty, 'undefined') && !is(_hasOwnProperty.call, 'undefined') ) {
+ hasOwnProp = function (object, property) {
+ return _hasOwnProperty.call(object, property);
+ };
+ }
+ else {
+ hasOwnProp = function (object, property) {
+ return ((property in object) && is(object.constructor.prototype[property], 'undefined'));
+ };
+ }
+
+
+ if (!Function.prototype.bind) {
+ Function.prototype.bind = function bind(that) {
+
+ var target = this;
+
+ if (typeof target != "function") {
+ throw new TypeError();
+ }
+
+ var args = slice.call(arguments, 1),
+ bound = function () {
+
+ if (this instanceof bound) {
+
+ var F = function(){};
+ F.prototype = target.prototype;
+ var self = new F();
+
+ var result = target.apply(
+ self,
+ args.concat(slice.call(arguments))
+ );
+ if (Object(result) === result) {
+ return result;
+ }
+ return self;
+
+ } else {
+
+ return target.apply(
+ that,
+ args.concat(slice.call(arguments))
+ );
+
+ }
+
+ };
+
+ return bound;
+ };
+ }
+
+ function setCss( str ) {
+ mStyle.cssText = str;
+ }
+
+ function setCssAll( str1, str2 ) {
+ return setCss(prefixes.join(str1 + ';') + ( str2 || '' ));
+ }
+
+ function is( obj, type ) {
+ return typeof obj === type;
+ }
+
+ function contains( str, substr ) {
+ return !!~('' + str).indexOf(substr);
+ }
+
+ function testProps( props, prefixed ) {
+ for ( var i in props ) {
+ var prop = props[i];
+ if ( !contains(prop, "-") && mStyle[prop] !== undefined ) {
+ return prefixed == 'pfx' ? prop : true;
+ }
+ }
+ return false;
+ }
+
+ function testDOMProps( props, obj, elem ) {
+ for ( var i in props ) {
+ var item = obj[props[i]];
+ if ( item !== undefined) {
+
+ if (elem === false) return props[i];
+
+ if (is(item, 'function')){
+ return item.bind(elem || obj);
+ }
+
+ return item;
+ }
+ }
+ return false;
+ }
+
+ function testPropsAll( prop, prefixed, elem ) {
+
+ var ucProp = prop.charAt(0).toUpperCase() + prop.slice(1),
+ props = (prop + ' ' + cssomPrefixes.join(ucProp + ' ') + ucProp).split(' ');
+
+ if(is(prefixed, "string") || is(prefixed, "undefined")) {
+ return testProps(props, prefixed);
+
+ } else {
+ props = (prop + ' ' + (domPrefixes).join(ucProp + ' ') + ucProp).split(' ');
+ return testDOMProps(props, prefixed, elem);
+ }
+ }
+ tests['draganddrop'] = function() {
+ var div = document.createElement('div');
+ return ('draggable' in div) || ('ondragstart' in div && 'ondrop' in div);
+ };
+ tests['audio'] = function() {
+ var elem = document.createElement('audio'),
+ bool = false;
+
+ try {
+ if ( bool = !!elem.canPlayType ) {
+ bool = new Boolean(bool);
+ bool.ogg = elem.canPlayType('audio/ogg; codecs="vorbis"').replace(/^no$/,'');
+ bool.mp3 = elem.canPlayType('audio/mpeg;') .replace(/^no$/,'');
+
+ bool.wav = elem.canPlayType('audio/wav; codecs="1"') .replace(/^no$/,'');
+ bool.m4a = ( elem.canPlayType('audio/x-m4a;') ||
+ elem.canPlayType('audio/aac;')) .replace(/^no$/,'');
+ }
+ } catch(e) { }
+
+ return bool;
+ }; for ( var feature in tests ) {
+ if ( hasOwnProp(tests, feature) ) {
+ featureName = feature.toLowerCase();
+ Modernizr[featureName] = tests[feature]();
+
+ classes.push((Modernizr[featureName] ? '' : 'no-') + featureName);
+ }
+ }
+
+
+
+ Modernizr.addTest = function ( feature, test ) {
+ if ( typeof feature == 'object' ) {
+ for ( var key in feature ) {
+ if ( hasOwnProp( feature, key ) ) {
+ Modernizr.addTest( key, feature[ key ] );
+ }
+ }
+ } else {
+
+ feature = feature.toLowerCase();
+
+ if ( Modernizr[feature] !== undefined ) {
+ return Modernizr;
+ }
+
+ test = typeof test == 'function' ? test() : test;
+
+ if (typeof enableClasses !== "undefined" && enableClasses) {
+ docElement.className += ' ' + (test ? '' : 'no-') + feature;
+ }
+ Modernizr[feature] = test;
+
+ }
+
+ return Modernizr;
+ };
+
+
+ setCss('');
+ modElem = inputElem = null;
+
+ ;(function(window, document) {
+ var options = window.html5 || {};
+
+ var reSkip = /^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i;
+
+ var saveClones = /^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i;
+
+ var supportsHtml5Styles;
+
+ var expando = '_html5shiv';
+
+ var expanID = 0;
+
+ var expandoData = {};
+
+ var supportsUnknownElements;
+
+ (function() {
+ try {
+ var a = document.createElement('a');
+ a.innerHTML = '';
+ supportsHtml5Styles = ('hidden' in a);
+
+ supportsUnknownElements = a.childNodes.length == 1 || (function() {
+ (document.createElement)('a');
+ var frag = document.createDocumentFragment();
+ return (
+ typeof frag.cloneNode == 'undefined' ||
+ typeof frag.createDocumentFragment == 'undefined' ||
+ typeof frag.createElement == 'undefined'
+ );
+ }());
+ } catch(e) {
+ supportsHtml5Styles = true;
+ supportsUnknownElements = true;
+ }
+
+ }()); function addStyleSheet(ownerDocument, cssText) {
+ var p = ownerDocument.createElement('p'),
+ parent = ownerDocument.getElementsByTagName('head')[0] || ownerDocument.documentElement;
+
+ p.innerHTML = 'x';
+ return parent.insertBefore(p.lastChild, parent.firstChild);
+ }
+
+ function getElements() {
+ var elements = html5.elements;
+ return typeof elements == 'string' ? elements.split(' ') : elements;
+ }
+
+ function getExpandoData(ownerDocument) {
+ var data = expandoData[ownerDocument[expando]];
+ if (!data) {
+ data = {};
+ expanID++;
+ ownerDocument[expando] = expanID;
+ expandoData[expanID] = data;
+ }
+ return data;
+ }
+
+ function createElement(nodeName, ownerDocument, data){
+ if (!ownerDocument) {
+ ownerDocument = document;
+ }
+ if(supportsUnknownElements){
+ return ownerDocument.createElement(nodeName);
+ }
+ if (!data) {
+ data = getExpandoData(ownerDocument);
+ }
+ var node;
+
+ if (data.cache[nodeName]) {
+ node = data.cache[nodeName].cloneNode();
+ } else if (saveClones.test(nodeName)) {
+ node = (data.cache[nodeName] = data.createElem(nodeName)).cloneNode();
+ } else {
+ node = data.createElem(nodeName);
+ }
+
+ return node.canHaveChildren && !reSkip.test(nodeName) ? data.frag.appendChild(node) : node;
+ }
+
+ function createDocumentFragment(ownerDocument, data){
+ if (!ownerDocument) {
+ ownerDocument = document;
+ }
+ if(supportsUnknownElements){
+ return ownerDocument.createDocumentFragment();
+ }
+ data = data || getExpandoData(ownerDocument);
+ var clone = data.frag.cloneNode(),
+ i = 0,
+ elems = getElements(),
+ l = elems.length;
+ for(;i .active > a > [class^="icon-"],
+.nav-pills > .active > a > [class*=" icon-"],
+.nav-list > .active > a > [class^="icon-"],
+.nav-list > .active > a > [class*=" icon-"],
+.navbar-inverse .nav > .active > a > [class^="icon-"],
+.navbar-inverse .nav > .active > a > [class*=" icon-"],
+.dropdown-menu > li > a:hover > [class^="icon-"],
+.dropdown-menu > li > a:hover > [class*=" icon-"],
+.dropdown-menu > .active > a > [class^="icon-"],
+.dropdown-menu > .active > a > [class*=" icon-"],
+.dropdown-submenu:hover > a > [class^="icon-"],
+.dropdown-submenu:hover > a > [class*=" icon-"] {
+ background-image: none;
+}
+[class^="icon-"]:before,
+[class*=" icon-"]:before {
+ text-decoration: inherit;
+ display: inline-block;
+ speak: none;
+}
+/* makes sure icons active on rollover in links */
+a [class^="icon-"],
+a [class*=" icon-"] {
+ display: inline-block;
+}
+/* makes the font 33% larger relative to the icon container */
+.icon-large:before {
+ vertical-align: -10%;
+ font-size: 1.3333333333333333em;
+}
+.btn [class^="icon-"],
+.nav [class^="icon-"],
+.btn [class*=" icon-"],
+.nav [class*=" icon-"] {
+ display: inline;
+ /* keeps button heights with and without icons the same */
+
+}
+.btn [class^="icon-"].icon-large,
+.nav [class^="icon-"].icon-large,
+.btn [class*=" icon-"].icon-large,
+.nav [class*=" icon-"].icon-large {
+ line-height: .9em;
+}
+.btn [class^="icon-"].icon-spin,
+.nav [class^="icon-"].icon-spin,
+.btn [class*=" icon-"].icon-spin,
+.nav [class*=" icon-"].icon-spin {
+ display: inline-block;
+}
+.nav-tabs [class^="icon-"],
+.nav-pills [class^="icon-"],
+.nav-tabs [class*=" icon-"],
+.nav-pills [class*=" icon-"] {
+ /* keeps button heights with and without icons the same */
+
+}
+.nav-tabs [class^="icon-"],
+.nav-pills [class^="icon-"],
+.nav-tabs [class*=" icon-"],
+.nav-pills [class*=" icon-"],
+.nav-tabs [class^="icon-"].icon-large,
+.nav-pills [class^="icon-"].icon-large,
+.nav-tabs [class*=" icon-"].icon-large,
+.nav-pills [class*=" icon-"].icon-large {
+ line-height: .9em;
+}
+li [class^="icon-"],
+.nav li [class^="icon-"],
+li [class*=" icon-"],
+.nav li [class*=" icon-"] {
+ display: inline-block;
+ width: 1.25em;
+ text-align: center;
+}
+li [class^="icon-"].icon-large,
+.nav li [class^="icon-"].icon-large,
+li [class*=" icon-"].icon-large,
+.nav li [class*=" icon-"].icon-large {
+ /* increased font size for icon-large */
+
+ width: 1.5625em;
+}
+ul.icons {
+ list-style-type: none;
+ text-indent: -0.75em;
+}
+ul.icons li [class^="icon-"],
+ul.icons li [class*=" icon-"] {
+ width: .75em;
+}
+.icon-muted {
+ color: #eeeeee;
+}
+.icon-border {
+ border: solid 1px #eeeeee;
+ padding: .2em .25em .15em;
+ -webkit-border-radius: 3px;
+ -moz-border-radius: 3px;
+ border-radius: 3px;
+}
+.icon-2x {
+ font-size: 2em;
+}
+.icon-2x.icon-border {
+ border-width: 2px;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+}
+.icon-3x {
+ font-size: 3em;
+}
+.icon-3x.icon-border {
+ border-width: 3px;
+ -webkit-border-radius: 5px;
+ -moz-border-radius: 5px;
+ border-radius: 5px;
+}
+.icon-4x {
+ font-size: 4em;
+}
+.icon-4x.icon-border {
+ border-width: 4px;
+ -webkit-border-radius: 6px;
+ -moz-border-radius: 6px;
+ border-radius: 6px;
+}
+.pull-right {
+ float: right;
+}
+.pull-left {
+ float: left;
+}
+[class^="icon-"].pull-left,
+[class*=" icon-"].pull-left {
+ margin-right: .3em;
+}
+[class^="icon-"].pull-right,
+[class*=" icon-"].pull-right {
+ margin-left: .3em;
+}
+.btn [class^="icon-"].pull-left.icon-2x,
+.btn [class*=" icon-"].pull-left.icon-2x,
+.btn [class^="icon-"].pull-right.icon-2x,
+.btn [class*=" icon-"].pull-right.icon-2x {
+ margin-top: .18em;
+}
+.btn [class^="icon-"].icon-spin.icon-large,
+.btn [class*=" icon-"].icon-spin.icon-large {
+ line-height: .8em;
+}
+.btn.btn-small [class^="icon-"].pull-left.icon-2x,
+.btn.btn-small [class*=" icon-"].pull-left.icon-2x,
+.btn.btn-small [class^="icon-"].pull-right.icon-2x,
+.btn.btn-small [class*=" icon-"].pull-right.icon-2x {
+ margin-top: .25em;
+}
+.btn.btn-large [class^="icon-"],
+.btn.btn-large [class*=" icon-"] {
+ margin-top: 0;
+}
+.btn.btn-large [class^="icon-"].pull-left.icon-2x,
+.btn.btn-large [class*=" icon-"].pull-left.icon-2x,
+.btn.btn-large [class^="icon-"].pull-right.icon-2x,
+.btn.btn-large [class*=" icon-"].pull-right.icon-2x {
+ margin-top: .05em;
+}
+.btn.btn-large [class^="icon-"].pull-left.icon-2x,
+.btn.btn-large [class*=" icon-"].pull-left.icon-2x {
+ margin-right: .2em;
+}
+.btn.btn-large [class^="icon-"].pull-right.icon-2x,
+.btn.btn-large [class*=" icon-"].pull-right.icon-2x {
+ margin-left: .2em;
+}
+.icon-spin {
+ display: inline-block;
+ -moz-animation: spin 2s infinite linear;
+ -o-animation: spin 2s infinite linear;
+ -webkit-animation: spin 2s infinite linear;
+ animation: spin 2s infinite linear;
+}
+@-moz-keyframes spin {
+ 0% { -moz-transform: rotate(0deg); }
+ 100% { -moz-transform: rotate(359deg); }
+}
+@-webkit-keyframes spin {
+ 0% { -webkit-transform: rotate(0deg); }
+ 100% { -webkit-transform: rotate(359deg); }
+}
+@-o-keyframes spin {
+ 0% { -o-transform: rotate(0deg); }
+ 100% { -o-transform: rotate(359deg); }
+}
+@-ms-keyframes spin {
+ 0% { -ms-transform: rotate(0deg); }
+ 100% { -ms-transform: rotate(359deg); }
+}
+@keyframes spin {
+ 0% { transform: rotate(0deg); }
+ 100% { transform: rotate(359deg); }
+}
+@-moz-document url-prefix() {
+ .icon-spin {
+ height: .9em;
+ }
+ .btn .icon-spin {
+ height: auto;
+ }
+ .icon-spin.icon-large {
+ height: 1.25em;
+ }
+ .btn .icon-spin.icon-large {
+ height: .75em;
+ }
+}
+/* Font Awesome uses the Unicode Private Use Area (PUA) to ensure screen
+ readers do not read off random characters that represent icons */
+.icon-glass:before { content: "\f000"; }
+.icon-music:before { content: "\f001"; }
+.icon-search:before { content: "\f002"; }
+.icon-envelope:before { content: "\f003"; }
+.icon-heart:before { content: "\f004"; }
+.icon-star:before { content: "\f005"; }
+.icon-star-empty:before { content: "\f006"; }
+.icon-user:before { content: "\f007"; }
+.icon-film:before { content: "\f008"; }
+.icon-th-large:before { content: "\f009"; }
+.icon-th:before { content: "\f00a"; }
+.icon-th-list:before { content: "\f00b"; }
+.icon-ok:before { content: "\f00c"; }
+.icon-remove:before { content: "\f00d"; }
+.icon-zoom-in:before { content: "\f00e"; }
+
+.icon-zoom-out:before { content: "\f010"; }
+.icon-off:before { content: "\f011"; }
+.icon-signal:before { content: "\f012"; }
+.icon-cog:before { content: "\f013"; }
+.icon-trash:before { content: "\f014"; }
+.icon-home:before { content: "\f015"; }
+.icon-file:before { content: "\f016"; }
+.icon-time:before { content: "\f017"; }
+.icon-road:before { content: "\f018"; }
+.icon-download-alt:before { content: "\f019"; }
+.icon-download:before { content: "\f01a"; }
+.icon-upload:before { content: "\f01b"; }
+.icon-inbox:before { content: "\f01c"; }
+.icon-play-circle:before { content: "\f01d"; }
+.icon-repeat:before { content: "\f01e"; }
+
+/* \f020 doesn't work in Safari. all shifted one down */
+.icon-refresh:before { content: "\f021"; }
+.icon-list-alt:before { content: "\f022"; }
+.icon-lock:before { content: "\f023"; }
+.icon-flag:before { content: "\f024"; }
+.icon-headphones:before { content: "\f025"; }
+.icon-volume-off:before { content: "\f026"; }
+.icon-volume-down:before { content: "\f027"; }
+.icon-volume-up:before { content: "\f028"; }
+.icon-qrcode:before { content: "\f029"; }
+.icon-barcode:before { content: "\f02a"; }
+.icon-tag:before { content: "\f02b"; }
+.icon-tags:before { content: "\f02c"; }
+.icon-book:before { content: "\f02d"; }
+.icon-bookmark:before { content: "\f02e"; }
+.icon-print:before { content: "\f02f"; }
+
+.icon-camera:before { content: "\f030"; }
+.icon-font:before { content: "\f031"; }
+.icon-bold:before { content: "\f032"; }
+.icon-italic:before { content: "\f033"; }
+.icon-text-height:before { content: "\f034"; }
+.icon-text-width:before { content: "\f035"; }
+.icon-align-left:before { content: "\f036"; }
+.icon-align-center:before { content: "\f037"; }
+.icon-align-right:before { content: "\f038"; }
+.icon-align-justify:before { content: "\f039"; }
+.icon-list:before { content: "\f03a"; }
+.icon-indent-left:before { content: "\f03b"; }
+.icon-indent-right:before { content: "\f03c"; }
+.icon-facetime-video:before { content: "\f03d"; }
+.icon-picture:before { content: "\f03e"; }
+
+.icon-pencil:before { content: "\f040"; }
+.icon-map-marker:before { content: "\f041"; }
+.icon-adjust:before { content: "\f042"; }
+.icon-tint:before { content: "\f043"; }
+.icon-edit:before { content: "\f044"; }
+.icon-share:before { content: "\f045"; }
+.icon-check:before { content: "\f046"; }
+.icon-move:before { content: "\f047"; }
+.icon-step-backward:before { content: "\f048"; }
+.icon-fast-backward:before { content: "\f049"; }
+.icon-backward:before { content: "\f04a"; }
+.icon-play:before { content: "\f04b"; }
+.icon-pause:before { content: "\f04c"; }
+.icon-stop:before { content: "\f04d"; }
+.icon-forward:before { content: "\f04e"; }
+
+.icon-fast-forward:before { content: "\f050"; }
+.icon-step-forward:before { content: "\f051"; }
+.icon-eject:before { content: "\f052"; }
+.icon-chevron-left:before { content: "\f053"; }
+.icon-chevron-right:before { content: "\f054"; }
+.icon-plus-sign:before { content: "\f055"; }
+.icon-minus-sign:before { content: "\f056"; }
+.icon-remove-sign:before { content: "\f057"; }
+.icon-ok-sign:before { content: "\f058"; }
+.icon-question-sign:before { content: "\f059"; }
+.icon-info-sign:before { content: "\f05a"; }
+.icon-screenshot:before { content: "\f05b"; }
+.icon-remove-circle:before { content: "\f05c"; }
+.icon-ok-circle:before { content: "\f05d"; }
+.icon-ban-circle:before { content: "\f05e"; }
+
+.icon-arrow-left:before { content: "\f060"; }
+.icon-arrow-right:before { content: "\f061"; }
+.icon-arrow-up:before { content: "\f062"; }
+.icon-arrow-down:before { content: "\f063"; }
+.icon-share-alt:before { content: "\f064"; }
+.icon-resize-full:before { content: "\f065"; }
+.icon-resize-small:before { content: "\f066"; }
+.icon-plus:before { content: "\f067"; }
+.icon-minus:before { content: "\f068"; }
+.icon-asterisk:before { content: "\f069"; }
+.icon-exclamation-sign:before { content: "\f06a"; }
+.icon-gift:before { content: "\f06b"; }
+.icon-leaf:before { content: "\f06c"; }
+.icon-fire:before { content: "\f06d"; }
+.icon-eye-open:before { content: "\f06e"; }
+
+.icon-eye-close:before { content: "\f070"; }
+.icon-warning-sign:before { content: "\f071"; }
+.icon-plane:before { content: "\f072"; }
+.icon-calendar:before { content: "\f073"; }
+.icon-random:before { content: "\f074"; }
+.icon-comment:before { content: "\f075"; }
+.icon-magnet:before { content: "\f076"; }
+.icon-chevron-up:before { content: "\f077"; }
+.icon-chevron-down:before { content: "\f078"; }
+.icon-retweet:before { content: "\f079"; }
+.icon-shopping-cart:before { content: "\f07a"; }
+.icon-folder-close:before { content: "\f07b"; }
+.icon-folder-open:before { content: "\f07c"; }
+.icon-resize-vertical:before { content: "\f07d"; }
+.icon-resize-horizontal:before { content: "\f07e"; }
+
+.icon-bar-chart:before { content: "\f080"; }
+.icon-twitter-sign:before { content: "\f081"; }
+.icon-facebook-sign:before { content: "\f082"; }
+.icon-camera-retro:before { content: "\f083"; }
+.icon-key:before { content: "\f084"; }
+.icon-cogs:before { content: "\f085"; }
+.icon-comments:before { content: "\f086"; }
+.icon-thumbs-up:before { content: "\f087"; }
+.icon-thumbs-down:before { content: "\f088"; }
+.icon-star-half:before { content: "\f089"; }
+.icon-heart-empty:before { content: "\f08a"; }
+.icon-signout:before { content: "\f08b"; }
+.icon-linkedin-sign:before { content: "\f08c"; }
+.icon-pushpin:before { content: "\f08d"; }
+.icon-external-link:before { content: "\f08e"; }
+
+.icon-signin:before { content: "\f090"; }
+.icon-trophy:before { content: "\f091"; }
+.icon-github-sign:before { content: "\f092"; }
+.icon-upload-alt:before { content: "\f093"; }
+.icon-lemon:before { content: "\f094"; }
+.icon-phone:before { content: "\f095"; }
+.icon-check-empty:before { content: "\f096"; }
+.icon-bookmark-empty:before { content: "\f097"; }
+.icon-phone-sign:before { content: "\f098"; }
+.icon-twitter:before { content: "\f099"; }
+.icon-facebook:before { content: "\f09a"; }
+.icon-github:before { content: "\f09b"; }
+.icon-unlock:before { content: "\f09c"; }
+.icon-credit-card:before { content: "\f09d"; }
+.icon-rss:before { content: "\f09e"; }
+
+.icon-hdd:before { content: "\f0a0"; }
+.icon-bullhorn:before { content: "\f0a1"; }
+.icon-bell:before { content: "\f0a2"; }
+.icon-certificate:before { content: "\f0a3"; }
+.icon-hand-right:before { content: "\f0a4"; }
+.icon-hand-left:before { content: "\f0a5"; }
+.icon-hand-up:before { content: "\f0a6"; }
+.icon-hand-down:before { content: "\f0a7"; }
+.icon-circle-arrow-left:before { content: "\f0a8"; }
+.icon-circle-arrow-right:before { content: "\f0a9"; }
+.icon-circle-arrow-up:before { content: "\f0aa"; }
+.icon-circle-arrow-down:before { content: "\f0ab"; }
+.icon-globe:before { content: "\f0ac"; }
+.icon-wrench:before { content: "\f0ad"; }
+.icon-tasks:before { content: "\f0ae"; }
+
+.icon-filter:before { content: "\f0b0"; }
+.icon-briefcase:before { content: "\f0b1"; }
+.icon-fullscreen:before { content: "\f0b2"; }
+
+.icon-group:before { content: "\f0c0"; }
+.icon-link:before { content: "\f0c1"; }
+.icon-cloud:before { content: "\f0c2"; }
+.icon-beaker:before { content: "\f0c3"; }
+.icon-cut:before { content: "\f0c4"; }
+.icon-copy:before { content: "\f0c5"; }
+.icon-paper-clip:before { content: "\f0c6"; }
+.icon-save:before { content: "\f0c7"; }
+.icon-sign-blank:before { content: "\f0c8"; }
+.icon-reorder:before { content: "\f0c9"; }
+.icon-list-ul:before { content: "\f0ca"; }
+.icon-list-ol:before { content: "\f0cb"; }
+.icon-strikethrough:before { content: "\f0cc"; }
+.icon-underline:before { content: "\f0cd"; }
+.icon-table:before { content: "\f0ce"; }
+
+.icon-magic:before { content: "\f0d0"; }
+.icon-truck:before { content: "\f0d1"; }
+.icon-pinterest:before { content: "\f0d2"; }
+.icon-pinterest-sign:before { content: "\f0d3"; }
+.icon-google-plus-sign:before { content: "\f0d4"; }
+.icon-google-plus:before { content: "\f0d5"; }
+.icon-money:before { content: "\f0d6"; }
+.icon-caret-down:before { content: "\f0d7"; }
+.icon-caret-up:before { content: "\f0d8"; }
+.icon-caret-left:before { content: "\f0d9"; }
+.icon-caret-right:before { content: "\f0da"; }
+.icon-columns:before { content: "\f0db"; }
+.icon-sort:before { content: "\f0dc"; }
+.icon-sort-down:before { content: "\f0dd"; }
+.icon-sort-up:before { content: "\f0de"; }
+
+.icon-envelope-alt:before { content: "\f0e0"; }
+.icon-linkedin:before { content: "\f0e1"; }
+.icon-undo:before { content: "\f0e2"; }
+.icon-legal:before { content: "\f0e3"; }
+.icon-dashboard:before { content: "\f0e4"; }
+.icon-comment-alt:before { content: "\f0e5"; }
+.icon-comments-alt:before { content: "\f0e6"; }
+.icon-bolt:before { content: "\f0e7"; }
+.icon-sitemap:before { content: "\f0e8"; }
+.icon-umbrella:before { content: "\f0e9"; }
+.icon-paste:before { content: "\f0ea"; }
+.icon-lightbulb:before { content: "\f0eb"; }
+.icon-exchange:before { content: "\f0ec"; }
+.icon-cloud-download:before { content: "\f0ed"; }
+.icon-cloud-upload:before { content: "\f0ee"; }
+
+.icon-user-md:before { content: "\f0f0"; }
+.icon-stethoscope:before { content: "\f0f1"; }
+.icon-suitcase:before { content: "\f0f2"; }
+.icon-bell-alt:before { content: "\f0f3"; }
+.icon-coffee:before { content: "\f0f4"; }
+.icon-food:before { content: "\f0f5"; }
+.icon-file-alt:before { content: "\f0f6"; }
+.icon-building:before { content: "\f0f7"; }
+.icon-hospital:before { content: "\f0f8"; }
+.icon-ambulance:before { content: "\f0f9"; }
+.icon-medkit:before { content: "\f0fa"; }
+.icon-fighter-jet:before { content: "\f0fb"; }
+.icon-beer:before { content: "\f0fc"; }
+.icon-h-sign:before { content: "\f0fd"; }
+.icon-plus-sign-alt:before { content: "\f0fe"; }
+
+.icon-double-angle-left:before { content: "\f100"; }
+.icon-double-angle-right:before { content: "\f101"; }
+.icon-double-angle-up:before { content: "\f102"; }
+.icon-double-angle-down:before { content: "\f103"; }
+.icon-angle-left:before { content: "\f104"; }
+.icon-angle-right:before { content: "\f105"; }
+.icon-angle-up:before { content: "\f106"; }
+.icon-angle-down:before { content: "\f107"; }
+.icon-desktop:before { content: "\f108"; }
+.icon-laptop:before { content: "\f109"; }
+.icon-tablet:before { content: "\f10a"; }
+.icon-mobile-phone:before { content: "\f10b"; }
+.icon-circle-blank:before { content: "\f10c"; }
+.icon-quote-left:before { content: "\f10d"; }
+.icon-quote-right:before { content: "\f10e"; }
+
+.icon-spinner:before { content: "\f110"; }
+.icon-circle:before { content: "\f111"; }
+.icon-reply:before { content: "\f112"; }
+.icon-github-alt:before { content: "\f113"; }
+.icon-folder-close-alt:before { content: "\f114"; }
+.icon-folder-open-alt:before { content: "\f115"; }
diff --git a/app/assets/stylesheets/plugins/_notification_list.sass b/app/assets/stylesheets/plugins/_notification_list.sass
new file mode 100644
index 00000000..fd39dc9c
--- /dev/null
+++ b/app/assets/stylesheets/plugins/_notification_list.sass
@@ -0,0 +1,5 @@
+.notifications_list
+ .notification
+ margin: 10px 0
+ a
+ text-decoration: none
diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb
index cbfbc1fc..7fb9b1ba 100644
--- a/app/views/layouts/application.html.erb
+++ b/app/views/layouts/application.html.erb
@@ -4,6 +4,7 @@
Kandan
<%= stylesheet_link_tag "http://ajax.googleapis.com/ajax/libs/jqueryui/1.8.16/themes/ui-lightness/jquery-ui.css" %>
<%= stylesheet_link_tag "http://fonts.googleapis.com/css?family=PT+Sans:400,700" %>
+ <%= stylesheet_link_tag "/assets/lib/font-awesome.css" %>
<%= stylesheet_link_tag "application", :media => "all" %>
<%= favicon_link_tag %>