Matins completed
This commit is contained in:
1 parent
ff5b8dc649
commit
79ac617aa8
4 files changed
+1935
-18
No files matched your search
+1321
File diff suppressed because it is too large.
Load diff
@@ -417,6 +417,15 @@ export async function assembleService(
|
||||
break;
|
||||
}
|
||||
|
||||
case 'HEADER': {
|
||||
flushGroup();
|
||||
const value = str(n.value);
|
||||
if (value) {
|
||||
html += `<h3 class="mt-4 mb-1 font-bold text-center">${value}</h3>\n`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case 'GETID': {
|
||||
const whoRaw = str(n.who);
|
||||
const who = whoRaw !== undefined ? localizeWho(whoRaw, ctx) : '';
|
||||
|
||||
+40
-2
@@ -4,12 +4,14 @@
|
||||
|
||||
import { CalendarView } from './calendar-view';
|
||||
import { BibleView } from './bible-view';
|
||||
import { PrayerView } from './prayer-view';
|
||||
import { MenaionView } from './menaion-view';
|
||||
import { SettingsView } from './settings-view';
|
||||
import { JDate } from '../core/jdate';
|
||||
import { loadSettings, type Settings } from './settings-view';
|
||||
import { getTranslations, type LanguageCode } from '../core/i18n';
|
||||
|
||||
type View = 'calendar' | 'bible' | 'settings';
|
||||
type View = 'calendar' | 'bible' | 'prayer' | 'akathists' | 'parimii' | 'horologion' | 'sbornik' | 'paraclete' | 'irmologion' | 'menaion' | 'triodion' | 'settings';
|
||||
|
||||
export class App {
|
||||
private container: HTMLElement;
|
||||
@@ -72,9 +74,18 @@ export class App {
|
||||
<div class="app-container min-h-screen flex flex-col">
|
||||
<header class="bg-navy text-parchment p-3 flex items-center justify-between shadow-md">
|
||||
<h1 class="text-sm font-bold tracking-wide">${t.appName}</h1>
|
||||
<nav class="flex gap-4 text-sm">
|
||||
<nav class="flex flex-wrap gap-4 text-sm">
|
||||
<a href="#calendar" class="nav-link hover:text-gold transition-colors" data-view="calendar">${t.nav.calendar}</a>
|
||||
<a href="#bible" class="nav-link hover:text-gold transition-colors" data-view="bible">${t.nav.bible}</a>
|
||||
<a href="#prayer" class="nav-link hover:text-gold transition-colors" data-view="prayer">${t.nav.prayer}</a>
|
||||
<a href="#akathists" class="nav-link hover:text-gold transition-colors" data-view="akathists">${t.nav.akathists}</a>
|
||||
<a href="#parimii" class="nav-link hover:text-gold transition-colors" data-view="parimii">${t.nav.parimii}</a>
|
||||
<a href="#horologion" class="nav-link hover:text-gold transition-colors" data-view="horologion">${t.nav.horologion}</a>
|
||||
<a href="#sbornik" class="nav-link hover:text-gold transition-colors" data-view="sbornik">${t.nav.sbornik}</a>
|
||||
<a href="#paraclete" class="nav-link hover:text-gold transition-colors" data-view="paraclete">${t.nav.paraclete}</a>
|
||||
<a href="#irmologion" class="nav-link hover:text-gold transition-colors" data-view="irmologion">${t.nav.irmologion}</a>
|
||||
<a href="#menaion" class="nav-link hover:text-gold transition-colors" data-view="menaion">${t.nav.menaion}</a>
|
||||
<a href="#triodion" class="nav-link hover:text-gold transition-colors" data-view="triodion">${t.nav.triodion}</a>
|
||||
<a href="#settings" class="nav-link hover:text-gold transition-colors" data-view="settings">${t.nav.settings}</a>
|
||||
</nav>
|
||||
</header>
|
||||
@@ -127,6 +138,33 @@ export class App {
|
||||
new BibleView(viewContainer, lang, bibleVersion, bibleBook, biblePassage).render();
|
||||
break;
|
||||
}
|
||||
case 'prayer':
|
||||
new PrayerView(viewContainer, lang, 'prayer-rule').render();
|
||||
break;
|
||||
case 'akathists':
|
||||
new PrayerView(viewContainer, lang, 'akathists').render();
|
||||
break;
|
||||
case 'parimii':
|
||||
new PrayerView(viewContainer, lang, 'parimii').render();
|
||||
break;
|
||||
case 'horologion':
|
||||
new PrayerView(viewContainer, lang, 'horologion').render();
|
||||
break;
|
||||
case 'sbornik':
|
||||
new PrayerView(viewContainer, lang, 'sbornik').render();
|
||||
break;
|
||||
case 'paraclete':
|
||||
new PrayerView(viewContainer, lang, 'paraclete').render();
|
||||
break;
|
||||
case 'irmologion':
|
||||
new PrayerView(viewContainer, lang, 'irmologion').render();
|
||||
break;
|
||||
case 'menaion':
|
||||
new MenaionView(viewContainer, lang).render();
|
||||
break;
|
||||
case 'triodion':
|
||||
new PrayerView(viewContainer, lang, 'triodion').render();
|
||||
break;
|
||||
case 'settings':
|
||||
new SettingsView(viewContainer, () => {
|
||||
this.render();
|
||||
|
||||
+565
-16
@@ -19,6 +19,10 @@ interface ServiceDef {
|
||||
template: string;
|
||||
description: string;
|
||||
titleNode: ServiceNode;
|
||||
divider?: boolean;
|
||||
menaionDayIndex?: number;
|
||||
menaionDateKey?: string;
|
||||
triodionIndex?: number;
|
||||
}
|
||||
|
||||
function title(value: string, header?: string, source?: string, comment?: string): ServiceNode {
|
||||
@@ -41,6 +45,7 @@ export class ServiceView {
|
||||
private commandCache = new Map<string, string>();
|
||||
private timesCache = new Map<string, { cmd: string; value: string }[]>();
|
||||
private activeService: string | null = null;
|
||||
private menaionDayCount = new Map<string, number>();
|
||||
|
||||
constructor(container: HTMLElement, date: JDate, language: LanguageCode = 'en') {
|
||||
this.container = container;
|
||||
@@ -63,6 +68,17 @@ export class ServiceView {
|
||||
const computed = computeDay(this.currentDate);
|
||||
const { dayInfo } = computed;
|
||||
|
||||
// Load the daily Menaion index (date -> section count) for the Служба дня tabs
|
||||
try {
|
||||
const resp = await fetch('/data/shared/menaion-daily/index.json');
|
||||
if (resp.ok) {
|
||||
const index = await resp.json() as Record<string, number>;
|
||||
for (const [dk, n] of Object.entries(index)) {
|
||||
this.menaionDayCount.set(dk, n);
|
||||
}
|
||||
}
|
||||
} catch { /* keep empty cache */ }
|
||||
|
||||
const availableServices = this.getAvailableServices(dayInfo);
|
||||
const fontClass = this.getFontClass();
|
||||
|
||||
@@ -72,6 +88,7 @@ export class ServiceView {
|
||||
<h3 class="font-bold text-navy mb-3">${this.t.services.title}</h3>
|
||||
<div class="flex flex-wrap gap-1 mb-6 border-b border-gold/20">
|
||||
${availableServices.map(s => `
|
||||
${s.divider ? '<span class="self-center mx-1 text-gold/40 select-none" aria-hidden="true">·</span>' : ''}
|
||||
<button
|
||||
class="service-tab px-4 py-2 text-sm border-b-2 transition-colors whitespace-nowrap
|
||||
${this.activeService === s.id
|
||||
@@ -124,51 +141,100 @@ export class ServiceView {
|
||||
}
|
||||
|
||||
private getAvailableServices(dayInfo: import('../core/types').DayInfo): ServiceDef[] {
|
||||
const services: ServiceDef[] = [];
|
||||
const special: ServiceDef[] = [];
|
||||
const daily: ServiceDef[] = [];
|
||||
|
||||
services.push({
|
||||
// Triodion movable days (by nday): Pre-Lent Sundays + Lent Sundays
|
||||
// (the ones not already covered: week 1, Marias Standing, Palm Sunday, Holy Week)
|
||||
const triodionDay: Record<number, { idx: number; name: string }> = {
|
||||
[-70]: { idx: 1, name: this.t.triodion.sections[0] },
|
||||
[-63]: { idx: 2, name: this.t.triodion.sections[1] },
|
||||
[-57]: { idx: 3, name: this.t.triodion.sections[2] },
|
||||
[-56]: { idx: 4, name: this.t.triodion.sections[3] },
|
||||
[-50]: { idx: 6, name: this.t.triodion.sections[5] },
|
||||
[-49]: { idx: 7, name: this.t.triodion.sections[6] },
|
||||
[-42]: { idx: 14, name: this.t.triodion.sections[13] },
|
||||
[-35]: { idx: 17, name: this.t.triodion.sections[16] },
|
||||
[-28]: { idx: 20, name: this.t.triodion.sections[19] },
|
||||
[-21]: { idx: 23, name: this.t.triodion.sections[22] },
|
||||
[-14]: { idx: 27, name: this.t.triodion.sections[26] },
|
||||
[-9]: { idx: 26, name: this.t.triodion.sections[25] },
|
||||
[-8]: { idx: 29, name: this.t.triodion.sections[28] },
|
||||
};
|
||||
const triodionHit = triodionDay[dayInfo.nday];
|
||||
if (triodionHit) {
|
||||
special.push({
|
||||
id: `triodion-${triodionHit.idx}`,
|
||||
name: triodionHit.name,
|
||||
serviceType: 'TRIODION',
|
||||
template: 'Triodion',
|
||||
description: this.t.triodion.title,
|
||||
titleNode: title('Triodion1', triodionHit.name),
|
||||
triodionIndex: triodionHit.idx,
|
||||
});
|
||||
}
|
||||
|
||||
// Daily Menaion: the day's proper service (menaion-daily/{MM-DD}/{NN}.json)
|
||||
const mmDay = `${String(dayInfo.month).padStart(2, '0')}-${String(dayInfo.day).padStart(2, '0')}`;
|
||||
const menaionDayCount = this.menaionDayCount.get(mmDay) ?? -1;
|
||||
if (menaionDayCount === -1) {
|
||||
// Cache lookup is populated in render(); fall back to 0 (fetched async)
|
||||
}
|
||||
for (let i = 1; i <= Math.max(0, menaionDayCount); i++) {
|
||||
special.push({
|
||||
id: `menaion-day-${i}`, name: i === 1 ? this.t.services.serviceNames.menaionDay : this.t.services.serviceNames.menaionDay,
|
||||
serviceType: 'MENAIONDAY',
|
||||
template: 'MenaionDay',
|
||||
description: this.t.services.serviceDescriptions.menaionDay,
|
||||
titleNode: title('MenaionDay1', this.t.services.serviceNames.menaionDay),
|
||||
menaionDayIndex: i,
|
||||
menaionDateKey: mmDay,
|
||||
});
|
||||
}
|
||||
|
||||
daily.push({
|
||||
id: 'primes', name: this.t.services.serviceNames.primes, serviceType: 'PRIMES',
|
||||
template: 'Prime',
|
||||
description: this.t.services.serviceDescriptions.primes,
|
||||
titleNode: title('Primes1', this.t.services.serviceNames.primes, 'PrimeSource'),
|
||||
});
|
||||
|
||||
services.push({
|
||||
daily.push({
|
||||
id: 'third', name: this.t.services.serviceNames.third, serviceType: 'TERCE',
|
||||
template: 'ThirdHour',
|
||||
description: this.t.services.serviceDescriptions.third,
|
||||
titleNode: title('Third1', this.t.services.serviceNames.third),
|
||||
});
|
||||
|
||||
services.push({
|
||||
daily.push({
|
||||
id: 'sixth', name: this.t.services.serviceNames.sixth, serviceType: 'SEXTE',
|
||||
template: 'SixthHour',
|
||||
description: this.t.services.serviceDescriptions.sixth,
|
||||
titleNode: title('Sixth1', this.t.services.serviceNames.sixth),
|
||||
});
|
||||
|
||||
services.push({
|
||||
daily.push({
|
||||
id: 'ninth', name: this.t.services.serviceNames.ninth, serviceType: 'NONE',
|
||||
template: 'NinthHour',
|
||||
description: this.t.services.serviceDescriptions.ninth,
|
||||
titleNode: title('Ninth1', this.t.services.serviceNames.ninth),
|
||||
});
|
||||
|
||||
services.push({
|
||||
daily.push({
|
||||
id: 'vespers', name: this.t.services.serviceNames.vespers, serviceType: 'VESPERS',
|
||||
template: 'Vespers',
|
||||
description: this.t.services.serviceDescriptions.vespers,
|
||||
titleNode: title('Vespers1', this.t.services.serviceNames.vespers, 'VesperSource'),
|
||||
});
|
||||
|
||||
services.push({
|
||||
daily.push({
|
||||
id: 'matins', name: this.t.services.serviceNames.matins, serviceType: 'MATINS',
|
||||
template: 'Matins',
|
||||
description: this.t.services.serviceDescriptions.matins,
|
||||
titleNode: title('Matins1', this.t.services.serviceNames.matins, 'MatinsSource'),
|
||||
});
|
||||
|
||||
services.push({
|
||||
daily.push({
|
||||
id: 'liturgy', name: this.t.services.serviceNames.liturgy, serviceType: 'LITURGY',
|
||||
template: 'DivineLiturgy',
|
||||
description: this.t.services.serviceDescriptions.liturgy,
|
||||
@@ -176,7 +242,7 @@ export class ServiceView {
|
||||
});
|
||||
|
||||
if (dayInfo.dRank >= 6) {
|
||||
services.push({
|
||||
daily.push({
|
||||
id: 'royalhours', name: this.t.services.serviceNames.royalhours, serviceType: 'ROYALHOURS',
|
||||
template: 'RoyalHours',
|
||||
description: this.t.services.serviceDescriptions.royalhours,
|
||||
@@ -184,9 +250,162 @@ export class ServiceView {
|
||||
});
|
||||
}
|
||||
|
||||
// Bright Week services (Pascha through Saturday)
|
||||
if (dayInfo.isBrightWeek) {
|
||||
const brightDay: Record<number, { id: string; name: string; type: string; desc: string }> = {
|
||||
[0]: { id: 'pascha', name: this.t.services.serviceNames.pascha, type: 'PASCHA', desc: this.t.services.serviceDescriptions.pascha },
|
||||
[1]: { id: 'brightmonday', name: this.t.services.serviceNames.brightmonday, type: 'BRIGHTMONDAY', desc: this.t.services.serviceDescriptions.brightmonday },
|
||||
[2]: { id: 'brighttuesday', name: this.t.services.serviceNames.brighttuesday, type: 'BRIGHTTUESDAY', desc: this.t.services.serviceDescriptions.brighttuesday },
|
||||
[3]: { id: 'brightwednesday', name: this.t.services.serviceNames.brightwednesday, type: 'BRIGHTWEDNESDAY', desc: this.t.services.serviceDescriptions.brightwednesday },
|
||||
[4]: { id: 'brightthursday', name: this.t.services.serviceNames.brightthursday, type: 'BRIGHTTHURSDAY', desc: this.t.services.serviceDescriptions.brightthursday },
|
||||
[5]: { id: 'brightfriday', name: this.t.services.serviceNames.brightfriday, type: 'BRIGHTFRIDAY', desc: this.t.services.serviceDescriptions.brightfriday },
|
||||
[6]: { id: 'brightsaturday', name: this.t.services.serviceNames.brightsaturday, type: 'BRIGHTSATURDAY', desc: this.t.services.serviceDescriptions.brightsaturday },
|
||||
};
|
||||
const bd = brightDay[dayInfo.nday];
|
||||
if (bd) {
|
||||
const templateName = bd.id.charAt(0).toUpperCase() + bd.id.slice(1);
|
||||
special.push({
|
||||
id: bd.id, name: bd.name, serviceType: bd.type,
|
||||
template: templateName,
|
||||
description: bd.desc,
|
||||
titleNode: title(`${templateName}1`, bd.name),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Pentecostarion services (Antipascha through All Saints)
|
||||
if (dayInfo.pentecostarionFile !== null && dayInfo.nday > 6) {
|
||||
const pentDay: Record<number, { id: string; name: string; type: string; desc: string }> = {
|
||||
[7]: { id: 'antipascha', name: this.t.services.serviceNames.antipascha, type: 'ANTIPASCHA', desc: this.t.services.serviceDescriptions.antipascha },
|
||||
[14]: { id: 'myrrhbearers', name: this.t.services.serviceNames.myrrhbearers, type: 'MYRRHBEARERS', desc: this.t.services.serviceDescriptions.myrrhbearers },
|
||||
[21]: { id: 'paralytic', name: this.t.services.serviceNames.paralytic, type: 'PARALYTIC', desc: this.t.services.serviceDescriptions.paralytic },
|
||||
[25]: { id: 'prepolovenie', name: this.t.services.serviceNames.prepolovenie, type: 'PREPOLOVENIE', desc: this.t.services.serviceDescriptions.prepolovenie },
|
||||
[28]: { id: 'samaritan', name: this.t.services.serviceNames.samaritan, type: 'SAMARITAN', desc: this.t.services.serviceDescriptions.samaritan },
|
||||
[35]: { id: 'blindman', name: this.t.services.serviceNames.blindman, type: 'BLINDMAN', desc: this.t.services.serviceDescriptions.blindman },
|
||||
[38]: { id: 'apodosis', name: this.t.services.serviceNames.apodosis, type: 'APODOSIS', desc: this.t.services.serviceDescriptions.apodosis },
|
||||
[39]: { id: 'ascension', name: this.t.services.serviceNames.ascension, type: 'ASCENSION', desc: this.t.services.serviceDescriptions.ascension },
|
||||
[42]: { id: 'holyfathers', name: this.t.services.serviceNames.holyfathers, type: 'HOLYFATHERS', desc: this.t.services.serviceDescriptions.holyfathers },
|
||||
[48]: { id: 'pentecostsaturday', name: this.t.services.serviceNames.pentecostsaturday, type: 'PENTECOSTSATURDAY', desc: this.t.services.serviceDescriptions.pentecostsaturday },
|
||||
[49]: { id: 'pentecost', name: this.t.services.serviceNames.pentecost, type: 'PENTECOST', desc: this.t.services.serviceDescriptions.pentecost },
|
||||
[50]: { id: 'holyspirit', name: this.t.services.serviceNames.holyspirit, type: 'HOLYSPIRIT', desc: this.t.services.serviceDescriptions.holyspirit },
|
||||
[56]: { id: 'allsaints', name: this.t.services.serviceNames.allsaints, type: 'ALLSAINTS', desc: this.t.services.serviceDescriptions.allsaints },
|
||||
};
|
||||
const pd = pentDay[dayInfo.nday];
|
||||
if (pd) {
|
||||
const templateName = pd.id.charAt(0).toUpperCase() + pd.id.slice(1);
|
||||
special.push({
|
||||
id: pd.id, name: pd.name, serviceType: pd.type,
|
||||
template: templateName,
|
||||
description: pd.desc,
|
||||
titleNode: title(`${templateName}1`, pd.name),
|
||||
});
|
||||
}
|
||||
// All Saints of Russia (appendix, same Sunday as All Saints)
|
||||
if (dayInfo.nday === 56) {
|
||||
special.push({
|
||||
id: 'russiansaints', name: this.t.services.serviceNames.russiansaints, serviceType: 'RUSSIANSAINTS',
|
||||
template: 'RussianSaints',
|
||||
description: this.t.services.serviceDescriptions.russiansaints,
|
||||
titleNode: title('RussianSaints1', this.t.services.serviceNames.russiansaints),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// First Week of Lent: complete daily cycle (Matins, Hours, Typica, Vespers, Compline)
|
||||
if (dayInfo.isLent && dayInfo.nday >= -48 && dayInfo.nday <= -43) {
|
||||
const fwDay: Record<number, { id: string; name: string; type: string; desc: string }> = {
|
||||
[-48]: { id: 'firstweekmonday', name: this.t.services.serviceNames.firstweekmonday, type: 'FIRSTWEEKMONDAY', desc: this.t.services.serviceDescriptions.firstweekmonday },
|
||||
[-47]: { id: 'firstweektuesday', name: this.t.services.serviceNames.firstweektuesday, type: 'FIRSTWEEKTUESDAY', desc: this.t.services.serviceDescriptions.firstweektuesday },
|
||||
[-46]: { id: 'firstweekwednesday', name: this.t.services.serviceNames.firstweekwednesday, type: 'FIRSTWEEKWEDNESDAY', desc: this.t.services.serviceDescriptions.firstweekwednesday },
|
||||
[-45]: { id: 'firstweekthursday', name: this.t.services.serviceNames.firstweekthursday, type: 'FIRSTWEEKTHURSDAY', desc: this.t.services.serviceDescriptions.firstweekthursday },
|
||||
[-44]: { id: 'firstweekfriday', name: this.t.services.serviceNames.firstweekfriday, type: 'FIRSTWEEKFRIDAY', desc: this.t.services.serviceDescriptions.firstweekfriday },
|
||||
[-43]: { id: 'firstweeksaturday', name: this.t.services.serviceNames.firstweeksaturday, type: 'FIRSTWEEKSATURDAY', desc: this.t.services.serviceDescriptions.firstweeksaturday },
|
||||
};
|
||||
const fw = fwDay[dayInfo.nday];
|
||||
if (fw) {
|
||||
const templateName = 'FirstWeek' + fw.id.charAt(0).toUpperCase() + fw.id.slice(1);
|
||||
special.push({
|
||||
id: fw.id, name: fw.name, serviceType: fw.type,
|
||||
template: templateName,
|
||||
description: fw.desc,
|
||||
titleNode: title(`${templateName}1`, fw.name),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Festal Menaion: Great feasts on fixed Julian dates (Typikon Ch. 47)
|
||||
const menaionFeast: Record<string, { id: string; name: string; type: string; desc: string }> = {
|
||||
'9-8': { id: 'nativitytheotokos', name: this.t.services.serviceNames.nativitytheotokos, type: 'NATIVITYTHEOTOKOS', desc: this.t.services.serviceDescriptions.nativitytheotokos },
|
||||
'9-14': { id: 'exaltation', name: this.t.services.serviceNames.exaltation, type: 'EXALTATION', desc: this.t.services.serviceDescriptions.exaltation },
|
||||
'11-21': { id: 'vvedenie', name: this.t.services.serviceNames.vvedenie, type: 'VVEDENIE', desc: this.t.services.serviceDescriptions.vvedenie },
|
||||
'12-24': { id: 'nativityhours', name: this.t.services.serviceNames.nativityhours, type: 'NATIVITYHOURS', desc: this.t.services.serviceDescriptions.nativityhours },
|
||||
'12-25': { id: 'nativity', name: this.t.services.serviceNames.nativity, type: 'NATIVITY', desc: this.t.services.serviceDescriptions.nativity },
|
||||
'1-5': { id: 'theophanyhours', name: this.t.services.serviceNames.theophanyhours, type: 'THEOPHANYHOURS', desc: this.t.services.serviceDescriptions.theophanyhours },
|
||||
'1-6': { id: 'theophany', name: this.t.services.serviceNames.theophany, type: 'THEOPHANY', desc: this.t.services.serviceDescriptions.theophany },
|
||||
'2-2': { id: 'sretenie', name: this.t.services.serviceNames.sretenie, type: 'SRETENIE', desc: this.t.services.serviceDescriptions.sretenie },
|
||||
'3-25': { id: 'annunciation', name: this.t.services.serviceNames.annunciation, type: 'ANNUNCIATION', desc: this.t.services.serviceDescriptions.annunciation },
|
||||
'6-24': { id: 'forerunnerbirth', name: this.t.services.serviceNames.forerunnerbirth, type: 'FORERUNNERBIRTH', desc: this.t.services.serviceDescriptions.forerunnerbirth },
|
||||
'6-29': { id: 'peterpaul', name: this.t.services.serviceNames.peterpaul, type: 'PETERPAUL', desc: this.t.services.serviceDescriptions.peterpaul },
|
||||
'8-6': { id: 'transfiguration', name: this.t.services.serviceNames.transfiguration, type: 'TRANSFIGURATION', desc: this.t.services.serviceDescriptions.transfiguration },
|
||||
'8-15': { id: 'dormition', name: this.t.services.serviceNames.dormition, type: 'DORMITION', desc: this.t.services.serviceDescriptions.dormition },
|
||||
'8-29': { id: 'forerunnerbeheading', name: this.t.services.serviceNames.forerunnerbeheading, type: 'FORERUNNERBEHEADING', desc: this.t.services.serviceDescriptions.forerunnerbeheading },
|
||||
// Middle feasts (fixed dates)
|
||||
'9-25': { id: 'sergius', name: this.t.services.serviceNames.sergius, type: 'SERGIUS', desc: this.t.services.serviceDescriptions.sergius },
|
||||
'9-26': { id: 'johntheologiansep', name: this.t.services.serviceNames.johntheologiansep, type: 'JOHNTHEOLOGIANSEP', desc: this.t.services.serviceDescriptions.johntheologiansep },
|
||||
'10-1': { id: 'pokrov', name: this.t.services.serviceNames.pokrov, type: 'POKROV', desc: this.t.services.serviceDescriptions.pokrov },
|
||||
'10-10': { id: 'ambrose', name: this.t.services.serviceNames.ambrose, type: 'AMBROSE', desc: this.t.services.serviceDescriptions.ambrose },
|
||||
'10-11': { id: 'seventhcouncilefathers', name: this.t.services.serviceNames.seventhcouncilefathers, type: 'SEVENTHCOUNCILFATHERS', desc: this.t.services.serviceDescriptions.seventhcouncilefathers },
|
||||
'10-22': { id: 'kazan', name: this.t.services.serviceNames.kazan, type: 'KAZAN', desc: this.t.services.serviceDescriptions.kazan },
|
||||
'10-26': { id: 'demetrius', name: this.t.services.serviceNames.demetrius, type: 'DEMETRIUS', desc: this.t.services.serviceDescriptions.demetrius },
|
||||
'11-8': { id: 'michaelsynaxis', name: this.t.services.serviceNames.michaelsynaxis, type: 'MICHAELSYNAXIS', desc: this.t.services.serviceDescriptions.michaelsynaxis },
|
||||
'12-6': { id: 'nicholas', name: this.t.services.serviceNames.nicholas, type: 'NICHOLAS', desc: this.t.services.serviceDescriptions.nicholas },
|
||||
'1-1': { id: 'circumcision', name: this.t.services.serviceNames.circumcision, type: 'CIRCUMCISION', desc: this.t.services.serviceDescriptions.circumcision },
|
||||
'2-24': { id: 'findinghead1st', name: this.t.services.serviceNames.findinghead1st, type: 'FINDINGHEAD1ST', desc: this.t.services.serviceDescriptions.findinghead1st },
|
||||
'3-9': { id: 'fortymartyrs', name: this.t.services.serviceNames.fortymartyrs, type: 'FORTYMARTYRS', desc: this.t.services.serviceDescriptions.fortymartyrs },
|
||||
'5-8': { id: 'johntheologianmay', name: this.t.services.serviceNames.johntheologianmay, type: 'JOHNTHEOLOGIANMAY', desc: this.t.services.serviceDescriptions.johntheologianmay },
|
||||
'5-9': { id: 'nicholastranslation', name: this.t.services.serviceNames.nicholastranslation, type: 'NICHOLASTRANSLATION', desc: this.t.services.serviceDescriptions.nicholastranslation },
|
||||
'5-25': { id: 'findinghead3rd', name: this.t.services.serviceNames.findinghead3rd, type: 'FINDINGHEAD3RD', desc: this.t.services.serviceDescriptions.findinghead3rd },
|
||||
'7-15': { id: 'vladimir', name: this.t.services.serviceNames.vladimir, type: 'VLADIMIR', desc: this.t.services.serviceDescriptions.vladimir },
|
||||
'7-16': { id: 'sixcouncilfathers', name: this.t.services.serviceNames.sixcouncilfathers, type: 'SIXCOUNCILFATHERS', desc: this.t.services.serviceDescriptions.sixcouncilfathers },
|
||||
'7-20': { id: 'elijah', name: this.t.services.serviceNames.elijah, type: 'ELIJAH', desc: this.t.services.serviceDescriptions.elijah },
|
||||
'7-27': { id: 'panteleimon', name: this.t.services.serviceNames.panteleimon, type: 'PANTELEIMON', desc: this.t.services.serviceDescriptions.panteleimon },
|
||||
'8-1': { id: 'processioncross', name: this.t.services.serviceNames.processioncross, type: 'PROCESSIONCROSS', desc: this.t.services.serviceDescriptions.processioncross },
|
||||
};
|
||||
const feast = menaionFeast[`${dayInfo.month}-${dayInfo.day}`];
|
||||
if (feast) {
|
||||
const templateName = feast.id.charAt(0).toUpperCase() + feast.id.slice(1);
|
||||
special.push({
|
||||
id: feast.id, name: feast.name, serviceType: feast.type,
|
||||
template: templateName,
|
||||
description: feast.desc,
|
||||
titleNode: title(`${templateName}1`, feast.name),
|
||||
});
|
||||
}
|
||||
// Movable Sundays of the Nativity season (dow-based)
|
||||
if (dayInfo.dow === 0 && dayInfo.month === 12) {
|
||||
const movable: { id: string; name: string; type: string; desc: string }[] = [];
|
||||
if (dayInfo.day >= 11 && dayInfo.day <= 17) {
|
||||
movable.push({ id: 'forefatherssunday', name: this.t.services.serviceNames.forefatherssunday, type: 'FOREFATHERSSUNDAY', desc: this.t.services.serviceDescriptions.forefatherssunday });
|
||||
} else if (dayInfo.day >= 18 && dayInfo.day <= 24) {
|
||||
movable.push({ id: 'holyfathersnativity', name: this.t.services.serviceNames.holyfathersnativity, type: 'HOLYFATHERSNATIVITY', desc: this.t.services.serviceDescriptions.holyfathersnativity });
|
||||
} else if (dayInfo.day >= 26 && dayInfo.day <= 31) {
|
||||
movable.push({ id: 'sundayafternativity', name: this.t.services.serviceNames.sundayafternativity, type: 'SUNDAYAFTERNATIVITY', desc: this.t.services.serviceDescriptions.sundayafternativity });
|
||||
}
|
||||
const mv = movable[0];
|
||||
if (mv) {
|
||||
const templateName = mv.id.charAt(0).toUpperCase() + mv.id.slice(1);
|
||||
special.push({
|
||||
id: mv.id, name: mv.name, serviceType: mv.type,
|
||||
template: templateName,
|
||||
description: mv.desc,
|
||||
titleNode: title(`${templateName}1`, mv.name),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Great Compline: Lenten weekdays (Mon-Thu)
|
||||
if (dayInfo.isLent && dayInfo.dow >= 1 && dayInfo.dow <= 4) {
|
||||
services.push({
|
||||
special.push({
|
||||
id: 'greatcompline', name: this.t.services.serviceNames.greatcompline, serviceType: 'GREATCOMPLINE',
|
||||
template: 'GreatCompline',
|
||||
description: this.t.services.serviceDescriptions.greatcompline,
|
||||
@@ -196,7 +415,7 @@ export class ServiceView {
|
||||
|
||||
// Standing of St. Mary of Egypt: Thursday of the 5th week of Great Lent
|
||||
if (dayInfo.isLent && dayInfo.nday === -17) {
|
||||
services.push({
|
||||
special.push({
|
||||
id: 'mariasstanding', name: this.t.services.serviceNames.mariasstanding, serviceType: 'MARIASSTANDING',
|
||||
template: 'MariasStanding',
|
||||
description: this.t.services.serviceDescriptions.mariasstanding,
|
||||
@@ -204,7 +423,96 @@ export class ServiceView {
|
||||
});
|
||||
}
|
||||
|
||||
return services;
|
||||
// Holy Week services
|
||||
if (dayInfo.isLent) {
|
||||
// Palm Sunday: Vespers + Matins
|
||||
if (dayInfo.nday === -7) {
|
||||
special.push({
|
||||
id: 'palmsunday', name: this.t.services.serviceNames.palmsunday, serviceType: 'PALMSUNDAY',
|
||||
template: 'PalmSunday',
|
||||
description: this.t.services.serviceDescriptions.palmsunday,
|
||||
titleNode: title('PalmSunday1', this.t.services.serviceNames.palmsunday),
|
||||
});
|
||||
}
|
||||
// Great Monday through Thursday: daily cycle (Matins, Hours, Typica, Vespers)
|
||||
const greatDay: Record<number, { id: string; name: string; type: string; desc: string }> = {
|
||||
[-6]: { id: 'greatmonday', name: this.t.services.serviceNames.greatmonday, type: 'GREATMONDAY', desc: this.t.services.serviceDescriptions.greatmonday },
|
||||
[-5]: { id: 'greattuesday', name: this.t.services.serviceNames.greattuesday, type: 'GREATTUESDAY', desc: this.t.services.serviceDescriptions.greattuesday },
|
||||
[-4]: { id: 'greatwednesday', name: this.t.services.serviceNames.greatwednesday, type: 'GREATWEDNESDAY', desc: this.t.services.serviceDescriptions.greatwednesday },
|
||||
[-3]: { id: 'greatthursday', name: this.t.services.serviceNames.greatthursday, type: 'GREATTHURSDAY', desc: this.t.services.serviceDescriptions.greatthursday },
|
||||
};
|
||||
const gd = greatDay[dayInfo.nday];
|
||||
if (gd) {
|
||||
special.push({
|
||||
id: gd.id, name: gd.name, serviceType: gd.type,
|
||||
template: gd.id.charAt(0).toUpperCase() + gd.id.slice(1),
|
||||
description: gd.desc,
|
||||
titleNode: title(`${gd.id.charAt(0).toUpperCase() + gd.id.slice(1)}1`, gd.name),
|
||||
});
|
||||
}
|
||||
// Matins of the 12 Passion Gospels: Great Thursday evening (Great Friday Matins)
|
||||
if (dayInfo.nday === -3) {
|
||||
special.push({
|
||||
id: 'passiongospels', name: this.t.services.serviceNames.passiongospels, serviceType: 'PASSIONGOSPELS',
|
||||
template: 'PassionGospels',
|
||||
description: this.t.services.serviceDescriptions.passiongospels,
|
||||
titleNode: title('PassionGospels1', this.t.services.serviceNames.passiongospels),
|
||||
});
|
||||
}
|
||||
// Royal Hours of Great Friday
|
||||
if (dayInfo.nday === -2) {
|
||||
special.push({
|
||||
id: 'royalhoursfriday', name: this.t.services.serviceNames.royalhoursfriday, serviceType: 'ROYALHOURSFRIDAY',
|
||||
template: 'RoyalHoursFriday',
|
||||
description: this.t.services.serviceDescriptions.royalhoursfriday,
|
||||
titleNode: title('RoyalHoursFriday1', this.t.services.serviceNames.royalhoursfriday),
|
||||
});
|
||||
}
|
||||
// Lamentations Matins: Great Saturday Matins (served Friday night)
|
||||
if (dayInfo.nday === -1) {
|
||||
special.push({
|
||||
id: 'lamentations', name: this.t.services.serviceNames.lamentations, serviceType: 'LAMENTATIONS',
|
||||
template: 'Lamentations',
|
||||
description: this.t.services.serviceDescriptions.lamentations,
|
||||
titleNode: title('Lamentations1', this.t.services.serviceNames.lamentations),
|
||||
});
|
||||
}
|
||||
// Vespers of the Burial + cell Compline: Great Friday evening
|
||||
if (dayInfo.nday === -2) {
|
||||
special.push({
|
||||
id: 'burialvespers', name: this.t.services.serviceNames.burialvespers, serviceType: 'BURIALVESPERS',
|
||||
template: 'BurialVespers',
|
||||
description: this.t.services.serviceDescriptions.burialvespers,
|
||||
titleNode: title('BurialVespers1', this.t.services.serviceNames.burialvespers),
|
||||
});
|
||||
}
|
||||
// Holy Saturday: Hours, Vespers+Liturgy of St. Basil, Midnight Office
|
||||
if (dayInfo.nday === -1) {
|
||||
special.push({
|
||||
id: 'saturdayhours', name: this.t.services.serviceNames.saturdayhours, serviceType: 'SATURDAYHOURS',
|
||||
template: 'SaturdayHours',
|
||||
description: this.t.services.serviceDescriptions.saturdayhours,
|
||||
titleNode: title('SaturdayHours1', this.t.services.serviceNames.saturdayhours),
|
||||
});
|
||||
special.push({
|
||||
id: 'saturdayliturgy', name: this.t.services.serviceNames.saturdayliturgy, serviceType: 'SATURDAYLITURGY',
|
||||
template: 'SaturdayVespersLiturgy',
|
||||
description: this.t.services.serviceDescriptions.saturdayliturgy,
|
||||
titleNode: title('SaturdayVespersLiturgy1', this.t.services.serviceNames.saturdayliturgy),
|
||||
});
|
||||
special.push({
|
||||
id: 'saturdaymidnight', name: this.t.services.serviceNames.saturdaymidnight, serviceType: 'SATURDAYMIDNIGHT',
|
||||
template: 'SaturdayMidnight',
|
||||
description: this.t.services.serviceDescriptions.saturdaymidnight,
|
||||
titleNode: title('SaturdayMidnight1', this.t.services.serviceNames.saturdaymidnight),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (special.length > 0 && daily.length > 0) {
|
||||
daily[0].divider = true;
|
||||
}
|
||||
return [...special, ...daily];
|
||||
}
|
||||
|
||||
private async loadToneData(serviceType: string): Promise<{ troparion1?: string; kontakion1?: string; theotokion1?: string; prokimenon1?: string; alleluia1?: string; hypakoe1?: string } | null> {
|
||||
@@ -376,6 +684,46 @@ export class ServiceView {
|
||||
}
|
||||
}
|
||||
|
||||
private async loadParacleteCanon(tone: number, dow: number): Promise<ServiceNode[] | null> {
|
||||
if (tone < 1 || tone > 8) return null;
|
||||
const WEEKDAY = ['', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'];
|
||||
const dayKey = WEEKDAY[dow] ?? '';
|
||||
if (!dayKey) return null;
|
||||
const url = `/data/shared/services/canons/paraclete/tone${tone}/${dayKey}.json`;
|
||||
try {
|
||||
const resp = await fetch(url);
|
||||
if (!resp.ok) return null;
|
||||
const nodes: ServiceNode[] = await resp.json();
|
||||
return nodes;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async loadMenaionDay(dateKey: string, index: number): Promise<ServiceNode[] | null> {
|
||||
const url = `/data/shared/menaion-daily/${dateKey}/${index}.json`;
|
||||
try {
|
||||
const resp = await fetch(url);
|
||||
if (!resp.ok) return null;
|
||||
const nodes: ServiceNode[] = await resp.json();
|
||||
return nodes;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async loadTriodion(index: number): Promise<ServiceNode[] | null> {
|
||||
const url = `/data/shared/triodion/${String(index).padStart(2, '0')}.json`;
|
||||
try {
|
||||
const resp = await fetch(url);
|
||||
if (!resp.ok) return null;
|
||||
const nodes: ServiceNode[] = await resp.json();
|
||||
return nodes;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async loadMariasStandingData(): Promise<ServiceNode[] | null> {
|
||||
const url = `/data/shared/services/marias-standing/full.json`;
|
||||
try {
|
||||
@@ -388,6 +736,18 @@ export class ServiceView {
|
||||
}
|
||||
}
|
||||
|
||||
private async loadHolyWeekData(service: string): Promise<ServiceNode[] | null> {
|
||||
const url = `/data/shared/services/${service}/full.json`;
|
||||
try {
|
||||
const resp = await fetch(url);
|
||||
if (!resp.ok) return null;
|
||||
const nodes: ServiceNode[] = await resp.json();
|
||||
return nodes;
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private async loadGreatCanonData(): Promise<ServiceNode[] | null> {
|
||||
const computed = computeDay(this.currentDate);
|
||||
const { dayInfo } = computed;
|
||||
@@ -464,7 +824,7 @@ export class ServiceView {
|
||||
private generateVarNodes(toneData: { troparion1?: string; kontakion1?: string; theotokion1?: string; prokimenon1?: string; alleluia1?: string; hypakoe1?: string } | null, serviceType: string): Map<string, ServiceNode[]> {
|
||||
const varNodes = new Map<string, ServiceNode[]>();
|
||||
|
||||
const prefix: Record<string, string> = { PRIMES: '', TERCE: '3', SEXTE: '6', NONE: '9', VESPERS: 'V', LITURGY: 'L', MATINS: 'U', GREATCOMPLINE: 'GC', MARIASSTANDING: 'MS' };
|
||||
const prefix: Record<string, string> = { PRIMES: '', TERCE: '3', SEXTE: '6', NONE: '9', VESPERS: 'V', LITURGY: 'L', MATINS: 'U', GREATCOMPLINE: 'GC', MARIASSTANDING: 'MS', PASSIONGOSPELS: 'PG', ROYALHOURSFRIDAY: 'RF', LAMENTATIONS: 'LM', PALMSUNDAY: 'PS', GREATMONDAY: 'GM', GREATTUESDAY: 'GT', GREATWEDNESDAY: 'GW', GREATTHURSDAY: 'GTH', BURIALVESPERS: 'BV', SATURDAYHOURS: 'SH', SATURDAYLITURGY: 'SL', SATURDAYMIDNIGHT: 'SM', PASCHA: 'PA', BRIGHTMONDAY: 'BM', BRIGHTTUESDAY: 'BT', BRIGHTWEDNESDAY: 'BW', BRIGHTTHURSDAY: 'BTH', BRIGHTFRIDAY: 'BF', BRIGHTSATURDAY: 'BS', ANTIPASCHA: 'AP', MYRRHBEARERS: 'MB', PARALYTIC: 'PL', PREPOLOVENIE: 'PP', SAMARITAN: 'SA', BLINDMAN: 'BM', APODOSIS: 'AD', ASCENSION: 'AS', HOLYFATHERS: 'HF', PENTECOSTSATURDAY: 'PSA', PENTECOST: 'PE', HOLYSPIRIT: 'HS', ALLSAINTS: 'AL', RUSSIANSAINTS: 'RS', FIRSTWEEKMONDAY: 'FM', FIRSTWEEKTUESDAY: 'FT', FIRSTWEEKWEDNESDAY: 'FW', FIRSTWEEKTHURSDAY: 'FTH', FIRSTWEEKFRIDAY: 'FF', FIRSTWEEKSATURDAY: 'FS', NATIVITYTHEOTOKOS: 'NT', EXALTATION: 'EX', VVEDENIE: 'VV', NATIVITYHOURS: 'NH', NATIVITY: 'NA', THEOPHANYHOURS: 'TH', THEOPHANY: 'TP', SRETENIE: 'SR', ANNUNCIATION: 'AN', FORERUNNERBIRTH: 'FB', PETERPAUL: 'PP', TRANSFIGURATION: 'TR', DORMITION: 'DO', FORERUNNERBEHEADING: 'FH', SERGIUS: 'SE', JOHNTHEOLOGIANSEP: 'JT', POKROV: 'PO', AMBROSE: 'AM', SEVENTHCOUNCILFATHERS: 'SC', KAZAN: 'KZ', DEMETRIUS: 'DE', MICHAELSYNAXIS: 'MS', NICHOLAS: 'NI', CIRCUMCISION: 'CI', FINDINGHEAD1ST: 'F1', FORTYMARTYRS: 'FM', JOHNTHEOLOGIANMAY: 'JM', NICHOLASTRANSLATION: 'NT', FINDINGHEAD3RD: 'F3', VLADIMIR: 'VL', SIXCOUNCILFATHERS: 'XC', ELIJAH: 'EL', PANTELEIMON: 'PA', PROCESSIONCROSS: 'PC', FOREFATHERSSUNDAY: 'FD', HOLYFATHERSNATIVITY: 'HFN', SUNDAYAFTERNATIVITY: 'SAN' };
|
||||
const p = prefix[serviceType] ?? '';
|
||||
|
||||
if (toneData?.troparion1) {
|
||||
@@ -593,9 +953,35 @@ export class ServiceView {
|
||||
// Load Matins canon data
|
||||
if (service.serviceType === 'MATINS') {
|
||||
const computed = computeDay(this.currentDate);
|
||||
const canonNodes = await this.loadCanonData(computed.dayInfo.Tone);
|
||||
if (canonNodes) {
|
||||
varNodes.set('PCanonU', canonNodes);
|
||||
const tone = computed.dayInfo.Tone;
|
||||
const dow = computed.dayInfo.dow;
|
||||
// Weekdays (Mon-Sat): use the Параклитика weekday canons; Sunday: Octoechos Sunday canon
|
||||
if (dow >= 1 && dow <= 6) {
|
||||
const paracleteNodes = await this.loadParacleteCanon(tone, dow);
|
||||
if (paracleteNodes) {
|
||||
varNodes.set('PCanonU', paracleteNodes);
|
||||
}
|
||||
} else {
|
||||
const canonNodes = await this.loadCanonData(tone);
|
||||
if (canonNodes) {
|
||||
varNodes.set('PCanonU', canonNodes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Load Daily Menaion service (Служба дня)
|
||||
if (service.serviceType === 'MENAIONDAY' && service.menaionDateKey && service.menaionDayIndex) {
|
||||
const dayNodes = await this.loadMenaionDay(service.menaionDateKey, service.menaionDayIndex);
|
||||
if (dayNodes) {
|
||||
varNodes.set('PMenaionDay', dayNodes);
|
||||
}
|
||||
}
|
||||
|
||||
// Load Triodion movable-day service
|
||||
if (service.serviceType === 'TRIODION' && service.triodionIndex) {
|
||||
const triodionNodes = await this.loadTriodion(service.triodionIndex);
|
||||
if (triodionNodes) {
|
||||
varNodes.set('PTriodion', triodionNodes);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -615,6 +1001,169 @@ export class ServiceView {
|
||||
}
|
||||
}
|
||||
|
||||
// Load Holy Week service data
|
||||
const holyWeekVarMap: Record<string, string> = {
|
||||
PALMSUNDAY: 'PPalmSunday',
|
||||
GREATMONDAY: 'PGreatMonday',
|
||||
GREATTUESDAY: 'PGreatTuesday',
|
||||
GREATWEDNESDAY: 'PGreatWednesday',
|
||||
GREATTHURSDAY: 'PGreatThursday',
|
||||
PASSIONGOSPELS: 'PPassionGospels',
|
||||
ROYALHOURSFRIDAY: 'PRoyalHoursFriday',
|
||||
LAMENTATIONS: 'PLamentations',
|
||||
BURIALVESPERS: 'PBurialVespers',
|
||||
SATURDAYHOURS: 'PSaturdayHours',
|
||||
SATURDAYLITURGY: 'PSaturdayVespersLiturgy',
|
||||
SATURDAYMIDNIGHT: 'PSaturdayMidnight',
|
||||
PASCHA: 'PPascha',
|
||||
BRIGHTMONDAY: 'PBrightMonday',
|
||||
BRIGHTTUESDAY: 'PBrightTuesday',
|
||||
BRIGHTWEDNESDAY: 'PBrightWednesday',
|
||||
BRIGHTTHURSDAY: 'PBrightThursday',
|
||||
BRIGHTFRIDAY: 'PBrightFriday',
|
||||
BRIGHTSATURDAY: 'PBrightSaturday',
|
||||
ANTIPASCHA: 'PAntipascha',
|
||||
MYRRHBEARERS: 'PMyrrhbearers',
|
||||
PARALYTIC: 'PParalytic',
|
||||
PREPOLOVENIE: 'PPrepolovenie',
|
||||
SAMARITAN: 'PSamaritan',
|
||||
BLINDMAN: 'PBlindMan',
|
||||
APODOSIS: 'PApodosis',
|
||||
ASCENSION: 'PAscension',
|
||||
HOLYFATHERS: 'PHolyFathers',
|
||||
PENTECOSTSATURDAY: 'PPentecostSaturday',
|
||||
PENTECOST: 'PPentecost',
|
||||
HOLYSPIRIT: 'PHolySpirit',
|
||||
ALLSAINTS: 'PAllSaints',
|
||||
RUSSIANSAINTS: 'PRussianSaints',
|
||||
FIRSTWEEKMONDAY: 'PFirstWeekMonday',
|
||||
FIRSTWEEKTUESDAY: 'PFirstWeekTuesday',
|
||||
FIRSTWEEKWEDNESDAY: 'PFirstWeekWednesday',
|
||||
FIRSTWEEKTHURSDAY: 'PFirstWeekThursday',
|
||||
FIRSTWEEKFRIDAY: 'PFirstWeekFriday',
|
||||
FIRSTWEEKSATURDAY: 'PFirstWeekSaturday',
|
||||
NATIVITYTHEOTOKOS: 'PNativityTheotokos',
|
||||
EXALTATION: 'PExaltation',
|
||||
VVEDENIE: 'PVvedenie',
|
||||
NATIVITYHOURS: 'PNativityHours',
|
||||
NATIVITY: 'PNativity',
|
||||
THEOPHANYHOURS: 'PTheophanyHours',
|
||||
THEOPHANY: 'PTheophany',
|
||||
SRETENIE: 'PSretenie',
|
||||
ANNUNCIATION: 'PAnnunciation',
|
||||
FORERUNNERBIRTH: 'PForerunnerBirth',
|
||||
PETERPAUL: 'PPeterPaul',
|
||||
TRANSFIGURATION: 'PTransfiguration',
|
||||
DORMITION: 'PDormition',
|
||||
FORERUNNERBEHEADING: 'PForerunnerBeheading',
|
||||
SERGIUS: 'PSergius',
|
||||
JOHNTHEOLOGIANSEP: 'PJohnTheologianSep',
|
||||
POKROV: 'PPokrov',
|
||||
AMBROSE: 'PAmbrose',
|
||||
SEVENTHCOUNCILFATHERS: 'PSeventhCouncilFathers',
|
||||
KAZAN: 'PKazan',
|
||||
DEMETRIUS: 'PDemetrius',
|
||||
MICHAELSYNAXIS: 'PMichaelSynaxis',
|
||||
NICHOLAS: 'PNicholas',
|
||||
CIRCUMCISION: 'PCircumcision',
|
||||
FINDINGHEAD1ST: 'PFindingHead1st',
|
||||
FORTYMARTYRS: 'PFortyMartyrs',
|
||||
JOHNTHEOLOGIANMAY: 'PJohnTheologianMay',
|
||||
NICHOLASTRANSLATION: 'PNicholasTranslation',
|
||||
FINDINGHEAD3RD: 'PFindingHead3rd',
|
||||
VLADIMIR: 'PVladimir',
|
||||
SIXCOUNCILFATHERS: 'PSixCouncilsFathers',
|
||||
ELIJAH: 'PElijah',
|
||||
PANTELEIMON: 'PPanteleimon',
|
||||
PROCESSIONCROSS: 'PProcessionCross',
|
||||
FOREFATHERSSUNDAY: 'PForefathersSunday',
|
||||
HOLYFATHERSNATIVITY: 'PHolyFathersNativity',
|
||||
SUNDAYAFTERNATIVITY: 'PSundayAfterNativity',
|
||||
};
|
||||
const holyWeekDir: Record<string, string> = {
|
||||
PALMSUNDAY: 'palm-sunday',
|
||||
GREATMONDAY: 'great-monday',
|
||||
GREATTUESDAY: 'great-tuesday',
|
||||
GREATWEDNESDAY: 'great-wednesday',
|
||||
GREATTHURSDAY: 'great-thursday',
|
||||
PASSIONGOSPELS: 'passion-gospels',
|
||||
ROYALHOURSFRIDAY: 'royal-hours-friday',
|
||||
LAMENTATIONS: 'lamentations',
|
||||
BURIALVESPERS: 'burial-vespers',
|
||||
SATURDAYHOURS: 'saturday-hours',
|
||||
SATURDAYLITURGY: 'saturday-vespers-liturgy',
|
||||
SATURDAYMIDNIGHT: 'saturday-midnight',
|
||||
PASCHA: 'pascha',
|
||||
BRIGHTMONDAY: 'bright-monday',
|
||||
BRIGHTTUESDAY: 'bright-tuesday',
|
||||
BRIGHTWEDNESDAY: 'bright-wednesday',
|
||||
BRIGHTTHURSDAY: 'bright-thursday',
|
||||
BRIGHTFRIDAY: 'bright-friday',
|
||||
BRIGHTSATURDAY: 'bright-saturday',
|
||||
ANTIPASCHA: 'antipascha',
|
||||
MYRRHBEARERS: 'myrrhbearers',
|
||||
PARALYTIC: 'paralytic',
|
||||
PREPOLOVENIE: 'prepolovenie',
|
||||
SAMARITAN: 'samaritan',
|
||||
BLINDMAN: 'blindman',
|
||||
APODOSIS: 'apodosis',
|
||||
ASCENSION: 'ascension',
|
||||
HOLYFATHERS: 'holyfathers',
|
||||
PENTECOSTSATURDAY: 'pentecostsaturday',
|
||||
PENTECOST: 'pentecost',
|
||||
HOLYSPIRIT: 'holyspirit',
|
||||
ALLSAINTS: 'allsaints',
|
||||
RUSSIANSAINTS: 'russiansaints',
|
||||
FIRSTWEEKMONDAY: 'first-week-monday',
|
||||
FIRSTWEEKTUESDAY: 'first-week-tuesday',
|
||||
FIRSTWEEKWEDNESDAY: 'first-week-wednesday',
|
||||
FIRSTWEEKTHURSDAY: 'first-week-thursday',
|
||||
FIRSTWEEKFRIDAY: 'first-week-friday',
|
||||
FIRSTWEEKSATURDAY: 'first-week-saturday',
|
||||
NATIVITYTHEOTOKOS: 'nativity-theotokos',
|
||||
EXALTATION: 'exaltation',
|
||||
VVEDENIE: 'vvedenie',
|
||||
NATIVITYHOURS: 'nativity-hours',
|
||||
NATIVITY: 'nativity',
|
||||
THEOPHANYHOURS: 'theophany-hours',
|
||||
THEOPHANY: 'theophany',
|
||||
SRETENIE: 'sretenie',
|
||||
ANNUNCIATION: 'annunciation',
|
||||
FORERUNNERBIRTH: 'forerunner-birth',
|
||||
PETERPAUL: 'peter-paul',
|
||||
TRANSFIGURATION: 'transfiguration',
|
||||
DORMITION: 'dormition',
|
||||
FORERUNNERBEHEADING: 'forerunner-beheading',
|
||||
SERGIUS: 'sergius',
|
||||
JOHNTHEOLOGIANSEP: 'johntheologian-sep',
|
||||
POKROV: 'pokrov',
|
||||
AMBROSE: 'ambrose',
|
||||
SEVENTHCOUNCILFATHERS: 'seventh-council-fathers',
|
||||
KAZAN: 'kazan',
|
||||
DEMETRIUS: 'demetrius',
|
||||
MICHAELSYNAXIS: 'michael-synaxis',
|
||||
NICHOLAS: 'nicholas',
|
||||
CIRCUMCISION: 'circumcision',
|
||||
FINDINGHEAD1ST: 'finding-head-1st',
|
||||
FORTYMARTYRS: 'forty-martyrs',
|
||||
JOHNTHEOLOGIANMAY: 'johntheologian-may',
|
||||
NICHOLASTRANSLATION: 'nicholas-translation',
|
||||
FINDINGHEAD3RD: 'finding-head-3rd',
|
||||
VLADIMIR: 'vladimir',
|
||||
SIXCOUNCILFATHERS: 'six-councils-fathers',
|
||||
ELIJAH: 'elijah',
|
||||
PANTELEIMON: 'panteleimon',
|
||||
PROCESSIONCROSS: 'procession-cross',
|
||||
FOREFATHERSSUNDAY: 'forefathers-sunday',
|
||||
HOLYFATHERSNATIVITY: 'holy-fathers-nativity',
|
||||
SUNDAYAFTERNATIVITY: 'sunday-after-nativity',
|
||||
};
|
||||
const hwVar = holyWeekVarMap[service.serviceType];
|
||||
if (hwVar) {
|
||||
const nodes = await this.loadHolyWeekData(holyWeekDir[service.serviceType]);
|
||||
if (nodes) varNodes.set(hwVar, nodes);
|
||||
}
|
||||
|
||||
// Load Epistle and Gospel readings from commemoration
|
||||
const loadReadings = async () => {
|
||||
const ids: string[] = [];
|
||||
|
||||
Reference in new issue
Block a user