sweeper/webif/plugin/sweeper/script.js

759 lines
17 KiB
JavaScript

var mroot = '(Media Root)';
function quot(str)
{
if (!str)
return '""';
if (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;
}
var setters = {
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];
}
};
var getters = {
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 'UNKNOWN (' + a + ')';
}
};
function ruleconf(rule)
{
var s = '';
if (rule.hasClass('ruledisabled'))
s += '## ';
if (rule.attr('type') == 'folder')
s += 'folder ';
rule.find('tr.clause').each(function(i) {
cmd = $(this).find('th.cmd').attr('cmd');
c = schema.criterion[cmd];
val = $.trim($(this).find('td.val').text());
if (getters[c.type])
val = getters[c.type](cmd, val);
s += cmd + ' ' + quot(val) + ' ';
});
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').text('And:').first().text('If:');
if (rule.find('tr.clause').length < 1)
{
rule.find('tr.action th.title').text('Always:');
rule.find('tr.otherwise').hide();
rule.find('div.criteria,div.arrow').hide();
}
else
{
rule.find('tr.action th.title').text('Then:');
rule.find('tr.otherwise').show();
rule.find('div.criteria,div.arrow').show();
}
}
function criterion(data)
{
var c = schema.criterion[data.cmd];
var s;
s = '<tr class=clause><th class=title>And:</th>' +
'<th class=cmd cmd=' + data.cmd + '>' +
c.desc + '</th><td class=val>';
if (setters[c.type])
s += setters[c.type](data.cmd, data.arg);
else
s += 'UNKNOWN (' + data.arg + ')';
s += '</td><td>' +
'<a class=editclause href=#>' +
'<img src=/img/context/edit.png></a>' +
'&nbsp;' +
'<a class=delclause href=#>' +
'<img src=/img/context/delete.png></a>' +
'</td></tr>';
return s;
}
function action(data)
{
var c = schema.action[data.cmd];
var s;
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/context/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>&nbsp;</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');
rule.find('span.comment').html(data.name);
if (data.type == 'folder')
rule.find('.commentleft > span.folder').show();
else
rule.find('.commentleft > span.file').show();
rule.attr('type', data.type);
var $c = rule.find('table.criteria');
$.each(data.criteria, function(key, val) {
if (val.cmd == 'lock' && (
data.action.cmd == 'lock' || data.action.cmd == 'unlock'))
return;
$c.find('tbody').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);
// rule.find('button.addcriterion')
// .button({icons: { primary: "ui-icon-plus"}});
rulerefresh(rule);
return rule;
}
function edit_text(obj, title, text, callback)
{
$('#edit_text_field').val(text);
$('#edit_text').dialog({
title: title,
height: 'auto', width: 'auto',
draggable: false, resizable: false,
autoOpen: true,
position: {
my: 'bottom left',
at: 'top right',
of: obj
},
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');
}
}
});
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: false, resizable: false,
autoOpen: true,
position: {
my: 'bottom left',
at: 'top right',
of: obj
},
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_select(obj, title, options, val, callback)
{
$('#edit_select_field').empty();
$.each(options, function(k, v) {
$('#edit_select_field').append(
$('<option></option>').attr('value', k).text(v)
);
});
if (val && val != '')
$('#edit_select_field').val(val);
$('#edit_select').dialog({
title: title,
height: 'auto', width: 'auto',
draggable: false, resizable: false,
autoOpen: true,
position: {
my: 'bottom left',
at: 'top right',
of: obj
},
buttons: {
"Save": function() {
callback(obj, $('#edit_select_field').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 val = $.trim($(target).text());
var title = $(obj).find('th.cmd').html();
if (!schema.criterion[cmd])
{
alert('Unhandled command (' + cmd + ')');
return;
}
switch (schema.criterion[cmd].type)
{
case 'substr':
edit_text(target, title, val, function(obj, text) {
$(obj).text(text);
rulerefresh($(obj).closest('div.rule'));
changed(1);
});
break;
case 'int':
b = val.split(" ");
if (b.length != 2)
{
alert('Bad int value');
break;
}
edit_int(target, title, b[0], b[1], function(obj, op, val) {
$(obj).text(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).text(setters.select(cmd, val));
rulerefresh($(obj).closest('div.rule'));
changed(1);
});
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: false, resizable: false,
autoOpen: true,
position: {
my: 'bottom left',
at: 'top right',
of: $(this)
},
buttons: {
"Create Rule": function() {
rule = addrule(last_ruleid + 1, {
raw: '',
name: $('#newrule_comment').val(),
type: $('input[name=newrule_type]' +
':checked').val(),
criteria: [],
action: {
cmd: 'continue',
arg: ''
}
});
changed(1);
$(this).dialog('close');
},
"Close": function() {
$(this).dialog('close');
}
}
});
$('#newrule_type_file').prop('checked', true);
$('#newrule_comment').focus().val('').val('Unnamed rule').select();
});
$('#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').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_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);
$('#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');
var type = rule.attr('type');
if (type == 'folder')
options = select_folder_criteria;
else
options = select_file_criteria;
edit_select(rule, 'Add new condition',
options, '', function(rule, val) {
var id = rule.attr('id');
rule.find('table.criteria tbody')
.append(criterion({
cmd: val,
arg: schema.criterion[val].def
}));
changed(1);
rulerefresh(rule);
});
})
.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.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');
if (type == 'folder')
options = select_folder_actions;
else
options = select_file_actions;
$('#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 = '';
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
},
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());
});
});
});
// 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());
});