feat: ograniczenie widocznych plików do 10 ostatnio używanych, dodanie okna modalnego z całą bazą plików oraz zmiana ikony na plus przy przycisku Dodaj
This commit is contained in:
4 files changed
+121
-14
No files matched your search
+90
-9
@@ -53,6 +53,12 @@ const uploadStatusText = document.getElementById('upload-status-text');
|
|||||||
const uploadsList = document.getElementById('uploads-list');
|
const uploadsList = document.getElementById('uploads-list');
|
||||||
const emptyUploadsMsg = document.getElementById('empty-uploads-msg');
|
const emptyUploadsMsg = document.getElementById('empty-uploads-msg');
|
||||||
const uploadsCountBadge = document.getElementById('uploads-count');
|
const uploadsCountBadge = document.getElementById('uploads-count');
|
||||||
|
const btnOpenAllUploads = document.getElementById('btn-open-all-uploads');
|
||||||
|
const btnAllUploadsCount = document.getElementById('btn-all-uploads-count');
|
||||||
|
const uploadsModal = document.getElementById('uploads-modal');
|
||||||
|
const btnCloseUploads = document.getElementById('btn-close-uploads');
|
||||||
|
const modalUploadsList = document.getElementById('modal-uploads-list');
|
||||||
|
const emptyModalUploadsMsg = document.getElementById('empty-modal-uploads-msg');
|
||||||
const historyList = document.getElementById('history-list');
|
const historyList = document.getElementById('history-list');
|
||||||
const emptyHistoryMsg = document.getElementById('empty-history-msg');
|
const emptyHistoryMsg = document.getElementById('empty-history-msg');
|
||||||
const historyCountBadge = document.getElementById('history-count');
|
const historyCountBadge = document.getElementById('history-count');
|
||||||
@@ -170,6 +176,15 @@ function bindEvents() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Uploads Modal Events
|
||||||
|
if (btnOpenAllUploads) btnOpenAllUploads.addEventListener('click', openUploadsModal);
|
||||||
|
if (btnCloseUploads) btnCloseUploads.addEventListener('click', closeUploadsModal);
|
||||||
|
if (uploadsModal) {
|
||||||
|
uploadsModal.addEventListener('click', (e) => {
|
||||||
|
if (e.target === uploadsModal) closeUploadsModal();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
// Upload Events
|
// Upload Events
|
||||||
if (btnSelectFile && fileInput) {
|
if (btnSelectFile && fileInput) {
|
||||||
btnSelectFile.addEventListener('click', () => fileInput.click());
|
btnSelectFile.addEventListener('click', () => fileInput.click());
|
||||||
@@ -848,20 +863,33 @@ async function fetchUploads() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Render Uploaded Files
|
let allUploadedFiles = [];
|
||||||
function renderUploads(files) {
|
|
||||||
if (!uploadsList) return;
|
// Open Uploads Modal
|
||||||
const items = uploadsList.querySelectorAll('.queue-item');
|
function openUploadsModal() {
|
||||||
|
if (uploadsModal) {
|
||||||
|
uploadsModal.style.display = 'flex';
|
||||||
|
renderModalUploads(allUploadedFiles);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close Uploads Modal
|
||||||
|
function closeUploadsModal() {
|
||||||
|
if (uploadsModal) uploadsModal.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render Modal Uploads (All files)
|
||||||
|
function renderModalUploads(files) {
|
||||||
|
if (!modalUploadsList) return;
|
||||||
|
const items = modalUploadsList.querySelectorAll('.queue-item');
|
||||||
items.forEach(el => el.remove());
|
items.forEach(el => el.remove());
|
||||||
|
|
||||||
if (!files || files.length === 0) {
|
if (!files || files.length === 0) {
|
||||||
emptyUploadsMsg.style.display = 'flex';
|
if (emptyModalUploadsMsg) emptyModalUploadsMsg.style.display = 'flex';
|
||||||
uploadsCountBadge.textContent = '0 plików';
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
emptyUploadsMsg.style.display = 'none';
|
if (emptyModalUploadsMsg) emptyModalUploadsMsg.style.display = 'none';
|
||||||
uploadsCountBadge.textContent = `${files.length} ${files.length === 1 ? 'plik' : files.length < 5 ? 'pliki' : 'plików'}`;
|
|
||||||
|
|
||||||
files.forEach(file => {
|
files.forEach(file => {
|
||||||
const li = document.createElement('li');
|
const li = document.createElement('li');
|
||||||
@@ -877,7 +905,55 @@ function renderUploads(files) {
|
|||||||
</div>
|
</div>
|
||||||
<div class="queue-item-actions" style="display: flex; gap: 6px; align-items: center;">
|
<div class="queue-item-actions" style="display: flex; gap: 6px; align-items: center;">
|
||||||
<button class="btn btn-primary" style="padding: 4px 10px; font-size: 0.8rem; display: flex; align-items: center; gap: 4px;" onclick="playUploadedFile('${safeFilename}')" title="Dodaj do kolejki">
|
<button class="btn btn-primary" style="padding: 4px 10px; font-size: 0.8rem; display: flex; align-items: center; gap: 4px;" onclick="playUploadedFile('${safeFilename}')" title="Dodaj do kolejki">
|
||||||
<i data-lucide="play"></i> Dodaj
|
<i data-lucide="plus"></i> Dodaj
|
||||||
|
</button>
|
||||||
|
<button class="btn-action-icon delete" onclick="deleteUploadedFile('${safeFilename}')" title="Usuń z serwera">
|
||||||
|
<i data-lucide="trash-2"></i>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
`;
|
||||||
|
modalUploadsList.appendChild(li);
|
||||||
|
});
|
||||||
|
lucide.createIcons();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Render Uploaded Files (Top 10 most recent on dashboard panel)
|
||||||
|
function renderUploads(files) {
|
||||||
|
allUploadedFiles = files || [];
|
||||||
|
if (btnAllUploadsCount) btnAllUploadsCount.textContent = allUploadedFiles.length;
|
||||||
|
|
||||||
|
if (!uploadsList) return;
|
||||||
|
const items = uploadsList.querySelectorAll('.queue-item');
|
||||||
|
items.forEach(el => el.remove());
|
||||||
|
|
||||||
|
if (!files || files.length === 0) {
|
||||||
|
emptyUploadsMsg.style.display = 'flex';
|
||||||
|
uploadsCountBadge.textContent = '0 plików';
|
||||||
|
if (modalUploadsList) renderModalUploads([]);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
emptyUploadsMsg.style.display = 'none';
|
||||||
|
uploadsCountBadge.textContent = `${files.length} ${files.length === 1 ? 'plik' : files.length < 5 ? 'pliki' : 'plików'}`;
|
||||||
|
|
||||||
|
// Take only top 10 most recently used/uploaded
|
||||||
|
const top10 = files.slice(0, 10);
|
||||||
|
|
||||||
|
top10.forEach(file => {
|
||||||
|
const li = document.createElement('li');
|
||||||
|
li.className = 'queue-item';
|
||||||
|
|
||||||
|
const safeFilename = file.filename.replace(/'/g, "\\'");
|
||||||
|
|
||||||
|
li.innerHTML = `
|
||||||
|
<div class="queue-index"><i data-lucide="file-audio"></i></div>
|
||||||
|
<div class="queue-track-info" style="flex: 1; min-width: 0;">
|
||||||
|
<div class="queue-track-title" title="${file.filename}" style="white-space: nowrap; overflow: hidden; text-overflow: ellipsis;">${file.filename}</div>
|
||||||
|
<div class="queue-track-artist">${file.size_mb} MB</div>
|
||||||
|
</div>
|
||||||
|
<div class="queue-item-actions" style="display: flex; gap: 6px; align-items: center;">
|
||||||
|
<button class="btn btn-primary" style="padding: 4px 10px; font-size: 0.8rem; display: flex; align-items: center; gap: 4px;" onclick="playUploadedFile('${safeFilename}')" title="Dodaj do kolejki">
|
||||||
|
<i data-lucide="plus"></i> Dodaj
|
||||||
</button>
|
</button>
|
||||||
<button class="btn-action-icon delete" onclick="deleteUploadedFile('${safeFilename}')" title="Usuń z serwera">
|
<button class="btn-action-icon delete" onclick="deleteUploadedFile('${safeFilename}')" title="Usuń z serwera">
|
||||||
<i data-lucide="trash-2"></i>
|
<i data-lucide="trash-2"></i>
|
||||||
@@ -886,6 +962,11 @@ function renderUploads(files) {
|
|||||||
`;
|
`;
|
||||||
uploadsList.appendChild(li);
|
uploadsList.appendChild(li);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (uploadsModal && uploadsModal.style.display !== 'none') {
|
||||||
|
renderModalUploads(allUploadedFiles);
|
||||||
|
}
|
||||||
|
|
||||||
lucide.createIcons();
|
lucide.createIcons();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+23
-1
@@ -139,7 +139,7 @@
|
|||||||
<input type="text" id="track-query" class="premium-input" placeholder="Wklej link YouTube lub wpisz wyszukiwanie..." required>
|
<input type="text" id="track-query" class="premium-input" placeholder="Wklej link YouTube lub wpisz wyszukiwanie..." required>
|
||||||
</div>
|
</div>
|
||||||
<button type="submit" id="btn-add-track" class="btn btn-primary">
|
<button type="submit" id="btn-add-track" class="btn btn-primary">
|
||||||
<span id="btn-add-text"><i data-lucide="music-3"></i> Dodaj</span>
|
<span id="btn-add-text"><i data-lucide="plus"></i> Dodaj</span>
|
||||||
<span id="btn-add-spinner" class="spinner" style="display: none;"></span>
|
<span id="btn-add-spinner" class="spinner" style="display: none;"></span>
|
||||||
</button>
|
</button>
|
||||||
</form>
|
</form>
|
||||||
@@ -173,6 +173,9 @@
|
|||||||
</div>
|
</div>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
|
<button type="button" id="btn-open-all-uploads" class="btn btn-secondary" style="width: 100%; margin-top: 10px; display: flex; align-items: center; justify-content: center; gap: 8px;">
|
||||||
|
<i data-lucide="folder-open"></i> Pokaż wszystkie pliki na serwerze (<span id="btn-all-uploads-count">0</span>)
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Queue List Panel -->
|
<!-- Queue List Panel -->
|
||||||
@@ -234,6 +237,25 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- All Uploads Modal -->
|
||||||
|
<div class="modal-overlay" id="uploads-modal" style="display: none;">
|
||||||
|
<div class="modal-card glass-card" style="max-width: 650px;">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h2 class="card-title"><i data-lucide="folder-up"></i> Wszystkie pliki na serwerze</h2>
|
||||||
|
<button class="btn-icon" id="btn-close-uploads" title="Zamknij"><i data-lucide="x"></i></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body" style="max-height: 70vh; overflow-y: auto;">
|
||||||
|
<p class="settings-desc">Pełna lista plików zapisanych w serwerowej bazie danych (posortowana od ostatnio używanych / przesłanych).</p>
|
||||||
|
<ul class="queue-list" id="modal-uploads-list">
|
||||||
|
<div class="empty-queue-message" id="empty-modal-uploads-msg">
|
||||||
|
<i data-lucide="folder-open"></i>
|
||||||
|
<p>Brak przesłanych plików na serwerze.</p>
|
||||||
|
</div>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Notification Toast -->
|
<!-- Notification Toast -->
|
||||||
<div class="toast-container" id="toast-container"></div>
|
<div class="toast-container" id="toast-container"></div>
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -988,7 +988,7 @@ body {
|
|||||||
background: rgba(255, 255, 255, 0.02);
|
background: rgba(255, 255, 255, 0.02);
|
||||||
}
|
}
|
||||||
|
|
||||||
#btn-close-settings {
|
#btn-close-settings, #btn-close-uploads {
|
||||||
width: 42px;
|
width: 42px;
|
||||||
height: 42px;
|
height: 42px;
|
||||||
background: rgba(255, 255, 255, 0.12);
|
background: rgba(255, 255, 255, 0.12);
|
||||||
@@ -1002,7 +1002,7 @@ body {
|
|||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
#btn-close-settings:hover {
|
#btn-close-settings:hover, #btn-close-uploads:hover {
|
||||||
background: rgba(239, 68, 68, 0.25);
|
background: rgba(239, 68, 68, 0.25);
|
||||||
border-color: rgba(239, 68, 68, 0.6);
|
border-color: rgba(239, 68, 68, 0.6);
|
||||||
color: #ff6b6b;
|
color: #ff6b6b;
|
||||||
|
|||||||
@@ -510,14 +510,17 @@ async def get_uploads():
|
|||||||
uploads_dir = "uploads"
|
uploads_dir = "uploads"
|
||||||
os.makedirs(uploads_dir, exist_ok=True)
|
os.makedirs(uploads_dir, exist_ok=True)
|
||||||
files = []
|
files = []
|
||||||
for f in sorted(os.listdir(uploads_dir)):
|
for f in os.listdir(uploads_dir):
|
||||||
filepath = os.path.join(uploads_dir, f)
|
filepath = os.path.join(uploads_dir, f)
|
||||||
if os.path.isfile(filepath) and not f.startswith("."):
|
if os.path.isfile(filepath) and not f.startswith("."):
|
||||||
size_mb = round(os.path.getsize(filepath) / (1024 * 1024), 2)
|
size_mb = round(os.path.getsize(filepath) / (1024 * 1024), 2)
|
||||||
|
mtime = os.path.getmtime(filepath)
|
||||||
files.append({
|
files.append({
|
||||||
"filename": f,
|
"filename": f,
|
||||||
"size_mb": size_mb
|
"size_mb": size_mb,
|
||||||
|
"mtime": mtime
|
||||||
})
|
})
|
||||||
|
files.sort(key=lambda x: x["mtime"], reverse=True)
|
||||||
return {"files": files}
|
return {"files": files}
|
||||||
|
|
||||||
@app.post("/api/upload")
|
@app.post("/api/upload")
|
||||||
@@ -567,6 +570,7 @@ async def api_play_file(req: PlayFileRequest):
|
|||||||
raise HTTPException(status_code=404, detail="Plik nie istnieje na serwerze")
|
raise HTTPException(status_code=404, detail="Plik nie istnieje na serwerze")
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
os.utime(filepath, None)
|
||||||
player = await YTDLSource.from_file(filepath, loop=bot.loop)
|
player = await YTDLSource.from_file(filepath, loop=bot.loop)
|
||||||
res = await music_cog.enqueue_track(guild_id, player, from_web=True)
|
res = await music_cog.enqueue_track(guild_id, player, from_web=True)
|
||||||
await broadcast_status()
|
await broadcast_status()
|
||||||
|
|||||||
Reference in new issue
Block a user