173 lines
6.4 KiB
HTML
Executable File
173 lines
6.4 KiB
HTML
Executable File
---
|
|
layout: default
|
|
title: "Visualizando Projeto"
|
|
---
|
|
|
|
<div id="project-loader" class="section has-text-centered">
|
|
<button class="button is-loading is-large is-ghost">
|
|
Carregando Projeto...
|
|
</button>
|
|
</div>
|
|
|
|
<div id="project-content" class="publication is-hidden">
|
|
<div class="container">
|
|
<br />
|
|
<div class="tabs is-centered is-boxed is-medium mb-6">
|
|
{% include sidebar.html %}
|
|
</div>
|
|
|
|
<div
|
|
id="project-header"
|
|
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>
|
|
|
|
<div class="columns">
|
|
<div class="column is-8" id="main-content"></div>
|
|
<div class="column is-4" id="sidebar-content"></div>
|
|
</div>
|
|
</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(
|
|
'{{ "/mmpSearch/src_mmpSearch/saida_analises/db_final_completo.json" | relative_url }}',
|
|
)
|
|
.then((r) => r.json())
|
|
.then((data) => {
|
|
const project = data.find(
|
|
(p) =>
|
|
p.file === projectId ||
|
|
p.arquivo === projectId + ".ogg" ||
|
|
p.arquivo === projectId,
|
|
);
|
|
if (!project) {
|
|
document.getElementById("project-loader").innerHTML =
|
|
"<h1 class='title'>Projeto não encontrado 😢</h1>";
|
|
return;
|
|
}
|
|
renderProjectPage(project, factory);
|
|
});
|
|
});
|
|
|
|
function renderProjectPage(p, factory) {
|
|
const header = document.getElementById("project-header");
|
|
const main = document.getElementById("main-content");
|
|
const sidebar = document.getElementById("sidebar-content");
|
|
|
|
// 1. Render Header
|
|
header.innerHTML = `
|
|
<div style="display: flex; align-items: center; gap: 15px">
|
|
<h1 class="title is-5 m-0"><code>${p.file || p.arquivo}</code></h1>
|
|
${p.bpm ? `<span class="tag is-dark">🎵 ${p.bpm}</span>` : ""}
|
|
</div>
|
|
<div style="display: flex; align-items: center; gap: 15px">
|
|
<audio controls style="height: 25px;">
|
|
<source src="{{ '/src_mmpSearch/wav/' | relative_url }}${p.file}.ogg" type="audio/ogg">
|
|
</audio>
|
|
</div>
|
|
`;
|
|
|
|
// 2. Render Tags
|
|
let tagsHtml = "";
|
|
if (p.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;"><p class="card-header-title">🏷️ Tags</p></summary>
|
|
<div class="card-content">
|
|
${Object.entries(p.tags)
|
|
.map(
|
|
([cat, values]) => `
|
|
<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>`;
|
|
}
|
|
|
|
// 3. Render Tracks/Instruments
|
|
const 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;"><p class="card-header-title">🎚️ Instrumentos</p></summary>
|
|
<div class="card-content">
|
|
${(p.tracks || [])
|
|
.map(
|
|
(track) => `
|
|
<div class="box mb-4" style="border-left: 5px solid #3298dc;">
|
|
<span class="tag is-link is-light mb-2">📂 ${track.bassline_name || "Track"}</span>
|
|
${(track.instruments || [track])
|
|
.map(
|
|
(inst) => `
|
|
<div class="instrument-wrapper p-2 mb-2" style="background: #fff; border-radius: 4px;">
|
|
<strong>${inst.instrument_name}</strong>
|
|
<div class="mt-2">${renderPatternGrid(inst.patterns)}</div>
|
|
<button class="button is-small is-primary is-outlined mt-2 js-play-synth" data-params='${JSON.stringify(inst)}'>Testar Plugin</button>
|
|
</div>
|
|
`,
|
|
)
|
|
.join("")}
|
|
</div>
|
|
`,
|
|
)
|
|
.join("")}
|
|
</div>
|
|
</details>
|
|
`;
|
|
|
|
main.innerHTML = tagsHtml + tracksHtml;
|
|
|
|
// 4. Sidebar Editor
|
|
const creationUrl = `{{ '/mmpSearch/creation.html?project=' | relative_url }}${p.file}`;
|
|
sidebar.innerHTML = `
|
|
<div class="box has-background-info-light" style="position: sticky; top: 20px">
|
|
<h3 class="title is-6 has-text-info">🛠️ MMPCreator</h3>
|
|
<a href="${creationUrl}" target="_blank" class="button is-info is-fullwidth mb-4">Abrir no Editor</a>
|
|
<iframe src="${creationUrl}&embed=true" style="width: 100%; height: 300px; border-radius: 4px; background: #fff;"></iframe>
|
|
</div>
|
|
`;
|
|
|
|
document.getElementById("project-loader").classList.add("is-hidden");
|
|
document.getElementById("project-content").classList.remove("is-hidden");
|
|
|
|
// Event Listeners para Áudio
|
|
document.querySelectorAll(".js-play-synth").forEach((btn) => {
|
|
btn.addEventListener("click", () =>
|
|
factory.play(JSON.parse(btn.dataset.params)),
|
|
);
|
|
});
|
|
}
|
|
|
|
function renderPatternGrid(patterns) {
|
|
if (!patterns) return "";
|
|
return patterns
|
|
.map((p) => {
|
|
const steps = p.steps || [];
|
|
return `<div style="display: flex; gap: 2px; margin-bottom: 4px;">
|
|
${steps.map((s) => `<div style="width: 6px; height: 12px; background: ${s ? "#4caf50" : "#e0e0e0"}; border-radius: 1px;"></div>`).join("")}
|
|
</div>`;
|
|
})
|
|
.join("");
|
|
}
|
|
</script>
|