Compare commits

...

3 Commits

Author SHA1 Message Date
e43539d8e0 feat: use icons for files
All checks were successful
Deploy MinIO Explorer / deploy (push) Successful in 1m50s
2025-09-09 05:39:18 +02:00
6dd88bf1aa feat: add breadcrumb navigation
All checks were successful
Deploy MinIO Explorer / deploy (push) Successful in 51s
2025-09-08 22:17:08 +02:00
510959340d feat: uiux improvements. no scroll, direct link 2025-09-08 22:11:16 +02:00
2 changed files with 190 additions and 12 deletions

137
script.js
View File

@@ -165,9 +165,49 @@ function showLoading(show = true) {
function updateCurrentPathDisplay() {
const pathDisplay = document.getElementById("current-path");
if (pathDisplay) {
pathDisplay.textContent = "/" + config.currentPath;
if (!pathDisplay) return;
// Créer la structure de navigation breadcrumb
let breadcrumbHTML = '';
// Toujours commencer par la racine
if (config.currentPath) {
// Si on n'est pas à la racine, rendre "/" cliquable
breadcrumbHTML += '<a href="#" class="path-segment" data-path="">/ </a>';
} else {
// Si on est à la racine, afficher "/" sans lien
breadcrumbHTML += '/';
}
// Si on a un chemin, découper et créer les segments
if (config.currentPath) {
const segments = config.currentPath.split('/').filter(segment => segment.length > 0);
for (let i = 0; i < segments.length; i++) {
const segment = segments[i];
const segmentPath = segments.slice(0, i + 1).join('/');
// Le dernier segment (actuel) n'est pas cliquable
if (i === segments.length - 1) {
breadcrumbHTML += segment;
} else {
// Les segments précédents sont cliquables
breadcrumbHTML += `<a href="#" class="path-segment" data-path="${segmentPath}">${segment}</a> / `;
}
}
}
pathDisplay.innerHTML = breadcrumbHTML;
// Ajouter les event listeners aux liens de navigation
const pathLinks = pathDisplay.querySelectorAll('.path-segment');
pathLinks.forEach(link => {
link.addEventListener('click', (e) => {
e.preventDefault();
const targetPath = link.getAttribute('data-path');
loadBucketContents(targetPath, true);
});
});
}
async function loadBucketContents(path = "", pushToHistory = true) {
@@ -367,6 +407,7 @@ function displayContents(contents) {
function createParentRow(parentPath) {
const row = document.createElement("tr");
row.className = "clickable-row";
row.innerHTML = `
<td>
<span class="icon-parent"></span>
@@ -377,6 +418,15 @@ function createParentRow(parentPath) {
<td>-</td>
`;
// Rendre toute la ligne cliquable
row.addEventListener("click", (e) => {
// Éviter le double clic si on clique sur le lien
if (e.target.tagName !== 'A') {
e.preventDefault();
loadBucketContents(parentPath, true);
}
});
const link = row.querySelector(".folder-link");
link.addEventListener("click", (e) => {
e.preventDefault();
@@ -388,6 +438,7 @@ function createParentRow(parentPath) {
function createFolderRow(folder) {
const row = document.createElement("tr");
row.className = "clickable-row";
row.innerHTML = `
<td>
<span class="icon-folder"></span>
@@ -398,6 +449,15 @@ function createFolderRow(folder) {
<td>-</td>
`;
// Rendre toute la ligne cliquable
row.addEventListener("click", (e) => {
// Éviter le double clic si on clique sur le lien
if (e.target.tagName !== 'A') {
e.preventDefault();
loadBucketContents(folder.path, true);
}
});
const link = row.querySelector(".folder-link");
link.addEventListener("click", (e) => {
e.preventDefault();
@@ -409,20 +469,32 @@ function createFolderRow(folder) {
function createFileRow(file) {
const row = document.createElement("tr");
row.className = "clickable-row";
const fileUrl = `${config.baseUrl}/${file.fullKey}`;
const fileIcon = getFileIcon(file.name);
row.innerHTML = `
<td>
<span class="icon-file"></span>
<span class="file-icon">${fileIcon}</span>
<a href="#" class="file-link" data-file-url="${fileUrl}" data-file-name="${file.name}">${file.name}</a>
</td>
<td class="file-size">${formatFileSize(file.size)}</td>
<td class="file-date">${formatDate(file.modified)}</td>
<td>
<button class="copy-btn" data-url="${fileUrl}">Copier lien</button>
<button class="open-btn" data-url="${fileUrl}">Ouvrir</button>
</td>
`;
// Rendre toute la ligne cliquable
row.addEventListener("click", (e) => {
// Éviter le clic sur les boutons d'action et les liens
if (e.target.tagName !== 'BUTTON' && e.target.tagName !== 'A') {
e.preventDefault();
showPreview(fileUrl, file.name);
}
});
const fileLink = row.querySelector(".file-link");
fileLink.addEventListener("click", (e) => {
e.preventDefault();
@@ -430,7 +502,16 @@ function createFileRow(file) {
});
const copyBtn = row.querySelector(".copy-btn");
copyBtn.addEventListener("click", () => copyToClipboard(fileUrl));
copyBtn.addEventListener("click", (e) => {
e.stopPropagation(); // Empêcher la propagation vers le clic sur la ligne
copyToClipboard(fileUrl);
});
const openBtn = row.querySelector(".open-btn");
openBtn.addEventListener("click", (e) => {
e.stopPropagation(); // Empêcher la propagation vers le clic sur la ligne
openInNewTab(fileUrl);
});
return row;
}
@@ -480,6 +561,10 @@ async function copyToClipboard(text) {
}
}
function openInNewTab(fileUrl) {
window.open(fileUrl, '_blank', 'noopener,noreferrer');
}
// Variables globales pour la prévisualisation
let currentPreviewFile = {
url: "",
@@ -530,6 +615,50 @@ function detectFileType(fileName) {
return "unknown";
}
function getFileIcon(fileName) {
const extension = fileName.toLowerCase().split(".").pop();
const fileType = detectFileType(fileName);
// Icônes spécifiques par extension
const specificIcons = {
pdf: "📕",
zip: "📦", rar: "📦", "7z": "📦", tar: "📦", gz: "📦", bz2: "📦",
mp4: "🎬", avi: "🎬", mov: "🎬", wmv: "🎬", flv: "🎬", webm: "🎬", mkv: "🎬",
mp3: "🎵", wav: "🎵", ogg: "🎵", aac: "🎵", flac: "🎵", m4a: "🎵",
jpg: "🖼️", jpeg: "🖼️", png: "🖼️", gif: "🖼️", bmp: "🖼️", svg: "🖼️", webp: "🖼️",
txt: "📝", log: "📝",
json: "⚙️", xml: "⚙️", csv: "📊",
js: "🟨", ts: "🔷", jsx: "⚛️", tsx: "⚛️",
py: "🐍", java: "☕", php: "🐘", rb: "💎", go: "🐹", rs: "🦀",
html: "🌐", htm: "🌐", css: "🎨",
vue: "💚", svelte: "🧡",
md: "📖", markdown: "📖", rst: "📖",
tex: "📄", latex: "📄",
c: "⚡", cpp: "⚡",
};
// Retourner l'icône spécifique si elle existe
if (specificIcons[extension]) {
return specificIcons[extension];
}
// Sinon, retourner une icône par type
const typeIcons = {
images: "🖼️",
text: "📝",
code: "💻",
markdown: "📖",
rst: "📖",
pdf: "📕",
video: "🎬",
audio: "🎵",
archive: "📦",
unknown: "📄"
};
return typeIcons[fileType] || "📄";
}
function showPreview(fileUrl, fileName) {
currentPreviewFile = { url: fileUrl, name: fileName };

View File

@@ -34,6 +34,23 @@ h1 {
margin-bottom: 20px;
}
/* Styles pour la navigation breadcrumb dans le titre */
.path-segment {
color: #0066cc;
text-decoration: none;
font-weight: normal;
cursor: pointer;
}
.path-segment:hover {
text-decoration: underline;
color: #004499;
}
.path-segment:active {
color: #002266;
}
/* Section développement */
.dev-section {
background-color: #f0f0f0;
@@ -133,6 +150,15 @@ tr:hover {
background-color: #e6f3ff;
}
/* Lignes cliquables */
.clickable-row {
cursor: pointer;
}
.clickable-row:hover {
background-color: #e6f3ff !important;
}
/* Liens et dossiers */
.folder-link {
color: #0066cc;
@@ -157,24 +183,41 @@ tr:hover {
font-weight: bold;
}
/* Bouton copier lien */
.copy-btn {
/* Boutons d'actions */
.copy-btn,
.open-btn {
background-color: #f0f0f0;
border: 1px solid #ccc;
padding: 2px 6px;
font-size: 11px;
cursor: pointer;
border-radius: 2px;
margin-left: 2px;
}
.copy-btn:hover {
.copy-btn:hover,
.open-btn:hover {
background-color: #e0e0e0;
}
.copy-btn:active {
.copy-btn:active,
.open-btn:active {
background-color: #d0d0d0;
}
.open-btn {
background-color: #007acc;
color: white;
}
.open-btn:hover {
background-color: #005999;
}
.open-btn:active {
background-color: #004d80;
}
/* Tailles de fichiers */
.file-size {
text-align: right;
@@ -244,8 +287,8 @@ tr:hover {
}
#content-section {
flex: 0 0 25%; /* Tableau prend seulement 25% de la hauteur */
overflow-y: auto;
flex: none; /* Tableau prend l'espace nécessaire */
overflow-y: visible;
}
#files-table {
@@ -271,8 +314,8 @@ tr:hover {
}
#content-section {
flex: 0 0 20%; /* Encore moins d'espace pour le tableau sur mobile */
overflow-y: auto;
flex: none; /* Tableau prend l'espace nécessaire */
overflow-y: visible;
}
#files-table {
@@ -720,3 +763,9 @@ address {
.icon-parent::before {
content: "⬆️ ";
}
/* Icônes dynamiques pour les fichiers */
.file-icon {
margin-right: 0.5em;
font-size: 1em;
}