Merge pull request #298 from EdouardVanbelle/feat/buttons
This commit is contained in:
@@ -37,15 +37,11 @@
|
|||||||
.batch-selection-bar {
|
.batch-selection-bar {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
|
||||||
background: var(--color-multiselect-bg);
|
background: var(--color-multiselect-bg);
|
||||||
color: var(--color-multiselect-text);
|
color: var(--color-multiselect-text);
|
||||||
padding: 10px 20px;
|
padding: 10px 20px;
|
||||||
border-radius: 12px;
|
border-radius: 12px;
|
||||||
margin: 0 0 12px;
|
|
||||||
height: 60px;
|
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
transform: translateY(-8px);
|
|
||||||
transition:
|
transition:
|
||||||
opacity 0.2s,
|
opacity 0.2s,
|
||||||
max-height 0.25s,
|
max-height 0.25s,
|
||||||
@@ -55,12 +51,6 @@
|
|||||||
pointer-events: auto;
|
pointer-events: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.batch-bar-left {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 12px;
|
|
||||||
}
|
|
||||||
|
|
||||||
.batch-bar-close {
|
.batch-bar-close {
|
||||||
background: none;
|
background: none;
|
||||||
border: none;
|
border: none;
|
||||||
|
|||||||
@@ -49,6 +49,7 @@
|
|||||||
|
|
||||||
.action-buttons {
|
.action-buttons {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex: auto;
|
||||||
gap: 12px;
|
gap: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+1
-36
@@ -210,42 +210,7 @@
|
|||||||
<h1 class="page-title" data-i18n="nav.files">Files</h1>
|
<h1 class="page-title" data-i18n="nav.files">Files</h1>
|
||||||
|
|
||||||
<div class="page-sticky-header" id="page-sticky-header">
|
<div class="page-sticky-header" id="page-sticky-header">
|
||||||
<div class="actions-bar" id="actions-bar">
|
<div class="actions-bar" id="actions-bar"><!-- content will be set up by JS --></div>
|
||||||
|
|
||||||
<div class="action-buttons" id="action-buttons">
|
|
||||||
<div class="upload-dropdown" id="upload-dropdown">
|
|
||||||
<button class="btn btn-primary" id="upload-btn">
|
|
||||||
<i class="fas fa-cloud-upload-alt"></i>
|
|
||||||
<span data-i18n="actions.upload">Upload</span>
|
|
||||||
<i class="fas fa-caret-down upload-caret"></i>
|
|
||||||
</button>
|
|
||||||
<div class="upload-dropdown-menu" id="upload-dropdown-menu">
|
|
||||||
<button class="upload-dropdown-item" id="upload-files-btn">
|
|
||||||
<i class="fas fa-file"></i>
|
|
||||||
<span data-i18n="actions.upload_files">Upload files</span>
|
|
||||||
</button>
|
|
||||||
<button class="upload-dropdown-item" id="upload-folder-btn">
|
|
||||||
<i class="fas fa-folder-open"></i>
|
|
||||||
<span data-i18n="actions.upload_folder">Upload folder</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<button class="btn btn-secondary" id="new-folder-btn">
|
|
||||||
<i class="fas fa-folder-plus"></i>
|
|
||||||
<span data-i18n="actions.new_folder">New folder</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="view-toggle">
|
|
||||||
<button class="toggle-btn active" id="grid-view-btn" title="Grid view">
|
|
||||||
<i class="fas fa-th"></i>
|
|
||||||
</button>
|
|
||||||
<button class="toggle-btn" id="list-view-btn" title="List view">
|
|
||||||
<i class="fas fa-list"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div id="batch-selection-bar" class="batch-selection-bar hidden"></div>
|
|
||||||
|
|
||||||
<div class="breadcrumb">
|
<div class="breadcrumb">
|
||||||
<span class="breadcrumb-item" data-i18n="breadcrumb.home">Home</span>
|
<span class="breadcrumb-item" data-i18n="breadcrumb.home">Home</span>
|
||||||
|
|||||||
@@ -107,6 +107,7 @@ async function rebuildBreadCrumb() {
|
|||||||
app.currentFolderInfo = currentFolderInfo;
|
app.currentFolderInfo = currentFolderInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO split load() vs view()
|
||||||
/**
|
/**
|
||||||
* Files view loading logic
|
* Files view loading logic
|
||||||
*
|
*
|
||||||
|
|||||||
+53
-36
@@ -38,9 +38,51 @@ let uploadDropdownDocumentClickHandler = null;
|
|||||||
let uploadDropdownBindingsController = null;
|
let uploadDropdownBindingsController = null;
|
||||||
let actionsBarDelegationBound = false;
|
let actionsBarDelegationBound = false;
|
||||||
|
|
||||||
|
const _multiSelectButons = `
|
||||||
|
<div class="action-buttons batch-selection-bar hidden" id="multi-select-buttons">
|
||||||
|
<div class="list-header-checkbox">
|
||||||
|
<button class="batch-bar-close" id="batch-selection-close" title="Cancel selection">
|
||||||
|
<i class="fas fa-times"></i>
|
||||||
|
</button>
|
||||||
|
<span class="batch-bar-count" id="batch-bar-count"></span>
|
||||||
|
</div>
|
||||||
|
<div class="batch-selection-info">
|
||||||
|
<div class="batch-bar-actions">
|
||||||
|
<button class="batch-btn" id="batch-fav" title="Add to favorites" data-i18n-title="batch.add_favorites">
|
||||||
|
<i class="fas fa-star"></i>
|
||||||
|
<span data-i18n="batch.add_favorites">Add to favorites</span>
|
||||||
|
</button>
|
||||||
|
<button class="batch-btn" id="batch-move" title="Move or copy" data-i18n-title="batch.move_copy">
|
||||||
|
<i class="fas fa-arrows-alt"></i>
|
||||||
|
<span data-i18n="batch.move_copy">Move or copy</span>
|
||||||
|
</button>
|
||||||
|
<button class="batch-btn" id="batch-download" title="Download" data-i18n-title="actions.download">
|
||||||
|
<i class="fas fa-download"></i>
|
||||||
|
<span data-i18n="actions.download">Download</span>
|
||||||
|
</button>
|
||||||
|
<button class="batch-btn batch-btn-danger" id="batch-delete" title="Delete" data-i18-title="actions.delete">
|
||||||
|
<i class="fas fa-trash-alt"></i>
|
||||||
|
<span data-i18n="actions.delete">Delete</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
|
const _toggleButtons = `
|
||||||
|
<div class="view-toggle">
|
||||||
|
<button class="toggle-btn active" id="grid-view-btn" title="Grid view">
|
||||||
|
<i class="fas fa-th"></i>
|
||||||
|
</button>
|
||||||
|
<button class="toggle-btn" id="list-view-btn" title="List view">
|
||||||
|
<i class="fas fa-list"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
|
||||||
const ACTIONS_BAR_TEMPLATES = {
|
const ACTIONS_BAR_TEMPLATES = {
|
||||||
files: `
|
files: `
|
||||||
<div class="action-buttons">
|
<div class="action-buttons" id="default-buttons">
|
||||||
<div class="upload-dropdown" id="upload-dropdown">
|
<div class="upload-dropdown" id="upload-dropdown">
|
||||||
<button class="btn btn-primary" id="upload-btn">
|
<button class="btn btn-primary" id="upload-btn">
|
||||||
<i class="fas fa-cloud-upload-alt icon-mr"></i>
|
<i class="fas fa-cloud-upload-alt icon-mr"></i>
|
||||||
@@ -63,57 +105,32 @@ const ACTIONS_BAR_TEMPLATES = {
|
|||||||
<span data-i18n="actions.new_folder">New folder</span>
|
<span data-i18n="actions.new_folder">New folder</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="view-toggle">
|
${_multiSelectButons}
|
||||||
<button class="toggle-btn active" id="grid-view-btn" title="Grid view">
|
${_toggleButtons}
|
||||||
<i class="fas fa-th"></i>
|
|
||||||
</button>
|
|
||||||
<button class="toggle-btn" id="list-view-btn" title="List view">
|
|
||||||
<i class="fas fa-list"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`,
|
`,
|
||||||
trash: `
|
trash: `
|
||||||
<div class="action-buttons">
|
<div class="action-buttons" id="default-buttons">
|
||||||
<button class="btn btn-danger" id="empty-trash-btn">
|
<button class="btn btn-danger" id="empty-trash-btn">
|
||||||
<i class="fas fa-trash-alt"></i>
|
<i class="fas fa-trash-alt"></i>
|
||||||
<span data-i18n="trash.empty_trash">Empty trash</span>
|
<span data-i18n="trash.empty_trash">Empty trash</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="view-toggle">
|
${_toggleButtons}
|
||||||
<button class="toggle-btn active" id="grid-view-btn" title="Grid view">
|
|
||||||
<i class="fas fa-th"></i>
|
|
||||||
</button>
|
|
||||||
<button class="toggle-btn" id="list-view-btn" title="List view">
|
|
||||||
<i class="fas fa-list"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`,
|
`,
|
||||||
favorites: `
|
favorites: `
|
||||||
<div class="action-buttons"></div>
|
<div class="action-buttons" id="default-buttons"></div>
|
||||||
<div class="view-toggle">
|
${_multiSelectButons}
|
||||||
<button class="toggle-btn active" id="grid-view-btn" title="Grid view">
|
${_toggleButtons}
|
||||||
<i class="fas fa-th"></i>
|
|
||||||
</button>
|
|
||||||
<button class="toggle-btn" id="list-view-btn" title="List view">
|
|
||||||
<i class="fas fa-list"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`,
|
`,
|
||||||
recent: `
|
recent: `
|
||||||
<div class="action-buttons">
|
<div class="action-buttons" id="default-buttons">
|
||||||
<button class="btn btn-secondary" id="clear-recent-btn">
|
<button class="btn btn-secondary" id="clear-recent-btn">
|
||||||
<i class="fas fa-broom icon-mr"></i>
|
<i class="fas fa-broom icon-mr"></i>
|
||||||
<span data-i18n="actions.clear_recent">Clear recent</span>
|
<span data-i18n="actions.clear_recent">Clear recent</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="view-toggle">
|
${_multiSelectButons}
|
||||||
<button class="toggle-btn active" id="grid-view-btn" title="Grid view">
|
${_toggleButtons}
|
||||||
<i class="fas fa-th"></i>
|
|
||||||
</button>
|
|
||||||
<button class="toggle-btn" id="list-view-btn" title="List view">
|
|
||||||
<i class="fas fa-list"></i>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
`
|
`
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -1309,6 +1309,9 @@ const ui = {
|
|||||||
|
|
||||||
filesList.classList.remove('hidden');
|
filesList.classList.remove('hidden');
|
||||||
filesContainerError?.classList.add('hidden');
|
filesContainerError?.classList.add('hidden');
|
||||||
|
|
||||||
|
// apply hook as header changed
|
||||||
|
multiSelect.init();
|
||||||
},
|
},
|
||||||
|
|
||||||
showEmptyList() {
|
showEmptyList() {
|
||||||
|
|||||||
@@ -230,51 +230,12 @@ const multiSelect = {
|
|||||||
this._syncSelectAllCheckbox();
|
this._syncSelectAllCheckbox();
|
||||||
},
|
},
|
||||||
|
|
||||||
// ── Selection bar (replaces list-header when items selected) ────
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build the inner HTML for the selection bar that replaces the
|
|
||||||
* normal list-header columns (Name / Type / Size / Modified).
|
|
||||||
*/
|
|
||||||
_buildSelectionBarHTML() {
|
|
||||||
//FIXME: should support i18n lang change
|
|
||||||
|
|
||||||
return `
|
|
||||||
<div x-class="batch-bar-left" class="list-header-checkbox">
|
|
||||||
<button class="batch-bar-close" id="batch-grid-close" title="Cancel selection">
|
|
||||||
<i class="fas fa-times"></i>
|
|
||||||
</button>
|
|
||||||
<span class="batch-bar-count" id="batch-bar-count"></span>
|
|
||||||
</div>
|
|
||||||
<div class="batch-selection-info">
|
|
||||||
<div class="batch-bar-actions">
|
|
||||||
<button class="batch-btn" id="batch-fav" title="Add to favorites" data-i18n-title="batch.add_favorites">
|
|
||||||
<i class="fas fa-star"></i>
|
|
||||||
<span data-i18n="batch.add_favorites">Add to favorites</span>
|
|
||||||
</button>
|
|
||||||
<button class="batch-btn" id="batch-move" title="Move or copy" data-i18n-title="batch.move_copy">
|
|
||||||
<i class="fas fa-arrows-alt"></i>
|
|
||||||
<span data-i18n="batch.move_copy">Move or copy</span>
|
|
||||||
</button>
|
|
||||||
<button class="batch-btn" id="batch-download" title="Download" data-i18n-title="actions.download">
|
|
||||||
<i class="fas fa-download"></i>
|
|
||||||
<span data-i18n="actions.download">Download</span>
|
|
||||||
</button>
|
|
||||||
<button class="batch-btn batch-btn-danger" id="batch-delete" title="Delete" data-i18-title="actions.delete">
|
|
||||||
<i class="fas fa-trash-alt"></i>
|
|
||||||
<span data-i18n="actions.delete">Delete</span>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
},
|
|
||||||
|
|
||||||
/** Main UI sync — called after every selection change */
|
/** Main UI sync — called after every selection change */
|
||||||
_syncUI() {
|
_syncUI() {
|
||||||
const n = this._selected.size;
|
const n = this._selected.size;
|
||||||
|
|
||||||
const batchSelectionBar = document.getElementById('batch-selection-bar');
|
const multiSelectButtons = document.getElementById('multi-select-buttons');
|
||||||
const actionsBar = document.getElementById('actions-bar');
|
const defaultButtons = document.getElementById('default-buttons');
|
||||||
|
|
||||||
if (n > 0) {
|
if (n > 0) {
|
||||||
this._barVisible = true;
|
this._barVisible = true;
|
||||||
@@ -282,16 +243,14 @@ const multiSelect = {
|
|||||||
const countText = n === 1 ? this._t('batch.one_selected') || '1 item selected' : this._t('batch.n_selected', { count: n }) || `${n} items selected`;
|
const countText = n === 1 ? this._t('batch.one_selected') || '1 item selected' : this._t('batch.n_selected', { count: n }) || `${n} items selected`;
|
||||||
document.getElementById('batch-bar-count').innerText = countText;
|
document.getElementById('batch-bar-count').innerText = countText;
|
||||||
|
|
||||||
actionsBar.classList.add('hidden');
|
defaultButtons?.classList.add('hidden');
|
||||||
|
multiSelectButtons?.classList.remove('hidden');
|
||||||
batchSelectionBar.classList.remove('hidden');
|
|
||||||
} else {
|
} else {
|
||||||
this._barVisible = false;
|
this._barVisible = false;
|
||||||
|
|
||||||
// Hide grid bar
|
// Hide grid bar
|
||||||
batchSelectionBar.classList.add('hidden');
|
multiSelectButtons?.classList.add('hidden');
|
||||||
|
defaultButtons?.classList.remove('hidden');
|
||||||
if (actionsBar.dataset.mode !== 'hidden') actionsBar.classList.remove('hidden');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sync individual item checkboxes
|
// Sync individual item checkboxes
|
||||||
@@ -306,7 +265,7 @@ const multiSelect = {
|
|||||||
const move = document.getElementById('batch-move');
|
const move = document.getElementById('batch-move');
|
||||||
const dl = document.getElementById('batch-download');
|
const dl = document.getElementById('batch-download');
|
||||||
const fav = document.getElementById('batch-fav');
|
const fav = document.getElementById('batch-fav');
|
||||||
const closeBtn = document.getElementById('batch-grid-close');
|
const closeBtn = document.getElementById('batch-selection-close');
|
||||||
if (del) del.onclick = () => this.batchDelete();
|
if (del) del.onclick = () => this.batchDelete();
|
||||||
if (move) move.onclick = () => this.batchMove();
|
if (move) move.onclick = () => this.batchMove();
|
||||||
if (dl) dl.onclick = () => this.batchDownload();
|
if (dl) dl.onclick = () => this.batchDownload();
|
||||||
@@ -515,12 +474,6 @@ const multiSelect = {
|
|||||||
if (e.key === 'Delete' && this.hasSelection) this.batchDelete();
|
if (e.key === 'Delete' && this.hasSelection) this.batchDelete();
|
||||||
});
|
});
|
||||||
|
|
||||||
const batchSelectionBar = document.getElementById('batch-selection-bar');
|
|
||||||
batchSelectionBar.innerHTML = this._buildSelectionBarHTML();
|
|
||||||
|
|
||||||
if (i18n?.translateElement) {
|
|
||||||
i18n.translateElement(batchSelectionBar);
|
|
||||||
}
|
|
||||||
this._wireBarButtons();
|
this._wireBarButtons();
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user