checkpoint sweeper GUI
This commit is contained in:
parent
047bdc208f
commit
1b6785375e
|
@ -339,12 +339,14 @@ proc ::sweeper::apply {dir cf} {
|
|||
if {[lindex $rule 0] eq "folder"} { incr runfolder }
|
||||
}
|
||||
|
||||
log "Sweep scan starting for $dir" 2
|
||||
log "" 2
|
||||
log "--- SWEEP SCAN STARTING FOR $dir ---" 2
|
||||
log "" 2
|
||||
|
||||
foreach e [readdir -nocomplain $dir] {
|
||||
set entry "$dir/$e"
|
||||
if {[file isdirectory $entry]} continue
|
||||
#if {![string match {*.ts} $entry]} continue
|
||||
if {![string match {*.ts} $entry]} continue
|
||||
|
||||
log "+ Sweeper processing $entry" 2
|
||||
|
||||
|
@ -440,8 +442,14 @@ proc ::sweeper::apply {dir cf} {
|
|||
}
|
||||
}
|
||||
|
||||
proc ::sweeper::sweep {dir} {
|
||||
if {$dir eq $::root} return
|
||||
::sweeper::apply $dir "$dir/.sweeper"
|
||||
}
|
||||
|
||||
proc ::sweeper::scan {args} {
|
||||
::sweeper::apply $::root $::sweeper::cf
|
||||
scan_run $::root sweeper ::sweeper::sweep
|
||||
}
|
||||
|
||||
if {[file exists $::sweeper::cf]} {
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
#!/mod/bin/jimsh
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require system.class
|
||||
|
||||
httpheader "text/javascript"
|
||||
|
||||
puts {
|
||||
|
||||
var showraw = true;
|
||||
|
||||
}
|
||||
|
|
@ -6,43 +6,111 @@ require system.class
|
|||
|
||||
set dir [cgi_get dir ""]
|
||||
|
||||
if {$dir eq ""} {
|
||||
set dir [system mediaroot]
|
||||
set cf "/mod/etc/sweeper.conf"
|
||||
} else {
|
||||
set cf "[system mediaroot]/$dir/.rulelist"
|
||||
}
|
||||
if {$dir eq ""} { set dir [system mediaroot] }
|
||||
|
||||
jscss {schema.js script.js} style.css
|
||||
jscss {schema.js config.jim script.js} style.css
|
||||
jqplugin confirmAction enadis
|
||||
header
|
||||
|
||||
puts "
|
||||
<h3>
|
||||
<img src=img/icon22.png> Sweeper rules for
|
||||
<span class=dir>$dir</span>
|
||||
<span id=pendingnote class=\"blood hidden\">
|
||||
(changes pending, not yet saved.)
|
||||
</span>
|
||||
</h3>
|
||||
<div id=ruleset> </div>
|
||||
<div id=ruleset></div>
|
||||
<div id=buttons>
|
||||
<button id=b_add>Add rule</button>
|
||||
<button id=b_save>Save changes</button>
|
||||
<button id=b_revert>Discard changes</button>
|
||||
<button id=b_show>View configuration</button>
|
||||
<button id=b_raw>Toggle raw display</button>
|
||||
</div>
|
||||
<div id=output></div>
|
||||
"
|
||||
|
||||
puts {
|
||||
<div id=rule_template class="rule hidden">
|
||||
<fieldset class=rule>
|
||||
<legend class=comment>
|
||||
<span class=comment>Unnamed rule</span>
|
||||
<img class=edit src=/img/context/edit.png>
|
||||
</legend>
|
||||
<div class=criteria>
|
||||
<table class="criteria keyval"><tbody>
|
||||
<tr><th colspan=3 class=title>If all of:</th></tr>
|
||||
</tbody></table>
|
||||
<div id=rule_template class="hidden">
|
||||
<fieldset class=rule>
|
||||
<legend class=comment>
|
||||
<span class=commentleft>
|
||||
<span class="ruleicon folder hidden">
|
||||
<img src=/images/711_1_09_Media_Folder.png>
|
||||
</span>
|
||||
<span class="ruleicon file hidden">
|
||||
<img src=/img/Video_TS_New.png>
|
||||
</span>
|
||||
<span class=comment>Unnamed rule</span>
|
||||
<a class=editcomment href=#>
|
||||
<img src=/img/context/edit.png>
|
||||
</a>
|
||||
</span>
|
||||
<span class=legendright>
|
||||
<a class=delrule href=#>
|
||||
<img src=/img/context/delete.png>
|
||||
</a>
|
||||
<a class=uprule href=#>
|
||||
<img src=/img/nav/up.png>
|
||||
</a>
|
||||
<a class=downrule href=#>
|
||||
<img src=/img/nav/down.png>
|
||||
</a>
|
||||
</span>
|
||||
</legend>
|
||||
<div class=criteria>
|
||||
<table class="criteria keyval"><tbody>
|
||||
</tbody></table>
|
||||
</div>
|
||||
<div class=action>
|
||||
<table class="action keyval"><tbody>
|
||||
</tbody></table>
|
||||
<button class=addcriterion>Add Criterion</button>
|
||||
</div>
|
||||
<div class=raw></div>
|
||||
</fieldset>
|
||||
</div>
|
||||
<div class=action>
|
||||
<table class="action keyval"><tbody>
|
||||
<tr><th colspan=2 class=title>Then:</th></tr>
|
||||
</tbody></table>
|
||||
|
||||
<div class=hidden id=edit_text title="Edit text">
|
||||
<input name=edit_text_field id=edit_text_field size=80 maxlength=255 />
|
||||
</div>
|
||||
<div class="raw cleft"></div>
|
||||
</fieldset>
|
||||
|
||||
<div class=hidden id=edit_int title="Edit int">
|
||||
<select name=edit_int_op id=edit_int_op>
|
||||
<option value='='>=</option>
|
||||
<option value='>'>></option>
|
||||
<option value='<'><</option>
|
||||
<option value='>='>>=</option>
|
||||
<option value='<='><=</option>
|
||||
</select>
|
||||
<input name=edit_int_field id=edit_int_field type=number
|
||||
size=5 maxlength=6 />
|
||||
</div>
|
||||
|
||||
<div class=hidden id=edit_select title="Edit select">
|
||||
<select name=edit_select_field id=edit_select_field>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class=hidden id=showconf title="Generated Configuration File">
|
||||
</div>
|
||||
|
||||
<div class=hidden id=newrule title="Add New Rule">
|
||||
Rule Type:
|
||||
<input name=newrule_type id=newrule_type_file type=radio
|
||||
value='file' checked/>File
|
||||
<input name=newrule_type id=newrule_type_folder type=radio
|
||||
value='folder' />Folder
|
||||
<br>
|
||||
Description:
|
||||
<input name=newrule_comment id=newrule_comment size=80 maxlength=255 />
|
||||
</div>
|
||||
|
||||
<div class=hidden id=edit_action title="Rule Action">
|
||||
<select name=edit_action_act id=edit_action_act>
|
||||
</select>
|
||||
<input name=edit_action_arg id=edit_action_arg size=60 maxlength=255 />
|
||||
</div>
|
||||
}
|
||||
|
||||
|
|
|
@ -12,7 +12,7 @@ if {$dir eq "" || $dir eq $root} {
|
|||
set dir $root
|
||||
set cf "/mod/etc/sweeper.conf"
|
||||
} else {
|
||||
set cf "[system mediaroot]/$dir/.sweeper"
|
||||
set cf "$dir/.sweeper"
|
||||
}
|
||||
|
||||
httpheader "application/json"
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
#!/mod/bin/jimsh
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require system.class
|
||||
|
||||
httpheader
|
||||
|
||||
set dir [cgi_get dir ""]
|
||||
set root [system mediaroot]
|
||||
|
||||
if {$dir eq "" || $dir eq $root} {
|
||||
set cf "/mod/etc/sweeper.conf"
|
||||
} else {
|
||||
set cf "$dir/.sweeper"
|
||||
}
|
||||
|
||||
if {![string match "$root/*" $cf]} {
|
||||
puts "Bad directory, $dir"
|
||||
exit
|
||||
}
|
||||
set data [cgi_get data "-"]
|
||||
|
||||
if {$data eq "-"} {
|
||||
if {[file exists $cf]} { file delete $cf }
|
||||
puts "Configuration file $cf deleted."
|
||||
exit
|
||||
}
|
||||
|
||||
if {[catch {set fp [open $cf w]} msg]} {
|
||||
puts "Error, $msg"
|
||||
} else {
|
||||
$fp puts -nonewline $data
|
||||
close $fp
|
||||
puts "Configuration file $cf saved."
|
||||
}
|
||||
|
|
@ -2,47 +2,57 @@ var schema = {
|
|||
criterion: {
|
||||
lcn: {
|
||||
type: 'int',
|
||||
desc: 'Channel Number'
|
||||
desc: 'Logical Channel Number',
|
||||
def: "0"
|
||||
},
|
||||
duration: {
|
||||
type: 'int',
|
||||
desc: 'Recording duration (in minutes)'
|
||||
desc: 'Recording duration (in minutes)',
|
||||
def: "0"
|
||||
},
|
||||
schedduration: {
|
||||
type: 'int',
|
||||
desc: 'Scheduled duration (in minutes)'
|
||||
desc: 'Scheduled duration (in minutes)',
|
||||
def: "0"
|
||||
},
|
||||
size: {
|
||||
type: 'int',
|
||||
desc: 'Recording size (in bytes)'
|
||||
desc: 'Recording size (in bytes)',
|
||||
def: "0"
|
||||
},
|
||||
hour: {
|
||||
type: 'int',
|
||||
desc: 'Hour in which the recording started'
|
||||
desc: 'Hour in which the recording started',
|
||||
def: "0"
|
||||
},
|
||||
age: {
|
||||
type: 'int',
|
||||
desc: 'Age (in hours)'
|
||||
desc: 'Age (in hours)',
|
||||
def: "0"
|
||||
},
|
||||
wage: {
|
||||
type: 'int',
|
||||
desc: 'Time since last watched, or recorded (in hours)'
|
||||
desc: 'Time since last watched, or recorded (in hours)',
|
||||
def: "0"
|
||||
},
|
||||
title: {
|
||||
type: 'substr',
|
||||
desc: 'Part of the recording title'
|
||||
desc: 'Recording Title contains',
|
||||
def: 'Enter text here...'
|
||||
},
|
||||
synopsis: {
|
||||
type: 'substr',
|
||||
desc: 'Part of the synopsis'
|
||||
desc: 'Synopsis contains',
|
||||
def: 'Enter text here...'
|
||||
},
|
||||
guidance: {
|
||||
type: 'substr',
|
||||
desc: 'Part of the guidance text'
|
||||
desc: 'Guidance Text contains',
|
||||
def: 'Enter text here...'
|
||||
},
|
||||
genre: {
|
||||
type: 'select',
|
||||
desc: 'Recording genre',
|
||||
desc: 'Recording Genre',
|
||||
select: {
|
||||
Unclassified: 'Unclassified',
|
||||
Film: 'Film',
|
||||
|
@ -53,19 +63,21 @@ var schema = {
|
|||
Education: 'Education',
|
||||
Lifestyle: 'Lifestyle',
|
||||
Drama: 'Drama'
|
||||
}
|
||||
},
|
||||
def: 'Unclassified'
|
||||
},
|
||||
definition: {
|
||||
type: 'select',
|
||||
desc: 'Recording definition',
|
||||
desc: 'Recording Definition',
|
||||
select: {
|
||||
SD: 'Standard Definition',
|
||||
HD: 'High Definition'
|
||||
}
|
||||
},
|
||||
def: 'SD'
|
||||
},
|
||||
flag: {
|
||||
type: 'select',
|
||||
desc: 'Recording flag',
|
||||
desc: 'Recording Flagged as',
|
||||
select: {
|
||||
Locked: 'Locked',
|
||||
New: 'New',
|
||||
|
@ -74,49 +86,74 @@ var schema = {
|
|||
ODEncrypted: 'Encrypted On-Disk',
|
||||
Shrunk: 'Shrunk',
|
||||
Deduped: 'De-duplicated'
|
||||
}
|
||||
},
|
||||
def: 'New'
|
||||
},
|
||||
lock: {
|
||||
type: 'select',
|
||||
desc: 'Change recording lock',
|
||||
desc: 'Change Recording Lock',
|
||||
select: {
|
||||
1: 'Lock Recording',
|
||||
0: 'Unlock Recording'
|
||||
}
|
||||
},
|
||||
def: 1
|
||||
}
|
||||
},
|
||||
action: {
|
||||
continue: {
|
||||
class: 'all',
|
||||
'continue': {
|
||||
'class': 'all',
|
||||
argtype: 'none',
|
||||
desc: 'Continue to next rule'
|
||||
},
|
||||
stop: {
|
||||
class: 'all',
|
||||
'class': 'all',
|
||||
argtype: 'none',
|
||||
desc: 'Do nothing and stop processing rules'
|
||||
},
|
||||
move: {
|
||||
class: 'all',
|
||||
'class': 'all',
|
||||
argtype: 'folder',
|
||||
desc: 'Move recording to folder...'
|
||||
},
|
||||
movecreate: {
|
||||
class: 'all',
|
||||
'class': 'all',
|
||||
argtype: 'folder',
|
||||
desc: 'Move recording to folder (create folder if necessary)'
|
||||
desc: 'Move recording to folder (creating if necessary)'
|
||||
},
|
||||
fileunder: {
|
||||
class: 'folder',
|
||||
'class': 'folder',
|
||||
argtype: 'folder',
|
||||
desc: 'Scan for folder of same name and merge'
|
||||
desc: 'Merge into first folder of same name found under...'
|
||||
},
|
||||
fileundercreate: {
|
||||
class: 'folder',
|
||||
'class': 'folder',
|
||||
argtype: 'folder',
|
||||
desc: 'Scan for folder of same name and merge ' +
|
||||
'(create folder if necessary)'
|
||||
desc: 'Merge into or create folder of ' +
|
||||
'same name found under...'
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var select_criteria = {};
|
||||
$.each(schema.criterion, function(k, v) {
|
||||
select_criteria[k] = v.desc;
|
||||
});
|
||||
|
||||
var select_file_actions = {};
|
||||
var select_folder_actions = {};
|
||||
$.each(schema.action, function(k, v) {
|
||||
switch (v['class'])
|
||||
{
|
||||
case 'file':
|
||||
select_file_actions[k] = v.desc;
|
||||
break;
|
||||
case 'folder':
|
||||
select_folder_actions[k] = v.desc;
|
||||
break;
|
||||
case 'all':
|
||||
select_file_actions[k] = v.desc;
|
||||
select_folder_actions[k] = v.desc;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
|
|
|
@ -1,5 +1,226 @@
|
|||
|
||||
var printers = {
|
||||
function quot(str)
|
||||
{
|
||||
if (!str)
|
||||
return '""';
|
||||
|
||||
if (str.indexOf(" ") == -1)
|
||||
return str;
|
||||
return '{' + str + '}';
|
||||
}
|
||||
|
||||
function updateupdown()
|
||||
{
|
||||
$('#ruleset a.uprule').enable().filter(':first').disable();
|
||||
$('#ruleset a.downrule').enable().filter(':last').disable();
|
||||
}
|
||||
|
||||
function update_buttons(changed)
|
||||
{
|
||||
if (changed)
|
||||
{
|
||||
$('#b_save,#b_revert').enable();
|
||||
$('#pendingnote').show();
|
||||
$('#b_save')
|
||||
.jConfirmAction({
|
||||
question: 'Save changes?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
$('.jcaquestion').fadeOut(300);
|
||||
$.post('save.jim', {
|
||||
dir: $('span.dir').text(),
|
||||
data: conffile()
|
||||
}, function(data) {
|
||||
$('#output').html(data)
|
||||
.delay(5000).fadeOut('slow');
|
||||
update_buttons(0);
|
||||
});
|
||||
});
|
||||
$('#b_revert')
|
||||
.jConfirmAction({
|
||||
question: 'Discard changes?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
$('.jcaquestion').fadeOut(300);
|
||||
loadrules($('span.dir').text());
|
||||
update_buttons(0);
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#b_save,#b_revert').disable();
|
||||
$('#pendingnote').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function update_rulehooks(obj)
|
||||
{
|
||||
if (!obj)
|
||||
obj = $('#ruleset');
|
||||
|
||||
obj.find('a.delclause').jConfirmAction({
|
||||
question: 'Delete criterion?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
$('.jcaquestion').fadeOut(300);
|
||||
var rule = $(el).closest('div.rule');
|
||||
$(el).closest('tr.clause').fadeOut('slow', function() {
|
||||
$(this).remove();
|
||||
rawrefresh(rule);
|
||||
update_buttons(1);
|
||||
});
|
||||
});
|
||||
|
||||
obj.find('a.editclause').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
edit_clause($(this).closest('tr.clause'));
|
||||
});
|
||||
|
||||
obj.find('button.addcriterion')
|
||||
.button({icons: { primary: "ui-icon-plus"}})
|
||||
.on('click', function(e) {
|
||||
e.preventDefault();
|
||||
var rule = $(this).closest('div.rule');
|
||||
edit_select(rule, 'Select new criterion',
|
||||
select_criteria, '', function(rule, val) {
|
||||
var id = rule.attr('id');
|
||||
rule.find('table.criteria tbody')
|
||||
.append(criterion({
|
||||
cmd: val,
|
||||
arg: schema.criterion[val].def
|
||||
}));
|
||||
update_rulehooks(rule);
|
||||
update_buttons(1);
|
||||
});
|
||||
});
|
||||
|
||||
obj.find('a.delrule').jConfirmAction({
|
||||
question: 'Delete entire rule?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
$('.jcaquestion').fadeOut(300);
|
||||
$(el).closest('div.rule').slideUp('slow', function() {
|
||||
$(this).remove();
|
||||
update_buttons(1);
|
||||
updateupdown();
|
||||
if ($('div.rule').length < 1)
|
||||
$('#ruleset').attr('empty', true)
|
||||
.html('<i>No rules defined for this ' +
|
||||
'folder.</i>');
|
||||
});
|
||||
});
|
||||
|
||||
obj.find('a.editcomment').on('click', function(e) {
|
||||
e.preventDefault();
|
||||
edit_text($(this), 'Edit rule name',
|
||||
$(this).siblings('span.comment').text(),
|
||||
function(obj, text) {
|
||||
$(obj).siblings('span.comment').text(text);
|
||||
update_buttons(1);
|
||||
});
|
||||
});
|
||||
|
||||
obj.find('a.uprule').on('click', 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');
|
||||
updateupdown();
|
||||
update_buttons(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
obj.find('a.downrule').on('click', 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');
|
||||
updateupdown();
|
||||
update_buttons(1);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
obj.find('a.editaction').on('click', 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').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 == 'Media Root')
|
||||
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('tr.action').replaceWith(
|
||||
action({cmd: cmd, arg: arg}));
|
||||
$(this).dialog('close');
|
||||
rawrefresh(rule);
|
||||
update_rulehooks(rule);
|
||||
update_buttons(1);
|
||||
},
|
||||
"Close": function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
var setters = {
|
||||
int: function(cmd, a) {
|
||||
var b = a.split(" ");
|
||||
if (b.length == 1)
|
||||
|
@ -22,22 +243,91 @@ var printers = {
|
|||
}
|
||||
};
|
||||
|
||||
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;
|
||||
},
|
||||
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).attr('type') == 'folder')
|
||||
s += 'folder ';
|
||||
|
||||
$(rule).find('tr.clause').each(function(i) {
|
||||
cmd = $(this).find('th').attr('cmd');
|
||||
c = schema.criterion[cmd];
|
||||
val = $.trim($(this).find('td').text());
|
||||
if (getters[c.type])
|
||||
val = getters[c.type](cmd, val);
|
||||
|
||||
s += cmd + ' ' + quot(val) + ' ';
|
||||
});
|
||||
|
||||
act = $(rule).find('tr.action th').attr('cmd');
|
||||
arg = $.trim($(rule).find('tr.action td').text());
|
||||
if (schema.action[act].argtype == 'folder' && arg == 'Media Root')
|
||||
arg = '';
|
||||
if (act != 'continue')
|
||||
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 rawrefresh(rule)
|
||||
{
|
||||
$(rule).find('.raw').html(ruleconf(rule));
|
||||
}
|
||||
|
||||
function criterion(data)
|
||||
{
|
||||
var c = schema.criterion[data.cmd];
|
||||
var s;
|
||||
|
||||
s = '<tr><th>' + c.desc + '</th><td>';
|
||||
s = '<tr class=clause>' +
|
||||
'<th cmd=' + data.cmd + '>' + c.desc + '</th><td class=val>';
|
||||
|
||||
if (printers[c.type])
|
||||
s += printers[c.type](data.cmd, data.arg);
|
||||
if (setters[c.type])
|
||||
s += setters[c.type](data.cmd, data.arg);
|
||||
else
|
||||
s += 'RAW (' + data.arg + ')';
|
||||
s += 'UNKNOWN (' + data.arg + ')';
|
||||
|
||||
s += '</td><td>' +
|
||||
'<img class=edit src=/img/context/edit.png>' +
|
||||
'<a class=editclause href=#>' +
|
||||
'<img src=/img/context/edit.png></a>' +
|
||||
' ' +
|
||||
'<img class=delete src=/img/context/delete.png>' +
|
||||
'<a class=delclause href=#>' +
|
||||
'<img src=/img/context/delete.png></a>' +
|
||||
'</td></tr>';
|
||||
return s;
|
||||
}
|
||||
|
@ -47,53 +337,288 @@ function action(data)
|
|||
var c = schema.action[data.cmd];
|
||||
var s;
|
||||
|
||||
s = '<tr>' +
|
||||
'<th>' + c.desc + '</th>' +
|
||||
'<td>' + data.arg + '</td>' +
|
||||
if (c.argtype == 'folder' && !data.arg)
|
||||
data.arg = 'Media Root';
|
||||
|
||||
s = '<tr class=action>' +
|
||||
'<th 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>';
|
||||
|
||||
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').text(data.name);
|
||||
|
||||
// Only Firefox seems to have problems with top-right button
|
||||
// placement.
|
||||
if (navigator.userAgent.indexOf("Firefox") != -1)
|
||||
rule.find('span.legendright').css('top', '-20px');
|
||||
|
||||
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) {
|
||||
$($c).find('tbody').append(criterion(val));
|
||||
});
|
||||
|
||||
var $a = rule.find('table.action');
|
||||
$($a).find('tbody').append(action(data.action));
|
||||
rule.find('table.action tbody').append(action(data.action));
|
||||
|
||||
rule.find('.raw').html(data.raw);
|
||||
|
||||
// rule.find('.raw').append('<pre>' + JSON.stringify(data) + '</pre>');
|
||||
|
||||
$('#ruleset').append(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');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
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').attr('cmd');
|
||||
var target = $(obj).find('td.val');
|
||||
var val = $.trim($(target).text());
|
||||
var title = $(obj).find('th').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);
|
||||
rawrefresh($(obj).closest('div.rule'));
|
||||
update_buttons(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);
|
||||
rawrefresh($(obj).closest('div.rule'));
|
||||
update_buttons(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));
|
||||
rawrefresh($(obj).closest('div.rule'));
|
||||
update_buttons(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();
|
||||
$.each(data, function(key, val) {
|
||||
addrule(key, val);
|
||||
});
|
||||
$('#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('<i>No rules defined for this folder.</i>');
|
||||
return;
|
||||
}
|
||||
$.each(data, function(key, val) {
|
||||
addrule(key, val);
|
||||
});
|
||||
updateupdown();
|
||||
if (!showraw)
|
||||
$('#ruleset div.raw').hide();
|
||||
|
||||
update_rulehooks();
|
||||
});
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
||||
loadrules($('span.dir').text());
|
||||
|
||||
$('#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: ''
|
||||
}
|
||||
});
|
||||
update_rulehooks(rule);
|
||||
update_buttons(1);
|
||||
$(this).dialog('close');
|
||||
},
|
||||
"Close": function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
$('#newrule_type_file').prop('checked', true);
|
||||
$('#newrule_comment').focus().val('').val('Unnamed rule');
|
||||
});
|
||||
$('#b_save').button({icons: {primary: "ui-icon-disk"}});
|
||||
$('#b_revert').button({icons: {primary: "ui-icon-arrowrefresh-1-w"}});
|
||||
$('#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) {
|
||||
$('div.raw').toggle('slow');
|
||||
});
|
||||
update_buttons(0);
|
||||
|
||||
});
|
||||
|
||||
|
|
|
@ -1,7 +1,23 @@
|
|||
|
||||
fieldset
|
||||
span.ruleicon img
|
||||
{
|
||||
width: 95%;
|
||||
height: 21px;
|
||||
}
|
||||
|
||||
img
|
||||
{
|
||||
border: 0;
|
||||
}
|
||||
|
||||
#pendingnote
|
||||
{
|
||||
font-style: italic;
|
||||
font-size: 80%;
|
||||
}
|
||||
|
||||
.hl, .hl th, .hl td
|
||||
{
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
div.action
|
||||
|
@ -18,9 +34,17 @@ div.criteria
|
|||
|
||||
div.raw
|
||||
{
|
||||
position: absolute;
|
||||
font-style: italic;
|
||||
color: #ff4000;
|
||||
background: transparent;
|
||||
bottom: 5px;
|
||||
right: 5px;
|
||||
}
|
||||
|
||||
div#buttons
|
||||
{
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
th.title
|
||||
|
@ -30,9 +54,25 @@ th.title
|
|||
background: #eee !important;
|
||||
}
|
||||
|
||||
div.comment
|
||||
fieldset
|
||||
{
|
||||
width: 95%;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
span.comment
|
||||
{
|
||||
font-style: italic;
|
||||
color: blue;
|
||||
}
|
||||
|
||||
span.legendright
|
||||
{
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 5px;
|
||||
background-color: #f8f8f8;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.padleft
|
||||
|
@ -40,3 +80,9 @@ div.comment
|
|||
padding-left: 3em;
|
||||
}
|
||||
|
||||
#output
|
||||
{
|
||||
color: #ff4000;
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
|
|
|
@ -26,9 +26,25 @@ proc endclock {size} {
|
|||
|
||||
proc register {args} {}
|
||||
|
||||
proc scan_run {dir flag callback} {
|
||||
global dustbin
|
||||
|
||||
if {[string match {\[*} [file tail $dir]]} return
|
||||
|
||||
if {[file exists "$dir/.$flag"]} { $callback $dir }
|
||||
|
||||
foreach entry [readdir -nocomplain $dir] {
|
||||
if {[file isdirectory "$dir/$entry"]} {
|
||||
scan_run "$dir/$entry" $flag $callback
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set root [system mediaroot]
|
||||
|
||||
source auto.hook
|
||||
|
||||
::sweeper::scan 0
|
||||
#::sweeper::apply $::root $::sweeper::cf
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue