diff --git a/airtime_mvc/application/modules/rest/Bootstrap.php b/airtime_mvc/application/modules/rest/Bootstrap.php index b8575a2cf..3ac5a1891 100644 --- a/airtime_mvc/application/modules/rest/Bootstrap.php +++ b/airtime_mvc/application/modules/rest/Bootstrap.php @@ -21,6 +21,17 @@ class Rest_Bootstrap extends Zend_Application_Module_Bootstrap ); $router->addRoute('podcast-bulk', $podcastBulkRoute); + + $smartblockPodcastRoute = new Zend_Controller_Router_Route( + 'rest/podcast/smartblock', + array( + 'controller' => 'podcast', + 'action' => 'smartblock', + 'module' => 'rest' + ) + ); + $router->addRoute('podcast-smartblock', $smartblockPodcastRoute); + $stationPodcastRoute = new Zend_Controller_Router_Route( 'rest/podcast/station', array( diff --git a/airtime_mvc/application/modules/rest/controllers/PodcastController.php b/airtime_mvc/application/modules/rest/controllers/PodcastController.php index f80b16c34..eb454cb94 100644 --- a/airtime_mvc/application/modules/rest/controllers/PodcastController.php +++ b/airtime_mvc/application/modules/rest/controllers/PodcastController.php @@ -191,6 +191,26 @@ class Rest_PodcastController extends Zend_Rest_Controller $this->_helper->json->sendJson($responseBody); } + + /** + * Endpoint for triggering the generation of a smartblock and playlist to match the podcast name + */ + + public function smartblockAction() { + + $title = $this->_getParam('title', []); + $id = $this->_getParam('id', []); + if (!$id) { + return; + } + $podcast = Application_Service_PodcastService::getPodcastById($id); + + // logging::info($podcast); + Application_Service_PodcastService::createPodcastSmartblockAndPlaylist($podcast, $title); + } + + + /** * @throws PodcastNotFoundException * diff --git a/airtime_mvc/application/services/PodcastService.php b/airtime_mvc/application/services/PodcastService.php index b9aecb389..8ea319772 100644 --- a/airtime_mvc/application/services/PodcastService.php +++ b/airtime_mvc/application/services/PodcastService.php @@ -162,49 +162,59 @@ class Application_Service_PodcastService /** * @param $podcast + * @param $title passed in directly from web UI input * This will automatically create a smartblock and playlist for this podcast. */ - public static function createPodcastSmartblockAndPlaylist($podcast) + public static function createPodcastSmartblockAndPlaylist($podcast, $title = null) { - $newBl = new Application_Model_Block(); - $newBl->setCreator(Application_Model_User::getCurrentUser()->getId()); - $newBl->setName($podcast->getDbTitle()); - $newBl->setDescription('Auto-generated smartblock for podcast'); - $newBl->saveType('dynamic'); - // limit the smartblock to 1 item - $row = new CcBlockcriteria(); - $row->setDbCriteria('limit'); - $row->setDbModifier('items'); - $row->setDbValue(1); - $row->setDbBlockId($newBl->getId()); - $row->save(); - - // sort so that it is the newest item - $row = new CcBlockcriteria(); - $row->setDbCriteria('sort'); - $row->setDbModifier('N/A'); - $row->setDbValue('newest'); - $row->setDbBlockId($newBl->getId()); - $row->save(); - - // match the track by ensuring the album title matches the podcast - $row = new CcBlockcriteria(); - $row->setDbCriteria('album_title'); - $row->setDbModifier('is'); - $row->setDbValue($newBl->getName()); - $row->setDbBlockId($newBl->getId()); - $row->save(); - - $newPl = new Application_Model_Playlist(); - $newPl->setName($podcast->getDbTitle()); - $newPl->setCreator(Application_Model_User::getCurrentUser()->getId()); - $row = new CcPlaylistcontents(); - $row->setDbBlockId($newBl->getId()); - $row->setDbPlaylistId($newPl->getId()); - $row->setDbType(2); - $row->save(); + if (is_array($podcast)) { + $newpodcast = new Podcast(); + $newpodcast->fromArray($podcast, BasePeer::TYPE_FIELDNAME); + $podcast = $newpodcast; } + if ($title == null) { + $title = $podcast->getDbTitle(); + } + // Base class + $newBl = new Application_Model_Block(); + $newBl->setCreator(Application_Model_User::getCurrentUser()->getId()); + $newBl->setName($title); + $newBl->setDescription('Auto-generated smartblock for podcast'); + $newBl->saveType('dynamic'); + // limit the smartblock to 1 item + $row = new CcBlockcriteria(); + $row->setDbCriteria('limit'); + $row->setDbModifier('items'); + $row->setDbValue(1); + $row->setDbBlockId($newBl->getId()); + $row->save(); + + // sort so that it is the newest item + $row = new CcBlockcriteria(); + $row->setDbCriteria('sort'); + $row->setDbModifier('N/A'); + $row->setDbValue('newest'); + $row->setDbBlockId($newBl->getId()); + $row->save(); + + // match the track by ensuring the album title matches the podcast + $row = new CcBlockcriteria(); + $row->setDbCriteria('album_title'); + $row->setDbModifier('is'); + $row->setDbValue($title); + $row->setDbBlockId($newBl->getId()); + $row->save(); + + $newPl = new Application_Model_Playlist(); + $newPl->setName($title); + $newPl->setCreator(Application_Model_User::getCurrentUser()->getId()); + $row = new CcPlaylistcontents(); + $row->setDbBlockId($newBl->getId()); + $row->setDbPlaylistId($newPl->getId()); + $row->setDbType(2); + $row->save(); + } public static function createStationPodcast() diff --git a/airtime_mvc/application/views/scripts/podcast/podcast.phtml b/airtime_mvc/application/views/scripts/podcast/podcast.phtml index 1472bc78b..2a2c8122e 100644 --- a/airtime_mvc/application/views/scripts/podcast/podcast.phtml +++ b/airtime_mvc/application/views/scripts/podcast/podcast.phtml @@ -7,23 +7,36 @@
-
+ -
+ -
- - + -
- - + +
@@ -41,6 +54,6 @@
- +
diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css index 3cab8afd2..08d86810b 100644 --- a/airtime_mvc/public/css/styles.css +++ b/airtime_mvc/public/css/styles.css @@ -204,7 +204,7 @@ img.logo .airtime_auth_help_icon, .custom_auth_help_icon, .stream_username_help_icon, .playlist_type_help_icon, .repeat_tracks_help_icon, .show_linking_help_icon, .admin_username_help_icon, .stream_type_help_icon, .overflow_tracks_help_icon, -.show_timezone_help_icon, .show_autoplaylist_help_icon { +.show_timezone_help_icon, .show_autoplaylist_help_icon, .help_icon { cursor: help; position: relative; display:inline-block; zoom:1; @@ -4137,68 +4137,38 @@ li .ui-state-hover { padding: 5px 0 0 5px; } -.podcast-metadata p { - text-align: center; - padding: 0 10px; - margin-top: 0; +.podcast-metadata-row { + margin: 10px 0; + display: flex; + align-items: center; } - -.podcast-metadata label, -.podcast-metadata input:not([type="checkbox"]), -.podcast-metadata select, -.podcast-metadata textarea, -.media-metadata label, -.media-metadata input:not([type="checkbox"]), -.media-metadata select, -.media-metadata textarea { - margin: 4px 0; -} - -.podcast-metadata input[type="checkbox"] { - float: left; - margin: 8px 0 0; -} - -.podcast-metadata input[type="checkbox"].no-float { +.podcast-metadata .podcast-metadata-row * { + line-height: 1.3; + position: static; float: none; - margin: 8px 0 0; +} +.podcast-metadata-row > *:first-child { + flex: 0 0 25%; + max-width: 25%; + text-align: right; + padding-right: 2%; + box-sizing: border-box; +} +.podcast-metadata-row > *:last-child { + flex: 0 0 75%; + max-width: 75%; + box-sizing: border-box; + text-align: left; } -.podcast-metadata input[type="checkbox"].float-right { - float:right; - margin: 8px 0 0; - -} - -.podcast-metadata label, -.media-metadata label { - display: block; - width: 20%; - float: left; -} - -.podcast-metadata input:not([type="checkbox"]), -.podcast-metadata select, -.podcast-metadata textarea, -.media-metadata input:not([type="checkbox"]), -.media-metadata select, -.media-metadata textarea { - width: 60%; - float: left; -} - -.podcast-metadata-field { - display: inline-block; - width: 60%; - min-width: 60%; - max-width: 60%; +.podcast-url { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; - margin: 4px 0; - line-height: 24px; } - +.podcast-metadata-row .success { + margin-top: 10px; +} .podcast_episodes_imported { text-align: center !important; } @@ -4221,6 +4191,17 @@ li .ui-state-hover { overflow: auto; } + +#podcast_url_dialog table tr td { + padding: 0; +} + +#podcast_url_dialog .errors { + display: inline-block; + float: right; + width: 50%; +} + /* UI Revamp Video */ #whatsnew { @@ -4336,16 +4317,6 @@ li .ui-state-hover { float: right; } -#podcast_url_dialog table tr td { - padding: 0; -} - -#podcast_url_dialog .errors { - display: inline-block; - float: right; - width: 50%; -} - #upgrade-feature-locked { margin: 0 auto; width: 50%; diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js index 351c71e57..b1e3b5075 100644 --- a/airtime_mvc/public/js/airtime/library/library.js +++ b/airtime_mvc/public/js/airtime/library/library.js @@ -1379,8 +1379,8 @@ var AIRTIME = (function(AIRTIME) { }); $.extend(true, podcastToolbarButtons[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.EDIT], { - title: $.i18n._('Settings'), - iconClass : "icon-cog", + title: $.i18n._('Edit'), + iconClass : "icon-pencil", eventHandlers: { click: AIRTIME.podcast.editSelectedPodcasts }, diff --git a/airtime_mvc/public/js/airtime/library/podcast.js b/airtime_mvc/public/js/airtime/library/podcast.js index 1f23c9cf8..ac90eb588 100644 --- a/airtime_mvc/public/js/airtime/library/podcast.js +++ b/airtime_mvc/public/js/airtime/library/podcast.js @@ -35,8 +35,12 @@ var AIRTIME = (function (AIRTIME) { view.find("table").attr("id", "podcast_episodes_" + podcast.id); self.onSaveCallback = function () { + var successMsg = $('.active-tab .btn-toolbar .success') + successMsg.text($.i18n._("Podcast settings saved")).show("fast"); + setTimeout(function () { + successMsg.hide("fast"); + }, 5000); AIRTIME.library.podcastDataTable.fnDraw(); - tab.close(); }; /** @@ -49,6 +53,44 @@ var AIRTIME = (function (AIRTIME) { }); }; + + /** + * Generate a smartblock and playlist for this smartblock. + */ + $scope.createSmartblock = function () { + // send smarblock creation instruction to API + $.post( + endpoint + "smartblock", + { + csrf_token: $("#csrf").val(), + id: $scope.podcast.id, + title: $scope.podcast.title + }, + function() { + // show success message + var successMsg = $('.active-tab .pc-sb-success') + successMsg.text($.i18n._('Smartblock and playlist generated')); + successMsg.show("fast"); + setTimeout(function(){ + successMsg.hide("fast"); + }, 5000); + + // save podcast but do not display notification beside save button below + $http.put(endpoint + $scope.podcast.id, + { + csrf_token: $scope.csrf, + podcast: $scope.podcast + }) + .success(function () { + AIRTIME.library.podcastDataTable.fnDraw(); + }); + + // redraw list of smartblocks just in case they have it visible on the left + dt = $('table[id="library_display"]').dataTable(); + dt.fnStandingRedraw(); + } + ); + }; /** * Close the tab and discard any changes made to the podcast data. */ @@ -64,6 +106,9 @@ var AIRTIME = (function (AIRTIME) { return self; } + + + /** * Initialize the controller. * @@ -100,20 +145,21 @@ var AIRTIME = (function (AIRTIME) { function StationPodcastController($scope, $http, podcast, tab) { // Super call to parent controller PodcastController.call(this, $scope, $http, podcast, tab); - this.onSaveCallback = function () { - $http({ - method: 'POST', - url: '/preference/station-podcast-settings', - headers: {'Content-Type': 'application/x-www-form-urlencoded'}, - data: { stationPodcastPrivacy: $("#podcast-settings").find("input:checked").val() } - }).success(function (data) { - jQuery.extend($scope.podcast, data); - $(".success").text($.i18n._("Podcast settings saved")).slideDown("fast"); - setTimeout(function () { - $(".success").slideUp("fast"); - }, 2000); - }); - }; + // @frecuencialibre commenting this out since i think it is never called. @todo delete once confirmed + // this.onSaveCallback = function () { + // $http({ + // method: 'POST', + // url: '/preference/station-podcast-settings', + // headers: {'Content-Type': 'application/x-www-form-urlencoded'}, + // data: { stationPodcastPrivacy: $("#podcast-settings").find("input:checked").val() } + // }).success(function (data) { + // jQuery.extend($scope.podcast, data); + // $(".success").text($.i18n._("Podcast settings saved")).slideDown("fast"); + // setTimeout(function () { + // $(".success").slideUp("fast"); + // }, 2000); + // }); + // }; return this; } @@ -278,6 +324,28 @@ var AIRTIME = (function (AIRTIME) { uid = AIRTIME.library.MediaTypeStringEnum.PODCAST+"_"+podcast.id, tab = AIRTIME.tabs.openTab(data.html, uid, null); _bootstrapAngularApp(podcast, tab); + + $(".album_names.help_icon").qtip({ + content: { + text: $.i18n._('Overwrite downloaded podcast episodes\' "Album" metadata tag with the Podcast Name specified above. This album name can then be used as a search criteria by a smartblock.') + }, + hide: { + delay: 500, + fixed: true + }, + style: { + border: { + width: 0, + radius: 4 + }, + classes: "ui-tooltip-dark ui-tooltip-rounded" + }, + position: { + my: "left bottom", + at: "right center" + } + }); + } /**