<link href="//netdna.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" rel="stylesheet" id="bootstrap-css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<!------ Include the above in your HEAD tag ---------->
<link href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css" rel="stylesheet">
<div class="container-fluid">
<div class="row">
<div class="col-md-offset-3 col-md-6">
<ol class="list-group" id="alerts">
</ol>
</div>
</div>
<nav class="navbar navbar-default" role="navigation">
<!-- 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">
<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="#">Sikker Mail Fordeling</a>
</div>
<!-- Collect the nav links, forms, and other content for toggling -->
<div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
<ul class="nav navbar-nav navbar-left">
<li class="active"><a href="#" id="go_rules" class="nav-goto">Regler</a></li>
<li><a href="#" id="go_log" class="nav-goto">Ændringshistorik</a></li>
<li><a href="#" id="go_test" class="nav-goto">Test</a></li>
</ul>
<!--
<form class="navbar-form navbar-left" role="search">
<div class="form-group">
<input type="text" class="form-control" placeholder="Søgestreng">
</div>
<button type="submit" class="btn btn-default"><span class="glyphicon glyphicon-search"></span> Søg</button>
</form>
-->
<ul class="nav navbar-nav navbar-right">
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="false">Rasmus Lock Fuglsang <span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="#">Indstillinger...</a></li>
<li class="divider"></li>
<li><a href="#">Log ud</a></li>
</ul>
</li>
</ul>
</div><!-- /.navbar-collapse -->
</nav>
<div id="rules" class="page">
<form class="form-inline" role="form" id="bogusform" onkeypress="return event.keyCode != 13;">
<ol class="list-group" id="topdrags">
<li class="list-group-item">
<div class="top-toolbar">
<a href="#" class="do-collapseall" title="Fold sammen"><span class="fa fa-minus-square-o"></span></a>
<a href="#" class="do-expandall" title="Fold ud"><span class="fa fa-plus-square-o"></span></a>
<div class="pull-right main-action-panel">
<a href="#" class="do-add-if keyword btn btn-md" title="Tilføj regel"><span class="glyphicon glyphicon-plus-sign"></span>hvis</a>
<a href="#" class="do-save btn btn-primary" title="Gem regler"><span class="glyphicon glyphicon-ok"></span> Gem</a>
</div>
</div>
</li>
<li class="list-group-item">
<div id="toprules" class="rules">
<div class="rule">
<span class="keyword">hvis</span> <div class="dropdown clearfix term open" style="display: inline-block"><span class="term">Emne</span></div> <div class="dropdown clearfix operator open" style="display: inline-block"><div class="dropdown clearfix operator open" style="display: inline-block"><span class="operator">indeholder</span></div></div> <span class="value">ophør af §56-aftale</span>
<div class="clauses">
</div>
<div class="rules"></div>
<div class="target"><span class="keyword">så</span> <span class="target">send til</span> <span class="value">lonteam@haderslev.dk</span></div>
</div><div class="rule">
<span class="keyword">hvis</span> <div class="dropdown clearfix term open" style="display: inline-block"><span class="term">Emne</span></div> <div class="dropdown clearfix operator open" style="display: inline-block"><div class="dropdown clearfix operator open" style="display: inline-block"><span class="operator">indeholder</span></div></div> <span class="value">indkaldelse til periodisk syn</span>
<div class="clauses">
</div>
<div class="rules"></div>
<div class="target"><span class="keyword">så</span> <span class="target">send til</span> <span class="value">forsikring@haderslev.dk</span></div>
</div><div class="rule">
<span class="keyword">hvis</span> <div class="dropdown clearfix term open" style="display: inline-block"><span class="term">Emne</span></div> <div class="dropdown clearfix operator open" style="display: inline-block"><div class="dropdown clearfix operator open" style="display: inline-block"><span class="operator">indeholder</span></div></div> <span class="value">meddelelse om arbejdsgiverrefusion</span>
<div class="clauses">
</div>
<div class="rules"></div>
<div class="target"><span class="keyword">så</span> <span class="target">send til</span> <span class="value">lonteam@haderslev.dk</span></div>
</div><div class="rule">
<span class="keyword">hvis</span> <div class="dropdown clearfix term open" style="display: inline-block"><div class="dropdown clearfix term open" style="display: inline-block"><span class="term">Modtager</span></div></div> <div class="dropdown clearfix operator open" style="display: inline-block"><div class="dropdown clearfix operator open" style="display: inline-block"><span class="operator">lig med</span></div></div> <span class="value">sikkerpost@haderslev.dk</span>
<div class="clauses">
</div>
<div class="rules">
<div class="rule">
<span class="keyword">hvis</span> <div class="dropdown clearfix term open" style="display: inline-block"><div class="dropdown clearfix term open" style="display: inline-block"><span class="term">Emne</span></div></div> <div class="dropdown clearfix operator open" style="display: inline-block"><span class="operator">indeholder</span></div> <span class="value">kvittering for modtagelse af §133 henvisning</span>
<div class="clauses">
</div>
<div class="rules"></div>
<div class="target"><span class="keyword">så</span> <span class="target">send til</span> <span class="value">tandplejen@haderslev.dk</span></div>
</div><div class="rule">
<span class="keyword">hvis</span> <div class="dropdown clearfix term open" style="display: inline-block"><div class="dropdown clearfix term open" style="display: inline-block"><span class="term">Emne</span></div></div> <div class="dropdown clearfix operator open" style="display: inline-block"><span class="operator">indeholder</span></div> <span class="value">verificering</span>
<div class="clauses">
</div>
<div class="rules"></div>
<div class="target"><span class="keyword">så</span> <span class="target">send til</span> <span class="value">personreg@haderslev.dk</span></div>
</div><div class="rule">
<span class="keyword">hvis</span> <div class="dropdown clearfix term open" style="display: inline-block"><div class="dropdown clearfix term open" style="display: inline-block"><span class="term">Emne</span></div></div> <div class="dropdown clearfix operator open" style="display: inline-block"><span class="operator">indeholder</span></div> <span class="value">spor af rotter</span>
<div class="clauses">
</div>
<div class="rules"></div>
<div class="target"><span class="keyword">så</span> <span class="target">send til</span> <span class="value">borgerservicetm@haderslev.dk</span></div>
</div>
</div>
<div class="target"><span class="keyword">ellers</span> <span class="target">send til</span> <span class="value">post@haderslev.dk</span></div>
</div>
<div class="rule">
<span class="keyword">hvis</span> <span class="term">Modtager</span> <div class="dropdown clearfix operator open" style="display: inline-block"><span class="operator">lig med</span></div> <span class="value">sikkerpostforsikring@haderslev.dk</span>
<div class="clauses">
</div>
<div class="rules"></div>
<div class="target"><span class="keyword">så</span> <span class="target">send til</span> <span class="value">forsikring@haderslev.dk</span></div>
</div>
<div class="target"><span class="keyword">ellers</span> <span class="target">send til</span> <span class="value">post@haderslev.dk</span></div>
</div></li>
</ol>
</form>
</div>
<div id="log" class="page">
</div>
<div id="test" class="page"></div>
</div><!-- /.container-fluid -->
<script type="application/javascript" src="http://johnny.github.io/jquery-sortable/js/jquery-sortable.js">
</script>
.navbar-form {
border-left: 1px solid black;
}
body > .container-fluid {
margin-left: 10px;
margin-right: 10px;
}
body.dragging, body.dragging * {
cursor: move !important;
}
.dragged {
position: absolute;
opacity: 0.5;
z-index: 2000;
}
.placeholder {
position: relative;
/** More li styles **/
}
ol {
list-style-type: none;
}
.placeholder::before {
position: absolute;
/** Define arrowhead **/
content: "";
width: 0;
height: 1px;
margin-top: -5px;
left: -9px;
top: -4px;
border: 7px solid transparent;
border-left-color: #777;
border-right: none;
}
.term, .term a {
color: #65B042 !important;
}
.operator, .operator a {
color: #3387CC;
}
.keyword, .keyword a {
color: #E28964;
font-family: "Consolas", monospace;
}
.action-panel {
position:absolute;
right: 1em;
}
.action-panel .do-remove:hover, .action-panel .do-remove-and:hover, .action-panel .do-hide:hover {
color: white;
border-color: #d9534f;
background: #d9534f;
}
.action-panel > a {
padding: 4px;
color: #ccc;
}
.action-panel > a:hover, .top-toolbar a:hover {
color: #428bca;
border-color: #428bca;
}
.rules > .rule > span.keyword {
cursor: move;
}
span.term, span.operator {
cursor: pointer;
}
input.form-control {
width: 300px;
}
.action-panel {
z-index: 100;
}
.collapse-panel {
position: relative;
left: -1em;
width: 0px;
}
.top-toolbar {
font-size: 140%;
padding-left: 3px;
}
.collapse-panel > a, .top-toolbar a:not(.btn-primary) {
color: rgba(200,200,200,0.7);
}
.do-toggle-collapse:hover, .do-collapseall:hover, .do-expandall:hover, .top-toolbar a:hover {
color: #428bca;
}
a.btn-primary:hover {
color: white !important;
}
.timestamp {
position: relative;
z-index: 10;
top: 0px;
font-style: oblique;
color: #777;
display: inline-block;
}
#alerts {
z-index: 200;
position: absolute;
}
#alerts .alert {
width: 100%;
}
span.target {
color: #E28964;
font-weight: bold;
}
#toprules {
font-family: "Consolas", monospace;
font-size: 140%;
}
.rule, .clauses, div.target {
padding-left: 2em;
}
.clauses, .target {
border: 2px solid rgba(255,255,255,0.01);
}
.rule, .rules {
border: 2px solid rgba(0,0,0,0);
border-color: transparent;
border-radius: 3px;
}
.active {
border-color: #777 !important;
}
.error {
background: #f2dede !important;
}
.main-action-panel {
position: relative;
top: -5px;
}
$(function() {
var sourceContainer, oldContainer, mouseX, mouseY, templateIf, templateAnd;
templateIf = $('<div class="rule">\
<span class="keyword">hvis</span> <span class="term">Modtager</span> <span class="operator">ender med</span> <span class="value">@komunen.dk</span>\
<div class="clauses"></div>\
<div class="rules"></div>\
<div class="target"><span class="keyword">så</span> <span class="target">send til</span> <span class="value">support@mycompany.com</span></div>\
</div>');
templateAnd = $('<div class="clause">\
<span class="keyword">og</span> <span class="term">Afsender</span> <span class="operator">lig med</span> <span class="value">forvaltning@kommune.dk</span>\
</div>');
function debugE(e) {
return e && e.get(0) && e.get(0).outerHTML && e.get(0).outerHTML.replace(/[\n\r ]+/g, " ").substring(0, 150);
};
function updateThenClause(container) {
if (container == undefined) return;
var $container = container.el ? $(container.el) : container;
var $target = $container.closest('.rule').children('.target') || $container.children('.target');
$target.each(function() {
var thenClause = $(this);
var prev = thenClause.prev();
if (prev.is('.rules') && prev.children().length > 0) {
thenClause.children('.keyword').text('ellers');
thenClause.find('.do-hide').removeClass('hidden').show();
} else {
thenClause.children('.keyword').text('så');
thenClause.slideDown();
thenClause.closest('.rule').find('> div.action-panel > a.do-show-then').addClass('hidden');
thenClause.find('.do-hide').hide();
}
});
}
$("#toprules").sortable({
group: 'nested',
nested: true,
containerSelector: '.rules',
itemSelector: '.rule',
handle: '.rule > .keyword',
onDragStart: function (item, container, _super) {
sourceContainer = container;
_super(item, container);
},
afterMove: function (placeholder, container) {
if (oldContainer != container) {
if (oldContainer) {
oldContainer.el.removeClass("active")
}
if (container) {
container.el.addClass("active");
}
oldContainer = container;
}
},
onDrop: function (item, container, _super) {
if (container) {
container.el.removeClass("active")
updateThenClause(sourceContainer);
updateThenClause(container);
_super(item)
}
}
});
$('body').on('click', 'span.value', function() {
var text = $(this).text();
var parent = $(this).parent();
$(this).replaceWith('<div class="form-group"><input class="form-control target-input" style="width: 30em" value="' + text + '" type="text"></input></div>');
parent.find('input').focus();
});
/* Note: This is by no means comprehensive, but it weeds out the most blatant typos */
function validateEmail(elem) {
var text = elem.text();
if (/^.+@.+\..+$/.test(text)) {
elem.parent().removeClass('error');
} else {
elem.parent().addClass('error');
}
}
var fx = function(e) {
if ($(e) && $(e).closest('.form-group')) {
var newText = $(e).val();
try {
if (!newText) {
newText = "<nada>";
}
tt = $('<span class="value"></span>');
tt.text(newText);
var form = $(e).closest('.form-group')
var parent = form.parent();
form.replaceWith(tt);
if (parent.is('.target')) {
validateEmail(parent.children('.value'));
}
} catch (err) {
// Ignore
}
}
};
$('body').on('blur', 'input.target-input', function() {
fx($(this));
});
$('body').on('keypress', 'input.target-input', function(e) {
if (e.keyCode == 13) {
fx($(this));
e.preventDefault();
return false;
}
return true;
});
$('body').on('click', '.do-copy', function() {
var parent = $(this).closest('.rule');
var clone = parent.clone();
clone.hide();
parent.after(clone);
clone.slideDown();
});
$('body').on('click', '.do-copy-clause', function() {
var parent = $(this).closest('.clause');
var clone = parent.clone();
clone.hide();
parent.after(clone);
clone.slideDown();
});
$(document).on('click', '.do-remove', function() {
var li = $(this).closest('.rule');
var p = li.parent();
li.slideUp({done: function() { li.remove(); updateThenClause(p); }});
});
$(document).on('click', '.do-remove-clause', function() {
var li = $(this).closest('.clause');
var p = li.parent();
li.slideUp({done: function() { li.remove(); updateThenClause(p); }});
});
$(document).on('click', '.do-hide', function() {
$(this).closest('.target').slideUp();
$(this).closest('.rule').find('> div.action-panel > a.do-show-then').removeClass('hidden');
});
$(document).mousemove(function (e) {
mouseX = e.pageX;
mouseY = e.pageY;
if (e.buttons == 1) {
// TODO: Somehow trigger the target update...
}
return false;
});
$(document).on('click', '.do-add-clause', function() {
var clauses = $(this).closest('.rule').children('.clauses');
var e = templateAnd.clone();
e.hide();
clauses.append(e);
e.slideDown();
updateThenClause(clauses);
decorateWithActionPanels();
});
$(document).on('click', '.do-add-if', function() {
var newElement = templateIf.clone();
newElement.hide();
var rules = $(this).closest('.rule').children('.rules');
if (rules.length == 0) {
rules = $('#toprules');
rules.prepend(newElement);
} else {
rules.append(newElement);
}
newElement.slideDown();
updateThenClause($(this));
decorateWithActionPanels();
});
$('.do-collapseall').click(function() {
$('#topdrags').find('.rule').each(function () {
var icon = $(this).find('> .collapse-panel > .do-toggle-collapse > span');
var rule = $(this);
var subSections = rule.children('.rules,.clauses,.target');
subSections.each(function () {
$(this).slideUp();
});
icon.addClass('fa-plus-square-o');
icon.removeClass('fa-minus-square-o');
});
});
$('.do-expandall').click(function() {
$('#topdrags').find('.rule').each(function () {
var icon = $(this).find('>.collapse-panel > .do-toggle-collapse > span');
var rule = $(this);
var subSections = rule.children('.rules,.clauses,.target');
subSections.each(function () {
$(this).slideDown();
});
icon.addClass('fa-minus-square-o');
icon.removeClass('fa-plus-square-o');
});
});
$(document).on('click', '.do-show-then', function() {
$(this).closest('.rule').children('.target').slideDown();
$(this).addClass('hidden');
});
$('body').on('click', ".rule .dropdown-menu li a", function() {
var selText = $(this).text();
var $dropdown = $(this).closest('div.dropdown');
$dropdown.html('<span class="' + $dropdown.data('type') + '">' + selText + '</span>');
});
function getData(type) {
if (type == 'term') {
return ['Afsender', 'Modtager', '-', 'Emne', 'Besked', '-', 'Afs. CPR', 'Afs. CVR', '-', 'Modt. CPR', 'Modt. CVR', 'Modt. PNR', '-', 'Vedhæftning'];
} else if (type == 'operator') {
return ['lig med', 'indeholder', 'starter med', 'ender med', '-', 'lig en af', 'indeholder en af'];
}
return [];
};
function addDropDown($span, type) {
var text = $span.text();
var $dropdown = $('<div class="dropdown clearfix" style="display: inline-block">\
<a class="dropdown-toggle" data-toggle="dropdown" role="button" aria-expanded="true">' + text + '</a>\
<ul role="menu" class="dropdown dropdown-menu"></ul>');
$dropdown.data('type', type);
$dropdown.addClass(type);
var $list = $dropdown.find('ul.dropdown');
var data = getData(type);
for (i = 0; i < data.length; i++) {
var item = data[i];
if (item == '-') {
$list.append('<li class="divider"></li>');
} else {
$list.append('<li><a href="#">' + item + '</a></li>');
}
}
$span.replaceWith($dropdown);
window.setTimeout(function() {
$dropdown.find('.dropdown-toggle').click();
}, 1);
};
$(document).on('click', 'span.term', function() {
addDropDown($(this), 'term');
});
$(document).on('click', 'span.operator', function() {
addDropDown($(this), 'operator');
});
$('#bogusform input').keydown(function(event) {
if (event.keyCode == 13) {
event.preventDefault();
}
});
$('.nav-goto').click(function() {
var targetPage = $(this).attr('id').substring(3);
var currentTab = $('.page:visible');
var oldNav = '#go_' + currentTab.attr('id');
$(oldNav).closest('li').removeClass('active');
$('#go_' + targetPage).closest('li').addClass('active');
currentTab.fadeOut("fast", function() {
$('#' + targetPage).fadeIn("fast");
});
});
$('.page').hide();
$('#rules').show();
function serializeIf(indent, e) {
var sb = "";
var $e = $(e);
sb += indent + $e.children('.keyword').text() + ' ';
sb += $e.children('.term').text() + ' ';
sb += $e.children('.operator').text() + ' ';
sb += $e.children('.value').text() + "\n";
var clauses = $e.children('.clauses');
clauses.children('.clause').each(function(i,a) {
var $a = $(a);
sb += indent + ' ' + $a.children('.keyword').text() + ' ';
sb += $a.children('.term').text() + ' ';
sb += $a.children('.operator').text() + ' ';
sb += $a.children('.value').text() + "\n";
});
$e.children('.rules').children('.rule').each(function(i,sub) {
sb += serializeIf(indent + " ", sub);
});
$e.children('.target').each(function (i,a) {
var $a = $(a);
sb += indent + ' ' + $a.children('.keyword').text() + ' ';
sb += $a.children('.operator').text() + ' ';
sb += $a.children('.value').text() + "\n";
});
return sb;
}
$('.do-save').click(function() {
var sb = "";
var indent = "";
var date = new Date();
var user = "Rasmus Lock Fuglsang";
$('#toprules > .rule').each(function (i,e) { sb += "\n" + serializeIf(indent, e); });
var log = $('<pre class="rules">' + sb + '</pre>');
var numRules = $('#toprules').find('.rule').length;
var numTargets = $('#toprules').find('div.target').length;
var saveMessage = '<span class="keyword">gemte</span> <span class="term">' + numRules + ' regler</span> <span class="keyword">med</span>\
<span class="term"> '+ numTargets + ' modtagere</span>';
var entry = $('<ol class="list-group history"><li class="list-group-item">\
<div class="row">\
<div class="timestamp col-sm-4">' + date.toLocaleDateString('da-DK') + ' ' + date.toLocaleTimeString('da-DK').replace(/\./g, ':') +' - ' + user + '</div>\
<div class="action-panel pull-right col-sm-1">\
<a href="#" class="do-restore" title="Restore"><span class="fa fa-undo"></span></a>\
<a href="#" class="do-expand" title="Vis/Skjul regler"><span class="fa fa-plus-square-o"></span></a>\
\</div>\
<div class="action col-sm-7">' + saveMessage + '</div>\
</div></li></ol>');
entry.prependTo($('#log'));
entry.find('li').after(log);
entry.find('.rules').hide();
entry.find('.do-expand').on('click', function() {
var rules = $(this).closest('ol').find('pre.rules');
if (rules.is(':visible')) {
rules.slideUp();
$(this).children('span').removeClass('fa-minus-square-o').addClass('fa-plus-square-o');
} else {
rules.slideDown();
$(this).children('span').removeClass('fa-plus-square-o').addClass('fa-minus-square-o');
}
});
var alert = $('<li class="alert alert-success alert-dismissable">' + saveMessage + '</li>');
$('#alerts').append(alert);
var pageWidth = $('.page:visible').width();
alert.css('width', pageWidth*0.5);
//alert.offset().left = pageWidth*0.25;
alert.hide();
alert.slideDown(function() {
window.setTimeout(function() { alert.slideUp(); }, 1500);
});
//window.setTimeout(function() { alert.alert('close');}, 2000);
});
$(document).on('click', '.do-toggle-collapse', function() {
var icon = $(this).children('span');
var rule = $(this).closest('.rule');
var subSections = rule.children('.rules,.clauses,.target');
if (subSections.first().is(':visible')) {
subSections.each(function () {
$(this).slideUp();
});
icon.addClass('fa-plus-square-o');
icon.removeClass('fa-minus-square-o');
} else {
subSections.each(function () {
$(this).slideDown();
});
icon.removeClass('fa-plus-square-o');
icon.addClass('fa-minus-square-o');
}
});
function decorateWithActionPanels() {
$("#rules").find('.rule').each(function () {
if ($(this).children('.action-panel').length == 0) {
$(this).prepend($('<div class="action-panel pull-right">\
<a href="#" class="do-show-then keyword btn btn-md hidden" title="Tilføj modtager"><span class="glyphicon glyphicon-plus-sign"></span>ellers</a>\
<a href="#" class="do-add-if keyword btn btn-md" title="Tilføj regel"><span class="glyphicon glyphicon-plus-sign"></span>hvis</a>\
<a href="#" class="do-add-clause keyword btn btn-md" title="Tilføj klausul"><span class="glyphicon glyphicon-plus-sign"></span>og</a>\
<a href="#" class="do-copy keyword btn btn-md" title="Kopier regel"><span class="fa fa-copy"></span></a>\
<a href="#" class="do-remove keyword btn btn-md" title="Slet regel"><span class="glyphicon glyphicon-remove-sign"></span></a>\
</div>'));
}
if ($(this).children('.collapse-panel').length == 0) {
$(this).prepend($('<div class="collapse-panel pull-left">\
<a href="#" class="do-toggle-collapse"><span class="fa fa-minus-square-o"></span></a>\
</div>'));
}
});
$("#rules").find('.clause').each(function () {
if ($(this).children('.action-panel').length == 0) {
$(this).prepend($('<div class="action-panel pull-right">\
<a href="#" class="do-copy-clause keyword btn btn-md" title="Kopier klausul"><span class="fa fa-copy"></span></a>\
<a href="#" class="do-remove-clause keyword btn btn-md" title="Slet klausul"><span class="glyphicon glyphicon-remove-sign"></span></a>\
</div>'));
}
});
$('#rules').find('div.target').each(function() {
if ($(this).children('.action-panel').length == 0) {
$(this).prepend($('<div class="action-panel pull-right">\
<a href="#" class="do-hide keyword btn btn-md hidden" title="Fjern modtager"><span class="glyphicon glyphicon-remove-sign"></span></a>\
</div>'));
}
});
$('body').find('.rules').each(function() {
updateThenClause($(this));
});
}
decorateWithActionPanels();
})