diff --git a/airtime_mvc/application/common/UsabilityHints.php b/airtime_mvc/application/common/UsabilityHints.php index 934d89c2c..0b9ed51b0 100644 --- a/airtime_mvc/application/common/UsabilityHints.php +++ b/airtime_mvc/application/common/UsabilityHints.php @@ -55,7 +55,7 @@ class Application_Common_UsabilityHints return _("Upload some tracks below to add them to your library!"); } else { return sprintf(_("It looks like you haven't uploaded any audio files yet. %sUpload a file now%s."), - "", + "", ""); } } else if (!self::isFutureOrCurrentShowScheduled()) { @@ -63,7 +63,7 @@ class Application_Common_UsabilityHints return _("Click the 'New Show' button and fill out the required fields."); } else { return sprintf(_("It looks like you don't have any shows scheduled. %sCreate a show now%s."), - "", + "", ""); } } else if (self::isCurrentShowEmpty()) { @@ -73,14 +73,14 @@ class Application_Common_UsabilityHints return _("To start broadcasting, cancel the current linked show by clicking on it and selecting 'Cancel Show'."); } else { return sprintf(_("Linked shows need to be filled with tracks before it starts. To start broadcasting cancel the current linked show and schedule an unlinked show. - %sCreate an unlinked show now%s."), "", ""); + %sCreate an unlinked show now%s."), "", ""); } } else { if ($userIsOnCalendarPage) { return _("To start broadcasting, click on the current show and select 'Schedule Show'"); } else { return sprintf(_("It looks like the current show needs more tracks. %sAdd tracks to your show now%s."), - "", + "", ""); } } @@ -89,7 +89,7 @@ class Application_Common_UsabilityHints return _("Click on the show starting next and select 'Schedule Show'"); } else { return sprintf(_("It looks like the next show is empty. %sAdd tracks to your show now%s."), - "", + "", ""); } } else { diff --git a/airtime_mvc/application/controllers/PlaylistController.php b/airtime_mvc/application/controllers/PlaylistController.php index f9b21cddd..7bb425a7e 100644 --- a/airtime_mvc/application/controllers/PlaylistController.php +++ b/airtime_mvc/application/controllers/PlaylistController.php @@ -30,6 +30,7 @@ class PlaylistController extends Zend_Controller_Action ->addActionContext('get-block-info', 'json') ->addActionContext('shuffle', 'json') ->addActionContext('empty-content', 'json') + ->addActionContext('change-playlist', 'json') ->initContext(); //This controller writes to the session all over the place, so we're going to reopen it for writing here. @@ -201,6 +202,16 @@ class PlaylistController extends Zend_Controller_Action $this->createFullResponse($obj); } + public function changePlaylistAction() { + $this->view->layout()->disableLayout(); // Don't inject the standard Now Playing header. + $this->_helper->viewRenderer->setNoRender(true); // Don't use (phtml) templates + + $id = $this->_getParam('id', null); + $type = $this->_getParam('type'); + + Application_Model_Library::changePlaylist($id, $type); + } + public function editAction() { $id = $this->_getParam('id', null); @@ -241,7 +252,7 @@ class PlaylistController extends Zend_Controller_Action Logging::info("Currently active {$type} {$obj_sess->id}"); if (in_array($obj_sess->id, $ids)) { Logging::info("Deleting currently active {$type}"); - Application_Model_Library::changePlaylist(null, $type); + // Application_Model_Library::changePlaylist(null, $type); } else { Logging::info("Not deleting currently active {$type}"); $obj = new $objInfo['className']($obj_sess->id); diff --git a/airtime_mvc/application/controllers/plugins/Acl_plugin.php b/airtime_mvc/application/controllers/plugins/Acl_plugin.php index fb87574e0..18f1c69a5 100644 --- a/airtime_mvc/application/controllers/plugins/Acl_plugin.php +++ b/airtime_mvc/application/controllers/plugins/Acl_plugin.php @@ -82,7 +82,7 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract * @param string $module * @return void **/ - public function setErrorPage($action, $controller = 'error', $module = null) + public function setErrorPage($action, $controller = 'error', $module = 'default') { $this->_errorPage = array('module' => $module, 'controller' => $controller, @@ -204,11 +204,8 @@ class Zend_Controller_Plugin_Acl extends Zend_Controller_Plugin_Abstract $resourceName, $request->getActionName())) { /** Redirect to access denied page */ - $this->getResponse() - ->setHttpResponseCode(403) - ->appendBody("You don't have permission to access this resource.") - ->sendResponse(); - // $this->denyAccess(); /* This results in a 404! */ + $this->setErrorPage('error403'); + $this->denyAccess(); /* This results in a 404! */ } } } diff --git a/airtime_mvc/application/services/CalendarService.php b/airtime_mvc/application/services/CalendarService.php index 853052644..e85814afb 100644 --- a/airtime_mvc/application/services/CalendarService.php +++ b/airtime_mvc/application/services/CalendarService.php @@ -142,7 +142,8 @@ class Application_Service_CalendarService if ($isRepeating) { if ($populateInstance) { $menu["edit"] = array( - "name" => _("Edit This Instance"), + // "name" => _("Edit This Instance"), + "name" => _("Edit Instance"), "icon" => "edit", "url" => $baseUrl . "Schedule/populate-repeating-show-instance-form" ); @@ -160,7 +161,8 @@ class Application_Service_CalendarService ); $menu["edit"]["items"]["instance"] = array( - "name" => _("Edit This Instance"), + // "name" => _("Edit This Instance"), + "name" => _("Edit Instance"), "icon" => "edit", "url" => $baseUrl . "Schedule/populate-repeating-show-instance-form" ); @@ -188,12 +190,14 @@ class Application_Service_CalendarService "items" => array()); $menu["del"]["items"]["single"] = array( - "name"=> _("Delete This Instance"), + // "name"=> _("Delete This Instance"), + "name"=> _("Delete Instance"), "icon" => "delete", "url" => $baseUrl."schedule/delete-show-instance"); $menu["del"]["items"]["following"] = array( - "name"=> _("Delete This Instance and All Following"), + // "name"=> _("Delete This Instance and All Following"), + "name"=> _("Delete Instance and All Following"), "icon" => "delete", "url" => $baseUrl."schedule/delete-show"); } elseif ($populateInstance) { diff --git a/airtime_mvc/public/css/dashboard.css b/airtime_mvc/public/css/dashboard.css index d92d1041b..c30d2e848 100644 --- a/airtime_mvc/public/css/dashboard.css +++ b/airtime_mvc/public/css/dashboard.css @@ -150,6 +150,9 @@ div.btn > span { #library_empty_image { opacity: .3; + width: 16px; + height: 20px; + top: -20px; margin-top: -2px; padding-right: 2px; /* For the webstream icon */ @@ -456,8 +459,10 @@ li.ui-state-default { max-height: 60%; overflow-x: hidden; width: 100%; - flex: 1 0 100%; + flex: 1 0 auto; padding: 10px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; } @@ -500,6 +505,8 @@ li.ui-state-default { padding: 5px; border: 1px solid #444; border-radius: 3px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; background-color: #111; display: flex; @@ -559,6 +566,8 @@ li.ui-state-default { } .side_playlist .zend_form input { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; height: 26px; } diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css index c58102ad5..f2a21787d 100644 --- a/airtime_mvc/public/css/styles.css +++ b/airtime_mvc/public/css/styles.css @@ -1357,6 +1357,8 @@ input[type="checkbox"] { } #schedule_calendar { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; width: 100%; @@ -1819,6 +1821,8 @@ button, input { } .user-management .dataTables_filter input { width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; margin-bottom:8px; } @@ -1945,7 +1949,9 @@ div.success{ float: right; height: 30px; line-height: 24px; - box-sizing: border-box;; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } div.errors, span.errors{ @@ -1957,7 +1963,9 @@ div.errors, span.errors{ border:1px solid #c83f3f; height: 30px; line-height: 24px; - box-sizing: border-box;; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; + box-sizing: border-box; } span.errors.sp-errors{ @@ -2625,6 +2633,8 @@ label span { fieldset > legend { width: 100%; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; background: #333; @@ -3462,9 +3472,15 @@ dd .stream-status { min-width: 200px !important; } +.calendar-context-menu .context-menu-list { + min-width: 260px !important; +} + /* Add Media Page */ #upload_form, #recent_uploads_wrapper { + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; } @@ -3593,6 +3609,8 @@ button.btn-icon-text > i.icon-white { .dashboard_sub_nav { padding: 0px 0px 0px 10px; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; } @@ -3722,6 +3740,8 @@ button.btn-icon-text > i.icon-white { #listenerstat_content { width: 100%; display: block; + -webkit-box-sizing: border-box; + -moz-box-sizing: border-box; box-sizing: border-box; } @@ -3734,6 +3754,12 @@ button.btn-icon-text > i.icon-white { font-size: 12px; } +#flot_placeholder.processing { + width: 100%; + height: 100%; + background: url("img/loading.gif") no-repeat 50% 50% rgba(0, 0, 0, .25); +} + .dashboard-btn { width: 50%; } 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 6cdf9d394..3459c862d 100644 --- a/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js +++ b/airtime_mvc/public/js/airtime/library/events/library_showbuilder.js @@ -77,6 +77,7 @@ var AIRTIME = (function(AIRTIME) { cb.append(""); } + var libEmpty = $('#library_empty'); if (emptyRow.length > 0) { emptyRow.hide(); var mediaType = parseInt($('.media_type_selector.selected').attr('data-selection-id')), @@ -92,13 +93,13 @@ var AIRTIME = (function(AIRTIME) { $('#library_empty_text').html( $.i18n._("You haven't added any " + opts.media + ".") + "
" + $.i18n._(opts.subtext) - + "
" + $.i18n._("Learn about " + opts.media) + "" + + "
" + $.i18n._("Learn about " + opts.media) + "" ); - }) ; + }); - $('#library_empty').show(); + libEmpty.show(); } else { - $('#library_empty').hide(); + libEmpty.hide(); } if ($("#show_builder_table").is(":visible")) { diff --git a/airtime_mvc/public/js/airtime/library/spl.js b/airtime_mvc/public/js/airtime/library/spl.js index ca9ca135a..22cacd1fb 100644 --- a/airtime_mvc/public/js/airtime/library/spl.js +++ b/airtime_mvc/public/js/airtime/library/spl.js @@ -421,17 +421,19 @@ var AIRTIME = (function(AIRTIME){ $('.zend_form + .spl-no-margin > div:has(*:visible):last').css('margin-left', 0); } - function getId() { - return parseInt($pl.find(".obj_id").val(), 10); + function getId(pl) { + pl = (pl === undefined) ? $pl : pl; + return parseInt(pl.find(".obj_id").val(), 10); } - mod.getModified = function() { - return parseInt($pl.find(".obj_lastMod").val(), 10); - } + mod.getModified = function(pl) { + pl = (pl === undefined) ? $pl : pl; + return parseInt(pl.find(".obj_lastMod").val(), 10); + }; mod.setModified = function(modified) { $pl.find(".obj_lastMod").val(modified); - } + }; function setTitleLabel(title) { $pl.find(".title_obj_name").text(title); @@ -569,6 +571,10 @@ var AIRTIME = (function(AIRTIME){ if (pane.get(0) == curr.get(0)) { // Closing the current tab, otherwise we don't need to switch tabs AIRTIME.showbuilder.switchTab(toPane, toTab); } + + // If we close a tab that was causing tabs to wrap to the next row, we need to resize to change the + // margin for the tab nav + AIRTIME.playlist.onResize(); } mod.closeTab = function(id) { @@ -1208,8 +1214,8 @@ var AIRTIME = (function(AIRTIME){ var url, id, lastMod, type, pl = (tabId === undefined) ? $pl : $('#pl-tab-content-' + tabId); stopAudioPreview(); - id = (plid === undefined) ? getId() : plid; - lastMod = mod.getModified(); + id = (plid === undefined) ? getId(pl) : plid; + lastMod = mod.getModified(pl); type = pl.find('.obj_type').val(); url = baseUrl+'playlist/delete'; @@ -1558,6 +1564,7 @@ var AIRTIME = (function(AIRTIME){ mod.setAsActive = function() { $pl = $(".active-tab"); + $.post(baseUrl + "playlist/change-playlist", {"id": getId(), "type": $pl.find('.obj_type').val()}); }; mod.init = function() { diff --git a/airtime_mvc/public/js/airtime/listenerstat/listenerstat.js b/airtime_mvc/public/js/airtime/listenerstat/listenerstat.js index 8507c876e..0c239455f 100644 --- a/airtime_mvc/public/js/airtime/listenerstat/listenerstat.js +++ b/airtime_mvc/public/js/airtime/listenerstat/listenerstat.js @@ -10,7 +10,7 @@ $(document).ready(function() { width = width * .91; $("#listenerstat_content").find("#flot_placeholder").width(width); $("#listenerstat_content").find("#legend").width(width); - + getDataAndPlot(); listenerstat_content.find("#his_submit").click(function(){ @@ -21,7 +21,17 @@ $(document).ready(function() { }); }); -function getDataAndPlot(startTimestamp, endTimestamp){ +/** + * Toggle a spinner overlay so the user knows the page is processing + */ +function toggleOverlay() { + $('#flot_placeholder').toggleClass('processing'); +} + +function getDataAndPlot(startTimestamp, endTimestamp) { + // Turn on the processing overlay + toggleOverlay(); + // get data $.get(baseUrl+'Listenerstat/get-data', {start: startTimestamp, end: endTimestamp}, function(data){ out = new Object(); @@ -37,6 +47,8 @@ function getDataAndPlot(startTimestamp, endTimestamp){ out[mpName] = plotData; }); plot(out); + // Turn off the processing overlay + toggleOverlay(); }) } diff --git a/airtime_mvc/public/js/airtime/user/user.js b/airtime_mvc/public/js/airtime/user/user.js index e277d4266..921369546 100644 --- a/airtime_mvc/public/js/airtime/user/user.js +++ b/airtime_mvc/public/js/airtime/user/user.js @@ -43,10 +43,16 @@ function rowClickCallback(row_id){ }}); } -function removeUserCallback(row_id, nRow){ - $.ajax({ url: baseUrl+'User/remove-user/id/'+ row_id +'/format/json', dataType:"text", success:function(data){ - var o = $('#users_datatable').dataTable().fnDeleteRow(nRow); - }}); +function removeUserCallback(row_id, nRow) { + if (confirm($.i18n._("Are you sure you want to delete this user?"))) { + $.ajax({ + url: baseUrl + 'User/remove-user/id/' + row_id + '/format/json', + dataType: "text", + success: function (data) { + var o = $('#users_datatable').dataTable().fnDeleteRow(nRow); + } + }); + } } function rowCallback( nRow, aData, iDisplayIndex ){