diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index 0d499c9d6..7ff27b7bb 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -43,7 +43,7 @@ class LibraryController extends Zend_Controller_Action $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.pluginAPI.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.fnSetFilteringDelay.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColVis.js','text/javascript'); - $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColReorderResize.js','text/javascript'); + $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColReorder.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.FixedColumns.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/library.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/airtime/library/advancedsearch.js','text/javascript'); diff --git a/airtime_mvc/application/controllers/ShowbuilderController.php b/airtime_mvc/application/controllers/ShowbuilderController.php index 85d491fde..eb383c159 100644 --- a/airtime_mvc/application/controllers/ShowbuilderController.php +++ b/airtime_mvc/application/controllers/ShowbuilderController.php @@ -19,10 +19,6 @@ class ShowbuilderController extends Zend_Controller_Action $this->_helper->actionStack('library', 'library'); $this->_helper->actionStack('builder', 'showbuilder'); - - //user is allowed to schedule this show. - //if ($user->isAdmin() || $user->isHost($show_instance->getShowId())) { - //} } public function builderAction() { @@ -33,9 +29,9 @@ class ShowbuilderController extends Zend_Controller_Action $this->view->headScript()->appendFile($baseUrl.'/js/timepicker/jquery.ui.timepicker.js','text/javascript'); $this->view->headScript()->appendScript("var serverTimezoneOffset = ".date("Z")."; //in seconds"); - $this->view->headScript()->appendFile($baseUrl.'/js/datatables/js/jquery.dataTables.js','text/javascript'); - $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColVis.js','text/javascript'); - $this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColReorderResize.js','text/javascript'); + //$this->view->headScript()->appendFile($baseUrl.'/js/datatables/js/jquery.dataTables.js','text/javascript'); + //$this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColVis.js','text/javascript'); + //$this->view->headScript()->appendFile($baseUrl.'/js/datatables/plugin/dataTables.ColReorder.js','text/javascript'); $this->view->headScript()->appendFile($baseUrl.'/js/airtime/showbuilder/builder.js','text/javascript'); $this->view->headLink()->appendStylesheet($baseUrl.'/css/jquery.ui.timepicker.css'); @@ -46,23 +42,21 @@ class ShowbuilderController extends Zend_Controller_Action public function builderFeedAction() { $request = $this->getRequest(); - $current_time = microtime(true); + $current_time = time(); $starts_epoch = $request->getParam("start", $current_time); //default ends is 24 hours after starts. $ends_epoch = $request->getParam("end", $current_time + (60*60*24)); - $startsDT = DateTime::createFromFormat("U.u", $starts_epoch, new DateTimeZone("UTC")); - $endsDT = DateTime::createFromFormat("U.u", $ends_epoch, new DateTimeZone("UTC")); + $startsDT = DateTime::createFromFormat("U", $starts_epoch, new DateTimeZone("UTC")); + $endsDT = DateTime::createFromFormat("U", $ends_epoch, new DateTimeZone("UTC")); - $scheduled_items = Application_Model_Schedule::GetItems($startsDT->format("Y-m-d H:i:s.u"), $endsDT->format("Y-m-d H:i:s.u"), false); + Logging::log("showbuilder starts {$startsDT->format("Y-m-d H:i:s")}"); + Logging::log("showbuilder ends {$endsDT->format("Y-m-d H:i:s")}"); - foreach ($scheduled_items as &$item) { - $itemStartsDT = DateTime::createFromFormat("Y-m-d H:i:s.u", $item["starts"], new DateTimeZone("UTC")); - $itemEndsDT = DateTime::createFromFormat("Y-m-d H:i:s.u", $item["ends"], new DateTimeZone("UTC")); - } + $showBuilder = new Application_Model_ShowBuilder($startsDT, $endsDT); - $this->view->schedule = $scheduled_items; + $this->view->schedule = $showBuilder->GetItems(); } public function scheduleAction() { diff --git a/airtime_mvc/application/models/Schedule.php b/airtime_mvc/application/models/Schedule.php index a0c8f3a5e..1884a4ea5 100644 --- a/airtime_mvc/application/models/Schedule.php +++ b/airtime_mvc/application/models/Schedule.php @@ -309,10 +309,15 @@ class Application_Model_Schedule { $sql = "SELECT DISTINCT - showt.name, showt.color, showt.background_color, - si.starts, si.ends, si.time_filled, si.record, si.rebroadcast, - sched.starts, sched.ends, - ft.track_title, ft.artist_name, ft.album_title, ft.length + showt.name AS show_name, showt.color AS show_color, showt.background_color AS show_background_colour, + + si.starts AS si_starts, si.ends AS si_ends, si.time_filled AS si_time_filled, + si.record AS si_record, si.rebroadcast AS si_rebroadcast, si.id AS si_id, + + sched.starts AS sched_starts, sched.ends AS sched_ends, + + ft.track_title AS file_track_title, ft.artist_name AS file_artist_name, + ft.album_title AS file_album_title, ft.length AS file_length FROM ((cc_schedule AS sched JOIN cc_files AS ft ON (sched.file_id = ft.id) @@ -320,7 +325,11 @@ class Application_Model_Schedule { JOIN cc_show AS showt ON (showt.id = si.show_id) ) - ORDER BY sched.starts;"; + WHERE si.starts >= '{$p_startDateTime}' AND si.ends <= '{$p_endDateTime}' + + ORDER BY si.starts, sched.starts;"; + + //Logging::log($sql); $rows = $CC_DBC->GetAll($sql); return $rows; diff --git a/airtime_mvc/application/models/ShowBuilder.php b/airtime_mvc/application/models/ShowBuilder.php new file mode 100644 index 000000000..c031a3057 --- /dev/null +++ b/airtime_mvc/application/models/ShowBuilder.php @@ -0,0 +1,111 @@ + false, + "footer" => false, + "empty" => false, + "instance" => "", + "starts" => "", + "ends" => "", + "title" => "" + ); + + /* + * @param DateTime $p_startsDT + * @param DateTime $p_endsDT + */ + public function __construct($p_startDT, $p_endDT) { + + $this->startDT = $p_startDT; + $this->endDT = $p_endDT; + $this->timezone = date_default_timezone_get(); + } + + private function makeFooterRow() { + + $row = $this->defaultRowArray; + $row["footer"] = true; + + return $row; + } + + private function makeHeaderRow($p_item) { + + $row = $this->defaultRowArray; + + $showStartDT = new DateTime($p_item["si_starts"], new DateTimeZone("UTC")); + $showStartDT->setTimezone(new DateTimeZone($this->timezone)); + $showEndDT = new DateTime($p_item["si_ends"], new DateTimeZone("UTC")); + $showEndDT->setTimezone(new DateTimeZone($this->timezone)); + + $row["header"] = true; + $row["starts"] = $showStartDT->format("Y-m-d H:i"); + $row["ends"] = $showEndDT->format("Y-m-d H:i"); + $row["title"] = $p_item["show_name"]; + + return $row; + } + + private function makeScheduledItemRow($p_item) { + $row = $this->defaultRowArray; + + if (isset($p_item["sched_starts"])) { + + $schedStartDT = new DateTime($p_item["sched_starts"], new DateTimeZone("UTC")); + $schedStartDT->setTimezone(new DateTimeZone($this->timezone)); + $schedEndDT = new DateTime($p_item["sched_ends"], new DateTimeZone("UTC")); + $schedEndDT->setTimezone(new DateTimeZone($this->timezone)); + + $row["instance"] = $p_item["si_id"]; + $row["starts"] = $schedStartDT->format("Y-m-d H:i:s"); + $row["ends"] = $schedEndDT->format("Y-m-d H:i:s"); + $row["title"] = $p_item["file_track_title"]; + } + //show is empty + else { + $row["empty"] = true; + } + + return $row; + } + + public function GetItems() { + + $current_id = -1; + $display_items = array(); + + $scheduled_items = Application_Model_Schedule::GetScheduleDetailItems($this->startDT->format("Y-m-d H:i:s"), $this->endDT->format("Y-m-d H:i:s")); + + foreach ($scheduled_items as $item) { + + //make a header row. + if ($current_id !== $item["si_id"]) { + + //make a footer row. + if ($current_id !== -1) { + $display_items[] = $this->makeFooterRow(); + } + + $display_items[] = $this->makeHeaderRow($item); + + $current_id = $item["si_id"]; + } + + //make a normal data row. + $display_items[] = $this->makeScheduledItemRow($item); + } + + //make the last footer if there were any scheduled items. + if (count($scheduled_items) > 0) { + $display_items[] = $this->makeFooterRow(); + } + + return $display_items; + } +} \ No newline at end of file diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css index e2acc5daa..703d105c3 100644 --- a/airtime_mvc/public/css/styles.css +++ b/airtime_mvc/public/css/styles.css @@ -523,6 +523,11 @@ dl.inline-list dd { .even { background-color:#c7c7c7; } + +.datatable .show-builder-placeholder { + height: 30px; +} + .datatable tr.even.selected td { background-color: #abcfe2; } diff --git a/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js b/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js index 87c70d1cb..2fcec1285 100644 --- a/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js +++ b/airtime_mvc/public/js/airtime/library/events/library_playlistbuilder.js @@ -1,11 +1,11 @@ -function dtRowCallback( nRow, aData, iDisplayIndex, iDisplayIndexFull ) { +function fnLibraryTableRowCallback( nRow, aData, iDisplayIndex, iDisplayIndexFull ) { $(nRow).attr("id", aData["id"]); return nRow; } -function dtDrawCallback() { +function fnLibraryTableDrawCallback() { addLibraryItemEvents(); addMetadataQtip(); //saveNumEntriesSetting(); @@ -33,4 +33,3 @@ function setupLibraryToolbar() { 'Delete' + 'Add'); } - diff --git a/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js b/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js index 2070f9add..d380578a0 100644 --- a/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js +++ b/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js @@ -1,4 +1,4 @@ -function dtRowCallback( nRow, aData, iDisplayIndex, iDisplayIndexFull ) { +function fnLibraryTableRowCallback( nRow, aData, iDisplayIndex, iDisplayIndexFull ) { $(nRow).attr("id", aData["id"]); @@ -7,7 +7,7 @@ function dtRowCallback( nRow, aData, iDisplayIndex, iDisplayIndexFull ) { return nRow; } -function dtDrawCallback() { +function fnLibraryTableDrawCallback() { addLibraryItemEvents(); //addMetadataQtip(); //setupGroupActions(); @@ -28,4 +28,7 @@ function addLibraryItemEvents() { {id: getId, type: getType}, {xposition: "mouse", yposition: "mouse"}); +} + +function setupLibraryToolbar() { } \ No newline at end of file diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js index 31b776f59..fac705b37 100644 --- a/airtime_mvc/public/js/airtime/library/library.js +++ b/airtime_mvc/public/js/airtime/library/library.js @@ -467,8 +467,8 @@ function createDataTable(data) { "success": testCallback } ); }, - "fnRowCallback": dtRowCallback, - "fnDrawCallback": dtDrawCallback, + "fnRowCallback": fnLibraryTableRowCallback, + "fnDrawCallback": fnLibraryTableDrawCallback, "aoColumns": [ /* Checkbox */ {"sTitle": "", "bSortable": false, "bSearchable": false, "mDataProp": "checkbox", "sWidth": "25px", "sClass": "library_checkbox"}, /* Id */ {"sName": "id", "bSearchable": false, "bVisible": false, "mDataProp": "id", "sClass": "library_id"}, @@ -507,6 +507,8 @@ function createDataTable(data) { }); dTable.fnSetFilteringDelay(350); + setupLibraryToolbar(); + $('#library_order_reset').click(function() { ColReorder.fnReset( dTable ); return false; diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js index 02359e0d5..dd7133286 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js @@ -1,3 +1,4 @@ +/* function tpStartOnHourShowCallback(hour) { var tpEndHour = $('#show_builder_timepicker_end').timepicker('getHour'); @@ -39,6 +40,7 @@ function tpEndOnMinuteShowCallback(hour, minute) { // if minute did not match, it can not be selected return false; } +*/ /* * Get the schedule range start in unix timestamp form (in seconds). @@ -56,8 +58,8 @@ function fnGetUIPickerUnixTimestamp(sDatePickerId, sTimePickerId) { iTime, iHour, iMin, - iClientOffset, - iServerOffset; + iServerOffset, + iClientOffset; oDate = $( sDatePickerId ).datepicker( "getDate" ); @@ -74,26 +76,53 @@ function fnGetUIPickerUnixTimestamp(sDatePickerId, sTimePickerId) { iTime = oDate.getTime(); //value is in millisec. iTime = Math.round(iTime / 1000); - iClientOffset = -(oDate.getTimezoneOffset() * 60); //offset is returned in minutes. iServerOffset = serverTimezoneOffset; + iClientOffset = oDate.getTimezoneOffset() * 60;//function returns minutes + + //adjust for the fact the the Date object is + iTime = iTime + iServerOffset + iClientOffset; return iTime; } - +/* + * Returns an object containing a unix timestamp in seconds for the start/end range + * + * @return Object {"start", "end", "range"} + */ function fnGetScheduleRange() { var iStart, iEnd, - iRange; + iRange, + MIN_RANGE = 60*60*24; iStart = fnGetUIPickerUnixTimestamp("#show_builder_datepicker_start", "#show_builder_timepicker_start"); iEnd = fnGetUIPickerUnixTimestamp("#show_builder_datepicker_end", "#show_builder_timepicker_end"); iRange = iEnd - iStart; + + //return min range + if (iRange < MIN_RANGE){ + iEnd = iStart + MIN_RANGE; + iRange = MIN_RANGE; + } + + return { + start: iStart, + end: iEnd, + range: iRange + }; } -function fnServerData( sSource, aoData, fnCallback ) { +var fnServerData = function fnServerData( sSource, aoData, fnCallback ) { aoData.push( { name: "format", value: "json"} ); + if (fnServerData.hasOwnProperty("start")) { + aoData.push( { name: "start", value: fnServerData.start} ); + } + if (fnServerData.hasOwnProperty("end")) { + aoData.push( { name: "end", value: fnServerData.end} ); + } + $.ajax( { "dataType": "json", "type": "GET", @@ -101,16 +130,70 @@ function fnServerData( sSource, aoData, fnCallback ) { "data": aoData, "success": fnCallback } ); -} +}; + +var fnShowBuilderRowCallback = function ( nRow, aData, iDisplayIndex, iDisplayIndexFull ){ + var i, + sSeparatorHTML, + fnPrepareSeparatorRow; + + fnPrepareSeparatorRow = function(sRowContent, sClass) { + var node; + + node = nRow.children[0]; + node.innerHTML = sRowContent; + node.setAttribute('colspan',100); + for (i = 1; i < nRow.children.length; i = i+1) { + node = nRow.children[i]; + node.innerHTML = ""; + node.setAttribute("style", "display : none"); + } + + nRow.className = sClass; + }; + + if (aData.header === true) { + sSeparatorHTML = ''+aData.title+''+aData.starts+''+aData.ends+''; + fnPrepareSeparatorRow(sSeparatorHTML, "show-builder-header"); + } + else if (aData.footer === true) { + sSeparatorHTML = 'Show Footer'; + fnPrepareSeparatorRow(sSeparatorHTML, "show-builder-footer"); + } + + return nRow; +}; $(document).ready(function() { - var dTable; + var dTable, + oBaseDatePickerSettings, + oBaseTimePickerSettings; + + oBaseDatePickerSettings = { + dateFormat: 'yy-mm-dd', + onSelect: function(sDate, oDatePicker) { + var oDate, + dInput; + + dInput = $(this); + oDate = dInput.datepicker( "setDate", sDate ); + } + }; + + oBaseTimePickerSettings = { + showPeriodLabels: false, + showCloseButton: true, + showLeadingZero: false, + defaultTime: '0:00' + }; dTable = $('#show_builder_table').dataTable( { "aoColumns": [ + /* hidden */ {"mDataProp": "instance", "bVisible": false, "sTitle": "hidden"}, + /* instance */{"mDataProp": "instance", "sTitle": "si_id"}, /* starts */{"mDataProp": "starts", "sTitle": "starts"}, /* ends */{"mDataProp": "ends", "sTitle": "ends"}, - /* title */{"mDataProp": "file_id", "sTitle": "file_id"} + /* title */{"mDataProp": "title", "sTitle": "track_title"} ], "asStripClasses": [ 'odd' ], @@ -123,6 +206,11 @@ $(document).ready(function() { "bInfo": false, "fnServerData": fnServerData, + "fnRowCallback": fnShowBuilderRowCallback, + + "oColVis": { + "aiExclude": [ 0 ] + }, // R = ColReorder, C = ColVis, see datatables doc for others "sDom": 'Rr<"H"C>t<"F">', @@ -137,53 +225,33 @@ $(document).ready(function() { }); - $( "#show_builder_datepicker_start" ).datepicker({ - dateFormat: '@', - onSelect: function(sDate, oDatePicker) { - var oDate; - - oDate = new Date(parseInt(sDate, 10)); - $(this).val(oDate.toDateString()); - } - }); + $( "#show_builder_datepicker_start" ).datepicker(oBaseDatePickerSettings); - $( "#show_builder_timepicker_start" ).timepicker({ - showPeriodLabels: false, - showCloseButton: true, - showLeadingZero: false - }); + $( "#show_builder_timepicker_start" ).timepicker(oBaseTimePickerSettings); - $( "#show_builder_datepicker_end" ).datepicker({ - dateFormat: '@', - onSelect: function(sDate, oDatePicker) { - var oDate; - - oDate = new Date(parseInt(sDate, 10)); - $(this).val(oDate.toDateString()); - } - }); + $( "#show_builder_datepicker_end" ).datepicker(oBaseDatePickerSettings); - $( "#show_builder_timepicker_end" ).timepicker({ - showPeriodLabels: false, - showCloseButton: true, - showLeadingZero: false - }); + $( "#show_builder_timepicker_end" ).timepicker(oBaseTimePickerSettings); $( "#show_builder_timerange_button" ).click(function(ev){ - var oTable, oSettings, iStartDate, iEndDate, iStartTime, iEndTime; + var oTable, + oSettings, + oRange; - fnGetScheduleRange(); + oRange = fnGetScheduleRange(); oTable = $('#show_builder_table').dataTable({"bRetrieve": true}); oSettings = oTable.fnSettings(); - oSettings["_iDisplayStart"] = 1050; + oSettings.fnServerData.start = oRange.start; + oSettings.fnServerData.end = oRange.end; oTable.fnDraw(); }); $( "#show_builder_table" ).sortable({ - placeholder: "ui-state-highlight", + placeholder: "placeholder show-builder-placeholder", items: 'tr', + cancel: ".show-builder-header .show-builder-footer", receive: function(event, ui) { var x; }