Skip to content

Commit 42bba95

Browse files
Dale KunceDale Kunce
authored andcommitted
Implement CORS workaround for events
- Add GitHub Actions workflow for daily event updates (6 AM UTC) - Enhance fetch-events.cjs with timestamp metadata and error handling - Update events.js with graceful fallbacks and last-updated display - Support both legacy array format and new metadata format - Add comprehensive error messaging without social media references - Enable static JSON loading to eliminate CORS issues - Maintain backward compatibility with existing build process
1 parent 7d10707 commit 42bba95

4 files changed

Lines changed: 433 additions & 5 deletions

File tree

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
name: Update Events Data
2+
3+
on:
4+
# Run every 24 hours at 6 AM UTC
5+
schedule:
6+
- cron: '0 6 * * *'
7+
8+
# Allow manual triggering
9+
workflow_dispatch:
10+
11+
# Run on push to specific files (for testing)
12+
push:
13+
paths:
14+
- 'fetch-events.cjs'
15+
- '.github/workflows/update-events.yml'
16+
17+
jobs:
18+
update-events:
19+
runs-on: ubuntu-latest
20+
21+
steps:
22+
- name: Checkout repository
23+
uses: actions/checkout@v4
24+
with:
25+
token: ${{ secrets.GITHUB_TOKEN }}
26+
27+
- name: Setup Node.js
28+
uses: actions/setup-node@v4
29+
with:
30+
node-version: '20'
31+
cache: 'npm'
32+
33+
- name: Install dependencies
34+
run: npm install --only=production
35+
36+
- name: Fetch latest events
37+
run: node fetch-events.cjs
38+
39+
- name: Check for changes
40+
id: verify-changed-files
41+
run: |
42+
if [ -n "$(git status --porcelain app/assets/data/events.json)" ]; then
43+
echo "changed=true" >> $GITHUB_OUTPUT
44+
echo "Events data has been updated"
45+
else
46+
echo "changed=false" >> $GITHUB_OUTPUT
47+
echo "No changes to events data"
48+
fi
49+
50+
- name: Commit updated events
51+
if: steps.verify-changed-files.outputs.changed == 'true'
52+
run: |
53+
git config --local user.email "41898282+github-actions[bot]@users.noreply.github.com"
54+
git config --local user.name "github-actions[bot]"
55+
git add app/assets/data/events.json
56+
git commit -m "🤖 Auto-update events data from osmcal.org
57+
58+
- Updated: $(date -u +'%Y-%m-%d %H:%M:%S UTC')
59+
- Events count: $(jq '.count' app/assets/data/events.json)
60+
- Build time: $(jq -r '.buildTime' app/assets/data/events.json)"
61+
62+
- name: Push changes
63+
if: steps.verify-changed-files.outputs.changed == 'true'
64+
uses: ad-m/github-push-action@master
65+
with:
66+
github_token: ${{ secrets.GITHUB_TOKEN }}
67+
branch: ${{ github.ref }}
68+
69+
- name: Summary
70+
run: |
71+
echo "## Events Update Summary" >> $GITHUB_STEP_SUMMARY
72+
echo "- **Build Time:** $(jq -r '.buildTime' app/assets/data/events.json)" >> $GITHUB_STEP_SUMMARY
73+
echo "- **Events Count:** $(jq '.count' app/assets/data/events.json)" >> $GITHUB_STEP_SUMMARY
74+
echo "- **Changed:** ${{ steps.verify-changed-files.outputs.changed }}" >> $GITHUB_STEP_SUMMARY
75+
if [ -f app/assets/data/events.json ]; then
76+
echo "- **Event Names:**" >> $GITHUB_STEP_SUMMARY
77+
jq -r '.events[].name' app/assets/data/events.json | head -10 | sed 's/^/ - /' >> $GITHUB_STEP_SUMMARY
78+
fi

app/assets/data/events.json

Lines changed: 198 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,198 @@
1+
{
2+
"buildTime": "2025-10-01T02:02:02.199Z",
3+
"count": 15,
4+
"events": [
5+
{
6+
"name": "Mapathon - Monthly Missing Maps w/ EWB Norway",
7+
"url": "https://osmcal.org/event/4083/",
8+
"date": {
9+
"human": "7th October 16:30 – 19:00",
10+
"human_short": "7th October",
11+
"whole_day": false,
12+
"start": "2025-10-07T16:30:00+02:00",
13+
"end": "2025-10-07T19:00:00+02:00"
14+
},
15+
"location": {
16+
"short": "Oslo, Norway",
17+
"detailed": "Mesh Nationaltheatret, 2, Tordenskiolds gate, Sentrum, Oslo, Norway",
18+
"coords": [
19+
10.736582,
20+
59.912966
21+
],
22+
"venue": "Mesh Nationaltheatret"
23+
}
24+
},
25+
{
26+
"name": "Missing Maps London: (Online) Mapathon [eng]",
27+
"url": "https://osmcal.org/event/3737/",
28+
"date": {
29+
"human": "7th October 19:00 – 21:15 (Europe/London)",
30+
"human_short": "7th October",
31+
"whole_day": false,
32+
"start": "2025-10-07T19:00:00+01:00",
33+
"end": "2025-10-07T21:15:00+01:00"
34+
}
35+
},
36+
{
37+
"name": "Missing Maps : Mapathon en ligne - CartONG [fr]",
38+
"url": "https://osmcal.org/event/4040/",
39+
"date": {
40+
"human": "13th October 18:00 – 20:00 (Europe/Paris)",
41+
"human_short": "13th October",
42+
"whole_day": false,
43+
"start": "2025-10-13T18:00:00+02:00",
44+
"end": "2025-10-13T20:00:00+02:00"
45+
}
46+
},
47+
{
48+
"name": "Missing Maps London: (Online) Mid-Month Mapathon [eng]",
49+
"url": "https://osmcal.org/event/3745/",
50+
"date": {
51+
"human": "21st October 18:00 – 21:00 (Europe/London)",
52+
"human_short": "21st October",
53+
"whole_day": false,
54+
"start": "2025-10-21T18:00:00+01:00",
55+
"end": "2025-10-21T21:00:00+01:00"
56+
}
57+
},
58+
{
59+
"name": "Missing Maps : Mapathon en ligne - CartONG [fr]",
60+
"url": "https://osmcal.org/event/4041/",
61+
"date": {
62+
"human": "27th October 18:00 – 20:00 (Europe/Paris)",
63+
"human_short": "27th October",
64+
"whole_day": false,
65+
"start": "2025-10-27T18:00:00+01:00",
66+
"end": "2025-10-27T20:00:00+01:00"
67+
}
68+
},
69+
{
70+
"name": "Mapathon - Monthly Missing Maps w/ EWB Norway",
71+
"url": "https://osmcal.org/event/4084/",
72+
"date": {
73+
"human": "4th November 16:30 – 19:00",
74+
"human_short": "4th November",
75+
"whole_day": false,
76+
"start": "2025-11-04T16:30:00+01:00",
77+
"end": "2025-11-04T19:00:00+01:00"
78+
},
79+
"location": {
80+
"short": "Oslo, Norway",
81+
"detailed": "Mesh Nationaltheatret, 2, Tordenskiolds gate, Sentrum, Oslo, Norway",
82+
"coords": [
83+
10.736582,
84+
59.912966
85+
],
86+
"venue": "Mesh Nationaltheatret"
87+
}
88+
},
89+
{
90+
"name": "Missing Maps London: (Online) Mapathon [eng]",
91+
"url": "https://osmcal.org/event/3738/",
92+
"date": {
93+
"human": "4th November 19:00 – 21:15 (Europe/London)",
94+
"human_short": "4th November",
95+
"whole_day": false,
96+
"start": "2025-11-04T19:00:00+00:00",
97+
"end": "2025-11-04T21:15:00+00:00"
98+
}
99+
},
100+
{
101+
"name": "Missing Maps : Mapathon en ligne - CartONG [fr]",
102+
"url": "https://osmcal.org/event/4042/",
103+
"date": {
104+
"human": "10th November 18:00 – 20:00 (Europe/Paris)",
105+
"human_short": "10th November",
106+
"whole_day": false,
107+
"start": "2025-11-10T18:00:00+01:00",
108+
"end": "2025-11-10T20:00:00+01:00"
109+
}
110+
},
111+
{
112+
"name": "Missing Maps London: (Online) Mid-Month Mapathon [eng]",
113+
"url": "https://osmcal.org/event/3746/",
114+
"date": {
115+
"human": "18th November 18:00 – 21:00 (Europe/London)",
116+
"human_short": "18th November",
117+
"whole_day": false,
118+
"start": "2025-11-18T18:00:00+00:00",
119+
"end": "2025-11-18T21:00:00+00:00"
120+
}
121+
},
122+
{
123+
"name": "Missing Maps : Mapathon en ligne - CartONG [fr]",
124+
"url": "https://osmcal.org/event/4043/",
125+
"date": {
126+
"human": "24th November 18:00 – 20:00 (Europe/Paris)",
127+
"human_short": "24th November",
128+
"whole_day": false,
129+
"start": "2025-11-24T18:00:00+01:00",
130+
"end": "2025-11-24T20:00:00+01:00"
131+
}
132+
},
133+
{
134+
"name": "Mapathon - Monthly Missing Maps w/ EWB Norway",
135+
"url": "https://osmcal.org/event/4085/",
136+
"date": {
137+
"human": "2nd December 16:30 – 19:00",
138+
"human_short": "2nd December",
139+
"whole_day": false,
140+
"start": "2025-12-02T16:30:00+01:00",
141+
"end": "2025-12-02T19:00:00+01:00"
142+
},
143+
"location": {
144+
"short": "Oslo, Norway",
145+
"detailed": "Mesh Nationaltheatret, 2, Tordenskiolds gate, Sentrum, Oslo, Norway",
146+
"coords": [
147+
10.736582,
148+
59.912966
149+
],
150+
"venue": "Mesh Nationaltheatret"
151+
}
152+
},
153+
{
154+
"name": "Missing Maps London: (Online) Mapathon [eng]",
155+
"url": "https://osmcal.org/event/3739/",
156+
"date": {
157+
"human": "2nd December 19:00 – 21:15 (Europe/London)",
158+
"human_short": "2nd December",
159+
"whole_day": false,
160+
"start": "2025-12-02T19:00:00+00:00",
161+
"end": "2025-12-02T21:15:00+00:00"
162+
}
163+
},
164+
{
165+
"name": "Missing Maps : Mapathon en ligne - CartONG [fr]",
166+
"url": "https://osmcal.org/event/4044/",
167+
"date": {
168+
"human": "8th December 18:00 – 20:00 (Europe/Paris)",
169+
"human_short": "8th December",
170+
"whole_day": false,
171+
"start": "2025-12-08T18:00:00+01:00",
172+
"end": "2025-12-08T20:00:00+01:00"
173+
}
174+
},
175+
{
176+
"name": "Missing Maps London: (Online) Mid-Month Mapathon [eng]",
177+
"url": "https://osmcal.org/event/3747/",
178+
"date": {
179+
"human": "16th December 18:00 – 21:00 (Europe/London)",
180+
"human_short": "16th December",
181+
"whole_day": false,
182+
"start": "2025-12-16T18:00:00+00:00",
183+
"end": "2025-12-16T21:00:00+00:00"
184+
}
185+
},
186+
{
187+
"name": "Missing Maps : Mapathon en ligne - CartONG [fr]",
188+
"url": "https://osmcal.org/event/4045/",
189+
"date": {
190+
"human": "22nd December 18:00 – 20:00 (Europe/Paris)",
191+
"human_short": "22nd December",
192+
"whole_day": false,
193+
"start": "2025-12-22T18:00:00+01:00",
194+
"end": "2025-12-22T20:00:00+01:00"
195+
}
196+
}
197+
]
198+
}

