melhorando build
Deploy / Deploy (push) Successful in 3m7s
Details
Deploy / Deploy (push) Successful in 3m7s
Details
This commit is contained in:
parent
d9eecd41b1
commit
f2ab417cd8
|
|
@ -12,3 +12,4 @@ venv
|
||||||
.gitea
|
.gitea
|
||||||
src
|
src
|
||||||
assets/js/creations/server/data
|
assets/js/creations/server/data
|
||||||
|
_data
|
||||||
|
|
|
||||||
|
|
@ -1,179 +1,119 @@
|
||||||
---
|
---
|
||||||
layout: default
|
layout: default
|
||||||
title: "Visualizando Projeto"
|
title: "Detalhes do Projeto"
|
||||||
---
|
---
|
||||||
|
|
||||||
<div id="project-root">
|
<div id="project-root">
|
||||||
<div class="section has-text-centered py-6">
|
<div class="section has-text-centered py-6">
|
||||||
<button class="button is-loading is-large is-ghost">Carregando detalhes do projeto...</button>
|
<button class="button is-loading is-large is-ghost">
|
||||||
</div>
|
Carregando projeto...
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import { InstrumentFactory } from '{{ "/assets/js/audio/InstrumentFactory.js" | relative_url }}';
|
import { InstrumentFactory } from '{{ "/assets/js/audio/InstrumentFactory.js" | relative_url }}';
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", () => {
|
document.addEventListener("DOMContentLoaded", () => {
|
||||||
const factory = new InstrumentFactory();
|
const factory = new InstrumentFactory();
|
||||||
const params = new URLSearchParams(window.location.search);
|
const params = new URLSearchParams(window.location.search);
|
||||||
const projectId = params.get('id');
|
const projectId = params.get("id");
|
||||||
|
|
||||||
if (!projectId) {
|
if (!projectId) {
|
||||||
window.location.href = '{{ "/projetos/" | relative_url }}';
|
window.location.href = '{{ "/projetos/" | relative_url }}';
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
fetch('{{ "src_mmpSearch/saida_analises/db_final_completo.json" | relative_url }}')
|
fetch(
|
||||||
.then(r => r.json())
|
'{{ "src_mmpSearch/saida_analises/db_final_completo.json" | relative_url }}',
|
||||||
.then(data => {
|
)
|
||||||
// Busca o projeto pelo nome do arquivo (sem extensão ou com .ogg)
|
.then((r) => r.json())
|
||||||
const p = data.find(item =>
|
.then((data) => {
|
||||||
item.file === projectId ||
|
const p = data.find(
|
||||||
(item.arquivo && item.arquivo.replace('.ogg', '').replace('.mp3', '') === projectId)
|
(item) =>
|
||||||
);
|
item.file === projectId ||
|
||||||
|
(item.arquivo &&
|
||||||
|
item.arquivo.replace(".ogg", "").replace(".mp3", "") ===
|
||||||
|
projectId),
|
||||||
|
);
|
||||||
|
|
||||||
if (!p) {
|
if (!p) {
|
||||||
document.getElementById('project-root').innerHTML = `
|
document.getElementById("project-root").innerHTML =
|
||||||
<div class="container has-text-centered">
|
`<div class="container py-6"><h1 class="title">Projeto não encontrado.</h1><a href="{{ '/projetos/' | relative_url }}">Voltar</a></div>`;
|
||||||
<h1 class="title is-2 mt-6">😢 Projeto não encontrado</h1>
|
return;
|
||||||
<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>
|
renderDetails(p, factory);
|
||||||
</div>`;
|
});
|
||||||
return;
|
});
|
||||||
}
|
|
||||||
|
|
||||||
renderProjectTemplate(p, factory);
|
function renderDetails(p, factory) {
|
||||||
})
|
const root = document.getElementById("project-root");
|
||||||
.catch(err => {
|
const fileName = p.file || p.arquivo || "sem-nome";
|
||||||
console.error("Erro ao carregar JSON:", err);
|
const creationUrl = `{{ 'creation.html?project=' | relative_url }}${fileName}`;
|
||||||
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 = `
|
root.innerHTML = `
|
||||||
<div class="publication">
|
<div class="publication"><div class="container"><br />
|
||||||
<div class="container">
|
<div class="box has-background-white-ter mb-5" style="border-top: 4px solid #3273dc; display: flex; align-items: center; justify-content: space-between; padding: 10px 20px;">
|
||||||
<br />
|
<div style="display: flex; align-items: center; gap: 15px">
|
||||||
<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;">
|
<h1 class="title is-5 m-0"><code>${fileName}</code></h1>
|
||||||
<div style="display: flex; align-items: center; gap: 15px">
|
<span class="tag is-dark">🎵 ${p.bpm || "N/A"} BPM</span>
|
||||||
<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>
|
||||||
|
<audio controls style="height: 30px;"><source src="{{ 'src_mmpSearch/wav/' | relative_url }}${fileName}.ogg" type="audio/ogg"></audio>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column is-8">${tagsHtml} ${tracksHtml}</div>
|
<div class="column is-8">
|
||||||
<div class="column is-4">
|
<div class="card mb-4" style="border-radius: 8px;">
|
||||||
<div class="box has-background-info-light" style="position: sticky; top: 20px">
|
<header class="card-header has-background-light"><p class="card-header-title">🎚️ Instrumentos & Patterns</p></header>
|
||||||
<h3 class="title is-6 has-text-info mb-3">🛠️ Editor Colaborativo</h3>
|
<div class="card-content">
|
||||||
<a href="${creationUrl}" target="_blank" class="button is-info is-fullwidth is-medium mb-4 shadow-sm">Abrir no MMPCreator</a>
|
${(p.tracks || [])
|
||||||
<div class="mt-4 is-hidden-mobile">
|
.map(
|
||||||
<p class="title is-7 has-text-info-dark mb-2">Prévia do Editor:</p>
|
(track) => `
|
||||||
<iframe src="${embedUrl}" style="width: 100%; height: 300px; border: 1px solid #ccc; border-radius: 4px; background: #fff;"></iframe>
|
<div class="box mb-4">
|
||||||
</div>
|
<strong class="is-size-6">📂 ${track.bassline_name || "Track"}</strong>
|
||||||
|
<hr class="my-2">
|
||||||
|
${(track.instruments || [track])
|
||||||
|
.map(
|
||||||
|
(inst) => `
|
||||||
|
<div class="mb-3 p-2" style="border-left: 3px solid #3273dc;">
|
||||||
|
<p class="is-size-7"><strong>${inst.instrument_name || "Synth"}</strong></p>
|
||||||
|
<div class="mt-2" style="display: flex; gap: 2px;">
|
||||||
|
${(inst.patterns || [])
|
||||||
|
.flatMap(
|
||||||
|
(pat) => pat.steps || [],
|
||||||
|
)
|
||||||
|
.map(
|
||||||
|
(s) =>
|
||||||
|
`<div style="width: 4px; height: 10px; background: ${s ? "#4caf50" : "#eee"};"></div>`,
|
||||||
|
)
|
||||||
|
.join("")}
|
||||||
|
</div>
|
||||||
|
<button class="button is-small is-info is-outlined mt-2 js-play-synth" data-params='${JSON.stringify(inst)}'>Ouvir Synth</button>
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
.join("")}
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
)
|
||||||
|
.join("")}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="column is-4">
|
||||||
|
<div class="box has-background-info-light">
|
||||||
|
<h3 class="title is-6 has-text-info">🛠️ Editor</h3>
|
||||||
|
<a href="${creationUrl}" target="_blank" class="button is-info is-fullwidth mb-4">Abrir no MMPCreator</a>
|
||||||
|
<iframe src="${creationUrl}&embed=true" style="width:100%; height:300px; background:#fff; border:1px solid #ccc; border-radius:4px;"></iframe>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div></div>`;
|
||||||
|
|
||||||
// Ativa os botões de teste de synth
|
document.querySelectorAll(".js-play-synth").forEach((btn) => {
|
||||||
document.querySelectorAll('.js-play-synth-btn').forEach(btn => {
|
btn.addEventListener("click", () =>
|
||||||
btn.addEventListener('click', () => {
|
factory.play(JSON.parse(btn.dataset.params)),
|
||||||
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>
|
</script>
|
||||||
|
|
@ -4,11 +4,6 @@ title: MMPSearch - Projetos
|
||||||
permalink: /projetos/
|
permalink: /projetos/
|
||||||
---
|
---
|
||||||
|
|
||||||
{% assign list_plugins = "" %}{% assign list_instruments = "" %} {% for p in
|
|
||||||
site.data.all %}{% for item in p.tags.plugin %}{% assign list_plugins =
|
|
||||||
list_plugins | append: item | append: "|||" %}{% endfor %}{% endfor %} {% assign
|
|
||||||
unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
|
||||||
|
|
||||||
<div class="publication">
|
<div class="publication">
|
||||||
<div class="container is-fluid">
|
<div class="container is-fluid">
|
||||||
<br />
|
<br />
|
||||||
|
|
@ -44,21 +39,25 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
|
|
||||||
<div class="columns">
|
<div class="columns">
|
||||||
<div class="column is-3">
|
<div class="column is-3">
|
||||||
<div class="box p-3" style="background: #fcfcfc">
|
<div
|
||||||
|
class="box p-3"
|
||||||
|
style="background: #fcfcfc; border: 1px solid #eee"
|
||||||
|
>
|
||||||
<div class="field mb-5">
|
<div class="field mb-5">
|
||||||
<label class="label is-size-7">BUSCA TEXTUAL</label>
|
<label class="label is-size-7 has-text-grey">BUSCA TEXTUAL</label>
|
||||||
<div class="control has-icons-left">
|
<div class="control has-icons-left">
|
||||||
<input
|
<input
|
||||||
class="input is-small"
|
class="input is-small"
|
||||||
type="text"
|
type="text"
|
||||||
id="search-input"
|
id="search-input"
|
||||||
placeholder="Nome, plugin..."
|
placeholder="Nome, plugin..."
|
||||||
/><span class="icon is-small is-left"
|
/>
|
||||||
|
<span class="icon is-small is-left"
|
||||||
><i class="fa-solid fa-magnifying-glass"></i
|
><i class="fa-solid fa-magnifying-glass"></i
|
||||||
></span>
|
></span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<hr />
|
<hr class="my-3" />
|
||||||
<details open>
|
<details open>
|
||||||
<summary
|
<summary
|
||||||
class="menu-label has-text-weight-bold mb-2"
|
class="menu-label has-text-weight-bold mb-2"
|
||||||
|
|
@ -74,29 +73,14 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
"
|
"
|
||||||
>
|
></div>
|
||||||
${Array.from({length: 16}).map((_, i) => `
|
|
||||||
<div
|
|
||||||
class="search-step"
|
|
||||||
data-index="${i}"
|
|
||||||
style="
|
|
||||||
width: 22px;
|
|
||||||
height: 35px;
|
|
||||||
background: #eee;
|
|
||||||
border: 1px solid #ccc;
|
|
||||||
border-radius: 3px;
|
|
||||||
cursor: pointer;
|
|
||||||
"
|
|
||||||
></div>
|
|
||||||
`).join('')}
|
|
||||||
</div>
|
|
||||||
</details>
|
</details>
|
||||||
<hr />
|
<hr class="my-3" />
|
||||||
<label class="label is-size-7">BPM RANGE</label>
|
<label class="label is-size-7">FAIXA DE BPM</label>
|
||||||
<div class="columns is-mobile is-variable is-1">
|
<div class="columns is-mobile is-variable is-1">
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<input
|
<input
|
||||||
class="input is-small"
|
class="input is-small has-text-centered"
|
||||||
type="number"
|
type="number"
|
||||||
id="bpm-min"
|
id="bpm-min"
|
||||||
value="0"
|
value="0"
|
||||||
|
|
@ -104,7 +88,7 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
</div>
|
</div>
|
||||||
<div class="column">
|
<div class="column">
|
||||||
<input
|
<input
|
||||||
class="input is-small"
|
class="input is-small has-text-centered"
|
||||||
type="number"
|
type="number"
|
||||||
id="bpm-max"
|
id="bpm-max"
|
||||||
value="300"
|
value="300"
|
||||||
|
|
@ -116,11 +100,16 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
|
|
||||||
<div class="column is-9">
|
<div class="column is-9">
|
||||||
<div class="notification is-info is-light mb-4" id="results-count-bar">
|
<div class="notification is-info is-light mb-4" id="results-count-bar">
|
||||||
Encontrados <span id="visible-count">0</span> projetos.
|
Encontrados
|
||||||
|
<span id="visible-count" class="has-text-weight-bold">0</span>
|
||||||
|
projetos.
|
||||||
</div>
|
</div>
|
||||||
<div id="project-list" class="columns is-multiline"></div>
|
<div id="project-list" class="columns is-multiline"></div>
|
||||||
<div id="no-results" class="has-text-centered is-hidden mt-6">
|
<div id="no-results" class="has-text-centered is-hidden mt-6">
|
||||||
<p class="subtitle has-text-grey">Nenhum projeto encontrado.</p>
|
<span class="icon is-large has-text-grey-light"
|
||||||
|
><i class="fa-solid fa-face-frown fa-3x"></i
|
||||||
|
></span>
|
||||||
|
<p class="subtitle mt-3 has-text-grey">Nenhum projeto encontrado.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -128,6 +117,15 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
|
.search-step {
|
||||||
|
width: 22px;
|
||||||
|
height: 35px;
|
||||||
|
background: #eee;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-radius: 3px;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: 0.1s;
|
||||||
|
}
|
||||||
.search-step.is-active {
|
.search-step.is-active {
|
||||||
background-color: #3273dc !important;
|
background-color: #3273dc !important;
|
||||||
border-color: #205081 !important;
|
border-color: #205081 !important;
|
||||||
|
|
@ -164,15 +162,20 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
document.addEventListener("DOMContentLoaded", function () {
|
document.addEventListener("DOMContentLoaded", function () {
|
||||||
const projectList = document.getElementById("project-list");
|
const projectList = document.getElementById("project-list");
|
||||||
const searchInput = document.getElementById("search-input");
|
const searchInput = document.getElementById("search-input");
|
||||||
const bpmMin = document.getElementById("bpm-min");
|
const bpmMinInput = document.getElementById("bpm-min");
|
||||||
const bpmMax = document.getElementById("bpm-max");
|
const bpmMaxInput = document.getElementById("bpm-max");
|
||||||
const countSpan = document.getElementById("visible-count");
|
const countSpan = document.getElementById("visible-count");
|
||||||
const searchSteps = document.querySelectorAll(".search-step");
|
const patternBox = document.getElementById("pattern-search-box");
|
||||||
|
|
||||||
let allData = [];
|
let allData = [];
|
||||||
let activePatternChunks = [];
|
let activePatternChunks = [];
|
||||||
|
|
||||||
// 1. Carregar Dados
|
// Cria os 16 quadradinhos do filtro de ritmo
|
||||||
|
patternBox.innerHTML = Array.from({ length: 16 })
|
||||||
|
.map((_, i) => `<div class="search-step" data-index="${i}"></div>`)
|
||||||
|
.join("");
|
||||||
|
const searchSteps = document.querySelectorAll(".search-step");
|
||||||
|
|
||||||
fetch(
|
fetch(
|
||||||
'{{ "src_mmpSearch/saida_analises/db_final_completo.json" | relative_url }}',
|
'{{ "src_mmpSearch/saida_analises/db_final_completo.json" | relative_url }}',
|
||||||
)
|
)
|
||||||
|
|
@ -183,49 +186,54 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
applyFilters();
|
applyFilters();
|
||||||
});
|
});
|
||||||
|
|
||||||
// 2. Função de Renderização de Cards
|
|
||||||
function renderCards(data) {
|
function renderCards(data) {
|
||||||
projectList.innerHTML = data
|
projectList.innerHTML = data
|
||||||
.map((p) => {
|
.map((p) => {
|
||||||
|
const fileName = p.file || p.arquivo || "projeto-sem-nome"; // Correção do Erro
|
||||||
const pBpm = p.bpm || 0;
|
const pBpm = p.bpm || 0;
|
||||||
// Extração de chunks para o filtro de pattern (lógica idêntica ao original)
|
|
||||||
let chunks = [];
|
let chunks = [];
|
||||||
p.tracks?.forEach((t) => {
|
if (p.tracks) {
|
||||||
(t.instruments || [t]).forEach((inst) => {
|
p.tracks.forEach((t) => {
|
||||||
inst.patterns?.forEach((pat) => {
|
const instruments = t.instruments || [t];
|
||||||
for (let i = 0; i < (pat.steps?.length || 0); i += 4) {
|
instruments.forEach((inst) => {
|
||||||
const chunk = pat.steps
|
if (inst.patterns) {
|
||||||
.slice(i, i + 4)
|
inst.patterns.forEach((pat) => {
|
||||||
.map((s) => (s ? "1" : "0"))
|
if (pat.steps) {
|
||||||
.join("");
|
for (let i = 0; i < pat.steps.length; i += 4) {
|
||||||
if (chunk !== "0000" && !chunks.includes(chunk))
|
const chunk = pat.steps
|
||||||
chunks.push(chunk);
|
.slice(i, i + 4)
|
||||||
|
.map((s) => (s ? "1" : "0"))
|
||||||
|
.join("");
|
||||||
|
if (chunk !== "0000" && !chunks.includes(chunk))
|
||||||
|
chunks.push(chunk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
}
|
||||||
|
|
||||||
return `
|
return `
|
||||||
<div class="column is-4 project-item"
|
<div class="column is-12-mobile is-6-tablet is-4-desktop project-item"
|
||||||
data-name="${p.file.toLowerCase()}"
|
data-name="${fileName.toLowerCase()}"
|
||||||
data-bpm="${pBpm}"
|
data-bpm="${pBpm}"
|
||||||
data-patterns="${chunks.join(",")}">
|
data-patterns="${chunks.join(",")}">
|
||||||
<div class="card project-card" style="height: 100%; border-radius: 12px; border: 1px solid #cfe8fc; display: flex; flex-direction: column;">
|
<div class="card project-card" style="height: 100%; border-radius: 12px; border: 1px solid #cfe8fc; display: flex; flex-direction: column;">
|
||||||
<a href="{{ '/projeto/?id=' | relative_url }}${p.file}" style="text-decoration: none; flex: 1;">
|
<a href="{{ '/projeto/?id=' | relative_url }}${fileName}" style="text-decoration: none; flex: 1;">
|
||||||
<div class="card-content has-text-centered p-4">
|
<div class="card-content has-text-centered p-4">
|
||||||
<div style="width: 50px; height: 50px; background: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 10px;">
|
<div style="width: 50px; height: 50px; background: #fff; border-radius: 50%; display: flex; align-items: center; justify-content: center; margin: 0 auto 10px; box-shadow: 0 2px 5px rgba(0,0,0,0.05);">
|
||||||
<span class="icon" style="color: #3273dc;"><i class="fa-solid fa-music fa-lg"></i></span>
|
<span class="icon" style="color: #3273dc;"><i class="fa-solid fa-music fa-lg"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<p class="title is-6 mb-2" style="color: #205081;">${p.file.replace(".html", "")}</p>
|
<p class="title is-6 mb-2" style="color: #205081;">${fileName.replace(".html", "")}</p>
|
||||||
<div class="bpm-tag mb-3">
|
<div class="mb-3"><span class="tag is-dark is-rounded is-light">🎵 ${pBpm} BPM</span></div>
|
||||||
<span class="tag is-dark is-rounded is-light">🎵 ${pBpm} BPM</span>
|
<div class="patterns-preview">
|
||||||
</div>
|
|
||||||
<div class="patterns-preview" style="min-height: 20px;">
|
|
||||||
${chunks
|
${chunks
|
||||||
.slice(0, 5)
|
.slice(0, 4)
|
||||||
.map(
|
.map(
|
||||||
(c) => `
|
(c) => `
|
||||||
<div class="pattern-mini-grid">
|
<div class="pattern-mini-grid" title="Pattern: ${c}">
|
||||||
${c
|
${c
|
||||||
.split("")
|
.split("")
|
||||||
.map(
|
.map(
|
||||||
|
|
@ -240,8 +248,8 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
<footer class="card-footer" style="border-top: 1px solid #cfe8fc;">
|
<footer class="card-footer" style="border-top: 1px solid #cfe8fc; background: #fff; border-radius: 0 0 12px 12px;">
|
||||||
<a href="{{ '/projeto/?id=' | relative_url }}${p.file}" class="card-footer-item" style="font-size: 0.8rem; font-weight: 600;">Ver Detalhes</a>
|
<a href="{{ '/projeto/?id=' | relative_url }}${fileName}" class="card-footer-item" style="color: #3273dc; font-size: 0.8rem; font-weight: 600;">Ver Detalhes</a>
|
||||||
</footer>
|
</footer>
|
||||||
</div>
|
</div>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
@ -249,17 +257,18 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
.join("");
|
.join("");
|
||||||
}
|
}
|
||||||
|
|
||||||
// 3. Lógica de Filtro
|
|
||||||
function applyFilters() {
|
function applyFilters() {
|
||||||
const text = searchInput.value.toLowerCase();
|
const text = searchInput.value.toLowerCase();
|
||||||
const min = parseInt(bpmMin.value) || 0;
|
const min = parseInt(bpmMinInput.value) || 0;
|
||||||
const max = parseInt(bpmMax.value) || 999;
|
const max = parseInt(bpmMaxInput.value) || 999;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
|
|
||||||
document.querySelectorAll(".project-item").forEach((item) => {
|
document.querySelectorAll(".project-item").forEach((item) => {
|
||||||
const name = item.dataset.name;
|
const name = item.dataset.name || "";
|
||||||
const bpm = parseInt(item.dataset.bpm);
|
const bpm = parseInt(item.dataset.bpm) || 0;
|
||||||
const pPatterns = item.dataset.patterns.split(",");
|
const pPatterns = item.dataset.patterns
|
||||||
|
? item.dataset.patterns.split(",")
|
||||||
|
: [];
|
||||||
|
|
||||||
const matchText = name.includes(text);
|
const matchText = name.includes(text);
|
||||||
const matchBpm = bpm >= min && bpm <= max;
|
const matchBpm = bpm >= min && bpm <= max;
|
||||||
|
|
@ -275,12 +284,14 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
countSpan.textContent = count;
|
countSpan.textContent = count;
|
||||||
|
document
|
||||||
|
.getElementById("no-results")
|
||||||
|
.classList.toggle("is-hidden", count > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 4. Event Listeners
|
|
||||||
searchInput.addEventListener("input", applyFilters);
|
searchInput.addEventListener("input", applyFilters);
|
||||||
bpmMin.addEventListener("input", applyFilters);
|
bpmMinInput.addEventListener("input", applyFilters);
|
||||||
bpmMax.addEventListener("input", applyFilters);
|
bpmMaxInput.addEventListener("input", applyFilters);
|
||||||
|
|
||||||
searchSteps.forEach((step) => {
|
searchSteps.forEach((step) => {
|
||||||
step.addEventListener("click", function () {
|
step.addEventListener("click", function () {
|
||||||
|
|
@ -303,8 +314,8 @@ unique_plugins = list_plugins | split: "|||" | uniq | sort %}
|
||||||
.getElementById("reset-all-filters")
|
.getElementById("reset-all-filters")
|
||||||
.addEventListener("click", () => {
|
.addEventListener("click", () => {
|
||||||
searchInput.value = "";
|
searchInput.value = "";
|
||||||
bpmMin.value = 0;
|
bpmMinInput.value = 0;
|
||||||
bpmMax.value = 300;
|
bpmMaxInput.value = 300;
|
||||||
searchSteps.forEach((s) => s.classList.remove("is-active"));
|
searchSteps.forEach((s) => s.classList.remove("is-active"));
|
||||||
activePatternChunks = [];
|
activePatternChunks = [];
|
||||||
applyFilters();
|
applyFilters();
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue