Merge GitHub updates into Gitea master
All checks were successful
Build & Push Docker Image / build-and-push (push) Successful in 1m53s
All checks were successful
Build & Push Docker Image / build-and-push (push) Successful in 1m53s
This commit is contained in:
@@ -26,12 +26,18 @@ $(document).ready(function() {
|
||||
$('#users-tbody').empty();
|
||||
$('#user-select').html('<option value="">Nutzer waehlen...</option>');
|
||||
|
||||
if (!users || users.length === 0) {
|
||||
$('#users-tbody').html('<tr><td colspan="5" style="text-align:center;">Keine Nutzer gefunden</td></tr>');
|
||||
return;
|
||||
}
|
||||
|
||||
users.forEach(function(u) {
|
||||
var badge = $('<span></span>').addClass('badge badge-' + u.role).text(u.role);
|
||||
var role = u.role || 'unbekannt';
|
||||
var badge = $('<span></span>').addClass('badge badge-' + role).text(role);
|
||||
var created = u.created_at ? new Date(u.created_at).toLocaleDateString('de-DE') : '-';
|
||||
var info = created;
|
||||
|
||||
if (u.role === 'client' && u.expires_at) {
|
||||
if (role === 'client' && u.expires_at) {
|
||||
var expDate = new Date(u.expires_at).toLocaleDateString('de-DE');
|
||||
if (u.expired) {
|
||||
badge = $('<span></span>').addClass('badge badge-expired').text('abgelaufen');
|
||||
@@ -55,32 +61,47 @@ $(document).ready(function() {
|
||||
|
||||
row.append($('<td></td>').text(u.id));
|
||||
row.append(userCell);
|
||||
row.append($('<td></td>').text(u.role));
|
||||
row.append($('<td></td>').text(role));
|
||||
row.append($('<td></td>').text(info));
|
||||
row.append(actions);
|
||||
$('#users-tbody').append(row);
|
||||
|
||||
// Dropdown fuer Ordner-Zuweisung (nur non-admin)
|
||||
if (u.role !== 'admin') {
|
||||
$('#user-select').append($('<option></option>').val(u.id).text(u.username + ' (' + u.role + ')'));
|
||||
if (role !== 'admin') {
|
||||
$('#user-select').append($('<option></option>').val(u.id).text(u.username + ' (' + role + ')'));
|
||||
}
|
||||
});
|
||||
}).fail(function(xhr) {
|
||||
var msg = 'HTTP ' + xhr.status + ': ' + xhr.statusText;
|
||||
$('#users-tbody').html('<tr><td colspan="5" style="color:#e44d26;">Fehler beim Laden: ' + msg + '</td></tr>');
|
||||
});
|
||||
}
|
||||
|
||||
// Nutzer erstellen
|
||||
$('#create-user-form').submit(function(e) {
|
||||
e.preventDefault();
|
||||
$.post('/api/admin/users', {
|
||||
username: $('#new-username').val(),
|
||||
password: $('#new-password').val(),
|
||||
role: $('#new-role').val()
|
||||
}).done(function() {
|
||||
var username = $('#new-username').val().trim();
|
||||
var password = $('#new-password').val();
|
||||
var role = $('#new-role').val();
|
||||
if (!username || !password) {
|
||||
alert('Bitte Username und Passwort eingeben.');
|
||||
return;
|
||||
}
|
||||
$.ajax({
|
||||
url: '/api/admin/users',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ username: username, password: password, role: role })
|
||||
}).done(function(data) {
|
||||
alert('Nutzer "' + username + '" erfolgreich erstellt!');
|
||||
$('#new-username').val('');
|
||||
$('#new-password').val('');
|
||||
loadUsers();
|
||||
}).fail(function(err) {
|
||||
alert('Fehler: ' + (err.responseJSON ? err.responseJSON.error : 'Unbekannt'));
|
||||
}).fail(function(xhr) {
|
||||
var msg = 'Unbekannter Fehler';
|
||||
if (xhr.responseJSON && xhr.responseJSON.error) msg = xhr.responseJSON.error;
|
||||
else if (xhr.status) msg = 'HTTP ' + xhr.status + ': ' + xhr.statusText;
|
||||
alert('Fehler beim Erstellen: ' + msg);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -119,54 +140,89 @@ $(document).ready(function() {
|
||||
|
||||
// ==================== ORDNER-ZUWEISUNG ====================
|
||||
|
||||
var allFolders = [];
|
||||
var assignedFolders = [];
|
||||
|
||||
function loadFolders() {
|
||||
$.get('/api/admin/folders').done(function(folders) {
|
||||
$('#folder-checkboxes').empty();
|
||||
if (folders.length === 0) {
|
||||
$('#folder-checkboxes').html('<p>Keine Unterordner in Websitebilder gefunden. Erstelle Ordner in Nextcloud.</p>');
|
||||
return;
|
||||
}
|
||||
folders.forEach(function(f) {
|
||||
var wrapper = $('<div class="folder-check"></div>');
|
||||
var label = $('<label></label>');
|
||||
$('<input type="checkbox" class="folder-cb"/>').val(f).appendTo(label);
|
||||
label.append(' ');
|
||||
$('<i class="fa fa-folder"></i>').appendTo(label);
|
||||
label.append(' ' + f);
|
||||
wrapper.append(label);
|
||||
$('#folder-checkboxes').append(wrapper);
|
||||
});
|
||||
allFolders = folders || [];
|
||||
renderFolderTable();
|
||||
});
|
||||
}
|
||||
|
||||
// Bei User-Auswahl: zugewiesene Ordner laden
|
||||
function renderFolderTable() {
|
||||
var $tbody = $('#folder-tbody');
|
||||
$tbody.empty();
|
||||
if (allFolders.length === 0) {
|
||||
$tbody.html('<tr><td colspan="2" style="text-align:center;">Keine Unterordner gefunden. Erstelle Ordner in Nextcloud.</td></tr>');
|
||||
return;
|
||||
}
|
||||
allFolders.forEach(function(f) {
|
||||
var isAssigned = assignedFolders.indexOf(f) !== -1;
|
||||
var cls = isAssigned ? 'folder-row assigned' : 'folder-row';
|
||||
var statusCls = isAssigned ? 'folder-status yes' : 'folder-status no';
|
||||
var statusText = isAssigned ? 'Zugewiesen' : '—';
|
||||
$tbody.append(
|
||||
'<tr class="' + cls + '" data-folder="' + f + '">' +
|
||||
'<td><i class="fa fa-folder"></i> ' + f + '</td>' +
|
||||
'<td style="text-align:center;"><span class="' + statusCls + '">' + statusText + '</span></td>' +
|
||||
'</tr>'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
// Bei User-Auswahl: zugewiesene Ordner laden und Tabelle anzeigen
|
||||
$('#user-select').change(function() {
|
||||
var uid = $(this).val();
|
||||
$('.folder-cb').prop('checked', false);
|
||||
if (!uid) return;
|
||||
$.get('/api/admin/assign?user_id=' + uid).done(function(assignedFolders) {
|
||||
assignedFolders.forEach(function(f) {
|
||||
$('.folder-cb').filter(function() {
|
||||
return $(this).val() === f;
|
||||
}).prop('checked', true);
|
||||
if (!uid) {
|
||||
$('#folder-table-wrap').hide();
|
||||
assignedFolders = [];
|
||||
return;
|
||||
}
|
||||
// Ordner neu laden falls noch leer, dann Zuweisung anzeigen
|
||||
var showTable = function() {
|
||||
$.get('/api/admin/assign?user_id=' + uid).done(function(folders) {
|
||||
assignedFolders = folders || [];
|
||||
renderFolderTable();
|
||||
$('#folder-table-wrap').show();
|
||||
}).fail(function() {
|
||||
assignedFolders = [];
|
||||
renderFolderTable();
|
||||
$('#folder-table-wrap').show();
|
||||
});
|
||||
});
|
||||
};
|
||||
if (allFolders.length === 0) {
|
||||
$.get('/api/admin/folders').done(function(folders) {
|
||||
allFolders = folders || [];
|
||||
showTable();
|
||||
}).fail(function() {
|
||||
allFolders = [];
|
||||
showTable();
|
||||
});
|
||||
} else {
|
||||
showTable();
|
||||
}
|
||||
});
|
||||
|
||||
// Zuweisung speichern
|
||||
$('#save-assignments').click(function() {
|
||||
// Klick auf Ordner-Zeile: Toggle + sofort speichern
|
||||
$(document).on('click', '.folder-row', function() {
|
||||
var uid = $('#user-select').val();
|
||||
if (!uid) return alert('Bitte Nutzer waehlen');
|
||||
var selected = [];
|
||||
$('.folder-cb:checked').each(function() { selected.push($(this).val()); });
|
||||
|
||||
if (!uid) return;
|
||||
var folder = $(this).data('folder');
|
||||
var idx = assignedFolders.indexOf(folder);
|
||||
if (idx !== -1) {
|
||||
assignedFolders.splice(idx, 1);
|
||||
} else {
|
||||
assignedFolders.push(folder);
|
||||
}
|
||||
renderFolderTable();
|
||||
$.ajax({
|
||||
url: '/api/admin/assign',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: JSON.stringify({ user_id: uid, folders: selected })
|
||||
data: JSON.stringify({ user_id: uid, folders: assignedFolders })
|
||||
}).done(function() {
|
||||
$('#assign-status').text('Gespeichert!').fadeIn().delay(2000).fadeOut();
|
||||
$('#assign-status').text('Gespeichert!').show().delay(1500).fadeOut();
|
||||
}).fail(function() {
|
||||
alert('Fehler beim Speichern');
|
||||
});
|
||||
|
||||
2
assets/js/admin.min.js
vendored
2
assets/js/admin.min.js
vendored
@@ -1 +1 @@
|
||||
$(document).ready(function(){function e(){$.get("/api/admin/users").done(function(e){$("#users-tbody").empty(),$("#user-select").html('<option value="">Nutzer waehlen...</option>'),e.forEach(function(e){var n='<span class="badge badge-'+e.role+'">'+e.role+"</span>",a=e.created_at?new Date(e.created_at).toLocaleDateString("de-DE"):"-";if("client"===e.role&&e.expires_at){var t=new Date(e.expires_at).toLocaleDateString("de-DE");e.expired?(n='<span class="badge badge-expired">abgelaufen</span>',a="Abgelaufen: "+t):a="Bis: "+t}var r='<button class="btn-small" onclick="changePassword('+e.id+", '"+e.username.replace(/'/g,"\\'")+"')\">PW</button>";r+='<button class="btn-small" onclick="deleteUser('+e.id+", '"+e.username.replace(/'/g,"\\'")+"')\">X</button>",$("#users-tbody").append("<tr><td>"+e.id+"</td><td>"+e.username+" "+n+"</td><td>"+e.role+"</td><td>"+a+"</td><td>"+r+"</td></tr>"),"admin"!==e.role&&$("#user-select").append('<option value="'+e.id+'">'+e.username+" ("+e.role+")</option>")})})}$.get("/api/auth/me").done(function(n){"admin"!==n.role?(alert("Kein Zugriff!"),window.location.href="/"):(e(),$.get("/api/admin/folders").done(function(e){$("#folder-checkboxes").empty(),0!==e.length?e.forEach(function(e){$("#folder-checkboxes").append('<div class="folder-check"><label><input type="checkbox" value="'+e+'" class="folder-cb"/> <i class="fa fa-folder"></i> '+e+"</label></div>")}):$("#folder-checkboxes").html("<p>Keine Unterordner in Websitebilder gefunden. Erstelle Ordner in Nextcloud.</p>")}),$("body").removeClass("is-preload"))}).fail(function(){window.location.href="/"}),$("#logout-btn").click(function(e){e.preventDefault(),$.post("/api/auth/logout").done(function(){window.location.href="/"})}),$("#create-user-form").submit(function(n){n.preventDefault(),$.post("/api/admin/users",{username:$("#new-username").val(),password:$("#new-password").val(),role:$("#new-role").val()}).done(function(){$("#new-username").val(""),$("#new-password").val(""),e()}).fail(function(e){alert("Fehler: "+(e.responseJSON?e.responseJSON.error:"Unbekannt"))})}),window.deleteUser=function(n,a){confirm('Nutzer "'+a+'" wirklich loeschen?')&&$.ajax({url:"/api/admin/users/"+n,type:"DELETE"}).done(e).fail(function(e){alert(e.responseJSON?e.responseJSON.error:"Fehler")})},window.changePassword=function(e,n){var a=prompt('Neues Passwort fuer "'+n+'":');a&&$.ajax({url:"/api/admin/users/"+e+"/password",type:"PUT",contentType:"application/json",data:JSON.stringify({new_password:a})}).done(function(){alert("Passwort geaendert!")}).fail(function(e){alert(e.responseJSON?e.responseJSON.error:"Fehler")})},$("#user-select").change(function(){var e=$(this).val();$(".folder-cb").prop("checked",!1),e&&$.get("/api/admin/assign?user_id="+e).done(function(e){e.forEach(function(e){$('.folder-cb[value="'+e+'"]').prop("checked",!0)})})}),$("#save-assignments").click(function(){var e=$("#user-select").val();if(!e)return alert("Bitte Nutzer waehlen");var n=[];$(".folder-cb:checked").each(function(){n.push($(this).val())}),$.ajax({url:"/api/admin/assign",type:"POST",contentType:"application/json",data:JSON.stringify({user_id:e,folders:n})}).done(function(){$("#assign-status").text("Gespeichert!").fadeIn().delay(2e3).fadeOut()}).fail(function(){alert("Fehler beim Speichern")})}),$("#admin-pw-form").submit(function(e){e.preventDefault(),$.post("/api/auth/change-password",{old_password:$("#admin-pw-old").val(),new_password:$("#admin-pw-new").val()}).done(function(){alert("Passwort geaendert!"),$("#admin-pw-old, #admin-pw-new").val("")}).fail(function(e){alert(e.responseJSON?e.responseJSON.error:"Fehler")})})});
|
||||
$(document).ready(function(){function e(){$.get("/api/admin/users").done(function(e){$("#users-tbody").empty(),$("#user-select").html('<option value="">Nutzer waehlen...</option>'),e&&0!==e.length?e.forEach(function(e){var t=e.role||"unbekannt",n='<span class="badge badge-'+t+'">'+t+"</span>",a=e.created_at?new Date(e.created_at).toLocaleDateString("de-DE"):"-";if("client"===t&&e.expires_at){var r=new Date(e.expires_at).toLocaleDateString("de-DE");e.expired?(n='<span class="badge badge-expired">abgelaufen</span>',a="Abgelaufen: "+r):a="Bis: "+r}var o='<button class="btn-small" onclick="changePassword('+e.id+", '"+e.username.replace(/'/g,"\\'")+"')\">PW</button>";o+='<button class="btn-small" onclick="deleteUser('+e.id+", '"+e.username.replace(/'/g,"\\'")+"')\">X</button>",$("#users-tbody").append("<tr><td>"+e.id+"</td><td>"+e.username+" "+n+"</td><td>"+t+"</td><td>"+a+"</td><td>"+o+"</td></tr>"),"admin"!==t&&$("#user-select").append('<option value="'+e.id+'">'+e.username+" ("+t+")</option>")}):$("#users-tbody").html('<tr><td colspan="5" style="text-align:center;">Keine Nutzer gefunden</td></tr>')}).fail(function(e){var t="HTTP "+e.status+": "+e.statusText;$("#users-tbody").html('<tr><td colspan="5" style="color:#e44d26;">Fehler beim Laden: '+t+"</td></tr>")})}$.get("/api/auth/me").done(function(n){"admin"!==n.role?(alert("Kein Zugriff!"),window.location.href="/"):(e(),$.get("/api/admin/folders").done(function(e){t=e}),$("body").removeClass("is-preload"))}).fail(function(){window.location.href="/"}),$("#logout-btn").click(function(e){e.preventDefault(),$.post("/api/auth/logout").done(function(){window.location.href="/"})}),$("#create-user-form").submit(function(t){t.preventDefault();var n=$("#new-username").val().trim(),a=$("#new-password").val(),r=$("#new-role").val();n&&a?$.ajax({url:"/api/admin/users",type:"POST",contentType:"application/json",data:JSON.stringify({username:n,password:a,role:r})}).done(function(t){alert('Nutzer "'+n+'" erfolgreich erstellt!'),$("#new-username").val(""),$("#new-password").val(""),e()}).fail(function(e){var t="Unbekannter Fehler";e.responseJSON&&e.responseJSON.error?t=e.responseJSON.error:e.status&&(t="HTTP "+e.status+": "+e.statusText),alert("Fehler beim Erstellen: "+t)}):alert("Bitte Username und Passwort eingeben.")}),window.deleteUser=function(t,n){confirm('Nutzer "'+n+'" wirklich loeschen?')&&$.ajax({url:"/api/admin/users/"+t,type:"DELETE"}).done(e).fail(function(e){alert(e.responseJSON?e.responseJSON.error:"Fehler")})},window.changePassword=function(e,t){var n=prompt('Neues Passwort fuer "'+t+'":');n&&$.ajax({url:"/api/admin/users/"+e+"/password",type:"PUT",contentType:"application/json",data:JSON.stringify({new_password:n})}).done(function(){alert("Passwort geaendert!")}).fail(function(e){alert(e.responseJSON?e.responseJSON.error:"Fehler")})};var t=[],n=[];function a(){var e=$("#folder-tbody");e.empty(),0!==t.length?t.forEach(function(t){var a=-1!==n.indexOf(t),r=a?"folder-row assigned":"folder-row",o=a?"folder-status yes":"folder-status no",s=a?"Zugewiesen":"—";e.append('<tr class="'+r+'" data-folder="'+t+'"><td><i class="fa fa-folder"></i> '+t+'</td><td style="text-align:center;"><span class="'+o+'">'+s+"</span></td></tr>")}):e.html('<tr><td colspan="2" style="text-align:center;">Keine Unterordner gefunden. Erstelle Ordner in Nextcloud.</td></tr>')}$("#user-select").change(function(){var e=$(this).val();if(!e)return $("#folder-table-wrap").hide(),void(n=[]);var r=function(){$.get("/api/admin/assign?user_id="+e).done(function(e){n=e||[],a(),$("#folder-table-wrap").show()}).fail(function(){n=[],a(),$("#folder-table-wrap").show()})};0===t.length?$.get("/api/admin/folders").done(function(e){t=e||[],r()}).fail(function(){t=[],r()}):r()}),$(document).on("click",".folder-row",function(){var e=$("#user-select").val();if(e){var t=$(this).data("folder"),r=n.indexOf(t);-1!==r?n.splice(r,1):n.push(t),a(),$.ajax({url:"/api/admin/assign",type:"POST",contentType:"application/json",data:JSON.stringify({user_id:e,folders:n})}).done(function(){$("#assign-status").text("Gespeichert!").show().delay(1500).fadeOut()}).fail(function(){alert("Fehler beim Speichern")})}}),$("#admin-pw-form").submit(function(e){e.preventDefault(),$.post("/api/auth/change-password",{old_password:$("#admin-pw-old").val(),new_password:$("#admin-pw-new").val()}).done(function(){alert("Passwort geaendert!"),$("#admin-pw-old, #admin-pw-new").val("")}).fail(function(e){alert(e.responseJSON?e.responseJSON.error:"Fehler")})})});
|
||||
@@ -182,6 +182,8 @@
|
||||
|
||||
images.forEach(function(file) {
|
||||
var article = $('<article class="thumb"></article>');
|
||||
article.attr('data-name', file.name);
|
||||
if (file.folder) article.attr('data-folder', file.folder);
|
||||
var prefix = file.folder ? encodeURIComponent(file.folder) + '/' : '';
|
||||
var fullPath = '/images/fulls/' + prefix + encodeURIComponent(file.name);
|
||||
var thumbPath = '/images/thumbs/' + prefix + encodeURIComponent(file.name);
|
||||
@@ -193,6 +195,7 @@
|
||||
});
|
||||
|
||||
initThumbs();
|
||||
initSelectionMode(images);
|
||||
initPoptrox();
|
||||
},
|
||||
error: function() {
|
||||
@@ -214,6 +217,14 @@
|
||||
if ((x = $image_img.data("position"))) $image.css("background-position", x);
|
||||
$image_img.hide();
|
||||
|
||||
// Fallback: Wenn Thumbnail fehlt, Vollbild als Vorschau nutzen
|
||||
$image_img[0].addEventListener("error", function() {
|
||||
var fullUrl = $image.attr("href");
|
||||
if (fullUrl) {
|
||||
$image.css("background-image", "url('" + fullUrl + "')");
|
||||
}
|
||||
});
|
||||
|
||||
$image_img[0].addEventListener("load", function() {
|
||||
EXIF.getData($image_img[0], function () {
|
||||
exifDatas[$image_img.data('name')] = getExifDataMarkup(this);
|
||||
@@ -282,6 +293,194 @@
|
||||
return template;
|
||||
}
|
||||
|
||||
// ==================== SELECTION MODE ====================
|
||||
|
||||
function initSelectionMode(allImages) {
|
||||
var selectedImages = [];
|
||||
var selectionActive = false;
|
||||
|
||||
// Toolbar erstellen (versteckt)
|
||||
var $toolbar = $('<div id="selection-toolbar"></div>');
|
||||
$toolbar.html(
|
||||
'<span id="sel-count">0 ausgewaehlt</span>' +
|
||||
'<button id="sel-download" class="button small" disabled>' +
|
||||
'<i class="fa fa-download"></i> Herunterladen</button>' +
|
||||
'<button id="sel-cancel" class="button small">' +
|
||||
'<i class="fa fa-times"></i> Abbrechen</button>'
|
||||
);
|
||||
$('body').append($toolbar);
|
||||
|
||||
// Selection-Toggle Button im Header
|
||||
var $selectToggle = $('<li><a href="#" id="select-mode-toggle" title="Bilder auswaehlen">' +
|
||||
'<i class="fa fa-check-square"></i></a></li>');
|
||||
$('#header nav > ul').prepend($selectToggle);
|
||||
|
||||
// Ordner-Download Buttons (nur wenn Ordner-Bilder vorhanden)
|
||||
var folders = [];
|
||||
allImages.forEach(function(img) {
|
||||
if (img.folder && folders.indexOf(img.folder) === -1) {
|
||||
folders.push(img.folder);
|
||||
}
|
||||
});
|
||||
if (folders.length > 0) {
|
||||
folders.forEach(function(folder) {
|
||||
var $folderBtn = $('<li><a href="#" class="folder-download-btn" ' +
|
||||
'data-folder="' + folder + '" title="Ordner \'' + folder + '\' herunterladen">' +
|
||||
'<i class="fa fa-folder-open"></i></a></li>');
|
||||
$('#header nav > ul').prepend($folderBtn);
|
||||
});
|
||||
}
|
||||
|
||||
// Selection-Mode toggle
|
||||
$(document).on('click', '#select-mode-toggle', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
selectionActive = !selectionActive;
|
||||
$('body').toggleClass('selection-mode', selectionActive);
|
||||
if (!selectionActive) clearSelection();
|
||||
$toolbar.toggleClass('visible', selectionActive);
|
||||
});
|
||||
|
||||
// Klick auf Thumbnail im Selection-Mode
|
||||
// Capture-Phase auf document: faengt JEDEN Klick ab bevor Poptrox ihn sieht
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!selectionActive) return;
|
||||
var thumb = e.target.closest('#main .thumb');
|
||||
if (!thumb) return;
|
||||
|
||||
e.preventDefault();
|
||||
e.stopImmediatePropagation();
|
||||
|
||||
var $thumb = $(thumb);
|
||||
var imgName = $thumb.attr('data-name');
|
||||
var folder = $thumb.attr('data-folder') || null;
|
||||
|
||||
var idx = -1;
|
||||
for (var i = 0; i < selectedImages.length; i++) {
|
||||
if (selectedImages[i].name === imgName && selectedImages[i].folder === folder) {
|
||||
idx = i; break;
|
||||
}
|
||||
}
|
||||
|
||||
if (idx !== -1) {
|
||||
selectedImages.splice(idx, 1);
|
||||
$thumb.removeClass('selected');
|
||||
} else {
|
||||
selectedImages.push({ name: imgName, folder: folder });
|
||||
$thumb.addClass('selected');
|
||||
}
|
||||
updateToolbar();
|
||||
}, true);
|
||||
|
||||
function updateToolbar() {
|
||||
var count = selectedImages.length;
|
||||
$('#sel-count').text(count + ' ausgewaehlt');
|
||||
$('#sel-download').prop('disabled', count === 0);
|
||||
if (count > 3) {
|
||||
$('#sel-download').html('<i class="fa fa-file-archive-o"></i> Als ZIP (' + count + ')');
|
||||
} else if (count > 0) {
|
||||
$('#sel-download').html('<i class="fa fa-download"></i> Herunterladen (' + count + ')');
|
||||
} else {
|
||||
$('#sel-download').html('<i class="fa fa-download"></i> Herunterladen');
|
||||
}
|
||||
}
|
||||
|
||||
function clearSelection() {
|
||||
selectedImages = [];
|
||||
$('.thumb').removeClass('selected');
|
||||
updateToolbar();
|
||||
}
|
||||
|
||||
// Download-Button (direkt gebunden, nicht delegiert)
|
||||
$toolbar.on('click', '#sel-download', function() {
|
||||
if (selectedImages.length === 0) return;
|
||||
var payload = JSON.stringify({ images: selectedImages });
|
||||
|
||||
if (selectedImages.length <= 3) {
|
||||
// 1-3 Bilder: normales AJAX, Server gibt JSON mit URLs
|
||||
$.ajax({
|
||||
url: '/api/download/selected',
|
||||
type: 'POST',
|
||||
contentType: 'application/json',
|
||||
data: payload,
|
||||
success: function(resp) {
|
||||
if (resp.mode === 'individual') {
|
||||
resp.urls.forEach(function(url, i) {
|
||||
setTimeout(function() {
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = url.split('/').pop();
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
}, i * 500);
|
||||
});
|
||||
}
|
||||
},
|
||||
error: function(xhr) {
|
||||
var msg = (xhr.responseJSON && xhr.responseJSON.error) || 'Download fehlgeschlagen';
|
||||
alert(msg);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// 4+ Bilder: Blob-Download fuer ZIP
|
||||
var xhr = new XMLHttpRequest();
|
||||
xhr.open('POST', '/api/download/selected', true);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json');
|
||||
xhr.responseType = 'blob';
|
||||
xhr.onload = function() {
|
||||
if (xhr.status === 200) {
|
||||
var url = window.URL.createObjectURL(xhr.response);
|
||||
var a = document.createElement('a');
|
||||
a.href = url;
|
||||
a.download = 'mischkomposition-auswahl.zip';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
window.URL.revokeObjectURL(url);
|
||||
document.body.removeChild(a);
|
||||
} else {
|
||||
// Fehler-Blob als Text lesen
|
||||
var reader = new FileReader();
|
||||
reader.onload = function() {
|
||||
try {
|
||||
var resp = JSON.parse(this.result);
|
||||
alert(resp.error || 'Download fehlgeschlagen');
|
||||
} catch(e) {
|
||||
alert('Download fehlgeschlagen (Status ' + xhr.status + ')');
|
||||
}
|
||||
};
|
||||
reader.readAsText(xhr.response);
|
||||
}
|
||||
};
|
||||
xhr.onerror = function() {
|
||||
alert('Netzwerkfehler beim Download');
|
||||
};
|
||||
xhr.send(payload);
|
||||
}
|
||||
});
|
||||
|
||||
// Abbrechen-Button (direkt gebunden)
|
||||
$toolbar.on('click', '#sel-cancel', function() {
|
||||
selectionActive = false;
|
||||
$('body').removeClass('selection-mode');
|
||||
$toolbar.removeClass('visible');
|
||||
clearSelection();
|
||||
});
|
||||
|
||||
// Ordner-Download
|
||||
$(document).on('click', '.folder-download-btn', function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
var folder = $(this).data('folder');
|
||||
var a = document.createElement('a');
|
||||
a.href = '/api/download/folder/' + encodeURIComponent(folder);
|
||||
a.download = folder + '.zip';
|
||||
document.body.appendChild(a);
|
||||
a.click();
|
||||
document.body.removeChild(a);
|
||||
});
|
||||
}
|
||||
|
||||
// Galerie laden
|
||||
loadGallery();
|
||||
|
||||
|
||||
2
assets/js/main.min.js
vendored
2
assets/js/main.min.js
vendored
File diff suppressed because one or more lines are too long
Reference in New Issue
Block a user