1275 lines
28 KiB
JavaScript
1275 lines
28 KiB
JavaScript
|
|
var mroot = '(Media Root)';
|
|
var matchesp = ' ~matches~ ';
|
|
|
|
function quot(str)
|
|
{
|
|
if (!str)
|
|
return '""';
|
|
|
|
if (str.indexOf(" ") == -1 && str.indexOf('"') == -1
|
|
&& str.indexOf("\\") == -1)
|
|
return str;
|
|
return '{' + str + '}';
|
|
}
|
|
|
|
function fixupdown()
|
|
{
|
|
$('#ruleset a.uprule').enable().filter(':first').disable();
|
|
$('#ruleset a.downrule').enable().filter(':last').disable();
|
|
|
|
$('#ruleset a.uprule img').attr('src', '/img/nav/up.png')
|
|
.first().attr('src', '/img/nav/up-grey.png');
|
|
$('#ruleset a.downrule img').attr('src', '/img/nav/down.png')
|
|
.last().attr('src', '/img/nav/down-grey.png');
|
|
}
|
|
|
|
function changed(c)
|
|
{
|
|
if (typeof(changed.last) == 'number' && c == changed.last)
|
|
return;
|
|
if (c)
|
|
{
|
|
$('#b_save,#b_revert').button('enable');
|
|
$('#pendingnote').show();
|
|
}
|
|
else
|
|
{
|
|
$('#b_save,#b_revert').button('disable');
|
|
$('#pendingnote').hide();
|
|
}
|
|
changed.last = c;
|
|
}
|
|
|
|
// Setters convert from config file format to display
|
|
var setters = {
|
|
noarg: function(cmd, a) {
|
|
return '';
|
|
},
|
|
int: function(cmd, a) {
|
|
var b = a.split(" ");
|
|
if (b.length == 1)
|
|
{
|
|
op = '=';
|
|
val = a;
|
|
}
|
|
else
|
|
{
|
|
op = b[0];
|
|
val = b[1];
|
|
}
|
|
return op + ' ' + val;
|
|
},
|
|
substr: function(cmd, a) {
|
|
return a;
|
|
},
|
|
'string': function(cmd, a) {
|
|
return a;
|
|
},
|
|
select: function(cmd, a) {
|
|
return schema.criterion[cmd].select[a];
|
|
},
|
|
textmatch: function(cmd, a) {
|
|
return a.replace('~~', matchesp);
|
|
},
|
|
intmatch: function(cmd, a) {
|
|
return a.replace('~~', matchesp);
|
|
}
|
|
};
|
|
|
|
// Getters convert from display to config file format
|
|
var getters = {
|
|
noarg: function(cmd, a) {
|
|
return '';
|
|
},
|
|
int: function(cmd, a) {
|
|
var b = a.split(" ");
|
|
if (b.length != 2)
|
|
return a;
|
|
|
|
if (b[0] == '=')
|
|
return b[1];
|
|
return a;
|
|
},
|
|
substr: function(cmd, a) {
|
|
return a;
|
|
},
|
|
'string': function(cmd, a) {
|
|
return a;
|
|
},
|
|
select: function(cmd, a) {
|
|
var c = schema.criterion[cmd].select;
|
|
for (key in c)
|
|
if (c[key] == a)
|
|
return key;
|
|
return 'UNKNOWNKEY (' + a + ')';
|
|
},
|
|
textmatch: function(cmd, a) {
|
|
return a.replace(matchesp, '~~');
|
|
},
|
|
intmatch: function(cmd, a) {
|
|
return a.replace(matchesp, '~~');
|
|
}
|
|
};
|
|
|
|
function clauseconf(clause)
|
|
{
|
|
var s = '';
|
|
|
|
clause.find('tbody:first > tr.clause,tbody:first > tr.compositeclause')
|
|
.each(function() {
|
|
if ($(this).hasClass('compositeclause'))
|
|
{
|
|
cc = clauseconf($(this).find('table:first'));
|
|
cmd = $(this).attr('cmd');
|
|
if (cc && cc.length)
|
|
s += cmd + ' {' + cc + '} ';
|
|
return;
|
|
}
|
|
cmd = $(this).find('th.cmd').attr('cmd');
|
|
negate = $(this).find('th.cmd').attr('negate');
|
|
c = schema.criterion[cmd];
|
|
val = $.trim($(this).find('td.val').html());
|
|
if (getters[c.type])
|
|
val = getters[c.type](cmd, val);
|
|
|
|
if (negate == '1')
|
|
s += '!';
|
|
s += cmd + ' ' + quot(val) + ' ';
|
|
});
|
|
return s;
|
|
}
|
|
|
|
function ruleconf(rule)
|
|
{
|
|
var s = '';
|
|
|
|
if (rule.hasClass('ruledisabled'))
|
|
s += '## ';
|
|
|
|
if (rule.attr('type') == 'folder')
|
|
s += 'folder ';
|
|
else if (rule.attr('depth') > 0)
|
|
s += 'recurse ' + rule.attr('depth') + ' ';
|
|
|
|
s += clauseconf(rule);
|
|
|
|
act = rule.find('tr.action th.cmd').attr('cmd');
|
|
arg = $.trim(rule.find('tr.action td.val').text());
|
|
if (schema.action[act].argtype == 'folder' && arg == mroot)
|
|
arg = '';
|
|
if (act != 'continue')
|
|
{
|
|
if (schema.action[act].argtype == 'none')
|
|
s += 'action ' + act;
|
|
else
|
|
s += 'action {' + act + ' ' + quot(arg) + '}';
|
|
}
|
|
return s;
|
|
}
|
|
|
|
function conffile()
|
|
{
|
|
var s = '';
|
|
|
|
$('div.rule').each(function(i) {
|
|
comment = $(this).find('span.comment').text();
|
|
if (comment != 'Unnamed rule')
|
|
s += '# ' + comment + '\n';
|
|
s += ruleconf($(this)) + '\n';
|
|
});
|
|
return s;
|
|
}
|
|
|
|
function rulerefresh(rule)
|
|
{
|
|
if (!showraw)
|
|
rule.find('.raw').hide();
|
|
rule.find('.raw').html(ruleconf(rule));
|
|
rule.find('tr.clause th.title,tr.compositeclause th.title')
|
|
.text('And:').first().text('If:');
|
|
rule.find('tr.compositeclause').each(function(e) {
|
|
cmd = $(this).attr('cmd');
|
|
label = schema.criterion[cmd].label;
|
|
$(this).find('table th.title').text(label + ':')
|
|
.first().text('If:');
|
|
});
|
|
if (rule.find('tr.clause,tr.compositeclause').length < 1)
|
|
{
|
|
rule.find('tr.action th.title').text('Always:');
|
|
rule.find('tr.otherwise,div.criteria,div.arrow').hide();
|
|
}
|
|
else
|
|
{
|
|
rule.find('tr.action th.title').text('Then:');
|
|
rule.find('tr.otherwise,div.criteria,div.arrow').show();
|
|
}
|
|
|
|
if (rule.attr('type') == 'recurse')
|
|
rule.find('.recursecomment .depth').text(rule.attr('depth') +
|
|
' level' + (rule.attr('depth') == 1 ? '' : 's'));
|
|
}
|
|
|
|
function critdesc(cmd, negate)
|
|
{
|
|
var c = schema.criterion[cmd];
|
|
if (!c)
|
|
return 'Unknown (' + cmd + ')';
|
|
if (negate == '1' && c.idesc)
|
|
return c.idesc;
|
|
else if (negate == '1')
|
|
return c.desc + ' is not';
|
|
else
|
|
return c.desc;
|
|
}
|
|
|
|
function composite_criterion(c, data)
|
|
{
|
|
s = '<tr class="compositeclause" cmd=' + data.cmd + '>' +
|
|
'<th class=title>And:</th>' +
|
|
'<td colspan=3>' +
|
|
'<table class=compositeclause>' +
|
|
'<tr><td colspan=4>' +
|
|
'<a href=# class=addsubcriterion>' +
|
|
'<img src=img/plus.png height=15 ' +
|
|
'title="Add condition to sub-clause"></a>' +
|
|
' ' +
|
|
'<a class=delsubclause href=# ' +
|
|
'title="Delete sub-clause and the conditions within it">' +
|
|
'<img src=img/delete.png></a>' +
|
|
' ' +
|
|
c.desc +
|
|
'</td></tr>';
|
|
|
|
$.each(data.criteria, function(key, val) {
|
|
s += criterion(val, 'comp');
|
|
});
|
|
|
|
s += '</table></td></tr>';
|
|
|
|
return s;
|
|
}
|
|
|
|
function criterion(data, classes)
|
|
{
|
|
var c = schema.criterion[data.cmd];
|
|
var s;
|
|
|
|
if (!c)
|
|
{
|
|
alert('Unknown Criterion (' + data.cmd + ')');
|
|
return;
|
|
}
|
|
if (c.type == 'composite')
|
|
return composite_criterion(c, data);
|
|
|
|
s = '<tr class="clause';
|
|
if (classes) s += ' ' + classes;
|
|
s += '"><th class=title>And:</th>' +
|
|
'<th class=cmd negate=' + data.negate + ' cmd=' + data.cmd + '>' +
|
|
critdesc(data.cmd, data.negate) + '</th><td class=val>';
|
|
|
|
if (setters[c.type])
|
|
s += setters[c.type](data.cmd, data.arg);
|
|
else
|
|
s += 'UNKNOWN (' + data.arg + ')';
|
|
|
|
s += '</td><td>';
|
|
if (c.type != 'noarg')
|
|
s += '<a class=editclause href=# title="Edit condition">' +
|
|
'<img src=img/edit.png></a>' +
|
|
' ';
|
|
else
|
|
s += '<img src=/img/blank.gif width=16>' +
|
|
' ';
|
|
s += '<a class=delclause href=# title="Delete condition">' +
|
|
'<img src=img/delete.png></a>' +
|
|
'</td></tr>';
|
|
return s;
|
|
}
|
|
|
|
function action(data)
|
|
{
|
|
var c = schema.action[data.cmd];
|
|
var s;
|
|
|
|
if (!c)
|
|
{
|
|
alert('Unknown action - ' + data.cmd);
|
|
return '';
|
|
}
|
|
|
|
if (c.argtype == 'folder' && !data.arg)
|
|
data.arg = mroot;
|
|
|
|
s = '<tr class=action>' +
|
|
'<th class=title>Then:</th>' +
|
|
'<th class=cmd cmd=' + data.cmd + '>' + c.desc + '</th>' +
|
|
'<td class=val>' + data.arg + '</td>' +
|
|
'<td><a class=editaction href=#>' +
|
|
'<img src=img/edit.png></a></td>' +
|
|
'</tr>';
|
|
|
|
if (data.cmd != 'continue')
|
|
{
|
|
if (c.continues)
|
|
s += '<tr><th class=title>And:</th><td class=title>' +
|
|
'Continue to next rule.</td></tr>';
|
|
else if (data.cmd != 'stop')
|
|
s += '<tr><th class=title>And:</th><td class=title>' +
|
|
'Stop processing rules.</td></tr>';
|
|
|
|
s += '<tr class=blank><td> </th></tr>' +
|
|
'<tr class=otherwise><th class=title>Otherwise:</th>' +
|
|
'<td class=title>Continue to next rule.</td></tr>';
|
|
}
|
|
|
|
return s;
|
|
}
|
|
|
|
var last_ruleid = 0;
|
|
|
|
function addrule(id, data)
|
|
{
|
|
if ($('#ruleset').attr('empty'))
|
|
$('#ruleset').empty().removeAttr('empty');
|
|
last_ruleid = id;
|
|
var rule = $('#rule_template')
|
|
.clone()
|
|
.attr('id', 'rule_' + id)
|
|
.addClass('rule')
|
|
.removeClass('hidden');
|
|
|
|
if (!data.depth)
|
|
data.depth = 0;
|
|
if (data.type == 'global')
|
|
{
|
|
data.type = 'recurse';
|
|
data.depth = 1;
|
|
}
|
|
else if (data.type == 'file')
|
|
data.depth = 0;
|
|
|
|
rule.find('span.comment').html(data.name);
|
|
switch (data.type)
|
|
{
|
|
case 'recurse':
|
|
rule.find('.commentleft > span.recurse').show();
|
|
rule.find('.recursecomment').show()
|
|
.find('.depth').text(data.depth + ' level' +
|
|
(data.depth == 1 ? '' : 's'));
|
|
break;
|
|
case 'folder':
|
|
rule.find('.commentleft > span.folder').show();
|
|
rule.find('.foldercomment').show();
|
|
break;
|
|
default:
|
|
rule.find('.commentleft > span.file').show();
|
|
break;
|
|
}
|
|
rule.attr('type', data.type);
|
|
rule.attr('depth', data.depth);
|
|
|
|
var $c = rule.find('table.criteria');
|
|
$.each(data.criteria, function(key, val) {
|
|
if (val.cmd == 'lock' && (
|
|
data.action.cmd == 'lock' || data.action.cmd == 'unlock'))
|
|
{
|
|
alert('Removed legacy lock/unlock - ' +
|
|
'check rules before saving.');
|
|
return;
|
|
}
|
|
$c.find('tbody:first').append(criterion(val));
|
|
});
|
|
$c.find('th.title:first').text('If:');
|
|
|
|
rule.find('table.action tbody').append(action(data.action));
|
|
|
|
if (data.enabled == 0)
|
|
{
|
|
rule.addClass('ruledisabled');
|
|
rule.find('span.disabledtext').removeClass('hidden');
|
|
}
|
|
|
|
$('#ruleset').append(rule);
|
|
|
|
rulerefresh(rule);
|
|
|
|
return rule;
|
|
}
|
|
|
|
function edit_text(obj, title, text, callback, typ)
|
|
{
|
|
$('#edit_text_field').val(text);
|
|
$('#edit_text').dialog({
|
|
title: title,
|
|
height: 'auto', width: 'auto',
|
|
draggable: true, resizable: false,
|
|
autoOpen: true,
|
|
position: {
|
|
my: 'bottom left',
|
|
at: 'top right',
|
|
of: obj,
|
|
collision: 'fit'
|
|
},
|
|
buttons: {
|
|
"Save": function() {
|
|
var val = $.trim($('#edit_text_field').val());
|
|
if (!val)
|
|
alert("Bad value");
|
|
else
|
|
{
|
|
callback(obj, val);
|
|
$(this).dialog('close');
|
|
}
|
|
},
|
|
"Close": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
$('.edit_text_help').hide();
|
|
if (typ)
|
|
$('#edit_text_help_' + typ).show();
|
|
if (text == 'Enter text here...')
|
|
$('#edit_text_field').focus().select();
|
|
}
|
|
|
|
function edit_int(obj, title, op, val, callback)
|
|
{
|
|
$('#edit_int_field').val(val);
|
|
$('#edit_int_op').val(op);
|
|
$('#edit_int').dialog({
|
|
title: title,
|
|
height: 'auto', width: 'auto',
|
|
draggable: true, resizable: false,
|
|
autoOpen: true,
|
|
position: {
|
|
my: 'bottom left',
|
|
at: 'top right',
|
|
of: obj,
|
|
collision: 'fit'
|
|
},
|
|
buttons: {
|
|
"Save": function() {
|
|
var op = $.trim($('#edit_int_op').val());
|
|
var val = $.trim($('#edit_int_field').val());
|
|
if (!op || !val)
|
|
alert("Bad value");
|
|
else
|
|
{
|
|
callback(obj, op, val);
|
|
$(this).dialog('close');
|
|
}
|
|
},
|
|
"Close": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function edit_plainint(obj, title, val, callback)
|
|
{
|
|
$('#edit_plainint_field').val(val);
|
|
$('#edit_plainint').dialog({
|
|
title: title,
|
|
height: 'auto', width: 'auto',
|
|
draggable: true, resizable: false,
|
|
autoOpen: true,
|
|
position: {
|
|
my: 'bottom left',
|
|
at: 'top right',
|
|
of: obj,
|
|
collision: 'fit'
|
|
},
|
|
buttons: {
|
|
"Save": function() {
|
|
var val = $.trim($('#edit_plainint_field')
|
|
.val());
|
|
if (!val)
|
|
alert("Bad value");
|
|
else
|
|
{
|
|
callback(obj, val);
|
|
$(this).dialog('close');
|
|
}
|
|
},
|
|
"Close": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function edit_select(obj, title, options, val, callback)
|
|
{
|
|
$('#edit_select_field').empty();
|
|
$.each(options, function(k, v) {
|
|
$('#edit_select_field').append(
|
|
$('<option></option>').attr('value', k).html(v)
|
|
);
|
|
});
|
|
if (val && val != '')
|
|
$('#edit_select_field').val(val);
|
|
$('#edit_select').dialog({
|
|
title: title,
|
|
height: 'auto', width: 'auto',
|
|
draggable: true, resizable: false,
|
|
autoOpen: true,
|
|
position: {
|
|
my: 'bottom left',
|
|
at: 'top right',
|
|
of: obj,
|
|
collision: 'fit'
|
|
},
|
|
buttons: {
|
|
"Save": function() {
|
|
callback(obj, $('#edit_select_field').val());
|
|
$(this).dialog('close');
|
|
},
|
|
"Close": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function edit_textmatch(obj, title, target, pattern, callback, typ)
|
|
{
|
|
$('#edit_textmatch_target').val(target);
|
|
$('#edit_textmatch_pattern').val(pattern);
|
|
$('#edit_textmatch').dialog({
|
|
title: title,
|
|
height: 'auto', width: 'auto',
|
|
draggable: true, resizable: false,
|
|
autoOpen: true,
|
|
position: {
|
|
my: 'bottom left',
|
|
at: 'top right',
|
|
of: obj,
|
|
collision: 'fit'
|
|
},
|
|
buttons: {
|
|
"Save": function() {
|
|
var pattern =
|
|
$.trim($('#edit_textmatch_pattern').val());
|
|
var target =
|
|
$.trim($('#edit_textmatch_target').val());
|
|
if (!pattern)
|
|
alert("Bad pattern");
|
|
else if (!target)
|
|
alert("Bad target");
|
|
else
|
|
{
|
|
callback(obj, target, pattern);
|
|
$(this).dialog('close');
|
|
}
|
|
},
|
|
"Close": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
$('.edit_textmatch_help').hide();
|
|
if (typ)
|
|
$('#edit_textmatch_help_' + typ).show();
|
|
// if (text == 'Enter text here...')
|
|
// $('#edit_text_field').focus().select();
|
|
}
|
|
|
|
function edit_intmatch(obj, title, target, op, val, callback)
|
|
{
|
|
$('#edit_intmatch_target').val(target);
|
|
$('#edit_intmatch_op').val(op);
|
|
$('#edit_intmatch_field').val(val);
|
|
$('#edit_intmatch').dialog({
|
|
title: title,
|
|
height: 'auto', width: 'auto',
|
|
draggable: true, resizable: false,
|
|
autoOpen: true,
|
|
position: {
|
|
my: 'bottom left',
|
|
at: 'top right',
|
|
of: obj,
|
|
collision: 'fit'
|
|
},
|
|
buttons: {
|
|
"Save": function() {
|
|
var target =
|
|
$.trim($('#edit_intmatch_target').val());
|
|
var op = $.trim($('#edit_intmatch_op').val());
|
|
var val =
|
|
$.trim($('#edit_intmatch_field').val());
|
|
if (!target)
|
|
alert('Bad target');
|
|
else if (!op || !val)
|
|
alert("Bad value");
|
|
else
|
|
{
|
|
callback(obj, target, op, val);
|
|
$(this).dialog('close');
|
|
}
|
|
},
|
|
"Close": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
function edit_clause(obj)
|
|
{
|
|
var cmd = $(obj).find('th.cmd').attr('cmd');
|
|
var target = $(obj).find('td.val');
|
|
var tval = $.trim($(target).text());
|
|
var val = $.trim($(target).html());
|
|
var title = $(obj).find('th.cmd').html();
|
|
if (!schema.criterion[cmd])
|
|
{
|
|
alert('Unhandled command (' + cmd + ')');
|
|
return;
|
|
}
|
|
switch (schema.criterion[cmd].type)
|
|
{
|
|
case 'string':
|
|
case 'substr':
|
|
edit_text(target, title, tval, function(obj, text) {
|
|
$(obj).html(text);
|
|
rulerefresh($(obj).closest('div.rule'));
|
|
changed(1);
|
|
}, schema.criterion[cmd].type);
|
|
break;
|
|
case 'int':
|
|
b = tval.split(" ");
|
|
if (b.length != 2)
|
|
{
|
|
alert('Bad int value');
|
|
break;
|
|
}
|
|
edit_int(target, title, b[0], b[1], function(obj, op, val) {
|
|
$(obj).html(op + ' ' + val);
|
|
rulerefresh($(obj).closest('div.rule'));
|
|
changed(1);
|
|
});
|
|
break;
|
|
case 'select':
|
|
edit_select(target, title, schema.criterion[cmd].select,
|
|
getters.select(cmd, val), function(obj, val) {
|
|
$(obj).html(setters.select(cmd, val));
|
|
rulerefresh($(obj).closest('div.rule'));
|
|
changed(1);
|
|
});
|
|
break;
|
|
case 'textmatch':
|
|
if (tval == 'Enter text here...')
|
|
{
|
|
tgt = "%field";
|
|
ptn = tval;
|
|
}
|
|
else
|
|
{
|
|
b = tval.split(matchesp);
|
|
if (b.length != 2)
|
|
{
|
|
alert('Bad textmatch value');
|
|
break;
|
|
}
|
|
tgt = b[0];
|
|
ptn = b[1];
|
|
}
|
|
edit_textmatch(target, title, tgt, ptn,
|
|
function(obj, tgt, ptn) {
|
|
$(obj).html(tgt + matchesp + ptn);
|
|
rulerefresh($(obj).closest('div.rule'));
|
|
changed(1);
|
|
});
|
|
break;
|
|
case 'intmatch':
|
|
if (tval == "0")
|
|
{
|
|
tgt = "%field";
|
|
op = "=";
|
|
val = "0";
|
|
}
|
|
else
|
|
{
|
|
b = tval.split(matchesp);
|
|
if (b.length != 2)
|
|
{
|
|
alert('Bad intmatch value');
|
|
break;
|
|
}
|
|
c = b[1].split(" ");
|
|
if (c.length != 2)
|
|
{
|
|
alert('Bad intmatch value');
|
|
break;
|
|
}
|
|
tgt = b[0];
|
|
op = c[0];
|
|
val = c[1];
|
|
}
|
|
edit_intmatch(target, title, tgt, op, val,
|
|
function(obj, tgt, op, val) {
|
|
$(obj).html(tgt + matchesp + op + ' ' + val);
|
|
rulerefresh($(obj).closest('div.rule'));
|
|
changed(1);
|
|
});
|
|
break;
|
|
case 'noarg':
|
|
alert('This condition cannot be edited.');
|
|
break;
|
|
|
|
default:
|
|
alert('Unhandled clause type (' + cmd + ')');
|
|
}
|
|
}
|
|
|
|
function loadrules(dir)
|
|
{
|
|
$('#ruleset')
|
|
.html('<img src=/img/loading.gif> Loading rules...');
|
|
$.getJSON('rules_json.jim', {'dir': dir}, function(data) {
|
|
$('#ruleset').empty();
|
|
if (!data.length)
|
|
{
|
|
$('#ruleset').attr('empty', true)
|
|
.html($('#empty_rulebase').html());
|
|
return;
|
|
}
|
|
$.each(data, function(key, val) {
|
|
addrule(key, val);
|
|
});
|
|
fixupdown();
|
|
if (!showraw)
|
|
$('#ruleset div.raw').hide();
|
|
});
|
|
}
|
|
|
|
$(function() {
|
|
|
|
$('#b_add').button({icons: {primary: "ui-icon-plus"}})
|
|
.on('click', function(e) {
|
|
e.preventDefault();
|
|
$('#newrule').dialog({
|
|
height: 'auto', width: 'auto',
|
|
draggable: true, resizable: false,
|
|
autoOpen: true,
|
|
position: {
|
|
my: 'bottom left',
|
|
at: 'top right',
|
|
of: $(this),
|
|
collision: 'fit'
|
|
},
|
|
buttons: {
|
|
"Create Rule": function() {
|
|
rule = addrule(last_ruleid + 1, {
|
|
raw: '',
|
|
name: $('#newrule_comment').val(),
|
|
type: $('input[name=newrule_type]' +
|
|
':checked').val(),
|
|
depth: $('#newrule_depth').val(),
|
|
criteria: [],
|
|
action: {
|
|
cmd: 'continue',
|
|
arg: ''
|
|
}
|
|
});
|
|
changed(1);
|
|
$(this).dialog('close');
|
|
},
|
|
"Close": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
$('#newrule_type_file').prop('checked', true);
|
|
$('#newrule_depth').val(1);
|
|
$('#newrule_depth_box').hide();
|
|
$('#newrule_comment').focus().val('').val('Unnamed rule').select();
|
|
});
|
|
|
|
$('input[name=newrule_type]').on('change', function() {
|
|
if ($('input[name=newrule_type]:checked').val() == 'recurse')
|
|
$('#newrule_depth_box').show();
|
|
else
|
|
$('#newrule_depth_box').hide();
|
|
});
|
|
|
|
$('#b_edit').button({icons: {primary: "ui-icon-script"}});
|
|
$('#buttons')
|
|
.on('click', '#b_edit', function(e) {
|
|
e.preventDefault();
|
|
if (changed.last && !confirm(
|
|
'There are pending changes that will be lost if you switch to ' +
|
|
'the text editor. Continue?'))
|
|
return;
|
|
var dir = $('span.dir').text();
|
|
var root = $('span.root').text();
|
|
var edir = encodeURIComponent(dir);
|
|
if (dir == root)
|
|
cf = '/mod/etc/sweeper.conf';
|
|
else
|
|
cf = edir + '/.sweeper';
|
|
window.location = '/edit/edit.jim' +
|
|
'?file=' + cf +
|
|
'&backdesc=Return+to+sweeper' +
|
|
'&backlink=' + encodeURIComponent('/plugin/sweeper/edit.jim?dir=')
|
|
+ edir;
|
|
});
|
|
|
|
$('#b_save').button({icons: {primary: "ui-icon-disk"}});
|
|
$('#buttons')
|
|
.on('click', '#b_save', function(e) {
|
|
e.preventDefault();
|
|
$(this).dojConfirmAction({
|
|
question: 'Save changes?',
|
|
yesAnswer: 'Yes',
|
|
cancelAnswer: 'No'
|
|
}, function(el) {
|
|
$.post('save.jim', {
|
|
dir: $('span.dir').text(),
|
|
data: conffile()
|
|
}, function(data) {
|
|
$('#output').fadeIn('fast').html(data)
|
|
.delay(5000).fadeOut('slow');
|
|
changed(0);
|
|
});
|
|
});
|
|
});
|
|
|
|
$('#b_revert').button({icons: {primary: "ui-icon-arrowrefresh-1-w"}});
|
|
$('#buttons')
|
|
.on('click', '#b_revert', function(e) {
|
|
e.preventDefault();
|
|
$(this).dojConfirmAction({
|
|
question: 'Discard changes?',
|
|
yesAnswer: 'Yes',
|
|
cancelAnswer: 'No'
|
|
}, function(el) {
|
|
loadrules($('span.dir').text());
|
|
changed(0);
|
|
});
|
|
});
|
|
|
|
$('#b_show').button({icons: {primary: "ui-icon-clipboard"}})
|
|
.on('click', function(e) {
|
|
e.preventDefault();
|
|
$('#showconf')
|
|
.empty()
|
|
.html('<pre>' + conffile() + '</pre>')
|
|
.dialog({
|
|
height: 'auto', width: 'auto',
|
|
autoOpen: true,
|
|
modal: true,
|
|
buttons: {
|
|
"Close": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
$('#b_test').button({icons: {primary: "ui-icon-check"}});
|
|
$('#b_run').button({icons: {primary: "ui-icon-play"}});
|
|
|
|
$('#b_test,#b_run')
|
|
.on('click', function(e) {
|
|
e.preventDefault();
|
|
var id = $(this).attr('id');
|
|
$('#testresults_inner').empty()
|
|
.html('<img src=/img/loading.gif> Running rules... Please wait...');
|
|
|
|
if (id == 'b_test')
|
|
{
|
|
$('#dryrun_info').show();
|
|
dryrun = 1;
|
|
}
|
|
else
|
|
{
|
|
if (!confirm('Run ruleset now?'))
|
|
return;
|
|
$('#dryrun_info').hide();
|
|
dryrun = 0;
|
|
}
|
|
|
|
$('#testresults').dialog({
|
|
height: '600', width: '800',
|
|
draggable: true, resizable: true,
|
|
autoOpen: true,
|
|
buttons: {
|
|
"Close": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
$.post('test.jim', {
|
|
dir: $('span.dir').text(),
|
|
dryrun: dryrun,
|
|
data: conffile()
|
|
}, function(data) {
|
|
$('#testresults_inner').text(data);
|
|
});
|
|
});
|
|
|
|
$('#b_raw').button({icons: {primary: "ui-icon-gear"}})
|
|
.on('click', function(e) {
|
|
$('#ruleset div.raw').toggle('slow');
|
|
showraw = !showraw;
|
|
$.get('save.jim?act=raw&val=' + (showraw ? 1 : 0));
|
|
});
|
|
|
|
$('#b_macro').button({disabled: true, icons: {primary: "ui-icon-plus"}});
|
|
$('#macros').on('click', '#b_macro', function(e) {
|
|
e.preventDefault();
|
|
var set = $('#macroselect').val();
|
|
if (!set) return;
|
|
var desc = macros[set].desc;
|
|
$(this).dojConfirmAction({
|
|
question: 'Add ' + desc + '?',
|
|
yesAnswer: 'Yes',
|
|
cancelAnswer: 'No'
|
|
}, function(el) {
|
|
$('.jcaquestion').remove();
|
|
$.each(macros[set].rules, function(k, v) {
|
|
addrule(last_ruleid + 1, v).hide().addClass('hl');
|
|
});
|
|
$('.hl').slideDown('slow', function() {
|
|
$(this).removeClass('hl');
|
|
});
|
|
fixupdown();
|
|
changed(1);
|
|
$('#macroselect').val(0);
|
|
});
|
|
});
|
|
|
|
changed(0);
|
|
|
|
function addcriterion(rule, target)
|
|
{
|
|
var type = rule.attr('type');
|
|
|
|
switch (type)
|
|
{
|
|
case 'folder':
|
|
options = select_folder_criteria;
|
|
break;
|
|
default:
|
|
options = select_file_criteria;
|
|
break;
|
|
}
|
|
|
|
// Populate select box and reset form.
|
|
$('#newcondition_cmd').empty();
|
|
$.each(options, function(k, v) {
|
|
$('#newcondition_cmd').append(
|
|
$('<option></option>').attr('value', k).html(v)
|
|
);
|
|
});
|
|
$('#newcondition_negate').prop('checked', false);
|
|
$('#newcondition_cmd').trigger('change');
|
|
|
|
$('#newcondition').dialog({
|
|
height: 'auto', width: 'auto',
|
|
draggable: true, resizable: false,
|
|
autoOpen: true,
|
|
position: {
|
|
my: 'bottom left',
|
|
at: 'top right',
|
|
of: target,
|
|
collision: 'fit'
|
|
},
|
|
buttons: {
|
|
"Add Condition": function() {
|
|
$(this).dialog('close');
|
|
var val = $('#newcondition_cmd').val();
|
|
var negate = $('#newcondition_negate')
|
|
.prop('checked') ? '1' : '0';
|
|
var obj = {
|
|
cmd: val,
|
|
negate: negate,
|
|
arg: schema.criterion[val].def,
|
|
criteria: []
|
|
};
|
|
target.find('tbody:first')
|
|
.append(criterion(obj));
|
|
changed(1);
|
|
rulerefresh(rule);
|
|
},
|
|
"Cancel": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
}
|
|
|
|
$('#ruleset')
|
|
.on('click', 'a.editclause', function(e) {
|
|
e.preventDefault();
|
|
edit_clause($(this).closest('tr.clause'));
|
|
})
|
|
.on('click', 'a.addcriterion', function(e) {
|
|
e.preventDefault();
|
|
var rule = $(this).closest('div.rule');
|
|
addcriterion(rule, rule.find('table.criteria'));
|
|
})
|
|
.on('click', 'a.editcomment', function(e) {
|
|
e.preventDefault();
|
|
edit_text($(this), 'Edit rule name',
|
|
$(this).siblings('span.comment').text(),
|
|
function(obj, text) {
|
|
$(obj).siblings('span.comment').text(text);
|
|
changed(1);
|
|
});
|
|
})
|
|
.on('click', 'a.editdepth', function(e) {
|
|
e.preventDefault();
|
|
var rule = $(this).closest('div.rule');
|
|
edit_plainint($(this), 'Edit recursion depth',
|
|
rule.attr('depth'),
|
|
function(obj, val) {
|
|
if (val > 0 && val < 16)
|
|
{
|
|
rule.attr('depth', val);
|
|
if (val > 1)
|
|
rule.attr('type', 'recurse');
|
|
rulerefresh(rule);
|
|
changed(1);
|
|
}
|
|
});
|
|
})
|
|
.on('click', 'a.uprule', function(e) {
|
|
e.preventDefault();
|
|
if ($(this).hasClass('ui-state-disabled'))
|
|
return false;
|
|
var rule = $(this).closest('div.rule');
|
|
var target = $(rule).prev('div.rule');
|
|
if (!target || !target.length)
|
|
return false;
|
|
$(rule).addClass('hl').slideUp('slow', function() {
|
|
$(this).insertBefore($(target))
|
|
.slideDown('slow', function() {
|
|
$(this).removeClass('hl');
|
|
fixupdown();
|
|
changed(1);
|
|
});
|
|
});
|
|
})
|
|
.on('click', 'a.downrule', function(e) {
|
|
e.preventDefault();
|
|
if ($(this).hasClass('ui-state-disabled'))
|
|
return false;
|
|
var rule = $(this).closest('div.rule');
|
|
var target = $(rule).next('div.rule');
|
|
if (!target || !target.length)
|
|
return false;
|
|
$(rule).addClass('hl').slideUp('slow', function() {
|
|
$(this).insertAfter($(target))
|
|
.slideDown('slow', function() {
|
|
$(this).removeClass('hl');
|
|
fixupdown();
|
|
changed(1);
|
|
});
|
|
});
|
|
})
|
|
.on('click', 'a.cprule', function(e) {
|
|
e.preventDefault();
|
|
$(this).dojConfirmAction({
|
|
question: 'Duplicate rule?',
|
|
yesAnswer: 'Yes',
|
|
cancelAnswer: 'No'
|
|
}, function(el) {
|
|
$('.jcaquestion').remove();
|
|
var rule = $(el).closest('div.rule');
|
|
rule.clone()
|
|
.attr('id', 'rule_' + ++last_ruleid)
|
|
.addClass('hl').hide()
|
|
.insertAfter(rule)
|
|
.slideDown('slow', function() {
|
|
$(this).removeClass('hl');
|
|
changed(1);
|
|
})
|
|
.find('span.comment').append(' (copy)');
|
|
});
|
|
})
|
|
.on('click', 'a.enadisrule', function(e) {
|
|
e.preventDefault();
|
|
var rule = $(this).closest('div.rule')
|
|
.toggleClass('ruledisabled');
|
|
rule.find('span.disabledtext').toggleClass('hidden',
|
|
!rule.hasClass('ruledisabled'));
|
|
rulerefresh(rule);
|
|
changed(1);
|
|
})
|
|
.on('click', 'a.editaction', function(e) {
|
|
e.preventDefault();
|
|
|
|
var rule = $(this).closest('div.rule');
|
|
var type = rule.attr('type');
|
|
|
|
switch (type)
|
|
{
|
|
case 'folder':
|
|
options = select_folder_actions;
|
|
break;
|
|
default:
|
|
options = select_file_actions;
|
|
break;
|
|
}
|
|
|
|
$('#edit_action_act').empty();
|
|
$.each(options, function(k, v) {
|
|
$('#edit_action_act').append(
|
|
$('<option></option>').attr('value', k).text(v)
|
|
);
|
|
});
|
|
|
|
var cmd = rule.find('tr.action th.cmd').attr('cmd');
|
|
var arg = rule.find('tr.action td.val').html();
|
|
|
|
if (schema.action[cmd].argtype == 'none')
|
|
{
|
|
arg = '';
|
|
$('#edit_action_arg').disable();
|
|
}
|
|
else
|
|
$('#edit_action_arg').enable();
|
|
|
|
$('.edit_action_help').hide();
|
|
$('#edit_action_help_' + schema.action[cmd].argtype).show();
|
|
|
|
if (schema.action[cmd].argtype == 'folder' && arg == mroot)
|
|
arg = '';
|
|
|
|
$('#edit_action_act').val(cmd);
|
|
$('#edit_action_arg').val(arg);
|
|
|
|
$('#edit_action').dialog({
|
|
height: 'auto', width: 'auto',
|
|
draggable: false, resizable: false,
|
|
autoOpen: true,
|
|
position: {
|
|
my: 'bottom left',
|
|
at: 'top right',
|
|
of: rule,
|
|
collision: 'fit'
|
|
},
|
|
buttons: {
|
|
"Save": function() {
|
|
cmd = $('#edit_action_act').val();
|
|
arg = $('#edit_action_arg').val();
|
|
|
|
rule.find('table.action tbody').empty()
|
|
.append(action({cmd: cmd, arg: arg}));
|
|
$(this).dialog('close');
|
|
rulerefresh(rule);
|
|
changed(1);
|
|
},
|
|
"Close": function() {
|
|
$(this).dialog('close');
|
|
}
|
|
}
|
|
});
|
|
})
|
|
.on('click', 'a.delclause', function(e) {
|
|
e.preventDefault();
|
|
$(this).dojConfirmAction({
|
|
question: 'Delete condition?',
|
|
yesAnswer: 'Yes',
|
|
cancelAnswer: 'No'
|
|
}, function(el) {
|
|
var rule = $(el).closest('div.rule');
|
|
$(el).closest('tr.clause').fadeOut('slow', function() {
|
|
$(this).remove();
|
|
rulerefresh(rule);
|
|
changed(1);
|
|
});
|
|
});
|
|
})
|
|
.on('click', 'a.delrule', function(e) {
|
|
e.preventDefault();
|
|
$(this).dojConfirmAction({
|
|
question: 'Delete entire rule?',
|
|
yesAnswer: 'Yes',
|
|
cancelAnswer: 'No'
|
|
}, function(el) {
|
|
$(el).closest('div.rule')
|
|
.addClass('hl')
|
|
.slideUp('slow', function() {
|
|
$(this).remove();
|
|
changed(1);
|
|
fixupdown();
|
|
if ($('div.rule').length < 1)
|
|
$('#ruleset').attr('empty', true)
|
|
.html($('#empty_rulebase').html());
|
|
});
|
|
});
|
|
})
|
|
.on('click', 'a.delsubclause', function(e) {
|
|
e.preventDefault();
|
|
$(this).dojConfirmAction({
|
|
question: 'Delete sub-condition?',
|
|
yesAnswer: 'Yes',
|
|
cancelAnswer: 'No'
|
|
}, function(el) {
|
|
var rule = $(el).closest('div.rule');
|
|
$(el).closest('tr.compositeclause')
|
|
.fadeOut('slow', function() {
|
|
$(this).remove();
|
|
rulerefresh(rule);
|
|
changed(1);
|
|
});
|
|
});
|
|
})
|
|
.on('click', 'a.addsubcriterion', function(e) {
|
|
e.preventDefault();
|
|
var rule = $(this).closest('div.rule');
|
|
var clause = $(this).closest('table.compositeclause');
|
|
addcriterion(rule, clause);
|
|
})
|
|
.on('dblclick', 'div.raw', function(e) {
|
|
e.preventDefault();
|
|
$(this).toggleClass("rawvis");
|
|
});
|
|
|
|
$('#edit_action_act').on('change', function(e) {
|
|
var cmd = $(this).val();
|
|
if (schema.action[cmd].argtype == 'none')
|
|
$('#edit_action_arg').disable();
|
|
else
|
|
$('#edit_action_arg').enable();
|
|
$('.edit_action_help').hide();
|
|
$('#edit_action_help_' + schema.action[cmd].argtype).show();
|
|
});
|
|
|
|
$('#newcondition_cmd').on('change', function(e) {
|
|
var cmd = $(this).val();
|
|
if (schema.criterion[cmd].negate)
|
|
$('#newcondition_negate').enable();
|
|
else
|
|
$('#newcondition_negate')
|
|
.prop('checked', false)
|
|
.disable();
|
|
});
|
|
|
|
// Set up macros
|
|
$.each(macros, function(key, val) {
|
|
$('#macroselect').append(
|
|
$('<option></option>').attr('value', key).text(val.desc)
|
|
);
|
|
});
|
|
|
|
$('#macroselect').on('change', function(el) {
|
|
if ($(this).val() == "0")
|
|
$('#b_macro').button('disable');
|
|
else
|
|
$('#b_macro').button('enable');
|
|
});
|
|
|
|
loadrules($('span.dir').text());
|
|
|
|
$(document).tooltip();
|
|
});
|
|
|