feature: move folders

This commit is contained in:
2026-07-27 12:37:27 -04:00
parent 03c06c0dd9
commit af7940a6d5
10 changed files with 839 additions and 38 deletions

View File

@@ -0,0 +1,101 @@
(function () {
'use strict';
function apiFolderPath(path) {
return (path || '')
.replace(/^\/+/, '')
.split('/')
.map(encodeURIComponent)
.join('/');
}
function parentFolder(path) {
var index = path.lastIndexOf('/');
return index < 0 ? '' : path.slice(0, index);
}
function baseName(path) {
var index = path.lastIndexOf('/');
return index < 0 ? path : path.slice(index + 1);
}
function postFolder(path, operation, body) {
return fetch('/api/folders/' + apiFolderPath(path) + '/' + operation, {
method: 'POST',
credentials: 'same-origin',
headers: body ? { 'Content-Type': 'application/json' } : undefined,
body: body ? JSON.stringify(body) : undefined,
}).then(function (response) {
return response.json().then(function (data) {
if (!response.ok) throw new Error(data.error || 'Folder operation failed');
return data;
});
});
}
function closeMenu(button) {
var details = button.closest('details');
if (details) details.removeAttribute('open');
}
document.addEventListener('click', function (event) {
var renameButton = event.target.closest('[data-folder-rename-path]');
if (renameButton) {
var renamePath = renameButton.getAttribute('data-folder-rename-path');
var newName = window.prompt('Rename folder to:', baseName(renamePath));
if (newName === null) return;
newName = newName.trim().replace(/^\/+|\/+$/g, '');
if (newName === '' || newName === baseName(renamePath)) return;
var parent = parentFolder(renamePath);
var renameDestination = (parent ? parent + '/' : '') + newName;
renameButton.disabled = true;
postFolder(renamePath, 'move', { path: renameDestination })
.then(function (data) {
window.location.assign(data.url);
})
.catch(function (error) {
window.alert(error.message || 'Failed to rename folder');
renameButton.disabled = false;
});
return;
}
var moveButton = event.target.closest('[data-folder-move-path]');
if (moveButton) {
var movePath = moveButton.getAttribute('data-folder-move-path');
var destination = window.prompt('Move folder to:', movePath);
if (destination === null) return;
destination = destination.trim().replace(/^\/+|\/+$/g, '');
if (destination === '' || destination === movePath) return;
moveButton.disabled = true;
postFolder(movePath, 'move', { path: destination })
.then(function (data) {
window.location.assign(data.url);
})
.catch(function (error) {
window.alert(error.message || 'Failed to move folder');
moveButton.disabled = false;
});
return;
}
var archiveButton = event.target.closest('[data-folder-archive-path]');
if (archiveButton) {
var archivePath = archiveButton.getAttribute('data-folder-archive-path');
if (!archivePath) return;
if (!window.confirm('Archive this folder and all its documents? They will be hidden from the site but can be restored later.')) {
return;
}
archiveButton.disabled = true;
closeMenu(archiveButton);
postFolder(archivePath, 'archive')
.then(function () {
window.location.assign('/');
})
.catch(function (error) {
window.alert(error.message || 'Failed to archive folder');
archiveButton.disabled = false;
});
}
});
})();