CC-1977: Allow multiple files to be selected and acted upon in the library and playlist
- Added checkbox column to playlist builder - Added the ability to add multiple songs to playlist by using checkboxes and "Add" button - Added the ability to delete multiple songs/playlists by using checkboxes and "Delete" button - Make them look nice by adjusting CSS and datatable
This commit is contained in:
parent
f025dccc4f
commit
8833f4462e
|
@ -11,6 +11,7 @@ class LibraryController extends Zend_Controller_Action
|
|||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('contents', 'json')
|
||||
->addActionContext('delete', 'json')
|
||||
->addActionContext('delete-group', 'json')
|
||||
->addActionContext('context-menu', 'json')
|
||||
->addActionContext('get-file-meta-data', 'html')
|
||||
->addActionContext('upload-file-soundcloud', 'json')
|
||||
|
@ -178,6 +179,45 @@ class LibraryController extends Zend_Controller_Action
|
|||
$this->view->id = $id;
|
||||
}
|
||||
}
|
||||
|
||||
public function deleteGroupAction()
|
||||
{
|
||||
$ids = $this->_getParam('ids');
|
||||
$userInfo = Zend_Auth::getInstance()->getStorage()->read();
|
||||
$user = new Application_Model_User($userInfo->id);
|
||||
|
||||
if ($user->isAdmin()) {
|
||||
|
||||
if (!is_null($ids)) {
|
||||
foreach ($ids as $key => $id) {
|
||||
$file = Application_Model_StoredFile::Recall($id);
|
||||
|
||||
if (PEAR::isError($file)) {
|
||||
$this->view->message = $file->getMessage();
|
||||
return;
|
||||
}
|
||||
else if(is_null($file)) {
|
||||
$this->view->message = "file doesn't exist";
|
||||
return;
|
||||
}
|
||||
|
||||
$res = $file->delete();
|
||||
|
||||
if (PEAR::isError($res)) {
|
||||
$this->view->message = $res->getMessage();
|
||||
return;
|
||||
}
|
||||
else {
|
||||
$res = settype($res, "integer");
|
||||
$data = array("filepath" => $file->getFilePath(), "delete" => $res);
|
||||
Application_Model_RabbitMq::SendMessageToMediaMonitor("file_delete", $data);
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->ids = $ids;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function contentsAction()
|
||||
{
|
||||
|
|
|
@ -8,18 +8,20 @@ class PlaylistController extends Zend_Controller_Action
|
|||
{
|
||||
$ajaxContext = $this->_helper->getHelper('AjaxContext');
|
||||
$ajaxContext->addActionContext('add-item', 'json')
|
||||
->addActionContext('delete-item', 'json')
|
||||
->addActionContext('set-fade', 'json')
|
||||
->addActionContext('set-cue', 'json')
|
||||
->addActionContext('move-item', 'json')
|
||||
->addActionContext('close', 'json')
|
||||
->addActionContext('new', 'json')
|
||||
->addActionContext('edit', 'json')
|
||||
->addActionContext('delete-active', 'json')
|
||||
->addActionContext('delete', 'json')
|
||||
->addActionContext('delete-item', 'json')
|
||||
->addActionContext('add-group', 'json')
|
||||
->addActionContext('delete-group', 'json')
|
||||
->addActionContext('set-fade', 'json')
|
||||
->addActionContext('set-cue', 'json')
|
||||
->addActionContext('move-item', 'json')
|
||||
->addActionContext('close', 'json')
|
||||
->addActionContext('new', 'json')
|
||||
->addActionContext('edit', 'json')
|
||||
->addActionContext('delete-active', 'json')
|
||||
->addActionContext('delete', 'json')
|
||||
->addActionContext('set-playlist-fades', 'json')
|
||||
->addActionContext('set-playlist-name', 'json')
|
||||
->addActionContext('set-playlist-description', 'json')
|
||||
->addActionContext('set-playlist-description', 'json')
|
||||
->initContext();
|
||||
|
||||
$this->pl_sess = new Zend_Session_Namespace(UI_PLAYLIST_SESSNAME);
|
||||
|
@ -209,6 +211,59 @@ class PlaylistController extends Zend_Controller_Action
|
|||
unset($this->view->pl);
|
||||
}
|
||||
|
||||
public function addGroupAction()
|
||||
{
|
||||
$ids = $this->_getParam('ids');
|
||||
$pos = $this->_getParam('pos', null);
|
||||
|
||||
if (!is_null($ids)) {
|
||||
$pl = $this->getPlaylist();
|
||||
if ($pl === false) {
|
||||
$this->view->playlist_error = true;
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($ids as $key => $value) {
|
||||
$res = $pl->addAudioClip($value);
|
||||
if (PEAR::isError($res)) {
|
||||
$this->view->message = $res->getMessage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->pl = $pl;
|
||||
$this->view->html = $this->view->render('playlist/update.phtml');
|
||||
$this->view->name = $pl->getName();
|
||||
$this->view->length = $pl->getLength();
|
||||
$this->view->description = $pl->getDescription();
|
||||
return;
|
||||
}
|
||||
$this->view->message = "a file is not chosen";
|
||||
}
|
||||
|
||||
public function deleteGroupAction()
|
||||
{
|
||||
$ids = $this->_getParam('ids', null);
|
||||
|
||||
foreach ($ids as $key => $id) {
|
||||
$pl = Application_Model_Playlist::Recall($id);
|
||||
|
||||
if ($pl !== FALSE) {
|
||||
Application_Model_Playlist::Delete($id);
|
||||
$pl_sess = $this->pl_sess;
|
||||
if($pl_sess->id === $id){
|
||||
unset($pl_sess->id);
|
||||
}
|
||||
} else {
|
||||
$this->view->playlist_error = true;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
$this->view->ids = $ids;
|
||||
$this->view->html = $this->view->render('playlist/index.phtml');
|
||||
}
|
||||
|
||||
public function setCueAction()
|
||||
{
|
||||
$pos = $this->_getParam('pos');
|
||||
|
|
|
@ -607,10 +607,10 @@ dl.inline-list dd {
|
|||
}
|
||||
.dataTables_filter input {
|
||||
background: url("images/search_auto_bg.png") no-repeat scroll 0 0 #DDDDDD;
|
||||
width: 60%;
|
||||
border: 1px solid #5B5B5B;
|
||||
margin: 0;
|
||||
padding: 4px 3px 4px 25px;
|
||||
width: 60%;
|
||||
border: 1px solid #5B5B5B;
|
||||
margin-left: -8px;
|
||||
padding: 4px 3px 4px 25px;
|
||||
}
|
||||
.dataTables_length select {
|
||||
background-color: #DDDDDD;
|
||||
|
@ -623,6 +623,15 @@ dl.inline-list dd {
|
|||
vertical-align: top;
|
||||
}
|
||||
|
||||
.library_toolbar .ui-button {
|
||||
float: right;
|
||||
text-align:center;
|
||||
font-size:12px;
|
||||
font-weight:normal;
|
||||
padding: 0.2em 1em;
|
||||
margin: 0.5em 0.2em;
|
||||
}
|
||||
|
||||
/*----END Data Table----*/
|
||||
|
||||
fieldset {
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
var dTable;
|
||||
var checkedCount = 0;
|
||||
|
||||
//used by jjmenu
|
||||
function getId() {
|
||||
|
@ -32,8 +33,20 @@ function deleteAudioClip(json) {
|
|||
return;
|
||||
}
|
||||
|
||||
deleteItem("au", json.id);
|
||||
if (json.ids != undefined) {
|
||||
for (var i = json.ids.length - 1; i >= 0; i--) {
|
||||
deleteItem("au", json.ids[i]);
|
||||
}
|
||||
} else if (json.id != undefined) {
|
||||
deleteItem("au", json.id);
|
||||
}
|
||||
location.reload(true);
|
||||
}
|
||||
|
||||
function confirmDeleteGroup() {
|
||||
if(confirm('Are you sure you want to delete the selected items?')){
|
||||
groupDelete();
|
||||
}
|
||||
}
|
||||
|
||||
//callbacks called by jjmenu
|
||||
|
@ -75,11 +88,17 @@ function checkImportStatus(){
|
|||
|
||||
function deletePlaylist(json) {
|
||||
if(json.message) {
|
||||
alert(json.message);
|
||||
return;
|
||||
alert(json.message);
|
||||
return;
|
||||
}
|
||||
|
||||
deleteItem("pl", json.id);
|
||||
|
||||
if (json.ids != undefined) {
|
||||
for (var i = json.ids.length - 1; i >= 0; i--) {
|
||||
deleteItem("pl", json.ids[i]);
|
||||
}
|
||||
} else if (json.id != undefined) {
|
||||
deleteItem("pl", json.id);
|
||||
}
|
||||
window.location.reload();
|
||||
}
|
||||
//end callbacks called by jjmenu
|
||||
|
@ -92,7 +111,7 @@ function addLibraryItemEvents() {
|
|||
cursor: 'pointer'
|
||||
});
|
||||
|
||||
$('#library_display tbody tr td').not('[class=datatable_checkbox]')
|
||||
$('#library_display tbody tr td').not('[class=library_checkbox]')
|
||||
.jjmenu("click",
|
||||
[{get:"/Library/context-menu/format/json/id/#id#/type/#type#"}],
|
||||
{id: getId, type: getType},
|
||||
|
@ -105,36 +124,34 @@ function dtRowCallback( nRow, aData, iDisplayIndex, iDisplayIndexFull ) {
|
|||
|
||||
type = aData["ftype"].substring(0,2);
|
||||
id = aData["id"];
|
||||
|
||||
|
||||
if(type == "au") {
|
||||
$('td:eq(6)', nRow).html( '<img src="css/images/icon_audioclip.png">' );
|
||||
}
|
||||
else if(type == "pl") {
|
||||
$('td:eq(6)', nRow).html( '<img src="css/images/icon_playlist.png">' );
|
||||
$('td.library_type', nRow).html( '<img src="css/images/icon_audioclip.png">' );
|
||||
} else if(type == "pl") {
|
||||
$('td.library_type', nRow).html( '<img src="css/images/icon_playlist.png">' );
|
||||
}
|
||||
|
||||
$(nRow).attr("id", type+'_'+id);
|
||||
$(nRow).attr("id", type+'_'+id);
|
||||
|
||||
// insert id on lenth field
|
||||
$('td:eq(5)', nRow).attr("id", "length");
|
||||
// insert id on lenth field
|
||||
$('td.library_length', nRow).attr("id", "length");
|
||||
|
||||
return nRow;
|
||||
return nRow;
|
||||
}
|
||||
|
||||
function dtDrawCallback() {
|
||||
addLibraryItemEvents();
|
||||
addMetadataQtip();
|
||||
saveNumEntriesSetting();
|
||||
var temp = dTable.fnGetData()
|
||||
console.log(temp)
|
||||
addLibraryItemEvents();
|
||||
addMetadataQtip();
|
||||
saveNumEntriesSetting();
|
||||
setupGroupActions();
|
||||
}
|
||||
|
||||
function addProgressIcon(id) {
|
||||
if($("#au_"+id).find("td:eq(0)").find("span").length > 0){
|
||||
$("#au_"+id).find("td:eq(0)").find("span").removeClass();
|
||||
if($("#au_"+id).find("td.library_title").find("span").length > 0){
|
||||
$("#au_"+id).find("td.library_title").find("span").removeClass();
|
||||
$("span[id="+id+"]").addClass("small-icon progress");
|
||||
}else{
|
||||
$("#au_"+id).find("td:eq(0)").append('<span id="'+id+'" class="small-icon progress"></span>')
|
||||
$("#au_"+id).find("td.library_title").append('<span id="'+id+'" class="small-icon progress"></span>')
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,7 +250,7 @@ function addQtipToSCIcons(){
|
|||
function addMetadataQtip(){
|
||||
var tableRow = $('#library_display tbody tr');
|
||||
tableRow.each(function(){
|
||||
var title = $(this).find('td:eq(0)').html()
|
||||
var title = $(this).find('td.library_title').html()
|
||||
var info = $(this).attr("id")
|
||||
info = info.split("_");
|
||||
var id = info[1];
|
||||
|
@ -301,6 +318,133 @@ function getNumEntriesPreference(data) {
|
|||
return parseInt(data.libraryInit.numEntries);
|
||||
}
|
||||
|
||||
function groupAdd() {
|
||||
var ids = new Array();
|
||||
var addGroupUrl = '/Playlist/add-group';
|
||||
var newSPLUrl = '/Playlist/new/format/json';
|
||||
var dirty = true;
|
||||
$('#library_display tbody tr').each(function() {
|
||||
var idSplit = $(this).attr('id').split("_");
|
||||
var id = idSplit.pop();
|
||||
var type = idSplit.pop();
|
||||
if (dirty && $(this).find(":checkbox").attr("checked")) {
|
||||
if (type == "au") {
|
||||
ids.push(id);
|
||||
} else if (type == "pl") {
|
||||
alert("Can't add playlist to another playlist");
|
||||
dirty = false;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (dirty && ids.length > 0) {
|
||||
stopAudioPreview();
|
||||
|
||||
if ($('#spl_sortable').length == 0) {
|
||||
$.post(newSPLUrl, function(json) {
|
||||
openDiffSPL(json);
|
||||
redrawDataTablePage();
|
||||
|
||||
$.post(addGroupUrl, {format: "json", ids: ids}, setSPLContent);
|
||||
});
|
||||
} else {
|
||||
$.post(addGroupUrl, {format: "json", ids: ids}, setSPLContent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function groupDelete() {
|
||||
var auIds = new Array();
|
||||
var plIds = new Array();
|
||||
var auUrl = '/Library/delete-group';
|
||||
var plUrl = '/Playlist/delete-group';
|
||||
var dirty = true;
|
||||
$('#library_display tbody tr').each(function() {
|
||||
var idSplit = $(this).attr('id').split("_");
|
||||
var id = idSplit.pop();
|
||||
var type = idSplit.pop();
|
||||
if (dirty && $(this).find(":checkbox").attr("checked")) {
|
||||
if (type == "au") {
|
||||
auIds.push(id);
|
||||
} else if (type == "pl") {
|
||||
plIds.push(id);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (dirty && (auIds.length > 0 || plIds.length > 0)) {
|
||||
stopAudioPreview();
|
||||
|
||||
if (auIds.length > 0) {
|
||||
$.post(auUrl, {format: "json", ids: auIds}, deleteAudioClip);
|
||||
}
|
||||
if (plIds.length > 0) {
|
||||
$.post(plUrl, {format: "json", ids: plIds}, deletePlaylist);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggleAll() {
|
||||
var checked = $(this).attr("checked");
|
||||
$('#library_display tr').each(function() {
|
||||
$(this).find(":checkbox").attr("checked", checked);
|
||||
if (checked) {
|
||||
$(this).addClass('selected');
|
||||
} else {
|
||||
$(this).removeClass('selected');
|
||||
}
|
||||
});
|
||||
|
||||
if (checked) {
|
||||
checkedCount = $('#library_display tbody tr').size();
|
||||
} else {
|
||||
checkedCount = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function checkBoxChanged() {
|
||||
var cbAll = $('#library_display thead').find(":checkbox");
|
||||
var cbAllChecked = cbAll.attr("checked");
|
||||
var checked = $(this).attr("checked");
|
||||
var size = $('#library_display tbody tr').size();
|
||||
if (checked) {
|
||||
if (checkedCount < size) {
|
||||
checkedCount++;
|
||||
}
|
||||
$(this).parent().parent().addClass('selected');
|
||||
} else {
|
||||
if (!checked && checkedCount > 0) {
|
||||
checkedCount--;
|
||||
}
|
||||
$(this).parent().parent().removeClass('selected');
|
||||
}
|
||||
|
||||
if (cbAllChecked && checkedCount < size) {
|
||||
cbAll.attr("checked", false);
|
||||
} else if (!cbAllChecked && checkedCount == size) {
|
||||
cbAll.attr("checked", true);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
function setupGroupActions() {
|
||||
checkedCount = 0;
|
||||
$('#library_display tr:nth-child(1)').find(":checkbox").attr("checked", false);
|
||||
$('#library_display thead').find(":checkbox").change(toggleAll);
|
||||
$('#library_display tbody tr').each(function() {
|
||||
$(this).find(":checkbox").change(checkBoxChanged);
|
||||
});
|
||||
}
|
||||
|
||||
function fnShowHide(iCol) {
|
||||
/* Get the DataTables object again - this is not a recreation, just a get of the object */
|
||||
var oTable = dTable;
|
||||
|
||||
var bVis = oTable.fnSettings().aoColumns[iCol].bVisible;
|
||||
oTable.fnSetColumnVis( iCol, bVis ? false : true );
|
||||
}
|
||||
|
||||
function createDataTable(data) {
|
||||
dTable = $('#library_display').dataTable( {
|
||||
"bProcessing": true,
|
||||
|
@ -318,14 +462,14 @@ function createDataTable(data) {
|
|||
"fnRowCallback": dtRowCallback,
|
||||
"fnDrawCallback": dtDrawCallback,
|
||||
"aoColumns": [
|
||||
/* Checkbox */ { "sTitle": "<input type='checkbox' name='cb_all'>", "bSortable": false, "bSearchable": false, "mDataProp": "checkbox", "sWidth": "25px", "sClass": "datatable_checkbox" },
|
||||
/* Id */ { "sName": "id", "bSearchable": false, "bVisible": false, "mDataProp": "id" },
|
||||
/* Title */ { "sTitle": "Title", "sName": "track_title", "mDataProp": "track_title" },
|
||||
/* Creator */ { "sTitle": "Creator", "sName": "artist_name", "mDataProp": "artist_name" },
|
||||
/* Album */ { "sTitle": "Album", "sName": "album_title", "mDataProp": "album_title" },
|
||||
/* Genre */ { "sTitle": "Genre", "sName": "genre", "mDataProp": "genre" },
|
||||
/* Length */ { "sTitle": "Length", "sName": "length", "mDataProp": "length" },
|
||||
/* Type */ { "sTitle": "Type", "sName": "ftype", "bSearchable": false, "mDataProp": "ftype", "sWidth": "50px" },
|
||||
/* Checkbox */ { "sTitle": "<input type='checkbox' name='cb_all'>", "bSortable": false, "bSearchable": false, "mDataProp": "checkbox", "sWidth": "25px", "sClass": "library_checkbox"},
|
||||
/* Id */ { "sName": "id", "bSearchable": false, "bVisible": false, "mDataProp": "id", "sClass": "library_id"},
|
||||
/* Title */ { "sTitle": "Title", "sName": "track_title", "mDataProp": "track_title", "sClass": "library_title"},
|
||||
/* Creator */ { "sTitle": "Creator", "sName": "artist_name", "mDataProp": "artist_name", "sClass": "library_creator"},
|
||||
/* Album */ { "sTitle": "Album", "sName": "album_title", "mDataProp": "album_title", "sClass": "library_album"},
|
||||
/* Genre */ { "sTitle": "Genre", "sName": "genre", "mDataProp": "genre", "sClass": "library_genre"},
|
||||
/* Length */ { "sTitle": "Length", "sName": "length", "mDataProp": "length", "sWidth": "15%", "sClass": "library_length"},
|
||||
/* Type */ { "sTitle": "Type", "sName": "ftype", "bSearchable": false, "mDataProp": "ftype", "sWidth": "7%", "sClass": "library_type"},
|
||||
],
|
||||
"aaSorting": [[2,'asc']],
|
||||
"sPaginationType": "full_numbers",
|
||||
|
@ -335,9 +479,16 @@ function createDataTable(data) {
|
|||
"sSearch": ""
|
||||
},
|
||||
"iDisplayLength": getNumEntriesPreference(data),
|
||||
"bStateSave": true
|
||||
"bStateSave": true,
|
||||
"sDom": 'lfr<"H"C<"library_toolbar">>t<"F"ip>'
|
||||
});
|
||||
dTable.fnSetFilteringDelay(350);
|
||||
|
||||
|
||||
$("div.library_toolbar").html('<span class="fg-button ui-button ui-state-default" id="library_group_delete">Delete</span>' +
|
||||
'<span class="fg-button ui-button ui-state-default" id="library_group_add">Add</span>');
|
||||
$('#library_group_add').click(groupAdd);
|
||||
$('#library_group_delete').click(confirmDeleteGroup);
|
||||
}
|
||||
|
||||
$(document).ready(function() {
|
||||
|
@ -346,7 +497,7 @@ $(document).ready(function() {
|
|||
$.ajax({ url: "/Api/library-init/format/json", dataType:"json", success:createDataTable,
|
||||
error:function(jqXHR, textStatus, errorThrown){}});
|
||||
|
||||
checkImportStatus()
|
||||
checkImportStatus();
|
||||
setInterval( "checkImportStatus()", 5000 );
|
||||
setInterval( "checkSCUploadStatus()", 5000 );
|
||||
|
||||
|
|
Loading…
Reference in New Issue