- ${esc(p.name)}
+ ${esc(p.name)} ${beadHint}
${badgeLabel}
${esc(preview)}${preview.length >= 100 ? '…' : ''}
@@ -177,18 +189,27 @@
const leaderPrev = (p.leader_text || '').replace(/\n/g, ' ').substring(0, 60);
const allPrev = (p.all_text || '').replace(/\n/g, ' ').substring(0, 60);
+ const bead = step.bead_type || '';
return `
${i + 1}
${esc(p.name)}
${leaderPrev ? `
Leader: ${esc(leaderPrev)}${leaderPrev.length >= 60 ? '…' : ''}
` : ''}
${allPrev ? `
All: ${esc(allPrev)}${allPrev.length >= 60 ? '…' : ''}
` : ''}
-
+
+
+
+
+
+
+
+
+
${moveUp}${moveDn}${remove}
`;
@@ -220,7 +241,8 @@
else if (!prayer.all_text) attr = 'leader_only';
else if (!prayer.leader_text) attr = 'all_only';
- STEPS.push({ step_type: 'prayer', prayer_id: prayerId, attribution: attr, _prayer: prayer });
+ const defaultBead = prayer.default_bead_type || null;
+ STEPS.push({ step_type: 'prayer', prayer_id: prayerId, attribution: attr, bead_type: defaultBead, _prayer: prayer });
renderSequence();
// Briefly highlight the new step
const list = document.getElementById('step-list');
@@ -249,6 +271,13 @@
if (STEPS[index]) STEPS[index].attribution = value;
};
+ window.builderSetBead = function (index, value) {
+ if (STEPS[index]) {
+ STEPS[index].bead_type = value;
+ renderSequence(); // re-render so active bead button updates
+ }
+ };
+
window.builderEditPrayer = function (prayerId) {
openModal(prayerId);
};
@@ -276,6 +305,12 @@
document.getElementById('modal-leader').value = p.leader_text || '';
document.getElementById('modal-all').value = p.all_text || '';
document.getElementById('modal-global').checked = !!p.is_global;
+ // Pre-fill bead type
+ const beadVal = p.default_bead_type || '';
+ document.getElementById('modal-bead-type').value = beadVal;
+ document.querySelectorAll('#modal-bead-row .bead-sel-btn').forEach(function (btn) {
+ btn.classList.toggle('active', btn.dataset.bead === beadVal);
+ });
// Determine existing attribution for radio pre-selection
const hasLeader = !!(p.leader_text || '').trim();
@@ -327,8 +362,9 @@
const name = document.getElementById('modal-name').value.trim();
const leader = document.getElementById('modal-leader').value.trim();
const all = document.getElementById('modal-all').value.trim();
- const global = document.getElementById('modal-global').checked ? 1 : 0;
- const attr = getSelectedAttr();
+ const global = document.getElementById('modal-global').checked ? 1 : 0;
+ const beadType = document.getElementById('modal-bead-type').value || null;
+ const attr = getSelectedAttr();
if (!name) {
document.getElementById('modal-name').focus();
@@ -350,7 +386,7 @@
fetch(url, {
method: method,
headers: { 'Content-Type': 'application/json' },
- body: JSON.stringify({ name, leader_text: sendLeader, all_text: sendAll, is_global: global }),
+ body: JSON.stringify({ name, leader_text: sendLeader, all_text: sendAll, default_bead_type: beadType, is_global: global }),
})
.then(r => r.json())
.then(function (data) {
@@ -417,7 +453,7 @@
subject_dates: document.getElementById('subject-dates').value.trim(),
steps: STEPS.map(s => s.step_type === 'bead'
? { step_type: 'bead', bead_type: s.bead_type }
- : { step_type: 'prayer', prayer_id: s.prayer_id, attribution: s.attribution }),
+ : { step_type: 'prayer', prayer_id: s.prayer_id, attribution: s.attribution, bead_type: s.bead_type || null }),
};
const btn = document.getElementById('btn-save');
diff --git a/includes/build_slides.php b/includes/build_slides.php
index ad0e723..cf21240 100644
--- a/includes/build_slides.php
+++ b/includes/build_slides.php
@@ -137,6 +137,7 @@ function build_slides(array $session): array {
$leader = ($step['leader_text'] ?: $step['all_text']) ?? '';
}
+ $bead_type = $step['bead_type'] ?? null;
$slides[] = [
'id' => 'custom_' . $i,
'type' => 'prayer',
@@ -144,8 +145,8 @@ function build_slides(array $session): array {
'title' => $step['name'],
'leader' => $leader,
'all' => $all,
- 'bead' => null,
- 'bead_index' => null,
+ 'bead' => $bead_type,
+ 'bead_index' => $bead_type ? $bead_idx++ : null,
];
}
diff --git a/migrate_v6.php b/migrate_v6.php
new file mode 100644
index 0000000..4c2977a
--- /dev/null
+++ b/migrate_v6.php
@@ -0,0 +1,74 @@
+exec($sql);
+ $log[] = ['ok', $label];
+ } catch (PDOException $e) {
+ if (in_array($e->errorInfo[1], [1060, 1054], true)) {
+ $log[] = ['skip', $label . ' (already exists)'];
+ } else {
+ $log[] = ['err', $label . ': ' . $e->getMessage()];
+ }
+ }
+}
+
+mig6_sql($pdo, 'Add default_bead_type to custom_prayers', "
+ ALTER TABLE custom_prayers
+ ADD COLUMN default_bead_type ENUM('small','large','crucifix') NULL AFTER all_text
+", $log);
+
+// Set defaults for the seeded standard global prayers
+$defaults = [
+ 'Sign of the Cross' => 'crucifix',
+ 'Our Father' => 'large',
+ 'Hail Mary' => 'small',
+ 'Eternal Father (Divine Mercy)' => 'large',
+ 'For the Sake of His Sorrowful Passion' => 'small',
+];
+
+$updated = 0;
+$st = $pdo->prepare(
+ "UPDATE custom_prayers SET default_bead_type = ? WHERE name = ? AND is_global = 1"
+);
+foreach ($defaults as $name => $bead) {
+ $st->execute([$bead, $name]);
+ if ($st->rowCount() > 0) $updated++;
+}
+$log[] = ['ok', "Updated default bead types for {$updated} standard prayers"];
+
+?>
+
+
+
+
Migrate v6
+
+
+
+
Migrate v6 — Prayer Bead Defaults
+
+
+ -
+ = $status === 'ok' ? '✓' : ($status === 'skip' ? '◌' : '✗') ?>
+ = htmlspecialchars($msg) ?>
+
+
+
+ $l[0] === 'err')): ?>
+
Migration complete. Delete this file: migrate_v6.php
+
+
+