179 lines
8.9 KiB
HTML
Executable File
179 lines
8.9 KiB
HTML
Executable File
---
|
|
layout: default
|
|
title: "Visualizando Projeto"
|
|
---
|
|
|
|
<div id="project-root">
|
|
<div class="section has-text-centered py-6">
|
|
<button class="button is-loading is-large is-ghost">Carregando detalhes do projeto...</button>
|
|
</div>
|
|
</div>
|
|
|
|
<script type="module">
|
|
import { InstrumentFactory } from '{{ "/assets/js/audio/InstrumentFactory.js" | relative_url }}';
|
|
|
|
document.addEventListener("DOMContentLoaded", () => {
|
|
const factory = new InstrumentFactory();
|
|
const params = new URLSearchParams(window.location.search);
|
|
const projectId = params.get('id');
|
|
|
|
if (!projectId) {
|
|
window.location.href = '{{ "/projetos/" | relative_url }}';
|
|
return;
|
|
}
|
|
|
|
fetch('{{ "src_mmpSearch/saida_analises/db_final_completo.json" | relative_url }}')
|
|
.then(r => r.json())
|
|
.then(data => {
|
|
// Busca o projeto pelo nome do arquivo (sem extensão ou com .ogg)
|
|
const p = data.find(item =>
|
|
item.file === projectId ||
|
|
(item.arquivo && item.arquivo.replace('.ogg', '').replace('.mp3', '') === projectId)
|
|
);
|
|
|
|
if (!p) {
|
|
document.getElementById('project-root').innerHTML = `
|
|
<div class="container has-text-centered">
|
|
<h1 class="title is-2 mt-6">😢 Projeto não encontrado</h1>
|
|
<p>O arquivo <code>${projectId}</code> não foi localizado na base de dados.</p>
|
|
<a href="{{ '/projetos/' | relative_url }}" class="button is-info mt-4">Voltar para a lista</a>
|
|
</div>`;
|
|
return;
|
|
}
|
|
|
|
renderProjectTemplate(p, factory);
|
|
})
|
|
.catch(err => {
|
|
console.error("Erro ao carregar JSON:", err);
|
|
document.getElementById('project-root').innerHTML = "<div class='notification is-danger'>Erro ao carregar dados do projeto.</div>";
|
|
});
|
|
});
|
|
|
|
function renderProjectTemplate(page, factory) {
|
|
const root = document.getElementById('project-root');
|
|
const creationUrl = `{{ '/mmpSearch/creation.html?project=' | relative_url }}${page.file}`;
|
|
const embedUrl = `${creationUrl}&embed=true`;
|
|
const audioFilePath = `{{ 'src_mmpSearch/wav/' | relative_url }}${page.file}.ogg`;
|
|
|
|
let tagsHtml = '';
|
|
if (page.tags) {
|
|
tagsHtml = `
|
|
<details class="card mb-4" open style="background-color: #f0f8ff; border: 1px solid #cfe8fc; border-radius: 8px;">
|
|
<summary class="card-header" style="cursor: pointer; background-color: #e1f0fa; border-bottom: 1px solid #cfe8fc;">
|
|
<p class="card-header-title" style="color: #205081">🏷️ Tags do Projeto</p>
|
|
</summary>
|
|
<div class="card-content">
|
|
${Object.entries(page.tags).map(([cat, values]) => {
|
|
if (!values || values.length === 0) return '';
|
|
return `
|
|
<div class="mb-3">
|
|
<strong class="is-size-7 is-uppercase" style="color: #5b7da3">${cat}:</strong>
|
|
<div class="tags mt-2">
|
|
${values.map(v => `<span class="tag is-link is-light">${v}</span>`).join('')}
|
|
</div>
|
|
</div>`;
|
|
}).join('')}
|
|
</div>
|
|
</details>`;
|
|
}
|
|
|
|
let tracksHtml = '';
|
|
if (page.tracks && page.tracks.length > 0) {
|
|
tracksHtml = `
|
|
<details class="card mb-4" open style="background-color: #f0f8ff; border: 1px solid #cfe8fc; border-radius: 8px;">
|
|
<summary class="card-header" style="cursor: pointer; background-color: #e1f0fa; border-bottom: 1px solid #cfe8fc;">
|
|
<p class="card-header-title" style="color: #205081">🎚️ Instrumentos & Padrões</p>
|
|
</summary>
|
|
<div class="card-content" style="padding: 1.5rem">
|
|
${page.tracks.map(track => {
|
|
const instruments = track.instruments || [track];
|
|
return `
|
|
<div class="box p-0 mb-4" style="background-color: #fff; border: 1px solid #cfe8fc; border-radius: 8px; overflow: hidden;">
|
|
<div class="px-4 py-3" style="background-color: #eef6fc; border-bottom: 1px solid #cfe8fc;">
|
|
<span class="tag is-link is-light" style="font-weight: 600">📂 ${track.bassline_name || 'Track Principal'}</span>
|
|
</div>
|
|
<div class="p-4">
|
|
${instruments.map(inst => renderInstrumentBlock(inst)).join('')}
|
|
</div>
|
|
</div>`;
|
|
}).join('')}
|
|
</div>
|
|
</details>`;
|
|
}
|
|
|
|
root.innerHTML = `
|
|
<div class="publication">
|
|
<div class="container">
|
|
<br />
|
|
<div class="box has-background-white-ter mb-5" style="border-top: 4px solid #3273dc; padding: 8px 16px; display: flex; align-items: center; justify-content: space-between;">
|
|
<div style="display: flex; align-items: center; gap: 15px">
|
|
<h1 class="title is-5 m-0"><code>${page.file}</code></h1>
|
|
${page.bpm ? `<span class="tag is-dark is-small">🎵 ${page.bpm}</span>` : ''}
|
|
</div>
|
|
<div style="display: flex; align-items: center; gap: 15px">
|
|
<audio controls style="height: 25px; max-width: 220px;">
|
|
<source src="${audioFilePath}" type="audio/ogg">
|
|
</audio>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="columns">
|
|
<div class="column is-8">${tagsHtml} ${tracksHtml}</div>
|
|
<div class="column is-4">
|
|
<div class="box has-background-info-light" style="position: sticky; top: 20px">
|
|
<h3 class="title is-6 has-text-info mb-3">🛠️ Editor Colaborativo</h3>
|
|
<a href="${creationUrl}" target="_blank" class="button is-info is-fullwidth is-medium mb-4 shadow-sm">Abrir no MMPCreator</a>
|
|
<div class="mt-4 is-hidden-mobile">
|
|
<p class="title is-7 has-text-info-dark mb-2">Prévia do Editor:</p>
|
|
<iframe src="${embedUrl}" style="width: 100%; height: 300px; border: 1px solid #ccc; border-radius: 4px; background: #fff;"></iframe>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>`;
|
|
|
|
// Ativa os botões de teste de synth
|
|
document.querySelectorAll('.js-play-synth-btn').forEach(btn => {
|
|
btn.addEventListener('click', () => {
|
|
const data = JSON.parse(btn.dataset.params);
|
|
factory.play(data);
|
|
});
|
|
});
|
|
}
|
|
|
|
function renderInstrumentBlock(inst) {
|
|
const isSample = (inst.instrument_name && inst.instrument_name.toLowerCase() === 'audiofileprocessor') || !!inst.audiofileprocessor;
|
|
let displayName = inst.instrument_name;
|
|
|
|
if (isSample && inst.patterns && inst.patterns.length > 0) {
|
|
displayName = inst.patterns[0].name ? inst.patterns[0].name.replace(/\.(ogg|mp3|flac|wav)$/i, '') : displayName;
|
|
}
|
|
|
|
return `
|
|
<div class="instrument-wrapper mb-4 p-2" style="border-left: 3px solid #3298dc; background: #fff">
|
|
<details open>
|
|
<summary style="cursor: pointer; margin-bottom: 0.5rem">
|
|
<span class="tag is-info is-light"><strong>${displayName}</strong> ${isSample ? '' : '<span class="ml-1" style="font-size: 0.7em">(Synth 🎹)</span>'}</span>
|
|
</summary>
|
|
${(inst.patterns || []).map(pat => renderPatternSteps(pat)).join('')}
|
|
</details>
|
|
<div class="playback-controls mt-2 pl-4">
|
|
${isSample ?
|
|
(inst.audiofileprocessor?.src ? `<audio controls style="height: 30px; width: 250px;"><source src="{{ '/src/samples/' | relative_url }}${inst.audiofileprocessor.src}" type="audio/ogg"></audio>` : '<p class="is-size-7 has-text-grey-light">Sample não disponível</p>')
|
|
: `<button class="button is-small is-primary is-outlined js-play-synth-btn" data-params='${JSON.stringify(inst)}'>Testar Plugin</button>`
|
|
}
|
|
</div>
|
|
</div>`;
|
|
}
|
|
|
|
function renderPatternSteps(pattern) {
|
|
if (!pattern.steps || pattern.steps.length === 0) return '';
|
|
return `
|
|
<div class="mt-2 ml-4" style="display: flex; flex-wrap: wrap; gap: 4px">
|
|
${pattern.steps.map(step => `
|
|
<div style="width: 5px; height: 10px; background-color: ${step ? '#4caf50' : '#e0e0e0'}; border-radius: 1px;"></div>
|
|
`).join('')}
|
|
</div>`;
|
|
}
|
|
</script> |