More than working version

This commit is contained in:
nikolark committed 2014-11-17 21:31:53 +01:00
1 parent 13545da18e
commit e243513bd9
19 files changed
+809 -150

No files matched your search

+233 -48
View File
@@ -1,49 +1,234 @@
$(document).ready(function() {
nunjucks.configure({ autoescape: true });
var api_urls = {
fwd_list: '/api/forwards/',
fwd_delete: '/api/forward/',
fwd_create: '/api/forward/',
ou_list: '/api/orgunits/',
me: '/api/me/',
};
if( $('body.home').length ) {
$.getJSON(api_urls.ou_list, function(data) {
var ou_html = nunjucks.render('orgunits.html', {
orgunits: data,
api_urls: api_urls
});
$(".orgunit-list").append(ou_html);
/* Add listeners */
$(".orgunit-list a").on('click', function(e) {
e.preventDefault();
$(".orgunit-list li").removeClass('active');
$(this).parent().toggleClass('active');
// TODO: you are here
});
});
$.getJSON(api_urls.fwd_list, function(data) {
if( !data.cpanelresult ) {
$(".forwards-container").html("No results.");
return;
}
var forwards = data.cpanelresult.data;
var lists =_.groupBy(forwards, function(fwd) { return fwd.dest; });
var fw_html = nunjucks.render('list.html', {
lists: lists,
api_urls: api_urls
});
$(".forwards-container").html(fw_html);
$("input[name=fwd-delete]").click(function() {
$(this).parent().parent().toggleClass('danger');
});
});
(function() {
'use strict';
/*global moment, jQuery, document, _, $, window, List */
function getParameterByName(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'),
results = regex.exec(location.search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}
});
function parseEmails(text) {
if(text === undefined || text === "") {
return [];
}
/* Get each word from the text, split by spaces, end line, semicolon,
quotes, commas, colons, parens and brackets. */
var words = text.split(/[\s\n;"',;:()<>[\]\\]+/),
emails = [],
distinct_emails;
// Regex for identifying an email address.
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
// For each of the words, add to the array of emails if the word matches the email regex.
emails = _.filter(words, function(word) {
return word.match(re);
});
emails = _.map(emails, function(el) {
return el.toLowerCase();
});
return _.unique(emails);
}
function render_alert(msg, cssClass) {
return nunjucks.render('alert.html', {'msg': msg, 'cssClass': cssClass});
}
$(document).ready(function() {
var csrf_token = $('meta[name=x-csrf-token]').attr('content');
var api_urls = {
fwd_list: '/api/forwards/',
fwd_delete: '/api/forward/',
fwd_create: '/api/forward/', // + forwarder
ou_list: '/api/orgunits/',
me: '/api/me/',
};
nunjucks.configure({ autoescape: true });
/* Home view (lists) */
if( $('body.home').length ) {
$.getJSON(api_urls.ou_list, function(data) {
var ou_html = nunjucks.render('orgunits.html', {
orgunits: data,
api_urls: api_urls
});
$(".orgunit-list").append(ou_html);
/* New list */
var new_list_html = nunjucks.render('new_list.html', {
orgunits: data,
api_urls: api_urls
});
$('.new-list').html(new_list_html);
$('.new-list .js-new-list-name').on('keyup', function(e) {
var new_list_name = $('.new-list .js-new-list-name').val();
if(new_list_name === '') {
new_list_name = 'Ny liste';
} else {
var prefix = $('.new-list .prefix-select .active').attr('data-value');
new_list_name = 'NY: ' + prefix + new_list_name + "@studentersamfundet.no";
}
$('.new-list .panel-heading').text(new_list_name);
});
$('.new-list textarea').on('keyup', function(e) {
var text = $(this).val();
var emails = parseEmails(text);
if(emails.length > 0) {
$('.new-list .email-counter').text(emails.length);
} else {
$('.new-list .email-counter').text('');
}
});
$('.js-add-list').on('click', function(e) {
$('.new-list .result').html(''); // reset errors
e.preventDefault();
/* Validate */
var new_list_name = $('.new-list .js-new-list-name').val();
if(new_list_name.length === 0) {
$('.new-list-result').html(render_alert('Navn på epostliste mangler', 'danger'));
return;
}
var text = $('.new-list textarea').val();
var emails = parseEmails(text);
if(emails.length === 0) {
$('.new-list-result').html(render_alert('Ingen eposter i epost-feltet...', 'danger'));
return;
}
// Valid form
var prefix = $('.new-list .prefix-select .active').attr('data-value');
var dest = prefix + new_list_name + "@studentersamfundet.no";
var new_list = {};
new_list[dest] = _.map(emails, function(el) {
return {'dest': dest, 'forward': el};
});
var deferreds = [];
$.each(new_list[dest], function(i, el) {
el.csrfmiddlewaretoken = csrf_token;
deferreds.push($.post(api_urls.fwd_create, el, function() {}, 'json'));
});
$.when.apply($, deferreds).then(function(){
// Success
$('.new-list-result').html(render_alert('Lagt til ny liste: ' + dest, 'success'));
$('.new-list textarea').val('');
$('.new-list .js-new-list-name').val('');
}).fail(function(err){
$('.new-list-result').html(render_alert('Kunne ikke opprette ny liste \'' + dest +'\': '+ err, 'danger'));
});
var added_list_html = nunjucks.render('list.html', {
lists: new_list,
});
$(".forwards-container").prepend(added_list_html);
});
/* Add list filter listeners */
$(".orgunit-list a").on('click', function(e) {
var prefix = $(this).attr('data-prefix');
var querystring = $(this).attr('href');
e.preventDefault();
/* Toggle selection */
$(".orgunit-list li").removeClass('active');
$(this).parent().toggleClass('active');
/* Update query string */
window.history.pushState(null, null, querystring);
/* Filter lists */
var re_prefix = new RegExp('^'+prefix);
$(".fwdlist").each(function(el) {
var cur_name = $(this).attr('data-list-name');
if(re_prefix.test(cur_name)) {
$(this).removeClass('hidden');
} else {
$(this).addClass('hidden');
}
});
});
});
/* Load lists */
$.getJSON(api_urls.fwd_list, function(data) {
if( !data.cpanelresult ) {
$(".forwards-container").html("No results.");
return;
}
var forwards = data.cpanelresult.data;
var lists =_.groupBy(forwards, function(fwd) { return fwd.dest; });
var fw_html = nunjucks.render('list.html', {
lists: lists,
api_urls: api_urls
});
$(".forwards-container").html(fw_html);
/* Toggle delete state */
$("input[name=fwd-delete]").click(function() {
$(this).parent().parent().parent().toggleClass('danger');
});
});
$(".forwards-container").on('click', function(e) {
/* Add to delete selection */
var target = $(e.target);
if( target.attr('name') == 'fwd-delete' ) {
var tbody = target.closest('tbody');
var num_selected = tbody.find("[name=fwd-delete]:checked").length;
if(num_selected > 0) {
tbody.find('.btn-del').addClass('visible');
} else {
tbody.find('.btn-del').removeClass('visible');
}
}
/* Delete selected */
else if( target.hasClass('js-del-selected') ) {
var list_name = target.attr('data-delete-list-name');
var checked = $('[data-list-name="'+list_name+'"] [name="fwd-delete"]:checked');
var delete_these = _.map(checked, function(el) {
return $(el).val();
});
var deferreds = [];
$.each(delete_these, function(i, el) {
var data = {
type: 'DELETE',
headers: {'X-CSRFToken': csrf_token},
url: api_urls.fwd_delete + el + '/',
dataType: 'json'
};
deferreds.push($.ajax(data));
});
$.when.apply($, deferreds).then(function(){
// Success
checked.closest('tr').remove();
// TODO remove list if no more rows
}).fail(function(err){
$('[data-list-name="'+list_name+'"] .result-alert').html(render_alert('Kunne ikke fjerne epostaliaser', 'danger'));
});
}
/* Add new */
else if( target.hasClass('js-new-email') ) {
// TODO not working
var email_field = target.parent().parent().find('[name=new-email]');
console.log(email_field);
if(email_field.get(0).checkValidity() === false) {
return true;
}
e.preventDefault();
console.log(email_field.val());
}
});
/* New list toggle display */
$('.new-list-btn').on('click', function() {
$('.new-list').toggleClass('visible');
});
}
});
})();
+57 -1
View File
@@ -1,8 +1,10 @@
$icon-font-path: "../fonts/";
@import "../../bower_components/bootstrap-sass-official/vendor/assets/stylesheets/bootstrap";
.login-form {
margin: 0 auto;
max-width: 400px;
max-width: 300px;
float: none;
input[type=submit] {
float: right;
@@ -42,4 +44,58 @@ body {
height: 100px;
background-color: #f5f5f5;
padding-top: 20px;
}
/* Lists */
.del-header {
text-align: center;
width: 82px;
}
.del-cell {
padding: 0 !important;
}
.del-label {
display: block;
height: 30px;
margin: 0;
text-align: center;
input {
margin: 0;
position: relative;
top: 6px;
}
}
.btn-del {
display: none;
&.visible {
display: block;
}
}
.forwards-container table > thead > tr > th:first-child,
.forwards-container table > tbody > tr > td:first-child
{
padding-left: 16px;
}
.forwards-container .badge {
float: right;
margin-right: 14px;
}
.new-list-btn {
margin-bottom: 20px;
}
.new-list {
display: none;
&.visible {
display: block;
}
}
.btn-add-list {
float: right;
margin-top: 10px;
}
/* Responsive fixes */
@media(max-width: $screen-xs-max){
td {
font-size: 13px;
}
}
@@ -0,0 +1,4 @@
<div class="alert alert-{{ cssClass }}">
<a class="close" data-dismiss="alert">×</a>
{{ msg }}
</div>
+10 -6
View File
@@ -1,23 +1,27 @@
{% for list,members in lists %}
<div class="fwdlist">
<div class="fwdlist" data-list-name="{{ list }}">
<div class="panel panel-default">
<div class="panel-heading">{{ list }} <span class="badge">{{members|length}}</span></div>
<table class="table table-striped table-condensed">
<thead>
<tr>
<th>Medlem</th>
<th class="text-center">Slett</th>
<th class="del-header">Velg</th>
</tr>
</thead>
<tbody>
{% for member in members %}
<tr><td>{{ member.forward }}</td><td class="text-center"><input type="checkbox" name='fwd-delete' value="{{ member.uri_dest }}={{ member.uri_forward }}"></td></tr>
<tr><td>{{ member.forward }}</td><td class="del-cell"><label class="del-label" for="{{ member.dest }}={{ member.forward }}"><input id="{{ member.dest }}={{ member.forward }}" type="checkbox" name='fwd-delete' value="{{ member.dest }}={{ member.forward }}"></label></td></tr>
{% endfor %}
<tr><td colspan="2">
<div class="input-group"><input type="email" name="" class="form-control"><span class="input-group-btn"><button class="btn btn-default" type="button">Legg til</button></span></div>
</td></tr>
<tr><td>
<form><div class="input-group">
<input type="email" name="new-email" class="form-control">
<span class="input-group-btn"><button class="btn btn-default js-new-email" type="button"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Legg til</button></span>
</div></form>
</td><td><button class="btn btn-default btn-del js-del-selected" type="button" data-delete-list-name="{{ list }}"><span class="glyphicon glyphicon-remove" aria-hidden="true"></span> Slett</button></td></tr>
</tbody>
</table>
<div class="result-alert"></div>
</div>
</div>
{% endfor %}
@@ -0,0 +1,20 @@
<div class="panel panel-default">
<div class="panel-heading">Ny liste</div>
<div class="panel-body">
<div class="input-group">
<span class="input-group-btn">
<button type="button" class="btn btn-default dropdown-toggle" data-toggle="dropdown" aria-expanded="false">{{orgunits[0].prefix}} <span class="caret"></span></button>
<ul class="dropdown-menu prefix-select">
{% for ou in orgunits %}
<li{% if loop.first %} class="active"{% endif %}data-value="{{ ou.prefix }}-"><a href="#">{{ou.prefix}}-</a></li>
{% endfor %}
</ul>
</span>
<input type="text" class="form-control js-new-list-name">
<span class="input-group-addon">@studentersamfundet.no</span>
</div>
<h4>Eposter <span class="badge email-counter"></span></h4>
<textarea class="form-control" placeholder="asdf@studentersamfundet.no, qwerty@studentersamfundet.no" rows="4"></textarea>
<button type="button" class="btn btn-primary btn-add-list js-add-list"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Opprett liste</button>
</div>
</div>
+1 -1
View File
@@ -1,3 +1,3 @@
{% for ou in orgunits %}
<li><a href="/?q={{ou.prefix }}">{{ ou.name }}</a></li>
<li><a href="/lists/?q={{ou.prefix }}" data-prefix="{{ou.prefix }}">{{ ou.name }}</a></li>
{% endfor %}
+234 -48
View File
@@ -1,49 +1,235 @@
$(document).ready(function() {
nunjucks.configure({ autoescape: true });
var api_urls = {
fwd_list: '/api/forwards/',
fwd_delete: '/api/forward/',
fwd_create: '/api/forward/',
ou_list: '/api/orgunits/',
me: '/api/me/',
};
if( $('body.home').length ) {
$.getJSON(api_urls.ou_list, function(data) {
var ou_html = nunjucks.render('orgunits.html', {
orgunits: data,
api_urls: api_urls
});
$(".orgunit-list").append(ou_html);
/* Add listeners */
$(".orgunit-list a").on('click', function(e) {
e.preventDefault();
$(".orgunit-list li").removeClass('active');
$(this).parent().toggleClass('active');
// TODO: you are here
});
});
$.getJSON(api_urls.fwd_list, function(data) {
if( !data.cpanelresult ) {
$(".forwards-container").html("No results.");
return;
}
var forwards = data.cpanelresult.data;
var lists =_.groupBy(forwards, function(fwd) { return fwd.dest; });
var fw_html = nunjucks.render('list.html', {
lists: lists,
api_urls: api_urls
});
$(".forwards-container").html(fw_html);
$("input[name=fwd-delete]").click(function() {
$(this).parent().parent().toggleClass('danger');
});
});
(function() {
'use strict';
/*global moment, jQuery, document, _, $, window, List */
function getParameterByName(name) {
name = name.replace(/[\[]/, '\\[').replace(/[\]]/, '\\]');
var regex = new RegExp('[\\?&]' + name + '=([^&#]*)'),
results = regex.exec(location.search);
return results === null ? '' : decodeURIComponent(results[1].replace(/\+/g, ' '));
}
});
function parseEmails(text) {
if(text === undefined || text === "") {
return [];
}
/* Get each word from the text, split by spaces, end line, semicolon, quotes, commas, colons, parens,
and brackets.
*/
var words = text.split(/[\s\n;"',;:()<>[\]\\]+/),
emails = [],
distinct_emails;
// Regex for identifying an email address.
var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
// For each of the words, add to the array of emails if the word matches the email regex.
emails = _.filter(words, function(word) {
return word.match(re);
});
emails = _.map(emails, function(el) {
return el.toLowerCase();
});
return _.unique(emails);
}
function render_alert(msg, cssClass) {
return nunjucks.render('alert.html', {'msg': msg, 'cssClass': cssClass});
}
$(document).ready(function() {
var csrf_token = $('meta[name=x-csrf-token]').attr('content');
var api_urls = {
fwd_list: '/api/forwards/',
fwd_delete: '/api/forward/',
fwd_create: '/api/forward/', // + forwarder
ou_list: '/api/orgunits/',
me: '/api/me/',
};
nunjucks.configure({ autoescape: true });
/* Home view (lists) */
if( $('body.home').length ) {
$.getJSON(api_urls.ou_list, function(data) {
var ou_html = nunjucks.render('orgunits.html', {
orgunits: data,
api_urls: api_urls
});
$(".orgunit-list").append(ou_html);
/* New list */
var new_list_html = nunjucks.render('new_list.html', {
orgunits: data,
api_urls: api_urls
});
$('.new-list').html(new_list_html);
$('.new-list .js-new-list-name').on('keyup', function(e) {
var new_list_name = $('.new-list .js-new-list-name').val();
if(new_list_name === '') {
new_list_name = 'Ny liste';
} else {
var prefix = $('.new-list .prefix-select .active').attr('data-value');
new_list_name = 'NY: ' + prefix + new_list_name + "@studentersamfundet.no";
}
$('.new-list .panel-heading').text(new_list_name);
});
$('.new-list textarea').on('keyup', function(e) {
var text = $(this).val();
var emails = parseEmails(text);
if(emails.length > 0) {
$('.new-list .email-counter').text(emails.length);
} else {
$('.new-list .email-counter').text('');
}
});
$('.js-add-list').on('click', function(e) {
$('.new-list .result').html(''); // reset errors
e.preventDefault();
/* Validate */
var new_list_name = $('.new-list .js-new-list-name').val();
if(new_list_name.length === 0) {
$('.new-list-result').html(render_alert('Navn på epostliste mangler', 'danger'));
return;
}
var text = $('.new-list textarea').val();
var emails = parseEmails(text);
if(emails.length === 0) {
$('.new-list-result').html(render_alert('Ingen eposter i epost-feltet...', 'danger'));
return;
}
// Valid form
var prefix = $('.new-list .prefix-select .active').attr('data-value');
var dest = prefix + new_list_name + "@studentersamfundet.no";
var new_list = {};
new_list[dest] = _.map(emails, function(el) {
return {'dest': dest, 'forward': el};
});
var deferreds = [];
$.each(new_list[dest], function(i, el) {
el.csrfmiddlewaretoken = csrf_token;
deferreds.push($.post(api_urls.fwd_create, el, function() {}, 'json'));
});
$.when.apply($, deferreds).then(function(){
// Success
$('.new-list-result').html(render_alert('Lagt til ny liste: ' + dest, 'success'));
$('.new-list textarea').val('');
$('.new-list .js-new-list-name').val('');
}).fail(function(err){
$('.new-list-result').html(render_alert('Kunne ikke opprette ny liste \'' + dest +'\': '+ err, 'danger'));
});
var added_list_html = nunjucks.render('list.html', {
lists: new_list,
});
$(".forwards-container").prepend(added_list_html);
});
/* Add list filter listeners */
$(".orgunit-list a").on('click', function(e) {
var prefix = $(this).attr('data-prefix');
var querystring = $(this).attr('href');
e.preventDefault();
/* Toggle selection */
$(".orgunit-list li").removeClass('active');
$(this).parent().toggleClass('active');
/* Update query string */
window.history.pushState(null, null, querystring);
/* Filter lists */
var re_prefix = new RegExp('^'+prefix);
$(".fwdlist").each(function(el) {
var cur_name = $(this).attr('data-list-name');
if(re_prefix.test(cur_name)) {
$(this).removeClass('hidden');
} else {
$(this).addClass('hidden');
}
});
});
});
/* Load lists */
$.getJSON(api_urls.fwd_list, function(data) {
if( !data.cpanelresult ) {
$(".forwards-container").html("No results.");
return;
}
var forwards = data.cpanelresult.data;
var lists =_.groupBy(forwards, function(fwd) { return fwd.dest; });
var fw_html = nunjucks.render('list.html', {
lists: lists,
api_urls: api_urls
});
$(".forwards-container").html(fw_html);
/* Toggle delete state */
$("input[name=fwd-delete]").click(function() {
$(this).parent().parent().parent().toggleClass('danger');
});
});
$(".forwards-container").on('click', function(e) {
/* Add to delete selection */
var target = $(e.target);
if( target.attr('name') == 'fwd-delete' ) {
var tbody = target.closest('tbody');
var num_selected = tbody.find("[name=fwd-delete]:checked").length;
if(num_selected > 0) {
tbody.find('.btn-del').addClass('visible');
} else {
tbody.find('.btn-del').removeClass('visible');
}
}
/* Delete selected */
else if( target.hasClass('js-del-selected') ) {
var list_name = target.attr('data-delete-list-name');
var checked = $('[data-list-name="'+list_name+'"] [name="fwd-delete"]:checked');
var delete_these = _.map(checked, function(el) {
return $(el).val();
});
var deferreds = [];
$.each(delete_these, function(i, el) {
var data = {
type: 'DELETE',
headers: {'X-CSRFToken': csrf_token},
url: api_urls.fwd_delete + el + '/',
dataType: 'json'
};
deferreds.push($.ajax(data));
});
$.when.apply($, deferreds).then(function(){
// Success
checked.closest('tr').remove();
// TODO remove list if no more rows
}).fail(function(err){
$('[data-list-name="'+list_name+'"] .result-alert').html(render_alert('Kunne ikke fjerne epostaliaser', 'danger'));
});
}
/* Add new */
else if( target.hasClass('js-new-email') ) {
// TODO not working
var email_field = target.parent().parent().find('[name=new-email]');
console.log(email_field);
if(email_field.get(0).checkValidity() === false) {
return true;
}
e.preventDefault();
console.log(email_field.val());
}
});
/* New list toggle display */
$('.new-list-btn').on('click', function() {
$('.new-list').toggleClass('visible');
});
}
});
})();
+111 -15
View File
@@ -1,3 +1,25 @@
(function() {(window.nunjucksPrecompiled = window.nunjucksPrecompiled || {})["alert.html"] = (function() {function root(env, context, frame, runtime, cb) {
var lineno = null;
var colno = null;
var output = "";
try {
output += "<div class=\"alert alert-";
output += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, "cssClass"), env.autoesc);
output += "\">\n\t<a class=\"close\" data-dismiss=\"alert\">×</a>\n\t";
output += runtime.suppressValue(runtime.contextOrFrameLookup(context, frame, "msg"), env.autoesc);
output += "\n</div>";
cb(null, output);
;
} catch (e) {
cb(runtime.handleError(e, lineno, colno));
}
}
return {
root: root
};
})();
})();
(function() {(window.nunjucksPrecompiled = window.nunjucksPrecompiled || {})["list.html"] = (function() {function root(env, context, frame, runtime, cb) {
var lineno = null;
var colno = null;
@@ -20,11 +42,13 @@ frame.set("loop.revindex0", t_2 - t_1 - 1);
frame.set("loop.first", t_1 === 0);
frame.set("loop.last", t_1 === t_2 - 1);
frame.set("loop.length", t_2);
output += "\n<div class=\"fwdlist\">\n\t<div class=\"panel panel-default\">\n\t <div class=\"panel-heading\">";
output += "\n<div class=\"fwdlist\" data-list-name=\"";
output += runtime.suppressValue(t_4, env.autoesc);
output += "\">\n\t<div class=\"panel panel-default\">\n\t <div class=\"panel-heading\">";
output += runtime.suppressValue(t_4, env.autoesc);
output += " <span class=\"badge\">";
output += runtime.suppressValue(env.getFilter("length").call(context, t_5), env.autoesc);
output += "</span></div>\n\t\t<table class=\"table table-striped table-condensed\">\n\t\t\t<thead>\n\t\t <tr>\n\t\t\t <th>Medlem</th>\n\t\t\t <th class=\"text-center\">Slett</th>\n\t\t </tr>\n\t </thead>\n\t <tbody>\n\t\t\t";
output += "</span></div>\n\t\t<table class=\"table table-striped table-condensed\">\n\t\t\t<thead>\n\t\t <tr>\n\t\t\t <th>Medlem</th>\n\t\t\t <th class=\"del-header\">Velg</th>\n\t\t </tr>\n\t </thead>\n\t <tbody>\n\t\t\t";
frame = frame.push();
var t_8 = t_5;
if(t_8) {var t_7 = t_8.length;
@@ -40,16 +64,26 @@ frame.set("loop.last", t_6 === t_7 - 1);
frame.set("loop.length", t_7);
output += "\n\t\t\t\t<tr><td>";
output += runtime.suppressValue(runtime.memberLookup((t_9),"forward", env.autoesc), env.autoesc);
output += "</td><td class=\"text-center\"><input type=\"checkbox\" name='fwd-delete' value=\"";
output += runtime.suppressValue(runtime.memberLookup((t_9),"uri_dest", env.autoesc), env.autoesc);
output += "</td><td class=\"del-cell\"><label class=\"del-label\" for=\"";
output += runtime.suppressValue(runtime.memberLookup((t_9),"dest", env.autoesc), env.autoesc);
output += "=";
output += runtime.suppressValue(runtime.memberLookup((t_9),"uri_forward", env.autoesc), env.autoesc);
output += "\"></td></tr>\n\t\t\t";
output += runtime.suppressValue(runtime.memberLookup((t_9),"forward", env.autoesc), env.autoesc);
output += "\"><input id=\"";
output += runtime.suppressValue(runtime.memberLookup((t_9),"dest", env.autoesc), env.autoesc);
output += "=";
output += runtime.suppressValue(runtime.memberLookup((t_9),"forward", env.autoesc), env.autoesc);
output += "\" type=\"checkbox\" name='fwd-delete' value=\"";
output += runtime.suppressValue(runtime.memberLookup((t_9),"dest", env.autoesc), env.autoesc);
output += "=";
output += runtime.suppressValue(runtime.memberLookup((t_9),"forward", env.autoesc), env.autoesc);
output += "\"></label></td></tr>\n\t\t\t";
;
}
}
frame = frame.pop();
output += "\n\t\t\t\t<tr><td colspan=\"2\">\n\t\t\t\t<div class=\"input-group\"><input type=\"email\" name=\"\" class=\"form-control\"><span class=\"input-group-btn\"><button class=\"btn btn-default\" type=\"button\">Legg til</button></span></div>\n\t\t\t\t</td></tr>\n\t\t\t</tbody>\n\t\t</table>\n\t</div>\n</div>\n";
output += "\n\t\t\t\t<tr><td>\n\t\t\t\t<form><div class=\"input-group\">\n\t\t\t\t\t<input type=\"email\" name=\"new-email\" class=\"form-control\">\n\t\t\t\t\t<span class=\"input-group-btn\"><button class=\"btn btn-default js-new-email\" type=\"button\"><span class=\"glyphicon glyphicon-plus\" aria-hidden=\"true\"></span> Legg til</button></span>\n\t\t\t\t</div></form>\n\t\t\t\t</td><td><button class=\"btn btn-default btn-del js-del-selected\" type=\"button\" data-delete-list-name=\"";
output += runtime.suppressValue(t_4, env.autoesc);
output += "\"><span class=\"glyphicon glyphicon-remove\" aria-hidden=\"true\"></span> Slett</button></td></tr>\n\t\t\t</tbody>\n\t\t</table>\n\t\t<div class=\"result-alert\"></div>\n\t</div>\n</div>\n";
;
}
} else {
@@ -67,11 +101,13 @@ frame.set("loop.revindex0", t_2 - t_1 - 1);
frame.set("loop.first", t_1 === 0);
frame.set("loop.last", t_1 === t_2 - 1);
frame.set("loop.length", t_2);
output += "\n<div class=\"fwdlist\">\n\t<div class=\"panel panel-default\">\n\t <div class=\"panel-heading\">";
output += "\n<div class=\"fwdlist\" data-list-name=\"";
output += runtime.suppressValue(t_10, env.autoesc);
output += "\">\n\t<div class=\"panel panel-default\">\n\t <div class=\"panel-heading\">";
output += runtime.suppressValue(t_10, env.autoesc);
output += " <span class=\"badge\">";
output += runtime.suppressValue(env.getFilter("length").call(context, t_11), env.autoesc);
output += "</span></div>\n\t\t<table class=\"table table-striped table-condensed\">\n\t\t\t<thead>\n\t\t <tr>\n\t\t\t <th>Medlem</th>\n\t\t\t <th class=\"text-center\">Slett</th>\n\t\t </tr>\n\t </thead>\n\t <tbody>\n\t\t\t";
output += "</span></div>\n\t\t<table class=\"table table-striped table-condensed\">\n\t\t\t<thead>\n\t\t <tr>\n\t\t\t <th>Medlem</th>\n\t\t\t <th class=\"del-header\">Velg</th>\n\t\t </tr>\n\t </thead>\n\t <tbody>\n\t\t\t";
frame = frame.push();
var t_14 = t_11;
if(t_14) {var t_13 = t_14.length;
@@ -87,16 +123,26 @@ frame.set("loop.last", t_12 === t_13 - 1);
frame.set("loop.length", t_13);
output += "\n\t\t\t\t<tr><td>";
output += runtime.suppressValue(runtime.memberLookup((t_15),"forward", env.autoesc), env.autoesc);
output += "</td><td class=\"text-center\"><input type=\"checkbox\" name='fwd-delete' value=\"";
output += runtime.suppressValue(runtime.memberLookup((t_15),"uri_dest", env.autoesc), env.autoesc);
output += "</td><td class=\"del-cell\"><label class=\"del-label\" for=\"";
output += runtime.suppressValue(runtime.memberLookup((t_15),"dest", env.autoesc), env.autoesc);
output += "=";
output += runtime.suppressValue(runtime.memberLookup((t_15),"uri_forward", env.autoesc), env.autoesc);
output += "\"></td></tr>\n\t\t\t";
output += runtime.suppressValue(runtime.memberLookup((t_15),"forward", env.autoesc), env.autoesc);
output += "\"><input id=\"";
output += runtime.suppressValue(runtime.memberLookup((t_15),"dest", env.autoesc), env.autoesc);
output += "=";
output += runtime.suppressValue(runtime.memberLookup((t_15),"forward", env.autoesc), env.autoesc);
output += "\" type=\"checkbox\" name='fwd-delete' value=\"";
output += runtime.suppressValue(runtime.memberLookup((t_15),"dest", env.autoesc), env.autoesc);
output += "=";
output += runtime.suppressValue(runtime.memberLookup((t_15),"forward", env.autoesc), env.autoesc);
output += "\"></label></td></tr>\n\t\t\t";
;
}
}
frame = frame.pop();
output += "\n\t\t\t\t<tr><td colspan=\"2\">\n\t\t\t\t<div class=\"input-group\"><input type=\"email\" name=\"\" class=\"form-control\"><span class=\"input-group-btn\"><button class=\"btn btn-default\" type=\"button\">Legg til</button></span></div>\n\t\t\t\t</td></tr>\n\t\t\t</tbody>\n\t\t</table>\n\t</div>\n</div>\n";
output += "\n\t\t\t\t<tr><td>\n\t\t\t\t<form><div class=\"input-group\">\n\t\t\t\t\t<input type=\"email\" name=\"new-email\" class=\"form-control\">\n\t\t\t\t\t<span class=\"input-group-btn\"><button class=\"btn btn-default js-new-email\" type=\"button\"><span class=\"glyphicon glyphicon-plus\" aria-hidden=\"true\"></span> Legg til</button></span>\n\t\t\t\t</div></form>\n\t\t\t\t</td><td><button class=\"btn btn-default btn-del js-del-selected\" type=\"button\" data-delete-list-name=\"";
output += runtime.suppressValue(t_10, env.autoesc);
output += "\"><span class=\"glyphicon glyphicon-remove\" aria-hidden=\"true\"></span> Slett</button></td></tr>\n\t\t\t</tbody>\n\t\t</table>\n\t\t<div class=\"result-alert\"></div>\n\t</div>\n</div>\n";
;
}
}
@@ -114,6 +160,54 @@ root: root
})();
})();
(function() {(window.nunjucksPrecompiled = window.nunjucksPrecompiled || {})["new_list.html"] = (function() {function root(env, context, frame, runtime, cb) {
var lineno = null;
var colno = null;
var output = "";
try {
output += "<div class=\"panel panel-default\">\n <div class=\"panel-heading\">Ny liste</div>\n <div class=\"panel-body\">\n \t<div class=\"input-group\">\n\t\t<span class=\"input-group-btn\">\n\t\t\t<button type=\"button\" class=\"btn btn-default dropdown-toggle\" data-toggle=\"dropdown\" aria-expanded=\"false\">";
output += runtime.suppressValue(runtime.memberLookup((runtime.memberLookup((runtime.contextOrFrameLookup(context, frame, "orgunits")),0, env.autoesc)),"prefix", env.autoesc), env.autoesc);
output += " <span class=\"caret\"></span></button>\n\t\t\t<ul class=\"dropdown-menu prefix-select\">\n\t\t\t";
frame = frame.push();
var t_3 = runtime.contextOrFrameLookup(context, frame, "orgunits");
if(t_3) {var t_2 = t_3.length;
for(var t_1=0; t_1 < t_3.length; t_1++) {
var t_4 = t_3[t_1];
frame.set("ou", t_4);
frame.set("loop.index", t_1 + 1);
frame.set("loop.index0", t_1);
frame.set("loop.revindex", t_2 - t_1);
frame.set("loop.revindex0", t_2 - t_1 - 1);
frame.set("loop.first", t_1 === 0);
frame.set("loop.last", t_1 === t_2 - 1);
frame.set("loop.length", t_2);
output += "\n\t\t\t\t<li";
if(runtime.memberLookup((runtime.contextOrFrameLookup(context, frame, "loop")),"first", env.autoesc)) {
output += " class=\"active\"";
;
}
output += "data-value=\"";
output += runtime.suppressValue(runtime.memberLookup((t_4),"prefix", env.autoesc), env.autoesc);
output += "-\"><a href=\"#\">";
output += runtime.suppressValue(runtime.memberLookup((t_4),"prefix", env.autoesc), env.autoesc);
output += "-</a></li>\n\t\t\t";
;
}
}
frame = frame.pop();
output += "\n\t\t\t</ul>\n\t\t</span>\n\t\t<input type=\"text\" class=\"form-control js-new-list-name\">\n\t\t<span class=\"input-group-addon\">@studentersamfundet.no</span>\n\t</div>\n \t<h4>Eposter <span class=\"badge email-counter\"></span></h4>\n <textarea class=\"form-control\" placeholder=\"asdf@studentersamfundet.no, qwerty@studentersamfundet.no\" rows=\"4\"></textarea>\n <button type=\"button\" class=\"btn btn-primary btn-add-list js-add-list\"><span class=\"glyphicon glyphicon-plus\" aria-hidden=\"true\"></span> Opprett liste</button>\n </div>\n</div>";
cb(null, output);
;
} catch (e) {
cb(runtime.handleError(e, lineno, colno));
}
}
return {
root: root
};
})();
})();
(function() {(window.nunjucksPrecompiled = window.nunjucksPrecompiled || {})["orgunits.html"] = (function() {function root(env, context, frame, runtime, cb) {
var lineno = null;
var colno = null;
@@ -132,7 +226,9 @@ frame.set("loop.revindex0", t_2 - t_1 - 1);
frame.set("loop.first", t_1 === 0);
frame.set("loop.last", t_1 === t_2 - 1);
frame.set("loop.length", t_2);
output += "\n<li><a href=\"/?q=";
output += "\n<li><a href=\"/lists/?q=";
output += runtime.suppressValue(runtime.memberLookup((t_4),"prefix", env.autoesc), env.autoesc);
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);
+65 -3
View File
@@ -306,8 +306,8 @@ th {
}
@font-face {
font-family: 'Glyphicons Halflings';
src: url("bootstrap/glyphicons-halflings-regular.eot");
src: url("bootstrap/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"), url("bootstrap/glyphicons-halflings-regular.woff") format("woff"), url("bootstrap/glyphicons-halflings-regular.ttf") format("truetype"), url("bootstrap/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg");
src: url("../fonts/glyphicons-halflings-regular.eot");
src: url("../fonts/glyphicons-halflings-regular.eot?#iefix") format("embedded-opentype"), url("../fonts/glyphicons-halflings-regular.woff") format("woff"), url("../fonts/glyphicons-halflings-regular.ttf") format("truetype"), url("../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular") format("svg");
}
.glyphicon {
position: relative;
@@ -6517,7 +6517,7 @@ button.close {
}
.login-form {
margin: 0 auto;
max-width: 400px;
max-width: 300px;
float: none;
}
.login-form input[type=submit] {
@@ -6562,3 +6562,65 @@ body {
background-color: #f5f5f5;
padding-top: 20px;
}
/* Lists */
.del-header {
text-align: center;
width: 82px;
}
.del-cell {
padding: 0 !important;
}
.del-label {
display: block;
height: 30px;
margin: 0;
text-align: center;
}
.del-label input {
margin: 0;
position: relative;
top: 6px;
}
.btn-del {
display: none;
}
.btn-del.visible {
display: block;
}
.forwards-container table > thead > tr > th:first-child,
.forwards-container table > tbody > tr > td:first-child {
padding-left: 16px;
}
.forwards-container .badge {
float: right;
margin-right: 14px;
}
.new-list-btn {
margin-bottom: 20px;
}
.new-list {
display: none;
}
.new-list.visible {
display: block;
}
.btn-add-list {
float: right;
margin-top: 10px;
}
/* Responsive fixes */
@media (max-width: 767px) {
td {
font-size: 13px;
}
}
+2 -1
View File
@@ -3,6 +3,7 @@
<head lang="en">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="x-csrf-token" content="{{ csrf_token }}">
<title>{% block "title" %}lister.neuf.no - Epostlister på Det Norske Studentersamfund{% endblock %}</title>
<link rel="stylesheet" href="{% static 'dist/styles/main.css' %}" type="text/css">
<script type="text/javascript" src="{% static 'bower_components/jquery/dist/jquery.js' %}"></script>
@@ -11,7 +12,6 @@
</head>
<body class="{% block "body-css-classes" %}{% endblock %}">
{% include "nav.html" %}
{% block "navigation" %}{% endblock %}
{% block "body" %}{% endblock %}
<footer class="footer">
@@ -22,6 +22,7 @@
</footer>
<script type="text/javascript" src="{% static 'bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/alert.js' %}"></script>
<script type="text/javascript" src="{% static 'bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/dropdown.js' %}"></script>
<script type="text/javascript" src="{% static 'bower_components/bootstrap-sass-official/vendor/assets/javascripts/bootstrap/collapse.js' %}"></script>
<script type="text/javascript" src="{% static 'dist/scripts/templates.js' %}"></script>
<script type="text/javascript" src="{% static 'dist/scripts/main.js' %}"></script>
</body>
+11 -14
View File
@@ -1,23 +1,20 @@
{% extends "base.html" %}
{% block "body-css-classes" %}{% if user.is_authenticated %}home{% else %}login{% endif %}{% endblock %}
{% block "body-css-classes" %}home{% endblock %}
{% block "body" %}
<div class="container">
<div class="row">
{% if not user.is_authenticated %}
<div class="col-md-12"><p>Her kan du administrere epostlistene på <a href="https://studentersamfundet.no">Det Norske Studentersamfund</a>.<br>Logg inn med din DNS-konto under.</p></div>
{% include "login_form.html" %}
{% else %}
<div class="row">
<div class="col-sm-4 sidebar">
<ul class="nav nav-sidebar orgunit-list">
<li class="active"><a href="/">Alle</a></li>
</ul>
<div class="col-sm-4 sidebar">
<ul class="nav nav-sidebar orgunit-list">
<li class="active"><a href="/lists/" data-prefix=".+">Alle</a></li>
</ul>
</div>
<div class="col-sm-8">
<div class="new-list-container">
<button type="button" class="btn btn-default new-list-btn"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> Opprett ny liste</button>
<div class="new-list"></div><div class="new-list-result"></div>
</div>
<div class="col-sm-8">
<div class="forwards-container"></div>
</div>
<div class="forwards-container"></div>
</div>
{% endif %}
</div>
</div>
{% endblock %}
+10
View File
@@ -0,0 +1,10 @@
{% extends "base.html" %}
{% block "body-css-classes" %}index{% endblock %}
{% block "body" %}
<div class="container">
<div class="row">
<div class="col-md-12"><p>Her kan du administrere epostlistene på <a href="https://studentersamfundet.no">Det Norske Studentersamfund</a>.<br>Logg inn med din DNS-konto under.</p></div>
<div class="col-md-12">{% include "registration/login_form.html" %}</div>
</div>
</div>
{% endblock %}
+3 -4
View File
@@ -2,16 +2,15 @@
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#lister-nav-collapse">
<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="#">lister.neuf.no</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<div class="collapse navbar-collapse" id="lister-nav-collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="{% url 'home' %}">Hjem</a></li>
<li{% if 'lister' in request.path %} class="active"{% endif %}><a href="{% url 'home' %}">Hjem</a></li>
</ul>
{% if user.is_authenticated %}
<ul class="nav navbar-nav navbar-right">
@@ -0,0 +1,10 @@
{% extends "base.html" %}
{% block "body-css-classes" %}index{% endblock %}
{% block "body" %}
<div class="container">
<div class="row">
<div class="col-md-12"><p>For å administrere epostlistene på <a href="https://studentersamfundet.no">Det Norske Studentersamfund</a> må du logge inn først.<br>Logg inn med din DNS-konto under.</p></div>
<div class="col-md-12">{% include "registration/login_form.html" %}</div>
</div>
</div>
{% endblock %}
+18 -5
View File
@@ -1,8 +1,9 @@
from django.conf import settings
from django.contrib.auth import login
from django.contrib.auth import login, logout as auth_logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.forms import AuthenticationForm
from django.contrib.auth.models import User
from django.shortcuts import render
from django.shortcuts import render, redirect
from rest_framework import viewsets, views
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
@@ -13,18 +14,30 @@ from mailadmin.serializers import UserSerializer, OrgUnitSerializer, ForwardSeri
from mailadmin.permissions import DestinationPrefixOwner
def home(request):
def index(request):
form = {}
if request.method == "POST":
form = AuthenticationForm(data=request.POST)
if form.is_valid():
# Log the user in.
login(request, form.get_user())
return redirect('home')
else:
if not request.user.is_authenticated():
if request.user.is_authenticated():
return redirect('home')
else:
form = AuthenticationForm(request)
return render(request, "home.html", {'form': form})
return render(request, "index.html", {'form': form})
@login_required
def home(request):
return render(request, "home.html")
def logout(request):
auth_logout(request)
return redirect('index')
class ForwardsViewSet(viewsets.ViewSet):