diff --git a/airtime_mvc/application/Bootstrap.php b/airtime_mvc/application/Bootstrap.php index 7edb8b0ea..b6c3440ed 100644 --- a/airtime_mvc/application/Bootstrap.php +++ b/airtime_mvc/application/Bootstrap.php @@ -31,6 +31,7 @@ require_once "Auth.php"; require_once "interface/OAuth2.php"; require_once "TaskManager.php"; require_once "UsabilityHints.php"; +require_once __DIR__.'/models/formatters/LengthFormatter.php'; require_once __DIR__.'/services/CeleryService.php'; require_once __DIR__.'/services/SoundcloudService.php'; require_once __DIR__.'/forms/helpers/ValidationTypes.php'; diff --git a/airtime_mvc/application/configs/ACL.php b/airtime_mvc/application/configs/ACL.php index 39bba31ae..bbd10bd7d 100644 --- a/airtime_mvc/application/configs/ACL.php +++ b/airtime_mvc/application/configs/ACL.php @@ -16,6 +16,7 @@ $ccAcl->add(new Zend_Acl_Resource('library')) ->add(new Zend_Acl_Resource('error')) ->add(new Zend_Acl_Resource('login')) ->add(new Zend_Acl_Resource('whmcs-login')) + ->add(new Zend_Acl_Resource('new-playlist')) ->add(new Zend_Acl_Resource('playlist')) ->add(new Zend_Acl_Resource('plupload')) ->add(new Zend_Acl_Resource('schedule')) @@ -30,6 +31,7 @@ $ccAcl->add(new Zend_Acl_Resource('library')) ->add(new Zend_Acl_Resource('listenerstat')) ->add(new Zend_Acl_Resource('usersettings')) ->add(new Zend_Acl_Resource('audiopreview')) + ->add(new Zend_Acl_Resource('new-webstream')) ->add(new Zend_Acl_Resource('webstream')) ->add(new Zend_Acl_Resource('locale')) ->add(new Zend_Acl_Resource('upgrade')) @@ -55,6 +57,7 @@ $ccAcl->allow('G', 'index') ->allow('G', 'schedule') ->allow('G', 'dashboard') ->allow('G', 'audiopreview') + ->allow('G', 'new-webstream') ->allow('G', 'webstream') ->allow('G', 'locale') ->allow('G', 'upgrade') @@ -69,6 +72,7 @@ $ccAcl->allow('G', 'index') ->allow('H', 'usersettings') ->allow('H', 'plupload') ->allow('H', 'library') + ->allow('H', 'new-playlist') ->allow('H', 'playlist') ->allow('H', 'playouthistory') ->allow('A', 'playouthistorytemplate') diff --git a/airtime_mvc/application/controllers/NewPlaylistController.php b/airtime_mvc/application/controllers/NewPlaylistController.php new file mode 100644 index 000000000..f26a5d9c0 --- /dev/null +++ b/airtime_mvc/application/controllers/NewPlaylistController.php @@ -0,0 +1,643 @@ +<?php + +class NewPlaylistController extends Zend_Controller_Action +{ + + public function init() + { + $ajaxContext = $this->_helper->getHelper('AjaxContext'); + $ajaxContext->addActionContext('add-items', 'json') + ->addActionContext('move-items', 'json') + ->addActionContext('delete-items', 'json') + ->addActionContext('set-fade', 'json') + ->addActionContext('set-crossfade', 'json') + ->addActionContext('set-cue', 'json') + ->addActionContext('new', 'json') + ->addActionContext('edit', 'json') + ->addActionContext('delete', 'json') + ->addActionContext('close-playlist', 'json') + ->addActionContext('play', 'json') + ->addActionContext('set-playlist-fades', 'json') + ->addActionContext('get-playlist-fades', 'json') + ->addActionContext('set-playlist-name', 'json') + ->addActionContext('set-playlist-description', 'json') + ->addActionContext('playlist-preview', 'json') + ->addActionContext('get-playlist', 'json') + ->addActionContext('save', 'json') + ->addActionContext('smart-block-generate', 'json') + ->addActionContext('smart-block-shuffle', 'json') + ->addActionContext('get-block-info', 'json') + ->addActionContext('shuffle', 'json') + ->addActionContext('empty-content', 'json') + ->initContext(); + + //This controller writes to the session all over the place, so we're going to reopen it for writing here. + session_start(); //Reopen the session for writing + } + + private function getPlaylist($p_type) + { + $obj = null; + $objInfo = Application_Model_Library::getObjInfo($p_type); + + $obj_sess = new Zend_Session_Namespace(UI_PLAYLISTCONTROLLER_OBJ_SESSNAME); + + if (isset($obj_sess->id)) { + $obj = new $objInfo['className']($obj_sess->id); + + $modified = $this->_getParam('modified', null); + if ($obj->getLastModified("U") !== $modified) { + $this->createFullResponse($obj); + throw new PlaylistOutDatedException(sprintf(_("You are viewing an older version of %s"), $obj->getName())); + } + } + + return $obj; + } + + private function createUpdateResponse($obj) + { + $formatter = new LengthFormatter($obj->getLength()); + $this->view->length = $formatter->format(); + + $this->view->obj = $obj; + $this->view->contents = $obj->getContents(); + $this->view->html = $this->view->render('playlist/update.phtml'); + $this->view->name = $obj->getName(); + $this->view->description = $obj->getDescription(); + $this->view->modified = $obj->getLastModified("U"); + + unset($this->view->obj); + } + + private function createFullResponse($obj = null, $isJson = false, + $formIsValid = false) + { + $isBlock = false; + $viewPath = 'playlist/_playlist.phtml'; + if ($obj instanceof Application_Model_Block) { + $isBlock = true; + $viewPath = 'playlist/_smart-block.phtml'; + } + if (isset($obj)) { + $formatter = new LengthFormatter($obj->getLength()); + $this->view->length = $formatter->format(); + + if ($isBlock) { + $form = new Application_Form_SmartBlockCriteria(); + $form->removeDecorator('DtDdWrapper'); + $form->startForm($obj->getId(), $formIsValid); + + $this->view->form = $form; + $this->view->obj = $obj; + $this->view->id = $obj->getId(); + + if ($isJson) { + return $this->view->render($viewPath); + } else { + $this->view->html = $this->view->render($viewPath); + } + } else { + $this->view->obj = $obj; + $this->view->id = $obj->getId(); + if ($isJson) { + return $this->view->html = $this->view->render($viewPath); + } else { + $this->view->html = $this->view->render($viewPath); + } + unset($this->view->obj); + } + } else { + if ($isJson) { + return $this->view->render($viewPath); + } else { + $this->view->html = $this->view->render($viewPath); + } + } + } + + private function playlistOutdated($e) + { + $this->view->error = $e->getMessage(); + } + + private function blockDynamic($obj) + { + $this->view->error = _("You cannot add tracks to dynamic blocks."); + $this->createFullResponse($obj); + } + + private function playlistNotFound($p_type, $p_isJson = false) + { + $p_type = ucfirst($p_type); + $this->view->error = sprintf(_("%s not found"), $p_type); + + Logging::info("{$p_type} not found"); + Application_Model_Library::changePlaylist(null, $p_type); + + if (!$p_isJson) { + $this->createFullResponse(null); + } else { + $this->_helper->json->sendJson(array("error"=>$this->view->error, "result"=>1, "html"=>$this->createFullResponse(null, $p_isJson))); + } + } + + private function playlistNoPermission($p_type) + { + $this->view->error = sprintf(_("You don't have permission to delete selected %s(s)."), $p_type); + $this->changePlaylist(null, $p_type); + $this->createFullResponse(null); + } + + private function playlistUnknownError($e) + { + $this->view->error = _("Something went wrong."); + Logging::info($e->getMessage()); + } + + private function wrongTypeToBlock($obj) + { + $this->view->error = _("You can only add tracks to smart block."); + $this->createFullResponse($obj); + } + + private function wrongTypeToPlaylist($obj) + { + $this->view->error = _("You can only add tracks, smart blocks, and webstreams to playlists."); + $this->createFullResponse($obj); + } + + public function newAction() + { + //$pl_sess = $this->pl_sess; + $userInfo = Zend_Auth::getInstance()->getStorage()->read(); + $type = $this->_getParam('type'); + + $objInfo = Application_Model_Library::getObjInfo($type); + + $name = _('Untitled Playlist'); + if ($type == 'block') { + $name = _('Untitled Smart Block'); + } + + $obj = new $objInfo['className'](); + $obj->setName($name); + $obj->setMetadata('dc:creator', $userInfo->id); + + Application_Model_Library::changePlaylist($obj->getId(), $type); + $this->createFullResponse($obj); + } + + public function editAction() + { + $id = $this->_getParam('id', null); + $type = $this->_getParam('type'); + $objInfo = Application_Model_Library::getObjInfo($type); + Logging::info("editing {$type} {$id}"); + + if (!is_null($id)) { + Application_Model_Library::changePlaylist($id, $type); + } + + try { + $obj = new $objInfo['className']($id); + $this->createFullResponse($obj); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound(); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function deleteAction() + { + $ids = $this->_getParam('ids'); + $ids = (!is_array($ids)) ? array($ids) : $ids; + $type = $this->_getParam('type'); + + $obj = null; + + $objInfo = Application_Model_Library::getObjInfo($type); + + $userInfo = Zend_Auth::getInstance()->getStorage()->read(); + + $obj_sess = new Zend_Session_Namespace( + UI_PLAYLISTCONTROLLER_OBJ_SESSNAME); + + try { + Logging::info("Currently active {$type} {$obj_sess->id}"); + if (in_array($obj_sess->id, $ids)) { + Logging::info("Deleting currently active {$type}"); + Application_Model_Library::changePlaylist(null, $type); + } else { + Logging::info("Not deleting currently active {$type}"); + $obj = new $objInfo['className']($obj_sess->id); + } + + if (strcmp($objInfo['className'], 'Application_Model_Playlist')==0) { + Application_Model_Playlist::deletePlaylists($ids, $userInfo->id); + } else { + Application_Model_Block::deleteBlocks($ids, $userInfo->id); + } + $this->createFullResponse($obj); + } catch (PlaylistNoPermissionException $e) { + $this->playlistNoPermission($type); + } catch (BlockNoPermissionException $e) { + $this->playlistNoPermission($type); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($type); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function closePlaylistAction() { + $type = $this->_getParam('type'); + $obj = null; + Application_Model_Library::changePlaylist($obj, $type); + $this->createFullResponse($obj); + } + + public function addItemsAction() + { + $ids = $this->_getParam('aItems', array()); + $ids = (!is_array($ids)) ? array($ids) : $ids; + $afterItem = $this->_getParam('afterItem', null); + $addType = $this->_getParam('type', 'after'); + // this is the obj type of destination + $obj_type = $this->_getParam('obj_type'); + + try { + $obj = $this->getPlaylist($obj_type); + if ($obj_type == 'playlist') { + foreach ($ids as $id) { + if (is_array($id) && isset($id[1])) { + if ($id[1] == 'playlist') { + throw new WrongTypeToPlaylistException; + } + } + } + $obj->addAudioClips($ids, $afterItem, $addType); + } elseif ($obj->isStatic()) { + // if the dest is a block object + //check if any items are playlists + foreach ($ids as $id) { + if (is_array($id) && isset($id[1])) { + if ($id[1] != 'audioclip') { + throw new WrongTypeToBlockException; + } + } + } + $obj->addAudioClips($ids, $afterItem, $addType); + } else { + throw new BlockDynamicException; + } + $this->createUpdateResponse($obj); + } catch (PlaylistOutDatedException $e) { + $this->playlistOutdated($e); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($obj_type); + } catch (WrongTypeToBlockException $e) { + $this->wrongTypeToBlock($obj); + } catch (WrongTypeToPlaylistException $e) { + $this->wrongTypeToPlaylist($obj); + } catch (BlockDynamicException $e) { + $this->blockDynamic($obj); + } catch (BlockNotFoundException $e) { + $this->playlistNotFound($obj_type); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function moveItemsAction() + { + $ids = $this->_getParam('ids'); + $ids = (!is_array($ids)) ? array($ids) : $ids; + $afterItem = $this->_getParam('afterItem', null); + $type = $this->_getParam('obj_type'); + + try { + $obj = $this->getPlaylist($type); + $obj->moveAudioClips($ids, $afterItem); + $this->createUpdateResponse($obj); + } catch (PlaylistOutDatedException $e) { + $this->playlistOutdated($e); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($type); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function deleteItemsAction() + { + $ids = $this->_getParam('ids'); + $ids = (!is_array($ids)) ? array($ids) : $ids; + $modified = $this->_getParam('modified'); + $type = $this->_getParam('obj_type'); + + try { + $obj = $this->getPlaylist($type); + $obj->delAudioClips($ids); + $this->createUpdateResponse($obj); + } catch (PlaylistOutDatedException $e) { + $this->playlistOutdated($e); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($type); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function emptyContentAction() + { + $type = $this->_getParam('obj_type'); + try { + $obj = $this->getPlaylist($type); + if ($type == 'playlist') { + $obj->deleteAllFilesFromPlaylist(); + } else { + $obj->deleteAllFilesFromBlock(); + } + $this->createUpdateResponse($obj); + } catch (PlaylistOutDatedException $e) { + $this->playlistOutdated($e); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($type); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function setCueAction() + { + $id = $this->_getParam('id'); + $cueIn = $this->_getParam('cueIn', null); + $cueOut = $this->_getParam('cueOut', null); + $type = $this->_getParam('type'); + + try { + $obj = $this->getPlaylist($type); + $response = $obj->changeClipLength($id, $cueIn, $cueOut); + + if (!isset($response["error"])) { + $this->view->response = $response; + $this->createUpdateResponse($obj); + } else { + $this->view->cue_error = $response["error"]; + $this->view->code = $response["type"]; + } + } catch (PlaylistOutDatedException $e) { + $this->playlistOutdated($e); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($type); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function setFadeAction() + { + $id = $this->_getParam('id'); + $fadeIn = $this->_getParam('fadeIn', null); + $fadeOut = $this->_getParam('fadeOut', null); + $type = $this->_getParam('type'); + + try { + $obj = $this->getPlaylist($type); + $response = $obj->changeFadeInfo($id, $fadeIn, $fadeOut); + + if (!isset($response["error"])) { + $this->createUpdateResponse($obj); + $this->view->response = $response; + } else { + $this->view->fade_error = $response["error"]; + } + } catch (PlaylistOutDatedException $e) { + $this->playlistOutdated($e); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($type); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function setCrossfadeAction() + { + $id1 = $this->_getParam('id1', null); + $id2 = $this->_getParam('id2', null); + $type = $this->_getParam('type'); + $fadeIn = $this->_getParam('fadeIn', 0); + $fadeOut = $this->_getParam('fadeOut', 0); + $offset = $this->_getParam('offset', 0); + + try { + $obj = $this->getPlaylist($type); + $response = $obj->createCrossfade($id1, $fadeOut, $id2, $fadeIn, $offset); + + if (!isset($response["error"])) { + $this->createUpdateResponse($obj); + } else { + $this->view->error = $response["error"]; + } + } catch (PlaylistOutDatedException $e) { + $this->playlistOutdated($e); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($type); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function getPlaylistFadesAction() + { + $type = $this->_getParam('type'); + try { + $obj = $this->getPlaylist($type); + $fades = $obj->getFadeInfo(0); + $this->view->fadeIn = $fades[0]; + + $fades = $obj->getFadeInfo($obj->getSize()-1); + $this->view->fadeOut = $fades[1]; + } catch (PlaylistOutDatedException $e) { + $this->playlistOutdated($e); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($type); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + /** + * The playlist fades are stored in the elements themselves. + * The fade in is set to the first elements fade in and + * the fade out is set to the last elements fade out. + **/ + public function setPlaylistFadesAction() + { + $fadeIn = $this->_getParam('fadeIn', null); + $fadeOut = $this->_getParam('fadeOut', null); + $type = $this->_getParam('type'); + + try { + $obj = $this->getPlaylist($type); + $obj->setfades($fadeIn, $fadeOut); + $this->view->modified = $obj->getLastModified("U"); + } catch (PlaylistOutDatedException $e) { + $this->playlistOutdated($e); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($type); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function setPlaylistNameDescAction() + { + $name = $this->_getParam('name', _('Unknown Playlist')); + $description = $this->_getParam('description', ""); + $type = $this->_getParam('type'); + + try { + $obj = $this->getPlaylist($type); + $obj->setName(trim($name)); + $obj->setDescription($description); + $this->view->description = $description; + $this->view->playlistName = $name; + $this->view->modified = $obj->getLastModified("U"); + } catch (PlaylistOutDatedException $e) { + $this->playlistOutdated($e); + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound($type, true); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function saveAction() + { + $request = $this->getRequest(); + $params = $request->getPost(); + $result = array(); + + if ($params['type'] == 'block') { + try { + $bl = new Application_Model_Block($params['obj_id']); + } catch (BlockNotFoundException $e) { + $this->playlistNotFound('block', true); + } + $form = new Application_Form_SmartBlockCriteria(); + $form->startForm($params['obj_id']); + if ($form->isValid($params)) { + $this->setPlaylistNameDescAction(); + $bl->saveSmartBlockCriteria($params['data']); + $result['html'] = $this->createFullResponse($bl, true, true); + $result['result'] = 0; + } else { + $this->view->obj = $bl; + $this->view->id = $bl->getId(); + $this->view->form = $form; + $this->view->unsavedName = $params['name']; + $this->view->unsavedDesc = $params['description']; + $viewPath = 'playlist/_smart-block.phtml'; + $result['html'] = $this->view->render($viewPath); + $result['result'] = 1; + } + } else if ($params['type'] == 'playlist') { + $this->setPlaylistNameDescAction(); + } + + $result["modified"] = $this->view->modified; + $this->_helper->json->sendJson($result); + } + + public function smartBlockGenerateAction() + { + $request = $this->getRequest(); + $params = $request->getPost(); + + //make sure block exists + try { + $bl = new Application_Model_Block($params['obj_id']); + + $form = new Application_Form_SmartBlockCriteria(); + $form->startForm($params['obj_id']); + if ($form->isValid($params)) { + $result = $bl->generateSmartBlock($params['data']); + $this->_helper->json->sendJson(array("result"=>0, "html"=>$this->createFullResponse($bl, true, true))); + } else { + $this->view->obj = $bl; + $this->view->id = $bl->getId(); + $this->view->form = $form; + $viewPath = 'playlist/_smart-block.phtml'; + $result['html'] = $this->view->render($viewPath); + $result['result'] = 1; + $this->_helper->json->sendJson($result); + } + } catch (BlockNotFoundException $e) { + $this->playlistNotFound('block', true); + } catch (Exception $e) { + Logging::info($e); + $this->playlistUnknownError($e); + } + } + + public function smartBlockShuffleAction() + { + $request = $this->getRequest(); + $params = $request->getPost(); + try { + $bl = new Application_Model_Block($params['obj_id']); + $result = $bl->shuffleSmartBlock(); + + if ($result['result'] == 0) { + $this->_helper->json->sendJson(array("result"=>0, "html"=>$this->createFullResponse($bl, true))); + } else { + $this->_helper->json->sendJson($result); + } + } catch (BlockNotFoundException $e) { + $this->playlistNotFound('block', true); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function shuffleAction() + { + $request = $this->getRequest(); + $params = $request->getPost(); + try { + $pl = new Application_Model_Playlist($params['obj_id']); + $result = $pl->shuffle(); + + if ($result['result'] == 0) { + $this->_helper->json->sendJson(array("result"=>0, "html"=>$this->createFullResponse($pl, true))); + } else { + $this->_helper->json->sendJson($result); + } + } catch (PlaylistNotFoundException $e) { + $this->playlistNotFound('block', true); + } catch (Exception $e) { + $this->playlistUnknownError($e); + } + } + + public function getBlockInfoAction() + { + $request = $this->getRequest(); + $params = $request->getPost(); + $bl = new Application_Model_Block($params['id']); + if ($bl->isStatic()) { + $out = $bl->getContents(); + $out['isStatic'] = true; + } else { + $out = $bl->getCriteria(); + $out['isStatic'] = false; + } + $this->_helper->json->sendJson($out); + } +} +class WrongTypeToBlockException extends Exception {} +class WrongTypeToPlaylistException extends Exception {} +class BlockDynamicException extends Exception {} diff --git a/airtime_mvc/application/controllers/NewWebstreamController.php b/airtime_mvc/application/controllers/NewWebstreamController.php new file mode 100644 index 000000000..22db7bf7f --- /dev/null +++ b/airtime_mvc/application/controllers/NewWebstreamController.php @@ -0,0 +1,150 @@ +<?php + +class NewWebstreamController extends Zend_Controller_Action +{ + public function init() + { + $ajaxContext = $this->_helper->getHelper('AjaxContext'); + $ajaxContext->addActionContext('new', 'json') + ->addActionContext('save', 'json') + ->addActionContext('edit', 'json') + ->addActionContext('delete', 'json') + ->initContext(); + } + + public function newAction() + { + $userInfo = Zend_Auth::getInstance()->getStorage()->read(); + if (!$this->isAuthorized(-1)) { + // TODO: this header call does not actually print any error message + header("Status: 401 Not Authorized"); + return; + } + + $webstream = new CcWebstream(); + + //we're not saving this primary key in the DB so it's OK to be -1 + $webstream->setDbId(-1); + $webstream->setDbName(_("Untitled Webstream")); + $webstream->setDbDescription(""); + $webstream->setDbUrl("http://"); + $webstream->setDbLength("00:30:00"); + $webstream->setDbName(_("Untitled Webstream")); + $webstream->setDbCreatorId($userInfo->id); + $webstream->setDbUtime(new DateTime("now", new DateTimeZone('UTC'))); + $webstream->setDbMtime(new DateTime("now", new DateTimeZone('UTC'))); + + //clear the session in case an old playlist was open: CC-4196 + Application_Model_Library::changePlaylist(null, null); + + $this->view->obj = new Application_Model_Webstream($webstream); + $this->view->action = "new"; + $this->view->html = $this->view->render('webstream/_webstream.phtml'); + } + + public function editAction() + { + $request = $this->getRequest(); + + $id = $request->getParam("id"); + if (is_null($id)) { + throw new Exception("Missing parameter 'id'"); + } + + $webstream = CcWebstreamQuery::create()->findPK($id); + if ($webstream) { + Application_Model_Library::changePlaylist($id, "stream"); + } + $this->view->obj = new Application_Model_Webstream($webstream); + $this->view->action = "edit"; + $this->view->html = $this->view->render('webstream/_webstream.phtml'); + } + + public function deleteAction() + { + $request = $this->getRequest(); + $id = $request->getParam("ids"); + + if (!$this->isAuthorized($id)) { + header("Status: 401 Not Authorized"); + + return; + } + + $type = "stream"; + Application_Model_Library::changePlaylist(null, $type); + + $webstream = CcWebstreamQuery::create()->findPK($id)->delete(); + + $this->view->obj = null; + $this->view->action = "delete"; + $this->view->html = $this->view->render('webstream/_webstream.phtml'); + + } + + /*TODO : make a user object be passed a parameter into this function so + that it does not have to be fetched multiple times.*/ + public function isAuthorized($webstream_id) + { + $user = Application_Model_User::getCurrentUser(); + if ($user->isUserType(array(UTYPE_SUPERADMIN, UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER))) { + return true; + } + + if ($user->isHost()) { + // not creating a webstream + if ($webstream_id != -1) { + $webstream = CcWebstreamQuery::create()->findPK($webstream_id); + /*we are updating a playlist. Ensure that if the user is a + host/dj, that he has the correct permission.*/ + $user = Application_Model_User::getCurrentUser(); + //only allow when webstream belongs to the DJ + return $webstream->getDbCreatorId() == $user->getId(); + } + /*we are creating a new stream. Don't need to check whether the + DJ/Host owns the stream*/ + return true; + } else { + Logging::info( $user ); + } + return false; + } + + public function saveAction() + { + $request = $this->getRequest(); + + $id = $request->getParam("id"); + + $parameters = array(); + foreach (array('id','length','name','description','url') as $p) { + $parameters[$p] = trim($request->getParam($p)); + } + + if (!$this->isAuthorized($id)) { + header("Status: 401 Not Authorized"); + return; + } + + + list($analysis, $mime, $mediaUrl, $di) = Application_Model_Webstream::analyzeFormData($parameters); + try { + if (Application_Model_Webstream::isValid($analysis)) { + $streamId = Application_Model_Webstream::save($parameters, $mime, $mediaUrl, $di); + + Application_Model_Library::changePlaylist($streamId, "stream"); + + $this->view->statusMessage = "<div class='success'>"._("Webstream saved.")."</div>"; + $this->view->streamId = $streamId; + $this->view->length = $di->format("%Hh %Im"); + } else { + throw new Exception("isValid returned false"); + } + } catch (Exception $e) { + Logging::debug($e->getMessage()); + $this->view->statusMessage = "<div class='errors'>"._("Invalid form values.")."</div>"; + $this->view->streamId = -1; + $this->view->analysis = $analysis; + } + } +} diff --git a/airtime_mvc/application/layouts/scripts/layout.phtml b/airtime_mvc/application/layouts/scripts/layout.phtml index 3bb782dee..8192b474e 100644 --- a/airtime_mvc/application/layouts/scripts/layout.phtml +++ b/airtime_mvc/application/layouts/scripts/layout.phtml @@ -69,14 +69,12 @@ j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src= <?php endif; //suspended ?> </div> +<?php $hint = Application_Common_UsabilityHints::getUsabilityHint(); ?> +<div class="usability_hint" <?php if ($hint == "") { echo "style='display:none'"; } ?>><?php echo $hint; ?></div> <div class="wrapper" id="content"> - <?php - $hint = Application_Common_UsabilityHints::getUsabilityHint(); ?> - - <div class="usability_hint" <?php if ($hint == "") { echo "style='display:none'"; } ?>><?php echo $hint; ?></div> - - <?php echo $this->layout()->content ?></div> + <?php echo $this->layout()->content ?> +</div> <script id="tmpl-pl-cues" type="text/template"> <div class="waveform-cues"> diff --git a/airtime_mvc/application/models/Library.php b/airtime_mvc/application/models/Library.php index 1659f498d..336bd7e7b 100644 --- a/airtime_mvc/application/models/Library.php +++ b/airtime_mvc/application/models/Library.php @@ -11,7 +11,7 @@ class Application_Model_Library $info['className'] = 'Application_Model_Playlist'; } elseif (strcmp($p_type, 'block')==0) { $info['className'] = 'Application_Model_Block'; - } elseif (strcmp($p_type, 'stream')==0) { + } elseif (strcmp($p_type, 'webstream')==0) { $info['className'] = 'Application_Model_Webstream'; } else { throw new Exception("Unknown object type: '$p_type'"); diff --git a/airtime_mvc/application/views/scripts/playlist/_playlist.phtml b/airtime_mvc/application/views/scripts/playlist/_playlist.phtml new file mode 100644 index 000000000..2dde0b61c --- /dev/null +++ b/airtime_mvc/application/views/scripts/playlist/_playlist.phtml @@ -0,0 +1,76 @@ +<?php +if (isset($this->obj)) { + $contents = $this->obj->getContents(); + $count = count($contents); +} +?> +<a href="#" class="close-round" id="lib_pl_close"></a> +<div class="btn-toolbar spl-no-top-margin clearfix"> +<?php if (isset($this->obj)) : ?> + <div class='btn-group pull-right'> + <button class="btn btn-inverse" title='<?php echo _("Empty playlist content") ?>' type="button" id="pl-bl-clear-content"><?php echo _("Clear") ?></button> + </div> + <div class='btn-group pull-right'> + <button class="btn btn-inverse" title='<?php echo _("Shuffle playlist") ?>' type="button" id="playlist_shuffle_button"><?php echo _("Shuffle") ?></button> + </div> + <div class='btn-group pull-right'> + <button class="btn btn-inverse" title='<?php echo _("Save playlist") ?>' type="button" id="save_button"><?php echo _("Save") ?></button> + </div> + <div class='btn-group pull-right'> + <button id="spl_delete" class="btn" role="button" aria-disabled="false"><?php echo _("Delete") ?></button> + </div> + <div class='btn-group pull-right'> + <a href="#" id="spl_crossfade" class="btn crossfade-main-button" style="display:<?php echo $count > 0 ?"block;":"none;"?>"> + <i class='crossfade-main-icon'></i><span class="ui-button-text"><?php echo _("Playlist crossfade") ?></span> + </a> + </div> +<?php endif; ?> +</div> + +<?php if (isset($this->obj)) : ?> + <input id="obj_id" type="hidden" value="<?php echo $this->obj->getId(); ?>"></input> + <input id="obj_lastMod" type="hidden" value="<?php echo $this->obj->getLastModified('U'); ?>"></input> + <input id='obj_type' type='hidden' value='playlist'></input> + <div class="playlist_title"> + <h3 id="obj_name"> + <a id="playlist_name_display" contenteditable="true"><?php echo $this->escape($this->obj->getName()); ?></a> + </h3> + <h4 id="obj_length"><?php echo $this->length; ?></h4> + </div> + <div id='sp-success' class='success' style='display:none'></div> + + <fieldset class="toggle closed" id="fieldset-metadate_change"> + <legend style="cursor: pointer;"><span class="ui-icon ui-icon-triangle-2-n-s"></span><?php echo _("View / edit description"); ?></legend> + <dl class="zend_form"> + <dt id="description-label"><label for="description"><?php echo _("Description") ?></label></dt> + <dd id="description-element"> + <textarea cols="80" rows="24" id="description" name="description"><?php echo $this->escape($this->obj->getDescription()); ?></textarea> + </dd> + </dl> + </fieldset> + + <?php //echo $this->form; ?> + + <div id="crossfade_main" class="crossfade-main clearfix" style="display:none;"> + <span class="ui-icon ui-icon-closethick sp-closethick-center"></span> + <dl id="spl_editor-main" class="inline-list"> + <dt><?php echo _("Fade in: "); ?><span class='spl_cue_hint'>(ss.t)</span></dt> + <dd><span contenteditable="true" class="spl_text_input spl_main_fade_in">00</span></dd> + <dd class="edit-error"></dd> + <dt><?php echo _("Fade out: "); ?><span class='spl_cue_hint'>(ss.t)</span></dt> + <dd><span contenteditable="true" class="spl_text_input spl_main_fade_out">00</span></dd> + <dd class="edit-error"></dd> + </dl> + </div> + + <div class="clear"></div> + <div class="" style="clear:both; float:none; width:100%;"> + <ul id="spl_sortable"> + <?php $this->contents = $contents; + echo $this->render('playlist/update.phtml') ?> + </ul> + </div> + +<?php else : ?> + <div><?php echo _("No open playlist") ?></div> +<?php endif; ?> diff --git a/airtime_mvc/application/views/scripts/playlist/_smart-block.phtml b/airtime_mvc/application/views/scripts/playlist/_smart-block.phtml new file mode 100644 index 000000000..843f98fb3 --- /dev/null +++ b/airtime_mvc/application/views/scripts/playlist/_smart-block.phtml @@ -0,0 +1,81 @@ +<?php +if (isset($this->obj)) { + $contents = $this->obj->getContents(); + $count = count($contents); +} +?> +<a href="#" class="close-round" id="lib_pl_close"></a> +<div class="btn-toolbar spl-no-top-margin clearfix"> +<?php if (isset($this->obj)) : ?> + <div class='btn-group pull-right'> + <button class="btn btn-inverse" title='<?php echo _("Empty smart block content") ?>' type="button" id="pl-bl-clear-content"><?php echo _("Clear") ?></button> + </div> + <div class='btn-group pull-right'> + <button class="btn btn-inverse" title='Save smart block's title, description, and criteria' type="button" id="save_button"><?php echo _("Save") ?></button> + </div> + <div class='btn-group pull-right'> + <button id="spl_delete" class="btn" role="button" aria-disabled="false"><?php echo _("Delete") ?></button> + </div> + <div class='btn-group pull-right'> + <a href="#" id="spl_crossfade" class="btn crossfade-main-button" style="display:<?php echo ($this->obj->isStatic() && $count > 0) ?"block;":"none;"?>"> + <i class='crossfade-main-icon'></i><span class="ui-button-text"><?php echo _("Playlist crossfade") ?></span> + </a> + </div> +<?php endif; ?> +</div> + +<?php if (isset($this->obj)) : ?> + <input id="obj_id" type="hidden" value="<?php echo $this->obj->getId(); ?>"></input> + <input id="obj_lastMod" type="hidden" value="<?php echo $this->obj->getLastModified('U'); ?>"></input> + <input id='obj_type' type='hidden' value='block'></input> + <div class="playlist_title"> + <h3 id="obj_name"> + <a id="playlist_name_display" contenteditable="true"> + <?php + if (isset($this->unsavedName)) echo $this->unsavedName; + else echo $this->escape($this->obj->getName()); + ?> + </a> + </h3> + <h4 id="obj_length"><?php echo $this->length; ?></h4> + </div> + <div id='sp-success-saved' class='success' style='display:none'></div> + + <fieldset class="toggle closed" id="fieldset-metadate_change"> + <legend style="cursor: pointer;"><span class="ui-icon ui-icon-triangle-2-n-s"></span><?php echo _("View / edit description"); ?></legend> + <dl class="zend_form"> + <dt id="description-label"><label for="description"><?php echo _("Description") ?></label></dt> + <dd id="description-element"> + <textarea cols="80" rows="24" id="description" name="description"><?php + if (isset($this->unsavedDesc)) echo $this->unsavedDesc; + else echo $this->obj->getDescription();?> + </textarea> + </dd> + </dl> + </fieldset> + + <?php echo $this->form; ?> + + <div id="crossfade_main" class="crossfade-main clearfix" style="display:none;"> + <span class="ui-icon ui-icon-closethick"></span> + <dl id="spl_editor-main" class="inline-list"> + <dt><?php echo _("Fade in: "); ?><span class='spl_cue_hint'><?php echo _("(ss.t)")?></span></dt> + <dd><span contenteditable="true" class="spl_text_input spl_main_fade_in">00</span></dd> + <dd class="edit-error"></dd> + <dt><?php echo _("Fade out: "); ?><span class='spl_cue_hint'><?php echo _("(ss.t)")?></span></dt> + <dd><span contenteditable="true" class="spl_text_input spl_main_fade_out">00</span></dd> + <dd class="edit-error"></dd> + </dl> + </div> + + <div class="clear"></div> + <div class="" style="clear:both; float:none; width:100%;"> + <ul id="spl_sortable"> + <?php $this->contents = $contents; + echo $this->render('playlist/update.phtml') ?> + </ul> + </div> + +<?php else : ?> + <div><?php echo _("No open smart block") ?></div> +<?php endif; ?> diff --git a/airtime_mvc/application/views/scripts/playlist/playlist.phtml b/airtime_mvc/application/views/scripts/playlist/playlist.phtml index 263b9008c..d187dc866 100644 --- a/airtime_mvc/application/views/scripts/playlist/playlist.phtml +++ b/airtime_mvc/application/views/scripts/playlist/playlist.phtml @@ -6,16 +6,16 @@ if (isset($this->obj)) { ?> <a href="#" class="close-round" id="lib_pl_close"></a> <div class="btn-toolbar spl-no-top-margin clearfix"> -<!-- <div class="btn-group pull-left">--> -<!-- <button id="spl_new" class="btn dropdown-toggle" data-toggle="dropdown" aria-disabled="false">--> -<!-- --><?php //echo _("New")?><!-- <span class="caret"></span>--> -<!-- </button>--> -<!-- <ul class="dropdown-menu">--> -<!-- <li id='lib-new-pl'><a href="#">--><?php //echo _("New Playlist") ?><!--</a></li>--> -<!-- <li id='lib-new-bl'><a href="#">--><?php //echo _("New Smart Block") ?><!--</a></li>--> -<!-- <li id='lib-new-ws'><a href="#">--><?php //echo _("New Webstream") ?><!--</a></li>--> -<!-- </ul>--> -<!-- </div>--> + <div class="btn-group pull-left"> + <button id="spl_new" class="btn dropdown-toggle" data-toggle="dropdown" aria-disabled="false"> + <?php echo _("New")?> <span class="caret"></span> + </button> + <ul class="dropdown-menu"> + <li id='lib-new-pl'><a href="#"><?php echo _("New Playlist") ?></a></li> + <li id='lib-new-bl'><a href="#"><?php echo _("New Smart Block") ?></a></li> + <li id='lib-new-ws'><a href="#"><?php echo _("New Webstream") ?></a></li> + </ul> + </div> <?php if (isset($this->obj)) : ?> <div class='btn-group pull-right'> <button class="btn btn-inverse" title='<?php echo _("Empty playlist content") ?>' type="button" id="pl-bl-clear-content"><?php echo _("Clear") ?></button> diff --git a/airtime_mvc/application/views/scripts/playlist/smart-block.phtml b/airtime_mvc/application/views/scripts/playlist/smart-block.phtml index 8b9e0ad82..716fdce38 100644 --- a/airtime_mvc/application/views/scripts/playlist/smart-block.phtml +++ b/airtime_mvc/application/views/scripts/playlist/smart-block.phtml @@ -6,16 +6,16 @@ if (isset($this->obj)) { ?> <a href="#" class="close-round" id="lib_pl_close"></a> <div class="btn-toolbar spl-no-top-margin clearfix"> -<!-- <div class="btn-group pull-left">--> -<!-- <button id="spl_new" class="btn dropdown-toggle" data-toggle='dropdown' aria-disabled="false">--> -<!-- --><?php //echo _("New")?><!-- <span class="caret"></span>--> -<!-- </button>--> -<!-- <ul class="dropdown-menu">--> -<!-- <li id='lib-new-pl'><a href="#">--><?php //echo _("New Playlist") ?><!--</a></li>--> -<!-- <li id='lib-new-bl'><a href="#">--><?php //echo _("New Smart Block") ?><!--</a></li>--> -<!-- <li id='lib-new-ws'><a href="#">--><?php //echo _("New Webstream") ?><!--</a></li>--> -<!-- </ul>--> -<!-- </div>--> + <div class="btn-group pull-left"> + <button id="spl_new" class="btn dropdown-toggle" data-toggle='dropdown' aria-disabled="false"> + <?php echo _("New")?> <span class="caret"></span> + </button> + <ul class="dropdown-menu"> + <li id='lib-new-pl'><a href="#"><?php echo _("New Playlist") ?></a></li> + <li id='lib-new-bl'><a href="#"><?php echo _("New Smart Block") ?></a></li> + <li id='lib-new-ws'><a href="#"><?php echo _("New Webstream") ?></a></li> + </ul> + </div> <?php if (isset($this->obj)) : ?> <div class='btn-group pull-right'> <button class="btn btn-inverse" title='<?php echo _("Empty smart block content") ?>' type="button" id="pl-bl-clear-content"><?php echo _("Clear") ?></button> diff --git a/airtime_mvc/application/views/scripts/show-builder/index.phtml b/airtime_mvc/application/views/scripts/show-builder/index.phtml index 8142bd68c..0308b1cf0 100644 --- a/airtime_mvc/application/views/scripts/show-builder/index.phtml +++ b/airtime_mvc/application/views/scripts/show-builder/index.phtml @@ -5,7 +5,7 @@ <!-- </div>--> <!--</form>--> -<div id="media_type_nav"> +<div id="media_type_nav" class="content-pane"> <div class="btn-group"> <button id="new_media_selector" class="btn btn-small dropdown-toggle" data-toggle="dropdown"> New <span class="caret"></span> @@ -28,26 +28,33 @@ <div class="media_type_selector" selection_id="4"><?php echo _("Webstreams") ?></div> </div> -<div id="library_content" class="lib-content tabs"> - <fieldset class="toggle closed" id="filter_options"> - <legend style="cursor: pointer;"> - <span class="ui-icon ui-icon-triangle-2-n-s"></span> - <?php echo _("Advanced Search Options") ?> - </legend> - <div id="advanced_search" class="advanced_search form-horizontal"></div> - </fieldset> - <table id="library_display" cellpadding="0" cellspacing="0" class="datatable"> - </table> -</div> - -<div id="show_builder" class="sb-content"> - <div class="sb-timerange"> - <?php echo $this->sb_form; ?> +<div id="library_content" class="lib-content tabs content-pane wide-panel"> + <div class="panel-header"> + <fieldset class="toggle closed" id="filter_options"> + <legend style="cursor: pointer;"> + <span class="ui-icon ui-icon-triangle-2-n-s"></span> + <?php echo _("Advanced Search Options") ?> + </legend> + <div id="advanced_search" class="advanced_search form-horizontal"></div> + </fieldset> + </div> + <div class="outer-datatable-wrapper"> + <table id="library_display" cellpadding="0" cellspacing="0" class="datatable"></table> </div> - <table id="show_builder_table" cellpadding="0" cellspacing="0" class="datatable"></table> </div> -<div id="side_playlist" class="pl-content"> +<div id="show_builder" class="sb-content content-pane wide-panel"> + <div class="panel-header"> + <ul class="nav nav-tabs"> + <li id="timeline-tab" role="presentation" class="active"><a href="#">Timeline</a></li> + </ul> + </div> + <div class="outer-datatable-wrapper active-tab"> + <table id="show_builder_table" cellpadding="0" cellspacing="0" class="datatable"></table> + <div class="sb-timerange"> + <?php echo $this->sb_form; ?> + </div> + </div> </div> <?php echo $this->dialog ?> diff --git a/airtime_mvc/application/views/scripts/webstream/_webstream.phtml b/airtime_mvc/application/views/scripts/webstream/_webstream.phtml new file mode 100644 index 000000000..3fb175c9c --- /dev/null +++ b/airtime_mvc/application/views/scripts/webstream/_webstream.phtml @@ -0,0 +1,55 @@ +<a href="#" class="close-round" id="lib_pl_close"></a> +<div class="btn-toolbar spl-no-top-margin clearfix"> + +<?php if (isset($this->obj)) : ?> + <div class="btn-group pull-right"> + <button class="btn btn-inverse" type="submit" id="webstream_save" name="submit"><?php echo _("Save") ?></button> +</div> +<div class="btn-group pull-right"> + <button id="ws_delete" class="btn" <?php if ($this->action == "new"): ?>style="display:none;"<?php endif; ?>aria-disabled="false"><?php echo _("Delete") ?></button> +</div> +<?php endif; ?> +</div> + +<?php if (isset($this->obj)) : ?> + <input id="obj_id" type="hidden" value="<?php echo $this->obj->getId(); ?>"/> + <input id="obj_lastMod" type="hidden" value="<?php echo "1";//$this->obj->getLastModified('U'); ?>"/> + <input id="obj_type" type="hidden" value="webstream"/> + <div class="status" style="display:none;"></div> + + <div class="playlist_title"> + <div id="name-error" class="errors" style="display:none;"></div> + <h3 id="ws_name"> + <a id="playlist_name_display" contenteditable="true"><?php echo $this->escape($this->obj->getName()); ?></a> + </h3> + <h4 id="ws_length"><?php echo $this->obj->getDefaultLength(); ?></h4> + </div> + + <fieldset class="toggle" id="fieldset-metadate_change"> + <legend style="cursor: pointer;"><span class="ui-icon ui-icon-triangle-2-n-s"></span><?php echo _("View / edit description"); ?></legend> + <dl class="zend_form"> + <dt id="description-label"><label for="description"><?php echo _("Description") ?></label></dt> + <dd id="description-element"> + <textarea cols="80" rows="24" id="description" name="description"><?php echo $this->obj->getDescription(); ?></textarea> + </dd> + + </dl> + </fieldset> + + <dl class="zend_form"> + <dt id="submit-label" style="display: none;"> </dt> + <div id="url-error" class="errors" style="display:none;"></div> + <dt id="streamurl-label"><label for="streamurl"><?php echo _("Stream URL:"); ?></label></dt> + <dd id="streamurl-element"> + <input type="text" value="<?php echo $this->obj->getUrl(); ?>" size="40"/> + </dd> + <div id="length-error" class="errors" style="display:none;"></div> + <dt id="streamlength-label"><label for="streamlength"><?php echo _("Default Length:"); ?></label></dt> + <dd id="streamlength-element"> + <input type="text" value="<?php echo $this->obj->getDefaultLength() ?>"/> + </dd> + </dl> + +<?php else : ?> + <div><?php echo _("No webstream") ?></div> +<?php endif; ?> diff --git a/airtime_mvc/application/views/scripts/webstream/webstream.phtml b/airtime_mvc/application/views/scripts/webstream/webstream.phtml index 45790bb3b..9c9af52b4 100644 --- a/airtime_mvc/application/views/scripts/webstream/webstream.phtml +++ b/airtime_mvc/application/views/scripts/webstream/webstream.phtml @@ -1,15 +1,15 @@ <a href="#" class="close-round" id="lib_pl_close"></a> <div class="btn-toolbar spl-no-top-margin clearfix"> -<!-- <div class="btn-group pull-left">--> -<!-- <button id="ws_new" class="btn dropdown-toggle" data-toggle="dropdown" aria-disabled="false">--> -<!-- --><?php //echo _("New")?><!-- <span class="caret"></span>--> -<!-- </button>--> -<!-- <ul class="dropdown-menu">--> -<!-- <li id='lib-new-pl'><a href="#">--><?php //echo _("New Playlist") ?><!--</a></li>--> -<!-- <li id='lib-new-bl'><a href="#">--><?php //echo _("New Smart Block") ?><!--</a></li>--> -<!-- <li id='lib-new-ws'><a href="#">--><?php //echo _("New Webstream") ?><!--</a></li>--> -<!-- </ul>--> -<!-- </div>--> + <div class="btn-group pull-left"> + <button id="ws_new" class="btn dropdown-toggle" data-toggle="dropdown" aria-disabled="false"> + <?php echo _("New")?> <span class="caret"></span> + </button> + <ul class="dropdown-menu"> + <li id='lib-new-pl'><a href="#"><?php echo _("New Playlist") ?></a></li> + <li id='lib-new-bl'><a href="#"><?php echo _("New Smart Block") ?></a></li> + <li id='lib-new-ws'><a href="#"><?php echo _("New Webstream") ?></a></li> + </ul> + </div> <?php if (isset($this->obj)) : ?> <div class="btn-group pull-right"> diff --git a/airtime_mvc/public/css/_showbuilder.css b/airtime_mvc/public/css/_showbuilder.css index 9d2daa730..d42272c12 100644 --- a/airtime_mvc/public/css/_showbuilder.css +++ b/airtime_mvc/public/css/_showbuilder.css @@ -9,17 +9,12 @@ div.ColVis_collectionBackground { } .wrapper { - position: absolute; - /* Height of the top panel */ - top: 141px; - bottom: 0; /*background: #242424;*/ background: #111; left: 0; right: 0; + bottom: 0; padding: 10px; - overflow-y: auto; - overflow-x: hidden; display: -webkit-box; display: -moz-box; @@ -28,6 +23,8 @@ div.ColVis_collectionBackground { display: flex; -webkit-flex-flow: row wrap; flex-flow: row wrap; + + overflow: auto; } /* Usability hint */ @@ -57,40 +54,98 @@ div.ColVis_collectionBackground { /* Show Builder*/ +.content-pane { + position: relative; + + border: 1px solid #202020; + border-top: 1px solid #353535; + border-left: 1px solid #2a2a2a; + + -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.65); + -moz-box-shadow: inset 0 0 6px rgba(0,0,0,.65); + box-shadow: inset 0 0 6px rgba(0,0,0,.65); + + background-color: #242424; +} + +.wide-panel { + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -webkit-flex-flow: column; + flex-flow: column; + + /* Account for the left pane */ + flex: 6 auto; + min-width: 555px; +} + +.btn { + color: #efefef; +} + +.outer-datatable-wrapper { + position: relative; + flex: 1; +} + +@media screen and (max-height: 650px) { + #master-panel { + display: none; + } + .wrapper { + top: 40px !important; + } +} + @media screen and (max-width: 1475px) { - #library_content, #show_builder, #side_playlist, #media_type_nav { - /*height: auto !important;*/ - max-height: 50% !important; + .wrapper { + -webkit-flex-flow: column !important; + flex-flow: column !important; + } + .content-pane { + height: auto !important; width: 100% !important; } + .wide-panel { + flex: 8 100%; + min-height: 50%; + } #side_playlist { margin-top: 0 !important; } - #media_type_nav div { - float: left; - width: 20%; - text-align: center; - margin: auto; + #media_type_nav { + display: -webkit-box; + display: -moz-box; + display: -ms-flexbox; + display: -webkit-flex; + display: flex; + -webkit-flex-flow: row; + flex-flow: row; + + -webkit-align-items: center; + align-items: center; + -webkit-justify-content: center; + justify-content: center; + } + #media_type_nav .btn-group { + flex: 1 100%; } #media_type_nav .dropdown-menu { width: 100%; - text-align: center; } #media_type_nav .media_type_selector { + flex: 1 100%; margin-top: 3px; } } @media screen and (max-width: 780px) { - #library_content .dataTables_filter input[type="text"] { - position: relative; - width: calc(100% - 10px) !important; - margin: 0 .5em .5em 0; - } .wrapper { - height: calc(100% - 166px) !important; /* Correct for margins */ + height: 100% !important; /* Correct for margins */ padding: 0 15px 15px !important; - margin-top: 10px; /* This is only necessary if we aren't using a responsive menu! */ } } @@ -101,23 +156,11 @@ div.ColVis_collectionBackground { } } -.btn { - color: #efefef; -} - /* Library */ #library_content { margin-right: 10px; overflow: hidden !important; - - display: -webkit-box; - display: -moz-box; - display: -ms-flexbox; - display: -webkit-flex; - display: flex; - -webkit-flex-flow: row wrap; - flex-flow: row wrap; } #library_content .dataTables_filter { @@ -143,67 +186,56 @@ div.ColVis_collectionBackground { color: #555555; } +#library_content legend { + position: absolute; + top: 0; + + padding-top: 4px; + font-size: 14px; +} + #library_content legend, #library_content span, #library_content label { font-weight: normal; color: #efefef; } -#library_content .fg-toolbar.ui-toolbar.ui-widget-header.ui-corner-bl.ui-corner-br.ui-helper-clearfix { +.fg-toolbar.ui-toolbar.ui-widget-header.ui-corner-bl.ui-corner-br.ui-helper-clearfix { position: absolute; right: 0; left: 0; bottom: 0; } -#library_display_wrapper { - flex: 1 100%; -} - #library_display_wrapper, #show_builder_table_wrapper { position: absolute; - top: 36px; + top: 4px; bottom: 4px; right: 4px; left: 4px; - /*background-color: #474747;*/ } -#library_content, #show_builder, #side_playlist, #media_type_nav { - position: relative; - height: 95%; - - border: 1px solid #202020; - border-top: 1px solid #272727; - border-left: 1px solid #272727; - - -webkit-box-shadow: inset 0 0 6px rgba(0,0,0,.65); - -moz-box-shadow: inset 0 0 6px rgba(0,0,0,.65); - box-shadow: inset 0 0 6px rgba(0,0,0,.65); - - background-color: #242424; -} - -#library_content, #show_builder, #side_playlist { - /* Account for the left pane */ - flex: 5 auto; - min-width: 470px; -} - -#library_content .dataTables_scrolling { +.dataTables_scrolling { position: absolute; - bottom: 38px; + bottom: 38px; /* 38 px is the size of the header/footer */ top: 38px; - left: 0; + left: 1px; /* Border */ right: 0; } -#filter_options{ - position: absolute; - top: 4px; - left: 4px; - right: 4px; +#filter_options { + text-align: center; + padding: 15px 0 15px 15px; + margin: 0; + border: none; +} - flex: 1 100%; +#advanced_search { + margin-top: 15px; +} + +.panel-header { + position: relative; + top: 4px; } /* Timeline */ @@ -221,6 +253,7 @@ div.ColVis_collectionBackground { } #sb_submit { + font-weight: normal; text-decoration: none; padding: 4px; color: #efefef; @@ -228,10 +261,8 @@ div.ColVis_collectionBackground { } .sb-options-form { - position: absolute; - top: 4px; - left: 4px; - right: 4px; + position: relative; + padding: 5px; float: left; } @@ -240,29 +271,64 @@ div.ColVis_collectionBackground { line-height: 26px; } -.dataTables_scrolling.sb-padded { - position: absolute; - top: 38px; - bottom: 4px; - right: 0; - left: 0; -} - #sb_show_filter { float: right; + margin-left: 4px; } -#show_builder_table_wrapper { - bottom: 0; +.nav-tabs { + border-bottom: 1px solid #474747; + font-family: Arial, Helvetica, sans-serif; + font-size: 12px; + padding: 0; + margin: 0 4px 0; +} + +.nav-tabs a { + padding: 4px 8px !important; + + color: #efefef; + font-size: 14px; + text-decoration: none; + + background-color: rgba(71,71,71,.5); + +} + +.nav-tabs :not(.active) a:hover { + background-color: rgba(239, 76, 10, .5) !important; + border: 1px solid transparent !important; + border-bottom: 1px solid #474747 !important; +} + +.nav-tabs > .active > a, .nav-tabs > .active > a:hover { + color: #efefef; + + background-color: #474747; + border: 1px solid #474747; + border-bottom-color: transparent; + cursor: default; } /* Media editors */ #side_playlist { - float: right; - color: #efefef; - font-size: inherit; - overflow: hidden; + width: 100%; /* Override because we're using flexbox */ + + overflow-x: hidden; + overflow-y: auto; + + position: relative; + + flex: 1; +} + +.editor_pane_wrapper { + padding: 4px; +} + +#spl_sortable .list-item-container { + cursor: move; } /* Media type selector */ @@ -270,6 +336,7 @@ div.ColVis_collectionBackground { #media_type_nav { flex: 1 auto; margin-right: 10px; + text-align: center; } #media_type_nav div { @@ -278,6 +345,7 @@ div.ColVis_collectionBackground { #new_media_selector { width: 100%; + font-size: 14px; } .media_type_selector { @@ -286,7 +354,6 @@ div.ColVis_collectionBackground { font-family: Roboto, "Open Sans", sans-serif; font-size: 16px; font-weight: 400; - width: 100%; margin: 10px 10px 0 0; -webkit-transition: color 0.2s linear; @@ -318,19 +385,21 @@ div.ColVis_collectionBackground { overflow: auto; } -.helper.ui-draggable-dragging { - z-index: 9999; -} - .datatable tr, .datatable td { border: none !important; } +/* This is so dragged items show up above the layout */ +.ui-draggable-dragging { + z-index: 9999; + position: fixed !important; +} + /* Uploads/Dropzone */ #upload_form { width: 100%; - min-width: 470px; + min-width: 555px; background: none; border: 2px dashed #efefef; diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css index b51c8b049..eb302fb71 100644 --- a/airtime_mvc/public/css/styles.css +++ b/airtime_mvc/public/css/styles.css @@ -3310,13 +3310,27 @@ dd .stream-status { /* Usability Hints */ +/* + * This is a temporary solution to a larger issue; + * we should revisit this (and really all of the + * absolute positioning in Airtime) when we want + * to focus on responsive design. + */ +.usability_hint + .wrapper { + top: 170px; +} + .usability_hint { padding: 5px 10px 5px 10px; - margin-bottom: 10px; border: 1px solid #ff611f; background-color: #ff611f; color: white; font-size: 14px; + + position: absolute; + top: 139px; + width: 100%; + z-index: 1; } .usability_hint a { diff --git a/airtime_mvc/public/js/airtime/library/_library.js b/airtime_mvc/public/js/airtime/library/_library.js index b2b4284f0..a8a484e51 100644 --- a/airtime_mvc/public/js/airtime/library/_library.js +++ b/airtime_mvc/public/js/airtime/library/_library.js @@ -392,7 +392,7 @@ var AIRTIME = (function(AIRTIME) { $.post(baseUrl+"playlist/close-playlist", {"format": "json", "type": currentObjType}, function(json) { - $("#side_playlist").empty().append(json.html); + $("#editor_pane_wrapper").empty().append(json.html); }); } } @@ -685,7 +685,7 @@ var AIRTIME = (function(AIRTIME) { "oLanguage": datatables_dict, // R = ColReorder, C = ColVis - "sDom": 'R<"#library_display_type"><"dt-process-rel"r><"H"<"library_toolbar"Cf>><"dataTables_scrolling"t><"F"ilp>>', + "sDom": 'R<"dt-process-rel"r><"H"<"library_toolbar"Cf>><"dataTables_scrolling"t><"F"ilp>>', "oColVis": { "sAlign": "right", diff --git a/airtime_mvc/public/js/airtime/library/_spl.js b/airtime_mvc/public/js/airtime/library/_spl.js index 6b1c29df1..f5885ce30 100644 --- a/airtime_mvc/public/js/airtime/library/_spl.js +++ b/airtime_mvc/public/js/airtime/library/_spl.js @@ -15,7 +15,9 @@ var AIRTIME = (function(AIRTIME){ $togglePl = $("<button id='pl_edit' class='btn btn-small' href='#' title='"+$.i18n._("Open Media Builder")+"'>"+$.i18n._("Open Media Builder")+"</button>"), widgetHeight, resizeTimeout, - width; + width, + $plCount = 0, + $openTabs = {}; function isTimeValid(time) { //var regExpr = new RegExp("^\\d{2}[:]\\d{2}[:]\\d{2}([.]\\d{1,6})?$"); @@ -32,6 +34,7 @@ var AIRTIME = (function(AIRTIME){ function playlistError(json) { alert(json.error); + closeTab(); openPlaylist(json); } @@ -67,7 +70,7 @@ var AIRTIME = (function(AIRTIME){ event.stopPropagation(); var span = $(this), id = span.parent().attr("id").split("_").pop(), - url = baseUrl+"Playlist/set-cue", + url = baseUrl+"new-playlist/set-cue", cueIn = $.trim(span.text()), li = span.parents("li"), unqid = li.attr("unqid"), @@ -104,7 +107,7 @@ var AIRTIME = (function(AIRTIME){ event.stopPropagation(); var span = $(this), id = span.parent().attr("id").split("_").pop(), - url = baseUrl+"Playlist/set-cue", + url = baseUrl+"new-playlist/set-cue", cueOut = $.trim(span.text()), li = span.parents("li"), unqid = li.attr("unqid"), @@ -141,7 +144,7 @@ var AIRTIME = (function(AIRTIME){ /* used from waveform pop-up */ function changeCues($el, id, cueIn, cueOut) { - var url = baseUrl+"Playlist/set-cue", + var url = baseUrl+"new-playlist/set-cue", lastMod = getModified(), type = $('#obj_type').val(), li, @@ -211,7 +214,7 @@ var AIRTIME = (function(AIRTIME){ /* used from waveform pop-up */ function changeCrossfade($el, id1, id2, fadeIn, fadeOut, offset, id) { - var url = baseUrl+"Playlist/set-crossfade", + var url = baseUrl+"new-playlist/set-crossfade", lastMod = getModified(), type = $('#obj_type').val(); @@ -229,7 +232,7 @@ var AIRTIME = (function(AIRTIME){ setPlaylistContent(json); - $li = $('#side_playlist li[unqid='+id+']'); + $li = $pl.find('li[unqid='+id+']'); $li.find('.crossfade').toggle(); highlightActive($li.find('.spl_fade_control')); }); @@ -240,7 +243,7 @@ var AIRTIME = (function(AIRTIME){ var span = $(this), id = span.parent().attr("id").split("_").pop(), - url = baseUrl+"Playlist/set-fade", + url = baseUrl+"new-playlist/set-fade", fadeIn = $.trim(span.text()), li = span.parents("li"), unqid = li.attr("unqid"), @@ -267,7 +270,7 @@ var AIRTIME = (function(AIRTIME){ setPlaylistContent(json); - li = $('#side_playlist li[unqid='+unqid+']'); + li = $pl.find('li[unqid='+unqid+']'); li.find('.crossfade').toggle(); highlightActive(li.find('.spl_fade_control')); }); @@ -278,7 +281,7 @@ var AIRTIME = (function(AIRTIME){ var span = $(this), id = span.parent().attr("id").split("_").pop(), - url = baseUrl+"Playlist/set-fade", + url = baseUrl+"new-playlist/set-fade", fadeOut = $.trim(span.text()), li = span.parents("li"), unqid = li.attr("unqid"), @@ -305,7 +308,7 @@ var AIRTIME = (function(AIRTIME){ setPlaylistContent(json); - li = $('#side_playlist li[unqid='+unqid+']'); + li = $pl.find('li[unqid='+unqid+']'); li.find('.crossfade').toggle(); highlightActive(li.find('.spl_fade_control')); }); @@ -358,6 +361,9 @@ var AIRTIME = (function(AIRTIME){ var nameElement = $(this); //remove any newlines if user somehow snuck them in (easy to do if dragging/dropping text) nameElement.text(nameElement.text().replace("\n", "")); + + var name = $pl.find("#playlist_name_display").text(); + $(".nav.nav-tabs .active a").text(name); } function redrawLib() { @@ -392,12 +398,12 @@ var AIRTIME = (function(AIRTIME){ } function setFadeIcon(){ - var contents = $("#spl_sortable"); + var contents = $pl.find("#spl_sortable"); var show = contents.is(":visible"); - var empty = $(".spl_empty"); + var empty = $pl.find(".spl_empty"); if (!show || empty.length > 0) { - $("#spl_crossfade").hide(); + $pl.find("#spl_crossfade").hide(); } else { //get list of playlist contents var list = contents.children(); @@ -407,33 +413,60 @@ var AIRTIME = (function(AIRTIME){ var last = list.last(); if (first.find(':first-child').children().attr('blockid') !== undefined && last.find(':first-child').children().attr('blockid') !== undefined) { - $("#spl_crossfade").hide(); + $pl.find("#spl_crossfade").hide(); } else { - $("#spl_crossfade").show(); + $pl.find("#spl_crossfade").show(); } } } function getId() { - return parseInt($("#obj_id").val(), 10); + return parseInt($pl.find("#obj_id").val(), 10); } function getModified() { - return parseInt($("#obj_lastMod").val(), 10); + return parseInt($pl.find("#obj_lastMod").val(), 10); } function setModified(modified) { - $("#obj_lastMod").val(modified); + $pl.find("#obj_lastMod").val(modified); } function openPlaylist(json) { - $("#side_playlist") - .empty() - .append(json.html); + $plCount++; + var tabId = $openTabs[json.id]; + if ($openTabs[json.id] !== undefined) { + AIRTIME.showbuilder.switchTab($(".pl-tab-content-" + tabId), $("#pl-tab-" + tabId)); + return; + } - setUpPlaylist(); - setCueEvents(); - setFadeEvents(); + var wrapper = "<div id='side_playlist' class='pl-content pl-tab-content-" + $plCount + "'><div class='editor_pane_wrapper'></div></div>", + t = $("#show_builder").append(wrapper).find(".pl-tab-content-" + $plCount), + pane = $(".editor_pane_wrapper:last"), + name = pane.append(json.html).find("#playlist_name_display").text(), + tab = "<li id='pl-tab-" + $plCount + "' role='presentation' class='active'><a href='#'>" + name + "</a></li>", + tabs = $(".nav.nav-tabs"); + + if (json.id) { + $openTabs[json.id] = $plCount; + } + + + $(".nav.nav-tabs li").removeClass("active"); + tabs.append(tab); + var newTab = $("#pl-tab-" + $plCount); + + newTab.on("click", function() { + AIRTIME.showbuilder.switchTab(t, newTab); + $.post(baseUrl+'new-playlist/edit', + {format: "json", id: t.find("#obj_id").val(), type: t.find("#obj_type").val()}); + }); + AIRTIME.showbuilder.switchTab(t, newTab); + AIRTIME.playlist.init(); + + //setUpPlaylist(); + //setCueEvents(); + //setFadeEvents(); // functions in smart_blockbuilder.js setupUI(); @@ -452,6 +485,13 @@ var AIRTIME = (function(AIRTIME){ $("#pl_edit").hide(); } + function closeTab() { + delete $openTabs[$(".active-tab").find("#obj_id").val()]; + $(".nav.nav-tabs .active").remove(); + $pl.remove(); + AIRTIME.showbuilder.switchTab($("#show_builder .outer-datatable-wrapper"), $("#timeline-tab")); + } + //Purpose of this function is to iterate over all playlist elements //and verify whether they can be previewed by the browser or not. If not //then the playlist element is greyed out @@ -514,11 +554,10 @@ var AIRTIME = (function(AIRTIME){ } } }); - } + }; //sets events dynamically for playlist entries (each row in the playlist) function setPlaylistEntryEvents() { - $pl.delegate("#spl_sortable .ui-icon-closethick", {"click": function(ev){ var id; @@ -537,7 +576,7 @@ var AIRTIME = (function(AIRTIME){ var id = parseInt($(this).attr("id").split("_").pop(), 10); var blockId = parseInt($(this).attr("blockId"), 10); if ($(this).hasClass('close')) { - var sUrl = baseUrl+"playlist/get-block-info"; + var sUrl = baseUrl+"new-playlist/get-block-info"; mod.disableUI(); $.post(sUrl, {format:"json", id:blockId}, function(data){ $html = ""; @@ -624,7 +663,7 @@ var AIRTIME = (function(AIRTIME){ //main playlist fades events $pl.on("click", "#spl_crossfade", function() { var lastMod = getModified(), - type = $('#obj_type').val(); + type = $pl.find('#obj_type').val(); if ($(this).hasClass("ui-state-active")) { $(this).removeClass("ui-state-active"); @@ -633,7 +672,7 @@ var AIRTIME = (function(AIRTIME){ else { $(this).addClass("ui-state-active"); - var url = baseUrl+'Playlist/get-playlist-fades'; + var url = baseUrl+'new-playlist/get-playlist-fades'; $.post(url, {format: "json", modified: lastMod, type: type}, function(json){ @@ -670,11 +709,11 @@ var AIRTIME = (function(AIRTIME){ $pl.on("blur", "span.spl_main_fade_in", function(event){ event.stopPropagation(); - var url = baseUrl+"Playlist/set-playlist-fades", + var url = baseUrl+"new-playlist/set-playlist-fades", span = $(this), fadeIn = $.trim(span.text()), lastMod = getModified(), - type = $('#obj_type').val(); + type = $pl.find('#obj_type').val(); if (!isFadeValid(fadeIn)){ showError(span, $.i18n._("please put in a time in seconds '00 (.0)'")); @@ -694,11 +733,11 @@ var AIRTIME = (function(AIRTIME){ $pl.on("blur", "span.spl_main_fade_out", function(event){ event.stopPropagation(); - var url = baseUrl+"Playlist/set-playlist-fades", + var url = baseUrl+"new-playlist/set-playlist-fades", span = $(this), fadeOut = $.trim(span.text()), lastMod = getModified(), - type = $('#obj_type').val(); + type = $pl.find('#obj_type').val(); if (!isFadeValid(fadeOut)){ showError(span, $.i18n._("please put in a time in seconds '00 (.0)'")); @@ -743,14 +782,14 @@ var AIRTIME = (function(AIRTIME){ $pl.on("click", 'button[id="playlist_shuffle_button"]', function(){ obj_id = $('input[id="obj_id"]').val(); - url = baseUrl+"Playlist/shuffle"; + url = baseUrl+"new-playlist/shuffle"; enableLoadingIcon(); $.post(url, {format: "json", obj_id: obj_id}, function(json){ if (json.error !== undefined) { alert(json.error); } - AIRTIME.playlist.fnOpenPlaylist(json); + $pl.find(".editor_pane_wrapper").empty().append(json.html); if (json.result == "0") { $pl.find('.success').text($.i18n._('Playlist shuffled')); $pl.find('.success').show(); @@ -760,7 +799,7 @@ var AIRTIME = (function(AIRTIME){ }); }); - $pl.on("click", "#webstream_save", function(){ + $pl.find("#webstream_save").on("click", function(){ //get all fields and POST to server //description //stream url @@ -775,7 +814,7 @@ var AIRTIME = (function(AIRTIME){ //hide any previous errors (if any) $("#side_playlist .errors").empty().hide(); - var url = baseUrl+'Webstream/save'; + var url = baseUrl+'new-webstream/save'; $.post(url, {format: "json", id:id, description: description, url:streamurl, length: length, name: name}, function(json){ @@ -815,7 +854,7 @@ var AIRTIME = (function(AIRTIME){ $lib.on("click", "#pl_edit", function() { openPlaylistPanel(); - $.ajax( { + $.ajax({ url : baseUrl+"usersettings/set-library-screen-settings", type : "POST", data : { @@ -830,18 +869,19 @@ var AIRTIME = (function(AIRTIME){ $pl.on("click", "#lib_pl_close", function() { $pl.hide(); - $("#show_builder").show(); // We need to update the text on the add button AIRTIME.library.checkAddButton(); // We also need to run the draw callback to update how dragged items are drawn AIRTIME.library.fnDrawCallback(); - var name = $('#playlist_name_display').text().trim(); + var name = $pl.find('#playlist_name_display').text().trim(); if ((name == "Untitled Playlist" || name == "Untitled Smart Block") - && $("#spl_sortable .spl_empty").length == 1) { + && $pl.find("#spl_sortable .spl_empty").length == 1) { mod.fnDelete(); + } else { + closeTab(); } $.ajax( { @@ -857,16 +897,16 @@ var AIRTIME = (function(AIRTIME){ }); }); - $('#save_button').live("click", function(event){ + $pl.on("click", "#save_button", function(event) { /* Smart blocks: get name, description, and criteria * Playlists: get name, description */ - var criteria = $('form').serializeArray(), - block_name = $('#playlist_name_display').text(), - block_desc = $('textarea[name="description"]').val(), - save_action = baseUrl+'Playlist/save', - obj_id = $('input[id="obj_id"]').val(), - obj_type = $('#obj_type').val(), + var criteria = $pl.find('form').serializeArray(), + block_name = $pl.find('#playlist_name_display').text(), + block_desc = $pl.find('textarea[name="description"]').val(), + save_action = baseUrl+'new-playlist/save', + obj_id = $pl.find('input[id="obj_id"]').val(), + obj_type = $pl.find('#obj_type').val(), lastMod = getModified(), dt = $('table[id="library_display"]').dataTable(); enableLoadingIcon(); @@ -894,8 +934,8 @@ var AIRTIME = (function(AIRTIME){ ); }); - $("#pl-bl-clear-content").live("click", function(event) { - var sUrl = baseUrl+"playlist/empty-content", + $pl.find("#pl-bl-clear-content").live("click", function(event) { + var sUrl = baseUrl+"new-playlist/empty-content", oData = {}; playlistRequest(sUrl, oData); }); @@ -994,9 +1034,7 @@ var AIRTIME = (function(AIRTIME){ } mod.fnNew = function() { - var url = baseUrl+'Playlist/new'; - $("#side_playlist").show(); - $("#show_builder").hide(); + var url = baseUrl+'new-playlist/new'; stopAudioPreview(); @@ -1009,9 +1047,7 @@ var AIRTIME = (function(AIRTIME){ }; mod.fnWsNew = function() { - var url = baseUrl+'Webstream/new'; - $("#side_playlist").show(); - $("#show_builder").hide(); + var url = baseUrl+'new-webstream/new'; stopAudioPreview(); @@ -1025,9 +1061,7 @@ var AIRTIME = (function(AIRTIME){ mod.fnNewBlock = function() { - var url = baseUrl+'Playlist/new'; - $("#side_playlist").show(); - $("#show_builder").hide(); + var url = baseUrl+'new-playlist/new'; stopAudioPreview(); @@ -1040,18 +1074,14 @@ var AIRTIME = (function(AIRTIME){ }; mod.fnEdit = function(id, type, url) { - $("#side_playlist").show(); - $("#show_builder").hide(); - - if ($pl.is(":hidden")) { - openPlaylistPanel(); - } + //openPlaylistPanel(); stopAudioPreview(); $.post(url, {format: "json", id: id, type: type}, function(json){ openPlaylist(json); + redrawLib(); }); }; @@ -1062,13 +1092,14 @@ var AIRTIME = (function(AIRTIME){ stopAudioPreview(); id = (plid === undefined) ? getId() : plid; lastMod = getModified(); - type = $('#obj_type').val(); - url = baseUrl+'Playlist/delete'; + type = $pl.find('#obj_type').val(); + url = baseUrl+'new-playlist/delete'; $.post(url, {format: "json", ids: id, modified: lastMod, type: type}, - function(json){ - openPlaylist(json); + function(json) { + closeTab(); + // openPlaylist(json); redrawLib(); }); }; @@ -1079,8 +1110,8 @@ var AIRTIME = (function(AIRTIME){ stopAudioPreview(); id = (wsid === undefined) ? getId() : wsid; lastMod = getModified(); - type = $('#obj_type').val(); - url = baseUrl+'Webstream/delete'; + type = $pl.find('#obj_type').val(); + url = baseUrl+'new-webstream/delete'; $.post(url, {format: "json", ids: id, modified: lastMod, type: type}, @@ -1110,18 +1141,13 @@ var AIRTIME = (function(AIRTIME){ }; mod.enableUI = function() { - $lib.unblock(); $pl.unblock(); - //Block UI changes the postion to relative to display the messages. - $lib.css("position", "static"); - $pl.css("position", "static"); setupUI(); }; function playlistResponse(json){ - if (json.error !== undefined) { playlistError(json); } @@ -1135,7 +1161,7 @@ var AIRTIME = (function(AIRTIME){ function playlistRequest(sUrl, oData) { var lastMod, - obj_type = $('#obj_type').val(); + obj_type = $pl.find('#obj_type').val(); mod.disableUI(); @@ -1153,20 +1179,20 @@ var AIRTIME = (function(AIRTIME){ } mod.fnAddItems = function(aItems, iAfter, sAddType) { - var sUrl = baseUrl+"playlist/add-items"; + var sUrl = baseUrl+"new-playlist/add-items"; oData = {"aItems": aItems, "afterItem": iAfter, "type": sAddType}; playlistRequest(sUrl, oData); }; mod.fnMoveItems = function(aIds, iAfter) { - var sUrl = baseUrl+"playlist/move-items", + var sUrl = baseUrl+"new-playlist/move-items", oData = {"ids": aIds, "afterItem": iAfter}; playlistRequest(sUrl, oData); }; mod.fnDeleteItems = function(aItems) { - var sUrl = baseUrl+"playlist/delete-items", + var sUrl = baseUrl+"new-playlist/delete-items", oData = {"ids": aItems}; playlistRequest(sUrl, oData); @@ -1399,10 +1425,12 @@ var AIRTIME = (function(AIRTIME){ }); }; + mod.setAsActive = function() { + $pl = $(".active-tab"); + }; + mod.init = function() { - $('#new-playlist').live('click', function(){AIRTIME.playlist.fnNew();}); - $('#new-smart-block').live('click', function(){AIRTIME.playlist.fnNewBlock();}); - $('#new-webstream').live('click', function(){AIRTIME.playlist.fnWsNew();}); + AIRTIME.playlist.setAsActive(); $pl.delegate("#spl_delete", {"click": function(ev){ AIRTIME.playlist.fnDelete(); @@ -1427,15 +1455,6 @@ var AIRTIME = (function(AIRTIME){ initialEvents(); setUpPlaylist(); - }; - - mod.onReady = function() { - $lib = $("#library_content"); - $pl = $("#side_playlist"); - - $pl.hide(); - - AIRTIME.playlist.init(); $pl.find(".ui-icon-alert").qtip({ content: { @@ -1443,8 +1462,8 @@ var AIRTIME = (function(AIRTIME){ }, position: { adjust: { - resize: true, - method: "flip flip" + resize: true, + method: "flip flip" }, at: "right center", my: "left top", @@ -1458,6 +1477,16 @@ var AIRTIME = (function(AIRTIME){ }); }; + mod.onReady = function() { + $lib = $("#library_content"); + + $('#new-playlist').live('click', function(){AIRTIME.playlist.fnNew();}); + $('#new-smart-block').live('click', function(){AIRTIME.playlist.fnNewBlock();}); + $('#new-webstream').live('click', function(){AIRTIME.playlist.fnWsNew();}); + + AIRTIME.playlist.init(); + }; + mod.onResize = function() { }; diff --git a/airtime_mvc/public/js/airtime/library/events/_library_showbuilder.js b/airtime_mvc/public/js/airtime/library/events/_library_showbuilder.js index 49bf64f27..2cd1b10a3 100644 --- a/airtime_mvc/public/js/airtime/library/events/_library_showbuilder.js +++ b/airtime_mvc/public/js/airtime/library/events/_library_showbuilder.js @@ -28,7 +28,7 @@ var AIRTIME = (function(AIRTIME) { AIRTIME.button.disableButton("btn-group #library-plus", false); } - if ($("#show_builder").is(":visible")) { + if ($("#show_builder_table").is(":visible")) { if ($cursor.length !== 0) { btnText = $.i18n._('Add after selected items'); } else if (current.length !== 0) { @@ -70,7 +70,7 @@ var AIRTIME = (function(AIRTIME) { mod.redrawChosen(); mod.checkToolBarIcons(); - if ($("#show_builder").is(":visible")) { + if ($("#show_builder_table").is(":visible")) { $('#library_display tr.lib-audio, tr.lib-pl, tr.lib-stream') .draggable( { @@ -154,7 +154,7 @@ var AIRTIME = (function(AIRTIME) { mod.dblClickAdd = function(data, type) { var i, length, temp, aMediaIds = [], aSchedIds = [], aData = []; - if ($("#show_builder").is(":visible")) { + if ($("#show_builder_table").is(":visible")) { // process selected files/playlists. aMediaIds.push({ "id": data.id, @@ -309,10 +309,10 @@ var AIRTIME = (function(AIRTIME) { buildEditMetadataDialog(json); }); } else if (data.ftype === "playlist" || data.ftype === "block") { - AIRTIME.playlist.fnEdit(data.id, data.ftype, baseUrl+'Playlist/edit'); + AIRTIME.playlist.fnEdit(data.id, data.ftype, baseUrl+'new-playlist/edit'); AIRTIME.playlist.validatePlaylistElements(); } else if (data.ftype === "stream") { - AIRTIME.playlist.fnEdit(data.id, data.ftype, baseUrl + 'Webstream/edit'); + AIRTIME.playlist.fnEdit(data.id, data.ftype, baseUrl + 'new-webstream/edit'); } }); diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js index 23fbc7bd4..735987c49 100644 --- a/airtime_mvc/public/js/airtime/library/library.js +++ b/airtime_mvc/public/js/airtime/library/library.js @@ -540,7 +540,7 @@ var AIRTIME = (function(AIRTIME) { dataType: "json" }); */ - + colReorderMap = oData.ColReorder; }, "fnStateLoad": function fnLibStateLoad(oSettings) { diff --git a/airtime_mvc/public/js/airtime/showbuilder/_builder.js b/airtime_mvc/public/js/airtime/showbuilder/_builder.js index 8a53fb9d5..78e2a8d44 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/_builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/_builder.js @@ -106,6 +106,19 @@ var AIRTIME = (function(AIRTIME){ } }; + mod.switchTab = function(tab, el) { + $(".active-tab").hide().removeClass("active-tab"); + tab.addClass("active-tab").show(); + + $(".nav.nav-tabs .active").removeClass("active"); + el.addClass("active"); + + if (tab.hasClass("pl-content")) { + AIRTIME.playlist.setAsActive(); + } + }; + + mod.checkSelectButton = function() { var $selectable = $sbTable.find("tr"); @@ -260,10 +273,6 @@ var AIRTIME = (function(AIRTIME){ mod.enableUI = function() { $lib.unblock(); $sbContent.unblock(); - - //Block UI changes the postion to relative to display the messages. - $lib.css("position", "static"); - $sbContent.css("position", "static"); }; mod.fnItemCallback = function(json) { @@ -726,7 +735,7 @@ var AIRTIME = (function(AIRTIME){ }, // R = ColReorder, C = ColVis - "sDom": 'R<"dt-process-rel"r><"sb-padded"<"H"C>><"dataTables_scrolling sb-padded"t>', + "sDom": 'R<"dt-process-rel"r><"sb-padded"<"H"C>><"dataTables_scrolling sb-padded"t><"F">', "oColVis": { "aiExclude": [ 0, 1 ], @@ -950,7 +959,10 @@ var AIRTIME = (function(AIRTIME){ $sbTable.sortable(sortableConf); //start setup of the builder toolbar. - $toolbar = $(".sb-content .fg-toolbar"); + $toolbar = $(".sb-content .fg-toolbar:first"); + var footer = $(".sb-content .fg-toolbar:last"), + timerange = $(".sb-timerange"); + footer.append(timerange); $menu = $("<div class='btn-toolbar'/>"); $menu.append("<div class='btn-group'>" + diff --git a/airtime_mvc/public/js/airtime/showbuilder/_main_builder.js b/airtime_mvc/public/js/airtime/showbuilder/_main_builder.js index 93ebbc4a0..19c022966 100644 --- a/airtime_mvc/public/js/airtime/showbuilder/_main_builder.js +++ b/airtime_mvc/public/js/airtime/showbuilder/_main_builder.js @@ -160,6 +160,10 @@ AIRTIME = (function(AIRTIME) { $builder = $("#show_builder"); $fs = $builder.find('fieldset'); + $("#timeline-tab").on("click", function() { + AIRTIME.showbuilder.switchTab($("#show_builder .outer-datatable-wrapper"), $(this)); + }); + /* * Icon hover states for search. */