1.0.14
This commit is contained in:
parent
3f6259fa09
commit
f44e2f20fc
@ -1,9 +1,9 @@
|
||||
Package: sweeper
|
||||
Priority: optional
|
||||
Section: misc
|
||||
Version: 1.0.13
|
||||
Version: 1.0.14
|
||||
Architecture: mipsel
|
||||
Maintainer: af123@hummypkg.org.uk
|
||||
Depends: webif(>=1.0.14-2)
|
||||
Depends: webif(>=1.0.14-3)
|
||||
Description: Automatically manage single recording files. [Web Interface. Multi-folder support.]
|
||||
Tags: http://hummy.tv/forum/threads/3843/
|
||||
|
@ -57,7 +57,7 @@ proc ::sweeper::strcontains {ref val} {
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Rule clauses
|
||||
# Rule criteria
|
||||
|
||||
proc ::sweeper::flag {ts flag} {
|
||||
return [$ts flag $flag]
|
||||
@ -124,15 +124,23 @@ proc ::sweeper::genre {ts genre} {
|
||||
|
||||
proc ::sweeper::lock {ts g} {
|
||||
if {$g} {
|
||||
log "Locked recording." 0
|
||||
$ts lock
|
||||
if {![$ts flag Locked]} {
|
||||
log "Locked recording." 0
|
||||
$ts lock
|
||||
}
|
||||
} else {
|
||||
log "Unlocked recording." 0
|
||||
$ts unlock
|
||||
if {[$ts flag Locked]} {
|
||||
log "Unlocked recording." 0
|
||||
$ts unlock
|
||||
}
|
||||
}
|
||||
return 1
|
||||
}
|
||||
|
||||
proc ::sweeper::folder_fflag {ts flag} {
|
||||
return [file exists "[file dirname [$ts get file]]/.$flag"]
|
||||
}
|
||||
|
||||
######################################################################
|
||||
|
||||
proc ::sweeper::action {ts cmds} {
|
||||
@ -172,6 +180,20 @@ proc ::sweeper::action {ts cmds} {
|
||||
}
|
||||
return 1
|
||||
}
|
||||
lock {
|
||||
if {![$ts flag Locked]} {
|
||||
log "Locked [$ts get file]" 0
|
||||
$ts lock
|
||||
}
|
||||
return 0
|
||||
}
|
||||
unlock {
|
||||
if {[$ts flag Locked]} {
|
||||
log "Unlocked [$ts get file]" 0
|
||||
$ts unlock
|
||||
}
|
||||
return 0
|
||||
}
|
||||
default {
|
||||
log "Unknown action '$cmd'" 0
|
||||
}
|
||||
@ -195,6 +217,32 @@ proc ::sweeper::find {root target orig} {
|
||||
return ""
|
||||
}
|
||||
|
||||
proc ::sweeper::folder_apply {dir callback} {
|
||||
log "Applying action to recordings in $dir" 2
|
||||
foreach e [readdir -nocomplain $dir] {
|
||||
if {![string match {*.ts} $e]} continue
|
||||
set entry "$dir/$e"
|
||||
|
||||
log "+ folder_apply processing $entry" 2
|
||||
|
||||
if {[catch {set ts [ts fetch $entry]} msg} {
|
||||
log "Error reading TS file, $msg" 0
|
||||
continue
|
||||
}
|
||||
|
||||
if {$ts == "0"} {
|
||||
log "Invalid TS file." 2
|
||||
continue
|
||||
}
|
||||
|
||||
if {[$ts inuse]} {
|
||||
log "Recording in use." 2
|
||||
continue
|
||||
}
|
||||
$callback $ts
|
||||
}
|
||||
}
|
||||
|
||||
proc ::sweeper:folder_merge {src dst} {
|
||||
if {$src eq $dst} return
|
||||
log "Moving recordings from $src to $dst" 0
|
||||
@ -287,6 +335,24 @@ proc ::sweeper::folder_action {ts cmds} {
|
||||
::sweeper:folder_merge $folder $target
|
||||
return 1
|
||||
}
|
||||
lock {
|
||||
::sweeper::folder_apply $folder [lambda {ts} {
|
||||
if {![$ts flag Locked]} {
|
||||
log "Locked [$ts get file]" 0
|
||||
$ts lock
|
||||
}
|
||||
}]
|
||||
return 0
|
||||
}
|
||||
unlock {
|
||||
::sweeper::folder_apply $folder [lambda {ts} {
|
||||
if {[$ts flag Locked]} {
|
||||
log "Unlocked [$ts get file]" 0
|
||||
$ts unlock
|
||||
}
|
||||
}]
|
||||
return 0
|
||||
}
|
||||
default {
|
||||
log "Unknown action '$cmd'" 0
|
||||
}
|
||||
@ -384,7 +450,9 @@ proc ::sweeper::apply {dir cf} {
|
||||
if {[string match {\[*} $e]} continue
|
||||
if {$e eq $dustbin} continue
|
||||
|
||||
log "+ Sweeper processing folder $entry" 2
|
||||
log "" 2
|
||||
log "==== folder $entry ====" 2
|
||||
log "" 2
|
||||
|
||||
if {![file exists "$entry/.series"]} {
|
||||
log "Not series folder." 2
|
||||
|
@ -6,9 +6,14 @@ require system.class
|
||||
|
||||
httpheader "text/javascript"
|
||||
|
||||
puts {
|
||||
|
||||
var showraw = true;
|
||||
|
||||
set raw 0
|
||||
if {[file exists /mod/webif/plugin/sweeper/.raw]} {
|
||||
set raw 1
|
||||
}
|
||||
|
||||
puts "
|
||||
|
||||
var showraw = $raw;
|
||||
|
||||
"
|
||||
|
||||
|
@ -39,6 +39,14 @@ puts {
|
||||
</div>
|
||||
<div id=output></div>
|
||||
|
||||
<div id=macros>
|
||||
Add pre-defined ruleset:
|
||||
<select id=macroselect>
|
||||
<option value=0>--- Select ruleset ---</option>
|
||||
</select>
|
||||
<button id=b_macro>Add to rules</button>
|
||||
</div>
|
||||
|
||||
<div id=rule_template class="hidden">
|
||||
<fieldset class=rule>
|
||||
<legend class=comment>
|
||||
@ -55,25 +63,44 @@ puts {
|
||||
</a>
|
||||
</span>
|
||||
<span class=legendright>
|
||||
<span class="disabledtext blood hidden">
|
||||
(Disabled)
|
||||
</span>
|
||||
<a class=enadisrule href=#>
|
||||
<img src=img/disable.png
|
||||
alt="Enable/Disable Rule"
|
||||
title="Enable/Disable Rule">
|
||||
</a>
|
||||
<a class=delrule href=#>
|
||||
<img src=/img/context/delete.png>
|
||||
<img src=/img/context/delete.png
|
||||
alt="Delete Rule" title="Delete Rule">
|
||||
</a>
|
||||
<a class=cprule href=#>
|
||||
<img src=/img/context/page_white_copy.png
|
||||
alt="Duplicate Rule" title="Duplicate Rule">
|
||||
</a>
|
||||
<a class=uprule href=#>
|
||||
<img src=/img/nav/up.png>
|
||||
<img src=/img/nav/up.png
|
||||
alt="Move Rule Up" title="Move Rule Up">
|
||||
</a>
|
||||
<a class=downrule href=#>
|
||||
<img src=/img/nav/down.png>
|
||||
<img src=/img/nav/down.png
|
||||
alt="Move Rule Down" title="Move Rule Down">
|
||||
</a>
|
||||
</span>
|
||||
</legend>
|
||||
<a href=# class=addcriterion>
|
||||
<img src=/img/context/plus.png
|
||||
alt="Add condition" title="Add condition">
|
||||
</a>
|
||||
<div class=criteria>
|
||||
<table class="criteria keyval"><tbody>
|
||||
</tbody></table>
|
||||
<table class="criteria"><tbody></tbody></table>
|
||||
</div>
|
||||
<div class=arrow>
|
||||
<img src=img/arrow.png height=32>
|
||||
</div>
|
||||
<div class=action>
|
||||
<table class="action keyval"><tbody>
|
||||
</tbody></table>
|
||||
<button class=addcriterion>Add Criterion</button>
|
||||
<table class="action"><tbody></tbody></table>
|
||||
</div>
|
||||
<div class=raw></div>
|
||||
</fieldset>
|
||||
@ -119,6 +146,13 @@ puts {
|
||||
</select>
|
||||
<input name=edit_action_arg id=edit_action_arg size=60 maxlength=255 />
|
||||
</div>
|
||||
|
||||
<div class=hidden id=empty_rulebase>
|
||||
<b>There are no rules currently defined for this folder.</b>
|
||||
<br>
|
||||
You can add some example rules by using the <i>Add pre-defined ruleset</i>
|
||||
option at the bottom of the screen.
|
||||
</div>
|
||||
}
|
||||
|
||||
footer
|
||||
|
BIN
webif/plugin/sweeper/img/arrow.png
Normal file
BIN
webif/plugin/sweeper/img/arrow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.7 KiB |
BIN
webif/plugin/sweeper/img/disable.png
Normal file
BIN
webif/plugin/sweeper/img/disable.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1001 B |
BIN
webif/plugin/sweeper/img/redstripes.gif
Normal file
BIN
webif/plugin/sweeper/img/redstripes.gif
Normal file
Binary file not shown.
After Width: | Height: | Size: 5.0 KiB |
@ -48,6 +48,12 @@ proc quot {str} {
|
||||
proc rule {id rule} {
|
||||
global clausedescr lcomment
|
||||
|
||||
set enabled 1
|
||||
if {[lindex $rule 0] eq "##"} {
|
||||
set enabled 0
|
||||
set rule [lrange $rule 1 end]
|
||||
}
|
||||
|
||||
if {$lcomment eq ""} { set lcomment "Unnamed rule" }
|
||||
if {[lindex $rule 0] eq "folder"} {
|
||||
set type "folder"
|
||||
@ -61,14 +67,17 @@ proc rule {id rule} {
|
||||
add_json " \"raw\": \"[quot $rule]\",\n"
|
||||
add_json " \"name\": \"[quot $lcomment]\",\n"
|
||||
add_json " \"type\": \"$type\",\n"
|
||||
add_json " \"enabled\": \"$enabled\",\n"
|
||||
add_json " \"criteria\": \[\n"
|
||||
|
||||
set lcomment ""
|
||||
|
||||
set c 0
|
||||
set lockfound -1
|
||||
while {[llength $rule] > 1} {
|
||||
set rule [lassign $rule cmd arg]
|
||||
if {$cmd eq "action"} break
|
||||
if {$cmd eq "lock"} { set lockfound $arg }
|
||||
if {$c} { add_json ",\n" }
|
||||
incr c
|
||||
|
||||
@ -78,7 +87,17 @@ proc rule {id rule} {
|
||||
add_json " }"
|
||||
}
|
||||
add_json "\n"
|
||||
if {$cmd ne "action"} { set arg "continue" }
|
||||
if {$cmd ne "action"} {
|
||||
if {$lockfound != -1} {
|
||||
if {$lockfound == "1"} {
|
||||
set arg "lock"
|
||||
} else {
|
||||
set arg "unlock"
|
||||
}
|
||||
} else {
|
||||
set arg "continue"
|
||||
}
|
||||
}
|
||||
lassign $arg cmd arg
|
||||
if {$cmd eq "preserve"} { set cmd 'stop' }
|
||||
add_json " ],\n"
|
||||
@ -95,8 +114,8 @@ foreach rule $rules {
|
||||
if {[string index $rule 0] eq "#"} {
|
||||
if {[string index $rule 1] ne "#"} {
|
||||
comment $n [string range $rule 1 end]
|
||||
continue
|
||||
}
|
||||
continue
|
||||
}
|
||||
if {[llength $rule] < 2} continue
|
||||
incr n
|
||||
|
@ -6,6 +6,21 @@ require system.class
|
||||
|
||||
httpheader
|
||||
|
||||
set act [cgi_get act "save"]
|
||||
|
||||
switch $act {
|
||||
raw {
|
||||
set val [cgi_get val 0]
|
||||
if {$val} {
|
||||
file touch /mod/webif/plugin/sweeper/.raw
|
||||
} else {
|
||||
file delete -force /mod/webif/plugin/sweeper/.raw
|
||||
}
|
||||
puts "Done."
|
||||
exit;
|
||||
}
|
||||
}
|
||||
|
||||
set dir [cgi_get dir ""]
|
||||
set root [system mediaroot]
|
||||
|
||||
|
@ -1,56 +1,67 @@
|
||||
var schema = {
|
||||
criterion: {
|
||||
lcn: {
|
||||
'class': 'all',
|
||||
type: 'int',
|
||||
desc: 'Logical Channel Number',
|
||||
def: "0"
|
||||
},
|
||||
duration: {
|
||||
'class': 'all',
|
||||
type: 'int',
|
||||
desc: 'Recording duration (in minutes)',
|
||||
def: "0"
|
||||
},
|
||||
schedduration: {
|
||||
'class': 'all',
|
||||
type: 'int',
|
||||
desc: 'Scheduled duration (in minutes)',
|
||||
def: "0"
|
||||
},
|
||||
size: {
|
||||
'class': 'all',
|
||||
type: 'int',
|
||||
desc: 'Recording size (in bytes)',
|
||||
def: "0"
|
||||
},
|
||||
hour: {
|
||||
'class': 'all',
|
||||
type: 'int',
|
||||
desc: 'Hour in which the recording started',
|
||||
def: "0"
|
||||
},
|
||||
age: {
|
||||
'class': 'all',
|
||||
type: 'int',
|
||||
desc: 'Age (in hours)',
|
||||
def: "0"
|
||||
},
|
||||
wage: {
|
||||
'class': 'all',
|
||||
type: 'int',
|
||||
desc: 'Time since last watched, or recorded (in hours)',
|
||||
def: "0"
|
||||
},
|
||||
title: {
|
||||
'class': 'all',
|
||||
type: 'substr',
|
||||
desc: 'Recording Title contains',
|
||||
def: 'Enter text here...'
|
||||
},
|
||||
synopsis: {
|
||||
'class': 'all',
|
||||
type: 'substr',
|
||||
desc: 'Synopsis contains',
|
||||
def: 'Enter text here...'
|
||||
},
|
||||
guidance: {
|
||||
'class': 'all',
|
||||
type: 'substr',
|
||||
desc: 'Guidance Text contains',
|
||||
def: 'Enter text here...'
|
||||
},
|
||||
genre: {
|
||||
'class': 'all',
|
||||
type: 'select',
|
||||
desc: 'Recording Genre',
|
||||
select: {
|
||||
@ -67,6 +78,7 @@ var schema = {
|
||||
def: 'Unclassified'
|
||||
},
|
||||
definition: {
|
||||
'class': 'all',
|
||||
type: 'select',
|
||||
desc: 'Recording Definition',
|
||||
select: {
|
||||
@ -76,6 +88,7 @@ var schema = {
|
||||
def: 'SD'
|
||||
},
|
||||
flag: {
|
||||
'class': 'all',
|
||||
type: 'select',
|
||||
desc: 'Recording Flagged as',
|
||||
select: {
|
||||
@ -90,13 +103,21 @@ var schema = {
|
||||
def: 'New'
|
||||
},
|
||||
lock: {
|
||||
'class': 'all',
|
||||
type: 'select',
|
||||
desc: 'Change Recording Lock',
|
||||
select: {
|
||||
1: 'Lock Recording',
|
||||
0: 'Unlock Recording'
|
||||
},
|
||||
def: 1
|
||||
def: 1,
|
||||
deprecated: true
|
||||
},
|
||||
fflag: {
|
||||
'class': 'folder',
|
||||
type: 'string',
|
||||
desc: 'Folder flagged as',
|
||||
def: 'noflatten'
|
||||
}
|
||||
},
|
||||
action: {
|
||||
@ -104,50 +125,224 @@ var schema = {
|
||||
'class': 'all',
|
||||
argtype: 'none',
|
||||
desc: 'Continue on to next rule',
|
||||
showcont: false
|
||||
continues: true
|
||||
},
|
||||
stop: {
|
||||
'class': 'all',
|
||||
argtype: 'none',
|
||||
desc: 'Do nothing and stop processing rules',
|
||||
showcont: false
|
||||
continues: false
|
||||
},
|
||||
move: {
|
||||
'class': 'all',
|
||||
argtype: 'folder',
|
||||
desc: 'Move recording to folder...',
|
||||
showcont: true
|
||||
continues: false
|
||||
},
|
||||
lock: {
|
||||
'class': 'all',
|
||||
argtype: 'none',
|
||||
desc: 'Lock recordings',
|
||||
continues: true
|
||||
},
|
||||
unlock: {
|
||||
'class': 'all',
|
||||
argtype: 'none',
|
||||
desc: 'Unlock recordings',
|
||||
continues: true
|
||||
},
|
||||
movecreate: {
|
||||
'class': 'all',
|
||||
argtype: 'folder',
|
||||
desc: 'Move recording to folder (creating if necessary)',
|
||||
showcont: true
|
||||
continues: false
|
||||
},
|
||||
fileunder: {
|
||||
'class': 'folder',
|
||||
argtype: 'folder',
|
||||
desc: 'Merge into first folder of same name found under...',
|
||||
showcont: true
|
||||
continues: false
|
||||
},
|
||||
fileundercreate: {
|
||||
'class': 'folder',
|
||||
argtype: 'folder',
|
||||
desc: 'Merge into or create folder of ' +
|
||||
'same name found under...',
|
||||
showcont: true
|
||||
continues: false
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var select_criteria = {};
|
||||
var macros = {
|
||||
seriesfiler: {
|
||||
desc: 'Series-Filer',
|
||||
rules: [
|
||||
{
|
||||
"raw": "action {fileunder ""}",
|
||||
"name": "Emulate Seriesfiler",
|
||||
"type": "folder",
|
||||
"enabled": "1",
|
||||
"criteria": [],
|
||||
"action": {
|
||||
"cmd": "fileunder",
|
||||
"arg": ""
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
example: {
|
||||
desc: 'Example rules',
|
||||
rules: [
|
||||
{
|
||||
"raw": "lcn {>= 70} lcn {<= 79} duration {>= 90} action {move Children/Films}",
|
||||
"name": "Move any Children's films (by length)",
|
||||
"type": "file",
|
||||
"enabled": "0",
|
||||
"criteria": [
|
||||
{
|
||||
"cmd": "lcn",
|
||||
"arg": ">= 70"
|
||||
},
|
||||
{
|
||||
"cmd": "lcn",
|
||||
"arg": "<= 79"
|
||||
},
|
||||
{
|
||||
"cmd": "duration",
|
||||
"arg": ">= 90"
|
||||
}
|
||||
],
|
||||
"action": {
|
||||
"cmd": "move",
|
||||
"arg": "Children/Films"
|
||||
}
|
||||
},
|
||||
{
|
||||
"raw": "lcn {>= 70} lcn {<= 79} genre Film action {move Children/Films}",
|
||||
"name": "Move any Children's films (by genre)",
|
||||
"type": "file",
|
||||
"enabled": "0",
|
||||
"criteria": [
|
||||
{
|
||||
"cmd": "lcn",
|
||||
"arg": ">= 70"
|
||||
},
|
||||
{
|
||||
"cmd": "lcn",
|
||||
"arg": "<= 79"
|
||||
},
|
||||
{
|
||||
"cmd": "genre",
|
||||
"arg": "Film"
|
||||
}
|
||||
],
|
||||
"action": {
|
||||
"cmd": "move",
|
||||
"arg": "Children/Films"
|
||||
}
|
||||
},
|
||||
{
|
||||
"raw": "lcn {>= 70} lcn {<= 79} action {move Children/Miscellaneous}",
|
||||
"name": "Move anything else recorded from a children's channel",
|
||||
"type": "file",
|
||||
"enabled": "0",
|
||||
"criteria": [
|
||||
{
|
||||
"cmd": "lcn",
|
||||
"arg": ">= 70"
|
||||
},
|
||||
{
|
||||
"cmd": "lcn",
|
||||
"arg": "<= 79"
|
||||
}
|
||||
],
|
||||
"action": {
|
||||
"cmd": "move",
|
||||
"arg": "Children/Miscellaneous"
|
||||
}
|
||||
},
|
||||
{
|
||||
"raw": "lcn {>= 70} lcn {<= 79} action {fileundercreate Children}",
|
||||
"name": "Move any series recordings from a Children's channel (folder rule)",
|
||||
"type": "folder",
|
||||
"enabled": "0",
|
||||
"criteria": [
|
||||
{
|
||||
"cmd": "lcn",
|
||||
"arg": ">= 70"
|
||||
},
|
||||
{
|
||||
"cmd": "lcn",
|
||||
"arg": "<= 79"
|
||||
}
|
||||
],
|
||||
"action": {
|
||||
"cmd": "fileundercreate",
|
||||
"arg": "Children"
|
||||
}
|
||||
},
|
||||
{
|
||||
"raw": "title {Formula 1} action {move F1}",
|
||||
"name": "Move any one-off Formula 1 recordings into the F1 folder",
|
||||
"type": "file",
|
||||
"enabled": "0",
|
||||
"criteria": [
|
||||
{
|
||||
"cmd": "title",
|
||||
"arg": "Formula 1"
|
||||
}
|
||||
],
|
||||
"action": {
|
||||
"cmd": "move",
|
||||
"arg": "F1"
|
||||
}
|
||||
},
|
||||
{
|
||||
"raw": "age {> 120} action {movecreate Misc}",
|
||||
"name": "Move any one-off recordings into a folder called Misc after a while",
|
||||
"type": "file",
|
||||
"enabled": "0",
|
||||
"criteria": [
|
||||
{
|
||||
"cmd": "age",
|
||||
"arg": "> 120"
|
||||
}
|
||||
],
|
||||
"action": {
|
||||
"cmd": "movecreate",
|
||||
"arg": "Misc"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
var select_file_criteria = {};
|
||||
var select_folder_criteria = {};
|
||||
$.each(schema.criterion, function(k, v) {
|
||||
select_criteria[k] = v.desc;
|
||||
if (v.deprecated)
|
||||
return;
|
||||
switch (v['class'])
|
||||
{
|
||||
case 'file':
|
||||
select_file_criteria[k] = v.desc;
|
||||
break;
|
||||
case 'folder':
|
||||
select_folder_criteria[k] = v.desc;
|
||||
break;
|
||||
case 'all':
|
||||
select_file_criteria[k] = v.desc;
|
||||
select_folder_criteria[k] = v.desc;
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
var select_file_actions = {};
|
||||
var select_folder_actions = {};
|
||||
$.each(schema.action, function(k, v) {
|
||||
if (v.deprecated)
|
||||
return;
|
||||
switch (v['class'])
|
||||
{
|
||||
case 'file':
|
||||
|
@ -6,7 +6,7 @@ function quot(str)
|
||||
if (!str)
|
||||
return '""';
|
||||
|
||||
if (str.indexOf(" ") == -1)
|
||||
if (str.indexOf(" ") == -1 && str.indexOf('"') == -1)
|
||||
return str;
|
||||
return '{' + str + '}';
|
||||
}
|
||||
@ -15,6 +15,11 @@ 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)
|
||||
@ -23,12 +28,12 @@ function changed(c)
|
||||
return;
|
||||
if (c)
|
||||
{
|
||||
$('#b_save,#b_revert').enable();
|
||||
$('#b_save,#b_revert').button('enable');
|
||||
$('#pendingnote').show();
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#b_save,#b_revert').disable();
|
||||
$('#b_save,#b_revert').button('disable');
|
||||
$('#pendingnote').hide();
|
||||
}
|
||||
changed.last = c;
|
||||
@ -52,6 +57,9 @@ var setters = {
|
||||
substr: function(cmd, a) {
|
||||
return a;
|
||||
},
|
||||
'string': function(cmd, a) {
|
||||
return a;
|
||||
},
|
||||
select: function(cmd, a) {
|
||||
return schema.criterion[cmd].select[a];
|
||||
}
|
||||
@ -70,6 +78,9 @@ var getters = {
|
||||
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)
|
||||
@ -83,11 +94,13 @@ function ruleconf(rule)
|
||||
{
|
||||
var s = '';
|
||||
|
||||
if ($(rule).attr('type') == 'folder')
|
||||
if (rule.hasClass('ruledisabled'))
|
||||
s += '## ';
|
||||
if (rule.attr('type') == 'folder')
|
||||
s += 'folder ';
|
||||
|
||||
$(rule).find('tr.clause').each(function(i) {
|
||||
cmd = $(this).find('th').attr('cmd');
|
||||
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])
|
||||
@ -96,12 +109,17 @@ function ruleconf(rule)
|
||||
s += cmd + ' ' + quot(val) + ' ';
|
||||
});
|
||||
|
||||
act = $(rule).find('tr.action th').attr('cmd');
|
||||
arg = $.trim($(rule).find('tr.action td.val').text());
|
||||
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')
|
||||
s += 'action {' + act + ' ' + quot(arg) + '}';
|
||||
{
|
||||
if (schema.action[act].argtype == 'none')
|
||||
s += 'action ' + act;
|
||||
else
|
||||
s += 'action {' + act + ' ' + quot(arg) + '}';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
@ -120,12 +138,22 @@ function conffile()
|
||||
|
||||
function rulerefresh(rule)
|
||||
{
|
||||
if (!showraw)
|
||||
rule.find('.raw').hide();
|
||||
rule.find('.raw').html(ruleconf(rule));
|
||||
rule.find('tr.clause td.title').text('And:').first().text('If:');
|
||||
rule.find('tr.clause th.title').text('And:').first().text('If:');
|
||||
if (rule.find('tr.clause').length < 1)
|
||||
rule.find('tr.action td.title').text('Always:');
|
||||
{
|
||||
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 td.title').text('Then:');
|
||||
{
|
||||
rule.find('tr.action th.title').text('Then:');
|
||||
rule.find('tr.otherwise').show();
|
||||
rule.find('div.criteria,div.arrow').show();
|
||||
}
|
||||
}
|
||||
|
||||
function criterion(data)
|
||||
@ -133,8 +161,9 @@ function criterion(data)
|
||||
var c = schema.criterion[data.cmd];
|
||||
var s;
|
||||
|
||||
s = '<tr class=clause><td class=title>And:</td>' +
|
||||
'<th cmd=' + data.cmd + '>' + c.desc + '</th><td class=val>';
|
||||
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);
|
||||
@ -160,16 +189,26 @@ function action(data)
|
||||
data.arg = mroot;
|
||||
|
||||
s = '<tr class=action>' +
|
||||
'<td class=title>Then:</td>' +
|
||||
'<th cmd=' + data.cmd + '>' + c.desc + '</th>' +
|
||||
'<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 (c.showcont)
|
||||
s += '<tr><td class=title>Else:</td>' +
|
||||
'<th>Continue on to next rule.</th></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;
|
||||
}
|
||||
@ -196,16 +235,25 @@ function addrule(id, data)
|
||||
|
||||
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('td.title:first').text('If:');
|
||||
$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"}});
|
||||
// rule.find('button.addcriterion')
|
||||
// .button({icons: { primary: "ui-icon-plus"}});
|
||||
|
||||
rulerefresh(rule);
|
||||
|
||||
@ -241,6 +289,8 @@ function edit_text(obj, title, text, callback)
|
||||
}
|
||||
}
|
||||
});
|
||||
if (text == 'Enter text here...')
|
||||
$('#edit_text_field').focus().select();
|
||||
}
|
||||
|
||||
function edit_int(obj, title, op, val, callback)
|
||||
@ -310,10 +360,10 @@ function edit_select(obj, title, options, val, callback)
|
||||
|
||||
function edit_clause(obj)
|
||||
{
|
||||
var cmd = $(obj).find('th').attr('cmd');
|
||||
var cmd = $(obj).find('th.cmd').attr('cmd');
|
||||
var target = $(obj).find('td.val');
|
||||
var val = $.trim($(target).text());
|
||||
var title = $(obj).find('th').html();
|
||||
var title = $(obj).find('th.cmd').html();
|
||||
if (!schema.criterion[cmd])
|
||||
{
|
||||
alert('Unhandled command (' + cmd + ')');
|
||||
@ -364,7 +414,7 @@ function loadrules(dir)
|
||||
if (!data.length)
|
||||
{
|
||||
$('#ruleset').attr('empty', true)
|
||||
.html('<i>No rules defined for this folder.</i>');
|
||||
.html($('#empty_rulebase').html());
|
||||
return;
|
||||
}
|
||||
$.each(data, function(key, val) {
|
||||
@ -412,18 +462,18 @@ $('#b_add').button({icons: {primary: "ui-icon-plus"}})
|
||||
}
|
||||
});
|
||||
$('#newrule_type_file').prop('checked', true);
|
||||
$('#newrule_comment').focus().val('').val('Unnamed rule');
|
||||
$('#newrule_comment').focus().val('').val('Unnamed rule').select();
|
||||
});
|
||||
|
||||
$('#b_save').button({icons: {primary: "ui-icon-disk"}})
|
||||
.on('click', function(e) {
|
||||
$('#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) {
|
||||
$('.jcaquestion').fadeOut(300);
|
||||
$.post('save.jim', {
|
||||
dir: $('span.dir').text(),
|
||||
data: conffile()
|
||||
@ -435,15 +485,15 @@ $('#b_save').button({icons: {primary: "ui-icon-disk"}})
|
||||
});
|
||||
});
|
||||
|
||||
$('#b_revert').button({icons: {primary: "ui-icon-arrowrefresh-1-w"}})
|
||||
.on('click', function(e) {
|
||||
$('#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) {
|
||||
$('.jcaquestion').fadeOut(300);
|
||||
loadrules($('span.dir').text());
|
||||
changed(0);
|
||||
});
|
||||
@ -470,6 +520,32 @@ $('#b_show').button({icons: {primary: "ui-icon-clipboard"}})
|
||||
$('#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);
|
||||
@ -479,11 +555,17 @@ $('#ruleset')
|
||||
e.preventDefault();
|
||||
edit_clause($(this).closest('tr.clause'));
|
||||
})
|
||||
.on('click', 'button.addcriterion', function(e) {
|
||||
.on('click', 'a.addcriterion', function(e) {
|
||||
e.preventDefault();
|
||||
var rule = $(this).closest('div.rule');
|
||||
edit_select(rule, 'Select new criterion',
|
||||
select_criteria, '', function(rule, val) {
|
||||
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({
|
||||
@ -537,6 +619,35 @@ $('#ruleset')
|
||||
});
|
||||
});
|
||||
})
|
||||
.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();
|
||||
|
||||
@ -555,7 +666,7 @@ $('#ruleset')
|
||||
);
|
||||
});
|
||||
|
||||
var cmd = rule.find('tr.action th').attr('cmd');
|
||||
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')
|
||||
@ -596,11 +707,10 @@ $('#ruleset')
|
||||
.on('click', 'a.delclause', function(e) {
|
||||
e.preventDefault();
|
||||
$(this).dojConfirmAction({
|
||||
question: 'Delete criterion?',
|
||||
question: 'Delete condition?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
$('.jcaquestion').fadeOut(300);
|
||||
var rule = $(el).closest('div.rule');
|
||||
$(el).closest('tr.clause').fadeOut('slow', function() {
|
||||
$(this).remove();
|
||||
@ -616,19 +726,33 @@ $('#ruleset')
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
$('.jcaquestion').fadeOut(300);
|
||||
$(el).closest('div.rule').slideUp('slow', function() {
|
||||
$(el).closest('div.rule')
|
||||
.addClass('hl')
|
||||
.slideUp('slow', function() {
|
||||
$(this).remove();
|
||||
changed(1);
|
||||
fixupdown();
|
||||
if ($('div.rule').length < 1)
|
||||
$('#ruleset').attr('empty', true)
|
||||
.html('<i>No rules defined for this ' +
|
||||
'folder.</i>');
|
||||
.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());
|
||||
});
|
||||
|
||||
|
@ -1,4 +1,9 @@
|
||||
|
||||
a
|
||||
{
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
span.ruleicon img
|
||||
{
|
||||
height: 21px;
|
||||
@ -20,15 +25,30 @@ img
|
||||
background: yellow;
|
||||
}
|
||||
|
||||
.ruledisabled
|
||||
{
|
||||
background: #663436 url(img/redstripes.gif) repeat;
|
||||
}
|
||||
|
||||
div.action
|
||||
{
|
||||
padding-left: 1em;
|
||||
float: left;
|
||||
}
|
||||
|
||||
a.addcriterion
|
||||
{
|
||||
padding: 4px 2px 0 0;
|
||||
float: left;
|
||||
clear: left;
|
||||
}
|
||||
|
||||
div.criteria
|
||||
{
|
||||
clear: left;
|
||||
float: left;
|
||||
}
|
||||
|
||||
div.arrow
|
||||
{
|
||||
float: left;
|
||||
}
|
||||
|
||||
@ -47,11 +67,9 @@ div#buttons
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
td.title,th.title
|
||||
div#macros
|
||||
{
|
||||
line-height: 1em;
|
||||
text-align: left !important;
|
||||
background: #eee !important;
|
||||
padding-top: 1em;
|
||||
}
|
||||
|
||||
div.rule
|
||||
@ -86,3 +104,47 @@ span.legendright
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
table
|
||||
{
|
||||
border: 0;
|
||||
}
|
||||
|
||||
table th
|
||||
{
|
||||
background: #ccff99;
|
||||
font-weight: bold;
|
||||
text-align: right;
|
||||
color: black;
|
||||
xpadding: 0.5em;
|
||||
}
|
||||
|
||||
table td
|
||||
{
|
||||
background: #ffffcc;
|
||||
color: black;
|
||||
}
|
||||
|
||||
td.title,th.title
|
||||
{
|
||||
line-height: 1em;
|
||||
background: #eee !important;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
td.title
|
||||
{
|
||||
text-align: left !important;
|
||||
}
|
||||
|
||||
th.title
|
||||
{
|
||||
font-weight: normal;
|
||||
text-align: right !important;
|
||||
}
|
||||
|
||||
tr.blank td
|
||||
{
|
||||
background: transparent;
|
||||
line-height: 7px;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user