diff --git a/airtime_mvc/application/controllers/LibraryController.php b/airtime_mvc/application/controllers/LibraryController.php index a1d0d245e..72111cbc1 100644 --- a/airtime_mvc/application/controllers/LibraryController.php +++ b/airtime_mvc/application/controllers/LibraryController.php @@ -181,7 +181,8 @@ class LibraryController extends Zend_Controller_Action } } } - if ($isAdminOrPM) { + + if ($isAdminOrPM || $file->getFileOwnerId() == $user->getId()) { $menu["del"] = array("name"=> "Delete", "icon" => "delete", "url" => "/library/delete"); $menu["edit"] = array("name"=> "Edit Metadata", "icon" => "edit", "url" => "/library/edit-file-md/id/{$id}"); } @@ -364,15 +365,17 @@ class LibraryController extends Zend_Controller_Action { $user = Application_Model_User::getCurrentUser(); $isAdminOrPM = $user->isUserType(array(UTYPE_ADMIN, UTYPE_PROGRAM_MANAGER)); - if (!$isAdminOrPM) { - return; - } $request = $this->getRequest(); - $form = new Application_Form_EditAudioMD(); $file_id = $this->_getParam('id', null); $file = Application_Model_StoredFile::Recall($file_id); + + if (!$isAdminOrPM && $file->getFileOwnerId() != $user->getId()) { + return; + } + + $form = new Application_Form_EditAudioMD(); $form->populate($file->getDbColMetadata()); if ($request->isPost()) { diff --git a/airtime_mvc/application/controllers/PlaylistController.php b/airtime_mvc/application/controllers/PlaylistController.php index 2cca81ac2..38dbd4fd2 100644 --- a/airtime_mvc/application/controllers/PlaylistController.php +++ b/airtime_mvc/application/controllers/PlaylistController.php @@ -513,6 +513,7 @@ class PlaylistController extends Zend_Controller_Action } catch (BlockNotFoundException $e) { $this->playlistNotFound('block', true); } catch (Exception $e) { + //Logging::info($e); $this->playlistUnknownError($e); } } diff --git a/airtime_mvc/application/forms/SmartBlockCriteria.php b/airtime_mvc/application/forms/SmartBlockCriteria.php index 55a28c79a..e48fc7590 100644 --- a/airtime_mvc/application/forms/SmartBlockCriteria.php +++ b/airtime_mvc/application/forms/SmartBlockCriteria.php @@ -212,6 +212,14 @@ class Application_Form_SmartBlockCriteria extends Zend_Form_SubForm }//for + $repeatTracks = new Zend_Form_Element_Checkbox('sp_repeat_tracks'); + $repeatTracks->setDecorators(array('viewHelper')) + ->setLabel('Allow Repeat Tracks:'); + if (isset($storedCrit["repeat_tracks"])) { + $repeatTracks->setChecked($storedCrit["repeat_tracks"]["value"] == 1?true:false); + } + $this->addElement($repeatTracks); + $limit = new Zend_Form_Element_Select('sp_limit_options'); $limit->setAttrib('class', 'sp_input_select') ->setDecorators(array('viewHelper')) @@ -220,7 +228,7 @@ class Application_Form_SmartBlockCriteria extends Zend_Form_SubForm $limit->setValue($storedCrit["limit"]["modifier"]); } $this->addElement($limit); - + $limitValue = new Zend_Form_Element_Text('sp_limit_value'); $limitValue->setAttrib('class', 'sp_input_text_limit') ->setLabel('Limit to') diff --git a/airtime_mvc/application/models/Block.php b/airtime_mvc/application/models/Block.php index 80fae297d..57018ad5f 100644 --- a/airtime_mvc/application/models/Block.php +++ b/airtime_mvc/application/models/Block.php @@ -1093,6 +1093,14 @@ SQL; ->setDbValue($p_criteriaData['etc']['sp_limit_value']) ->setDbBlockId($this->id) ->save(); + + // insert repeate track option + $qry = new CcBlockcriteria(); + $qry->setDbCriteria("repeat_tracks") + ->setDbModifier("N/A") + ->setDbValue($p_criteriaData['etc']['sp_repeat_tracks']) + ->setDbBlockId($this->id) + ->save(); } /** @@ -1105,7 +1113,12 @@ SQL; $this->saveSmartBlockCriteria($p_criteria); $insertList = $this->getListOfFilesUnderLimit(); $this->deleteAllFilesFromBlock(); - $this->addAudioClips(array_keys($insertList)); + // constrcut id array + $ids = array(); + foreach ($insertList as $ele) { + $ids[] = $ele['id']; + } + $this->addAudioClips(array_values($ids)); // update length in playlist contents. $this->updateBlockLengthInAllPlaylist(); @@ -1134,6 +1147,7 @@ SQL; $info = $this->getListofFilesMeetCriteria(); $files = $info['files']; $limit = $info['limit']; + $repeat = $info['repeat_tracks']; $insertList = array(); $totalTime = 0; @@ -1142,19 +1156,37 @@ SQL; // this moves the pointer to the first element in the collection $files->getFirst(); $iterator = $files->getIterator(); - while ($iterator->valid() && $totalTime < $limit['time']) { + + $isBlockFull = false; + + while ($iterator->valid()) { $id = $iterator->current()->getDbId(); $length = Application_Common_DateHelper::calculateLengthInSeconds($iterator->current()->getDbLength()); - $insertList[$id] = $length; + $insertList[] = array('id'=>$id, 'length'=>$length); $totalTime += $length; $totalItems++; - - if ((!is_null($limit['items']) && $limit['items'] == count($insertList)) || $totalItems > 500) { + + if ((!is_null($limit['items']) && $limit['items'] == count($insertList)) || $totalItems > 500 || $totalTime > $limit['time']) { + $isBlockFull = true; break; } $iterator->next(); } + + $sizeOfInsert = count($insertList); + + // if block is not full and reapeat_track is check, fill up more + while (!$isBlockFull && $repeat == 1) { + $randomEleKey = array_rand(array_slice($insertList, 0, $sizeOfInsert)); + $insertList[] = $insertList[$randomEleKey]; + $totalTime += $insertList[$randomEleKey]['length']; + $totalItems++; + + if ((!is_null($limit['items']) && $limit['items'] == count($insertList)) || $totalItems > 500 || $totalTime > $limit['time']) { + break; + } + } return $insertList; } @@ -1202,6 +1234,8 @@ SQL; if ($criteria == "limit") { $storedCrit["limit"] = array("value"=>$value, "modifier"=>$modifier); + } else if($criteria == "repeat_tracks") { + $storedCrit["repeat_tracks"] = array("value"=>$value); } else { $storedCrit["crit"][$criteria][] = array("criteria"=>$criteria, "value"=>$value, "modifier"=>$modifier, "extra"=>$extra, "display_name"=>$criteriaOptions[$criteria]); } @@ -1317,6 +1351,7 @@ SQL; } // construct limit restriction $limits = array(); + if (isset($storedCrit['limit'])) { if ($storedCrit['limit']['modifier'] == "items") { $limits['time'] = 1440 * 60; @@ -1328,10 +1363,16 @@ SQL; $limits['items'] = null; } } + + $repeatTracks = 0; + if (isset($storedCrit['repeat_tracks'])) { + $repeatTracks = $storedCrit['repeat_tracks']['value']; + } + try { $out = $qry->setFormatter(ModelCriteria::FORMAT_ON_DEMAND)->find(); - return array("files"=>$out, "limit"=>$limits, "count"=>$out->count()); + return array("files"=>$out, "limit"=>$limits, "repeat_tracks"=> $repeatTracks, "count"=>$out->count()); } catch (Exception $e) { Logging::info($e); } @@ -1377,7 +1418,7 @@ SQL; $output['etc'][$ele['name']] = $ele['value']; } } - + return $output; } // smart block functions end diff --git a/airtime_mvc/application/models/Datatables.php b/airtime_mvc/application/models/Datatables.php index 65e7b1256..7545aec71 100644 --- a/airtime_mvc/application/models/Datatables.php +++ b/airtime_mvc/application/models/Datatables.php @@ -13,9 +13,9 @@ class Application_Model_Datatables if ($dbname == 'utime' || $dbname == 'mtime') { $input1 = isset($info[0])?Application_Common_DateHelper::ConvertToUtcDateTimeString($info[0]):null; $input2 = isset($info[1])?Application_Common_DateHelper::ConvertToUtcDateTimeString($info[1]):null; - } else if($dbname == 'bit_rate') { - $input1 = isset($info[0])?intval($info[0]) * 1000:null; - $input2 = isset($info[1])?intval($info[1]) * 1000:null; + } else if($dbname == 'bit_rate' || $dbname == 'sample_rate') { + $input1 = isset($info[0])?doubleval($info[0]) * 1000:null; + $input2 = isset($info[1])?doubleval($info[1]) * 1000:null; } else { $input1 = isset($info[0])?$info[0]:null; $input2 = isset($info[1])?$info[1]:null; diff --git a/airtime_mvc/application/models/Show.php b/airtime_mvc/application/models/Show.php index 41ffbeefd..6f088046d 100644 --- a/airtime_mvc/application/models/Show.php +++ b/airtime_mvc/application/models/Show.php @@ -270,6 +270,13 @@ SQL; try { //update the status flag in cc_schedule. + + /* Since we didn't use a propel object when updating + * cc_show_instances table we need to clear the instances + * so the correct information is retrieved from the db + */ + CcShowInstancesPeer::clearInstancePool(); + $instances = CcShowInstancesQuery::create() ->filterByDbEnds($current_timestamp, Criteria::GREATER_THAN) ->filterByDbShowId($this->_showId) @@ -1253,6 +1260,7 @@ SQL; if ($data['add_show_id'] != -1) { $con = Propel::getConnection(CcSchedulePeer::DATABASE_NAME); $con->beginTransaction(); + //current timesamp in UTC. $current_timestamp = gmdate("Y-m-d H:i:s"); diff --git a/airtime_mvc/application/models/StoredFile.php b/airtime_mvc/application/models/StoredFile.php index 2300f4eb7..41178f2e3 100644 --- a/airtime_mvc/application/models/StoredFile.php +++ b/airtime_mvc/application/models/StoredFile.php @@ -1161,6 +1161,10 @@ SQL; return $this->_file->getDbFileExists(); } + public function getFileOwnerId() + { + return $this->_file->getDbOwnerId(); + } // note: never call this method from controllers because it does a sleep public function uploadToSoundCloud() diff --git a/airtime_mvc/application/views/scripts/form/smart-block-criteria.phtml b/airtime_mvc/application/views/scripts/form/smart-block-criteria.phtml index 0f27248ca..c75791fe1 100644 --- a/airtime_mvc/application/views/scripts/form/smart-block-criteria.phtml +++ b/airtime_mvc/application/views/scripts/form/smart-block-criteria.phtml @@ -59,6 +59,20 @@
+
+ element->getElement('sp_repeat_tracks')->getLabel() ?> + + element->getElement('sp_repeat_tracks')?> + element->getElement("sp_repeat_tracks")->hasErrors()) : ?> + element->getElement("sp_repeat_tracks")->getMessages() as $error): ?> + + + + + +
+
+
element->getElement('sp_limit_value')->getLabel() ?> element->getElement('sp_limit_value')?> diff --git a/airtime_mvc/application/views/scripts/library/edit-file-md.phtml b/airtime_mvc/application/views/scripts/library/edit-file-md.phtml index 6b7696c0a..bdead9832 100644 --- a/airtime_mvc/application/views/scripts/library/edit-file-md.phtml +++ b/airtime_mvc/application/views/scripts/library/edit-file-md.phtml @@ -1,6 +1,6 @@

Edit Metadata

- form->setAction($this->url()); + form->setAction($this->url()); echo $this->form; ?>
diff --git a/airtime_mvc/public/css/styles.css b/airtime_mvc/public/css/styles.css index b14b77251..c47192450 100644 --- a/airtime_mvc/public/css/styles.css +++ b/airtime_mvc/public/css/styles.css @@ -105,7 +105,7 @@ select { } .airtime_auth_help_icon, .custom_auth_help_icon, .stream_username_help_icon, -.playlist_type_help_icon, .master_username_help_icon { +.playlist_type_help_icon, .master_username_help_icon, .repeat_tracks_help_icon{ cursor: help; position: relative; display:inline-block; zoom:1; diff --git a/airtime_mvc/public/js/airtime/library/library.js b/airtime_mvc/public/js/airtime/library/library.js index c50b2a375..504fa8b59 100644 --- a/airtime_mvc/public/js/airtime/library/library.js +++ b/airtime_mvc/public/js/airtime/library/library.js @@ -70,7 +70,7 @@ var AIRTIME = (function(AIRTIME) { }; mod.getChosenAudioFilesLength = function(){ - //var files = Object.keys(chosenItems), + // var files = Object.keys(chosenItems), var files, $trs, cItem, @@ -215,7 +215,7 @@ var AIRTIME = (function(AIRTIME) { mod.removeFromChosen = function($el) { var id = $el.attr("id"); - //used to not keep dragged items selected. + // used to not keep dragged items selected. if (!$el.hasClass(LIB_SELECTED_CLASS)) { delete chosenItems[id]; } @@ -252,11 +252,11 @@ var AIRTIME = (function(AIRTIME) { }; /* - * selects all items which the user can currently see. - * (behaviour taken from gmail) + * selects all items which the user can currently see. (behaviour taken from + * gmail) * - * by default the items are selected in reverse order - * so we need to reverse it back + * by default the items are selected in reverse order so we need to reverse + * it back */ mod.selectCurrentPage = function() { $.fn.reverse = [].reverse; @@ -276,8 +276,8 @@ var AIRTIME = (function(AIRTIME) { }; /* - * deselects all items that the user can currently see. - * (behaviour taken from gmail) + * deselects all items that the user can currently see. (behaviour taken + * from gmail) */ mod.deselectCurrentPage = function() { var $inputs = $libTable.find("tbody input:checkbox"), @@ -328,7 +328,7 @@ var AIRTIME = (function(AIRTIME) { temp, aMedia = []; - //process selected files/playlists. + // process selected files/playlists. for (item in aData) { temp = aData[item]; if (temp !== null && temp.hasOwnProperty('id') ) { @@ -433,36 +433,37 @@ var AIRTIME = (function(AIRTIME) { oTable = $libTable.dataTable( { - //put hidden columns at the top to insure they can never be visible on the table through column reordering. + // put hidden columns at the top to insure they can never be visible + // on the table through column reordering. "aoColumns": [ - /* ftype */ { "sTitle" : "" , "mDataProp" : "ftype" , "bSearchable" : false , "bVisible" : false } , - /* Checkbox */ { "sTitle" : "" , "mDataProp" : "checkbox" , "bSortable" : false , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_checkbox" } , - /* Type */ { "sTitle" : "" , "mDataProp" : "image" , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_type" , "iDataSort" : 0 } , - /* Title */ { "sTitle" : "Title" , "mDataProp" : "track_title" , "sClass" : "library_title" , "sWidth" : "170px" } , - /* Creator */ { "sTitle" : "Creator" , "mDataProp" : "artist_name" , "sClass" : "library_creator" , "sWidth" : "160px" } , - /* Album */ { "sTitle" : "Album" , "mDataProp" : "album_title" , "sClass" : "library_album" , "sWidth" : "150px" } , - /* Bit Rate */ { "sTitle" : "Bit Rate" , "mDataProp" : "bit_rate" , "bVisible" : false , "sClass" : "library_bitrate" , "sWidth" : "80px" }, - /* BPM */ { "sTitle" : "BPM" , "mDataProp" : "bpm" , "bVisible" : false , "sClass" : "library_bpm" , "sWidth" : "50px" }, - /* Composer */ { "sTitle" : "Composer" , "mDataProp" : "composer" , "bVisible" : false , "sClass" : "library_composer" , "sWidth" : "150px" }, - /* Conductor */ { "sTitle" : "Conductor" , "mDataProp" : "conductor" , "bVisible" : false , "sClass" : "library_conductor" , "sWidth" : "125px" }, - /* Copyright */ { "sTitle" : "Copyright" , "mDataProp" : "copyright" , "bVisible" : false , "sClass" : "library_copyright" , "sWidth" : "125px" }, - /* Encoded */ { "sTitle" : "Encoded By" , "mDataProp" : "encoded_by" , "bVisible" : false , "sClass" : "library_encoded" , "sWidth" : "150px" }, - /* Genre */ { "sTitle" : "Genre" , "mDataProp" : "genre" , "bVisible" : false , "sClass" : "library_genre" , "sWidth" : "100px" }, - /* ISRC Number */ { "sTitle" : "ISRC" , "mDataProp" : "isrc_number" , "bVisible" : false , "sClass" : "library_isrc" , "sWidth" : "150px" }, - /* Label */ { "sTitle" : "Label" , "mDataProp" : "label" , "bVisible" : false , "sClass" : "library_label" , "sWidth" : "125px" }, - /* Language */ { "sTitle" : "Language" , "mDataProp" : "language" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" }, + /* ftype */ { "sTitle" : "" , "mDataProp" : "ftype" , "bSearchable" : false , "bVisible" : false } , + /* Checkbox */ { "sTitle" : "" , "mDataProp" : "checkbox" , "bSortable" : false , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_checkbox" } , + /* Type */ { "sTitle" : "" , "mDataProp" : "image" , "bSearchable" : false , "sWidth" : "25px" , "sClass" : "library_type" , "iDataSort" : 0 } , + /* Title */ { "sTitle" : "Title" , "mDataProp" : "track_title" , "sClass" : "library_title" , "sWidth" : "170px" } , + /* Creator */ { "sTitle" : "Creator" , "mDataProp" : "artist_name" , "sClass" : "library_creator" , "sWidth" : "160px" } , + /* Album */ { "sTitle" : "Album" , "mDataProp" : "album_title" , "sClass" : "library_album" , "sWidth" : "150px" } , + /* Bit Rate */ { "sTitle" : "Bit Rate" , "mDataProp" : "bit_rate" , "bVisible" : false , "sClass" : "library_bitrate" , "sWidth" : "80px" }, + /* BPM */ { "sTitle" : "BPM" , "mDataProp" : "bpm" , "bVisible" : false , "sClass" : "library_bpm" , "sWidth" : "50px" }, + /* Composer */ { "sTitle" : "Composer" , "mDataProp" : "composer" , "bVisible" : false , "sClass" : "library_composer" , "sWidth" : "150px" }, + /* Conductor */ { "sTitle" : "Conductor" , "mDataProp" : "conductor" , "bVisible" : false , "sClass" : "library_conductor" , "sWidth" : "125px" }, + /* Copyright */ { "sTitle" : "Copyright" , "mDataProp" : "copyright" , "bVisible" : false , "sClass" : "library_copyright" , "sWidth" : "125px" }, + /* Encoded */ { "sTitle" : "Encoded By" , "mDataProp" : "encoded_by" , "bVisible" : false , "sClass" : "library_encoded" , "sWidth" : "150px" }, + /* Genre */ { "sTitle" : "Genre" , "mDataProp" : "genre" , "bVisible" : false , "sClass" : "library_genre" , "sWidth" : "100px" }, + /* ISRC Number */ { "sTitle" : "ISRC" , "mDataProp" : "isrc_number" , "bVisible" : false , "sClass" : "library_isrc" , "sWidth" : "150px" }, + /* Label */ { "sTitle" : "Label" , "mDataProp" : "label" , "bVisible" : false , "sClass" : "library_label" , "sWidth" : "125px" }, + /* Language */ { "sTitle" : "Language" , "mDataProp" : "language" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" }, /* Last Modified */ { "sTitle" : "Last Modified" , "mDataProp" : "mtime" , "bVisible" : false , "sClass" : "library_modified_time" , "sWidth" : "125px" }, - /* Last Played */ { "sTitle" : "Last Played " , "mDataProp" : "lptime" , "bVisible" : false , "sClass" : "library_modified_time" , "sWidth" : "125px" }, - /* Length */ { "sTitle" : "Length" , "mDataProp" : "length" , "sClass" : "library_length" , "sWidth" : "80px" } , - /* Mime */ { "sTitle" : "Mime" , "mDataProp" : "mime" , "bVisible" : false , "sClass" : "library_mime" , "sWidth" : "80px" }, - /* Mood */ { "sTitle" : "Mood" , "mDataProp" : "mood" , "bVisible" : false , "sClass" : "library_mood" , "sWidth" : "70px" }, - /* Owner */ { "sTitle" : "Owner" , "mDataProp" : "owner_id" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" }, - /* Replay Gain */ { "sTitle" : "Replay Gain" , "mDataProp" : "replay_gain" , "bVisible" : false , "sClass" : "library_replay_gain" , "sWidth" : "80px" }, - /* Sample Rate */ { "sTitle" : "Sample Rate" , "mDataProp" : "sample_rate" , "bVisible" : false , "sClass" : "library_sr" , "sWidth" : "80px" }, - /* Track Number */ { "sTitle" : "Track Number" , "mDataProp" : "track_number" , "bVisible" : false , "sClass" : "library_track" , "sWidth" : "65px" }, - /* Upload Time */ { "sTitle" : "Uploaded" , "mDataProp" : "utime" , "sClass" : "library_upload_time" , "sWidth" : "125px" } , - /* Website */ { "sTitle" : "Website" , "mDataProp" : "info_url" , "bVisible" : false , "sClass" : "library_url" , "sWidth" : "150px" }, - /* Year */ { "sTitle" : "Year" , "mDataProp" : "year" , "bVisible" : false , "sClass" : "library_year" , "sWidth" : "60px" } + /* Last Played */ { "sTitle" : "Last Played " , "mDataProp" : "lptime" , "bVisible" : false , "sClass" : "library_modified_time" , "sWidth" : "125px" }, + /* Length */ { "sTitle" : "Length" , "mDataProp" : "length" , "sClass" : "library_length" , "sWidth" : "80px" } , + /* Mime */ { "sTitle" : "Mime" , "mDataProp" : "mime" , "bVisible" : false , "sClass" : "library_mime" , "sWidth" : "80px" }, + /* Mood */ { "sTitle" : "Mood" , "mDataProp" : "mood" , "bVisible" : false , "sClass" : "library_mood" , "sWidth" : "70px" }, + /* Owner */ { "sTitle" : "Owner" , "mDataProp" : "owner_id" , "bVisible" : false , "sClass" : "library_language" , "sWidth" : "125px" }, + /* Replay Gain */ { "sTitle" : "Replay Gain" , "mDataProp" : "replay_gain" , "bVisible" : false , "sClass" : "library_replay_gain" , "sWidth" : "80px" }, + /* Sample Rate */ { "sTitle" : "Sample Rate" , "mDataProp" : "sample_rate" , "bVisible" : false , "sClass" : "library_sr" , "sWidth" : "80px" }, + /* Track Number */ { "sTitle" : "Track Number" , "mDataProp" : "track_number" , "bVisible" : false , "sClass" : "library_track" , "sWidth" : "65px" }, + /* Upload Time */ { "sTitle" : "Uploaded" , "mDataProp" : "utime" , "sClass" : "library_upload_time" , "sWidth" : "125px" } , + /* Website */ { "sTitle" : "Website" , "mDataProp" : "info_url" , "bVisible" : false , "sClass" : "library_url" , "sWidth" : "150px" }, + /* Year */ { "sTitle" : "Year" , "mDataProp" : "year" , "bVisible" : false , "sClass" : "library_year" , "sWidth" : "60px" } ], "bProcessing": true, @@ -472,7 +473,7 @@ var AIRTIME = (function(AIRTIME) { "bStateSave": true, "fnStateSaveParams": function (oSettings, oData) { - //remove oData components we don't want to save. + // remove oData components we don't want to save. delete oData.oSearch; delete oData.aoSearchCols; }, @@ -499,8 +500,8 @@ var AIRTIME = (function(AIRTIME) { length, a = oData.abVisCols; - //putting serialized data back into the correct js type to make - //sure everything works properly. + // putting serialized data back into the correct js type to make + // sure everything works properly. for (i = 0, length = a.length; i < length; i++) { if (typeof(a[i]) === "string") { a[i] = (a[i] === "true") ? true : false; @@ -524,11 +525,12 @@ var AIRTIME = (function(AIRTIME) { "sAjaxDataProp": "files", "fnServerData": function ( sSource, aoData, fnCallback ) { - /* The real validation check is done in dataTables.columnFilter.js - * We also need to check it here because datatable is redrawn everytime - * an action is performed in the Library page. - * In order for datatable to redraw the advanced search fields - * MUST all be valid. + /* + * The real validation check is done in + * dataTables.columnFilter.js We also need to check it here + * because datatable is redrawn everytime an action is performed + * in the Library page. In order for datatable to redraw the + * advanced search fields MUST all be valid. */ var advSearchFields = $("div#advanced_search").children(':visible'); var advSearchValid = validateAdvancedSearch(advSearchFields); @@ -536,7 +538,7 @@ var AIRTIME = (function(AIRTIME) { aoData.push( { name: "format", value: "json"} ); aoData.push( { name: "advSearch", value: advSearchValid} ); - //push whether to search files/playlists or all. + // push whether to search files/playlists or all. type = $("#library_display_type").find("select").val(); type = (type === undefined) ? 0 : type; aoData.push( { name: "type", value: type} ); @@ -552,30 +554,37 @@ var AIRTIME = (function(AIRTIME) { "fnRowCallback": AIRTIME.library.fnRowCallback, "fnCreatedRow": function( nRow, aData, iDataIndex ) { - //add the play function to the library_type td + // add the play function to the library_type td $(nRow).find('td.library_type').click(function(){ if (aData.ftype === 'playlist' && aData.length !== '0.0'){ - playlistIndex = $(this).parent().attr('id').substring(3); //remove the pl_ + playlistIndex = $(this).parent().attr('id').substring(3); // remove + // the + // pl_ open_playlist_preview(playlistIndex, 0); } else if (aData.ftype === 'audioclip') { open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name); } else if (aData.ftype == 'stream') { open_audio_preview(aData.ftype, aData.audioFile, aData.track_title, aData.artist_name); } else if (aData.ftype == 'block' && aData.bl_type == 'static') { - blockIndex = $(this).parent().attr('id').substring(3); //remove the bl_ + blockIndex = $(this).parent().attr('id').substring(3); // remove + // the + // bl_ open_block_preview(blockIndex, 0); } return false; }); alreadyclicked=false; - //call the context menu so we can prevent the event from propagating. + // call the context menu so we can prevent the event from + // propagating. $(nRow).find('td:not(.library_checkbox, .library_type)').click(function(e){ var el=$(this); if (alreadyclicked) { alreadyclicked=false; // reset - clearTimeout(alreadyclickedTimeout); // prevent this from happening + clearTimeout(alreadyclickedTimeout); // prevent this + // from + // happening // do what needs to happen on double click. $tr = $(el).parent(); @@ -587,8 +596,8 @@ var AIRTIME = (function(AIRTIME) { alreadyclicked=true; alreadyclickedTimeout=setTimeout(function(){ alreadyclicked=false; // reset when it happens - // do what needs to happen on single click. - // use el instead of $(this) because $(this) is + // do what needs to happen on single click. + // use el instead of $(this) because $(this) is // no longer the element el.contextMenu({x: e.pageX, y: e.pageY}); },300); // <-- dblclick tolerance here @@ -596,7 +605,8 @@ var AIRTIME = (function(AIRTIME) { return false; }); - //add a tool tip to appear when the user clicks on the type icon. + // add a tool tip to appear when the user clicks on the type + // icon. $(nRow).find("td:not(.library_checkbox, .library_type)").qtip({ content: { text: "Loading...", @@ -620,7 +630,8 @@ var AIRTIME = (function(AIRTIME) { }, my: 'left center', at: 'right center', - viewport: $(window), // Keep the tooltip on-screen at all times + viewport: $(window), // Keep the tooltip on-screen at + // all times effect: false // Disable positioning animation }, style: { @@ -638,10 +649,11 @@ var AIRTIME = (function(AIRTIME) { hide: {event:'mouseout', delay: 50, fixed:true} }); }, - //remove any selected nodes before the draw. + // remove any selected nodes before the draw. "fnPreDrawCallback": function( oSettings ) { - //make sure any dragging helpers are removed or else they'll be stranded on the screen. + // make sure any dragging helpers are removed or else they'll be + // stranded on the screen. $("#draggingContainer").remove(); }, "fnDrawCallback": AIRTIME.library.fnDrawCallback, @@ -673,18 +685,33 @@ var AIRTIME = (function(AIRTIME) { setColumnFilter(oTable); oTable.fnSetFilteringDelay(350); - + + var simpleSearchText; + $libContent.on("click", "legend", function(){ $simpleSearch = $libContent.find("#library_display_filter label"); var $fs = $(this).parents("fieldset"); if ($fs.hasClass("closed")) { $fs.removeClass("closed"); + + //keep value of simple search for when user switches back to it + simpleSearchText = $simpleSearch.find('input').val(); + + // clear the simple search text field and reset datatable + $(".dataTables_filter input").val("").keyup(); + $simpleSearch.addClass("sp-invisible"); } else { - $fs.addClass("closed"); + //clear the advanced search fields and reset datatable + $(".filter_column input").val("").keyup(); + + //reset datatable with previous simple search results (if any) + $(".dataTables_filter input").val(simpleSearchText).keyup(); + $simpleSearch.removeClass("sp-invisible"); + $fs.addClass("closed"); } }); @@ -737,7 +764,7 @@ var AIRTIME = (function(AIRTIME) { addQtipToSCIcons(); - //begin context menu initialization. + // begin context menu initialization. $.contextMenu({ selector: '#library_display td:not(.library_checkbox)', trigger: "left", @@ -752,7 +779,7 @@ var AIRTIME = (function(AIRTIME) { function processMenuItems(oItems) { - //define an add to playlist callback. + // define an add to playlist callback. if (oItems.pl_add !== undefined) { var aItems = []; @@ -764,7 +791,7 @@ var AIRTIME = (function(AIRTIME) { oItems.pl_add.callback = callback; } - //define an edit callback. + // define an edit callback. if (oItems.edit !== undefined) { if (data.ftype === "audioclip") { @@ -788,7 +815,7 @@ var AIRTIME = (function(AIRTIME) { oItems.edit.callback = callback; } - //define a play callback. + // define a play callback. if (oItems.play !== undefined) { if (oItems.play.mime !== undefined) { @@ -799,23 +826,28 @@ var AIRTIME = (function(AIRTIME) { callback = function() { if (data.ftype === 'playlist' && data.length !== '0.0'){ - playlistIndex = $(this).parent().attr('id').substring(3); //remove the pl_ + playlistIndex = $(this).parent().attr('id').substring(3); // remove + // the + // pl_ open_playlist_preview(playlistIndex, 0); } else if (data.ftype === 'audioclip' || data.ftype === 'stream') { open_audio_preview(data.ftype, data.audioFile, data.track_title, data.artist_name); } else if (data.ftype === 'block') { - blockIndex = $(this).parent().attr('id').substring(3); //remove the pl_ + blockIndex = $(this).parent().attr('id').substring(3); // remove + // the + // pl_ open_block_preview(blockIndex, 0); } }; oItems.play.callback = callback; } - //define a delete callback. + // define a delete callback. if (oItems.del !== undefined) { - //delete through the playlist controller, will reset - //playlist screen if this is the currently edited playlist. + // delete through the playlist controller, will reset + // playlist screen if this is the currently edited + // playlist. if ((data.ftype === "playlist" || data.ftype === "block") && screen === "playlist") { callback = function() { aMedia = []; @@ -849,7 +881,7 @@ var AIRTIME = (function(AIRTIME) { oItems.del.callback = callback; } - //define a download callback. + // define a download callback. if (oItems.download !== undefined) { callback = function() { @@ -857,11 +889,11 @@ var AIRTIME = (function(AIRTIME) { }; oItems.download.callback = callback; } - //add callbacks for Soundcloud menu items. + // add callbacks for Soundcloud menu items. if (oItems.soundcloud !== undefined) { var soundcloud = oItems.soundcloud.items; - //define an upload to soundcloud callback. + // define an upload to soundcloud callback. if (soundcloud.upload !== undefined) { callback = function() { @@ -872,7 +904,7 @@ var AIRTIME = (function(AIRTIME) { soundcloud.upload.callback = callback; } - //define a view on soundcloud callback + // define a view on soundcloud callback if (soundcloud.view !== undefined) { callback = function() { @@ -988,7 +1020,8 @@ function addQtipToSCIcons(){ viewport: $(window) }, show: { - ready: true // Needed to make it show on first mouseover event + ready: true // Needed to make it show on first mouseover + // event } }); } @@ -1015,7 +1048,8 @@ function addQtipToSCIcons(){ viewport: $(window) }, show: { - ready: true // Needed to make it show on first mouseover event + ready: true // Needed to make it show on first mouseover + // event } }); }else if($(this).hasClass("sc-error")){ @@ -1042,7 +1076,8 @@ function addQtipToSCIcons(){ viewport: $(window) }, show: { - ready: true // Needed to make it show on first mouseover event + ready: true // Needed to make it show on first mouseover + // event } }); } @@ -1096,7 +1131,7 @@ function validateAdvancedSearch(divs) { } } - //string fields do not need validation + // string fields do not need validation if (searchTermType !== "s") { valid = regExpr.test(searchTerm[i]); if (!valid) allValid = false; @@ -1104,11 +1139,11 @@ function validateAdvancedSearch(divs) { addRemoveValidationIcons(valid, $(field), searchTermType); - /* Empty fields should not have valid/invalid indicator - * Range values are considered valid even if only the - * 'From' value is provided. Therefore, if the 'To' value - * is empty but the 'From' value is not empty we need to - * keep the validation icon on screen. + /* + * Empty fields should not have valid/invalid indicator Range values + * are considered valid even if only the 'From' value is provided. + * Therefore, if the 'To' value is empty but the 'From' value is not + * empty we need to keep the validation icon on screen. */ } else if (searchTerm[0] === "" && searchTerm[1] !== "" || searchTerm[0] === "" && searchTerm[1] === ""){ @@ -1144,7 +1179,7 @@ function addRemoveValidationIcons(valid, field, searchTermType) { if (valid) { if (!field.closest('div').children(':last-child').hasClass('checked-icon')) { - //remove invalid icon before adding valid icon + // remove invalid icon before adding valid icon if (field.closest('div').children(':last-child').hasClass('not-available-icon')) { field.closest('div').children(':last-child').remove(); } @@ -1152,7 +1187,7 @@ function addRemoveValidationIcons(valid, field, searchTermType) { } } else { if (!field.closest('div').children(':last-child').hasClass('not-available-icon')) { - //remove valid icon before adding invalid icon + // remove valid icon before adding invalid icon if (field.closest('div').children(':last-child').hasClass('checked-icon')) { field.closest('div').children(':last-child').remove(); } @@ -1161,12 +1196,9 @@ function addRemoveValidationIcons(valid, field, searchTermType) { } } -/* Validation types: - * s => string - * i => integer - * n => numeric (positive/negative, whole/decimals) - * t => timestamp - * l => length +/* + * Validation types: s => string i => integer n => numeric (positive/negative, + * whole/decimals) t => timestamp l => length */ var validationTypes = { "album_title" : "s", @@ -1195,7 +1227,7 @@ var validationTypes = { "owner_id" : "s", "rating" : "i", "replay_gain" : "n", - "sample_rate" : "i", + "sample_rate" : "n", "track_title" : "s", "track_number" : "i", "info_url" : "s", diff --git a/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js b/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js index 0dc3bc0a9..fc736b84a 100644 --- a/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js +++ b/airtime_mvc/public/js/airtime/playlist/smart_blockbuilder.js @@ -384,6 +384,28 @@ function setupUI() { at: "right center" }, }); + + $(".repeat_tracks_help_icon").qtip({ + content: { + text: "If your criteria is too strict, Airtime may not be able to fill up the desired smart block length." + + " Hence, if you check this option, tracks will be used more than once." + }, + hide: { + delay: 500, + fixed: true + }, + style: { + border: { + width: 0, + radius: 4 + }, + classes: "ui-tooltip-dark ui-tooltip-rounded" + }, + position: { + my: "left bottom", + at: "right center" + }, + }); } function enableAndShowExtraField(valEle, index) { diff --git a/airtime_mvc/public/js/datatables/plugin/dataTables.columnFilter.js b/airtime_mvc/public/js/datatables/plugin/dataTables.columnFilter.js index 4084fbbdb..80cb011cf 100644 --- a/airtime_mvc/public/js/datatables/plugin/dataTables.columnFilter.js +++ b/airtime_mvc/public/js/datatables/plugin/dataTables.columnFilter.js @@ -190,7 +190,7 @@ } else if (th.attr('id') == "length") { label = " hh:mm:ss.t"; } else if (th.attr('id') == "sample_rate") { - label = " Hz"; + label = " kHz"; } th.html(_fnRangeLabelPart(0));