From 25ef70767ba17dbd937a60e037322fa0ade9043c Mon Sep 17 00:00:00 2001 From: drigato Date: Mon, 13 Jul 2015 17:02:31 -0400 Subject: [PATCH 1/2] SAAS-940: Provide usability hints to user Customized hints depending on what page the user is on and what action they just completed. --- .../application/common/UsabilityHints.php | 83 +++++++++++++++++++ .../application/controllers/ApiController.php | 9 ++ .../application/layouts/scripts/layout.phtml | 11 +++ .../public/js/airtime/common/common.js | 21 +++++ .../public/js/airtime/library/plupload.js | 3 + .../public/js/airtime/schedule/schedule.js | 1 + .../public/js/airtime/showbuilder/builder.js | 4 +- 7 files changed, 131 insertions(+), 1 deletion(-) diff --git a/airtime_mvc/application/common/UsabilityHints.php b/airtime_mvc/application/common/UsabilityHints.php index 74c448fb0..07688c8a9 100644 --- a/airtime_mvc/application/common/UsabilityHints.php +++ b/airtime_mvc/application/common/UsabilityHints.php @@ -2,6 +2,86 @@ class Application_Common_UsabilityHints { + + /** + * @param $userPath User's current location in Airtime (i.e. /Plupload) + * @return string + */ + public static function getUsabilityHint($userPath=null) + { + // We want to display hints in this order: + // 1. Check if files are uploaded + // 2. Check if a show is scheduled + // 3. Check if scheduled show needs content + + // Once the user is on the page linked to from the hint we want to + // display a new message further describing what to do. Once this + // action has been done we can hide the message and get the next + // usability hint, if there is one. + + $userIsOnCalendarPage = false; + $userIsOnAddMediaPage = false; + + // If $userPath is set the request came from AJAX so the user's + // current location inside Airtime gets passed in to this function. + if (!is_null($userPath)) { + // We check if the controller names are in the user's current location + // so we can ignore leading or trailing slashes, special characters like '#', + // and additional controller action names like '/user/add-user' + + if (strpos(strtolower($userPath), 'plupload') !== false) { + $userIsOnAddMediaPage = true; + } + + if (strpos(strtolower($userPath), 'schedule') !== false) { + $userIsOnCalendarPage = true; + } + } else { + // If $userPath is not set the request came from inside Airtime so + // we can use Zend's Front Controller to get the user's current location. + $currentController = strtolower(Zend_Controller_Front::getInstance()->getRequest()->getControllerName()); + + if ($currentController == "schedule") { + $userIsOnCalendarPage = true; + } + + if ($currentController == "plupload") { + $userIsOnAddMediaPage = true; + } + } + + if (self::zeroFilesUploaded()) { + if ($userIsOnAddMediaPage) { + return _("Click the 'Add files' button and select files from your computer to upload."); + } else { + return sprintf(_("It looks like you have not uploaded any audio files yet. %sUpload a file now.%s "), + "", + ""); + } + } else if (!self::isFutureOrCurrentShowScheduled()) { + if ($userIsOnCalendarPage) { + return _("Click the 'Create 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::isCurrentOrNextShowEmpty()) { + if ($userIsOnCalendarPage) { + return _("To start broadcasting click on your show and select 'Add / Remove Content'"); + } else { + //TODO: break this into two functions (current and next) so message is more clear + return sprintf(_("It looks like your show is empty. %sAdd tracks to your show now.%s"), + "", + ""); + } + } else { + return ""; + } + } + + //TODO: make functions below private? + /** * Returns true if no files have been uploaded. */ @@ -48,9 +128,11 @@ class Application_Common_UsabilityHints if (is_null($futureShow) && is_null($currentShow)) { return false; } else { + $now = new DateTime("now", new DateTimeZone("UTC")); if ($currentShow) { $scheduledTracks = CcScheduleQuery::create() ->filterByDbInstanceId($currentShow->getDbId()) + ->filterByDbEnds($now, Criteria::GREATER_EQUAL) ->find(); if ($scheduledTracks->count() == 0) { return true; @@ -58,6 +140,7 @@ class Application_Common_UsabilityHints } else if ($futureShow) { $scheduledTracks = CcScheduleQuery::create() ->filterByDbInstanceId($futureShow->getDbId()) + ->filterByDbStarts($now, Criteria::GREATER_EQUAL) ->find(); if ($scheduledTracks->count() == 0) { return true; diff --git a/airtime_mvc/application/controllers/ApiController.php b/airtime_mvc/application/controllers/ApiController.php index 60b1e186b..cf1241e1e 100644 --- a/airtime_mvc/application/controllers/ApiController.php +++ b/airtime_mvc/application/controllers/ApiController.php @@ -64,6 +64,7 @@ class ApiController extends Zend_Controller_Action ->addActionContext('update-stream-setting-table' , 'json') ->addActionContext('update-replay-gain-value' , 'json') ->addActionContext('update-cue-values-by-silan' , 'json') + ->addActionContext('get-usability-hint' , 'json') ->initContext(); } @@ -1466,5 +1467,13 @@ class ApiController extends Zend_Controller_Action } $this->_helper->json->sendJson(array(1)); } + + public function getUsabilityHintAction() + { + $userPath = $this->_getParam("userPath"); + + $hint = Application_Common_UsabilityHints::getUsabilityHint($userPath); + $this->_helper->json->sendJson($hint); + } } diff --git a/airtime_mvc/application/layouts/scripts/layout.phtml b/airtime_mvc/application/layouts/scripts/layout.phtml index e16b82248..51c1e8624 100644 --- a/airtime_mvc/application/layouts/scripts/layout.phtml +++ b/airtime_mvc/application/layouts/scripts/layout.phtml @@ -71,6 +71,16 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
+ +
+ + + layout()->content ?>
diff --git a/airtime_mvc/public/js/airtime/common/common.js b/airtime_mvc/public/js/airtime/common/common.js index cb1ba1a51..53a9ff3a1 100644 --- a/airtime_mvc/public/js/airtime/common/common.js +++ b/airtime_mvc/public/js/airtime/common/common.js @@ -161,3 +161,24 @@ function removeSuccessMsg() { $status.fadeOut("slow", function(){$status.empty()}); } + +function getUsabilityHint() { + var pathname = window.location.pathname; + $.getJSON("/api/get-usability-hint", {"format": "json", "userPath": pathname}, function(json) { + console.log(json); + var $hint_div = $('.usability_hint'); + var current_hint = $hint_div.html(); + if (json === "") { + $hint_div.hide(); + } else if (current_hint !== json) { + console.log($hint_div); + if ($hint_div.is(":hidden")) { + console.log("hidden"); + $hint_div.show(); + } + $hint_div.slideUp("slow"); + $hint_div.html(json); + $hint_div.slideDown("slow"); + } + }); +} diff --git a/airtime_mvc/public/js/airtime/library/plupload.js b/airtime_mvc/public/js/airtime/library/plupload.js index f96ee3157..ef5e7d1f1 100644 --- a/airtime_mvc/public/js/airtime/library/plupload.js +++ b/airtime_mvc/public/js/airtime/library/plupload.js @@ -146,6 +146,9 @@ $(document).ready(function() { } else { self.stopRefreshingRecentUploads(); } + + // Update usability hint - in common.js + getUsabilityHint(); } } ); } diff --git a/airtime_mvc/public/js/airtime/schedule/schedule.js b/airtime_mvc/public/js/airtime/schedule/schedule.js index e85d47be2..57e416a53 100644 --- a/airtime_mvc/public/js/airtime/schedule/schedule.js +++ b/airtime_mvc/public/js/airtime/schedule/schedule.js @@ -154,6 +154,7 @@ function buildScheduleDialog (json, instance_id) { "class": "btn", click: function() { $(this).dialog("close"); + //getUsabilityHint(); } } ] diff --git a/airtime_mvc/public/js/airtime/showbuilder/builder.js b/airtime_mvc/public/js/airtime/showbuilder/builder.js index d46d0aade..56e63ab61 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/builder.js @@ -283,6 +283,8 @@ var AIRTIME = (function(AIRTIME){ mod.enableUI(); //Unneccessary reload of the library pane after moving tracks in the showbuilder pane. //$("#library_content").find("#library_display").dataTable().fnStandingRedraw(); + + getUsabilityHint(); }; mod.getSelectedCursors = function() { @@ -316,7 +318,7 @@ var AIRTIME = (function(AIRTIME){ mod.disableUI(); $.post(baseUrl+"showbuilder/schedule-add", - {"format": "json", "mediaIds": aMediaIds, "schedIds": aSchedIds}, + {"format": "json", "mediaIds": aMediaIds, "schedIds": aSchedIds}, mod.fnItemCallback ); }; From 71e8909365709a5c847a8e0a2f5b7fa6a722028e Mon Sep 17 00:00:00 2001 From: drigato Date: Tue, 14 Jul 2015 10:08:56 -0400 Subject: [PATCH 2/2] SAAS-940: Provide usability hints to user Fixed bug where hints were not showing up sometimes --- airtime_mvc/application/layouts/scripts/layout.phtml | 1 - airtime_mvc/public/js/airtime/common/common.js | 10 +++++++--- .../js/airtime/schedule/full-calendar-functions.js | 1 + 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/airtime_mvc/application/layouts/scripts/layout.phtml b/airtime_mvc/application/layouts/scripts/layout.phtml index 51c1e8624..154f658f4 100644 --- a/airtime_mvc/application/layouts/scripts/layout.phtml +++ b/airtime_mvc/application/layouts/scripts/layout.phtml @@ -73,7 +73,6 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=