Browse Source

can now create tunes

master
Cerys 3 weeks ago
parent
commit
673e804364
  1. 17
      Pages/create/tune.php
  2. 3
      Pages/profile.php
  3. 63
      Public/FormHandling/NewTune.php
  4. 9
      Public/Static/CSS/Elements/Columns.css
  5. 10
      Routing/Router.php
  6. 146
      Templates/Pages/create/tune.html.twig
  7. 1
      Templates/Pages/profile.html.twig

17
Pages/create/tune.php

@ -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: [
]
);

3
Pages/profile.php

@ -47,6 +47,9 @@ $yourTuneSets = $db->RunSelect(
cond: 'T_TST.TuneID=T_T.ID'
)
->where(cond: 'T.CreatedBy LIKE :__user_id__')
->orderBy(spec: [
'T_TST.Order ASC',
])
->bindValue(name: '__user_id__', value: SessionWrapper::Get(target: SessionElement::USER_ID))
);

63
Public/FormHandling/NewTune.php

@ -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();

9
Public/Static/CSS/Elements/Columns.css

@ -4,12 +4,17 @@
width: 100%;
}
.left, .right {
.left,
.right {
width: 24%;
}
.left-main,
.right-main {
width: 75%;
}
.center {
.main {
width: 50%;
}

10
Routing/Router.php

@ -47,7 +47,6 @@ if (isset($routes[$requestElements[0]]))
return true;
}
// Route handling for tune-related pages
if ($requestElements[0] === "tune" && isset($requestElements[1]))
{
$_GET['tune-id'] = $requestElements[1];
@ -78,6 +77,15 @@ elseif ($requestElements[0] === "tune-set" && isset($requestElements[1]))
return true;
}
}
elseif ($requestElements[0] === "create" && isset($requestElements[1]))
{
switch($requestElements[1])
{
case "tune":
require_once __DIR__ . '/../Pages/create/tune.php';
return true;
}
}
// Default: route not found
http_response_code(404);

146
Templates/Pages/create/tune.html.twig

@ -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 %}

1
Templates/Pages/profile.html.twig

@ -28,6 +28,7 @@
<div id="MyUploadedTunes" class="TabContent">
<h2>{{ "My Uploaded Tunes"|translate }}</h2>
<a href="/create/tune">{{ "Upload Tune"|translate }}</a>
<table>
<thead>
<tr>

Loading…
Cancel
Save