@@ -23,29 +23,78 @@ title: Community call
2323 </div>
2424 </div >
2525 <div class =" col-lg-6 " role =" main " >
26- <div>
27- <p>We're using <a href="https://meet.jit.si/">Jitsi</a>, a free and open source video conferencing service.
28- You don't need an account to join.
29- </p>
30- <div class="alert alert-warning" role="alert">
31- <h4 class="alert-heading">Meetings are public (and recorded!)</h4>
32- <p>Meetings are recorded and shared on <a href="https://www.youtube.com/@kroxylicious-io">our YouTube channel</a>.</p>
33- </div>
34- <p>If your browser knows about your calendar app you should be able to subscribe in your calendar app by clicking the button below.</p>
35- <div><a href="{{ '/join-us/community-call/community-call.ics' | absolute_url | replace: 'http://', 'webcal://' | replace: 'https://', 'webcal://' }}" class="btn btn-primary">Subscribe</a></div>
36- </div>
37- <div>
38- <h2>Upcoming events</h2>
39- <div>Times are shown in your browser's local timezone, <span id="tz-display"></span>.</div>
40- <div id="calendar"/>
41- </div>
26+ <div>
27+ <p>We're using <a href="https://meet.jit.si/">Jitsi</a>, a free and open source video conferencing service.
28+ You don't need an account to join.</p>
29+ <div class="alert alert-warning" role="alert">
30+ <h4 class="alert-heading">Meetings are public (and recorded!)</h4>
31+ <p>Meetings are recorded and shared on <a href="https://www.youtube.com/@kroxylicious-io">our YouTube channel</a>.</p>
32+ </div>
33+ </div>
34+ <div class="d-flex flex-wrap align-items-center justify-content-between mb-4">
35+ <div>
36+ <h2 class="mb-1">Event Schedule</h2>
37+ <p class="text-muted mb-0">Local time: <strong id="tz-display">Detecting...</strong></p>
38+ </div>
39+ <div class="dropdown">
40+ <button class="btn btn-primary dropdown-toggle d-flex align-items-center" type="button" id="calendarDropdown" data-bs-toggle="dropdown" data-bs-auto-close="outside" aria-expanded="false">
41+ <i class="bi bi-calendar-plus me-2"></i> Add to Calendar</button>
42+ <ul class="dropdown-menu dropdown-menu-end shadow" aria-labelledby="calendarDropdown" style="min-width: 300px;">
43+ <li><h6 class="dropdown-header">Subscribe via App</h6></li>
44+ <li>
45+ <a class="dropdown-item d-flex align-items-center" href="{{ '/join-us/community-call/community-call.ics' | absolute_url | replace: 'http://', 'webcal://' | replace: 'https://', 'webcal://' }}">
46+ <i class="bi bi-apple me-2 text-dark"></i> Apple Calendar / Outlook</a>
47+ </li>
48+ <li>
49+ <a class="dropdown-item d-flex align-items-center" href="https://www.google.com/calendar/render?cid={{ '/join-us/community-call/community-call.ics' | absolute_url }}" target="_blank">
50+ <i class="bi bi-google me-2 text-danger"></i> Google Calendar (Web)</a>
51+ </li>
52+ <li><hr class="dropdown-divider"></li>
53+ <li><h6 class="dropdown-header">Manual Setup</h6></li>
54+ <li class="px-3 py-2">
55+ <label for="calLink" class="form-label small text-muted">Copy Subscription URL:</label>
56+ <div class="input-group input-group-sm">
57+ <input type="text" class="form-control" value="{{ '/join-us/community-call/community-call.ics' | absolute_url }}" id="calLink" readonly>
58+ <button class="btn btn-outline-secondary" type="button" onclick="copyCalLink()" id="copyBtn">
59+ <i class="bi bi-clipboard"></i></button>
60+ </div>
61+ <div id="copyFeedback" class="small text-success mt-1 d-none">Link copied!</div>
62+ </li>
63+ </ul>
64+ </div>
65+ </div>
66+ <div id="calendar" class="border rounded bg-white p-3 shadow-sm"></div>
4267 </div >
4368</div >
4469<script >
45- document .addEventListener (' DOMContentLoaded' , function () {
46- const userTimeZone = Intl .DateTimeFormat ().resolvedOptions ().timeZone ;
47- document .getElementById (' tz-display' ).textContent = userTimeZone;
70+
71+ function copyCalLink () {
72+ const copyText = document .getElementById (" calLink" );
73+ const btn = document .getElementById (" copyBtn" );
74+ const feedback = document .getElementById (" copyFeedback" );
75+
76+ // Copy to clipboard
77+ navigator .clipboard .writeText (copyText .value ).then (() => {
78+ // Show feedback
79+ feedback .classList .remove (' d-none' );
80+ btn .classList .replace (' btn-outline-secondary' , ' btn-success' );
4881
82+ // Reset after 3 seconds
83+ setTimeout (() => {
84+ feedback .classList .add (' d-none' );
85+ btn .classList .replace (' btn-success' , ' btn-outline-secondary' );
86+ }, 3000 );
87+ });
88+ }
89+
90+ // Timezone detection
91+ document .addEventListener (' DOMContentLoaded' , function () {
92+ const tz = Intl .DateTimeFormat ().resolvedOptions ().timeZone || ' UTC' ;
93+ document .getElementById (' tz-display' ).textContent = tz .replace (' _' , ' ' );
94+ });
95+
96+ // Render the events in the ics on the page
97+ document .addEventListener (' DOMContentLoaded' , function () {
4998 var calendarEl = document .getElementById (' calendar' );
5099 var calendar = new FullCalendar.Calendar (calendarEl, {
51100 initialView: ' listMonth' ,
0 commit comments