SAAS-1083 - work on publish dialog

This commit is contained in:
Duncan Sommerville 2015-10-28 18:54:30 -04:00
parent 05f51a9a2d
commit e97aa199bd
8 changed files with 198 additions and 41 deletions

View file

@ -84,5 +84,18 @@ class Rest_Bootstrap extends Zend_Application_Module_Bootstrap
) )
); );
$router->addRoute('publish', $publishRoute); $router->addRoute('publish', $publishRoute);
$publishSourcesRoute = new Zend_Controller_Router_Route(
'rest/media/:id/publish-sources',
array(
'controller' => 'media',
'action' => 'publish-sources',
'module' => 'rest'
),
array(
'id' => '\d+'
)
);
$router->addRoute('publish-sources', $publishSourcesRoute);
} }
} }

View file

@ -200,7 +200,7 @@ class Rest_MediaController extends Zend_Rest_Controller
try { try {
// Is there a better way to do this? // Is there a better way to do this?
$data = json_decode($this->getRequest()->getRawBody(), true)["sources"]; $data = json_decode($this->getRequest()->getRawBody(), true)["sources"];
Application_Service_MediaService::publish($id, $data); Application_Service_PublishService::publish($id, $data);
$this->getResponse() $this->getResponse()
->setHttpResponseCode(200); ->setHttpResponseCode(200);
} catch (Exception $e) { } catch (Exception $e) {
@ -209,6 +209,15 @@ class Rest_MediaController extends Zend_Rest_Controller
} }
} }
public function publishSourcesAction() {
$id = $this->_getParam('id', false);
$sources = Application_Service_PublishService::getSourceLists($id);
$this->getResponse()
->setHttpResponseCode(200)
->appendBody(json_encode($sources));
}
private function getId() private function getId()
{ {
if (!$id = $this->_getParam('id', false)) { if (!$id = $this->_getParam('id', false)) {

View file

@ -111,19 +111,5 @@ class Application_Service_MediaService
} }
} }
/**
* Publish or remove the file with the given file ID from the services
* specified in the request data (ie. SoundCloud, the station podcast)
*
* @param int $fileId ID of the file to be published
* @param array $data request data containing what services to publish to
*/
public static function publish($fileId, $data) {
foreach ($data as $k => $v) {
$service = PublishServiceFactory::getService($k);
$service->$v($fileId);
}
}
} }

View file

@ -0,0 +1,105 @@
<?php
class Application_Service_PublishService {
/**
* @var array map of arbitrary source names to descriptive labels
*/
private static $SOURCES = array(
"soundcloud" => SOUNDCLOUD,
"station_podcast" => "My Station Podcast"
);
/**
* @var array map of arbitrary source names to functions that return
* their publication state (true = published)
*/
private static $SOURCE_FUNCTIONS = array(
"soundcloud" => "getSoundCloudPublishStatus",
"station_podcast" => "getStationPodcastPublishStatus"
);
/**
* Publish or remove the file with the given file ID from the services
* specified in the request data (ie. SoundCloud, the station podcast)
*
* @param int $fileId ID of the file to be published
* @param array $data request data containing what services to publish to
*/
public static function publish($fileId, $data) {
foreach ($data as $k => $v) {
$service = PublishServiceFactory::getService($k);
if ($v) $service->publish($fileId);
}
}
/**
* For the file with the given ID, check external sources and generate
* an array of source states and labels.
*
* Sources to which the file has been published should be passed back in a
* "published" array, while sources to which the file has not been published
* should be passed back in a "toPublish" array.
*
* @param int $fileId the ID of the file to check
*
* @return array array containing published and toPublish arrays. Has the form
* [
* "toPublish" => [
* "source" => "label",
* ...
* ]
* "published" => [
* "source" => "label",
* ...
* ]
* ]
*/
public static function getSourceLists($fileId) {
$publishSources = $publishedSources = array();
foreach (self::$SOURCES as $source => $label) {
$fn = self::$SOURCE_FUNCTIONS[$source];
// Should be in a ternary but PHP doesn't play nice
if (self::$fn($fileId)) {
$publishedSources[$source] = _($label);
} else {
$publishSources[$source] = _($label);
}
}
return array(
"toPublish" => $publishSources,
"published" => $publishedSources
);
}
/** @noinspection PhpUnusedPrivateMethodInspection
* Reflective accessor for SoundCloud publication status for the
* file with the given ID
*
* @param int $fileId the ID of the file to check
*
* @return bool true if the file has been published to SoundCloud,
* otherwise false
*/
private static function getSoundCloudPublishStatus($fileId) {
$soundcloudService = new Application_Service_SoundcloudService();
return ($soundcloudService->getServiceId($fileId) != 0);
}
/** @noinspection PhpUnusedPrivateMethodInspection
* Reflective accessor for Station podcast publication status for the
* file with the given ID
*
* @param int $fileId the ID of the file to check
*
* @return bool true if the file has been published to the Station podcast,
* otherwise false
*/
private static function getStationPodcastPublishStatus($fileId) {
$stationPodcast = StationPodcastQuery::create()
->findOneByDbPodcastId(Application_Model_Preference::getStationPodcastId());
return $stationPodcast->hasEpisodeForFile($fileId);
}
}

