From 99b296aaeab93b60687946c4553674be2f94d1d8 Mon Sep 17 00:00:00 2001 From: Nikolai R Kristiansen Date: Sun, 30 Nov 2014 16:58:10 +0100 Subject: [PATCH] Notifications and fixes --- mailadmin/static/app/scripts/main.js | 56 +- .../static/app/styles/_pnotify.core.scss | 56 ++ mailadmin/static/app/styles/main.scss | 11 +- mailadmin/static/app/templates/orgunits.html | 4 +- mailadmin/static/bower.json | 3 +- .../bower_components/pnotify/.bower.json | 41 + .../bower_components/pnotify/.gitignore | 4 + .../bower_components/pnotify/bower.json | 30 + .../pnotify/pnotify.buttons.css | 4 + .../pnotify/pnotify.buttons.js | 132 +++ .../pnotify/pnotify.callbacks.js | 48 ++ .../pnotify/pnotify.confirm.js | 152 ++++ .../bower_components/pnotify/pnotify.core.css | 56 ++ .../bower_components/pnotify/pnotify.core.js | 778 ++++++++++++++++++ .../pnotify/pnotify.desktop.js | 143 ++++ .../pnotify/pnotify.history.css | 33 + .../pnotify/pnotify.history.js | 189 +++++ .../pnotify/pnotify.nonblock.js | 151 ++++ .../pnotify/pnotify.picon.css | 11 + .../pnotify/pnotify.reference.js | 132 +++ mailadmin/static/dist/scripts/main.js | 56 +- mailadmin/static/dist/scripts/templates.js | 6 +- mailadmin/static/dist/styles/main.css | 66 +- mailadmin/templates/base.html | 1 + 24 files changed, 2092 insertions(+), 71 deletions(-) create mode 100644 mailadmin/static/app/styles/_pnotify.core.scss create mode 100644 mailadmin/static/bower_components/pnotify/.bower.json create mode 100644 mailadmin/static/bower_components/pnotify/.gitignore create mode 100644 mailadmin/static/bower_components/pnotify/bower.json create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.buttons.css create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.buttons.js create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.callbacks.js create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.confirm.js create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.core.css create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.core.js create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.desktop.js create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.history.css create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.history.js create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.nonblock.js create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.picon.css create mode 100644 mailadmin/static/bower_components/pnotify/pnotify.reference.js diff --git a/mailadmin/static/app/scripts/main.js b/mailadmin/static/app/scripts/main.js index 1e90705..7fb3180 100644 --- a/mailadmin/static/app/scripts/main.js +++ b/mailadmin/static/app/scripts/main.js @@ -29,11 +29,7 @@ return _.unique(emails); } - function renderAlert(msg, alertClass, iconClass) { - return nunjucks.render('alert.html', {'msg': msg, 'alertClass': alertClass, 'iconClass': iconClass}); - } - function filter_lists_with_members(term, pushState) { - console.log(pushState); + function filter_lists(term, pushState, with_members) { if(pushState) { /* Update query string */ window.history.pushState(null, null, '/lists/?q=' + term); @@ -47,7 +43,7 @@ var hits = _.filter(members, function(el) { return re_term.test($(el).text()); }); - if(re_term.test(cur_name) || hits.length !== 0) { + if(re_term.test(cur_name) || (hits.length !== 0 && with_members) ) { $(this).removeClass('hidden'); } else { $(this).addClass('hidden'); @@ -55,21 +51,14 @@ }); } - // TODO combine with above - function filter_lists(prefix, pushState) { - if(pushState) { - /* Update query string */ - window.history.pushState(null, null, '/lists/?q=^' + prefix+'-'); - } - /* Filter lists */ - var re_prefix = new RegExp('^'+prefix+'-'); - $(".fwdlist").each(function() { - var cur_name = $(this).attr('data-list-name'); - if(re_prefix.test(cur_name)) { - $(this).removeClass('hidden'); - } else { - $(this).addClass('hidden'); - } + function notify(title, text, type) { + /* types: info, success, error */ + new PNotify({ + title: title, + text: text, + type: type, + delay: 3000, + animate_speed: 'fast' }); } @@ -93,6 +82,12 @@ $(".orgunit-list").append(ou_html); var ous_html = nunjucks.render('orgunits_select.html', { orgunits: data }); $(".orgunit-select-container").html(ous_html); + var q_term = getParameterByName('q'); + if(q_term && q_term[0] === '^') { + var prefix = q_term.slice(1, -1); + $(".orgunit-list li").removeClass('active'); + $('.orgunit-list li a[data-prefix="'+prefix+'"]').parent().toggleClass('active'); + } /* New list */ var new_list_html = nunjucks.render('new_list.html', { @@ -100,6 +95,7 @@ api_urls: api_urls }); + $('.new-list').html(new_list_html); $('.new-list .js-new-list-name').on('keyup', function() { var new_list_name = $('.new-list .js-new-list-name').val(); @@ -135,13 +131,13 @@ /* Validate */ var new_list_name = $('.new-list .js-new-list-name').val(); if(new_list_name.length === 0) { - $('.new-list-result').html(renderAlert('Navn på epostliste mangler', 'danger')); + notify('Ny epostliste', 'Navn på epostliste mangler', 'error'); return; } var text = $('.new-list textarea').val(); var emails = parseEmails(text); if(emails.length === 0) { - $('.new-list-result').html(renderAlert('Ingen eposter i epost-feltet...', 'danger')); + notify('Ny epostliste', 'Ingen eposter i epost-feltet...', 'error'); return; } // Valid form @@ -157,7 +153,7 @@ api_urls.fwd_create, new_list[dest], function() { - $('.new-list-result').html(renderAlert('Lagt til ny liste: ' + dest, 'success')); + notify('Lagt til', 'Ny liste: ' + dest + 'lagt til', 'success'); $('.new-list textarea').val(''); $('.new-list .js-new-list-name').val(''); }, @@ -178,7 +174,7 @@ $(this).parent().toggleClass('active'); $('.orgunits-select').val(prefix); - filter_lists(prefix, true); + filter_lists('^'+prefix+'-', true); $('.js-lists-filter-field').val(''); }); $(".orgunits-select").on('change', function() { @@ -188,7 +184,7 @@ $(".orgunit-list li").removeClass('active'); $(".orgunit-list li a[data-prefix="+prefix+"]").parent().toggleClass('active'); - filter_lists(prefix, true); + filter_lists('^'+prefix+'-', true); $('.js-lists-filter-field').val(''); }); }); @@ -196,11 +192,11 @@ /* Load forwards from API and put on page */ $.getJSON(api_urls.fwd_list, function(data) { if( !data.cpanelresult ) { - forwards_container.html(renderAlert("No results.", 'info')); + notify("Ingen lister.", 'Fant ingen tilhørende lister', 'info'); return; } if( 'error' in data.cpanelresult ) { - forwards_container.html(renderAlert("Klarte ikke hente epostlister fra APIet: "+data.cpanelresult.error, 'danger')); + notify('Oops!', 'Klarte ikke hente epostlister fra APIet: '+data.cpanelresult.error, 'error'); return; } @@ -219,13 +215,13 @@ if(q_term[0] === '^') { filter_lists(q_term, false); } else { - filter_lists_with_members(q_term, false); + filter_lists(q_term, false, true); } } /* Filter by search query */ $('.js-lists-filter-field').on('keyup', function() { var term = $(this).val(); - filter_lists_with_members(term, true); + filter_lists(term, true, true); $(".orgunit-list li").removeClass('active'); $(".orgunit-list li:first-child").toggleClass('active'); }); diff --git a/mailadmin/static/app/styles/_pnotify.core.scss b/mailadmin/static/app/styles/_pnotify.core.scss new file mode 100644 index 0000000..3f6b7a7 --- /dev/null +++ b/mailadmin/static/app/styles/_pnotify.core.scss @@ -0,0 +1,56 @@ +/* +Author : Hunter Perrin +Version : 2.0.1 +Link : http://sciactive.com/pnotify/ +*/ +/* -- Notice */ +.ui-pnotify { +top: 25px; +right: 25px; +position: absolute; +height: auto; +/* Ensures notices are above everything */ +z-index: 9999; +} +/* Hides position: fixed from IE6 */ +html > body > .ui-pnotify { +position: fixed; +} +.ui-pnotify .ui-pnotify-shadow { +-webkit-box-shadow: 0px 2px 10px rgba(50, 50, 50, 0.5); +-moz-box-shadow: 0px 2px 10px rgba(50, 50, 50, 0.5); +box-shadow: 0px 2px 10px rgba(50, 50, 50, 0.5); +} +.ui-pnotify-container { +background-position: 0 0; +padding: .8em; +height: 100%; +margin: 0; +} +.ui-pnotify-sharp { +-webkit-border-radius: 0; +-moz-border-radius: 0; +border-radius: 0; +} +.ui-pnotify-title { +display: block; +margin-bottom: .4em; +margin-top: 0; +} +.ui-pnotify-text { +display: block; +} +.ui-pnotify-icon, .ui-pnotify-icon span { +display: block; +float: left; +margin-right: .2em; +} +/* Alternate stack initial positioning. */ +.ui-pnotify.stack-topleft, .ui-pnotify.stack-bottomleft { +left: 25px; +right: auto; +} +.ui-pnotify.stack-bottomright, .ui-pnotify.stack-bottomleft { +bottom: 25px; +top: auto; +} diff --git a/mailadmin/static/app/styles/main.scss b/mailadmin/static/app/styles/main.scss index c628c9e..84894d9 100644 --- a/mailadmin/static/app/styles/main.scss +++ b/mailadmin/static/app/styles/main.scss @@ -1,6 +1,7 @@ $icon-font-path: "../fonts/"; @import "../../bower_components/bootstrap-sass-official/vendor/assets/stylesheets/bootstrap"; +@import "pnotify.core"; @import "animations"; .login-form { @@ -14,10 +15,12 @@ $icon-font-path: "../fonts/"; /* Hide for mobile, show later */ .sidebar { - display: none; - @media (min-width: 768px) { - display: block; - } + .orgunit-list { + display: none; + @media (min-width: 768px) { + display: block; + } + } } .search-field { margin-bottom: 20px; diff --git a/mailadmin/static/app/templates/orgunits.html b/mailadmin/static/app/templates/orgunits.html index 635108e..b8e326c 100644 --- a/mailadmin/static/app/templates/orgunits.html +++ b/mailadmin/static/app/templates/orgunits.html @@ -1,4 +1,4 @@ -
  • Alle
  • +
  • Alle
  • {% for ou in orgunits %} -
  • {{ ou.name }}
  • +
  • {{ ou.name }} ({{ ou.prefix }})
  • {% endfor %} \ No newline at end of file diff --git a/mailadmin/static/bower.json b/mailadmin/static/bower.json index 33c568f..e7ed933 100644 --- a/mailadmin/static/bower.json +++ b/mailadmin/static/bower.json @@ -5,7 +5,8 @@ "bootstrap-sass-official": "~3.1.1", "jquery": "~1.11.0", "underscore": "~1.7.0", - "nunjucks": "~1.1.0" + "nunjucks": "~1.1.0", + "pnotify": "~2.0.1" }, "devDependencies": {} } diff --git a/mailadmin/static/bower_components/pnotify/.bower.json b/mailadmin/static/bower_components/pnotify/.bower.json new file mode 100644 index 0000000..3ab279c --- /dev/null +++ b/mailadmin/static/bower_components/pnotify/.bower.json @@ -0,0 +1,41 @@ +{ + "name": "pnotify", + "version": "2.0.1", + "description": "JavaScript notification plugin.", + "main": [ + "pnotify.core.js", + "pnotify.buttons.js", + "pnotify.callbacks.js", + "pnotify.confirm.js", + "pnotify.desktop.js", + "pnotify.history.js", + "pnotify.nonblock.js", + "pnotify.core.css", + "pnotify.buttons.css", + "pnotify.history.css" + ], + "ignore": [ + "build-cache/", + "build-tools/", + "includes/", + "oxygen/", + "devnote*.*", + "index.html", + "README.md", + "testing.html", + "buildcustom.php", + "pnotify.tooltip.js", + "pnotify.mobile.js" + ], + "homepage": "https://github.com/sciactive/pnotify", + "_release": "2.0.1", + "_resolution": { + "type": "version", + "tag": "2.0.1", + "commit": "30d5ba591a20982d701ea28ad740e8f67823c137" + }, + "_source": "git://github.com/sciactive/pnotify.git", + "_target": "~2.0.1", + "_originalSource": "pnotify", + "_direct": true +} \ No newline at end of file diff --git a/mailadmin/static/bower_components/pnotify/.gitignore b/mailadmin/static/bower_components/pnotify/.gitignore new file mode 100644 index 0000000..835500e --- /dev/null +++ b/mailadmin/static/bower_components/pnotify/.gitignore @@ -0,0 +1,4 @@ +/pnotify.*.min.js +/pnotify.*.min.css +/build-cache/*.js +/build-cache/*.css \ No newline at end of file diff --git a/mailadmin/static/bower_components/pnotify/bower.json b/mailadmin/static/bower_components/pnotify/bower.json new file mode 100644 index 0000000..4db4ab0 --- /dev/null +++ b/mailadmin/static/bower_components/pnotify/bower.json @@ -0,0 +1,30 @@ +{ + "name": "pnotify", + "version": "2.0.1", + "description": "JavaScript notification plugin.", + "main": [ + "pnotify.core.js", + "pnotify.buttons.js", + "pnotify.callbacks.js", + "pnotify.confirm.js", + "pnotify.desktop.js", + "pnotify.history.js", + "pnotify.nonblock.js", + "pnotify.core.css", + "pnotify.buttons.css", + "pnotify.history.css" + ], + "ignore": [ + "build-cache/", + "build-tools/", + "includes/", + "oxygen/", + "devnote*.*", + "index.html", + "README.md", + "testing.html", + "buildcustom.php", + "pnotify.tooltip.js", + "pnotify.mobile.js" + ] +} diff --git a/mailadmin/static/bower_components/pnotify/pnotify.buttons.css b/mailadmin/static/bower_components/pnotify/pnotify.buttons.css new file mode 100644 index 0000000..68f3a12 --- /dev/null +++ b/mailadmin/static/bower_components/pnotify/pnotify.buttons.css @@ -0,0 +1,4 @@ +.ui-pnotify-closer, .ui-pnotify-sticker { +float: right; +margin-left: .2em; +} diff --git a/mailadmin/static/bower_components/pnotify/pnotify.buttons.js b/mailadmin/static/bower_components/pnotify/pnotify.buttons.js new file mode 100644 index 0000000..1e5006d --- /dev/null +++ b/mailadmin/static/bower_components/pnotify/pnotify.buttons.js @@ -0,0 +1,132 @@ +// Buttons +// Uses AMD or browser globals for jQuery. +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.buttons', ['jquery', 'pnotify'], factory); + } else { + // Browser globals + factory(jQuery, PNotify); + } +}(function($, PNotify){ + PNotify.prototype.options.buttons = { + // Provide a button for the user to manually close the notice. + closer: true, + // Only show the closer button on hover. + closer_hover: true, + // Provide a button for the user to manually stick the notice. + sticker: true, + // Only show the sticker button on hover. + sticker_hover: true, + // The various displayed text, helps facilitating internationalization. + labels: { + close: "Close", + stick: "Stick" + } + }; + PNotify.prototype.modules.buttons = { + // This lets us update the options available in the closures. + myOptions: null, + + closer: null, + sticker: null, + + init: function(notice, options){ + var that = this; + this.myOptions = options; + notice.elem.on({ + "mouseenter": function(e){ + // Show the buttons. + if (that.myOptions.sticker && !(notice.options.nonblock && notice.options.nonblock.nonblock)) that.sticker.trigger("pnotify_icon").css("visibility", "visible"); + if (that.myOptions.closer && !(notice.options.nonblock && notice.options.nonblock.nonblock)) that.closer.css("visibility", "visible"); + }, + "mouseleave": function(e){ + // Hide the buttons. + if (that.myOptions.sticker_hover) + that.sticker.css("visibility", "hidden"); + if (that.myOptions.closer_hover) + that.closer.css("visibility", "hidden"); + } + }); + + // Provide a button to stick the notice. + this.sticker = $("
    ", { + "class": "ui-pnotify-sticker", + "css": {"cursor": "pointer", "visibility": options.sticker_hover ? "hidden" : "visible"}, + "click": function(){ + notice.options.hide = !notice.options.hide; + if (notice.options.hide) + notice.queueRemove(); + else + notice.cancelRemove(); + $(this).trigger("pnotify_icon"); + } + }) + .bind("pnotify_icon", function(){ + $(this).children().removeClass(notice.styles.pin_up+" "+notice.styles.pin_down).addClass(notice.options.hide ? notice.styles.pin_up : notice.styles.pin_down); + }) + .append($("", {"class": notice.styles.pin_up, "title": options.labels.stick})) + .prependTo(notice.container); + if (!options.sticker || (notice.options.nonblock && notice.options.nonblock.nonblock)) + this.sticker.css("display", "none"); + + // Provide a button to close the notice. + this.closer = $("
    ", { + "class": "ui-pnotify-closer", + "css": {"cursor": "pointer", "visibility": options.closer_hover ? "hidden" : "visible"}, + "click": function(){ + notice.remove(false); + that.sticker.css("visibility", "hidden"); + that.closer.css("visibility", "hidden"); + } + }) + .append($("", {"class": notice.styles.closer, "title": options.labels.close})) + .prependTo(notice.container); + if (!options.closer || (notice.options.nonblock && notice.options.nonblock.nonblock)) + this.closer.css("display", "none"); + }, + update: function(notice, options){ + this.myOptions = options; + // Update the sticker and closer buttons. + if (!options.closer || (notice.options.nonblock && notice.options.nonblock.nonblock)) + this.closer.css("display", "none"); + else if (options.closer) + this.closer.css("display", "block"); + if (!options.sticker || (notice.options.nonblock && notice.options.nonblock.nonblock)) + this.sticker.css("display", "none"); + else if (options.sticker) + this.sticker.css("display", "block"); + // Update the sticker icon. + this.sticker.trigger("pnotify_icon"); + // Update the hover status of the buttons. + if (options.sticker_hover) + this.sticker.css("visibility", "hidden"); + else if (!(notice.options.nonblock && notice.options.nonblock.nonblock)) + this.sticker.css("visibility", "visible"); + if (options.closer_hover) + this.closer.css("visibility", "hidden"); + else if (!(notice.options.nonblock && notice.options.nonblock.nonblock)) + this.closer.css("visibility", "visible"); + } + }; + $.extend(PNotify.styling.jqueryui, { + closer: "ui-icon ui-icon-close", + pin_up: "ui-icon ui-icon-pin-w", + pin_down: "ui-icon ui-icon-pin-s" + }); + $.extend(PNotify.styling.bootstrap2, { + closer: "icon-remove", + pin_up: "icon-pause", + pin_down: "icon-play" + }); + $.extend(PNotify.styling.bootstrap3, { + closer: "glyphicon glyphicon-remove", + pin_up: "glyphicon glyphicon-pause", + pin_down: "glyphicon glyphicon-play" + }); + $.extend(PNotify.styling.fontawesome, { + closer: "fa fa-times", + pin_up: "fa fa-pause", + pin_down: "fa fa-play" + }); +})); diff --git a/mailadmin/static/bower_components/pnotify/pnotify.callbacks.js b/mailadmin/static/bower_components/pnotify/pnotify.callbacks.js new file mode 100644 index 0000000..a1563a3 --- /dev/null +++ b/mailadmin/static/bower_components/pnotify/pnotify.callbacks.js @@ -0,0 +1,48 @@ +// Callbacks +// Uses AMD or browser globals for jQuery. +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.callbacks', ['jquery', 'pnotify'], factory); + } else { + // Browser globals + factory(jQuery, PNotify); + } +}(function($, PNotify){ + var _init = PNotify.prototype.init, + _open = PNotify.prototype.open, + _remove = PNotify.prototype.remove; + PNotify.prototype.init = function(){ + if (this.options.before_init) { + this.options.before_init(this.options); + } + _init.apply(this, arguments); + if (this.options.after_init) { + this.options.after_init(this); + } + }; + PNotify.prototype.open = function(){ + var ret; + if (this.options.before_open) { + ret = this.options.before_open(this); + } + if (ret !== false) { + _open.apply(this, arguments); + if (this.options.after_open) { + this.options.after_open(this); + } + } + }; + PNotify.prototype.remove = function(timer_hide){ + var ret; + if (this.options.before_close) { + ret = this.options.before_close(this, timer_hide); + } + if (ret !== false) { + _remove.apply(this, arguments); + if (this.options.after_close) { + this.options.after_close(this, timer_hide); + } + } + }; +})); diff --git a/mailadmin/static/bower_components/pnotify/pnotify.confirm.js b/mailadmin/static/bower_components/pnotify/pnotify.confirm.js new file mode 100644 index 0000000..99156aa --- /dev/null +++ b/mailadmin/static/bower_components/pnotify/pnotify.confirm.js @@ -0,0 +1,152 @@ +// Confirm +// Uses AMD or browser globals for jQuery. +(function (factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as a module. + define('pnotify.confirm', ['jquery', 'pnotify'], factory); + } else { + // Browser globals + factory(jQuery, PNotify); + } +}(function($, PNotify){ + PNotify.prototype.options.confirm = { + // Make a confirmation box. + confirm: false, + // Make a prompt. + prompt: false, + // Classes to add to the input element of the prompt. + prompt_class: "", + // The default value of the prompt. + prompt_default: "", + // Whether the prompt should accept multiple lines of text. + prompt_multi_line: false, + // Where to align the buttons. (right, center, left, justify) + align: "right", + // The buttons to display, and their callbacks. + buttons: [ + { + text: "Ok", + addClass: "", + // Whether to trigger this button when the user hits enter in a single line prompt. + promptTrigger: true, + click: function(notice, value){ + notice.remove(); + notice.get().trigger("pnotify.confirm", [notice, value]); + } + }, + { + text: "Cancel", + addClass: "", + click: function(notice){ + notice.remove(); + notice.get().trigger("pnotify.cancel", notice); + } + } + ] + }; + PNotify.prototype.modules.confirm = { + // The div that contains the buttons. + container: null, + // The input element of a prompt. + prompt: null, + + init: function(notice, options){ + this.container = $('
    ').css('text-align', options.align).appendTo(notice.container); + + if (options.confirm || options.prompt) + this.makeDialog(notice, options); + else + this.container.hide(); + }, + + update: function(notice, options){ + if (options.confirm) { + this.makeDialog(notice, options); + this.container.show(); + } else { + this.container.hide().empty(); + } + }, + + afterOpen: function(notice, options){ + if (options.prompt) + this.prompt.focus(); + }, + + makeDialog: function(notice, options) { + var already = false, that = this, btn, elem; + this.container.empty(); + if (options.prompt) { + this.prompt = $('<'+(options.prompt_multi_line ? 'textarea rows="5"' : 'input type="text"')+' style="margin-bottom:5px;clear:both;" />') + .addClass(notice.styles.input+' '+options.prompt_class) + .val(options.prompt_default) + .appendTo(this.container); + } + for (var i in options.buttons) { + btn = options.buttons[i]; + if (already) + this.container.append(' '); + else + already = true; + elem = $('').appendTo(notice.container); + // Since our button is floated, we have to add a clearing div. + notice.container.append('
    ') + + // Now we're going to enable the button on mouseenter. + notice.elem.on({ + "mouseenter": function(e){ + // Enable the button. + // Notice that we have to use "that" to access thingElem, because + // we are in a different scope inside this function. + that.thingElem.prop("disabled", false); + }, + "mouseleave": function(e){ + // Disable the button. + that.thingElem.prop("disabled", true); + } + }); + + // Now we're going to make our button do something. + this.thingElem.on("click", function(){ + // Spin the notice around. + var cur_angle = 0; + var timer = setInterval(function(){ + cur_angle += 10; + if (cur_angle == 360) { + cur_angle = 0; + clearInterval(timer); + } + notice.elem.css({ + '-moz-transform': ('rotate('+cur_angle+'deg)'), + '-webkit-transform': ('rotate('+cur_angle+'deg)'), + '-o-transform': ('rotate('+cur_angle+'deg)'), + '-ms-transform': ('rotate('+cur_angle+'deg)'), + 'filter': ('progid:DXImageTransform.Microsoft.BasicImage(rotation='+(cur_angle / 360 * 4)+')') + }); + }, 20); + }); + }, + + // This is called when the notice is updating its options. + update: function(notice, options /* the new options for our module */, oldOpts /* the old options for our module */){ + // We need to remove the button if it's now disabled, and show it again if it's enabled. + if (options.putThing && this.thingElem) + this.thingElem.show(); + else if (!options.putThing && this.thingElem) + this.thingElem.hide(); + // You may notice that if the user creates a notice without our button, + // then updates it to enable our button, they will be out of luck. + // Whatever, I don't want to write that much code. + + // Now we update the icon, which may have changed. + // Note that as of right now, PNotify doesn't support updating styling. + if (this.thingElem) + this.thingElem.find('i').attr("class", notice.styles.athing); + }, + // I have nothing to put in these, just showing you that they exist. You + // won't need to include them if you aren't using them. + beforeOpen: function(notice, options){ + // Called before the notice is opened. + }, + afterOpen: function(notice, options){ + // Called after the notice is opened. + }, + beforeClose: function(notice, options){ + // Called before the notice is closed. + }, + afterClose: function(notice, options){ + // Called after the notice is closed. + }, + beforeDestroy: function(notice, options){ + // Called before the notice is destroyed. + }, + afterDestroy: function(notice, options){ + // Called after the notice is destroyed. + } + }; + // This is where you would add any styling options you are using in your code. + $.extend(PNotify.styling.jqueryui, { + athing: "ui-icon ui-icon-refresh" + }); + $.extend(PNotify.styling.bootstrap2, { + athing: "icon-refresh" + }); + $.extend(PNotify.styling.bootstrap3, { + athing: "glyphicon glyphicon-refresh" + }); + $.extend(PNotify.styling.fontawesome, { + athing: "fa fa-refresh" + }); +})); diff --git a/mailadmin/static/dist/scripts/main.js b/mailadmin/static/dist/scripts/main.js index 1e90705..7fb3180 100644 --- a/mailadmin/static/dist/scripts/main.js +++ b/mailadmin/static/dist/scripts/main.js @@ -29,11 +29,7 @@ return _.unique(emails); } - function renderAlert(msg, alertClass, iconClass) { - return nunjucks.render('alert.html', {'msg': msg, 'alertClass': alertClass, 'iconClass': iconClass}); - } - function filter_lists_with_members(term, pushState) { - console.log(pushState); + function filter_lists(term, pushState, with_members) { if(pushState) { /* Update query string */ window.history.pushState(null, null, '/lists/?q=' + term); @@ -47,7 +43,7 @@ var hits = _.filter(members, function(el) { return re_term.test($(el).text()); }); - if(re_term.test(cur_name) || hits.length !== 0) { + if(re_term.test(cur_name) || (hits.length !== 0 && with_members) ) { $(this).removeClass('hidden'); } else { $(this).addClass('hidden'); @@ -55,21 +51,14 @@ }); } - // TODO combine with above - function filter_lists(prefix, pushState) { - if(pushState) { - /* Update query string */ - window.history.pushState(null, null, '/lists/?q=^' + prefix+'-'); - } - /* Filter lists */ - var re_prefix = new RegExp('^'+prefix+'-'); - $(".fwdlist").each(function() { - var cur_name = $(this).attr('data-list-name'); - if(re_prefix.test(cur_name)) { - $(this).removeClass('hidden'); - } else { - $(this).addClass('hidden'); - } + function notify(title, text, type) { + /* types: info, success, error */ + new PNotify({ + title: title, + text: text, + type: type, + delay: 3000, + animate_speed: 'fast' }); } @@ -93,6 +82,12 @@ $(".orgunit-list").append(ou_html); var ous_html = nunjucks.render('orgunits_select.html', { orgunits: data }); $(".orgunit-select-container").html(ous_html); + var q_term = getParameterByName('q'); + if(q_term && q_term[0] === '^') { + var prefix = q_term.slice(1, -1); + $(".orgunit-list li").removeClass('active'); + $('.orgunit-list li a[data-prefix="'+prefix+'"]').parent().toggleClass('active'); + } /* New list */ var new_list_html = nunjucks.render('new_list.html', { @@ -100,6 +95,7 @@ api_urls: api_urls }); + $('.new-list').html(new_list_html); $('.new-list .js-new-list-name').on('keyup', function() { var new_list_name = $('.new-list .js-new-list-name').val(); @@ -135,13 +131,13 @@ /* Validate */ var new_list_name = $('.new-list .js-new-list-name').val(); if(new_list_name.length === 0) { - $('.new-list-result').html(renderAlert('Navn på epostliste mangler', 'danger')); + notify('Ny epostliste', 'Navn på epostliste mangler', 'error'); return; } var text = $('.new-list textarea').val(); var emails = parseEmails(text); if(emails.length === 0) { - $('.new-list-result').html(renderAlert('Ingen eposter i epost-feltet...', 'danger')); + notify('Ny epostliste', 'Ingen eposter i epost-feltet...', 'error'); return; } // Valid form @@ -157,7 +153,7 @@ api_urls.fwd_create, new_list[dest], function() { - $('.new-list-result').html(renderAlert('Lagt til ny liste: ' + dest, 'success')); + notify('Lagt til', 'Ny liste: ' + dest + 'lagt til', 'success'); $('.new-list textarea').val(''); $('.new-list .js-new-list-name').val(''); }, @@ -178,7 +174,7 @@ $(this).parent().toggleClass('active'); $('.orgunits-select').val(prefix); - filter_lists(prefix, true); + filter_lists('^'+prefix+'-', true); $('.js-lists-filter-field').val(''); }); $(".orgunits-select").on('change', function() { @@ -188,7 +184,7 @@ $(".orgunit-list li").removeClass('active'); $(".orgunit-list li a[data-prefix="+prefix+"]").parent().toggleClass('active'); - filter_lists(prefix, true); + filter_lists('^'+prefix+'-', true); $('.js-lists-filter-field').val(''); }); }); @@ -196,11 +192,11 @@ /* Load forwards from API and put on page */ $.getJSON(api_urls.fwd_list, function(data) { if( !data.cpanelresult ) { - forwards_container.html(renderAlert("No results.", 'info')); + notify("Ingen lister.", 'Fant ingen tilhørende lister', 'info'); return; } if( 'error' in data.cpanelresult ) { - forwards_container.html(renderAlert("Klarte ikke hente epostlister fra APIet: "+data.cpanelresult.error, 'danger')); + notify('Oops!', 'Klarte ikke hente epostlister fra APIet: '+data.cpanelresult.error, 'error'); return; } @@ -219,13 +215,13 @@ if(q_term[0] === '^') { filter_lists(q_term, false); } else { - filter_lists_with_members(q_term, false); + filter_lists(q_term, false, true); } } /* Filter by search query */ $('.js-lists-filter-field').on('keyup', function() { var term = $(this).val(); - filter_lists_with_members(term, true); + filter_lists(term, true, true); $(".orgunit-list li").removeClass('active'); $(".orgunit-list li:first-child").toggleClass('active'); }); diff --git a/mailadmin/static/dist/scripts/templates.js b/mailadmin/static/dist/scripts/templates.js index 77e5f06..af85147 100644 --- a/mailadmin/static/dist/scripts/templates.js +++ b/mailadmin/static/dist/scripts/templates.js @@ -223,7 +223,7 @@ var lineno = null; var colno = null; var output = ""; try { -output += "
  • Alle
  • \n"; +output += "
  • Alle
  • \n"; frame = frame.push(); var t_3 = runtime.contextOrFrameLookup(context, frame, "orgunits"); if(t_3) {var t_2 = t_3.length; @@ -243,7 +243,9 @@ output += "\" data-prefix=\""; output += runtime.suppressValue(runtime.memberLookup((t_4),"prefix", env.autoesc), env.autoesc); output += "\">"; output += runtime.suppressValue(runtime.memberLookup((t_4),"name", env.autoesc), env.autoesc); -output += "\n"; +output += " ("; +output += runtime.suppressValue(runtime.memberLookup((t_4),"prefix", env.autoesc), env.autoesc); +output += ")\n"; ; } } diff --git a/mailadmin/static/dist/styles/main.css b/mailadmin/static/dist/styles/main.css index 0a6823b..4c8595e 100644 --- a/mailadmin/static/dist/styles/main.css +++ b/mailadmin/static/dist/styles/main.css @@ -6515,6 +6515,68 @@ button.close { display: none !important; } } +/* +Author : Hunter Perrin +Version : 2.0.1 +Link : http://sciactive.com/pnotify/ +*/ +/* -- Notice */ +.ui-pnotify { + top: 25px; + right: 25px; + position: absolute; + height: auto; + /* Ensures notices are above everything */ + z-index: 9999; +} + +/* Hides position: fixed from IE6 */ +html > body > .ui-pnotify { + position: fixed; +} + +.ui-pnotify .ui-pnotify-shadow { + box-shadow: 0px 2px 10px rgba(50, 50, 50, 0.5); +} + +.ui-pnotify-container { + background-position: 0 0; + padding: .8em; + height: 100%; + margin: 0; +} + +.ui-pnotify-sharp { + border-radius: 0; +} + +.ui-pnotify-title { + display: block; + margin-bottom: .4em; + margin-top: 0; +} + +.ui-pnotify-text { + display: block; +} + +.ui-pnotify-icon, .ui-pnotify-icon span { + display: block; + float: left; + margin-right: .2em; +} + +/* Alternate stack initial positioning. */ +.ui-pnotify.stack-topleft, .ui-pnotify.stack-bottomleft { + left: 25px; + right: auto; +} + +.ui-pnotify.stack-bottomright, .ui-pnotify.stack-bottomleft { + bottom: 25px; + top: auto; +} + .spin { -webkit-animation: spin .8s infinite linear; animation: spin .8s infinite linear; @@ -6551,11 +6613,11 @@ button.close { } /* Hide for mobile, show later */ -.sidebar { +.sidebar .orgunit-list { display: none; } @media (min-width: 768px) { - .sidebar { + .sidebar .orgunit-list { display: block; } } diff --git a/mailadmin/templates/base.html b/mailadmin/templates/base.html index f38fd4b..0835254 100644 --- a/mailadmin/templates/base.html +++ b/mailadmin/templates/base.html @@ -24,6 +24,7 @@ +