21 KiB
Executable File
21 KiB
Executable File
layout, title, permalink
| layout | title | permalink |
|---|---|---|
| default | MMPSearch - Envie seu projeto | /envie_seu_projeto/ |
{% include modal_login.html %}
<div class="tabs is-centered is-boxed is-medium mb-6">
{% include sidebar.html %}
</div>
<div class="columns is-centered">
<div class="column is-8 has-text-centered">
<h1 class="title is-3 has-text-grey-dark mb-3">
<span class="icon has-text-info mr-2"><i class="fa-solid fa-cloud-arrow-up"></i></span>
Enviar Projeto
</h1>
<p class="subtitle is-6 has-text-grey">
Contribua com a comunidade! Envie seus arquivos <code>.mmp</code> ou <code>.mmpz</code>.
</p>
<div style="width: 60px; height: 4px; background-color: #3273dc; margin: 1rem auto; border-radius: 2px;"></div>
</div>
</div>
<div class="columns is-centered">
<div class="column is-8">
<div id="auth-loading" class="box has-text-centered p-6">
<span class="icon is-large has-text-info mb-3"><i class="fa-solid fa-circle-notch fa-spin fa-3x"></i></span>
<p class="subtitle is-5">Verificando permissões...</p>
</div>
<div id="login-warning" class="box has-text-centered p-6 is-hidden" style="background-color: #fffdf5; border: 1px solid #ffe08a;">
<span class="icon is-large has-text-warning mb-3"><i class="fa-solid fa-lock fa-3x"></i></span>
<h3 class="title is-4 has-text-grey-dark">Login Necessário</h3>
<p class="mb-5">Você precisa estar logado para enviar projetos e samples para a comunidade.</p>
<div class="buttons is-centered">
<a href="#" class="button is-info is-medium js-trigger-login">
<span class="icon"><i class="fa-solid fa-right-to-bracket"></i></span>
<span>Fazer Login / Cadastrar</span>
</a>
</div>
</div>
<div id="upload-content" class="box p-5 is-hidden" style="background-color: #f0f8ff; border: 1px solid #cfe8fc; border-radius: 12px;">
<form id="upload-project-form">
<div class="field mb-5">
<label class="label has-text-grey-dark">Arquivo do Projeto (LMMS)</label>
<div class="file-upload-wrapper" id="drop-zone">
<input class="file-upload-input" type="file" name="project_file" id="project_file" accept=".mmp, .mmpz" required>
<div class="drag-text has-text-centered">
<span class="icon is-large has-text-info mb-2"><i class="fa-solid fa-file-audio fa-3x"></i></span>
<h3 class="title is-5 has-text-grey-dark mb-1">Arraste e solte o arquivo aqui</h3>
<p class="is-size-7 has-text-grey">ou clique para selecionar (.mmp, .mmpz)</p>
<p id="file-name-display" class="tag is-info is-light mt-3 is-hidden"></p>
</div>
</div>
</div>
<div class="columns">
<div class="column is-6">
<div class="field">
<label class="label has-text-grey-dark">Nome do Projeto</label>
<div class="control has-icons-left">
<input class="input" type="text" placeholder="Ex: Manda a maladeza" required>
<span class="icon is-small is-left">
<i class="fa-solid fa-music"></i>
</span>
</div>
</div>
</div>
<div class="column is-6">
<div class="field">
<label class="label has-text-grey-dark">Qual o seu vulgo?</label>
<div class="control has-icons-left">
<input class="input" type="text" placeholder="Seu nome ou nick" required>
<span class="icon is-small is-left">
<i class="fa-solid fa-user"></i>
</span>
</div>
</div>
</div>
</div>
<div class="columns">
<div class="column is-4">
<div class="field">
<label class="label has-text-grey-dark">BPM</label>
<div class="control has-icons-left">
<input class="input" type="number" placeholder="128" min="1" max="999">
<span class="icon is-small is-left">
<i class="fa-solid fa-gauge-high"></i>
</span>
</div>
</div>
</div>
<div class="column is-8">
<div class="field">
<label class="label has-text-grey-dark">Tags (Opcional)</label>
<div class="control has-icons-left">
<input class="input" type="text" placeholder="Ex: rap, hip hop, boom bap, remix">
<span class="icon is-small is-left">
<i class="fa-solid fa-tags"></i>
</span>
</div>
<p class="help">Separe por vírgulas.</p>
</div>
</div>
</div>
<div class="field">
<label class="label has-text-grey-dark">Descrição</label>
<div class="control">
<textarea class="textarea" placeholder="Conte um pouco sobre como você criou esse projeto, plugins usados, etc." rows="3"></textarea>
</div>
</div>
<div class="field mb-5">
<label class="label has-text-grey-dark">Preview de Áudio (Opcional)</label>
<div class="file has-name is-fullwidth">
<label class="file-label">
<input class="file-input" type="file" name="audio_preview" accept=".wav, .mp3, .ogg">
<span class="file-cta">
<span class="file-icon">
<i class="fa-solid fa-upload"></i>
</span>
<span class="file-label">
Escolher arquivo de áudio...
</span>
</span>
<span class="file-name has-text-grey-light">
Nenhum arquivo selecionado
</span>
</label>
</div>
<p class="help">Envie um .mp3 ou .wav para que as pessoas possam ouvir antes de baixar.</p>
</div>
<div class="field mt-5">
<div class="control">
<button type="submit" class="button is-info is-fullwidth is-medium shadow-sm" id="submit-btn">
<span class="icon"><i class="fa-solid fa-paper-plane"></i></span>
<span>Enviar Projeto</span>
</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
Sucesso!
Projeto Enviado!
Obrigado por contribuir. Seu projeto está sendo processado e em breve aparecerá na lista.
Arquivos Externos Detectados
<section class="modal-card-body">
<div class="content is-small mb-4">
<p>Este projeto utiliza samples que não são nativos do LMMS. Para que o som saia correto, precisamos que você envie os arquivos correspondentes.</p>
</div>
<form id="resolve-form">
<input type="hidden" name="project_file" id="hidden-project-name">
<div class="table-container">
<table class="table is-fullwidth is-striped is-hoverable">
<thead>
<tr>
<th>Arquivo Faltante (XML)</th>
<th style="width: 50px;">Status</th>
<th style="width: 120px;">Ação</th>
</tr>
</thead>
<tbody id="missing-files-table-body">
</tbody>
</table>
</div>
<div class="notification is-danger is-light is-hidden" id="resolve-error-msg"></div>
<button type="submit" class="button is-success is-fullwidth mt-4" id="resolve-btn" disabled>
<span class="icon"><i class="fa-solid fa-check"></i></span>
<span>Enviar Todos e Processar</span>
</button>
</form>
</section>
Erro ao conectar com servidor.
"; } // ------------------------------------ const dropZone = document.getElementById('drop-zone'); const fileInput = document.getElementById('project_file'); const fileNameDisplay = document.getElementById('file-name-display'); const dragTextTitle = dropZone.querySelector('.title'); const successModal = document.getElementById('success-modal'); const resolveModal = document.getElementById('resolve-modal'); const closeBtns = document.querySelectorAll('.delete, #close-success-modal, .modal-background'); const mainForm = document.getElementById('upload-project-form'); const resolveForm = document.getElementById('resolve-form'); const submitBtn = document.getElementById('submit-btn'); const resolveBtn = document.getElementById('resolve-btn'); // Visual do Dropzone ['dragenter', 'dragover'].forEach(evt => dropZone.addEventListener(evt, (e) => { e.preventDefault(); dropZone.classList.add('dragover'); })); ['dragleave', 'drop'].forEach(evt => dropZone.addEventListener(evt, (e) => { dropZone.classList.remove('dragover'); })); fileInput.addEventListener('change', () => { if (fileInput.files.length > 0) { fileNameDisplay.textContent = fileInput.files[0].name; fileNameDisplay.classList.remove('is-hidden'); dragTextTitle.textContent = "Arquivo Pronto!"; dropZone.style.borderColor = "#4caf50"; dropZone.style.backgroundColor = "#f0fff4"; } }); document.querySelectorAll('.file-input').forEach(input => { input.addEventListener('change', () => { if (input.files.length > 0) { const nameContainer = input.parentElement.querySelector('.file-name'); if (nameContainer) { nameContainer.textContent = input.files.length > 1 ? `${input.files.length} arquivos selecionados` : input.files[0].name; } } }); }); closeBtns.forEach(btn => { btn.addEventListener('click', () => { successModal.classList.remove('is-active'); resolveModal.classList.remove('is-active'); document.documentElement.classList.remove('is-clipped'); }); }); // SUBMISSÃO PRINCIPAL mainForm.addEventListener('submit', async (e) => { e.preventDefault(); submitBtn.classList.add('is-loading'); const formData = new FormData(mainForm); try { // FIX: Usando caminho relativo (/api/upload) em vez da porta 33002 const response = await fetch('/api/upload', { method: 'POST', body: formData }); const result = await response.json(); submitBtn.classList.remove('is-loading'); if (response.status === 200) { mostrarSucesso(); mainForm.reset(); resetDropzone(); } else if (response.status === 202) { mostrarResolveModal(result); } else { alert('Erro: ' + (result.error || result.message || 'Ocorreu um erro desconhecido.')); } } catch (error) { console.error('Erro:', error); alert('Erro de conexão com o servidor.'); submitBtn.classList.remove('is-loading'); } }); // SUBMISSÃO RESOLVE resolveForm.addEventListener('submit', async (e) => { e.preventDefault(); resolveBtn.classList.add('is-loading'); const formData = new FormData(resolveForm); try { // FIX: Usando caminho relativo const response = await fetch('/api/upload/resolve', { method: 'POST', body: formData }); const result = await response.json(); resolveBtn.classList.remove('is-loading'); if (response.ok) { resolveModal.classList.remove('is-active'); mostrarSucesso(); mainForm.reset(); resetDropzone(); } else { alert('Erro ao enviar samples: ' + (result.error || 'Erro desconhecido')); } } catch (error) { console.error(error); alert('Erro ao enviar samples.'); resolveBtn.classList.remove('is-loading'); } }); function mostrarSucesso() { successModal.classList.add('is-active'); document.documentElement.classList.add('is-clipped'); } function mostrarResolveModal(data) { document.getElementById('hidden-project-name').value = data.project_file; const tbody = document.getElementById('missing-files-table-body'); tbody.innerHTML = ''; const resolveBtn = document.getElementById('resolve-btn'); resolveBtn.disabled = true; let totalFiles = data.missing_files.length; let filledFiles = 0; data.missing_files.forEach((originalName, index) => { const tr = document.createElement('tr'); const tdName = document.createElement('td'); tdName.style.verticalAlign = "middle"; tdName.innerHTML = `${originalName}`; const tdStatus = document.createElement('td'); tdStatus.style.verticalAlign = "middle"; tdStatus.style.textAlign = "center"; tdStatus.innerHTML = ``; const tdAction = document.createElement('td'); tdAction.style.textAlign = "right"; const fileInput = document.createElement('input'); fileInput.type = 'file'; fileInput.name = originalName; fileInput.style.display = 'none'; fileInput.accept = ".wav, .mp3, .ogg, .flac, .ds"; const uploadLabel = document.createElement('label'); uploadLabel.className = 'button is-small is-info is-outlined'; uploadLabel.innerHTML = ``; uploadLabel.addEventListener('click', (e) => { e.preventDefault(); fileInput.click(); }); fileInput.addEventListener('change', () => { if (fileInput.files.length > 0) { uploadLabel.className = 'button is-small is-success'; uploadLabel.innerHTML = ``; const icon = tdStatus.querySelector('.status-icon'); icon.innerHTML = ``; icon.classList.remove('has-text-grey-light'); icon.classList.add('has-text-success'); if (!fileInput.dataset.filled) { fileInput.dataset.filled = "true"; filledFiles++; } if (filledFiles >= totalFiles) { resolveBtn.disabled = false; resolveBtn.classList.remove('is-outlined'); } } }); tdAction.appendChild(fileInput); tdAction.appendChild(uploadLabel); tr.appendChild(tdName); tr.appendChild(tdStatus); tr.appendChild(tdAction); tbody.appendChild(tr); }); document.getElementById('resolve-modal').classList.add('is-active'); document.documentElement.classList.add('is-clipped'); } function resetDropzone() { fileNameDisplay.classList.add('is-hidden'); dragTextTitle.textContent = "Arraste e solte o arquivo aqui"; dropZone.style.borderColor = "#3273dc"; dropZone.style.backgroundColor = "#fff"; } }); </script>