View file

@ -16,12 +16,27 @@
</label> </label>
<fieldset> <fieldset>
<legend><?php echo _("Publish to:"); ?></legend> <legend><?php echo _("Publish to:"); ?></legend>
<input ng-model="publishSources.station_podcast" type="checkbox" name="publish_sources" id="station_podcast" value="station_podcast"> <div ng-repeat="(source, label) in sources.toPublish">
<label for="station_podcast"><?php echo(_("My Station Podcast"));?></label><br/> <input ng-model="publishData[source]" type="checkbox" name="publish_sources" id="{{source}}">
<input ng-model="publishSources.soundcloud" type="checkbox" name="publish_sources" id="soundcloud" value="soundcloud"> <label for="{{source}}">{{label}}</label><br/>
<label for="soundcloud"><?php echo(_(SOUNDCLOUD));?></label> </div>
<div ng-if="sources.toPublish.length == 0">
<?php echo _("You have already published this track to all available sources!<br/>"
. "Published tracks can be removed or updated below.") ?>
</div>
</fieldset>
<fieldset>
<legend><?php echo _("Published on:"); ?></legend>
<div class="published-sources" ng-repeat="(source, label) in sources.published">
<span class="sp-checked-icon checked-icon left-floated"></span>
<span class="source-name">{{label}}</span>
<button class="btn btn-small" ng-click="remove(source)"><?php echo _("Remove") ?></button>
</div>
<div ng-if="sources.published.length == 0">
<?php echo _("You haven't published this track to any sources!<br/>"
. "Check the boxes above and hit 'Publish' to publish this track to the marked sources.") ?>
</div>
</fieldset> </fieldset>
</form> </form>
</div> </div>

View file

