Frontend polish and fixes; make empty placeholder implementation more abstract and add placeholder to 'My Podcast' view

This commit is contained in:
Duncan Sommerville 2015-11-12 19:02:09 -05:00
parent 0e74229975
commit 55df7775c2
10 changed files with 81 additions and 36 deletions

View File

@ -122,7 +122,7 @@ class LocaleController extends Zend_Controller_Action
"Input must be a number" => _("Input must be a number"),
"Input must be in the format: yyyy-mm-dd" => _("Input must be in the format: yyyy-mm-dd"),
"Input must be in the format: hh:mm:ss.t" => _("Input must be in the format: hh:mm:ss.t"),
"Station Podcast" => _("Station Podcast"),
"My Podcast" => _("My Podcast"),
//library/plupload.js
"You are currently uploading files. %sGoing to another screen will cancel the upload process. %sAre you sure you want to leave the page?"
=> _("You are currently uploading files. %sGoing to another screen will cancel the upload process. %sAre you sure you want to leave the page?"),

View File

@ -9,7 +9,7 @@ class Application_Form_PodcastPreferences extends Zend_Form_SubForm {
$isPrivate = Application_Model_Preference::getStationPodcastPrivacy();
$stationPodcastPrivacy = new Zend_Form_Element_Radio('stationPodcastPrivacy');
$stationPodcastPrivacy->setLabel(_('Station Podcast Feed Privacy'));
$stationPodcastPrivacy->setLabel(_('My Podcast Feed Privacy'));
$stationPodcastPrivacy->setMultiOptions(array(
_("Public"),
_("Private"),
@ -23,7 +23,7 @@ class Application_Form_PodcastPreferences extends Zend_Form_SubForm {
$feedUrl->setAttrib('class', 'input_text')
->setAttrib('disabled', 'disabled')
->setRequired(false)
->setLabel(_("Station Podcast Feed URL"))
->setLabel(_("My Podcast Feed URL"))
->setValue($url);
$this->addElement($feedUrl);
}

View File

@ -7,7 +7,7 @@ class Application_Service_PublishService {
*/
private static $SOURCES = array(
"soundcloud" => SOUNDCLOUD,
"station_podcast" => "Station Podcast"
"station_podcast" => "My Podcast"
);
/**

View File

@ -3,7 +3,7 @@
<?php echo $this->element->getSubform('preferences_general') ?>
<h3 class="collapsible-header" id="podcast-heading"><span class="arrow-icon"></span><?php echo _("Station Podcast Settings"); ?></h3>
<h3 class="collapsible-header" id="podcast-heading"><span class="arrow-icon"></span><?php echo _("My Podcast Settings"); ?></h3>
<div class="collapsible-content" id="podcast-settings">
<?php echo $this->element->getSubform('preferences_podcast') ?>
</div>

View File

@ -1,7 +1,7 @@
<div class="angular_wrapper" ng-controller="StationPodcast">
<div class="inner_editor_title">
<h2>
<span class="title_obj_name"><?php echo _("My Station Podcast") ?></span>
<span class="title_obj_name"><?php echo _("My Podcast") ?></span>
</h2>
<a href="{{podcast.url}}" target="_blank">
<button class="btn"><?php echo _("View Feed") ?></button>

View File

@ -488,8 +488,14 @@ li.ui-state-default {
color: #efefef;
}
.editor_pane_wrapper a:visited, .angular_wrapper a:visited {
color: #cecece;
.editor_pane_wrapper a,
.angular_wrapper a {
color: #FF5D1A;
}
.editor_pane_wrapper a:visited,
.angular_wrapper a:visited {
color: #CE3C01;
}
.tab-name {

View File

@ -72,30 +72,35 @@ var AIRTIME = (function(AIRTIME) {
/**
* Draw a placeholder for the given table to show if it has no data.
*
* @param {jQuery} table jQuery object containing the table DOM node
* @param {Object} table jQuery object containing the table DOM node
*/
mod.drawEmptyPlaceholder = function (table) {
var opts;
if (table instanceof AIRTIME.widgets.Table) {
opts = table.getEmptyPlaceholder();
table = table.getDatatable();
if (!table) {
return;
}
}
var emptyRow = table.find('tr:has(td.dataTables_empty)'),
wrapper = table.closest(".dataTables_wrapper");
var libEmpty = wrapper.find('.empty_placeholder');
wrapper = table.closest(".dataTables_wrapper"),
libEmpty = wrapper.find('.empty_placeholder');
if (emptyRow.length > 0) {
emptyRow.hide();
var mediaType = parseInt($('.media_type_selector.selected').data('selection-id')),
img = wrapper.find('.empty_placeholder_image');
if (isNaN(mediaType)) { return; }
if (isNaN(mediaType)) {
return;
}
// Remove all classes for when we change between empty media types
img.removeClass(function() { return $(this).attr("class"); });
if (table[0] == AIRTIME.library.podcastEpisodeDataTable[0]) {
img.addClass("empty_placeholder_image icon-white icon-th-list");
wrapper.find('.empty_placeholder_text').html(
$.i18n._("This podcast doesn't have any episodes!")
+ "<br/>" + $.i18n._("Make sure the RSS feed contains audio items (with enclosure tags).")
+ "<br/><a target='_blank' href='http://www.apple.com/ca/itunes/podcasts/specs.html'>" + $.i18n._("Learn about podcasts") + "</a>"
);
if (opts) {
img.addClass("empty_placeholder_image " + opts.iconClass);
wrapper.find('.empty_placeholder_text').html(opts.html);
} else {
var opts = AIRTIME.library.placeholder(mediaType);
opts = AIRTIME.library.placeholder(mediaType);
img.addClass("empty_placeholder_image icon-white " + opts.icon);
wrapper.find('.empty_placeholder_text').html(
$.i18n._("You haven't added any " + opts.media + ".")

View File

@ -1399,7 +1399,7 @@ var AIRTIME = (function(AIRTIME) {
// Add a button to view the station podcast
podcastToolbarButtons["StationPodcast"] = {
title : $.i18n._("Station Podcast"),
title : $.i18n._("My Podcast"),
iconClass : "icon-music",
extraBtnClass : "btn-small",
elementId : "",
@ -1419,9 +1419,6 @@ var AIRTIME = (function(AIRTIME) {
sAjaxSource : ajaxSourceURL,
oColReorder: {
iFixedColumns: 1 // Checkbox
},
fnDrawCallback: function () {
AIRTIME.library.drawEmptyPlaceholder($(this));
}
});
@ -1588,13 +1585,18 @@ var AIRTIME = (function(AIRTIME) {
},
oColReorder: {
iFixedColumns: 3 // Checkbox + imported
},
fnDrawCallback: function () {
AIRTIME.library.drawEmptyPlaceholder($(this));
}
},
buttons,
{ hideIngestCheckboxes: false }
{
hideIngestCheckboxes: false,
emptyPlaceholder: {
iconClass: "icon-white icon-th-list",
html: $.i18n._("This podcast doesn't have any episodes!")
+ "<br/>" + $.i18n._("Make sure the RSS feed contains audio items (with enclosure tags).")
+ "<br/><a target='_blank' href='http://www.apple.com/ca/itunes/podcasts/specs.html'>" + $.i18n._("Learn about podcasts") + "</a>"
}
}
);
mod.podcastEpisodeDataTable = $datatables[mod.DataTableTypeEnum.PODCAST_EPISODES] = mod.podcastEpisodeTableWidget.getDatatable();

View File

@ -40,7 +40,7 @@ var AIRTIME = (function (AIRTIME) {
$http.put(endpoint + $scope.podcast.id, {csrf_token: $scope.csrf, podcast: $scope.podcast})
.success(function () {
AIRTIME.library.podcastDataTable.fnDraw();
tab.setName($scope.podcast.title);
tab.close();
});
};
@ -205,9 +205,17 @@ var AIRTIME = (function (AIRTIME) {
buttons,
{
hideIngestCheckboxes: true,
podcastId: $scope.podcast.id
podcastId: $scope.podcast.id,
emptyPlaceholder: {
iconClass: "icon-white icon-th-list",
html: $.i18n._("You haven't published any episodes!")
+ "<br/>" + $.i18n._("You can publish your uploaded content from the 'Tracks' view.")
+ "<br/><a target='_parent' href='showbuilder#tracks'>" + $.i18n._("Try it now") + "</a>"
}
}
);
mod.stationPodcastTable = this.episodeTable.getDatatable();
};
/**
@ -215,8 +223,8 @@ var AIRTIME = (function (AIRTIME) {
*/
StationPodcastController.prototype.initialize = function() {
PodcastController.prototype.initialize.call(this);
// We want to override the default tab name behaviour and use "Station Podcast" for clarity
this.$scope.tab.setName(jQuery.i18n._("Station Podcast"));
// We want to override the default tab name behaviour and use "My Podcast" for clarity
this.$scope.tab.setName(jQuery.i18n._("My Podcast"));
this._initTable();
};
@ -317,7 +325,7 @@ var AIRTIME = (function (AIRTIME) {
this.config = config; // Internal configuration object
this._setupImportListener();
// Call the superconstructor
return AIRTIME.widgets.Table.call(this, wrapperDOMNode, bItemSelection, toolbarButtons, dataTablesOptions);
return AIRTIME.widgets.Table.call(this, wrapperDOMNode, bItemSelection, toolbarButtons, dataTablesOptions, config.emptyPlaceholder);
}; // Subclass AIRTIME.widgets.Table
PodcastEpisodeTable.prototype = Object.create(AIRTIME.widgets.Table.prototype);
PodcastEpisodeTable.prototype.constructor = PodcastEpisodeTable;
@ -459,7 +467,6 @@ var AIRTIME = (function (AIRTIME) {
*/
mod.addPodcast = function () {
$.post(endpoint, $("#podcast_url_dialog").find("form").serialize(), function(json) {
_initAppFromResponse(json);
// Open the episode view for the newly created podcast in the left-hand pane
AIRTIME.library.podcastEpisodeTableWidget.reload(JSON.parse(json.podcast).id);
AIRTIME.library.podcastTableWidget.clearSelection();
@ -613,6 +620,9 @@ var AIRTIME = (function (AIRTIME) {
connectToSortable: $("#show_builder_table, .active-tab .spl_sortable")
});
}
},
fnDrawCallback: function () {
AIRTIME.library.drawEmptyPlaceholder(this);
}
}
);

View File

@ -10,7 +10,21 @@ var AIRTIME = (function(AIRTIME) {
}
//Table widget constructor
var Table = function(wrapperDOMNode, bItemSelection, toolbarButtons, dataTablesOptions) {
/**
*
*
* @param wrapperDOMNode
* @param {boolean} bItemSelection
* @param {Object} toolbarButtons
* @param {Object} dataTablesOptions
* @param {Object} [emptyPlaceholder]
* @param {string} emptyPlaceholder.html
* @param {string} emptyPlaceholder.iconClass
*
* @returns {Table}
* @constructor
*/
var Table = function(wrapperDOMNode, bItemSelection, toolbarButtons, dataTablesOptions, emptyPlaceholder) {
var self = this;
@ -34,6 +48,7 @@ var AIRTIME = (function(AIRTIME) {
//Save some of the constructor parameters
self._$wrapperDOMNode = $(wrapperDOMNode);
self._toolbarButtons = toolbarButtons;
self._emptyPlaceholder = emptyPlaceholder;
// Exclude the leftmost column if we're implementing item selection
self._colVisExcludeColumns = bItemSelection ? [0] : [];
@ -93,6 +108,9 @@ var AIRTIME = (function(AIRTIME) {
if (options.fnCreatedRow) {
options.fnCreatedRow = options.fnCreatedRow.bind(this);
}
if (options.fnDrawCallback) {
options.fnDrawCallback = options.fnDrawCallback.bind(this);
}
self._datatable = self._$wrapperDOMNode.dataTable(options);
// self._datatable.fnDraw(); //Load the AJAX data now that our event handlers have been bound.
@ -372,6 +390,10 @@ var AIRTIME = (function(AIRTIME) {
return this._selectedRows;
};
Table.prototype.getEmptyPlaceholder = function () {
return this._emptyPlaceholder;
};
Table.prototype._handleAjaxError = function(r) {
// If the request was denied due to permissioning
if (r.status === 403) {