app/assets/scripts/events.js

Lines changed: 78 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -159,17 +159,90 @@ const buildEvents = (events) => {
159159
console.log('✅ All events built with Foundation cards!');
160160
};
161161

162-
// Fetch events
162+
// Show last updated timestamp
163+
const showLastUpdated = (buildTime) => {
164+
try {
165+
const lastUpdate = luxon.DateTime.fromISO(buildTime);
166+
const now = luxon.DateTime.now();
167+
const hoursSinceUpdate = now.diff(lastUpdate, 'hours').hours;
168+
169+
console.log(`📅 Events last updated: ${lastUpdate.toRelative()} (${hoursSinceUpdate.toFixed(1)} hours ago)`);
170+
171+
// Only show visual indicator if data is getting old (more than 12 hours)
172+
if (hoursSinceUpdate > 12) {
173+
const eventList = document.getElementById('eventList');
174+
if (eventList && hoursSinceUpdate > 24) {
175+
const notice = document.createElement('div');
176+
notice.className = 'text-center';
177+
notice.style.cssText = 'font-size: 0.9em; color: #666; margin-bottom: 20px;';
178+
notice.innerHTML = `<em>Events last updated ${lastUpdate.toRelative()}</em>`;
179+
eventList.parentNode.insertBefore(notice, eventList);
180+
}
181+
}
182+
} catch (error) {
183+
console.warn('Could not parse build time:', error);
184+
}
185+
};
186+
187+
// Fallback display when events can't be loaded
188+
const showEventsFallback = () => {
189+
const eventList = document.getElementById('eventList');
190+
if (!eventList) return;
191+
192+
eventList.innerHTML = `
193+
<div class="column">
194+
<div class="textbox-container" style="text-align: center; padding: 40px 20px;">
195+
<h3>Events Temporarily Unavailable</h3>
196+
<p>We're having trouble loading the latest Missing Maps events. Please try:</p>
197+
<ul style="text-align: left; max-width: 400px; margin: 20px auto;">
198+
<li>Refreshing the page in a few minutes</li>
199+
<li>Visiting <a href="https://osmcal.org" target="_blank" rel="noopener">OSMCal.org</a> directly</li>
200+
<li>Checking our website again later</li>
201+
</ul>
202+
<p style="margin-top: 30px;">
203+
<a class="btn btn-blue" href="https://osmcal.org" target="_blank" rel="noopener">
204+
View Events on OSMCal.org
205+
</a>
206+
</p>
207+
</div>
208+
</div>
209+
`;
210+
};
211+
212+
// Fetch events with enhanced error handling and metadata support
163213
const fetchEvents = async () => {
164214
try {
165-
console.log('📡 Fetching events...');
215+
console.log('📡 Fetching events from', EVENTS_JSON_URL);
166216
const response = await fetch(EVENTS_JSON_URL);
167-
if (!response.ok) throw new Error('HTTP ' + response.status);
168-
const events = await response.json();
169-
console.log('📦 Got', events.length, 'events');
217+
if (!response.ok) throw new Error(`HTTP ${response.status}: ${response.statusText}`);
218+
219+
const eventsData = await response.json();
220+
console.log('📦 Raw events data:', eventsData);
221+
222+
// Handle both old format (array) and new format (object with metadata)
223+
let events, buildTime;
224+
225+
if (Array.isArray(eventsData)) {
226+
// Old format - just an array of events
227+
events = eventsData;
228+
buildTime = null;
229+
console.log('📦 Got', events.length, 'events (legacy format)');
230+
} else {
231+
// New format - object with metadata
232+
events = eventsData.events || [];
233+
buildTime = eventsData.buildTime;
234+
console.log('📦 Got', events.length, 'events (new format with metadata)');
235+
236+
if (buildTime) {
237+
console.log('🕒 Events built at:', buildTime);
238+
showLastUpdated(buildTime);
239+
}
240+
}
241+
170242
return events;
171243
} catch (error) {
172244
console.error('💥 Fetch error:', error);
245+
showEventsFallback();
173246
return [];
174247
}
175248
};

0 commit comments

Comments
 (0)