checkpoint sweeper GUI

This commit is contained in:
hummypkg 2014-06-03 17:23:03 +00:00
parent 047bdc208f
commit 1b6785375e
9 changed files with 833 additions and 82 deletions

View File

@ -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]} {

14
webif/plugin/sweeper/config.jim Executable file
View File

@ -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;
}

View File

@ -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='&gt;'>&gt;</option>
<option value='&lt;'>&lt;</option>
<option value='&gt;='>&gt;=</option>
<option value='&lt;='>&lt;=</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>
}

View File

@ -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"

37
webif/plugin/sweeper/save.jim Executable file
View File

@ -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."
}

View File

@ -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;
}
});

View File

@ -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>' +
'&nbsp;' +
'<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);
});

View File

@ -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;
}

View File

@ -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