Compare commits
No commits in common. "4eeed4b1e999181973d3d38b2c187c36439f2833" and "71ac3aae26a981859573e7d1a628700f72104a4c" have entirely different histories.
4eeed4b1e9
...
71ac3aae26
11 changed files with 385 additions and 649 deletions
|
|
@ -1,53 +1,25 @@
|
|||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: deploy-main
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
deploy:
|
||||
runs-on: self-hosted
|
||||
runs-on: docker
|
||||
steps:
|
||||
- name: Build Astro and restart Nomad
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restart Nomad allocation
|
||||
env:
|
||||
NOMAD_ADDR: ${{ secrets.NOMAD_ADDR }}
|
||||
NOMAD_TOKEN: ${{ secrets.NOMAD_TOKEN }}
|
||||
REPO_URL: https://git.bcgen.ie/familyfedie/familyfedie-website.git
|
||||
run: |
|
||||
set -eu
|
||||
rm -rf source
|
||||
export REF_NAME="${GITHUB_REF_NAME:-main}"
|
||||
|
||||
nix --extra-experimental-features "nix-command flakes" \
|
||||
shell nixpkgs#git \
|
||||
-c git clone --depth 1 --branch "$REF_NAME" "$REPO_URL" source
|
||||
|
||||
cd source
|
||||
nix --extra-experimental-features "nix-command flakes" \
|
||||
shell nixpkgs#nodejs_24 \
|
||||
-c npm ci
|
||||
rm -rf dist
|
||||
nix --extra-experimental-features "nix-command flakes" \
|
||||
shell nixpkgs#nodejs_24 \
|
||||
-c npm run build
|
||||
|
||||
test -f dist/index.html
|
||||
test -f dist/speeches/index.html
|
||||
test -f dist/assets/icons/familyfed-favicon.png
|
||||
|
||||
ALLOC_ID=$(nix --extra-experimental-features "nix-command flakes" \
|
||||
shell nixpkgs#curl nixpkgs#jq \
|
||||
-c sh -c 'curl -sf -H "X-Nomad-Token: $NOMAD_TOKEN" "$NOMAD_ADDR/v1/job/familyfed/allocations" | jq -r "map(select(.ClientStatus == \"running\"))[0].ID"')
|
||||
|
||||
test -n "$ALLOC_ID"
|
||||
test "$ALLOC_ID" != "null"
|
||||
set -e
|
||||
ALLOC_ID=$(curl -sf \
|
||||
-H "X-Nomad-Token: $NOMAD_TOKEN" \
|
||||
"$NOMAD_ADDR/v1/job/familyfed/allocations" \
|
||||
| python3 -c "import sys,json; allocs=json.load(sys.stdin); print(next(a['ID'] for a in allocs if a['ClientStatus']=='running'))")
|
||||
echo "Stopping allocation to trigger fresh prestart: $ALLOC_ID"
|
||||
nix --extra-experimental-features "nix-command flakes" \
|
||||
shell nixpkgs#curl \
|
||||
-c curl -sf -X POST \
|
||||
curl -sf -X POST \
|
||||
-H "X-Nomad-Token: $NOMAD_TOKEN" \
|
||||
"$NOMAD_ADDR/v1/allocation/$ALLOC_ID/stop"
|
||||
echo "Deploy triggered. Nomad will schedule a new alloc that re-fetches the site."
|
||||
echo "Deploy triggered — Nomad will schedule a new alloc that re-fetches the site."
|
||||
|
|
|
|||
Binary file not shown.
|
Before Width: | Height: | Size: 160 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 73 KiB |
|
|
@ -1,7 +1,6 @@
|
|||
import { defineConfig } from "astro/config";
|
||||
|
||||
export default defineConfig({
|
||||
site: "https://familyfed.ie",
|
||||
output: "static",
|
||||
outDir: "dist",
|
||||
build: {
|
||||
|
|
|
|||
490
css/site.css
490
css/site.css
|
|
@ -30,7 +30,7 @@ body.custom-background { background-color: #ffffff; }
|
|||
|
||||
.speech-filters {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(240px, 2fr) repeat(2, minmax(150px, 1fr)) auto;
|
||||
grid-template-columns: minmax(240px, 2fr) repeat(3, minmax(150px, 1fr)) auto;
|
||||
gap: 12px;
|
||||
align-items: end;
|
||||
margin: 0 0 18px;
|
||||
|
|
@ -100,16 +100,18 @@ body.custom-background { background-color: #ffffff; }
|
|||
}
|
||||
|
||||
.speech-result p {
|
||||
margin: 0;
|
||||
margin: 0 0 10px;
|
||||
}
|
||||
|
||||
.speech-result-meta {
|
||||
.speech-result-meta,
|
||||
.speech-result-categories {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.speech-result-meta span {
|
||||
.speech-result-meta span,
|
||||
.speech-result-categories span {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
min-height: 22px;
|
||||
|
|
@ -156,6 +158,238 @@ body.custom-background { background-color: #ffffff; }
|
|||
}
|
||||
}
|
||||
|
||||
/* Events calendar. */
|
||||
.events-page-shell {
|
||||
box-sizing: border-box;
|
||||
width: min(1100px, calc(100% - 40px));
|
||||
margin: 0 auto;
|
||||
padding: 28px 0 44px;
|
||||
}
|
||||
|
||||
.events-page-header {
|
||||
margin: 0 0 22px;
|
||||
}
|
||||
|
||||
.events-page-kicker {
|
||||
margin: 0 0 6px;
|
||||
color: #5f7f38;
|
||||
font-size: 13px;
|
||||
font-weight: 700;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.events-page-header h1,
|
||||
.events-calendar-heading h2,
|
||||
.events-past h2,
|
||||
.events-past-item h3 {
|
||||
color: #2f332c;
|
||||
}
|
||||
|
||||
.events-page-header h1 {
|
||||
margin: 0 0 8px;
|
||||
font-size: 32px;
|
||||
line-height: 1.18;
|
||||
}
|
||||
|
||||
.events-page-header p:last-child {
|
||||
max-width: 680px;
|
||||
margin: 0;
|
||||
color: #5a5d56;
|
||||
font-size: 16px;
|
||||
line-height: 1.55;
|
||||
}
|
||||
|
||||
.events-calendar-panel,
|
||||
.events-past {
|
||||
border: 1px solid #e5e2d8;
|
||||
border-radius: 8px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.events-calendar-panel {
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.events-calendar-heading {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 12px 18px;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding: 20px 22px;
|
||||
border-bottom: 1px solid #e5e2d8;
|
||||
background: #fafbf7;
|
||||
}
|
||||
|
||||
.events-calendar-heading h2,
|
||||
.events-past h2 {
|
||||
margin: 0;
|
||||
font-size: 24px;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.events-calendar-heading p {
|
||||
margin: 0;
|
||||
padding: 7px 11px;
|
||||
border: 1px solid #d6e3c1;
|
||||
border-radius: 999px;
|
||||
color: #3d662c;
|
||||
background: #f0f7e8;
|
||||
font-size: 14px;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.events-calendar-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||
background: #e9e5db;
|
||||
gap: 1px;
|
||||
}
|
||||
|
||||
.events-calendar-weekday,
|
||||
.events-calendar-day {
|
||||
box-sizing: border-box;
|
||||
min-width: 0;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.events-calendar-weekday {
|
||||
min-height: 42px;
|
||||
padding: 12px 8px;
|
||||
color: #676961;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
line-height: 1.2;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.events-calendar-day {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
min-height: 92px;
|
||||
padding: 10px;
|
||||
color: #34372f;
|
||||
font-size: 15px;
|
||||
font-weight: 700;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.events-calendar-day--weekend {
|
||||
background: #fbfaf7;
|
||||
}
|
||||
|
||||
.events-calendar-day--outside-month {
|
||||
color: #97978f;
|
||||
background: #f5f4ef;
|
||||
}
|
||||
|
||||
.events-calendar-day--today {
|
||||
color: #ffffff;
|
||||
background: #5f7f38;
|
||||
}
|
||||
|
||||
.events-past {
|
||||
margin-top: 24px;
|
||||
padding: 22px;
|
||||
}
|
||||
|
||||
.events-past-list {
|
||||
display: grid;
|
||||
gap: 14px;
|
||||
margin-top: 16px;
|
||||
}
|
||||
|
||||
.events-past-item {
|
||||
display: grid;
|
||||
grid-template-columns: 76px minmax(0, 1fr);
|
||||
gap: 16px;
|
||||
align-items: center;
|
||||
padding: 14px;
|
||||
border: 1px solid #ece8dd;
|
||||
border-radius: 6px;
|
||||
background: #fdfdfb;
|
||||
}
|
||||
|
||||
.events-past-date {
|
||||
display: grid;
|
||||
place-items: center;
|
||||
min-height: 76px;
|
||||
border: 1px solid #d9d3c5;
|
||||
border-radius: 6px;
|
||||
color: #575b50;
|
||||
background: #ffffff;
|
||||
line-height: 1.1;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.events-past-date strong {
|
||||
color: #bf4d28;
|
||||
font-size: 27px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.events-past-date span {
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.events-past-item p {
|
||||
margin: 0 0 4px;
|
||||
color: #6b6d66;
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.events-past-item h3 {
|
||||
margin: 0;
|
||||
font-size: 20px;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
@media (max-width: 760px) {
|
||||
.events-page-shell {
|
||||
width: min(100% - 24px, 1100px);
|
||||
padding-top: 20px;
|
||||
}
|
||||
|
||||
.events-page-header h1 {
|
||||
font-size: 27px;
|
||||
}
|
||||
|
||||
.events-calendar-heading,
|
||||
.events-past {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.events-calendar-grid {
|
||||
overflow-x: auto;
|
||||
grid-template-columns: repeat(7, minmax(52px, 1fr));
|
||||
}
|
||||
|
||||
.events-calendar-weekday {
|
||||
min-height: 36px;
|
||||
padding: 10px 4px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.events-calendar-day {
|
||||
min-height: 58px;
|
||||
padding: 8px;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.events-past-item {
|
||||
grid-template-columns: 64px minmax(0, 1fr);
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.events-past-date {
|
||||
min-height: 64px;
|
||||
}
|
||||
}
|
||||
|
||||
/* Contact page form. */
|
||||
.contact-form {
|
||||
display: grid;
|
||||
|
|
@ -214,251 +448,3 @@ body.custom-background { background-color: #ffffff; }
|
|||
margin: 0;
|
||||
color: #5c5c56;
|
||||
}
|
||||
|
||||
/* Static events calendar. */
|
||||
.events-calendar-page .entry-content {
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.familyfed-calendar {
|
||||
display: grid;
|
||||
gap: 16px;
|
||||
}
|
||||
|
||||
.calendar-toolbar,
|
||||
.calendar-actions {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.calendar-toolbar {
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.calendar-title {
|
||||
margin: 0;
|
||||
color: #333333;
|
||||
font-size: 28px;
|
||||
line-height: 1.2;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.calendar-nav-button,
|
||||
.calendar-secondary-button {
|
||||
min-height: 38px;
|
||||
border: 1px solid #d8d8d0;
|
||||
border-radius: 4px;
|
||||
color: #333333;
|
||||
background: #ffffff;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.calendar-nav-button {
|
||||
width: 42px;
|
||||
font-size: 26px;
|
||||
line-height: 1;
|
||||
}
|
||||
|
||||
.calendar-secondary-button {
|
||||
padding: 8px 12px;
|
||||
}
|
||||
|
||||
.calendar-nav-button:hover,
|
||||
.calendar-nav-button:focus,
|
||||
.calendar-secondary-button:hover,
|
||||
.calendar-secondary-button:focus {
|
||||
border-color: #bf4d28;
|
||||
color: #bf4d28;
|
||||
}
|
||||
|
||||
.calendar-layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) minmax(240px, 300px);
|
||||
gap: 18px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.calendar-grid-wrap,
|
||||
.calendar-panel {
|
||||
border: 1px solid #eeeeee;
|
||||
border-radius: 6px;
|
||||
background: #ffffff;
|
||||
}
|
||||
|
||||
.calendar-weekdays,
|
||||
.calendar-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(7, minmax(0, 1fr));
|
||||
}
|
||||
|
||||
.calendar-weekdays {
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
background: #fbfbf8;
|
||||
}
|
||||
|
||||
.calendar-weekdays span {
|
||||
padding: 10px 8px;
|
||||
color: #5c5c56;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-align: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.calendar-day {
|
||||
display: grid;
|
||||
grid-template-rows: auto 1fr;
|
||||
gap: 6px;
|
||||
min-height: 112px;
|
||||
padding: 8px;
|
||||
border: 0;
|
||||
border-right: 1px solid #eeeeee;
|
||||
border-bottom: 1px solid #eeeeee;
|
||||
color: #333333;
|
||||
background: #ffffff;
|
||||
text-align: left;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.calendar-day:nth-child(7n) {
|
||||
border-right: 0;
|
||||
}
|
||||
|
||||
.calendar-day:hover,
|
||||
.calendar-day:focus {
|
||||
outline: 2px solid #bf4d28;
|
||||
outline-offset: -2px;
|
||||
}
|
||||
|
||||
.calendar-day-muted {
|
||||
color: #8c8c86;
|
||||
background: #fbfbf8;
|
||||
}
|
||||
|
||||
.calendar-day-today .calendar-day-number {
|
||||
border-color: #d5e6b3;
|
||||
color: #365d26;
|
||||
background: #f2f7e8;
|
||||
}
|
||||
|
||||
.calendar-day-selected {
|
||||
box-shadow: inset 0 0 0 2px #bf4d28;
|
||||
}
|
||||
|
||||
.calendar-day-number {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 28px;
|
||||
min-height: 28px;
|
||||
border: 1px solid transparent;
|
||||
border-radius: 50%;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.calendar-day-events {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
align-content: start;
|
||||
}
|
||||
|
||||
.calendar-event-pill,
|
||||
.calendar-event-more {
|
||||
overflow: hidden;
|
||||
padding: 3px 6px;
|
||||
border-radius: 4px;
|
||||
font-size: 12px;
|
||||
line-height: 1.25;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.calendar-event-pill {
|
||||
color: #365d26;
|
||||
background: #f2f7e8;
|
||||
}
|
||||
|
||||
.calendar-event-more {
|
||||
color: #5c5c56;
|
||||
background: #f7f7f2;
|
||||
}
|
||||
|
||||
.calendar-panel {
|
||||
padding: 16px;
|
||||
}
|
||||
|
||||
.calendar-panel h3 {
|
||||
margin: 0 0 12px;
|
||||
font-size: 20px;
|
||||
}
|
||||
|
||||
.calendar-event-list {
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.calendar-event-card {
|
||||
padding: 12px;
|
||||
border: 1px solid #eeeeee;
|
||||
border-radius: 6px;
|
||||
background: #fbfbf8;
|
||||
}
|
||||
|
||||
.calendar-event-card h4 {
|
||||
margin: 0 0 6px;
|
||||
font-size: 18px;
|
||||
line-height: 1.25;
|
||||
}
|
||||
|
||||
.calendar-event-card p {
|
||||
margin: 0 0 7px;
|
||||
}
|
||||
|
||||
.calendar-event-date {
|
||||
color: #5c5c56;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
|
||||
.calendar-empty {
|
||||
margin: 0;
|
||||
color: #5c5c56;
|
||||
}
|
||||
|
||||
@media (max-width: 900px) {
|
||||
.calendar-layout {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 640px) {
|
||||
.calendar-title {
|
||||
font-size: 22px;
|
||||
}
|
||||
|
||||
.calendar-actions {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.calendar-actions > * {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.calendar-weekdays span {
|
||||
padding: 8px 2px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
.calendar-day {
|
||||
min-height: 78px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.calendar-event-pill,
|
||||
.calendar-event-more {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,10 +14,7 @@ const {
|
|||
parabolaSettings = { masonry: "0", magazine: "0", mobile: "1", fitvids: "1" },
|
||||
} = Astro.props;
|
||||
const parabolaSettingsScript = `var parabola_settings = ${JSON.stringify(parabolaSettings)};`;
|
||||
const siteOrigin = Astro.site?.origin ?? "https://familyfed.ie";
|
||||
const absoluteUrl = (value) => value ? new URL(value, siteOrigin).toString() : undefined;
|
||||
const canonicalUrl = absoluteUrl(canonical ?? pathname);
|
||||
const imageUrl = absoluteUrl(image);
|
||||
const canonicalUrl = canonical ?? pathname;
|
||||
const metaTitle = title
|
||||
.replace(/–|–/g, "-")
|
||||
.replace(/‘|’|‘|’/g, "'")
|
||||
|
|
@ -30,6 +27,7 @@ const metaTitle = title
|
|||
<head>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<slot name="head" />
|
||||
<title set:html={title} />
|
||||
{description && <meta name="description" content={description} />}
|
||||
{robots && <meta name="robots" content={robots} />}
|
||||
|
|
@ -37,11 +35,9 @@ const metaTitle = title
|
|||
<meta property="og:title" content={metaTitle} />
|
||||
{description && <meta property="og:description" content={description} />}
|
||||
{canonicalUrl && <meta property="og:url" content={canonicalUrl} />}
|
||||
{imageUrl && <meta property="og:image" content={imageUrl} />}
|
||||
{image && <meta property="og:image" content={image} />}
|
||||
<meta property="og:type" content={ogType} />
|
||||
<meta name="twitter:card" content="summary_large_image" />
|
||||
<link rel="icon" href="/assets/icons/familyfed-favicon.png" type="image/png" />
|
||||
<link rel="apple-touch-icon" href="/assets/icons/familyfed-favicon.png" />
|
||||
<link rel="stylesheet" id="content-blocks-css" href="/css/block-library.css?ver=6.6.5" type="text/css" media="all" />
|
||||
<link rel="stylesheet" id="pdfprnt_frontend-css" href="/assets/vendor/pdf/css/frontend.css?ver=2.4.0" type="text/css" media="all" />
|
||||
<link rel="stylesheet" id="parabola-fonts-css" href="/assets/theme/parabola/fonts/fontfaces.css?ver=2.4.1" type="text/css" media="all" />
|
||||
|
|
@ -52,7 +48,6 @@ const metaTitle = title
|
|||
<script is:inline type="text/javascript" src="/js/jquery.min.js?ver=2.0.2" id="jquery-js"></script>
|
||||
<script is:inline type="text/javascript" id="parabola-frontend-js-extra" set:html={parabolaSettingsScript}></script>
|
||||
<script is:inline type="text/javascript" src="/assets/theme/parabola/js/frontend.js?ver=2.4.1" id="parabola-frontend-js"></script>
|
||||
<slot name="head" />
|
||||
{canonicalUrl && <link rel="canonical" href={canonicalUrl} />}
|
||||
</head>
|
||||
<body class={bodyClass}>
|
||||
|
|
|
|||
|
|
@ -5,14 +5,9 @@
|
|||
<p>We’re conveniently located in Dublin City Centre, directly across from the James Joyce Center. Feel free to drop by anytime, since most days someone is around to offer you a cup of tea and a friendly chat about our beliefs.</p>
|
||||
<p>Our address is:</p>
|
||||
<p><strong>19 North Great Georges St.</strong><br /><strong> Dublin 1, Ireland</strong></p>
|
||||
<p>Feel free to email us any questions you may have or to book an appointment to hear our lecture series of the Divine Principle or to organize a religious event at our church center.</p>
|
||||
<ul>
|
||||
<li>Directors: <a href="mailto:directors@familyfed.ie">directors@familyfed.ie</a></li>
|
||||
<li>General enquiries: <a href="mailto:info@familyfed.ie">info@familyfed.ie</a></li>
|
||||
<li>Media: <a href="mailto:media@familyfed.ie">media@familyfed.ie</a></li>
|
||||
</ul>
|
||||
<p>Feel free to email us any questions you may have or to book an appointment to hear our lecture series of the Divine Principle or to organize a religious event at our church center: <a href="mailto:directors@familyfed.ie">directors@familyfed.ie</a></p>
|
||||
|
||||
<form id="contact-form" class="contact-form" action="mailto:directors@familyfed.ie,info@familyfed.ie,media@familyfed.ie" method="post" enctype="text/plain">
|
||||
<form id="contact-form" class="contact-form" action="mailto:directors@familyfed.ie" method="post" enctype="text/plain">
|
||||
<div class="contact-field">
|
||||
<label for="contact-name">Name</label>
|
||||
<input id="contact-name" name="name" type="text" autocomplete="name" required />
|
||||
|
|
|
|||
|
|
@ -1,47 +1,110 @@
|
|||
<div id="main">
|
||||
<div id="forbottom">
|
||||
<div style="clear:both;"> </div>
|
||||
<section id="container" class="one-column events-calendar-page">
|
||||
<div id="content" role="main">
|
||||
<div class="post page type-page status-publish hentry">
|
||||
<h1 class="entry-title">Events Calendar</h1>
|
||||
<div class="entry-content">
|
||||
<div class="familyfed-calendar" data-calendar>
|
||||
<div class="calendar-toolbar" aria-label="Calendar navigation">
|
||||
<button class="calendar-nav-button" type="button" data-calendar-prev aria-label="Previous month">‹</button>
|
||||
<h2 id="calendar-month-title" class="calendar-title" aria-live="polite"></h2>
|
||||
<button class="calendar-nav-button" type="button" data-calendar-next aria-label="Next month">›</button>
|
||||
|
||||
<main class="events-page-shell" id="content" role="main">
|
||||
<header class="events-page-header">
|
||||
<p class="events-page-kicker">Calendar</p>
|
||||
<h1>Upcoming Events</h1>
|
||||
<p>FFWPU Ireland community events will appear here when they are scheduled.</p>
|
||||
</header>
|
||||
|
||||
<section class="events-calendar-panel" aria-labelledby="events-calendar-heading">
|
||||
<div class="events-calendar-heading">
|
||||
<h2 id="events-calendar-heading">June 2026</h2>
|
||||
<p role="status">There are no upcoming events.</p>
|
||||
</div>
|
||||
|
||||
<div class="calendar-actions">
|
||||
<button class="calendar-secondary-button" type="button" data-calendar-today>This Month</button>
|
||||
<button class="calendar-secondary-button" type="button" data-calendar-export>Export Calendar</button>
|
||||
</div>
|
||||
<div class="events-calendar-grid" role="grid" aria-readonly="true" aria-label="June 2026 calendar">
|
||||
<div class="events-calendar-weekday" role="columnheader">Mon</div>
|
||||
<div class="events-calendar-weekday" role="columnheader">Tue</div>
|
||||
<div class="events-calendar-weekday" role="columnheader">Wed</div>
|
||||
<div class="events-calendar-weekday" role="columnheader">Thu</div>
|
||||
<div class="events-calendar-weekday" role="columnheader">Fri</div>
|
||||
<div class="events-calendar-weekday" role="columnheader">Sat</div>
|
||||
<div class="events-calendar-weekday" role="columnheader">Sun</div>
|
||||
|
||||
<div class="calendar-layout">
|
||||
<div class="calendar-grid-wrap">
|
||||
<div class="calendar-weekdays" aria-hidden="true">
|
||||
<span>Mon</span>
|
||||
<span>Tue</span>
|
||||
<span>Wed</span>
|
||||
<span>Thu</span>
|
||||
<span>Fri</span>
|
||||
<span>Sat</span>
|
||||
<span>Sun</span>
|
||||
</div>
|
||||
<div class="calendar-grid" role="grid" aria-labelledby="calendar-month-title" data-calendar-grid></div>
|
||||
</div>
|
||||
|
||||
<aside class="calendar-panel" aria-live="polite">
|
||||
<h3 data-calendar-panel-title>Upcoming Events</h3>
|
||||
<div class="calendar-event-list" data-calendar-list></div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<time class="events-calendar-day" datetime="2026-06-01" role="gridcell">1</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-02" role="gridcell">2</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-03" role="gridcell">3</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-04" role="gridcell">4</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-05" role="gridcell">5</time>
|
||||
<time class="events-calendar-day events-calendar-day--weekend" datetime="2026-06-06" role="gridcell">6</time>
|
||||
<time class="events-calendar-day events-calendar-day--weekend" datetime="2026-06-07" role="gridcell">7</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-08" role="gridcell">8</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-09" role="gridcell">9</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-10" role="gridcell">10</time>
|
||||
<time class="events-calendar-day events-calendar-day--today" datetime="2026-06-11" role="gridcell" aria-label="June 11, 2026">11</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-12" role="gridcell">12</time>
|
||||
<time class="events-calendar-day events-calendar-day--weekend" datetime="2026-06-13" role="gridcell">13</time>
|
||||
<time class="events-calendar-day events-calendar-day--weekend" datetime="2026-06-14" role="gridcell">14</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-15" role="gridcell">15</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-16" role="gridcell">16</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-17" role="gridcell">17</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-18" role="gridcell">18</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-19" role="gridcell">19</time>
|
||||
<time class="events-calendar-day events-calendar-day--weekend" datetime="2026-06-20" role="gridcell">20</time>
|
||||
<time class="events-calendar-day events-calendar-day--weekend" datetime="2026-06-21" role="gridcell">21</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-22" role="gridcell">22</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-23" role="gridcell">23</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-24" role="gridcell">24</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-25" role="gridcell">25</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-26" role="gridcell">26</time>
|
||||
<time class="events-calendar-day events-calendar-day--weekend" datetime="2026-06-27" role="gridcell">27</time>
|
||||
<time class="events-calendar-day events-calendar-day--weekend" datetime="2026-06-28" role="gridcell">28</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-29" role="gridcell">29</time>
|
||||
<time class="events-calendar-day" datetime="2026-06-30" role="gridcell">30</time>
|
||||
<time class="events-calendar-day events-calendar-day--outside-month" datetime="2026-07-01" role="gridcell">1</time>
|
||||
<time class="events-calendar-day events-calendar-day--outside-month" datetime="2026-07-02" role="gridcell">2</time>
|
||||
<time class="events-calendar-day events-calendar-day--outside-month" datetime="2026-07-03" role="gridcell">3</time>
|
||||
<time class="events-calendar-day events-calendar-day--outside-month events-calendar-day--weekend" datetime="2026-07-04" role="gridcell">4</time>
|
||||
<time class="events-calendar-day events-calendar-day--outside-month events-calendar-day--weekend" datetime="2026-07-05" role="gridcell">5</time>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="events-past" aria-labelledby="events-past-heading">
|
||||
<h2 id="events-past-heading">Latest Past Events</h2>
|
||||
|
||||
<div class="events-past-list">
|
||||
<article class="events-past-item">
|
||||
<time class="events-past-date" datetime="2015-03-25">
|
||||
<span>Mar</span>
|
||||
<strong>25</strong>
|
||||
<span>2015</span>
|
||||
</time>
|
||||
<div>
|
||||
<p>March 25, 2015</p>
|
||||
<h3>Ahn Shi Il</h3>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="events-past-item">
|
||||
<time class="events-past-date" datetime="2015-03-17">
|
||||
<span>Mar</span>
|
||||
<strong>17</strong>
|
||||
<span>2015</span>
|
||||
</time>
|
||||
<div>
|
||||
<p>March 17, 2015</p>
|
||||
<h3>Ahn Shi Il</h3>
|
||||
</div>
|
||||
</article>
|
||||
|
||||
<article class="events-past-item">
|
||||
<time class="events-past-date" datetime="2015-03-09">
|
||||
<span>Mar</span>
|
||||
<strong>9</strong>
|
||||
<span>2015</span>
|
||||
</time>
|
||||
<div>
|
||||
<p>March 9, 2015</p>
|
||||
<h3>Ahn Shi Il</h3>
|
||||
</div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
</main>
|
||||
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ import articleHtml from "../content/pages/contact.html?raw";
|
|||
status.textContent = "Opening your email app with the message ready to send.";
|
||||
}
|
||||
|
||||
window.location.href = `mailto:directors@familyfed.ie,info@familyfed.ie,media@familyfed.ie?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
||||
window.location.href = `mailto:directors@familyfed.ie?subject=${encodeURIComponent(subject)}&body=${encodeURIComponent(body)}`;
|
||||
});
|
||||
})();
|
||||
</script>
|
||||
|
|
|
|||
|
|
@ -9,303 +9,7 @@ import mainHtml from "../content/pages/events.html?raw";
|
|||
bodyClass="archive post-type-archive post-type-archive-tribe_events custom-background metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left"
|
||||
pathname="/events.html"
|
||||
canonical="/events.html"
|
||||
robots="noindex, follow, max-image-preview:large"
|
||||
>
|
||||
<Fragment set:html={mainHtml} />
|
||||
<script is:inline slot="scripts">
|
||||
(() => {
|
||||
const calendar = document.querySelector("[data-calendar]");
|
||||
|
||||
if (!calendar) {
|
||||
return;
|
||||
}
|
||||
|
||||
const recurringEvents = [
|
||||
{
|
||||
id: "sunday-service",
|
||||
title: "Sunday Service",
|
||||
startTime: "11:00",
|
||||
endTime: "12:00",
|
||||
location: "19 North Great Georges St., Dublin 1, Ireland",
|
||||
details: "Weekly Sunday Service video upload and community worship.",
|
||||
url: "/services.html",
|
||||
weekday: 0,
|
||||
},
|
||||
];
|
||||
|
||||
const monthTitle = calendar.querySelector("[data-calendar-panel-title]");
|
||||
const grid = calendar.querySelector("[data-calendar-grid]");
|
||||
const list = calendar.querySelector("[data-calendar-list]");
|
||||
const title = calendar.querySelector("#calendar-month-title");
|
||||
const today = new Date();
|
||||
let visibleMonth = new Date(today.getFullYear(), today.getMonth(), 1);
|
||||
let selectedDate = toDateKey(today);
|
||||
|
||||
const monthFormatter = new Intl.DateTimeFormat("en-IE", { month: "long", year: "numeric" });
|
||||
const dayFormatter = new Intl.DateTimeFormat("en-IE", { weekday: "long", day: "numeric", month: "long", year: "numeric" });
|
||||
|
||||
function pad(value) {
|
||||
return String(value).padStart(2, "0");
|
||||
}
|
||||
|
||||
function toDateKey(date) {
|
||||
return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`;
|
||||
}
|
||||
|
||||
function fromDateKey(key) {
|
||||
const [year, month, day] = key.split("-").map(Number);
|
||||
return new Date(year, month - 1, day);
|
||||
}
|
||||
|
||||
function addDays(date, days) {
|
||||
const next = new Date(date);
|
||||
next.setDate(next.getDate() + days);
|
||||
return next;
|
||||
}
|
||||
|
||||
function isSameMonth(date, month) {
|
||||
return date.getFullYear() === month.getFullYear() && date.getMonth() === month.getMonth();
|
||||
}
|
||||
|
||||
function monthStartGridDate(month) {
|
||||
const first = new Date(month.getFullYear(), month.getMonth(), 1);
|
||||
const mondayIndex = (first.getDay() + 6) % 7;
|
||||
return addDays(first, -mondayIndex);
|
||||
}
|
||||
|
||||
function monthEndGridDate(month) {
|
||||
const last = new Date(month.getFullYear(), month.getMonth() + 1, 0);
|
||||
const sundayIndex = (7 - last.getDay()) % 7;
|
||||
return addDays(last, sundayIndex);
|
||||
}
|
||||
|
||||
function eventsBetween(start, end) {
|
||||
const events = [];
|
||||
|
||||
for (let date = new Date(start); date <= end; date = addDays(date, 1)) {
|
||||
for (const recurringEvent of recurringEvents) {
|
||||
if (date.getDay() !== recurringEvent.weekday) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const dateKey = toDateKey(date);
|
||||
events.push({
|
||||
...recurringEvent,
|
||||
id: `${recurringEvent.id}-${dateKey}`,
|
||||
date: dateKey,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return events;
|
||||
}
|
||||
|
||||
function formatEventTime(event) {
|
||||
return `${event.startTime} - ${event.endTime}`;
|
||||
}
|
||||
|
||||
function renderGrid() {
|
||||
const start = monthStartGridDate(visibleMonth);
|
||||
const end = monthEndGridDate(visibleMonth);
|
||||
const events = eventsBetween(start, end);
|
||||
const eventsByDate = new Map();
|
||||
|
||||
for (const event of events) {
|
||||
const dayEvents = eventsByDate.get(event.date) || [];
|
||||
dayEvents.push(event);
|
||||
eventsByDate.set(event.date, dayEvents);
|
||||
}
|
||||
|
||||
title.textContent = monthFormatter.format(visibleMonth);
|
||||
grid.innerHTML = "";
|
||||
|
||||
for (let date = new Date(start); date <= end; date = addDays(date, 1)) {
|
||||
const dateKey = toDateKey(date);
|
||||
const dayEvents = eventsByDate.get(dateKey) || [];
|
||||
const cell = document.createElement("button");
|
||||
cell.type = "button";
|
||||
cell.className = "calendar-day";
|
||||
cell.dataset.date = dateKey;
|
||||
cell.setAttribute("role", "gridcell");
|
||||
cell.setAttribute("aria-label", `${dayFormatter.format(date)}${dayEvents.length ? `, ${dayEvents.length} event` : ""}`);
|
||||
|
||||
if (!isSameMonth(date, visibleMonth)) {
|
||||
cell.classList.add("calendar-day-muted");
|
||||
}
|
||||
|
||||
if (dateKey === toDateKey(today)) {
|
||||
cell.classList.add("calendar-day-today");
|
||||
}
|
||||
|
||||
if (dateKey === selectedDate) {
|
||||
cell.classList.add("calendar-day-selected");
|
||||
cell.setAttribute("aria-selected", "true");
|
||||
}
|
||||
|
||||
const number = document.createElement("span");
|
||||
number.className = "calendar-day-number";
|
||||
number.textContent = String(date.getDate());
|
||||
cell.append(number);
|
||||
|
||||
const eventStack = document.createElement("span");
|
||||
eventStack.className = "calendar-day-events";
|
||||
for (const event of dayEvents.slice(0, 2)) {
|
||||
const pill = document.createElement("span");
|
||||
pill.className = "calendar-event-pill";
|
||||
pill.textContent = event.title;
|
||||
eventStack.append(pill);
|
||||
}
|
||||
|
||||
if (dayEvents.length > 2) {
|
||||
const more = document.createElement("span");
|
||||
more.className = "calendar-event-more";
|
||||
more.textContent = `+${dayEvents.length - 2} more`;
|
||||
eventStack.append(more);
|
||||
}
|
||||
|
||||
cell.append(eventStack);
|
||||
cell.addEventListener("click", () => {
|
||||
selectedDate = dateKey;
|
||||
render();
|
||||
});
|
||||
grid.append(cell);
|
||||
}
|
||||
}
|
||||
|
||||
function renderList() {
|
||||
const selected = fromDateKey(selectedDate);
|
||||
const monthStart = new Date(visibleMonth.getFullYear(), visibleMonth.getMonth(), 1);
|
||||
const monthEnd = new Date(visibleMonth.getFullYear(), visibleMonth.getMonth() + 1, 0);
|
||||
const selectedEvents = eventsBetween(selected, selected);
|
||||
const upcomingEvents = eventsBetween(monthStart, monthEnd)
|
||||
.filter((event) => event.date >= toDateKey(today))
|
||||
.slice(0, 8);
|
||||
const events = selectedEvents.length ? selectedEvents : upcomingEvents;
|
||||
|
||||
monthTitle.textContent = selectedEvents.length
|
||||
? dayFormatter.format(selected)
|
||||
: "Upcoming Events";
|
||||
list.innerHTML = "";
|
||||
|
||||
if (!events.length) {
|
||||
const empty = document.createElement("p");
|
||||
empty.className = "calendar-empty";
|
||||
empty.textContent = "No events for this view.";
|
||||
list.append(empty);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const event of events) {
|
||||
const item = document.createElement("article");
|
||||
item.className = "calendar-event-card";
|
||||
const eventDate = fromDateKey(event.date);
|
||||
|
||||
const date = document.createElement("p");
|
||||
date.className = "calendar-event-date";
|
||||
date.textContent = dayFormatter.format(eventDate);
|
||||
|
||||
const heading = document.createElement("h4");
|
||||
heading.textContent = event.title;
|
||||
|
||||
const time = document.createElement("p");
|
||||
time.textContent = formatEventTime(event);
|
||||
|
||||
const location = document.createElement("p");
|
||||
location.textContent = event.location;
|
||||
|
||||
const details = document.createElement("p");
|
||||
details.textContent = event.details;
|
||||
|
||||
const link = document.createElement("a");
|
||||
link.href = event.url;
|
||||
link.textContent = "Sunday Services";
|
||||
|
||||
item.append(date, heading, time, location, details, link);
|
||||
list.append(item);
|
||||
}
|
||||
}
|
||||
|
||||
function icsDate(dateKey, time) {
|
||||
const [year, month, day] = dateKey.split("-");
|
||||
const [hours, minutes] = time.split(":");
|
||||
return `${year}${month}${day}T${hours}${minutes}00`;
|
||||
}
|
||||
|
||||
function escapeIcs(value) {
|
||||
return String(value)
|
||||
.replace(/\\/g, "\\\\")
|
||||
.replace(/;/g, "\\;")
|
||||
.replace(/,/g, "\\,")
|
||||
.replace(/\n/g, "\\n");
|
||||
}
|
||||
|
||||
function exportCalendar() {
|
||||
const start = new Date(today.getFullYear(), today.getMonth(), 1);
|
||||
const end = new Date(today.getFullYear() + 1, today.getMonth() + 1, 0);
|
||||
const events = eventsBetween(start, end);
|
||||
const stamp = new Date().toISOString().replace(/[-:]/g, "").replace(/\.\d{3}Z$/, "Z");
|
||||
const siteUrl = "https://familyfed.ie";
|
||||
const lines = [
|
||||
"BEGIN:VCALENDAR",
|
||||
"VERSION:2.0",
|
||||
"PRODID:-//FFWPU Ireland//Events Calendar//EN",
|
||||
"CALSCALE:GREGORIAN",
|
||||
"METHOD:PUBLISH",
|
||||
];
|
||||
|
||||
for (const event of events) {
|
||||
lines.push(
|
||||
"BEGIN:VEVENT",
|
||||
`UID:${event.id}@familyfed.ie`,
|
||||
`DTSTAMP:${stamp}`,
|
||||
`DTSTART:${icsDate(event.date, event.startTime)}`,
|
||||
`DTEND:${icsDate(event.date, event.endTime)}`,
|
||||
`SUMMARY:${escapeIcs(event.title)}`,
|
||||
`DESCRIPTION:${escapeIcs(event.details)}`,
|
||||
`LOCATION:${escapeIcs(event.location)}`,
|
||||
`URL:${siteUrl}${event.url}`,
|
||||
"END:VEVENT",
|
||||
);
|
||||
}
|
||||
|
||||
lines.push("END:VCALENDAR");
|
||||
|
||||
const blob = new Blob([lines.join("\r\n")], { type: "text/calendar;charset=utf-8" });
|
||||
const url = URL.createObjectURL(blob);
|
||||
const link = document.createElement("a");
|
||||
link.href = url;
|
||||
link.download = "familyfed-events.ics";
|
||||
document.body.append(link);
|
||||
link.click();
|
||||
link.remove();
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
function render() {
|
||||
renderGrid();
|
||||
renderList();
|
||||
}
|
||||
|
||||
calendar.querySelector("[data-calendar-prev]")?.addEventListener("click", () => {
|
||||
visibleMonth = new Date(visibleMonth.getFullYear(), visibleMonth.getMonth() - 1, 1);
|
||||
selectedDate = toDateKey(new Date(visibleMonth.getFullYear(), visibleMonth.getMonth(), 1));
|
||||
render();
|
||||
});
|
||||
|
||||
calendar.querySelector("[data-calendar-next]")?.addEventListener("click", () => {
|
||||
visibleMonth = new Date(visibleMonth.getFullYear(), visibleMonth.getMonth() + 1, 1);
|
||||
selectedDate = toDateKey(new Date(visibleMonth.getFullYear(), visibleMonth.getMonth(), 1));
|
||||
render();
|
||||
});
|
||||
|
||||
calendar.querySelector("[data-calendar-today]")?.addEventListener("click", () => {
|
||||
visibleMonth = new Date(today.getFullYear(), today.getMonth(), 1);
|
||||
selectedDate = toDateKey(today);
|
||||
render();
|
||||
});
|
||||
|
||||
calendar.querySelector("[data-calendar-export]")?.addEventListener("click", exportCalendar);
|
||||
|
||||
render();
|
||||
})();
|
||||
</script>
|
||||
</SiteLayout>
|
||||
|
|
|
|||
|
|
@ -5,11 +5,12 @@ import { getSpeechArchive, uniqueSorted } from "../../lib/speeches";
|
|||
const speeches = getSpeechArchive();
|
||||
const years = uniqueSorted(speeches.map((speech) => speech.year), "desc");
|
||||
const speakers = uniqueSorted(speeches.map((speech) => speech.speaker));
|
||||
const categories = uniqueSorted(speeches.flatMap((speech) => speech.categories.length ? speech.categories : [speech.category]));
|
||||
---
|
||||
|
||||
<SiteLayout
|
||||
title="Speeches Archive – FFWPU Ireland"
|
||||
description="Search the FFWPU Ireland archive of speeches by Rev. Sun Myung Moon and Dr. Hak Ja Han Moon by year, speaker, and text."
|
||||
description="Search the FFWPU Ireland archive of speeches by Rev. Sun Myung Moon and Dr. Hak Ja Han Moon by year, speaker, category, and text."
|
||||
bodyClass="page-template page-template-templates page-template-template-onecolumn page-template-templatestemplate-onecolumn-php page custom-background tribe-no-js metaslider-plugin parabola-image-three caption-light meta-light parabola_triagles parabola-menu-left"
|
||||
pathname="/speeches/"
|
||||
canonical="/speeches/"
|
||||
|
|
@ -46,6 +47,14 @@ const speakers = uniqueSorted(speeches.map((speech) => speech.speaker));
|
|||
</select>
|
||||
</div>
|
||||
|
||||
<div class="speech-filter">
|
||||
<label for="speech-category">Category</label>
|
||||
<select id="speech-category" name="category">
|
||||
<option value="">All categories</option>
|
||||
{categories.map((category) => <option value={category}>{category}</option>)}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<button class="speech-reset" type="reset">Reset filters</button>
|
||||
</form>
|
||||
|
||||
|
|
@ -65,6 +74,9 @@ const speakers = uniqueSorted(speeches.map((speech) => speech.speaker));
|
|||
<a href={speech.url}>{speech.title}</a>
|
||||
</h2>
|
||||
<p>{speech.excerpt}</p>
|
||||
<div class="speech-result-categories">
|
||||
{(speech.categories.length ? speech.categories : [speech.category]).map((category) => <span>{category}</span>)}
|
||||
</div>
|
||||
</article>
|
||||
))
|
||||
}
|
||||
|
|
@ -86,8 +98,9 @@ const speakers = uniqueSorted(speeches.map((speech) => speech.speaker));
|
|||
const searchInput = document.getElementById("speech-search");
|
||||
const yearSelect = document.getElementById("speech-year");
|
||||
const speakerSelect = document.getElementById("speech-speaker");
|
||||
const categorySelect = document.getElementById("speech-category");
|
||||
|
||||
if (!form || !results || !count || !searchInput || !yearSelect || !speakerSelect) {
|
||||
if (!form || !results || !count || !searchInput || !yearSelect || !speakerSelect || !categorySelect) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -107,6 +120,7 @@ const speakers = uniqueSorted(speeches.map((speech) => speech.speaker));
|
|||
q: searchInput.value.trim(),
|
||||
year: yearSelect.value,
|
||||
speaker: speakerSelect.value,
|
||||
category: categorySelect.value,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +141,7 @@ const speakers = uniqueSorted(speeches.map((speech) => speech.speaker));
|
|||
searchInput.value = params.get("q") || "";
|
||||
yearSelect.value = params.get("year") || "";
|
||||
speakerSelect.value = params.get("speaker") || "";
|
||||
categorySelect.value = params.get("category") || "";
|
||||
}
|
||||
|
||||
function matchesSpeech(speech, filters) {
|
||||
|
|
@ -136,6 +151,9 @@ const speakers = uniqueSorted(speeches.map((speech) => speech.speaker));
|
|||
if (filters.speaker && speech.speaker !== filters.speaker) {
|
||||
return false;
|
||||
}
|
||||
if (filters.category && !speech.categories.includes(filters.category) && speech.category !== filters.category) {
|
||||
return false;
|
||||
}
|
||||
if (!filters.q) {
|
||||
return true;
|
||||
}
|
||||
|
|
@ -170,7 +188,11 @@ const speakers = uniqueSorted(speeches.map((speech) => speech.speaker));
|
|||
const excerpt = document.createElement("p");
|
||||
excerpt.textContent = speech.excerpt;
|
||||
|
||||
article.append(meta, title, excerpt);
|
||||
const categories = document.createElement("div");
|
||||
categories.className = "speech-result-categories";
|
||||
appendMeta(categories, speech.categories.length ? speech.categories : [speech.category]);
|
||||
|
||||
article.append(meta, title, excerpt, categories);
|
||||
return article;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue