122 lines
4.7 KiB
Twig
122 lines
4.7 KiB
Twig
<div id="file-browser-{{ domain }}-{{ id|e('html_attr') }}"
|
|
class="file-browser"
|
|
data-domain="{{ domain }}"
|
|
data-id="{{ id }}"
|
|
data-base-path="{{ path('app_files', { domain: domain, id: id, editable: editable }) }}"
|
|
data-current-path="{{ path }}">
|
|
|
|
<div class="card mt-3">
|
|
<div class="card-header">Fichiers</div>
|
|
<div class="card-body">
|
|
|
|
{% if editable %}
|
|
<div class="mb-3">
|
|
<form method="post" enctype="multipart/form-data" class="d-flex gap-2 align-items-center" id="upload-form-{{ domain }}-{{ id }}">
|
|
<input type="file" name="file" required>
|
|
<input type="hidden" name="path" value="{{ path }}">
|
|
<button type="submit" class="btn btn-sm btn-primary">Uploader</button>
|
|
</form>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<p><strong>Chemin :</strong> {{ path ?: '/' }}</p>
|
|
|
|
{% set parentPath = path|split('/')|slice(0, -1)|join('/') %}
|
|
|
|
<ul class="list-unstyled">
|
|
{% if path %}
|
|
<li><a href="#" class="file-nav" data-path="{{ parentPath }}">⬅️ ..</a></li>
|
|
{% endif %}
|
|
|
|
{% for file in files %}
|
|
<li>
|
|
{% if file.isDirectory %}
|
|
📁 <a href="#" class="file-nav" data-path="{{ path ? path ~ '/' ~ file.name : file.name }}">{{ file.name }}/</a>
|
|
{% if editable %}
|
|
<button class="btn btn-sm btn-danger btn-delete ms-2" data-path="{{ file.path }}">🗑️</button>
|
|
{% endif %}
|
|
{% else %}
|
|
📄 {{ file.name }}
|
|
{% if editable %}
|
|
<button class="btn btn-sm btn-danger btn-delete ms-2" data-path="{{ file.path }}">🗑️</button>
|
|
{% endif %}
|
|
{% endif %}
|
|
</li>
|
|
{% else %}
|
|
<li><em>Dossier vide</em></li>
|
|
{% endfor %}
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
|
|
<script>
|
|
(function () {
|
|
function initFileBrowser(container) {
|
|
if (!container) return;
|
|
|
|
container.addEventListener('click', function (e) {
|
|
// Navigation
|
|
if (e.target.classList.contains('file-nav')) {
|
|
e.preventDefault();
|
|
const path = e.target.dataset.path;
|
|
refreshContainer(container, path);
|
|
}
|
|
|
|
// Suppression
|
|
if (e.target.classList.contains('btn-delete')) {
|
|
e.preventDefault();
|
|
if (!confirm('Supprimer ce fichier ?')) return;
|
|
|
|
const pathToDelete = e.target.dataset.path;
|
|
const currentPath = container.dataset.currentPath || '';
|
|
|
|
fetch('/user/file/' + container.dataset.domain + '/' + container.dataset.id + '/delete', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
'X-Requested-With': 'XMLHttpRequest',
|
|
},
|
|
body: JSON.stringify({ path: pathToDelete })
|
|
})
|
|
.then(res => res.json())
|
|
.then(data => {
|
|
if (data.success) {
|
|
// Rafraîchit après suppression
|
|
refreshContainer(container, currentPath);
|
|
} else {
|
|
alert('Erreur : ' + data.error);
|
|
}
|
|
})
|
|
.catch(err => alert('Erreur lors de la suppression : ' + err.message));
|
|
}
|
|
});
|
|
}
|
|
|
|
function refreshContainer(oldContainer, path) {
|
|
const domain = oldContainer.dataset.domain;
|
|
const id = oldContainer.dataset.id;
|
|
const base = oldContainer.dataset.basePath;
|
|
|
|
fetch(base + '?path=' + encodeURIComponent(path))
|
|
.then(response => response.text())
|
|
.then(html => {
|
|
const parser = new DOMParser();
|
|
const doc = parser.parseFromString(html, 'text/html');
|
|
const newContainer = doc.getElementById(oldContainer.id);
|
|
if (newContainer) {
|
|
oldContainer.replaceWith(newContainer);
|
|
newContainer.dataset.currentPath = path;
|
|
initFileBrowser(newContainer); // re-binde sur le nouveau DOM
|
|
}
|
|
});
|
|
}
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
document.querySelectorAll('.file-browser').forEach(initFileBrowser);
|
|
});
|
|
})();
|
|
</script>
|
|
|
|
|
|
</div>
|