7 changed files with 246 additions and 3 deletions
@ -0,0 +1,17 @@ |
|||
<?php |
|||
|
|||
use App\Enumerators\SessionElement; |
|||
use App\Wrappers\DatabaseInteractions; |
|||
use App\Wrappers\SessionWrapper; |
|||
use App\Wrappers\SQLQueryBuilderWrapper; |
|||
use App\Wrappers\TwigWrapper; |
|||
|
|||
require_once __DIR__ . "/../../vendor/autoload.php"; |
|||
|
|||
|
|||
TwigWrapper::RenderTwig( |
|||
target: "Pages/create/tune.html.twig", |
|||
arguments: [ |
|||
] |
|||
); |
|||
|
@ -0,0 +1,63 @@ |
|||
<?php |
|||
|
|||
use App\Enumerators\SessionElement; |
|||
use App\Wrappers\DatabaseInteractions; |
|||
use App\Wrappers\SessionWrapper; |
|||
use App\Wrappers\SQLQueryBuilderWrapper; |
|||
use Ramsey\Uuid\Uuid; |
|||
|
|||
$tuneTitle = $_POST['TuneTitle']; |
|||
$tuneCopyright = $_POST['TuneCopyright']; |
|||
|
|||
$parts = []; |
|||
|
|||
foreach ($_POST as $key => $value) { |
|||
if (preg_match('/^PartTimeSignature-Part([A-Z])$/', $key, $matches)) { |
|||
$partLetter = $matches[1]; |
|||
$parts[$partLetter]['TimeSignature'] = $value; |
|||
} elseif (preg_match('/^PartKeySignature-Part([A-Z])$/', $key, $matches)) { |
|||
$partLetter = $matches[1]; |
|||
$parts[$partLetter]['KeySignature'] = $value; |
|||
} elseif (preg_match('/^TextArea-Part([A-Z])$/', $key, $matches)) { |
|||
$partLetter = $matches[1]; |
|||
$parts[$partLetter]['ABCNotation'] = $value; |
|||
} |
|||
} |
|||
|
|||
ksort($parts); |
|||
|
|||
$db = new DatabaseInteractions(); |
|||
$id = Uuid::uuid4()->toString(); |
|||
|
|||
$db->RunInsert( |
|||
queryBuilder: SQLQueryBuilderWrapper::INSERT('Tunes') |
|||
->set(col: 'ID', value: ':__id__') |
|||
->set(col: 'CreatedBy', value: ':__created_by__') |
|||
->set(col: 'Title', value: ':__tune_title__') |
|||
->set(col: 'Copyright', value: ':__copyright__') |
|||
->bindValue(name: '__id__', value: $id) |
|||
->bindValue(name: '__created_by__', value: SessionWrapper::Get(SessionElement::USER_ID)) |
|||
->bindValue(name: '__tune_title__', value: $tuneTitle) |
|||
->bindValue(name: '__copyright__', value: $tuneCopyright) |
|||
); |
|||
|
|||
foreach ($parts as $partLetter => $part) { |
|||
$db->RunInsert( |
|||
queryBuilder: SQLQueryBuilderWrapper::INSERT('TuneParts') |
|||
->set(col: 'CreatedBy', value: ':__created_by__') |
|||
->set(col: 'TuneID', value: ':__tune_id__') |
|||
->set(col: 'TimeSignature', value: ':__time_signature__') |
|||
->set(col: 'KeySignature', value: ':__key_signature__') |
|||
->set(col: 'PartLetter', value: ':__part_letter__') |
|||
->set(col: 'ABCNotation', value: ':__abc_notation__') |
|||
->bindValue(name: '__created_by__', value: SessionWrapper::Get(SessionElement::USER_ID)) |
|||
->bindValue(name: '__tune_id__', value: $id) |
|||
->bindValue(name: '__time_signature__', value: $part['TimeSignature']) |
|||
->bindValue(name: '__key_signature__', value: $part['KeySignature']) |
|||
->bindValue(name: '__part_letter__', value: $partLetter) |
|||
->bindValue(name: '__abc_notation__', value: $part['ABCNotation']) |
|||
); |
|||
} |
|||
|
|||
header("Location: /tune/{$id}"); |
|||
die(); |
@ -0,0 +1,146 @@ |
|||
{% extends "/Bases/StandardWebPage.html.twig" %} |
|||
|
|||
{% block content %} |
|||
<script src="/Static/JS/ThirdParty/abcjs-basic.js"></script> |
|||
<script> |
|||
|
|||
let partCounter = 0; // Track part count |
|||
let partLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; // Allowed letters for parts |
|||
let barCounters = {}; // Bar counters per part |
|||
|
|||
function getPartLetter(index) { |
|||
return partLetters[index] || `X${index}`; // Prevent overflow |
|||
} |
|||
|
|||
function generateABC() { |
|||
let builder = ""; |
|||
|
|||
builder += "T: " + document.getElementById("TuneTitle").value + "\n"; |
|||
builder += "S: " + document.getElementById("TuneCopyright").value + "\n"; |
|||
|
|||
for (let i = 0; i < partCounter; i++) { |
|||
let partLetter = getPartLetter(i); |
|||
let partTextarea = document.getElementById(`TextArea-Part${partLetter}`); |
|||
let timeSigInput = document.getElementById(`PartTimeSignature-Part${partLetter}`); |
|||
let keySigInput = document.getElementById(`PartKeySignature-Part${partLetter}`); |
|||
|
|||
if (partTextarea) { |
|||
builder += `P: Part ${partLetter}\n`; |
|||
|
|||
if (timeSigInput && timeSigInput.value.trim() !== "") { |
|||
builder += `M: ${timeSigInput.value}\n`; |
|||
} |
|||
|
|||
if (keySigInput && keySigInput.value.trim() !== "") { |
|||
builder += `K: ${keySigInput.value}\n`; |
|||
} |
|||
|
|||
builder += partTextarea.value + "\n"; |
|||
} |
|||
} |
|||
|
|||
renderABC(builder); |
|||
} |
|||
|
|||
|
|||
function renderABC(payload) |
|||
{ |
|||
document.getElementById('ABCReadout').innerHTML = payload; |
|||
const tunes = window.ABCJS.renderAbc( |
|||
'NotationContainer', |
|||
payload, |
|||
{ |
|||
add_classes: true, |
|||
format: { |
|||
gchordfont: "Atkinson Hyperlegible", |
|||
annotationfont: "Atkinson Hyperlegible", |
|||
headerfont: "Atkinson Hyperlegible", |
|||
infofont: "Atkinson Hyperlegible", |
|||
repeatfont: "Atkinson Hyperlegible", |
|||
tempofont: "Atkinson Hyperlegible", |
|||
titlefont: "Atkinson Hyperlegible", |
|||
voicefont: "Atkinson Hyperlegible", |
|||
wordsfont: "Atkinson Hyperlegible", |
|||
}, |
|||
} |
|||
); |
|||
} |
|||
|
|||
|
|||
function createNewPart() { |
|||
if (partCounter >= partLetters.length) { |
|||
alert("Maximum parts reached"); |
|||
return; |
|||
} |
|||
|
|||
let partLetter = getPartLetter(partCounter); |
|||
partCounter++; |
|||
|
|||
const container = document.getElementById('PartsWrapper'); |
|||
const newPartDiv = document.createElement('div'); |
|||
newPartDiv.id = `Part_${partLetter}`; |
|||
newPartDiv.classList.add('part'); |
|||
|
|||
newPartDiv.innerHTML = ` |
|||
<h3>Part ${partLetter}</h3> |
|||
<a class="delete-part-btn" href="javascript:deletePart('${partLetter}')">{{ "Delete Part"|translate }}</a> |
|||
<br> |
|||
<label for="PartTimeSignature-Part${partLetter}">{{ "Time Signature"|translate }}</label><br> |
|||
<input id="PartTimeSignature-Part${partLetter}" name="PartTimeSignature-Part${partLetter}" type="text" onchange="generateABC()"> |
|||
<br> |
|||
<label for="PartKeySignature-Part${partLetter}">{{ "Key Signature"|translate }}</label><br> |
|||
<input id="PartKeySignature-Part${partLetter}" name="PartKeySignature-Part${partLetter}" type="text" onchange="generateABC()"> |
|||
<br> |
|||
<textarea id="TextArea-Part${partLetter}" name="TextArea-Part${partLetter}" style="width: 100%; height: 5rem;" onchange="generateABC()"></textarea> |
|||
`; |
|||
|
|||
container.appendChild(newPartDiv); |
|||
} |
|||
|
|||
|
|||
function deletePart(partLetter) { |
|||
const partDiv = document.getElementById(`Part_${partLetter}`); |
|||
if (partDiv) { |
|||
partDiv.remove(); |
|||
} |
|||
} |
|||
</script> |
|||
|
|||
<style> |
|||
.part { |
|||
border: 1px solid #ddd; |
|||
margin: 1rem 0; |
|||
padding: 1rem; |
|||
border-radius: 5px; |
|||
background: #f9f9f9; |
|||
} |
|||
</style> |
|||
|
|||
<div class="InnerContent"> |
|||
<h1>{{ "Tune Creator"|translate }}</h1> |
|||
|
|||
<div class="container"> |
|||
<div class="left-main"> |
|||
<form action="/FormHandling/NewTune.php" method="POST"> |
|||
<label for="TuneTitle">{{ "Tune Title"|translate }}</label><br> |
|||
<input id="TuneTitle" name="TuneTitle" type="text" onchange="generateABC()"> |
|||
<br><br> |
|||
<label for="TuneCopyright">{{ "Copyright"|translate }}</label><br> |
|||
<input id="TuneCopyright" name="TuneCopyright" type="text" onchange="generateABC()"> |
|||
|
|||
<div> |
|||
<a href="javascript:createNewPart()">{{ "Create New Part"|translate }}</a> |
|||
<div id="PartsWrapper"></div> |
|||
</div> |
|||
|
|||
<input type="submit"> |
|||
</form> |
|||
</div> |
|||
<div class="right"> |
|||
<textarea id="ABCReadout" style="width: 100%; height: 25rem;" readonly></textarea> |
|||
</div> |
|||
</div> |
|||
|
|||
<div id="NotationContainer"></div> |
|||
</div> |
|||
{% endblock %} |
Loading…
Reference in new issue