Merge pull request #637 from Robbt/podcastname-edit

Make podcast name editable
This commit is contained in:
frecuencialibre 2018-12-17 12:28:28 -06:00 committed by GitHub
commit 0ccf4da1e6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 226 additions and 133 deletions

View File

@ -21,6 +21,17 @@ class Rest_Bootstrap extends Zend_Application_Module_Bootstrap
); );
$router->addRoute('podcast-bulk', $podcastBulkRoute); $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( $stationPodcastRoute = new Zend_Controller_Router_Route(
'rest/podcast/station', 'rest/podcast/station',
array( array(

View File

@ -191,6 +191,26 @@ class Rest_PodcastController extends Zend_Rest_Controller
$this->_helper->json->sendJson($responseBody); $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 * @throws PodcastNotFoundException
* *

View File

@ -162,49 +162,59 @@ class Application_Service_PodcastService
/** /**
* @param $podcast * @param $podcast
* @param $title passed in directly from web UI input
* This will automatically create a smartblock and playlist for this podcast. * 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(); if (is_array($podcast)) {
$newBl->setCreator(Application_Model_User::getCurrentUser()->getId()); $newpodcast = new Podcast();
$newBl->setName($podcast->getDbTitle()); $newpodcast->fromArray($podcast, BasePeer::TYPE_FIELDNAME);
$newBl->setDescription('Auto-generated smartblock for podcast'); $podcast = $newpodcast;
$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 ($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() public static function createStationPodcast()

View File

@ -7,23 +7,36 @@
<div class="inner_editor_wrapper"> <div class="inner_editor_wrapper">
<form class="podcast-metadata"> <form class="podcast-metadata">
<input ng-value="podcast.id" class="obj_id" type="hidden"/> <input ng-value="podcast.id" class="obj_id" type="hidden"/>
<div> <div class="podcast-metadata-row">
<label for="podcast_name"><?php echo _("Podcast Name: ") ?></label> <label for="podcast_name"><?php echo _("Podcast Name: ") ?></label>
<span class="podcast-metadata-field">{{podcast.title}}</span> <input name="podcast_name" type="text" ng-model="podcast.title" value={{podcast.title}} >
</div> </div>
<div> <div class="podcast-metadata-row">
<label for="podcast_url"><?php echo _("Podcast URL: ") ?></label> <label for="podcast_url"><?php echo _("Podcast URL: ") ?></label>
<a href="{{podcast.url}}" target="_blank"> <a href="{{podcast.url}}" target="_blank" class="podcast-url">{{podcast.url}}</a>
<span class="podcast-metadata-field">{{podcast.url}}</span>
</a>
</div> </div>
<div style="padding-top: 0.1em;"> <div class="podcast-metadata-row">
<label for="podcast_auto_ingest"><input name="podcast_auto_ingest" ng-model="podcast.auto_ingest" type="checkbox" class="float-right"/></label> <div>
<span class="podcast-metadata-field"><?php echo _("Automatically download latest episodes?") ?></span> <input name="podcast_auto_ingest" id="podcast_auto_ingest" ng-model="podcast.auto_ingest" type="checkbox"/>
</div>
<label for="podcast_auto_ingest"><?php echo _("Automatically download latest episodes") ?></label>
</div> </div>
<div style="padding-top: 0.1em;"> <div class="podcast-metadata-row">
<label for="podcast_album_override"><input name="podcast_album_override" ng-model="podcast.album_override" type="checkbox" class="no-float"/></label> <div>
<span class="podcast-metadata-field"><?php echo _("Override album name with podcast name during ingest."); ?></span> <input name="podcast_album_override" id="podcast_album_override" ng-model="podcast.album_override" type="checkbox" />
</div>
<div>
<label for="podcast_album_override"><?php echo _("Overwrite episode album names"); ?></label> <span class='album_names help_icon'></span>
</div>
</div>
<div class="podcast-metadata-row" >
<div></div>
<div>
<button ng-click="createSmartblock()" ng-disabled="!podcast.album_override" class="btn" type="button" name="smartblock">
<?php echo _("Generate Smartblock and Playlist for Podcast") ?>
</button>
<div class='pc-sb-success success' style='display:none'></span></div>
</div>
</div> </div>
</form> </form>
</div> </div>
@ -41,6 +54,6 @@
<?php echo _("Save") ?> <?php echo _("Save") ?>
</button> </button>
</div> </div>
<div class='success' style='display:none'></span></div> <div class='success' style='display:none'></div>
</div> </div>
</div> </div>

View File

@ -204,7 +204,7 @@ img.logo
.airtime_auth_help_icon, .custom_auth_help_icon, .stream_username_help_icon, .airtime_auth_help_icon, .custom_auth_help_icon, .stream_username_help_icon,
.playlist_type_help_icon, .repeat_tracks_help_icon, .show_linking_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, .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; cursor: help;
position: relative; position: relative;
display:inline-block; zoom:1; display:inline-block; zoom:1;
@ -4137,68 +4137,38 @@ li .ui-state-hover {
padding: 5px 0 0 5px; padding: 5px 0 0 5px;
} }
.podcast-metadata p { .podcast-metadata-row {
text-align: center; margin: 10px 0;
padding: 0 10px; display: flex;
margin-top: 0; align-items: center;
} }
.podcast-metadata .podcast-metadata-row * {
.podcast-metadata label, line-height: 1.3;
.podcast-metadata input:not([type="checkbox"]), position: static;
.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 {
float: none; 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 { .podcast-url {
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%;
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
margin: 4px 0;
line-height: 24px;
} }
.podcast-metadata-row .success {
margin-top: 10px;
}
.podcast_episodes_imported { .podcast_episodes_imported {
text-align: center !important; text-align: center !important;
} }
@ -4221,6 +4191,17 @@ li .ui-state-hover {
overflow: auto; overflow: auto;
} }
#podcast_url_dialog table tr td {
padding: 0;
}
#podcast_url_dialog .errors {
display: inline-block;
float: right;
width: 50%;
}
/* UI Revamp Video */ /* UI Revamp Video */
#whatsnew { #whatsnew {
@ -4336,16 +4317,6 @@ li .ui-state-hover {
float: right; float: right;
} }
#podcast_url_dialog table tr td {
padding: 0;
}
#podcast_url_dialog .errors {
display: inline-block;
float: right;
width: 50%;
}
#upgrade-feature-locked { #upgrade-feature-locked {
margin: 0 auto; margin: 0 auto;
width: 50%; width: 50%;

View File

@ -1379,8 +1379,8 @@ var AIRTIME = (function(AIRTIME) {
}); });
$.extend(true, podcastToolbarButtons[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.EDIT], $.extend(true, podcastToolbarButtons[AIRTIME.widgets.Table.TOOLBAR_BUTTON_ROLES.EDIT],
{ {
title: $.i18n._('Settings'), title: $.i18n._('Edit'),
iconClass : "icon-cog", iconClass : "icon-pencil",
eventHandlers: { eventHandlers: {
click: AIRTIME.podcast.editSelectedPodcasts click: AIRTIME.podcast.editSelectedPodcasts
}, },

View File

@ -35,8 +35,12 @@ var AIRTIME = (function (AIRTIME) {
view.find("table").attr("id", "podcast_episodes_" + podcast.id); view.find("table").attr("id", "podcast_episodes_" + podcast.id);
self.onSaveCallback = function () { 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(); 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. * Close the tab and discard any changes made to the podcast data.
*/ */
@ -64,6 +106,9 @@ var AIRTIME = (function (AIRTIME) {
return self; return self;
} }
/** /**
* Initialize the controller. * Initialize the controller.
* *
@ -100,20 +145,21 @@ var AIRTIME = (function (AIRTIME) {
function StationPodcastController($scope, $http, podcast, tab) { function StationPodcastController($scope, $http, podcast, tab) {
// Super call to parent controller // Super call to parent controller
PodcastController.call(this, $scope, $http, podcast, tab); PodcastController.call(this, $scope, $http, podcast, tab);
this.onSaveCallback = function () { // @frecuencialibre commenting this out since i think it is never called. @todo delete once confirmed
$http({ // this.onSaveCallback = function () {
method: 'POST', // $http({
url: '/preference/station-podcast-settings', // method: 'POST',
headers: {'Content-Type': 'application/x-www-form-urlencoded'}, // url: '/preference/station-podcast-settings',
data: { stationPodcastPrivacy: $("#podcast-settings").find("input:checked").val() } // headers: {'Content-Type': 'application/x-www-form-urlencoded'},
}).success(function (data) { // data: { stationPodcastPrivacy: $("#podcast-settings").find("input:checked").val() }
jQuery.extend($scope.podcast, data); // }).success(function (data) {
$(".success").text($.i18n._("Podcast settings saved")).slideDown("fast"); // jQuery.extend($scope.podcast, data);
setTimeout(function () { // $(".success").text($.i18n._("Podcast settings saved")).slideDown("fast");
$(".success").slideUp("fast"); // setTimeout(function () {
}, 2000); // $(".success").slideUp("fast");
}); // }, 2000);
}; // });
// };
return this; return this;
} }
@ -278,6 +324,28 @@ var AIRTIME = (function (AIRTIME) {
uid = AIRTIME.library.MediaTypeStringEnum.PODCAST+"_"+podcast.id, uid = AIRTIME.library.MediaTypeStringEnum.PODCAST+"_"+podcast.id,
tab = AIRTIME.tabs.openTab(data.html, uid, null); tab = AIRTIME.tabs.openTab(data.html, uid, null);
_bootstrapAngularApp(podcast, tab); _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"
}
});
} }
/** /**