@ -3991,3 +3991,15 @@ li .ui-state-hover {
/* jQuery dialog */ /* jQuery dialog */
.no-close .ui-dialog-titlebar-close {display: none } .no-close .ui-dialog-titlebar-close {display: none }
/* Publishing Dialog */
.published-sources {
color: #efefef;
font-size: 14px;
line-height: 26px;
}
.published-sources > .checked-icon {
height: 26px;
padding-right: 8px;
}

View file

@ -21,7 +21,7 @@ var AIRTIME = (function (AIRTIME) {
tab.setName($scope.podcast.title); tab.setName($scope.podcast.title);
$scope.csrf = jQuery("#csrf").val(); $scope.csrf = jQuery("#csrf").val();
tab.contents.find("table").attr("id", "podcast_episodes_" + podcast.id); tab.contents.find("table").attr("id", "podcast_episodes_" + podcast.id);
var episodeTable = AIRTIME.podcast.initPodcastEpisodeDatatable(podcast.episodes, tab); var episodeTable = AIRTIME.podcast.initPodcastEpisodeDatatable(podcast, tab);
// Override the switchTo function to reload the table when the tab is focused. // Override the switchTo function to reload the table when the tab is focused.
// Should help to reduce the number of cases where the frontend doesn't match the state // Should help to reduce the number of cases where the frontend doesn't match the state
@ -162,7 +162,7 @@ var AIRTIME = (function (AIRTIME) {
} }
}; };
mod.initPodcastEpisodeDatatable = function(episodes, tab) { mod.initPodcastEpisodeDatatable = function(podcast, tab) {
var aoColumns = [ var aoColumns = [
/* GUID */ { "sTitle" : "" , "mDataProp" : "guid" , "sClass" : "podcast_episodes_guid" , "bVisible" : false }, /* GUID */ { "sTitle" : "" , "mDataProp" : "guid" , "sClass" : "podcast_episodes_guid" , "bVisible" : false },
/* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "title" , "sClass" : "podcast_episodes_title" , "sWidth" : "170px" }, /* Title */ { "sTitle" : $.i18n._("Title") , "mDataProp" : "title" , "sClass" : "podcast_episodes_title" , "sWidth" : "170px" },
@ -194,7 +194,7 @@ var AIRTIME = (function (AIRTIME) {
// as json. Doing this caches all the episode data on the front-end, // as json. Doing this caches all the episode data on the front-end,
// which means we also don't need to go back to the server for pagination // which means we also don't need to go back to the server for pagination
'sAjaxSource' : null, 'sAjaxSource' : null,
'aaData' : episodes, 'aaData' : podcast.episodes,
"oColVis": { "oColVis": {
"sAlign": "right", "sAlign": "right",
"aiExclude": [0, 1], "aiExclude": [0, 1],

View file

@ -15,34 +15,51 @@ var AIRTIME = (function (AIRTIME) {
//AngularJS app //AngularJS app
var publishApp = angular.module(PUBLISH_APP_NAME, []) var publishApp = angular.module(PUBLISH_APP_NAME, [])
.controller('RestController', function($scope, $http, mediaId, tab) { .controller('RestController', function ($scope, $http, mediaId, tab) {
$scope.publishSources = {}; $scope.publishSources = {};
function init () {
$http.get(endpoint + mediaId, { csrf_token: jQuery("#csrf").val() }) $http.get(endpoint + mediaId, { csrf_token: jQuery("#csrf").val() })
.success(function(json) { .success(function (json) {
console.log(json); console.log(json);
$scope.media = json; $scope.media = json;
tab.setName($scope.media.track_title); tab.setName($scope.media.track_title);
}); });
// TODO: implement GET request to endpoint that returns source information // Get an object containing all sources, their translated labels,
// ie. SoundCloud connection + publish status // and their publication state for the file with the given ID
$http.get(endpoint + mediaId + '/publish-sources', { csrf_token: jQuery("#csrf").val() })
$scope.publish = function() { .success(function (json) {
var sources = {}; $scope.sources = json;
$.each($scope.publishSources, function(k, v) { // Store the data (whether each source should be published to when publish is clicked)
if (v) sources[k] = 'publish'; // Tentative TODO: decide on a robust implementation // in a separate array so we don't overwrite the labels
$scope.publishData = {};
jQuery.each($scope.sources.toPublish, function (k, v) {
$scope.publishData[k] = false;
}); });
$http.put(endpoint + $scope.media.id + '/publish', { csrf_token: jQuery("#csrf").val(), sources: sources }) });
.success(function() { }
// TODO
$scope.publish = function () {
$http.put(endpoint + mediaId + '/publish',
{
csrf_token: jQuery("#csrf").val(),
sources: $scope.publishData
}).success(function () {
init();
}); });
}; };
$scope.discard = function() { $scope.remove = function (source) {
// TODO
};
$scope.discard = function () {
tab.close(); tab.close();
$scope.media = {}; $scope.media = {};
}; };
init();
}); });