forked from hummypkg/webif
1.2.9 beta
git-svn-id: file:///root/webif/svn/pkg/webif/trunk@2871 2a923420-c742-0410-a762-8d5b09965624
This commit is contained in:
parent
9ce18af5cf
commit
58da098a11
@ -1,10 +1,10 @@
|
||||
Package: webif
|
||||
Priority: optional
|
||||
Section: web
|
||||
Version: 1.2.8-16
|
||||
Version: 1.2.9-0
|
||||
Architecture: mipsel
|
||||
Maintainer: af123@hpkg.tv
|
||||
Depends: tcpfix,webif-channelicons(>=1.1.20),lighttpd(>=1.4.39-1),jim(>=0.76-1),jim-oo,jim-sqlite3(>=0.76),jim-cgi(>=0.7-1),jim-binary(>=0.76),service-control(>=2.1),busybox(>=1.20.2-1),lsof(>=4.87),epg(>=1.2.1-1),hmt(>=2.0.9),ssmtp,cron-daemon(>=1.18.3-3),at(>=3.1.18),anacron,trm(>=1.1),openssl-command,nicesplice,id3v2,file,rsvsync(>=1.0.2),webif-charts(>=1.2-1),stripts(>=1.2.5-3),tmenu(>=1.08),ffmpeg,id3v2,multienv(>=1.6),tcpping(>=1.1),e2fsprogs,wireless-tools(>=29-1),dbupdate,recmon(>=2.0.7)
|
||||
Depends: tcpfix,webif-channelicons(>=1.1.20),lighttpd(>=1.4.39-1),jim(>=0.76-2),jim-oo,jim-sqlite3(>=0.76),jim-cgi(>=0.7-1),jim-binary(>=0.76),service-control(>=2.1),busybox(>=1.20.2-1),lsof(>=4.87),epg(>=1.2.1-1),hmt(>=2.0.9),ssmtp,cron-daemon(>=1.18.3-3),at(>=3.1.18),anacron,trm(>=1.1),openssl-command,nicesplice,id3v2,file,rsvsync(>=1.0.2),webif-charts(>=1.2-1),stripts(>=1.2.5-3),tmenu(>=1.08),ffmpeg,id3v2,multienv(>=1.6),tcpping(>=1.1),e2fsprogs,wireless-tools(>=29-1),dbupdate,recmon(>=2.0.7)
|
||||
Suggests:
|
||||
Description: An evolving web interface for the Humax.
|
||||
Tags: http://hummy.tv/forum/threads/6484/
|
||||
|
@ -29,7 +29,7 @@ fi
|
||||
ana=$PKG_ROOT/etc/anacrontab
|
||||
egrep -v 'backup/backup.jim|bin/diskattrs' $ana > $tmpf
|
||||
cat $tmpf - << EOM > $ana
|
||||
1 8 sched_backup /mod/webif/html/backup/backup.jim
|
||||
1 8 sched_backup /mod/webif/html/sched/backup/backup.jim
|
||||
1 5 diskattrs /mod/webif/lib/bin/diskattrs
|
||||
EOM
|
||||
|
||||
|
@ -25,14 +25,20 @@ if {[[settings] chanchangenc]} {
|
||||
|
||||
$record process_sched
|
||||
if {[$record get sched_type] < 1} {
|
||||
set tuners [system tuners]
|
||||
set conflicts [rsv conflicts [$record get start] [$record get duration]]
|
||||
if {$conflicts >= $tuners} {
|
||||
set conflicts [rsv checkconflict \
|
||||
[$record get start] [$record get duration] \
|
||||
[system tuners]]
|
||||
if {[llength $conflicts]} {
|
||||
puts {
|
||||
<div class=warningbox style="width: 100%; margin: 0.2em"><div>
|
||||
This event conflicts with items in your scheduled recording list.
|
||||
</div></div>
|
||||
This event conflicts with the following items in your scheduled recording list.
|
||||
<ul>
|
||||
}
|
||||
foreach x $conflicts {
|
||||
puts "<li>$x</li>\n"
|
||||
}
|
||||
|
||||
puts "</div></div>"
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -27,7 +27,7 @@ if {[$event percent] > 0} {
|
||||
}
|
||||
|
||||
set r [rsv construct $event $type]
|
||||
if {[catch {$r insert} msg]} {
|
||||
if {[catch {$r insert pending 1} msg]} {
|
||||
puts "Error encountered while scheduling: <i>$msg</i>"
|
||||
} else {
|
||||
puts "Successfully scheduled <i>[$event get name]</i>"
|
||||
|
@ -1,38 +0,0 @@
|
||||
$(function() {
|
||||
|
||||
$('#epgswitch').button().click(function() {
|
||||
window.location = '/epg/list.jim';
|
||||
});
|
||||
|
||||
$('button.nav').click(function() {
|
||||
window.location = '/cgi-bin/xepg.jim?stt=' + $(this).attr('tt') +
|
||||
'&pos=' + $('#xegrid').scrollTop();
|
||||
});
|
||||
|
||||
$('#xepg_dp').datepicker({
|
||||
buttonImage: '/img/cal.gif',
|
||||
buttonImageOnly: true,
|
||||
showOn: 'button',
|
||||
dateFormat: '@',
|
||||
minDate: 0,
|
||||
maxDate: 8,
|
||||
onSelect: function(val, sel) {
|
||||
var stt = $(this).attr('stt');
|
||||
// Extract date part
|
||||
dval = Math.round(val / 86400000.0);
|
||||
// Extract current time part
|
||||
var tm = ~~(stt % 86400);
|
||||
|
||||
var ret = dval * 86400 + tm;
|
||||
|
||||
window.location = '/cgi-bin/xepg.jim?stt=' + ret;
|
||||
}
|
||||
});
|
||||
|
||||
$('img.ui-datepicker-trigger').hover(
|
||||
function() { $(this).css('cursor', 'pointer'); },
|
||||
function() { $(this).css('cursor', 'auto'); }
|
||||
);
|
||||
|
||||
});
|
||||
|
@ -1,69 +0,0 @@
|
||||
|
||||
function refresh_files()
|
||||
{
|
||||
$('#backup_files').load('files.jim', function() {
|
||||
$('input.restore').change(function() {
|
||||
$('#restore_button').removeAttr('disabled')
|
||||
.button('option', 'disabled', false);
|
||||
$('#delete_button').removeAttr('disabled')
|
||||
.button('option', 'disabled', false);
|
||||
$('#view_button').removeAttr('disabled')
|
||||
.button('option', 'disabled', false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
$('button').button();
|
||||
|
||||
refresh_files();
|
||||
|
||||
$('#backup_button').click(function() {
|
||||
$('#backup_working').slideDown();
|
||||
$('#results').load('backup.jim?' +
|
||||
$('#backup_name').serialize(), function() {
|
||||
$('#results').slideDown(function() {
|
||||
$('#backup_working').slideUp();
|
||||
refresh_files();
|
||||
});
|
||||
});
|
||||
});
|
||||
$('#delete_button').click(function() {
|
||||
var backup = $('input.restore:checked').val();
|
||||
if (confirm('Confirm deletion of ' + backup))
|
||||
{
|
||||
$('#results').load('delete.jim?' +
|
||||
$('input.restore').serialize(), function() {
|
||||
$('#results').slideDown(function() {
|
||||
refresh_files();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#view_button').click(function() {
|
||||
var backup = $('input.restore:checked').val();
|
||||
$('#results').load('view.jim?' +
|
||||
$('input.restore').serialize(), function() {
|
||||
$('#results').slideDown(function() {
|
||||
refresh_files();
|
||||
});
|
||||
});
|
||||
});
|
||||
$('#restore_button').click(function() {
|
||||
var backup = $('input.restore:checked').val();
|
||||
if (confirm('!!!!!!!!!!!!!!!!!!!!!!!!! PLEASE CONFIRM !!!!!!!!!!!!!!!!!!!!!!!!!\n\nAre you sure you wish to erase all scheduled recordings and favourite channels and then restore them from\n' + backup + '?'))
|
||||
{
|
||||
$('#restore_working').slideDown();
|
||||
$('#results').load('restore.jim?' +
|
||||
$('input.restore').serialize(), function() {
|
||||
$('#results').slideDown(function() {
|
||||
$('#restore_working').slideUp();
|
||||
refresh_files();
|
||||
$('#restore_warning').slideDown();
|
||||
$('#restart_block').slideDown('slow');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@ -109,7 +109,7 @@ div.warningbox
|
||||
top: -2px;
|
||||
left: -2px;
|
||||
font-weight: bold;
|
||||
z-index: 30;
|
||||
#z-index: 30;
|
||||
box-shadow: 2px 2px 11px #666;
|
||||
-moz-box-shadow: 2px 2px 11px #666;
|
||||
-webkit-box-shadow: 2px 2px 11px #666;
|
||||
@ -174,22 +174,22 @@ table.keyval td
|
||||
|
||||
pre, .pre, .prelike
|
||||
{
|
||||
font-family: Consolas, 'Courier New', Courier, monospace;
|
||||
color: black;
|
||||
background: #f9d9b0 url('/img/prebg.png') repeat-x top;
|
||||
font-family: Consolas, 'Courier New', Courier, monospace;
|
||||
color: black;
|
||||
background: #f9d9b0 url('/img/prebg.png') repeat-x top;
|
||||
line-height: 1.24;
|
||||
padding: 3px 8px;
|
||||
margin: 0 5em 1em 5em;
|
||||
border-color: #f9d9b0;
|
||||
border-bottom: 1px solid #f9bc6d;
|
||||
border-top-left-radius: 4px;
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
-moz-border-radius-topleft: 4px;
|
||||
-khtml-border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
-moz-border-radius-topright: 4px;
|
||||
-khtml-border-top-right-radius: 4px;
|
||||
padding: 3px 8px;
|
||||
margin: 0 5em 1em 5em;
|
||||
border-color: #f9d9b0;
|
||||
border-bottom: 1px solid #f9bc6d;
|
||||
border-top-left-radius: 4px;
|
||||
-webkit-border-top-left-radius: 4px;
|
||||
-moz-border-radius-topleft: 4px;
|
||||
-khtml-border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
-webkit-border-top-right-radius: 4px;
|
||||
-moz-border-radius-topright: 4px;
|
||||
-khtml-border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
pre, .pre
|
||||
@ -291,7 +291,7 @@ tr.blueshade > td, .blueshade
|
||||
|
||||
.pinkshade
|
||||
{
|
||||
background: #ffccff;
|
||||
background: #ffccff !important;
|
||||
color: black;
|
||||
}
|
||||
|
||||
@ -312,12 +312,18 @@ tr.blueshade > td, .blueshade
|
||||
color: black;
|
||||
}
|
||||
|
||||
.orangeshade
|
||||
tr.orangeshade > td, .orangeshade
|
||||
{
|
||||
background: #ffeeaa;
|
||||
background: #ff8040 !important;
|
||||
color: black;
|
||||
}
|
||||
|
||||
tr.purpleshade > td, .purpleshade
|
||||
{
|
||||
background: #7e587e !important;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.redshade
|
||||
{
|
||||
background: #ff4000;
|
||||
@ -594,3 +600,56 @@ img.rollimg
|
||||
clear: right;
|
||||
}
|
||||
|
||||
/* Minimal tabs */
|
||||
|
||||
#minimaltabbar
|
||||
{
|
||||
background: transparent;
|
||||
border: none;
|
||||
padding: 0 0 0 0;
|
||||
position: relative;
|
||||
top: -40px;
|
||||
}
|
||||
|
||||
#minimaltabbar .ui-widget-header
|
||||
{
|
||||
background: transparent;
|
||||
border: none;
|
||||
border-bottom: 1px solid #c0c0c0;
|
||||
-moz-border-radius: 0px;
|
||||
-webkit-border-radius: 0px;
|
||||
border-radius: 0px;
|
||||
}
|
||||
|
||||
#minimaltabbar .ui-tabs-nav
|
||||
{
|
||||
margin-bottom: 15px;
|
||||
}
|
||||
|
||||
#minimaltabbar .ui-tabs-nav .ui-state-default
|
||||
{
|
||||
background: transparent;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#minimaltabbar .ui-tabs-nav .ui-state-active
|
||||
{
|
||||
background: transparent url(/img/uiTabsArrow.png) no-repeat bottom center;
|
||||
border: none;
|
||||
}
|
||||
|
||||
#minimaltabbar .ui-tabs-nav .ui-state-default a
|
||||
{
|
||||
color: #c0c0c0;
|
||||
}
|
||||
|
||||
#minimaltabbar .ui-tabs-nav .ui-state-active a
|
||||
{
|
||||
color: #000000;
|
||||
}
|
||||
|
||||
#minimaltabbar .ui-tabs-panel
|
||||
{
|
||||
padding: 0 0 0 0;
|
||||
}
|
||||
|
||||
|
@ -53,7 +53,7 @@ puts {
|
||||
<small><button id=switch>Switch to grid-style Now/Next</button></small>
|
||||
<script type=text/javascript>
|
||||
$('#switch').button().click(function() {
|
||||
window.location = '/cgi-bin/xepg.jim'; });
|
||||
window.location = '/xepg/'; });
|
||||
</script>
|
||||
<table class=borders>
|
||||
<tr>
|
||||
|
@ -21,7 +21,7 @@ require epg_popup
|
||||
set service [cgi_get service 4170]
|
||||
set records [epg dbfetch dump \
|
||||
-service $service \
|
||||
-sort "strftime('%%H%%J', start, 'unixepoch'), strftime('%%M', start, 'unixepoch')" \
|
||||
-sort "strftime('%%H%%J', start, 'unixepoch', 'localtime'), strftime('%%M', start, 'unixepoch')" \
|
||||
-debug 0
|
||||
]
|
||||
|
||||
|
@ -12,7 +12,7 @@ if {[dict exists $env HTTP_COOKIE]} {
|
||||
set settings [settings]
|
||||
|
||||
if {[$settings epg_style] eq "grid"} {
|
||||
set epglink "/cgi-bin/xepg.jim"
|
||||
set epglink "/xepg/"
|
||||
} else {
|
||||
set epglink "/epg/list.jim"
|
||||
}
|
||||
|
BIN
webif/html/img/uiTabsArrow.png
Normal file
BIN
webif/html/img/uiTabsArrow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 112 B |
@ -3,9 +3,9 @@ $(function() {
|
||||
{
|
||||
$('#epginfo_extra').load('/cgi-bin/epg/schedule.jim?' +
|
||||
'service=' +
|
||||
encodeURIComponent($('#dialogue').attr('xs')) +
|
||||
encodeURIComponent($('#epgpopup_dialogue').attr('xs')) +
|
||||
'&event=' +
|
||||
encodeURIComponent($('#dialogue').attr('xe')) +
|
||||
encodeURIComponent($('#epgpopup_dialogue').attr('xe')) +
|
||||
'&type=' + type, function() {
|
||||
$('#restart_block').slideDown('slow');
|
||||
});
|
||||
@ -24,14 +24,14 @@ $(function() {
|
||||
{"Record Series": function() { doschedule(2) }},
|
||||
$buttons2);
|
||||
|
||||
var $dialog = $('#dialogue').dialog({
|
||||
var $dialog = $('#epgpopup_dialogue').dialog({
|
||||
title: "Programme Details",
|
||||
modal: false, autoOpen: false,
|
||||
height: 500, width: 700,
|
||||
show: 'scale', hide: 'fade',
|
||||
draggable: true, resizable: true,
|
||||
buttons: $buttons1,
|
||||
close: function(e,u) { $('#dialogue').empty().html(
|
||||
close: function(e,u) { $('#epgpopup_dialogue').empty().html(
|
||||
'<img src="/img/loading.gif" alt="loading">'); }
|
||||
});
|
||||
|
||||
@ -51,15 +51,15 @@ $(function() {
|
||||
var url = '/cgi-bin/epg/info.jim?service=' +
|
||||
o.attr('xs') + '&event=' +
|
||||
o.attr('xe') + '&bare=1';
|
||||
$('#dialogue')
|
||||
$('#epgpopup_dialogue')
|
||||
.html('<img src=/img/loading.gif> Loading details...' +
|
||||
' Please wait...')
|
||||
.load(url, function() {
|
||||
$('#dialogue a.event').click(function(e) {
|
||||
$('#epgpopup_dialogue a.event').click(function(e) {
|
||||
epgpopup(e, $(this));
|
||||
});
|
||||
});
|
||||
$('#dialogue')
|
||||
$('#epgpopup_dialogue')
|
||||
.attr('xs', o.attr('xs'))
|
||||
.attr('xe', o.attr('xe'));
|
||||
$dialog.dialog('open');
|
||||
|
32
webif/html/js/icons.js
Normal file
32
webif/html/js/icons.js
Normal file
@ -0,0 +1,32 @@
|
||||
function schedule_icons(reckind, rsvtype, repeat)
|
||||
{
|
||||
var icons = [];
|
||||
|
||||
switch (rsvtype)
|
||||
{
|
||||
case 1: icons.push("175_1_00_Reservation_Watch"); break;
|
||||
case 2: icons.push("175_1_00_Reservation_Watch"); break;
|
||||
case 3: icons.push("175_1_11_Reservation_Record"); break;
|
||||
case 4: icons.push("175_1_11_Reservation_Record"); break;
|
||||
case 5: icons.push("745_1_10_Video_2Live"); break;
|
||||
case 6: icons.push("745_1_11_Video_1REC"); break;
|
||||
case 7: icons.push("345_6_08_ST_Ad_Hoc"); break;
|
||||
}
|
||||
|
||||
switch (reckind)
|
||||
{
|
||||
case 2: icons.push("178_1_26_Icon_Split"); break;
|
||||
case 4: icons.push("175_1_11_Series_Record"); break;
|
||||
default:
|
||||
switch (repeat)
|
||||
{
|
||||
case 1: icons.push("521_1_00_RP_Daily_C"); break;
|
||||
case 2: icons.push("521_1_00_RP_Weekly_C"); break;
|
||||
case 3: icons.push("521_1_00_RP_Weekdays_C"); break;
|
||||
case 4: icons.push("521_1_00_RP_Weekend_C"); break;
|
||||
}
|
||||
}
|
||||
|
||||
return icons;
|
||||
}
|
||||
|
@ -5,10 +5,9 @@ puts {
|
||||
<div class=footer>
|
||||
}
|
||||
|
||||
if {![catch {
|
||||
set rendertime [expr [expr [clock milliseconds] - $renderstart] / 1000.0]
|
||||
}]} {
|
||||
puts "<font class=footnote>Rendered in: $rendertime seconds</font>"
|
||||
catch {
|
||||
set rendertime [expr ([clock milliseconds] - $renderstart) / 1000.0]
|
||||
puts "<span class=footnote>Rendered in: $rendertime seconds</span>"
|
||||
}
|
||||
|
||||
puts {
|
||||
|
85
webif/html/lib/jquery.plugin/growl/jquery.growl.css
Normal file
85
webif/html/lib/jquery.plugin/growl/jquery.growl.css
Normal file
@ -0,0 +1,85 @@
|
||||
/* jQuery Growl
|
||||
* Copyright 2015 Kevin Sylvestre
|
||||
* 1.3.1
|
||||
*/
|
||||
#growls {
|
||||
z-index: 50000;
|
||||
position: fixed; }
|
||||
#growls.default {
|
||||
top: 10px;
|
||||
right: 10px; }
|
||||
#growls.tl {
|
||||
top: 10px;
|
||||
left: 10px; }
|
||||
#growls.tr {
|
||||
top: 10px;
|
||||
right: 10px; }
|
||||
#growls.bl {
|
||||
bottom: 10px;
|
||||
left: 10px; }
|
||||
#growls.br {
|
||||
bottom: 10px;
|
||||
right: 10px; }
|
||||
#growls.tc {
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
left: 10px; }
|
||||
#growls.bc {
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
left: 10px; }
|
||||
#growls.tc .growl, #growls.bc .growl {
|
||||
margin-left: auto;
|
||||
margin-right: auto; }
|
||||
|
||||
.growl {
|
||||
opacity: 0.8;
|
||||
filter: alpha(opacity=80);
|
||||
position: relative;
|
||||
border-radius: 4px;
|
||||
-webkit-transition: all 0.4s ease-in-out;
|
||||
-moz-transition: all 0.4s ease-in-out;
|
||||
transition: all 0.4s ease-in-out; }
|
||||
.growl.growl-incoming {
|
||||
opacity: 0;
|
||||
filter: alpha(opacity=0); }
|
||||
.growl.growl-outgoing {
|
||||
opacity: 0;
|
||||
filter: alpha(opacity=0); }
|
||||
.growl.growl-small {
|
||||
width: 200px;
|
||||
padding: 5px;
|
||||
margin: 5px; }
|
||||
.growl.growl-medium {
|
||||
width: 250px;
|
||||
padding: 10px;
|
||||
margin: 10px; }
|
||||
.growl.growl-large {
|
||||
width: 300px;
|
||||
padding: 15px;
|
||||
margin: 15px; }
|
||||
.growl.growl-default {
|
||||
color: #FFF;
|
||||
background: #7f8c8d; }
|
||||
.growl.growl-error {
|
||||
color: #FFF;
|
||||
background: #C0392B; }
|
||||
.growl.growl-notice {
|
||||
color: #FFF;
|
||||
background: #2ECC71; }
|
||||
.growl.growl-warning {
|
||||
color: #FFF;
|
||||
background: #F39C12; }
|
||||
.growl .growl-close {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-size: 14px;
|
||||
line-height: 18px;
|
||||
font-weight: normal;
|
||||
font-family: helvetica, verdana, sans-serif; }
|
||||
.growl .growl-title {
|
||||
font-size: 18px;
|
||||
line-height: 24px; }
|
||||
.growl .growl-message {
|
||||
font-size: 14px;
|
||||
line-height: 18px; }
|
244
webif/html/lib/jquery.plugin/growl/jquery.growl.js
Normal file
244
webif/html/lib/jquery.plugin/growl/jquery.growl.js
Normal file
@ -0,0 +1,244 @@
|
||||
// Generated by CoffeeScript 1.9.3
|
||||
|
||||
/*
|
||||
jQuery Growl
|
||||
Copyright 2015 Kevin Sylvestre
|
||||
1.3.1
|
||||
*/
|
||||
|
||||
(function() {
|
||||
"use strict";
|
||||
var $, Animation, Growl,
|
||||
bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
|
||||
|
||||
$ = jQuery;
|
||||
|
||||
Animation = (function() {
|
||||
function Animation() {}
|
||||
|
||||
Animation.transitions = {
|
||||
"webkitTransition": "webkitTransitionEnd",
|
||||
"mozTransition": "mozTransitionEnd",
|
||||
"oTransition": "oTransitionEnd",
|
||||
"transition": "transitionend"
|
||||
};
|
||||
|
||||
Animation.transition = function($el) {
|
||||
var el, ref, result, type;
|
||||
el = $el[0];
|
||||
ref = this.transitions;
|
||||
for (type in ref) {
|
||||
result = ref[type];
|
||||
if (el.style[type] != null) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return Animation;
|
||||
|
||||
})();
|
||||
|
||||
Growl = (function() {
|
||||
Growl.settings = {
|
||||
namespace: 'growl',
|
||||
duration: 3200,
|
||||
close: "×",
|
||||
location: "default",
|
||||
style: "default",
|
||||
size: "medium"
|
||||
};
|
||||
|
||||
Growl.growl = function(settings) {
|
||||
if (settings == null) {
|
||||
settings = {};
|
||||
}
|
||||
this.initialize();
|
||||
return new Growl(settings);
|
||||
};
|
||||
|
||||
Growl.initialize = function() {
|
||||
return $("body:not(:has(#growls))").append('<div id="growls" />');
|
||||
};
|
||||
|
||||
function Growl(settings) {
|
||||
if (settings == null) {
|
||||
settings = {};
|
||||
}
|
||||
this.container = bind(this.container, this);
|
||||
this.content = bind(this.content, this);
|
||||
this.html = bind(this.html, this);
|
||||
this.$growl = bind(this.$growl, this);
|
||||
this.$growls = bind(this.$growls, this);
|
||||
this.animate = bind(this.animate, this);
|
||||
this.remove = bind(this.remove, this);
|
||||
this.dismiss = bind(this.dismiss, this);
|
||||
this.present = bind(this.present, this);
|
||||
this.cycle = bind(this.cycle, this);
|
||||
this.close = bind(this.close, this);
|
||||
this.click = bind(this.click, this);
|
||||
this.unbind = bind(this.unbind, this);
|
||||
this.bind = bind(this.bind, this);
|
||||
this.render = bind(this.render, this);
|
||||
this.settings = $.extend({}, Growl.settings, settings);
|
||||
this.$growls().attr('class', this.settings.location);
|
||||
this.render();
|
||||
}
|
||||
|
||||
Growl.prototype.render = function() {
|
||||
var $growl;
|
||||
$growl = this.$growl();
|
||||
this.$growls().append($growl);
|
||||
if (this.settings.fixed) {
|
||||
this.present();
|
||||
} else {
|
||||
this.cycle();
|
||||
}
|
||||
};
|
||||
|
||||
Growl.prototype.bind = function($growl) {
|
||||
if ($growl == null) {
|
||||
$growl = this.$growl();
|
||||
}
|
||||
$growl.on("click", this.click);
|
||||
return $growl.on("contextmenu", this.close).find("." + this.settings.namespace + "-close").on("click", this.close);
|
||||
};
|
||||
|
||||
Growl.prototype.unbind = function($growl) {
|
||||
if ($growl == null) {
|
||||
$growl = this.$growl();
|
||||
}
|
||||
$growl.off("click", this.click);
|
||||
return $growl.off("contextmenu", this.close).find("." + this.settings.namespace + "-close").off("click", this.close);
|
||||
};
|
||||
|
||||
Growl.prototype.click = function(event) {
|
||||
if (this.settings.url != null) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
return window.open(this.settings.url);
|
||||
}
|
||||
};
|
||||
|
||||
Growl.prototype.close = function(event) {
|
||||
var $growl;
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
$growl = this.$growl();
|
||||
return $growl.stop().queue(this.dismiss).queue(this.remove);
|
||||
};
|
||||
|
||||
Growl.prototype.cycle = function() {
|
||||
var $growl;
|
||||
$growl = this.$growl();
|
||||
return $growl.queue(this.present).delay(this.settings.duration).queue(this.dismiss).queue(this.remove);
|
||||
};
|
||||
|
||||
Growl.prototype.present = function(callback) {
|
||||
var $growl;
|
||||
$growl = this.$growl();
|
||||
this.bind($growl);
|
||||
return this.animate($growl, this.settings.namespace + "-incoming", 'out', callback);
|
||||
};
|
||||
|
||||
Growl.prototype.dismiss = function(callback) {
|
||||
var $growl;
|
||||
$growl = this.$growl();
|
||||
this.unbind($growl);
|
||||
return this.animate($growl, this.settings.namespace + "-outgoing", 'in', callback);
|
||||
};
|
||||
|
||||
Growl.prototype.remove = function(callback) {
|
||||
this.$growl().remove();
|
||||
return callback();
|
||||
};
|
||||
|
||||
Growl.prototype.animate = function($element, name, direction, callback) {
|
||||
var transition;
|
||||
if (direction == null) {
|
||||
direction = 'in';
|
||||
}
|
||||
transition = Animation.transition($element);
|
||||
$element[direction === 'in' ? 'removeClass' : 'addClass'](name);
|
||||
$element.offset().position;
|
||||
$element[direction === 'in' ? 'addClass' : 'removeClass'](name);
|
||||
if (callback == null) {
|
||||
return;
|
||||
}
|
||||
if (transition != null) {
|
||||
$element.one(transition, callback);
|
||||
} else {
|
||||
callback();
|
||||
}
|
||||
};
|
||||
|
||||
Growl.prototype.$growls = function() {
|
||||
return this.$_growls != null ? this.$_growls : this.$_growls = $('#growls');
|
||||
};
|
||||
|
||||
Growl.prototype.$growl = function() {
|
||||
return this.$_growl != null ? this.$_growl : this.$_growl = $(this.html());
|
||||
};
|
||||
|
||||
Growl.prototype.html = function() {
|
||||
return this.container(this.content());
|
||||
};
|
||||
|
||||
Growl.prototype.content = function() {
|
||||
return "<div class='" + this.settings.namespace + "-close'>" + this.settings.close + "</div>\n<div class='" + this.settings.namespace + "-title'>" + this.settings.title + "</div>\n<div class='" + this.settings.namespace + "-message'>" + this.settings.message + "</div>";
|
||||
};
|
||||
|
||||
Growl.prototype.container = function(content) {
|
||||
return "<div class='" + this.settings.namespace + " " + this.settings.namespace + "-" + this.settings.style + " " + this.settings.namespace + "-" + this.settings.size + "'>\n " + content + "\n</div>";
|
||||
};
|
||||
|
||||
return Growl;
|
||||
|
||||
})();
|
||||
|
||||
this.Growl = Growl;
|
||||
|
||||
$.growl = function(options) {
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
return Growl.growl(options);
|
||||
};
|
||||
|
||||
$.growl.error = function(options) {
|
||||
var settings;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
settings = {
|
||||
title: "Error!",
|
||||
style: "error"
|
||||
};
|
||||
return $.growl($.extend(settings, options));
|
||||
};
|
||||
|
||||
$.growl.notice = function(options) {
|
||||
var settings;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
settings = {
|
||||
title: "Notice!",
|
||||
style: "notice"
|
||||
};
|
||||
return $.growl($.extend(settings, options));
|
||||
};
|
||||
|
||||
$.growl.warning = function(options) {
|
||||
var settings;
|
||||
if (options == null) {
|
||||
options = {};
|
||||
}
|
||||
settings = {
|
||||
title: "Warning!",
|
||||
style: "warning"
|
||||
};
|
||||
return $.growl($.extend(settings, options));
|
||||
};
|
||||
|
||||
}).call(this);
|
3
webif/html/lib/jquery.plugin/qtip/jquery.qtip.min.css
vendored
Normal file
3
webif/html/lib/jquery.plugin/qtip/jquery.qtip.min.css
vendored
Normal file
File diff suppressed because one or more lines are too long
5
webif/html/lib/jquery.plugin/qtip/jquery.qtip.min.js
vendored
Normal file
5
webif/html/lib/jquery.plugin/qtip/jquery.qtip.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
21
webif/html/lib/noheader.jim
Executable file
21
webif/html/lib/noheader.jim
Executable file
@ -0,0 +1,21 @@
|
||||
#!/mod/bin/jimsh
|
||||
|
||||
source /mod/webif/lib/setup
|
||||
require system.class
|
||||
|
||||
puts {
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv=X-UA-Compatible content="IE=edge,chrome=1" />
|
||||
}
|
||||
|
||||
incr ::mws::headerdone
|
||||
::mws::emit_jscss
|
||||
|
||||
puts {
|
||||
</head>
|
||||
<body>
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ set file [file tail [cgi_get file \
|
||||
[clock format $now -format "auto-%Y-%b-%d-%H:%M"]]]
|
||||
|
||||
if {[string match {auto-*} $file]} {
|
||||
# Delete any automatic backups over 7 days old.
|
||||
# Delete any automatic backups over 15 days old.
|
||||
set mt $(15 * 86400)
|
||||
foreach af [glob -nocomplain "$dir/auto-*"] {
|
||||
set aft [file mtime $af]
|
@ -1,13 +1,12 @@
|
||||
#!/mod/bin/jimsh
|
||||
|
||||
source /mod/webif/lib/setup
|
||||
require altrow rsv.class
|
||||
require rsv.class
|
||||
|
||||
jscss backup.js
|
||||
header
|
||||
noheader
|
||||
|
||||
puts {
|
||||
<h2>Backup/Restore</h2>
|
||||
<h2>Recording Schedule Backup & Restore</h2>
|
||||
|
||||
<div id=restore_warning class="hidden warningbox">
|
||||
<div>
|
||||
@ -60,7 +59,7 @@ puts {
|
||||
</div>
|
||||
|
||||
|
||||
<div id=results class=pre
|
||||
<div id=backup_results class=pre
|
||||
style="display: none; clear: both; float: left; padding: 1em;
|
||||
margin-top: 1em; border: 1px solid grey; width: 70%">
|
||||
</div>
|
72
webif/html/sched/backup/script.js
Executable file
72
webif/html/sched/backup/script.js
Executable file
@ -0,0 +1,72 @@
|
||||
|
||||
function refresh_backup_files()
|
||||
{
|
||||
$('#backup_files').load('backup/files.jim', function() {
|
||||
$('input.restore').change(function() {
|
||||
$('#restore_button').removeAttr('disabled')
|
||||
.button('option', 'disabled', false);
|
||||
$('#delete_button').removeAttr('disabled')
|
||||
.button('option', 'disabled', false);
|
||||
$('#view_button').removeAttr('disabled')
|
||||
.button('option', 'disabled', false);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function backup_loaded()
|
||||
{
|
||||
|
||||
$('button').button();
|
||||
|
||||
refresh_backup_files();
|
||||
|
||||
$('#backup_button').click(function() {
|
||||
$('#backup_working').slideDown();
|
||||
$('#backup_results').load('backup/backup.jim?' +
|
||||
$('#backup_name').serialize(), function() {
|
||||
$('#backup_results').slideDown(function() {
|
||||
$('#backup_working').slideUp();
|
||||
refresh_backup_files();
|
||||
});
|
||||
});
|
||||
});
|
||||
$('#delete_button').click(function() {
|
||||
var backup = $('input.restore:checked').val();
|
||||
if (confirm('Confirm deletion of ' + backup))
|
||||
{
|
||||
$('#backup_results').load('backup/delete.jim?' +
|
||||
$('input.restore').serialize(), function() {
|
||||
$('#backup_results').slideDown(function() {
|
||||
refresh_backup_files();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
$('#view_button').click(function() {
|
||||
var backup = $('input.restore:checked').val();
|
||||
$('#backup_results').load('backup/view.jim?' +
|
||||
$('input.restore').serialize(), function() {
|
||||
$('#backup_results').slideDown(function() {
|
||||
refresh_backup_files();
|
||||
});
|
||||
});
|
||||
});
|
||||
$('#restore_button').click(function() {
|
||||
var backup = $('input.restore:checked').val();
|
||||
if (confirm('!!!!!!!!!!!!!!!!!!!!!!!!! PLEASE CONFIRM !!!!!!!!!!!!!!!!!!!!!!!!!\n\nAre you sure you wish to erase all scheduled recordings and favourite channels and then restore them from\n' + backup + '?'))
|
||||
{
|
||||
$('#restore_working').slideDown();
|
||||
$('#backup_results').load('backup/restore.jim?' +
|
||||
$('input.restore').serialize(), function() {
|
||||
$('#backup_results').slideDown(function() {
|
||||
$('#restore_working').slideUp();
|
||||
refresh_backup_files();
|
||||
$('#restore_warning').slideDown();
|
||||
$('#restart_block').slideDown('slow');
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -52,7 +52,8 @@ foreach line $data {
|
||||
|
||||
set rsv [rsv new $vars]
|
||||
|
||||
puts " [$rsv name] ([$rsv channel_name])"
|
||||
puts " [$rsv name] ([$rsv channel_name] [\
|
||||
clock format [$rsv start]] - [clock format [$rsv end]])"
|
||||
}
|
||||
|
||||
close $fd
|
@ -2,281 +2,31 @@
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require altrow rsv.class progressbar epg.class system.class
|
||||
|
||||
jqplugin tablesorter2 contextMenu form blockui confirmAction \
|
||||
timepicker datepair
|
||||
jscss script.js
|
||||
timepicker datepair growl qtip
|
||||
|
||||
jscss {
|
||||
/js/icons.js
|
||||
list/script.js
|
||||
visual/script.js
|
||||
backup/script.js
|
||||
script.js
|
||||
} visual/style.css
|
||||
|
||||
header
|
||||
|
||||
set svcmap {}
|
||||
lmap i \
|
||||
[$::channeldb query {select hSvc, usSvcid from TBL_SVC}] \
|
||||
{
|
||||
set svcmap([lindex $i 1]) [lindex $i 3]
|
||||
}
|
||||
set svckeys [array names svcmap]
|
||||
|
||||
require epg_popup
|
||||
# Prevent render time being shown in footer
|
||||
unset renderstart
|
||||
|
||||
puts {
|
||||
<div id=output class=hidden></div>
|
||||
<div id=sdialogue></div>
|
||||
<div id=minimaltabbar>
|
||||
<ul>
|
||||
<li><a href=list/>Recording List</a></li>
|
||||
<li><a href=visual/>Visual Schedule</a></li>
|
||||
<li><a href=backup/>Backup/Restore</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
proc eventheader {{table TBL_RESERVATION} note} {
|
||||
if {$table eq "pending"} {
|
||||
set sortlist {[[6,0]]}
|
||||
} else {
|
||||
set sortlist {[[5,0]]}
|
||||
}
|
||||
|
||||
puts {
|
||||
<fieldset id=sched_fs_$table
|
||||
style="display: inline; padding: 1em">
|
||||
<legend>
|
||||
}
|
||||
puts "<h3>$note</h3>"
|
||||
puts "
|
||||
</legend>
|
||||
<table class=\"schedule tablesorter\" data-sortlist=\"$sortlist\">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-sorter=false> </th>
|
||||
"
|
||||
|
||||
if {$table eq "pending"} { puts "<th>Action</th>" }
|
||||
|
||||
puts {
|
||||
<th> </th>
|
||||
<th data-sorter=false> </th>
|
||||
<th>Channel</th>
|
||||
<th data-sorter=programme>Programme</th>
|
||||
<th data-sorter=xdate>Start Time</th>
|
||||
<th>Duration</th>
|
||||
<th data-sorter=false>Mode</th>
|
||||
<th data-sorter=false> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
}
|
||||
}
|
||||
|
||||
proc eventrow {event {table TBL_RESERVATION} {pending 0}} {
|
||||
global svcmap svckeys num_ended
|
||||
|
||||
set name [$event name]
|
||||
|
||||
set s [$event start]
|
||||
set d [$event get nduration]
|
||||
set e $($s + $d)
|
||||
set n [clock seconds]
|
||||
|
||||
if {$n > $e && [$event get ersvtype] <= 3} {
|
||||
set ended 1
|
||||
incr num_ended
|
||||
} else {
|
||||
set ended 0
|
||||
}
|
||||
|
||||
set attrs "table=$table sid=[$event get ulslot] \
|
||||
reckind=[$event get ucRecKind] rsvtype=[$event get ersvtype] \
|
||||
ar=[expr ! [$event padded]] ended=$ended"
|
||||
if {$pending} {
|
||||
append attrs " class=\"blueshade strike\""
|
||||
}
|
||||
altrow $attrs
|
||||
#puts "<tr $attrs>"
|
||||
|
||||
# Checkbox
|
||||
puts "<td><input type=checkbox class=schedselect></td>";
|
||||
|
||||
if {$table eq "pending"} {
|
||||
puts "<td align=center>[$event pendingicon]</td>"
|
||||
}
|
||||
|
||||
puts "<td>[$event get ulslot]</td>"
|
||||
|
||||
if {[$event get usLcn] ne ""} {
|
||||
puts "
|
||||
<td>
|
||||
[epg channelicon [$event channel_name] 50]
|
||||
</td>
|
||||
<td nowrap>[$event get usLcn]<br>
|
||||
[$event channel_name]</td>
|
||||
"
|
||||
} else {
|
||||
puts "<td> <br><br></td><td> </td>"
|
||||
}
|
||||
|
||||
puts "<td nowrap>
|
||||
<a slot=[$event get ulslot] table=$table
|
||||
href=# class=schedule>$name</a>"
|
||||
if {
|
||||
([$event get ucRecKind] == 4 && $name ne [$event folder]) ||
|
||||
([$event get ucRecKind] == 1 && [$event folder] ne "")
|
||||
} {
|
||||
puts "<br><span class=also> (Folder: [$event folder])</span>"
|
||||
}
|
||||
|
||||
puts "</td>"
|
||||
|
||||
if {$ended} {
|
||||
set ds "[clock format $s -format {%a %d %b %Y %H:%M}]"
|
||||
puts "<td nowrap class=va>
|
||||
--- -- --- ---- --:--<br>
|
||||
<span class=footnote>(Last: $ds)</span>"
|
||||
puts "</td><td>--:--:--</td>"
|
||||
} else {
|
||||
set elist [$event aul]
|
||||
set ds "[clock format $s -format {%a %d %b %Y %H:%M}]"
|
||||
puts "<td nowrap class=\"va"
|
||||
if {$n > $e} { puts " blood" }
|
||||
puts "\">"
|
||||
|
||||
if {[llength $elist] > 0} {
|
||||
lassign [lindex $elist 0] service_id start end event_id
|
||||
if {$start == $s && $service_id in $svckeys} {
|
||||
puts "<a class=event href=#
|
||||
xs=$svcmap($service_id) xe=$event_id>
|
||||
<span class=ds>$ds</span></a>"
|
||||
} else {
|
||||
puts "<span class=ds>$ds</span>"
|
||||
}
|
||||
} else {
|
||||
puts "<span class=ds>$ds</span>"
|
||||
}
|
||||
|
||||
if {$d > 0 && $n > $s && $n < $e} {
|
||||
puts "<br>"
|
||||
set perc [expr [expr $n - $s] * 100 / $d]
|
||||
puts "<img class=va
|
||||
src=/images/745_1_11_Video_1REC.png>"
|
||||
puts [progressbar $perc]
|
||||
}
|
||||
|
||||
if {[llength $elist] > 1} {
|
||||
puts "<div class=also style=\"margin-top: 0.5em\">"
|
||||
foreach e $elist {
|
||||
lassign $e service_id start end event_id
|
||||
if {$start == $s} continue
|
||||
if {$service_id in $svckeys} {
|
||||
puts "<a class=event href=#
|
||||
xs=$svcmap($service_id) xe=$event_id>
|
||||
[clock format $start \
|
||||
-format {%a %d %b %Y %H:%M}]</a>"
|
||||
if {$service_id != [$event get hsvc]} {
|
||||
set ch [system strip [\
|
||||
get_channel_attr_byhsvc \
|
||||
$service_id szSvcName]]
|
||||
puts "<img width=15 src=\"[\
|
||||
epg channeliconpath $ch]\""
|
||||
puts "title=\"$ch\" alt=\"$ch\">"
|
||||
}
|
||||
puts "<br>"
|
||||
} else {
|
||||
puts "[clock format $start \
|
||||
-format {%a %d %b %Y %H:%M}]
|
||||
($service_id)<br>"
|
||||
}
|
||||
}
|
||||
puts "</div>";
|
||||
}
|
||||
|
||||
puts "</td><td align=center>"
|
||||
set xndur [$event get nduration]
|
||||
if {$xndur > 0} {
|
||||
puts "[clock format $xndur -format %H:%M]"
|
||||
} else {
|
||||
puts "--:--:--"
|
||||
}
|
||||
if {[llength $elist] > 1} {
|
||||
puts "<div class=also style=\"margin-top: 0.5em\">"
|
||||
foreach e $elist {
|
||||
lassign $e service_id start end event_id
|
||||
if {$start == $s} continue
|
||||
puts "[clock format $($end - $start) \
|
||||
-format {%H:%M}]<br>"
|
||||
}
|
||||
puts "</div>";
|
||||
}
|
||||
|
||||
puts "</td>"
|
||||
}
|
||||
|
||||
puts "<td nowrap>[join [$event iconset] ""]</td>"
|
||||
|
||||
puts "<td><a href=# class=smenu sid=[$event get ulslot]>
|
||||
<img border=0 src=/img/more_btn.gif></a></td>"
|
||||
puts "</tr>"
|
||||
}
|
||||
|
||||
proc eventfooter {rawlink} {
|
||||
global num_ended
|
||||
|
||||
puts "</tbody></table>"
|
||||
puts "
|
||||
<br>
|
||||
<button class=selall>Select All</button>
|
||||
<button class=selnone>Select None</button>
|
||||
"
|
||||
if {$num_ended} {
|
||||
puts "
|
||||
<button class=selended>Select Finished</button>
|
||||
"
|
||||
}
|
||||
puts "
|
||||
<button class=\"delselected red\">Delete Selected
|
||||
<span class=delselcnt></span>
|
||||
</button>
|
||||
<button class=\"manual_rsv blue\">Manual Event</button>
|
||||
<button class=rawview
|
||||
path=\"$rawlink\"
|
||||
>Raw Database</button>
|
||||
</fieldset>
|
||||
"
|
||||
}
|
||||
|
||||
proc ekey {event} {
|
||||
set ret ""
|
||||
foreach key {ersvtype nsttime nduration hsvc usevtid} {
|
||||
append ret ".[$event get $key]"
|
||||
}
|
||||
return $ret
|
||||
}
|
||||
|
||||
set pmap {}
|
||||
set events [rsv list pending]
|
||||
set num_ended 0
|
||||
if {[llength $events] > 0} {
|
||||
eventheader pending "Pending Actions"
|
||||
foreach event $events {
|
||||
eventrow $event pending
|
||||
lappend pmap [ekey $event]
|
||||
}
|
||||
eventfooter "db=rsvp.db&tab=pending"
|
||||
}
|
||||
|
||||
set events [rsv list]
|
||||
set num_ended 0
|
||||
eventheader live "Scheduled Events"
|
||||
foreach event $events {
|
||||
if {[ekey $event] in $pmap} {
|
||||
eventrow $event TBL_RESERVATION 1
|
||||
} else {
|
||||
eventrow $event
|
||||
}
|
||||
}
|
||||
eventfooter "db=rsv.db&tab=TBL_RESERVATION"
|
||||
|
||||
puts {
|
||||
<br><br>
|
||||
<button class=backup>
|
||||
Backup/Restore Scheduled Recordings/Events
|
||||
</button>
|
||||
}
|
||||
|
||||
source assets.jim
|
||||
|
||||
footer
|
||||
|
||||
|
@ -1,5 +1,7 @@
|
||||
#!/mod/bin/jimsh
|
||||
|
||||
puts "<div id=sdialogue></div>"
|
||||
|
||||
lassign [system padding] pre post
|
||||
|
||||
proc padval {num str def} {
|
||||
@ -14,12 +16,13 @@ puts {
|
||||
<ul id=optmenu class=contextMenu style="width: 200px">
|
||||
<li class=delete><a href=#delete>Delete</a></li>
|
||||
<li class=separator><a href=#ar>Enable AR</a></li>
|
||||
<li class=separator><a href=#refresh>Refresh Events</a></li>
|
||||
<li class=separator><a href=#folder>Change Folder</a></li>
|
||||
<li class=separator><a href=#mkfolder>Create Folder</a></li>
|
||||
</ul>
|
||||
|
||||
<div id=padding style="display: none">
|
||||
<form id=paddingf method=post action=pad.jim>
|
||||
<form id=paddingf method=post action=rpc/pad.jim>
|
||||
<input type=hidden id=paddingsid name=slot value=0>
|
||||
<table class=keyval>
|
||||
<tr>
|
353
webif/html/sched/list/index.jim
Executable file
353
webif/html/sched/list/index.jim
Executable file
@ -0,0 +1,353 @@
|
||||
#!/mod/bin/jimsh
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require altrow rsv.class progressbar epg.class system.class
|
||||
|
||||
noheader
|
||||
set renderstart [clock milliseconds]
|
||||
|
||||
set svcmap {}
|
||||
lmap i \
|
||||
[$::channeldb query {select hSvc, usSvcid from TBL_SVC}] \
|
||||
{
|
||||
set svcmap([lindex $i 1]) [lindex $i 3]
|
||||
}
|
||||
set svckeys [array names svcmap]
|
||||
|
||||
set conflictstart [clock milliseconds]
|
||||
set conflicts [rsv newconflicts [system tuners] "xlist"]
|
||||
set conflicttime [expr ([clock milliseconds] - $conflictstart) / 1000.0]
|
||||
|
||||
if {[llength $conflicts] > 1} {
|
||||
puts "<div class=warningbox><div><center>
|
||||
Your recording schedule contains conflicts; shown in pink below.
|
||||
</center></div></div>"
|
||||
}
|
||||
|
||||
require epg_popup
|
||||
|
||||
set pkey_tags {
|
||||
1 "Pending unschedule"
|
||||
2 "Pending padding change"
|
||||
3 "Pending padding change"
|
||||
4 "Pending folder change"
|
||||
5 "Pending episode skip"
|
||||
6 "Pending refresh"
|
||||
}
|
||||
|
||||
proc eventheader {{table TBL_RESERVATION} note} {
|
||||
if {$table eq "pending"} {
|
||||
set sortlist {[[6,0]]}
|
||||
} else {
|
||||
set sortlist {[[5,0]]}
|
||||
}
|
||||
|
||||
puts "
|
||||
<fieldset id=sched_fs_$table
|
||||
style=\"display: inline; padding: 1em\">
|
||||
<legend>
|
||||
"
|
||||
puts "<h3>$note</h3>"
|
||||
puts "
|
||||
</legend>
|
||||
<table class=\"schedule tablesorter\" data-sortlist=\"$sortlist\">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-sorter=false> </th>
|
||||
"
|
||||
|
||||
if {$table eq "pending"} { puts "<th>Action</th>" }
|
||||
|
||||
puts {
|
||||
<th> </th>
|
||||
<th data-sorter=false> </th>
|
||||
<th>Channel</th>
|
||||
<th data-sorter=programme>Programme</th>
|
||||
<th data-sorter=xdate>Start Time</th>
|
||||
<th>Duration</th>
|
||||
<th data-sorter=false>Mode</th>
|
||||
<th data-sorter=false> </th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
}
|
||||
}
|
||||
|
||||
proc eventrow {event {table TBL_RESERVATION}} {
|
||||
global svcmap svckeys num_ended conflicts pmap pkey_tags
|
||||
|
||||
set name [$event name]
|
||||
|
||||
set s [$event start]
|
||||
set d [$event get nduration]
|
||||
set e $($s + $d)
|
||||
set n [clock seconds]
|
||||
|
||||
if {$n > $e && [$event get ersvtype] <= 3} {
|
||||
set ended 1
|
||||
incr num_ended
|
||||
} else {
|
||||
set ended 0
|
||||
}
|
||||
|
||||
set attrs "table=$table sid=[$event get ulslot] \
|
||||
reckind=[$event get ucRecKind] rsvtype=[$event get ersvtype] \
|
||||
ar=[expr ! [$event padded]] ended=$ended"
|
||||
|
||||
set ek [ekey $event]
|
||||
set opts 1
|
||||
set tag ""
|
||||
if {[dict exists $pmap $ek]} {
|
||||
set act $pmap($ek)
|
||||
|
||||
switch $act {
|
||||
1 -
|
||||
5 {
|
||||
append attrs " class=\"blueshade strike\""
|
||||
set opts 0
|
||||
}
|
||||
2 -
|
||||
3 -
|
||||
4 {
|
||||
set opts 0
|
||||
append attrs " class=orangeshade"
|
||||
}
|
||||
6 {
|
||||
append attrs " class=orangeshade"
|
||||
}
|
||||
}
|
||||
if {[dict exists $pkey_tags $act]} {
|
||||
set tag $pkey_tags($act)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
altrow $attrs
|
||||
|
||||
# Checkbox
|
||||
puts "<td><input type=checkbox class=schedselect></td>";
|
||||
|
||||
if {$table eq "pending"} {
|
||||
puts "<td align=center>[$event pendingicon]</td>"
|
||||
}
|
||||
|
||||
puts "<td>[$event get ulslot]</td>"
|
||||
|
||||
if {[$event get usLcn] ne ""} {
|
||||
puts "
|
||||
<td>
|
||||
[epg channelicon [$event channel_name] 50]
|
||||
</td>
|
||||
<td nowrap>[$event get usLcn]<br>
|
||||
[$event channel_name]</td>
|
||||
"
|
||||
} else {
|
||||
puts "<td> <br><br></td><td> </td>"
|
||||
}
|
||||
|
||||
puts "<td nowrap>
|
||||
<a slot=[$event get ulslot] table=$table
|
||||
href=# class=schedule>$name</a>"
|
||||
if {
|
||||
([$event get ucRecKind] == 4 && $name ne [$event folder]) ||
|
||||
([$event get ucRecKind] == 1 && [$event folder] ne "")
|
||||
} {
|
||||
puts "<br><span class=also> (Folder: [$event folder])</span>"
|
||||
}
|
||||
|
||||
if {$tag ne ""} {
|
||||
puts "<br><span class=blood> $tag</span>"
|
||||
}
|
||||
|
||||
puts "</td>"
|
||||
|
||||
if {$ended} {
|
||||
set ds "[clock format $s -format {%a %d %b %Y %H:%M}]"
|
||||
puts "<td nowrap class=va>
|
||||
--- -- --- ---- --:--<br>
|
||||
<span class=footnote>(Last: $ds)</span>"
|
||||
puts "</td><td>--:--:--</td>"
|
||||
} else {
|
||||
set elist [$event aul]
|
||||
set ds "[clock format $s -format {%a %d %b %Y %H:%M}]"
|
||||
puts "<td nowrap class=\"va"
|
||||
if {$n > $e} { puts -nonewline " blood" }
|
||||
if {"[$event get ulslot][$event end]" in $conflicts} {
|
||||
puts -nonewline " pinkshade"
|
||||
}
|
||||
puts "\">"
|
||||
|
||||
if {[llength $elist] > 0} {
|
||||
lassign [lindex $elist 0] service_id start end event_id
|
||||
if {$start == $s && $service_id in $svckeys} {
|
||||
puts "<a class=event href=#
|
||||
xs=$svcmap($service_id) xe=$event_id>
|
||||
<span class=ds>$ds</span></a>"
|
||||
} else {
|
||||
puts "<span class=ds>$ds</span>"
|
||||
}
|
||||
} else {
|
||||
puts "<span class=ds>$ds</span>"
|
||||
}
|
||||
|
||||
if {$d > 0 && $n > $s && $n < $e} {
|
||||
puts "<br>"
|
||||
set perc [expr [expr $n - $s] * 100 / $d]
|
||||
puts "<img class=va
|
||||
src=/images/745_1_11_Video_1REC.png>"
|
||||
puts [progressbar $perc]
|
||||
}
|
||||
|
||||
if {[llength $elist] > 1} {
|
||||
set i 0
|
||||
set c [llength $elist]
|
||||
set max 5
|
||||
foreach e $elist {
|
||||
lassign $e service_id start end event_id
|
||||
if {$start == $s} continue
|
||||
|
||||
if {[incr i] == $max} {
|
||||
set remain $($c - $i)
|
||||
puts "
|
||||
<div class=\"moretoshow footnote\">
|
||||
<center>
|
||||
Click for $remain more...
|
||||
</center>
|
||||
</div>
|
||||
<div class=\"hidden moretoshowc\">
|
||||
"
|
||||
} else {
|
||||
puts "<br>"
|
||||
}
|
||||
|
||||
set xcl "also"
|
||||
if {"[$event get ulslot]${end}" in $conflicts} {
|
||||
append xcl " pinkshade"
|
||||
}
|
||||
|
||||
puts "<span class=\"$xcl\">"
|
||||
if {$service_id in $svckeys} {
|
||||
puts "<a class=event href=#
|
||||
xs=$svcmap($service_id) xe=$event_id>
|
||||
[clock format $start \
|
||||
-format {%a %d %b %Y %H:%M}]</a>"
|
||||
if {$service_id != [$event get hsvc]} {
|
||||
set ch [system strip [\
|
||||
get_channel_attr_byhsvc \
|
||||
$service_id szSvcName]]
|
||||
puts "<img width=15 src=\"[\
|
||||
epg channeliconpath $ch]\""
|
||||
puts "title=\"$ch\" alt=\"$ch\">"
|
||||
}
|
||||
} else {
|
||||
puts "[clock format $start \
|
||||
-format {%a %d %b %Y %H:%M}]
|
||||
($service_id)<br>"
|
||||
}
|
||||
puts "</span>"
|
||||
}
|
||||
if {$i >= $max} {
|
||||
puts "</div>"
|
||||
}
|
||||
}
|
||||
|
||||
puts "</td><td align=center>"
|
||||
set xndur [$event get nduration]
|
||||
if {$xndur > 0} {
|
||||
puts "[clock format $xndur -format %H:%M]"
|
||||
} else {
|
||||
puts "--:--:--"
|
||||
}
|
||||
if {[llength $elist] > 1} {
|
||||
set i 0
|
||||
foreach e $elist {
|
||||
lassign $e service_id start end event_id
|
||||
if {$start == $s} continue
|
||||
if {[incr i] == $max} {
|
||||
puts "<div class=\"hidden moretoshowc\">"
|
||||
} else {
|
||||
puts "<br>"
|
||||
}
|
||||
puts "<span class=also>
|
||||
[clock format $($end - $start) \
|
||||
-format {%H:%M}]</span>"
|
||||
}
|
||||
if {$i >= $max} {
|
||||
puts "</div>"
|
||||
}
|
||||
}
|
||||
|
||||
puts "</td>"
|
||||
}
|
||||
|
||||
puts "<td nowrap>[join [$event iconset] ""]</td>"
|
||||
|
||||
puts "<td>"
|
||||
if {$opts} {
|
||||
puts "<a href=# class=smenu sid=[$event get ulslot]>
|
||||
<img border=0 src=/img/more_btn.gif></a>"
|
||||
}
|
||||
puts "</td></tr>"
|
||||
}
|
||||
|
||||
proc eventfooter {rawlink} {
|
||||
global num_ended
|
||||
|
||||
puts "</tbody></table>"
|
||||
puts "
|
||||
<br>
|
||||
<button class=selall>Select All</button>
|
||||
<button class=selnone>Select None</button>
|
||||
"
|
||||
if {$num_ended} {
|
||||
puts "
|
||||
<button class=selended>Select Finished</button>
|
||||
"
|
||||
}
|
||||
puts "
|
||||
<button class=\"delselected red\">Delete Selected
|
||||
<span class=delselcnt></span>
|
||||
</button>
|
||||
<button class=\"manual_rsv blue\">Manual Event</button>
|
||||
<button class=rawview
|
||||
path=\"$rawlink\"
|
||||
>Raw Database</button>
|
||||
</fieldset>
|
||||
"
|
||||
}
|
||||
|
||||
proc ekey {event} {
|
||||
set ret ""
|
||||
foreach key {ersvtype nsttime nduration hsvc usevtid} {
|
||||
append ret ".[$event get $key]"
|
||||
}
|
||||
return $ret
|
||||
}
|
||||
|
||||
set pmap {}
|
||||
set events [rsv list pending]
|
||||
set num_ended 0
|
||||
if {[llength $events] > 0} {
|
||||
eventheader pending "Pending Actions"
|
||||
foreach event $events {
|
||||
eventrow $event pending
|
||||
set pmap([ekey $event]) [$event get action]
|
||||
}
|
||||
eventfooter "db=rsvp.db&tab=pending"
|
||||
}
|
||||
|
||||
set events [rsv list]
|
||||
set num_ended 0
|
||||
eventheader live "Scheduled Events"
|
||||
foreach event $events {
|
||||
eventrow $event TBL_RESERVATION
|
||||
}
|
||||
eventfooter "db=rsv.db&tab=TBL_RESERVATION"
|
||||
|
||||
source assets.jim
|
||||
|
||||
puts "<div class=footnote>Conflict evaluation: $conflicttime seconds</div>"
|
||||
|
||||
footer
|
||||
|
439
webif/html/sched/list/script.js
Executable file
439
webif/html/sched/list/script.js
Executable file
@ -0,0 +1,439 @@
|
||||
|
||||
function list_loaded()
|
||||
{
|
||||
|
||||
$('table.tablesorter')
|
||||
.tablesorter({
|
||||
theme: 'webif',
|
||||
widthFixed: false,
|
||||
widgets: ['zebra', 'stickyHeaders']
|
||||
});
|
||||
|
||||
function docancel()
|
||||
{
|
||||
var table = $('#sdialogue').attr('table');
|
||||
var slot = $('#sdialogue').attr('slot');
|
||||
|
||||
if (confirm('Really remove scheduled event?'))
|
||||
{
|
||||
$.get('rpc/cancel.jim?slot=' + slot +
|
||||
'&table=' + table, function() {
|
||||
page_refresh();
|
||||
});
|
||||
$('#sdialogue').dialog('close');
|
||||
}
|
||||
}
|
||||
|
||||
var $buttons1 = {
|
||||
"Close" : function() {$(this).dialog('close');}
|
||||
};
|
||||
var $buttons2 = $.extend(
|
||||
{"Cancel Event": function() { docancel() }},
|
||||
$buttons1);
|
||||
|
||||
var $dialog = $('#sdialogue').dialog({
|
||||
title: "Schedule Details",
|
||||
modal: false, autoOpen: false,
|
||||
height: 500, width: 700,
|
||||
show: 'scale', hide: 'fade',
|
||||
draggable: true, resizable: true,
|
||||
buttons: $buttons2,
|
||||
close: function(e,u) { $('#sdialogue').empty().html(
|
||||
'<img src="/img/loading.gif" alt="loading">'); }
|
||||
});
|
||||
|
||||
function schedpopup(e, o)
|
||||
{
|
||||
e.preventDefault();
|
||||
var slot = o.attr('slot');
|
||||
var table = o.attr('table');
|
||||
$('#sdialogue').attr('slot', slot).attr('table', table);
|
||||
|
||||
var url = 'rpc/info.jim?slot=' + slot +
|
||||
'&table=' + table;
|
||||
$('#sdialogue').load(url);
|
||||
$dialog.dialog('open');
|
||||
}
|
||||
$('a.schedule').click(function(e) { schedpopup(e, $(this)) });
|
||||
|
||||
$('.schedselect:checked').prop('checked', false);
|
||||
|
||||
$('button.delselected').button({icons:{primary:"ui-icon-trash"}})
|
||||
.button('disable')
|
||||
.on('click', function() {
|
||||
$(this).dojConfirmAction({
|
||||
question: 'Delete selected?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
$.blockUI({
|
||||
message: '<h1><img src=/img/loading.gif> Deleting... </h1>'
|
||||
});
|
||||
|
||||
var els = $(el).parent().find('.schedselect:checked');
|
||||
var tab = $(els).first().closest('tr').attr('table');
|
||||
var slots = $.map(els, function(v) {
|
||||
return $(v).closest('tr').attr('sid');
|
||||
});
|
||||
$.get('rpc/cancel.jim?slot=' + slots.join(',') +
|
||||
'&table=' + tab, function() {
|
||||
page_refresh();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$('.schedselect').on('change', function() {
|
||||
var num = $(this).closest('table').find('.schedselect:checked').size();
|
||||
var but = $(this).closest('fieldset').find('button.delselected');
|
||||
if (num)
|
||||
$(but).button('enable').find('.delselcnt')
|
||||
.text('(' + num + ')');
|
||||
else
|
||||
$(but).button('disable').find('.delselcnt').empty();
|
||||
});
|
||||
|
||||
$('button.selall').button({icons:{primary:"ui-icon-check"}})
|
||||
.on('click', function() {
|
||||
$(this).parent().find('table .schedselect').prop('checked', true)
|
||||
.first().trigger('change');
|
||||
});
|
||||
|
||||
$('button.selnone').button({icons:{primary:"ui-icon-close"}})
|
||||
.on('click', function() {
|
||||
$(this).parent().find('table .schedselect').prop('checked', false)
|
||||
.first().trigger('change');
|
||||
});
|
||||
|
||||
$('button.selended').button({icons:{primary:"ui-icon-stop"}})
|
||||
.on('click', function() {
|
||||
$(this).parent().find('table .schedselect').prop('checked', false);
|
||||
$(this).parent().find('table tr[ended="1"] .schedselect')
|
||||
.prop('checked', true).first().trigger('change');
|
||||
|
||||
});
|
||||
|
||||
$('button.rawview').button({icons:{primary:"ui-icon-wrench"}})
|
||||
.on('click', function() {
|
||||
window.location = '/db/index.jim?' + $(this).attr('path');
|
||||
});
|
||||
|
||||
|
||||
// Menu
|
||||
|
||||
var $paddialog = $('#padding').dialog({
|
||||
title: "Padding values",
|
||||
modal: true, autoOpen: false,
|
||||
height: 'auto', width: 'auto',
|
||||
show: 'scale', hide: 'fade',
|
||||
draggable: false, resizable: false,
|
||||
buttons: {
|
||||
"Confirm": function() {
|
||||
$('#paddingf').ajaxSubmit({
|
||||
dataType: 'text',
|
||||
success: function(data) {
|
||||
page_refresh();
|
||||
}
|
||||
});
|
||||
},
|
||||
"Cancel": function() { $(this).dialog('close'); }
|
||||
}
|
||||
});
|
||||
|
||||
$('#fchange').dialog({
|
||||
autoOpen: false,
|
||||
height: 'auto', width: 'auto',
|
||||
modal: true,
|
||||
buttons: {
|
||||
"Update": function() {
|
||||
var s = $('#fchangeform').serialize();
|
||||
$.get('rpc/folder.jim?' + s,
|
||||
function() { page_refresh(); });
|
||||
},
|
||||
"Close": function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
},
|
||||
close: function() {
|
||||
$('#changeslot').val(0);
|
||||
$('#fchangename').val('');
|
||||
}
|
||||
});
|
||||
|
||||
function preparemenu(el, menu)
|
||||
{
|
||||
if (!$(el).is("tr"))
|
||||
el = $(el).closest('tr');
|
||||
|
||||
table = $(el).attr('table');
|
||||
rsvtype = $(el).attr('rsvtype');
|
||||
reckind = $(el).attr('reckind');
|
||||
|
||||
if (table != 'pending' && rsvtype == 3)
|
||||
{
|
||||
if ($(el).attr('ar') == 1)
|
||||
$('#optmenu').changeContextMenuItem('#ar',
|
||||
'Disable AR');
|
||||
else
|
||||
$('#optmenu').changeContextMenuItem('#ar',
|
||||
'Enable AR');
|
||||
$('#optmenu').enableContextMenuItems('#ar');
|
||||
}
|
||||
else
|
||||
$('#optmenu').disableContextMenuItems('#ar');
|
||||
|
||||
if (reckind == 4)
|
||||
$('#optmenu').enableContextMenuItems('#mkfolder');
|
||||
else
|
||||
$('#optmenu').disableContextMenuItems('#mkfolder');
|
||||
|
||||
if (table != 'pending' && rsvtype == 3 && reckind == 4)
|
||||
$('#optmenu').enableContextMenuItems('#refresh');
|
||||
else
|
||||
$('#optmenu').disableContextMenuItems('#refresh');
|
||||
|
||||
if (reckind == 4)
|
||||
$('#optmenu').enableContextMenuItems('#folder');
|
||||
else
|
||||
$('#optmenu').disableContextMenuItems('#folder');
|
||||
}
|
||||
|
||||
function menuclick(action, el, pos)
|
||||
{
|
||||
if (!$(el).is("tr"))
|
||||
el = $(el).closest('tr');
|
||||
var sid = $(el).attr('sid');
|
||||
var table = $(el).attr('table');
|
||||
//if (window.console)
|
||||
//console.log("Got %s, el: %o, id: %d", action, el, sid);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case 'delete':
|
||||
if (confirm('Are you sure you want to delete this entry?'))
|
||||
$.get('rpc/cancel.jim?slot=' + sid +
|
||||
'&table=' + table,
|
||||
function() {
|
||||
page_refresh();
|
||||
});
|
||||
break;
|
||||
|
||||
case 'ar':
|
||||
if ($(el).attr('ar') == 1)
|
||||
{
|
||||
$('#paddingsid').val(sid);
|
||||
$paddialog.dialog('open');
|
||||
}
|
||||
else
|
||||
$.get('rpc/ar.jim?slot=' + sid,
|
||||
function() {
|
||||
page_refresh();
|
||||
});
|
||||
break;
|
||||
|
||||
case 'folder':
|
||||
$('#fchangeslot').val(sid);
|
||||
$('#fchangename').val($(el).find('a.schedule').text());
|
||||
$('#fchangetable').val($(el).attr('table'));
|
||||
$('#fchange').dialog('open');
|
||||
break;
|
||||
|
||||
case 'mkfolder':
|
||||
$('#list_output')
|
||||
.empty()
|
||||
.show('slow')
|
||||
.load('rpc/mkdir.jim?slot=' + sid + '&table=' + table,
|
||||
function() {
|
||||
$('#list_output')
|
||||
.css('font-style', 'italic')
|
||||
.delay(5000).fadeOut('slow');
|
||||
});
|
||||
break;
|
||||
|
||||
case 'refresh':
|
||||
if (confirm('Are you sure you want to refresh events ' +
|
||||
'for this entry?'))
|
||||
$.get('rpc/refresh.jim?slot=' + sid,
|
||||
function() {
|
||||
visual_reload_required = true;
|
||||
$.growl.warning({ title: 'Success',
|
||||
message: "The schedule entry will be " +
|
||||
"refreshed." });
|
||||
$epgpopup.dialog('close');
|
||||
page_refresh();
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
alert('Unhandled menu event, ' + action);
|
||||
}
|
||||
}
|
||||
|
||||
$('table.schedule tbody tr').hover(
|
||||
function() { $(this).addClass('hover'); },
|
||||
function() { $(this).removeClass('hover'); })
|
||||
.contextMenu({menu: 'optmenu', beforeShow: preparemenu}, menuclick);
|
||||
|
||||
$('a.smenu')
|
||||
.contextMenu({menu: 'optmenu', leftButton: true, beforeShow: preparemenu}, menuclick);
|
||||
|
||||
$('#schedule_cleanup').bind('click', function(e) {
|
||||
if (confirm('Are you sure you want to remove all finished recordings?'))
|
||||
$.get('rpc/cleanup.jim',
|
||||
function() { page_refresh(); }
|
||||
);
|
||||
});
|
||||
|
||||
// Manual reservation
|
||||
|
||||
$('#manrsv').dialog({
|
||||
autoOpen: false,
|
||||
height: 'auto', width: 'auto',
|
||||
modal: true,
|
||||
buttons: {
|
||||
"Create event": function() {
|
||||
var data = $('#mrform').serializeArray();
|
||||
|
||||
var s = $('#mrstime').timepicker('getTime',
|
||||
$('#mrsdate').datepicker('getDate'));
|
||||
if (s)
|
||||
data.push({ name: "start", value: s.getTime() / 1000});
|
||||
|
||||
var e = $('#mretime').timepicker('getTime',
|
||||
$('#mredate').datepicker('getDate'));
|
||||
if (e)
|
||||
data.push({ name: "end", value: e.getTime() / 1000});
|
||||
|
||||
if (s.getTime() >= e.getTime())
|
||||
{
|
||||
$('#mrerr').html('Invalid time range...');
|
||||
return;
|
||||
}
|
||||
|
||||
$('#mrerr')
|
||||
.html('<img src=/img/loading.gif> Creating event...');
|
||||
|
||||
$.getJSON('rpc/manual.jim', data, function(d) {
|
||||
if (d.status)
|
||||
page_refresh();
|
||||
else if (d.errfields)
|
||||
{
|
||||
d.errfields.forEach(function(item) {
|
||||
$('#mrform input[name=' + item + ']')
|
||||
.addClass('error');
|
||||
});
|
||||
$('#mrerr').html('The start and end times '
|
||||
+ 'must be provided.');
|
||||
}
|
||||
else if (d.err)
|
||||
$('#mrerr').html(d.err);
|
||||
});
|
||||
},
|
||||
"Cancel": function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('button.manual_rsv').button({icons:{primary:"ui-icon-clock"}})
|
||||
.on('click', function() {
|
||||
$('#mrform').get(0).reset();
|
||||
$('#mrform input.date').datepicker('setDate', null);
|
||||
$('#mrform input.time').timepicker('setTime', null);
|
||||
$('#manrsv').dialog('open');
|
||||
|
||||
// $("#manrsv .ui-dialog-buttonpane button:contains('Create')")
|
||||
// .button('disable')
|
||||
|
||||
if ($('#mrlcn').hasClass('blood'))
|
||||
{
|
||||
var $s = $('#mrlcn');
|
||||
$.getJSON('/cgi-bin/chanlist.jim', function(data) {
|
||||
$s.find('option').remove();
|
||||
$.each(data, function(lcn, name) {
|
||||
$('<option>')
|
||||
.val(lcn)
|
||||
.text(lcn + ' - ' + name)
|
||||
.appendTo($s);
|
||||
});
|
||||
$('#mrlcn').removeClass('blood');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#mrform input.time').timepicker({
|
||||
showDuration: true,
|
||||
timeFormat: 'g:ia',
|
||||
step:5
|
||||
});
|
||||
|
||||
function dayfilter(date)
|
||||
{
|
||||
var cur = $('#mrrepeat').val();
|
||||
if (cur < 3) return [1, ""];
|
||||
|
||||
var day = date.getDay();
|
||||
if (cur == 3) // Weekdays only
|
||||
return [(day > 0 && day < 6), ""];
|
||||
else // Weekends only
|
||||
return [day == 0 || day >= 6, ""];
|
||||
}
|
||||
|
||||
$('#mrsdate').datepicker({
|
||||
firstDay: 1,
|
||||
defaultDate: 0,
|
||||
minDate: 0,
|
||||
maxDate: "+1Y",
|
||||
dateFormat: "D, dd/mm/yy",
|
||||
autoclose: true,
|
||||
beforeShowDay: dayfilter,
|
||||
onClose: function(s) {
|
||||
var dat = $(this).datepicker('getDate');
|
||||
if (dat)
|
||||
dat.setDate(dat.getDate() + 1);
|
||||
$('#mredate')
|
||||
.datepicker('setDate', s)
|
||||
.datepicker('option', 'minDate', s)
|
||||
.datepicker('option', 'maxDate', dat);
|
||||
}
|
||||
});
|
||||
|
||||
$('#mredate').datepicker({
|
||||
firstDay: 1,
|
||||
defaultDate: 0,
|
||||
minDate: 0,
|
||||
maxDate: "+1Y",
|
||||
autoclose: true,
|
||||
dateFormat: "D, dd/mm/yy",
|
||||
beforeShowDay: dayfilter
|
||||
});
|
||||
|
||||
$('#mrrepeat').on('change', function() {
|
||||
$('#mrform input.date').datepicker('refresh');
|
||||
});
|
||||
|
||||
$('#mrform').datepair({
|
||||
defaultDateDelta: null,
|
||||
defaultTimeDelta: 3600000,
|
||||
parseDate: function (el) {
|
||||
var utc = new Date($(el).datepicker('getDate'));
|
||||
return utc && new Date(utc.getTime() +
|
||||
(utc.getTimezoneOffset() * 60000));
|
||||
},
|
||||
updateDate: function (el, v) {
|
||||
$(el).datepicker('setDate', v);
|
||||
}
|
||||
});
|
||||
|
||||
$('.moretoshow')
|
||||
.hover(
|
||||
function() { $(this).css('cursor', 'pointer'); },
|
||||
function() { $(this).css('cursor', 'auto'); }
|
||||
)
|
||||
.on('click', function() {
|
||||
el = $(this).closest('tr');
|
||||
$(el).find('.moretoshow').hide();
|
||||
$(el).find('.moretoshowc').slideDown('slow');
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -19,9 +19,7 @@ foreach event $events {
|
||||
$event insert
|
||||
|
||||
system restartpending
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
footer
|
23
webif/html/sched/rpc/refresh.jim
Executable file
23
webif/html/sched/rpc/refresh.jim
Executable file
@ -0,0 +1,23 @@
|
||||
#!/mod/bin/jimsh
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require rsv.class system.class
|
||||
|
||||
httpheader
|
||||
|
||||
set slots [cgi_get slot 0]
|
||||
set table [cgi_get table TBL_RESERVATION]
|
||||
|
||||
if {$table eq "pending"} exit
|
||||
|
||||
foreach slot [split $slots ","] {
|
||||
set event [rsv slot $table $slot]
|
||||
|
||||
$event clear_ulslot
|
||||
$event set_refresh
|
||||
$event insert
|
||||
}
|
||||
|
||||
system restartpending
|
||||
|
45
webif/html/sched/rpc/skip.jim
Executable file
45
webif/html/sched/rpc/skip.jim
Executable file
@ -0,0 +1,45 @@
|
||||
#!/mod/bin/jimsh
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require rsv.class epg.class system.class
|
||||
|
||||
httpheader
|
||||
|
||||
set slots [cgi_get slot -]
|
||||
set xservice [cgi_get service 0]
|
||||
set xevent [cgi_get event 0]
|
||||
|
||||
if {$slots eq "-"} exit
|
||||
|
||||
foreach slot [split $slots ","] {
|
||||
puts "SLOT: $slot"
|
||||
set event [rsv slot $slot]
|
||||
|
||||
lassign [epg fetch dump -service $xservice -event $xevent] epg
|
||||
|
||||
if {$epg eq ""} {
|
||||
puts "!Cannot find event in EPG."
|
||||
break
|
||||
}
|
||||
$epg get_channel_info
|
||||
|
||||
# First check to see if there is already a pending skip for this
|
||||
# event and, if so, update that one.
|
||||
set crid "[$epg get channel_crid][$epg get series_crid]"
|
||||
set ev [rsv fetch pending [$event get ersvtype] \
|
||||
[$event get hsvc] 0 [$event get usevtid] $crid]
|
||||
if {$ev eq "0"} {
|
||||
# No pending event
|
||||
puts "No pending event."
|
||||
set ev $event
|
||||
$ev clear_ulslot
|
||||
}
|
||||
|
||||
puts "Set skip $xevent"
|
||||
$ev set_skip $epg
|
||||
$ev insert
|
||||
}
|
||||
|
||||
system restartpending
|
||||
|
@ -1,4 +1,14 @@
|
||||
|
||||
var spinner = '<div class=spinner><img border=0 src=/img/loading.gif>' +
|
||||
' Retrieving data... Please wait...</div>';
|
||||
|
||||
var LIST_INDEX = 0;
|
||||
var VISUAL_INDEX = 1;
|
||||
var BACKUP_INDEX = 3;
|
||||
|
||||
var list_reload_required = true;
|
||||
var visual_reload_required = true;
|
||||
|
||||
$.tablesorter.addParser({
|
||||
id: 'programme',
|
||||
is: function () { return false; },
|
||||
@ -20,410 +30,77 @@ $.tablesorter.addParser({
|
||||
type: 'numeric'
|
||||
});
|
||||
|
||||
function page_refresh(msg)
|
||||
{
|
||||
if (!msg)
|
||||
msg = 'Refreshing page...';
|
||||
$.blockUI({
|
||||
message: '<h1><img src=/img/loading.gif> ' + msg + '</h1>'
|
||||
});
|
||||
window.location.reload(true);
|
||||
}
|
||||
|
||||
$(function() {
|
||||
|
||||
$('table.tablesorter')
|
||||
.tablesorter({
|
||||
theme: 'webif',
|
||||
widthFixed: false,
|
||||
widgets: ['zebra', 'stickyHeaders']
|
||||
});
|
||||
// Retrieve the stored selected tab from the hash portion of the URL.
|
||||
var curtab = ~~(window.location.hash.slice(1));
|
||||
if (curtab < 0 || curtab > 2)
|
||||
curtab = 0;
|
||||
|
||||
function docancel()
|
||||
{
|
||||
var table = $('#sdialogue').attr('table');
|
||||
var slot = $('#sdialogue').attr('slot');
|
||||
|
||||
if (confirm('Really remove scheduled event?'))
|
||||
{
|
||||
$.get('cancel.jim?slot=' + slot +
|
||||
'&table=' + table, function() {
|
||||
window.location.reload(true);
|
||||
});
|
||||
$('#sdialogue').dialog('close');
|
||||
}
|
||||
}
|
||||
|
||||
var $buttons1 = {
|
||||
"Close" : function() {$(this).dialog('close');}
|
||||
};
|
||||
var $buttons2 = $.extend(
|
||||
{"Cancel Event": function() { docancel() }},
|
||||
$buttons1);
|
||||
|
||||
var $dialog = $('#sdialogue').dialog({
|
||||
title: "Schedule Details",
|
||||
modal: false, autoOpen: false,
|
||||
height: 500, width: 700,
|
||||
show: 'scale', hide: 'fade',
|
||||
draggable: true, resizable: true,
|
||||
buttons: $buttons2,
|
||||
close: function(e,u) { $('#sdialogue').empty().html(
|
||||
'<img src="/img/loading.gif" alt="loading">'); }
|
||||
});
|
||||
|
||||
function schedpopup(e, o)
|
||||
{
|
||||
e.preventDefault();
|
||||
var slot = o.attr('slot');
|
||||
var table = o.attr('table');
|
||||
$('#sdialogue').attr('slot', slot).attr('table', table);
|
||||
|
||||
var url = 'info.jim?slot=' + slot +
|
||||
'&table=' + table;
|
||||
$('#sdialogue').load(url);
|
||||
$dialog.dialog('open');
|
||||
}
|
||||
$('a.schedule').click(function(e) { schedpopup(e, $(this)) });
|
||||
|
||||
$('.schedselect:checked').prop('checked', false);
|
||||
|
||||
$('button.delselected').button({icons:{primary:"ui-icon-trash"}})
|
||||
.button('disable')
|
||||
.on('click', function() {
|
||||
$(this).dojConfirmAction({
|
||||
question: 'Delete selected?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
$.blockUI({
|
||||
message: '<h1><img src=/img/loading.gif> Deleting... </h1>'
|
||||
});
|
||||
|
||||
var els = $(el).parent().find('.schedselect:checked');
|
||||
var tab = $(els).first().closest('tr').attr('table');
|
||||
var slots = $.map(els, function(v) {
|
||||
return $(v).closest('tr').attr('sid');
|
||||
});
|
||||
$.get('cancel.jim?slot=' + slots.join(',') +
|
||||
'&table=' + tab, function() {
|
||||
window.location.reload(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
$('.schedselect').on('change', function() {
|
||||
var num = $(this).closest('table').find('.schedselect:checked').size();
|
||||
var but = $(this).closest('fieldset').find('button.delselected');
|
||||
if (num)
|
||||
$(but).button('enable').find('.delselcnt')
|
||||
.text('(' + num + ')');
|
||||
else
|
||||
$(but).button('disable').find('.delselcnt').empty();
|
||||
});
|
||||
|
||||
$('button.selall').button({icons:{primary:"ui-icon-check"}})
|
||||
.on('click', function() {
|
||||
$(this).parent().find('table .schedselect').prop('checked', true)
|
||||
.first().trigger('change');
|
||||
});
|
||||
|
||||
$('button.selnone').button({icons:{primary:"ui-icon-close"}})
|
||||
.on('click', function() {
|
||||
$(this).parent().find('table .schedselect').prop('checked', false)
|
||||
.first().trigger('change');
|
||||
});
|
||||
|
||||
$('button.selended').button({icons:{primary:"ui-icon-stop"}})
|
||||
.on('click', function() {
|
||||
$(this).parent().find('table .schedselect').prop('checked', false);
|
||||
$(this).parent().find('table tr[ended="1"] .schedselect')
|
||||
.prop('checked', true).first().trigger('change');
|
||||
|
||||
});
|
||||
|
||||
$('button.rawview').button({icons:{primary:"ui-icon-wrench"}})
|
||||
.on('click', function() {
|
||||
window.location = '/db/index.jim?' + $(this).attr('path');
|
||||
});
|
||||
|
||||
$('button.backup').button({icons:{primary:"ui-icon-disk"}})
|
||||
.on('click', function() {
|
||||
window.location = '/backup/index.jim';
|
||||
});
|
||||
|
||||
|
||||
// Menu
|
||||
|
||||
var $paddialog = $('#padding').dialog({
|
||||
title: "Padding values",
|
||||
modal: true, autoOpen: false,
|
||||
height: 'auto', width: 'auto',
|
||||
show: 'scale', hide: 'fade',
|
||||
draggable: false, resizable: false,
|
||||
buttons: {
|
||||
"Confirm": function() {
|
||||
$('#paddingf').ajaxSubmit({
|
||||
dataType: 'text',
|
||||
success: function(data) {
|
||||
window.location.reload(true);
|
||||
}
|
||||
});
|
||||
},
|
||||
"Cancel": function() { $(this).dialog('close'); }
|
||||
}
|
||||
});
|
||||
|
||||
$('#fchange').dialog({
|
||||
autoOpen: false,
|
||||
height: 'auto', width: 'auto',
|
||||
modal: true,
|
||||
buttons: {
|
||||
"Update": function() {
|
||||
var s = $('#fchangeform').serialize();
|
||||
$.get('folder.jim?' + s,
|
||||
function() { window.location.reload(true); });
|
||||
},
|
||||
"Close": function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
$('#minimaltabbar').tabs({
|
||||
active: curtab,
|
||||
heightStyle: "auto",
|
||||
spinner: spinner,
|
||||
create: function(event, ui) {
|
||||
$(ui.panel).html(spinner);
|
||||
},
|
||||
close: function() {
|
||||
$('#changeslot').val(0);
|
||||
$('#fchangename').val('');
|
||||
}
|
||||
});
|
||||
|
||||
function preparemenu(el, menu)
|
||||
{
|
||||
if (!$(el).is("tr"))
|
||||
el = $(el).closest('tr');
|
||||
|
||||
if ($(el).attr('table') != 'pending' && $(el).attr('rsvtype') == 3)
|
||||
{
|
||||
if ($(el).attr('ar') == 1)
|
||||
$('#optmenu').changeContextMenuItem('#ar',
|
||||
'Disable AR');
|
||||
else
|
||||
$('#optmenu').changeContextMenuItem('#ar',
|
||||
'Enable AR');
|
||||
$('#optmenu').enableContextMenuItems('#ar');
|
||||
}
|
||||
else
|
||||
$('#optmenu').disableContextMenuItems('#ar');
|
||||
|
||||
if ($(el).attr('reckind') == 4)
|
||||
$('#optmenu').enableContextMenuItems('#mkfolder');
|
||||
else
|
||||
$('#optmenu').disableContextMenuItems('#mkfolder');
|
||||
|
||||
// if ($(el).attr('table') != 'pending' && $(el).attr('reckind') == 4)
|
||||
if ($(el).attr('reckind') == 4)
|
||||
$('#optmenu').enableContextMenuItems('#folder');
|
||||
else
|
||||
$('#optmenu').disableContextMenuItems('#folder');
|
||||
}
|
||||
|
||||
function menuclick(action, el, pos)
|
||||
{
|
||||
if (!$(el).is("tr"))
|
||||
el = $(el).closest('tr');
|
||||
var sid = $(el).attr('sid');
|
||||
var table = $(el).attr('table');
|
||||
//if (window.console)
|
||||
//console.log("Got %s, el: %o, id: %d", action, el, sid);
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case 'delete':
|
||||
if (confirm('Are you sure you want to delete this entry?'))
|
||||
$.get('cancel.jim?slot=' + sid +
|
||||
'&table=' + table,
|
||||
function() {
|
||||
window.location.reload(true);
|
||||
});
|
||||
break;
|
||||
|
||||
case 'ar':
|
||||
if ($(el).attr('ar') == 1)
|
||||
{
|
||||
$('#paddingsid').val(sid);
|
||||
$paddialog.dialog('open');
|
||||
}
|
||||
else
|
||||
$.get('ar.jim?slot=' + sid,
|
||||
function() {
|
||||
window.location.reload(true);
|
||||
});
|
||||
break;
|
||||
|
||||
case 'folder':
|
||||
$('#fchangeslot').val(sid);
|
||||
$('#fchangename').val($(el).find('a.schedule').text());
|
||||
$('#fchangetable').val($(el).attr('table'));
|
||||
$('#fchange').dialog('open');
|
||||
break;
|
||||
|
||||
case 'mkfolder':
|
||||
$('#output')
|
||||
.empty()
|
||||
.show('slow')
|
||||
.load('mkdir.jim?slot=' + sid + '&table=' + table,
|
||||
function() {
|
||||
$(output)
|
||||
.css('font-style', 'italic')
|
||||
.delay(5000).fadeOut('slow');
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
alert('Unhandled menu event, ' + action);
|
||||
}
|
||||
}
|
||||
|
||||
$('table.schedule tbody tr').hover(
|
||||
function() { $(this).addClass('hover'); },
|
||||
function() { $(this).removeClass('hover'); })
|
||||
.contextMenu({menu: 'optmenu', beforeShow: preparemenu}, menuclick);
|
||||
|
||||
$('a.smenu')
|
||||
.contextMenu({menu: 'optmenu', leftButton: true, beforeShow: preparemenu}, menuclick);
|
||||
|
||||
$('#schedule_cleanup').bind('click', function(e) {
|
||||
if (confirm('Are you sure you want to remove all finished recordings?'))
|
||||
$.get('cleanup.jim',
|
||||
function() { window.location.reload(true);
|
||||
});
|
||||
});
|
||||
|
||||
// Manual reservation
|
||||
|
||||
$('#manrsv').dialog({
|
||||
autoOpen: false,
|
||||
height: 'auto', width: 'auto',
|
||||
modal: true,
|
||||
buttons: {
|
||||
"Create event": function() {
|
||||
var data = $('#mrform').serializeArray();
|
||||
|
||||
var s = $('#mrstime').timepicker('getTime',
|
||||
$('#mrsdate').datepicker('getDate'));
|
||||
if (s)
|
||||
data.push({ name: "start", value: s.getTime() / 1000});
|
||||
|
||||
var e = $('#mretime').timepicker('getTime',
|
||||
$('#mredate').datepicker('getDate'));
|
||||
if (e)
|
||||
data.push({ name: "end", value: e.getTime() / 1000});
|
||||
|
||||
if (s.getTime() >= e.getTime())
|
||||
{
|
||||
$('#mrerr').html('Invalid time range...');
|
||||
return;
|
||||
}
|
||||
|
||||
$('#mrerr')
|
||||
.html('<img src=/img/loading.gif> Creating event...');
|
||||
|
||||
$.getJSON('manual.jim', data, function(d) {
|
||||
if (d.status)
|
||||
window.location.reload(true);
|
||||
else if (d.errfields)
|
||||
{
|
||||
d.errfields.forEach(function(item) {
|
||||
$('#mrform input[name=' + item + ']')
|
||||
.addClass('error');
|
||||
});
|
||||
$('#mrerr').html('The start and end times '
|
||||
+ 'must be provided.');
|
||||
}
|
||||
else if (d.err)
|
||||
$('#mrerr').html(d.err);
|
||||
});
|
||||
},
|
||||
"Cancel": function() {
|
||||
$(this).dialog('close');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('button.manual_rsv').button({icons:{primary:"ui-icon-clock"}})
|
||||
.on('click', function() {
|
||||
$('#mrform').get(0).reset();
|
||||
$('#mrform input.date').datepicker('setDate', null);
|
||||
$('#mrform input.time').timepicker('setTime', null);
|
||||
$('#manrsv').dialog('open');
|
||||
|
||||
// $("#manrsv .ui-dialog-buttonpane button:contains('Create')")
|
||||
// .button('disable')
|
||||
|
||||
if ($('#mrlcn').hasClass('blood'))
|
||||
{
|
||||
var $s = $('#mrlcn');
|
||||
$.getJSON('/cgi-bin/chanlist.jim', function(data) {
|
||||
$s.find('option').remove();
|
||||
$.each(data, function(lcn, name) {
|
||||
$('<option>')
|
||||
.val(lcn)
|
||||
.text(lcn + ' - ' + name)
|
||||
.appendTo($s);
|
||||
});
|
||||
$('#mrlcn').removeClass('blood');
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
$('#mrform input.time').timepicker({
|
||||
showDuration: true,
|
||||
timeFormat: 'g:ia',
|
||||
step:5
|
||||
});
|
||||
|
||||
function dayfilter(date)
|
||||
{
|
||||
var cur = $('#mrrepeat').val();
|
||||
if (cur < 3) return [1, ""];
|
||||
|
||||
var day = date.getDay();
|
||||
if (cur == 3) // Weekdays only
|
||||
return [(day > 0 && day < 6), ""];
|
||||
else // Weekends only
|
||||
return [day == 0 || day >= 6, ""];
|
||||
}
|
||||
|
||||
$('#mrsdate').datepicker({
|
||||
firstDay: 1,
|
||||
defaultDate: 0,
|
||||
minDate: 0,
|
||||
maxDate: "+1Y",
|
||||
dateFormat: "D, dd/mm/yy",
|
||||
autoclose: true,
|
||||
beforeShowDay: dayfilter,
|
||||
onClose: function(s) {
|
||||
var dat = $(this).datepicker('getDate');
|
||||
if (dat)
|
||||
dat.setDate(dat.getDate() + 1);
|
||||
$('#mredate')
|
||||
.datepicker('setDate', s)
|
||||
.datepicker('option', 'minDate', s)
|
||||
.datepicker('option', 'maxDate', dat);
|
||||
}
|
||||
});
|
||||
|
||||
$('#mredate').datepicker({
|
||||
firstDay: 1,
|
||||
defaultDate: 0,
|
||||
minDate: 0,
|
||||
maxDate: "+1Y",
|
||||
autoclose: true,
|
||||
dateFormat: "D, dd/mm/yy",
|
||||
beforeShowDay: dayfilter
|
||||
});
|
||||
|
||||
$('#mrrepeat').on('change', function() {
|
||||
$('#mrform input.date').datepicker('refresh');
|
||||
});
|
||||
|
||||
$('#mrform').datepair({
|
||||
defaultDateDelta: null,
|
||||
defaultTimeDelta: 3600000,
|
||||
parseDate: function (el) {
|
||||
var utc = new Date($(el).datepicker('getDate'));
|
||||
return utc && new Date(utc.getTime() +
|
||||
(utc.getTimezoneOffset() * 60000));
|
||||
activate: function(event, ui) {
|
||||
window.location.hash = ui.newTab.index();
|
||||
},
|
||||
updateDate: function (el, v) {
|
||||
$(el).datepicker('setDate', v);
|
||||
beforeLoad: function (event, ui) {
|
||||
|
||||
var content = $(ui.panel).html();
|
||||
|
||||
switch (ui.tab.index())
|
||||
{
|
||||
case LIST_INDEX:
|
||||
if (list_reload_required)
|
||||
content = false;
|
||||
break;
|
||||
case VISUAL_INDEX:
|
||||
if (visual_reload_required)
|
||||
content = false;
|
||||
break;
|
||||
case BACKUP_INDEX:
|
||||
break;
|
||||
default:
|
||||
alert('Unknown tab just loaded.');
|
||||
}
|
||||
// Don't reload if content exists.
|
||||
if (content)
|
||||
event.preventDefault();
|
||||
else
|
||||
{
|
||||
list_reload_required = false;
|
||||
visual_reload_required = false;
|
||||
$(ui.panel).html(spinner);
|
||||
}
|
||||
},
|
||||
load: function(event, ui) {
|
||||
switch (ui.tab.index())
|
||||
{
|
||||
case LIST_INDEX:
|
||||
list_loaded(ui.panel);
|
||||
break;
|
||||
case VISUAL_INDEX:
|
||||
visual_loaded(ui.panel);
|
||||
break;
|
||||
case BACKUP_INDEX:
|
||||
backup_loaded(ui.panel);
|
||||
break;
|
||||
default:
|
||||
alert('Unknown tab just loaded.');
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
10
webif/html/sched/visual/assets.jim
Executable file
10
webif/html/sched/visual/assets.jim
Executable file
@ -0,0 +1,10 @@
|
||||
#!/mod/bin/jimsh
|
||||
|
||||
puts {
|
||||
<div id=epgpopup></div>
|
||||
|
||||
<ul id=optmenu class=contextMenu style="width: 200px">
|
||||
<li class=separator><a href=#refresh>Refresh Events</a></li>
|
||||
</ul>
|
||||
}
|
||||
|
456
webif/html/sched/visual/index.jim
Executable file
456
webif/html/sched/visual/index.jim
Executable file
@ -0,0 +1,456 @@
|
||||
#!/mod/bin/jimsh
|
||||
|
||||
package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require rsv.class epg.class system.class classdump
|
||||
|
||||
set debug 0
|
||||
|
||||
noheader
|
||||
set renderstart [clock milliseconds]
|
||||
|
||||
set events [rsv allevents]
|
||||
set pending [rsv list pending]
|
||||
|
||||
# hSvc -> usSvcId map
|
||||
lmap i \
|
||||
[$::channeldb query {select hSvc, usSvcid from TBL_SVC}] \
|
||||
{
|
||||
set hmap([lindex $i 1]) [lindex $i 3]
|
||||
}
|
||||
|
||||
# usSvcId -> hSvc map
|
||||
#set svcmap [lreverse $hmap]
|
||||
|
||||
proc pop_event {{debug 0}} {
|
||||
uplevel {
|
||||
lassign [lindex $events $eindex] \
|
||||
start end hsvc eid slotid kind sclass
|
||||
incr eindex
|
||||
if {$debug} {
|
||||
puts "
|
||||
--------------------------------------------------
|
||||
EVENT$eindex
|
||||
START: $start [clock format $start]
|
||||
END: $end [clock format $end]
|
||||
HSVC: $hsvc
|
||||
EID: $eid
|
||||
SID: $slotid
|
||||
KIND: $kind
|
||||
SCLASS: $sclass
|
||||
"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set pendingclasses {
|
||||
1 "pending-unschedule"
|
||||
2 "pending-ar"
|
||||
3 "pending-ar"
|
||||
4 "pending-folder"
|
||||
5 "pending-skip"
|
||||
6 "pending-refresh"
|
||||
}
|
||||
|
||||
foreach p $pending {
|
||||
set action [$p get action]
|
||||
|
||||
# Add - already handled.
|
||||
if {$action eq "0"} continue
|
||||
|
||||
set s [rsv fetch "TBL_RESERVATION" \
|
||||
[$p get ersvtype] [$p get hsvc] 0 [$p get usevtid]]
|
||||
|
||||
if {$s eq "0"} continue
|
||||
|
||||
set slot [$s get ulslot]
|
||||
|
||||
set elen [llength $events]
|
||||
set eindex 0
|
||||
while {$eindex < $elen} {
|
||||
pop_event 1
|
||||
|
||||
if {$slotid ne [$s get ulslot]} continue
|
||||
|
||||
if {$action eq "5" && $start != [$p start]} continue
|
||||
lset events $($eindex - 1) 6 $pendingclasses($action)
|
||||
}
|
||||
}
|
||||
|
||||
#foreach ev $events {
|
||||
# puts $ev
|
||||
#}
|
||||
|
||||
# Event array keys:
|
||||
# 0: start
|
||||
# 1: end
|
||||
# 2: hSvc
|
||||
# 3: event_id
|
||||
# 4: Schedule Slot ID
|
||||
# 5: ucRecKind
|
||||
# 6: class (live, pending)
|
||||
|
||||
# Sort final events array
|
||||
set events [lsort -index 0 -integer $events]
|
||||
|
||||
######################################################################
|
||||
# Visualisation functions
|
||||
|
||||
# Intend 40 pixels / hour for fully populated timeline.
|
||||
set width $(40 * 24)
|
||||
# This is the total padding/margin/border width.
|
||||
set pad 4
|
||||
set padadj 0
|
||||
|
||||
# Returns an absolute number of pixels from the left corresponding
|
||||
# to a number of seconds into the day.
|
||||
proc secstopx {daysecs hourpx usedhours} {
|
||||
# No floor() in Humax jim
|
||||
#set max [expr floor($daysecs / 3600)]
|
||||
set max [expr int($daysecs / 3600)]
|
||||
# Subtract any unused hours from $daysecs.
|
||||
for {set i 0} {$i < $max} {incr i} {
|
||||
if {$i >= 24} break
|
||||
if {![lindex $usedhours $i]} {
|
||||
incr daysecs -3600
|
||||
}
|
||||
}
|
||||
#return [expr floor($daysecs / 3600 * $hourpx)]
|
||||
return [expr int($daysecs * $hourpx / 3600)]
|
||||
}
|
||||
|
||||
# daysecs - absolute number of seconds into the day that needs to be reached.
|
||||
# pxpos - current pixel position.
|
||||
proc showpad {daysecs hourpx &pxpos usedhours} {
|
||||
global debug pad padadj
|
||||
|
||||
# Determine required pixel position.
|
||||
set newpos [set p [secstopx $daysecs $hourpx $usedhours]]
|
||||
|
||||
# Calculate required width of spacer
|
||||
incr p -$pxpos
|
||||
|
||||
# Account for padding and any pending adjustment
|
||||
incr p $(-($pad + $padadj))
|
||||
|
||||
if {$p <= 0} {
|
||||
# If too narrow, show bare skip at full required width.
|
||||
incr p $($pad + $padadj)
|
||||
# Bare skip
|
||||
set class "ct_bskip"
|
||||
} else {
|
||||
set class "ct_skip"
|
||||
if {$debug} { append class " ct_debug" }
|
||||
}
|
||||
|
||||
if {$p > 0} {
|
||||
puts -nonewline \
|
||||
"<div class=\"$class\" style=\"width: ${p}px;\">"
|
||||
if {$debug} {
|
||||
puts [format "@%d-%d s=%d w=%dpx @%dpx" \
|
||||
$pxpos $padadj $daysecs $p $newpos]
|
||||
}
|
||||
puts -nonewline "</div>"
|
||||
set pxpos $newpos
|
||||
set padadj 0
|
||||
}
|
||||
}
|
||||
|
||||
proc showevent {s class &overflow &tomorrow &pxpos start end usedhours daystart dayend hourpx service event sclass} {
|
||||
|
||||
global debug pad padadj dev
|
||||
|
||||
# Required pixel position of event start.
|
||||
set p [secstopx $($start - $daystart) $hourpx $usedhours]
|
||||
|
||||
if {$p < $pxpos} {
|
||||
# Backwards move => tuner conflict.
|
||||
lappend overflow [list $s $start $end $service $event $sclass]
|
||||
return
|
||||
}
|
||||
|
||||
# Show padding up to event.
|
||||
showpad $($start - $daystart) $hourpx pxpos $usedhours
|
||||
|
||||
# And now the event itself.
|
||||
|
||||
set name [set channel "Unknown"]
|
||||
set slotid -1
|
||||
if {$s ne "0"} {
|
||||
set name [$s name]
|
||||
set channel [$s channel_name]
|
||||
set slotid [$s get ulslot]
|
||||
}
|
||||
if {$service > 0} {
|
||||
set epgs [epg dbfetch dump -service $service -event $event]
|
||||
if {[llength $epgs] == 1} {
|
||||
lassign $epgs epg
|
||||
set name [$epg get name]
|
||||
$epg get_channel_info
|
||||
set channel [$epg get channel_name]
|
||||
}
|
||||
}
|
||||
|
||||
if {[string match -nocase "New:*" $name]} {
|
||||
set name [string trim [string range $name 4 end]]
|
||||
}
|
||||
set name [cgi_quote_html $name]
|
||||
|
||||
if {$sclass == "pending"} {
|
||||
append class " purpleshade"
|
||||
} elseif {$sclass == "pending-unschedule" ||
|
||||
$sclass == "pending-skip"} {
|
||||
append class " strike purpleshade"
|
||||
} elseif {[string match "*pending*" $sclass]} {
|
||||
append class " orangeshade"
|
||||
}
|
||||
|
||||
if {$end > $dayend + 1} {
|
||||
# Push event into tomorrow.
|
||||
if {$s ne "0"} { $s setorigstart $start }
|
||||
lappend tomorrow [list $s $($dayend + 1) $end \
|
||||
$service $event $sclass]
|
||||
set newpos [set p [secstopx 86400 $hourpx $usedhours]]
|
||||
append name "..."
|
||||
} else {
|
||||
set newpos [set p [\
|
||||
secstopx $($end - $daystart) $hourpx $usedhours]]
|
||||
if {$start == $daystart && $s ne "0" &&
|
||||
[$s get _origstart] > 0} {
|
||||
set name "..$name"
|
||||
set start [$s get _origstart]
|
||||
$s setorigstart 0
|
||||
}
|
||||
}
|
||||
|
||||
# Calculate width
|
||||
incr p -$pxpos
|
||||
|
||||
# Account for padding
|
||||
incr p -$pad
|
||||
|
||||
if {$p < 8} {
|
||||
# Event too narrow, force to 8 pixels.
|
||||
set padadj $(8 - $p)
|
||||
set p 8
|
||||
} else {
|
||||
set padadj 0
|
||||
}
|
||||
|
||||
puts -nonewline "<div class=\"$class ct_event\" style=\"width: ${p}px;\" sid=\"${slotid}\" sclass=\"$sclass\" period=\"[clock format $start -format {%H:%M}] - [clock format $end -format {%H:%M}]\" xs=$service xe=$event"
|
||||
if {$s ne "0"} {
|
||||
puts -nonewline " rc=\"[$s get ucRecKind]\" et=\"[$s get ersvtype]\" rt=\"[$s get erepeat]\""
|
||||
if {[$s get szCRID] ne ""} {
|
||||
puts " crid=\"[$s get szCRID]\""
|
||||
}
|
||||
}
|
||||
puts -nonewline " sz=\"[cgi_quote_html $channel]\""
|
||||
puts -nonewline ">"
|
||||
|
||||
if {$debug} {
|
||||
puts -nonewline [format "@%d s=%d w=%dpx @%dpx /=%d" \
|
||||
$pxpos $($end - $start) $p $newpos $padadj]
|
||||
}
|
||||
|
||||
puts -nonewline "$name</div>"
|
||||
|
||||
set pxpos $newpos
|
||||
}
|
||||
|
||||
proc render_timeline {usedhours} {
|
||||
global debug events width pad hmap padadj
|
||||
|
||||
puts "<div class=ct_visual>\n"
|
||||
|
||||
set tothours [ladd $usedhours]
|
||||
|
||||
if {!$tothours} {
|
||||
puts "No schedule data found."
|
||||
return
|
||||
}
|
||||
|
||||
# calculate pixels per hour
|
||||
#set hourpx [expr floor($width / $tothours)]
|
||||
set hourpx [expr int($width / $tothours)]
|
||||
|
||||
if {$debug} {
|
||||
puts "USEDHOURS: $usedhours<br>\n"
|
||||
puts "HOURPX: $hourpx (tothours: $tothours)<br>\n"
|
||||
}
|
||||
|
||||
# Show the hour bar.
|
||||
puts "<div class=ct_header><div class=ct_row>"
|
||||
puts "<div class=ct_dayname> </div>"
|
||||
# Account for element padding and margin
|
||||
set px $($hourpx - $pad)
|
||||
for {set i 0} {$i < 25} {incr i} {
|
||||
if {[lindex $usedhours $i] ne "1"} continue
|
||||
puts -nonewline \
|
||||
"<div class=ct_hour style=\"width:${px}px\"><center>[\
|
||||
format "%02dh" $i]</center></div>"
|
||||
}
|
||||
puts "</div></div>\n"
|
||||
|
||||
# To store events which overflow into tomorrow.
|
||||
set tomorrow {}
|
||||
|
||||
# Midnight today.
|
||||
set day [clock scan \
|
||||
[clock format [clock seconds] -format "%Y:%m:%d:0:0:0"] \
|
||||
-format "%Y:%m:%d:%T"]
|
||||
|
||||
set elength [llength $events]
|
||||
set eindex 0
|
||||
set start 0
|
||||
while {$start < $day} { pop_event }
|
||||
|
||||
for {set i 0} {$i < 8} {incr i} {
|
||||
# To store things that need to move to the next row.
|
||||
set rows {}
|
||||
|
||||
if {$i % 2} {
|
||||
set class "odd"
|
||||
} else {
|
||||
set class "even"
|
||||
}
|
||||
set eclass "blueshade"
|
||||
|
||||
set dayend [set daystart $day]
|
||||
incr dayend 86399
|
||||
|
||||
# Row 1
|
||||
puts "<div class=\"ct_day $class\">"
|
||||
puts "<div class=\"ct_row\">"
|
||||
|
||||
puts "<div class=ct_dayname>[clock format $day \
|
||||
-format {%a %d/%m/%Y}]</div>"
|
||||
|
||||
set pxpos [set padadj 0]
|
||||
|
||||
if {[llength $tomorrow]} {
|
||||
set dummy {}
|
||||
foreach row $tomorrow {
|
||||
lassign $row s xstart xend xs xe xsclass
|
||||
showevent $s $eclass rows dummy \
|
||||
pxpos $xstart $xend $usedhours \
|
||||
$daystart $dayend $hourpx \
|
||||
$xs $xe $xsclass
|
||||
}
|
||||
|
||||
set tomorrow {}
|
||||
}
|
||||
|
||||
while {$start >= $daystart && $start <= $dayend} {
|
||||
if {$slotid ne "-1"} {
|
||||
set tab "TBL_RESERVATION"
|
||||
if {$sclass eq "pending"} {
|
||||
set tab "pending"
|
||||
}
|
||||
set s [rsv slot $tab $slotid]
|
||||
} else {
|
||||
set s "0"
|
||||
}
|
||||
|
||||
if {[dict exists $hmap $hsvc]} {
|
||||
set service $hmap($hsvc)
|
||||
} else {
|
||||
set service 0
|
||||
}
|
||||
|
||||
showevent $s $eclass rows tomorrow pxpos \
|
||||
$start $end $usedhours \
|
||||
$daystart $dayend $hourpx \
|
||||
$service $eid $sclass
|
||||
|
||||
pop_event
|
||||
}
|
||||
|
||||
# Close row
|
||||
showpad 86400 $hourpx pxpos $usedhours
|
||||
puts "</div>"
|
||||
|
||||
# Output other rows if necessary
|
||||
while {[llength $rows]} {
|
||||
set nrows {}
|
||||
puts "<div class=\"ct_row $class\"><div class=ct_dayname></div>"
|
||||
set pxpos [set padadj 0]
|
||||
foreach row $rows {
|
||||
lassign $row s xstart xend xs xe xsclass
|
||||
showevent $s $eclass nrows tomorrow \
|
||||
pxpos $xstart $xend $usedhours \
|
||||
$daystart $dayend $hourpx \
|
||||
$xs $xe $xsclass
|
||||
}
|
||||
showpad 86400 $hourpx pxpos $usedhours
|
||||
puts "</div>"
|
||||
set rows $nrows
|
||||
set eclass "pinkshade"
|
||||
}
|
||||
|
||||
incr day 86400
|
||||
# Close ct_day
|
||||
puts "</div>"
|
||||
}
|
||||
|
||||
puts "\n</div>\n"
|
||||
}
|
||||
|
||||
######################################################################
|
||||
# Compressed Day Schedule Visualisation
|
||||
|
||||
set usedhours [lrepeat 24 0]
|
||||
|
||||
# Determine which hours are usde.
|
||||
foreach e $events {
|
||||
lassign $e start end
|
||||
set shour [clock format $start -format "%H"]
|
||||
set ehour [clock format $end -format "%H"]
|
||||
if {$ehour < $shour} {
|
||||
incr ehour 24
|
||||
}
|
||||
for {set i $shour} {$i <= $ehour} {incr i} {
|
||||
set index $i
|
||||
if {$i > 23} { incr index -24 }
|
||||
lset usedhours $index 1
|
||||
}
|
||||
}
|
||||
|
||||
# To show 24 hours
|
||||
# set usedhours [lrepeat 24 1]
|
||||
|
||||
puts "
|
||||
<fieldset id=sched_timeline class=visual>
|
||||
<legend>
|
||||
<h3>Schedule</h3>
|
||||
</legend>
|
||||
"
|
||||
|
||||
render_timeline $usedhours
|
||||
|
||||
puts "</fieldset>"
|
||||
|
||||
puts {
|
||||
<div id=legend>
|
||||
<h3 style="display: inline-block">Key:</h3>
|
||||
<div class="ct_key blueshade">
|
||||
Scheduled event
|
||||
</div>
|
||||
<div class="ct_key pinkshade">
|
||||
Conflict
|
||||
</div>
|
||||
<div class="ct_key orangeshade">
|
||||
Pending change
|
||||
</div>
|
||||
<div class="ct_key purpleshade">
|
||||
Pending <b>schedule</b>
|
||||
</div>
|
||||
<div class="ct_key purpleshade strike">
|
||||
Pending <b>unschedule</b>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
source assets.jim
|
||||
|
||||
footer
|
||||
|
414
webif/html/sched/visual/script.js
Normal file
414
webif/html/sched/visual/script.js
Normal file
@ -0,0 +1,414 @@
|
||||
|
||||
var visual_notes = {
|
||||
'pending': 'Pending schedule command',
|
||||
'pending-unschedule': 'Pending unschedule',
|
||||
'pending-folder': 'Pending folder change',
|
||||
'pending-ar': 'Pending padding change',
|
||||
'pending-refresh': 'Pending refresh',
|
||||
'pending-skip': 'Pending episode skip'
|
||||
};
|
||||
|
||||
function visual_loaded()
|
||||
{
|
||||
|
||||
$epgpopup = $('#epgpopup').dialog({
|
||||
title: "Programme Details",
|
||||
modal: false, autoOpen: false,
|
||||
height: 500, width: 700,
|
||||
show: 'scale', hide: 'fade',
|
||||
draggable: true, resizable: true,
|
||||
buttons: [
|
||||
{
|
||||
text: 'Cancel Entire Recording',
|
||||
id: 'b_cancel',
|
||||
class: 'ep_button',
|
||||
icons: { primary: "ui-icon-trash" },
|
||||
click: cancel_recording
|
||||
},
|
||||
{
|
||||
text: 'Skip This Episode',
|
||||
id: 'b_skip',
|
||||
class: 'ep_button',
|
||||
icons: { primary: "ui-icon-seek-next" },
|
||||
click: skip_episode
|
||||
},
|
||||
{
|
||||
text: 'Record This Showing Instead',
|
||||
id: 'b_alternate',
|
||||
class: 'ep_button',
|
||||
icons: { primary: "ui-icon-transfer-e-w" },
|
||||
click: alternate_recording
|
||||
},
|
||||
{
|
||||
text: 'Switch to This Series',
|
||||
id: 'b_alternateseries',
|
||||
class: 'ep_button',
|
||||
icons: { primary: "ui-icon-shuffle" },
|
||||
click: alternate_series
|
||||
},
|
||||
{
|
||||
text: 'More',
|
||||
id: 'b_more',
|
||||
class: 'ep_button',
|
||||
icons: { primary: "ui-icon-arrowthick-1-s" },
|
||||
click: function(e) { e.preventDefault(); }
|
||||
},
|
||||
{
|
||||
text: 'Close',
|
||||
icons: { primary: "ui-icon-close" },
|
||||
click: function() { $(this).dialog('close'); }
|
||||
},
|
||||
]
|
||||
});
|
||||
|
||||
function cancel_recording()
|
||||
{
|
||||
$('#b_cancel').dojConfirmAction({
|
||||
question: 'Cancel Recording?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
var sid = $epgpopup.attr('sid');
|
||||
$.get('rpc/cancel.jim?slot=' + sid,
|
||||
function() {
|
||||
$('.ct_event[sid=' + sid + ']')
|
||||
.attr('sclass', 'pending-unschedule')
|
||||
.addClass('purpleshade strike');
|
||||
$epgpopup.dialog('close');
|
||||
$.growl.error({ title: 'Success',
|
||||
message:
|
||||
"The recording has been cancelled." });
|
||||
list_reload_required = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function skip_episode()
|
||||
{
|
||||
$('#b_skip').dojConfirmAction({
|
||||
question: 'Skip Episode?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
var sid = $epgpopup.attr('sid');
|
||||
var xs = $epgpopup.attr('xs');
|
||||
var xe = $epgpopup.attr('xe');
|
||||
$.get('rpc/skip.jim?slot=' + sid +
|
||||
'&service=' + xs + '&event=' + xe,
|
||||
function() {
|
||||
$('.ct_event[sid=' + sid + ']')
|
||||
.filter('[xe=' + xe + ']')
|
||||
.attr('sclass', 'pending-skip')
|
||||
.addClass('purpleshade strike');
|
||||
$epgpopup.dialog('close');
|
||||
$.growl.warning({ title: 'Success',
|
||||
message: "The episode will be skipped." });
|
||||
list_reload_required = true;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function alternate_series()
|
||||
{
|
||||
$('#b_alternateseries').dojConfirmAction({
|
||||
question: 'Switch Series?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
var sid = $epgpopup.attr('sid');
|
||||
var xs = $epgpopup.attr('xs');
|
||||
var xe = $epgpopup.attr('xe');
|
||||
var reckind = $epgpopup.attr('reckind');
|
||||
|
||||
if (reckind != 4)
|
||||
{
|
||||
alert('Not a series!');
|
||||
return;
|
||||
}
|
||||
|
||||
$.blockUI({message: '<h1><img src=/img/loading.gif> ' +
|
||||
'Re-scheduling series... </h1>'});
|
||||
|
||||
$.get('/cgi-bin/epg/schedule.jim?type=2&service=' + xs + '&event=' + xe,
|
||||
function() {
|
||||
$.growl.notice({ title: 'Success', message: "Scheduled new series." });
|
||||
$.get('rpc/cancel.jim?slot=' + sid, function() {
|
||||
$epgpopup.dialog('close');
|
||||
$('.ct_event[sid=' + sid + ']')
|
||||
.addClass('purpleshade strike');
|
||||
$.unblockUI();
|
||||
$.growl.error({ title: 'Success',
|
||||
message: "Unscheduled old series." });
|
||||
page_refresh();
|
||||
});
|
||||
});
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function alternate_recording()
|
||||
{
|
||||
$('#b_alternate').dojConfirmAction({
|
||||
question: 'Move Recording?',
|
||||
yesAnswer: 'Yes',
|
||||
cancelAnswer: 'No'
|
||||
}, function(el) {
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
var sid = $epgpopup.attr('sid');
|
||||
var xs = $epgpopup.attr('xs');
|
||||
var xe = $epgpopup.attr('xe');
|
||||
var oxs = $epgpopup.attr('oxs');
|
||||
var oxe = $epgpopup.attr('oxe');
|
||||
var reckind = $epgpopup.attr('reckind');
|
||||
|
||||
// If it's a one-off event, schedule the new one and then cancel the old.
|
||||
|
||||
if (reckind != 4)
|
||||
{
|
||||
$.blockUI({message: '<h1><img src=/img/loading.gif> ' +
|
||||
'Re-scheduling one-off event... </h1>'});
|
||||
|
||||
$.get('/cgi-bin/epg/schedule.jim?type=1&service=' + xs + '&event=' + xe,
|
||||
function() {
|
||||
$.growl.notice({ title: 'Success',
|
||||
message: "Scheduled replacement event." });
|
||||
$.get('rpc/cancel.jim?slot=' + sid, function() {
|
||||
$epgpopup.dialog('close');
|
||||
$('.ct_event[sid=' + sid + ']')
|
||||
.attr('sclass', 'pending-unschedule')
|
||||
.addClass('purpleshade strike');
|
||||
$.unblockUI();
|
||||
$.growl.error({ title: 'Success',
|
||||
message: "Unscheduled original event." });
|
||||
page_refresh();
|
||||
});
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
$.blockUI({message: '<h1><img src=/img/loading.gif> ' +
|
||||
'Re-scheduling series event... </h1>'});
|
||||
|
||||
$.get('/cgi-bin/epg/schedule.jim?type=1&service=' + xs + '&event=' + xe,
|
||||
function() {
|
||||
$.growl.notice({ title: 'Success',
|
||||
message: "Scheduled replacement event." });
|
||||
$.get('rpc/skip.jim?slot=' + sid +
|
||||
'&service=' + oxs + '&event=' + oxe, function() {
|
||||
$epgpopup.dialog('close');
|
||||
$('.ct_event[sid=' + sid + ']')
|
||||
.attr('sclass', 'pending-skip')
|
||||
.addClass('purpleshade strike');
|
||||
$.unblockUI();
|
||||
$.growl.warning({ title: 'Success',
|
||||
message: "Skipped unwanted episode." });
|
||||
page_refresh();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function menuclick(action, el, pos)
|
||||
{
|
||||
var sid = $epgpopup.attr('sid');
|
||||
|
||||
switch (action)
|
||||
{
|
||||
case 'refresh':
|
||||
if (confirm('Are you sure you want to refresh events ' +
|
||||
'for this entry?'))
|
||||
$.get('rpc/refresh.jim?slot=' + sid,
|
||||
function() {
|
||||
$('.ct_event[sid=' + sid + ']')
|
||||
.attr('sclass', 'pending-refresh')
|
||||
.addClass('orangeshade');
|
||||
$.growl.warning({ title: 'Success',
|
||||
message: "The schedule entry will be " +
|
||||
"refreshed." });
|
||||
$epgpopup.dialog('close');
|
||||
list_reload_required = true;
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function update_buttons(xs, xe)
|
||||
{
|
||||
var oxs = $epgpopup.attr('oxs');
|
||||
var oxe = $epgpopup.attr('oxe');
|
||||
var sid = $epgpopup.attr('sid');
|
||||
var reckind = $epgpopup.attr('reckind');
|
||||
var ocrid = $epgpopup.attr('crid');
|
||||
var sclass = $epgpopup.attr('sclass');
|
||||
var crid = $.trim($epgpopup.find('span.scrid').text());
|
||||
|
||||
if (sid == 0 || sclass != 'tbl_reservation')
|
||||
{
|
||||
$('.ep_button').hide();
|
||||
return;
|
||||
}
|
||||
|
||||
$('#b_more').show().contextMenu({
|
||||
menu: 'optmenu',
|
||||
leftButton: true,
|
||||
position: {
|
||||
my: "center top",
|
||||
at: "center bottom+5",
|
||||
of: $('#b_more'),
|
||||
collision: "fit"
|
||||
}
|
||||
}, menuclick);
|
||||
|
||||
if (oxs == xs && oxe == xe)
|
||||
{
|
||||
// Viewing original event.
|
||||
$('#b_alternate,#b_alternateseries').hide();
|
||||
$('#b_cancel').show();
|
||||
if (reckind == 4)
|
||||
$('#b_skip').show();
|
||||
else
|
||||
$('#b_skip').hide();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Viewing alternate event.
|
||||
$('#b_alternate').show();
|
||||
$('#b_cancel,#b_skip').hide();
|
||||
if (reckind == 4 &&crid.toLowerCase() != ocrid.toLowerCase())
|
||||
$('#b_alternateseries').show();
|
||||
else
|
||||
$('#b_alternateseries').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function epgpopup(e, o, first)
|
||||
{
|
||||
if (e)
|
||||
e.preventDefault();
|
||||
var xs = o.attr('xs');
|
||||
var xe = o.attr('xe');
|
||||
|
||||
if (!xs || xs == 0 || !xe || xe == 0)
|
||||
return;
|
||||
|
||||
if (first)
|
||||
$epgpopup.attr('oxs', xs).attr('oxe', xe);
|
||||
|
||||
var url = '/cgi-bin/epg/info.jim?bare&service=' + xs + '&event=' + xe +
|
||||
'&bare=1';
|
||||
$epgpopup
|
||||
.empty().html('<img src="/img/loading.gif" alt="loading"> ' +
|
||||
'Retrieving details...')
|
||||
.load(url, function() {
|
||||
update_buttons(xs, xe);
|
||||
$epgpopup.find('a.event').on('click', function(e) {
|
||||
epgpopup(e, $(this));
|
||||
});
|
||||
})
|
||||
.attr('xs', xs)
|
||||
.attr('xe', xe)
|
||||
.dialog('open');
|
||||
}
|
||||
|
||||
$('.ct_event, .ct_debug')
|
||||
.hover(
|
||||
function() { $(this).css('cursor', 'pointer'); },
|
||||
function() { $(this).css('cursor', 'auto'); }
|
||||
)
|
||||
.qtip({
|
||||
position: {
|
||||
my: 'bottom center',
|
||||
at: 'top center',
|
||||
viewport: $(window)
|
||||
},
|
||||
style: {
|
||||
classes: 'qtip-rounded qtip-shadow'
|
||||
},
|
||||
content: {
|
||||
title: function() {
|
||||
var reckind = $(this).attr('rc');
|
||||
var rsvtype = $(this).attr('et');
|
||||
var repeat = $(this).attr('rt');
|
||||
var channel = $(this).attr('sz');
|
||||
var period = $(this).attr('period');
|
||||
var s = '';
|
||||
|
||||
schedule_icons(~~reckind, ~~rsvtype, ~~repeat)
|
||||
.forEach(function(item, index) {
|
||||
s += '<img class=visualicon '
|
||||
+ 'src=/images/'
|
||||
+ item + '.png>';
|
||||
});
|
||||
return "<span>" + s +
|
||||
'<img class=visualicon ' +
|
||||
'src="/img/channels/out/' +
|
||||
channel + '.png"></span> ' +
|
||||
"<span>" + channel +
|
||||
' (' + period + ')</span>';
|
||||
},
|
||||
text: function() {
|
||||
var t = '<center>' + $(this).html();
|
||||
var s = $(this).attr('sclass');
|
||||
|
||||
x = visual_notes[s];
|
||||
|
||||
if (x)
|
||||
t += '<div class=blood>' + x + '</div>';
|
||||
else if ($(this).hasClass('strike') ||
|
||||
$(this).hasClass('orangeshade'))
|
||||
t += '<div class=blood>' +
|
||||
'Changes pending</div>';
|
||||
|
||||
t += '</center>';
|
||||
return t;
|
||||
}
|
||||
},
|
||||
events: {
|
||||
show: function(event, api) {
|
||||
var sid = api.target.attr('sid');
|
||||
$('.ct_event[sid=' + sid + ']')
|
||||
.addClass('visual_hover');
|
||||
},
|
||||
hide: function(event, api) {
|
||||
var sid = api.target.attr('sid');
|
||||
$('.ct_event[sid=' + sid + ']')
|
||||
.removeClass('visual_hover');
|
||||
}
|
||||
}
|
||||
})
|
||||
.on('click', function(e) {
|
||||
var reckind = ~~$(this).attr('rc');
|
||||
if (reckind == 4) // Series record
|
||||
{
|
||||
$('#b_skip').show();
|
||||
$('#b_cancel .ui-button-text')
|
||||
.text('Cancel Entire Series');
|
||||
}
|
||||
else
|
||||
{
|
||||
$('#b_skip').hide();
|
||||
$('#b_cancel .ui-button-text')
|
||||
.text('Cancel Recording');
|
||||
}
|
||||
$('.ep_button').hide();
|
||||
$epgpopup.attr('reckind', reckind);
|
||||
$epgpopup.attr('sid', $(this).attr('sid'));
|
||||
$epgpopup.attr('crid', $(this).attr('crid'));
|
||||
$epgpopup.attr('sclass', $(this).attr('sclass'));
|
||||
epgpopup(e, $(this), true);
|
||||
});
|
||||
|
||||
}
|
||||
|
115
webif/html/sched/visual/style.css
Normal file
115
webif/html/sched/visual/style.css
Normal file
@ -0,0 +1,115 @@
|
||||
|
||||
fieldset.visual
|
||||
{
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.ct_visual
|
||||
{
|
||||
xborder: 1px solid red;
|
||||
min-width: 1100px;
|
||||
}
|
||||
|
||||
.ct_header
|
||||
{
|
||||
padding: 2px 6px;
|
||||
}
|
||||
|
||||
.ct_day
|
||||
{
|
||||
padding: 2px 5px;
|
||||
border-width: 2px 1px 0 1px;
|
||||
border-color: #999;
|
||||
border-style: solid;
|
||||
}
|
||||
|
||||
.ct_row
|
||||
{
|
||||
width: 100%;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.ct_dayname
|
||||
{
|
||||
xborder: 1px solid blue;
|
||||
width: 120px;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.ct_hour
|
||||
{
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
height: 25px;
|
||||
padding: 4px 0 3px 3px;
|
||||
margin: 3px 0 3px 0;
|
||||
border-right: 1px solid #ccc;
|
||||
}
|
||||
|
||||
.ct_skip, .ct_event, .ct_key
|
||||
{
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
height: 25px;
|
||||
padding: 4px 0 3px 0;
|
||||
margin: 3px 2px 3px 0;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 10px;
|
||||
-moz-border-radius: 10px;
|
||||
}
|
||||
|
||||
.ct_bskip
|
||||
{
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
vertical-align: middle;
|
||||
height: 25px;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
.visual_schedule
|
||||
{
|
||||
position: absolute;
|
||||
width: 400px;
|
||||
padding: 3px;
|
||||
margin: 5px;
|
||||
border: black solid 1px;
|
||||
}
|
||||
|
||||
img.visualicon
|
||||
{
|
||||
height: 20px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
#optprogname
|
||||
{
|
||||
color: #999;
|
||||
font-style: italic;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
|
||||
.qtip
|
||||
{
|
||||
max-width: 350px;
|
||||
}
|
||||
|
||||
.qtip span
|
||||
{
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.visual_hover
|
||||
{
|
||||
background: #f6ff5b !important;
|
||||
color: black;
|
||||
}
|
||||
|
@ -4,8 +4,8 @@ package require cgi
|
||||
source /mod/webif/lib/setup
|
||||
require settings.class
|
||||
|
||||
jqplugin enadis
|
||||
jscss xepg.js /css/xepg.css
|
||||
jqplugin enadis qtip
|
||||
jscss script.js style.css
|
||||
header
|
||||
|
||||
require epg.class spinner.class altrow epg_search totop system.class
|
||||
@ -46,8 +46,15 @@ if {$stt <= $now} {
|
||||
|
||||
set favgroup [$s channel_group]
|
||||
|
||||
set hours [expr 1.0 * [[settings] xepghours]]
|
||||
set hours [cgi_get hours -]
|
||||
if {$hours eq "-"} {
|
||||
set hours [expr 1.0 * [[settings] xepghours]]
|
||||
}
|
||||
|
||||
if {$hours == 0} { set hours 4.0 }
|
||||
if {$hours < 1} { set hours 1.0 }
|
||||
if {$hours > 8} { set hours 8.0 }
|
||||
|
||||
set seconds $($hours * 3600)
|
||||
|
||||
set ostt $stt
|
||||
@ -83,49 +90,119 @@ set got [clock milliseconds]
|
||||
proc but {label time {active 1}} {
|
||||
puts -nonewline "<button style=\"margin-right: 2em\" tt=$time"
|
||||
if {$active} {
|
||||
puts -nonewline " class=nav"
|
||||
puts -nonewline " class=\"nav delayshow\""
|
||||
} else {
|
||||
puts -nonewline " disabled class=\"nav ui-state-disabled\""
|
||||
puts -nonewline " disabled class=\"nav delayshow ui-state-disabled\""
|
||||
}
|
||||
puts " active=$active>$label</button>"
|
||||
}
|
||||
|
||||
puts "<!-- Hours $hours ($seconds) -->"
|
||||
puts "<div id=buttons style=\"width: $eventpx; margin-left: ${chanpx}px;\">"
|
||||
|
||||
but "<< -1 Week" $($stt - 3600 * 24 * 7) \
|
||||
$($stt - $now + 3600 >= 3600 * 24 * 7)
|
||||
but "<< -1 Day" $($stt - 3600 * 24) $($stt - $now >= 3600 * 23)
|
||||
but "<< Earlier" $($stt - 3600 * 4) $($stt > $now)
|
||||
#but "< Now >" $now $($current == 0)
|
||||
but "< Now >" $now
|
||||
but ">> Later" $ett;
|
||||
but ">> +1 Day" $($stt + 3600 * 24) $($stt < $now + 8 * 3600 * 24)
|
||||
but ">> +1 Week" $($stt + 3600 * 24 * 7) $($stt < $now + 8 * 3600 * 24)
|
||||
puts "<div id=timeline style=\"min-width: ${contwidth}px;\">"
|
||||
|
||||
puts "</div>"
|
||||
######################################################################
|
||||
# Time-jump bar
|
||||
|
||||
puts "
|
||||
<script type=text/javascript>
|
||||
\$('button.nav').button();
|
||||
</script>
|
||||
<div id=xepg style=\"min-width: ${contwidth}px; overflow: auto\">
|
||||
<div id=xepgnow></div>
|
||||
<div id=xegrid>
|
||||
puts "<div class=timejump_outer>
|
||||
<div class=timejump_label style=\"width: ${chanpx}px;\">
|
||||
Jump to:
|
||||
</div>
|
||||
<div class=timejump_bar>
|
||||
"
|
||||
|
||||
puts "<div id=epgdate style=\"width: ${eventpx}px; margin-left: ${chanpx}px;\">"
|
||||
puts [clock format $stt -format {%a %d/%m/%Y}]
|
||||
puts "<input type=hidden id=xepg_dp stt=$stt>"
|
||||
set starthour [clock format $stt -format "%H"]
|
||||
for {set i 0} {$i < 24} {incr i} {
|
||||
if {$i < 13} { set disp $i } else { set disp $($i - 12) }
|
||||
if {!$disp} { set disp 12 }
|
||||
|
||||
set xclass ""
|
||||
|
||||
if {$i == $starthour} {
|
||||
append xclass " tjstart"
|
||||
} elseif {$i > $starthour && $i < [expr $starthour + $hours]} {
|
||||
append xclass " tjother"
|
||||
}
|
||||
|
||||
set tt [expr $starthour + $stt + 3600 * ($i - $starthour)]
|
||||
# Back to start of hour (no floor() in Humax Jim)
|
||||
set tt $(3600 * round(1 + $tt / 3600))
|
||||
|
||||
if {$xclass ne "" || $i == 0 || $i == 12} {
|
||||
append disp "<br>[clock format $tt -format %p]"
|
||||
}
|
||||
|
||||
puts "<div tt=$tt class=\"timejump$xclass\">$disp</div>\n"
|
||||
}
|
||||
|
||||
puts "</div> "
|
||||
but "Now" $now
|
||||
puts "</div>"
|
||||
|
||||
puts "<div class=xechan style=\"width: ${chanpx}px;\"> </div>"
|
||||
######################################################################
|
||||
# Day-jump bar
|
||||
|
||||
puts "<div class=dayjump_outer>
|
||||
<div class=dayjump_label style=\"width: ${chanpx}px;\"></div>
|
||||
<div class=dayjump_bar>
|
||||
"
|
||||
|
||||
set stt_time [clock format $stt -format "%H:%M"]
|
||||
for {set i 0} {$i < 8} {incr i} {
|
||||
set day $($now + $i * 86400)
|
||||
if {!$i} {
|
||||
set s "Today"
|
||||
} else {
|
||||
set s [clock format $day -format "%A"]
|
||||
}
|
||||
set xclass ""
|
||||
if {[clock format $day -format "%j"] == \
|
||||
[clock format $stt -format "%j"]} {
|
||||
append xclass " dayjump_current"
|
||||
}
|
||||
|
||||
set tt [clock scan \
|
||||
[clock format $day -format "%Y:%m:%d:$stt_time"] \
|
||||
-format "%Y:%m:%d:%H:%M"]
|
||||
set alt [clock format $tt -format "%e %B"]
|
||||
|
||||
puts "<div tt=$tt title=\"$alt\" class=\"dayjump$xclass\">$s</div>\n"
|
||||
}
|
||||
|
||||
puts "</div>"
|
||||
puts "<span class=\"footnote delayshow\">
|
||||
(Right-Click to select end hour)</span>"
|
||||
puts "</div>"
|
||||
|
||||
######################################################################
|
||||
# Time-line bar
|
||||
|
||||
# Displays the top border above the timeline.
|
||||
puts "
|
||||
<div id=epgdate style=\"width: ${eventpx}px; margin-left: ${chanpx}px;\">
|
||||
</div>
|
||||
<div class=xedate style=\"width: ${chanpx}px;\">
|
||||
[clock format $stt -format "%A %e %B"] </div>
|
||||
"
|
||||
|
||||
for {set i 0} {$i < $hours * 2} {incr i} {
|
||||
puts "<div class=xetime id=xe$i
|
||||
style=\"width: [expr $minpx * 30]px\">"
|
||||
puts "[clock format $($stt + 1800 * $i) -format "%H:%M"]</div>"
|
||||
}
|
||||
|
||||
# Close timeline div
|
||||
puts "</div>"
|
||||
|
||||
######################################################################
|
||||
# Events
|
||||
|
||||
puts "
|
||||
<div id=xepgnow></div>
|
||||
<div id=xepg style=\"min-width: ${contwidth}px;\">
|
||||
<div id=xegrid>
|
||||
"
|
||||
|
||||
set lim 0
|
||||
set lcn 0
|
||||
set bg "odd"
|
||||
@ -218,6 +295,10 @@ puts "
|
||||
Switch to standard now/next display.
|
||||
</button></small>
|
||||
</div>
|
||||
<script type=text/javascript>
|
||||
var hours = $hours;
|
||||
var stt = [expr $stt + 0];
|
||||
</script>
|
||||
"
|
||||
|
||||
if {$current} {
|
||||
@ -231,13 +312,14 @@ var kt = $('#xe0');
|
||||
var ktpos = kt.position();
|
||||
|
||||
var height = $('#keypos').position().top - ktpos.top;
|
||||
var top = ktpos.top - 25;
|
||||
|
||||
}
|
||||
puts "var nowpos = ktpos.left + (kt.width() * $offset);"
|
||||
puts {
|
||||
$('#xepgnow')
|
||||
.css('left', nowpos + 'px')
|
||||
.css('top', ktpos.top)
|
||||
.css('top', top)
|
||||
.height(height)
|
||||
.show('slow');
|
||||
}
|
78
webif/html/xepg/script.js
Normal file
78
webif/html/xepg/script.js
Normal file
@ -0,0 +1,78 @@
|
||||
$(function() {
|
||||
|
||||
$('#epgswitch').button().click(function() {
|
||||
window.location = '/epg/list.jim';
|
||||
});
|
||||
|
||||
$('button.nav').button().click(function() {
|
||||
window.location = '/xepg/?stt=' + $(this).attr('tt') +
|
||||
'&pos=' + $('#xegrid').scrollTop();
|
||||
});
|
||||
|
||||
$('div.xeprog').qtip({
|
||||
position: {
|
||||
my: 'bottom center',
|
||||
at: 'top center',
|
||||
viewport: $(window)
|
||||
},
|
||||
style: {
|
||||
classes: 'qtip-rounded qtip-shadow'
|
||||
}
|
||||
});
|
||||
|
||||
$('.timejump').hover(
|
||||
function() {
|
||||
$(this).css('cursor', 'pointer');
|
||||
$(this).addClass('timejump_hover')
|
||||
$(this).nextAll('.timejump').slice(0,hours-1)
|
||||
.addClass('timejump_hover');
|
||||
},
|
||||
function() {
|
||||
$(this).css('cursor', 'auto');
|
||||
$(this).removeClass('timejump_hover')
|
||||
$(this).nextAll('.timejump').slice(0,hours-1)
|
||||
.removeClass('timejump_hover');
|
||||
}
|
||||
).on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
tt = $(this).attr('tt');
|
||||
|
||||
window.location = '/xepg/?stt=' + tt +
|
||||
'&hours=' + hours +
|
||||
'&pos=' + $('#xegrid').scrollTop();
|
||||
}).on('contextmenu', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
tt = $(this).attr('tt');
|
||||
|
||||
// Change the end hour.
|
||||
nhours = Math.ceil((tt - stt) / 3600) + 1;
|
||||
if (nhours > 1)
|
||||
hours = nhours;
|
||||
window.location = '/xepg/?stt=' + stt +
|
||||
'&hours=' + hours +
|
||||
'&pos=' + $('#xegrid').scrollTop();
|
||||
});
|
||||
|
||||
$('.dayjump').hover(
|
||||
function() {
|
||||
$(this).css('cursor', 'pointer');
|
||||
$(this).addClass('dayjump_hover')
|
||||
},
|
||||
function() {
|
||||
$(this).css('cursor', 'auto');
|
||||
$(this).removeClass('dayjump_hover')
|
||||
}
|
||||
).on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
||||
window.location = '/xepg/?stt=' + $(this).attr('tt') +
|
||||
'&hours=' + hours +
|
||||
'&pos=' + $('#xegrid').scrollTop();
|
||||
});
|
||||
|
||||
$('.delayshow').show();
|
||||
|
||||
});
|
||||
|
@ -58,6 +58,15 @@ div.xerow
|
||||
{
|
||||
}
|
||||
|
||||
div.xedate
|
||||
{
|
||||
float: left;
|
||||
clear: left;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
div.xechan
|
||||
{
|
||||
vertical-align: middle;
|
||||
@ -116,3 +125,74 @@ button#later
|
||||
margin-left: 0px !important;
|
||||
}
|
||||
|
||||
.timejump_outer, .dayjump_outer
|
||||
{
|
||||
}
|
||||
|
||||
.timejump_bar, .dayjump_bar
|
||||
{
|
||||
padding: 4px;
|
||||
background: #e6e6e6;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.dayjump_bar
|
||||
{
|
||||
padding-top: 0;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
.timejump_label, .dayjump_label
|
||||
{
|
||||
text-align: right;
|
||||
font-style: italic;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.timejump
|
||||
{
|
||||
display: inline-block;
|
||||
width: 25px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 1em;
|
||||
border-radius: 5px;
|
||||
padding: 2px 0;
|
||||
}
|
||||
|
||||
.dayjump
|
||||
{
|
||||
display: inline-block;
|
||||
width: 85px;
|
||||
text-align: center;
|
||||
vertical-align: middle;
|
||||
line-height: 1em;
|
||||
padding: 2px 0 5px 0;
|
||||
border-top: 1px solid #73e600;
|
||||
}
|
||||
|
||||
.timejump_hover, .dayjump_hover
|
||||
{
|
||||
background: #ffffcc !important;
|
||||
}
|
||||
|
||||
.dayjump_current
|
||||
{
|
||||
border-radius: 10px;
|
||||
}
|
||||
|
||||
.tjstart, .dayjump_current
|
||||
{
|
||||
background: #73e600;
|
||||
}
|
||||
|
||||
.tjother
|
||||
{
|
||||
background: #ccff99;
|
||||
}
|
||||
|
||||
.delayshow
|
||||
{
|
||||
display: none;
|
||||
}
|
||||
|
@ -813,7 +813,7 @@ if {[lindex $argv 0] eq "-singledir"} {
|
||||
}
|
||||
}
|
||||
|
||||
release_lock webif_auto
|
||||
if {!$prelocked} { release_lock webif_auto }
|
||||
|
||||
log "Media scan completed in [elapsed $scanstart] seconds."
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
puts {
|
||||
<div id=dialogue></div>
|
||||
<div id=epgpopup_dialogue></div>
|
||||
<script type=text/javascript src=/js/epg_popup.js></script>
|
||||
}
|
||||
|
||||
|
@ -17,9 +17,8 @@ if {![file exists /var/lib/humaxtv/rsvp.db]} {
|
||||
$tdb close
|
||||
}
|
||||
$rsvdb query {attach database '/var/lib/humaxtv/rsvp.db' as pending}
|
||||
# This is required to upgrade old tables and will be removed in a future
|
||||
# version.
|
||||
catch { $rsvdb query {alter table pending add column action int} }
|
||||
# These are required to upgrade old tables.
|
||||
catch { $rsvdb query { alter table pending add column action int} }
|
||||
|
||||
set binaryfields aulEventToRecordInfo
|
||||
|
||||
@ -54,6 +53,8 @@ class rsv {
|
||||
usLcn 0
|
||||
sort 0
|
||||
action 0
|
||||
_table ""
|
||||
_origstart 0
|
||||
}
|
||||
|
||||
require findhsvc
|
||||
@ -156,6 +157,10 @@ rsv method start {} {
|
||||
return $nsttime
|
||||
}
|
||||
|
||||
rsv method end {} {
|
||||
return $([$self start] + $nduration)
|
||||
}
|
||||
|
||||
rsv method icon {} {
|
||||
set rsvicon ""
|
||||
switch $ersvtype {
|
||||
@ -224,6 +229,10 @@ rsv method iconset {{height 20}} {
|
||||
return $iconlist
|
||||
}
|
||||
|
||||
rsv method setorigstart {o} {
|
||||
set _origstart $o
|
||||
}
|
||||
|
||||
rsv method set_delete {} {
|
||||
set action 1
|
||||
}
|
||||
@ -319,7 +328,10 @@ rsv method insert {{table pending} {force 0}} {
|
||||
if {$ulslot < 0} { set ulslot 0 }
|
||||
}
|
||||
|
||||
set fields [lsort [$self vars]]
|
||||
set fields [lsort [lmap i [$self vars] {
|
||||
if {[string index $i 0] eq "_"} continue
|
||||
concat "" $i
|
||||
}]]
|
||||
|
||||
foreach field {szSvcName usLcn sort} {
|
||||
set df [lsearch $fields $field]
|
||||
@ -379,6 +391,7 @@ proc {rsv list} {{table tbl_reservation} {extra ""}} {
|
||||
set res [$::rsvdb query $qstring]
|
||||
set records {}
|
||||
foreach rec $res {
|
||||
lappend rec _table $table
|
||||
lappend records [rsv new $rec]
|
||||
}
|
||||
|
||||
@ -872,31 +885,214 @@ proc {rsv restore} {file} {
|
||||
close $fd
|
||||
}
|
||||
|
||||
# Check for scheduled events at the same time
|
||||
proc {rsv conflicts} {s d} {
|
||||
global rsvdb
|
||||
set query "
|
||||
select count(*) as num
|
||||
from TBL_RESERVATION
|
||||
where ersvtype <= 3
|
||||
and (
|
||||
(
|
||||
nsttime >= $s
|
||||
and nsttime < $s + $d
|
||||
) or (
|
||||
nsttime + nduration > $s
|
||||
and nsttime + nduration <= $s + $d
|
||||
) or (
|
||||
nsttime <= $s
|
||||
and nsttime + nduration >= $s + $d
|
||||
))
|
||||
"
|
||||
set ret [$rsvdb query $query]
|
||||
# Returns an array of expanded events from the schedule.
|
||||
# Array keys:
|
||||
# 0: start
|
||||
# 1: end
|
||||
# 2: hSvc
|
||||
# 3: event_id
|
||||
# 4: Schedule ID (sid)
|
||||
# 5: ucRecKind
|
||||
# 6: class (live, pending)
|
||||
|
||||
set num 0
|
||||
if {[llength $ret] > 0} {
|
||||
lassign [lindex $ret 0] x num
|
||||
proc {rsv allevents} {{xota 0}} {
|
||||
set events [rsv list]
|
||||
set pending [rsv list pending]
|
||||
if {[llength $pending]} {
|
||||
lappend events {*}$pending
|
||||
}
|
||||
return $num
|
||||
|
||||
set xevents {}
|
||||
|
||||
foreach e $events {
|
||||
set seen 0
|
||||
|
||||
if {$xota && [$e get szevtname] eq "Disable OTA"} continue
|
||||
|
||||
if {[$e get action] ne "0"} continue
|
||||
|
||||
set trailer [list \
|
||||
[$e get ulslot] \
|
||||
[$e get ucRecKind] \
|
||||
[$e get _table] \
|
||||
]
|
||||
|
||||
# Expand the events encoded in the AUL data.
|
||||
foreach a [$e aul] {
|
||||
lassign $a service start end event_id
|
||||
if {$start == [$e start] && \
|
||||
$end == [$e end]} {
|
||||
incr seen
|
||||
}
|
||||
lappend xevents [list $start $end $service $event_id \
|
||||
{*}$trailer]
|
||||
}
|
||||
|
||||
if {$seen} continue
|
||||
|
||||
set start [$e start]
|
||||
set end [$e end]
|
||||
|
||||
lappend xevents [list $start $end \
|
||||
[$e get hsvc] [$e get usevtid] {*}$trailer]
|
||||
|
||||
set repeat [$e get erepeat]
|
||||
switch $repeat {
|
||||
1 -
|
||||
3 -
|
||||
4 {
|
||||
# 1 Daily
|
||||
# 3 Weekends
|
||||
# 4 Weekdays
|
||||
|
||||
for {set i 0} {$i < 8} {incr i} {
|
||||
|
||||
incr start 86400
|
||||
incr end 86400
|
||||
|
||||
# Sun == 0
|
||||
set day [clock format [$e start] \
|
||||
-format "%w"]
|
||||
|
||||
# Weekdays Only
|
||||
if {$repeat == 3 && ($day == 0 || $day == 6)} {
|
||||
continue
|
||||
}
|
||||
|
||||
# Weekends Only
|
||||
if {$repeat == 4 && $day != 0 && $day != 6} {
|
||||
continue
|
||||
}
|
||||
|
||||
lappend xevents [list \
|
||||
$start $end \
|
||||
[$e get hsvc] [$e get usevtid] \
|
||||
{*}$trailer]
|
||||
}
|
||||
}
|
||||
2 {
|
||||
# Weekly
|
||||
lappend xevents [list \
|
||||
$($start + 7 * 86400) \
|
||||
$($end + 7 * 86400) \
|
||||
[$e get hsvc] [$e get usevtid] \
|
||||
{*}$trailer]
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $xevents
|
||||
}
|
||||
|
||||
proc {rsv evaluate_conflicts} {events type thresh {debug 0}} {
|
||||
set conflicts {}
|
||||
set slots {0 0}
|
||||
foreach ev $events {
|
||||
lassign $ev start end hsvc eid sid
|
||||
|
||||
if {$debug} {
|
||||
puts "\nSLOTS: $slots"
|
||||
puts $ev
|
||||
}
|
||||
|
||||
# Close off any open slots that have now finished.
|
||||
for {set i 0} {$i < 2} {incr i} {
|
||||
set v [lindex $slots $i]
|
||||
if {$v eq "0"} {
|
||||
if {$debug} { puts "\[$i] empty." }
|
||||
continue
|
||||
}
|
||||
|
||||
lassign $v xsid xend
|
||||
|
||||
if {$start >= $xend} {
|
||||
lset slots $i 0
|
||||
if {$debug} { puts "\[$i] finished $xend." }
|
||||
} else {
|
||||
if {$debug} { puts "\[$i] running $xend." }
|
||||
}
|
||||
}
|
||||
|
||||
# Find slot for recording
|
||||
if {[lindex $slots 0] eq "0"} {
|
||||
set uslot 0
|
||||
} elseif {$thresh > 1 && [lindex $slots 1] eq "0"} {
|
||||
set uslot 1
|
||||
} else {
|
||||
# Conflict detected
|
||||
if {$debug} { puts " Conflict." }
|
||||
if {$type eq "xlist"} {
|
||||
set c "$sid$end"
|
||||
for {set i 0} {$i < 2} {incr i} {
|
||||
set v [lindex $slots $i]
|
||||
if {$v eq "0"} continue
|
||||
|
||||
lassign $v xsid xend
|
||||
|
||||
lappend c "$xsid$xend"
|
||||
}
|
||||
} else {
|
||||
set c "$sid"
|
||||
for {set i 0} {$i < 2} {incr i} {
|
||||
set v [lindex $slots $i]
|
||||
if {$v eq "0"} continue
|
||||
|
||||
lassign $v xsid xend
|
||||
|
||||
lappend c "$xsid"
|
||||
}
|
||||
}
|
||||
foreach x $c {
|
||||
if {![dict exists $conflicts $x]} {
|
||||
set conflicts($x) $c
|
||||
}
|
||||
}
|
||||
|
||||
# If this events ends later than the
|
||||
# existing one in slot 0, then replace that
|
||||
# with this one.
|
||||
|
||||
lassign [lindex $slots 0] xsid xend
|
||||
if {$xend >= $end} continue
|
||||
if {$debug} { puts " Replacing slot 0.\n" }
|
||||
set uslot 0
|
||||
}
|
||||
|
||||
if {$debug} {
|
||||
puts " -> into slot $uslot"
|
||||
}
|
||||
# Insert event into slot
|
||||
lset slots $uslot [list $sid $end]
|
||||
}
|
||||
return $conflicts
|
||||
}
|
||||
|
||||
proc {rsv newconflicts} {{thresh 1} {type "list"} {debug 0}} {
|
||||
set events [lsort -index 0 -integer [rsv allevents]]
|
||||
set conflicts [rsv evaluate_conflicts $events $type $thresh $debug]
|
||||
|
||||
if {$type eq "map"} { return $conflicts }
|
||||
return [dict keys $conflicts]
|
||||
}
|
||||
|
||||
proc {rsv checkconflict} {s d thresh {debug 0}} {
|
||||
set events [rsv allevents]
|
||||
lappend events [list $s $($s + $d) 0 0 0]
|
||||
set events [lsort -index 0 -integer $events]
|
||||
set conflicts [rsv evaluate_conflicts $events 'list' $thresh $debug]
|
||||
|
||||
set ret {}
|
||||
|
||||
if {![dict exists $conflicts "0"]} { return $ret }
|
||||
|
||||
foreach c [dict get $conflicts 0] {
|
||||
if {$c eq "0"} continue
|
||||
set s [rsv slot $c]
|
||||
set s [$s name]
|
||||
lappend ret $s
|
||||
}
|
||||
|
||||
return $ret
|
||||
}
|
||||
|
||||
|
@ -54,9 +54,10 @@ if {![exists -proc require]} {
|
||||
incr ::mws::headerdone
|
||||
}
|
||||
|
||||
proc noheader {} {
|
||||
proc noheader {{type "text/html"} {cache 0}} {
|
||||
httpheader $type $cache
|
||||
uplevel source /mod/webif/html/lib/noheader.jim
|
||||
incr ::mws::headerdone
|
||||
::mws::emit_jscss
|
||||
}
|
||||
|
||||
proc footer {} {
|
||||
|
@ -12,3 +12,7 @@ proc lremove {var val} {
|
||||
set v [lsearch -all -inline -not -exact $v $val]
|
||||
}
|
||||
|
||||
proc ladd {l} {
|
||||
expr [join $l +] + 0
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user