Merge pull request #591 from hrniels/subalbums
Some cleanup, fixes and a new feature for subalbums.
This commit is contained in:
commit
55ae8a4be2
@ -28,6 +28,7 @@ final class Admin extends Access {
|
||||
case 'Album::setPublic': self::setAlbumPublicAction(); break;
|
||||
case 'Album::delete': self::deleteAlbumAction(); break;
|
||||
case 'Album::merge': self::mergeAlbumsAction(); break;
|
||||
case 'Album::move': self::moveAlbumsAction(); break;
|
||||
|
||||
// Photo functions
|
||||
case 'Photo::get': self::getPhotoAction(); break;
|
||||
@ -143,6 +144,14 @@ final class Admin extends Access {
|
||||
|
||||
}
|
||||
|
||||
private static function moveAlbumsAction() {
|
||||
|
||||
Validator::required(isset($_POST['albumIDs']), __METHOD__);
|
||||
$album = new Album($_POST['albumIDs']);
|
||||
Response::json($album->move());
|
||||
|
||||
}
|
||||
|
||||
// Photo functions
|
||||
|
||||
private static function getPhotoAction() {
|
||||
|
@ -637,13 +637,6 @@ final class Album {
|
||||
$albumID = array_splice($albumIDs, 0, 1);
|
||||
$albumID = $albumID[0];
|
||||
|
||||
// Ensure that we don't merge an album into its own subalbum
|
||||
foreach($albumIDs as $id) {
|
||||
foreach($this->getSubAlbums($id) as $sid) {
|
||||
if($sid == $albumID) return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Move photos
|
||||
$query = Database::prepare(Database::get(), "UPDATE ? SET album = ? WHERE album IN (?)", array(LYCHEE_TABLE_PHOTOS, $albumID, $this->albumIDs));
|
||||
$result = Database::execute(Database::get(), $query, __METHOD__, __LINE__);
|
||||
@ -672,6 +665,40 @@ final class Album {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean Returns true when successful.
|
||||
*/
|
||||
public function move() {
|
||||
|
||||
// Check dependencies
|
||||
Validator::required(isset($this->albumIDs), __METHOD__);
|
||||
|
||||
// Call plugins
|
||||
Plugins::get()->activate(__METHOD__, 0, func_get_args());
|
||||
|
||||
// Convert to array
|
||||
$albumIDs = explode(',', $this->albumIDs);
|
||||
|
||||
// Get first albumID
|
||||
$albumID = array_splice($albumIDs, 0, 1);
|
||||
$albumID = $albumID[0];
|
||||
|
||||
// $albumIDs contains all IDs without the first albumID
|
||||
// Convert to string
|
||||
$filteredIDs = implode(',', $albumIDs);
|
||||
|
||||
// Move albums
|
||||
$query = Database::prepare(Database::get(), "UPDATE ? SET parent = ? WHERE id IN (?)", array(LYCHEE_TABLE_ALBUMS, $albumID, $filteredIDs));
|
||||
$result = Database::execute(Database::get(), $query, __METHOD__, __LINE__);
|
||||
|
||||
// Call plugins
|
||||
Plugins::get()->activate(__METHOD__, 1, func_get_args());
|
||||
|
||||
if ($result===false) return false;
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return boolean Returns true when successful.
|
||||
*/
|
||||
|
@ -3,6 +3,26 @@
|
||||
* @copyright 2015 by Tobias Reich
|
||||
*/
|
||||
|
||||
const buildAlbumOptions = function(albums, select, parent = 0, layer = 0) {
|
||||
|
||||
var cmbxOptions = ''
|
||||
|
||||
for (i in albums) {
|
||||
if (albums[i].parent==parent) {
|
||||
|
||||
let title = (layer>0 ? ' '.repeat(layer - 1) + '└ ' : '') + albums[i].title
|
||||
let selected = select==albums[i].id ? ' selected="selected"' : ''
|
||||
|
||||
cmbxOptions += `<option${ selected } value='${ albums[i].id }'>${ title }</option>`
|
||||
cmbxOptions += buildAlbumOptions(albums, select, albums[i].id, layer + 1)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return cmbxOptions
|
||||
|
||||
}
|
||||
|
||||
album = {
|
||||
|
||||
json: null,
|
||||
@ -146,21 +166,6 @@ album.parse = function() {
|
||||
|
||||
}
|
||||
|
||||
function buildAlbumOptions(albums, select, parent = 0, layer = 0) {
|
||||
var cmbxOptions = ''
|
||||
for (i in albums) {
|
||||
if (albums[i].parent == parent) {
|
||||
let title = (layer > 0 ? " ".repeat(layer - 1) + "└ " : "") + albums[i].title
|
||||
cmbxOptions += `<option `;
|
||||
if (select == albums[i].id)
|
||||
cmbxOptions += `selected="selected" `
|
||||
cmbxOptions += `value='` + albums[i].id + `'>` + title + `</option>`
|
||||
cmbxOptions += buildAlbumOptions(albums, select, albums[i].id, layer + 1)
|
||||
}
|
||||
}
|
||||
return cmbxOptions
|
||||
}
|
||||
|
||||
album.add = function(albumID = 0) {
|
||||
|
||||
const action = function(data) {
|
||||
@ -249,6 +254,21 @@ album.delete = function(albumIDs) {
|
||||
albums.deleteByID(id)
|
||||
})
|
||||
|
||||
} else if (visible.album()) {
|
||||
|
||||
// if we deleted the current album, go to its parent
|
||||
if (albumIDs.length==1 && album.json.id==albumIDs[0]) {
|
||||
|
||||
let id = album.getParent()
|
||||
album.refresh()
|
||||
lychee.goto(id)
|
||||
|
||||
}
|
||||
// otherwise, we deleted a subalbum
|
||||
else {
|
||||
album.reload()
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
albums.refresh()
|
||||
@ -628,7 +648,7 @@ album.getArchive = function(albumID) {
|
||||
|
||||
}
|
||||
|
||||
album.merge = function(albumIDs, titles = []) {
|
||||
const getMessage = function(albumIDs, titles, operation) {
|
||||
|
||||
let title = ''
|
||||
let sTitle = ''
|
||||
@ -653,14 +673,20 @@ album.merge = function(albumIDs, titles = []) {
|
||||
// Fallback for second album without a title
|
||||
if (sTitle==='') sTitle = 'Untitled'
|
||||
|
||||
msg = lychee.html`<p>Are you sure you want to merge the album '$${ sTitle }' into the album '$${ title }'?</p>`
|
||||
msg = lychee.html`<p>Are you sure you want to ${ operation } the album '$${ sTitle }' into '$${ title }'?</p>`
|
||||
|
||||
} else {
|
||||
|
||||
msg = lychee.html`<p>Are you sure you want to merge all selected albums into the album '$${ title }'?</p>`
|
||||
msg = lychee.html`<p>Are you sure you want to ${ operation } all selected albums into '$${ title }'?</p>`
|
||||
|
||||
}
|
||||
|
||||
return msg
|
||||
|
||||
}
|
||||
|
||||
album.merge = function(albumIDs, titles = []) {
|
||||
|
||||
const action = function() {
|
||||
|
||||
basicModal.close()
|
||||
@ -671,19 +697,15 @@ album.merge = function(albumIDs, titles = []) {
|
||||
|
||||
api.post('Album::merge', params, function(data) {
|
||||
|
||||
if (data!==true) {
|
||||
lychee.error(null, params, data)
|
||||
} else {
|
||||
albums.refresh()
|
||||
lychee.goto()
|
||||
}
|
||||
if (data!==true) lychee.error(null, params, data)
|
||||
else album.reload()
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
basicModal.show({
|
||||
body: msg,
|
||||
body: getMessage(albumIDs, titles, 'merge'),
|
||||
buttons: {
|
||||
action: {
|
||||
title: 'Merge Albums',
|
||||
@ -697,4 +719,59 @@ album.merge = function(albumIDs, titles = []) {
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
album.move = function(albumIDs, titles = []) {
|
||||
|
||||
const action = function() {
|
||||
|
||||
basicModal.close()
|
||||
|
||||
let params = {
|
||||
albumIDs: albumIDs.join()
|
||||
}
|
||||
|
||||
api.post('Album::move', params, function(data) {
|
||||
|
||||
if (data!==true) lychee.error(null, params, data)
|
||||
else album.reload()
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
basicModal.show({
|
||||
body: getMessage(albumIDs, titles, 'move'),
|
||||
buttons: {
|
||||
action: {
|
||||
title: 'Move Albums',
|
||||
fn: action,
|
||||
class: 'red'
|
||||
},
|
||||
cancel: {
|
||||
title: "Don't Move",
|
||||
fn: basicModal.close
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
album.reload = function() {
|
||||
|
||||
let albumID = album.getID()
|
||||
|
||||
album.refresh()
|
||||
albums.refresh()
|
||||
|
||||
if (visible.album()) lychee.goto(albumID)
|
||||
else lychee.goto()
|
||||
|
||||
}
|
||||
|
||||
album.refresh = function() {
|
||||
|
||||
album.json = null
|
||||
album.subjson = null
|
||||
|
||||
}
|
@ -15,11 +15,11 @@ build.iconic = function(icon, classes = '') {
|
||||
|
||||
}
|
||||
|
||||
build.divider = function(title) {
|
||||
build.divider = function(title, id = '') {
|
||||
|
||||
let html = ''
|
||||
|
||||
html += lychee.html`<div class='divider'><h1>$${ title }</h1></div>`
|
||||
html += lychee.html`<div class='divider' id='$${ id }'><h1>$${ title }</h1></div>`
|
||||
|
||||
return html
|
||||
|
||||
|
@ -51,6 +51,24 @@ const getAlbumFrom = function(albums, id) {
|
||||
|
||||
}
|
||||
|
||||
const getSubIDs = function(albums, albumID) {
|
||||
|
||||
let ids = [ albumID ]
|
||||
|
||||
for (a in albums) {
|
||||
if (albums[a].parent==albumID) {
|
||||
|
||||
let sub = getSubIDs(albums, albums[a].id)
|
||||
for (id in sub)
|
||||
ids.push(sub[id])
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return ids
|
||||
|
||||
}
|
||||
|
||||
const countSubAlbums = function(photoIDs) {
|
||||
|
||||
let count = 0
|
||||
@ -117,12 +135,10 @@ contextMenu.album = function(albumID, e) {
|
||||
|
||||
if (album.isSmartID(albumID)) return false
|
||||
|
||||
// Show merge-item when there's more than one album
|
||||
let showMerge = (albums.json && albums.json.albums && Object.keys(albums.json.albums).length>1)
|
||||
|
||||
let items = [
|
||||
{ title: build.iconic('pencil') + 'Rename', fn: () => album.setTitle([ albumID ]) },
|
||||
{ title: build.iconic('collapse-left') + 'Merge', visible: showMerge, fn: () => { basicContext.close(); contextMenu.mergeAlbum(albumID, e) } },
|
||||
{ title: build.iconic('collapse-left') + 'Merge', fn: () => { basicContext.close(); contextMenu.mergeAlbum(albumID, e) } },
|
||||
{ title: build.iconic('folder') + 'Move', fn: () => { basicContext.close(); contextMenu.moveAlbum([ albumID ], e) } },
|
||||
{ title: build.iconic('trash') + 'Delete', fn: () => album.delete([ albumID ]) }
|
||||
]
|
||||
|
||||
@ -140,13 +156,11 @@ contextMenu.albumMulti = function(albumIDs, e) {
|
||||
// Show list of albums otherwise
|
||||
let autoMerge = (albumIDs.length>1 ? true : false)
|
||||
|
||||
// Show merge-item when there's more than one album
|
||||
let showMerge = (albums.json && albums.json.albums && Object.keys(albums.json.albums).length>1)
|
||||
|
||||
let items = [
|
||||
{ title: build.iconic('pencil') + 'Rename All', fn: () => album.setTitle(albumIDs) },
|
||||
{ title: build.iconic('collapse-left') + 'Merge All', visible: showMerge && autoMerge, fn: () => album.merge(albumIDs) },
|
||||
{ title: build.iconic('collapse-left') + 'Merge', visible: showMerge && !autoMerge, fn: () => { basicContext.close(); contextMenu.mergeAlbum(albumIDs[0], e) } },
|
||||
{ title: build.iconic('collapse-left') + 'Merge All', visible: autoMerge, fn: () => album.merge(albumIDs) },
|
||||
{ title: build.iconic('collapse-left') + 'Merge', visible: !autoMerge, fn: () => { basicContext.close(); contextMenu.mergeAlbum(albumIDs[0], e) } },
|
||||
{ title: build.iconic('folder') + 'Move All', fn: () => { basicContext.close(); contextMenu.moveAlbum(albumIDs, e) } },
|
||||
{ title: build.iconic('trash') + 'Delete All', fn: () => album.delete(albumIDs) }
|
||||
]
|
||||
|
||||
@ -193,7 +207,7 @@ contextMenu.mergeAlbum = function(albumID, e) {
|
||||
// It's not possible to move them into us
|
||||
let exclude = [ albumID ]
|
||||
let a = getAlbumFrom(data.albums, selalbum.parent)
|
||||
while (a != null) {
|
||||
while (a!=null) {
|
||||
exclude.push(a.id)
|
||||
a = getAlbumFrom(data.albums, a.parent)
|
||||
}
|
||||
@ -210,6 +224,38 @@ contextMenu.mergeAlbum = function(albumID, e) {
|
||||
|
||||
}
|
||||
|
||||
contextMenu.moveAlbum = function(albumIDs, e) {
|
||||
|
||||
api.post('Albums::get', { parent: -1 }, function(data) {
|
||||
|
||||
let items = []
|
||||
|
||||
if (data.albums && data.num>1) {
|
||||
|
||||
let title = albums.getByID(albumIDs[0]).title
|
||||
// Disable all childs
|
||||
// It's not possible to move us into them
|
||||
let exclude = []
|
||||
for (i in albumIDs) {
|
||||
let sub = getSubIDs(data.albums, String(albumIDs[i]))
|
||||
for (s in sub)
|
||||
exclude.push(sub[s])
|
||||
}
|
||||
|
||||
items = buildAlbumList(data.albums, exclude, (a) => album.move([ a.id ].concat(albumIDs), [ a.title, title ]), 0, 1)
|
||||
|
||||
items.unshift({ title: 'Root', fn: () => album.move([ 0 ].concat(albumIDs), [ 'Root', title ]) })
|
||||
|
||||
}
|
||||
|
||||
if (items.length===0) return false
|
||||
|
||||
basicContext.show(items, e.originalEvent, contextMenu.close)
|
||||
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
contextMenu.photo = function(photoID, e) {
|
||||
|
||||
// Notice for 'Move':
|
||||
|
@ -141,8 +141,8 @@ header.setMode = function(mode) {
|
||||
header.dom('.header__toolbar--album').addClass('header__toolbar--visible')
|
||||
|
||||
// Hide download button when album empty
|
||||
if (album.json.content===false) $('#button_archive').hide()
|
||||
else $('#button_archive').show()
|
||||
if (album.json.content===false && album.subjson.num==0) $('#button_archive').hide()
|
||||
else $('#button_archive').show()
|
||||
|
||||
// Hide download button when not logged in and album not downloadable
|
||||
if (lychee.publicMode===true && album.json.downloadable==='0') $('#button_archive').hide()
|
||||
|
@ -158,7 +158,7 @@ view.album = {
|
||||
|
||||
if (album.json.content && album.json.content!==false) {
|
||||
|
||||
photosData += build.divider('Photos')
|
||||
photosData += build.divider('Photos', 'divider-photos')
|
||||
|
||||
// Build photos
|
||||
$.each(album.json.content, function() {
|
||||
@ -236,6 +236,7 @@ view.album = {
|
||||
if (!visible.albums()) {
|
||||
album.json.num--
|
||||
view.album.num()
|
||||
if (album.json.num == 0) $('#divider-photos').hide()
|
||||
}
|
||||
})
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user