Skip to content

feat(calendar): redesign app using plain HTML/CSS/TS#717

Open
nicomiguelino wants to merge 27 commits intomasterfrom
feat/overhaul-calendar-app
Open

feat(calendar): redesign app using plain HTML/CSS/TS#717
nicomiguelino wants to merge 27 commits intomasterfrom
feat/overhaul-calendar-app

Conversation

@nicomiguelino
Copy link
Contributor

@nicomiguelino nicomiguelino commented Mar 2, 2026

User description

Summary

  • Migrate calendar app from Vue 3 + Pinia to framework-free Web Components
  • Add reusable <weekly-calendar-view> custom element to edge-apps-library
  • Port column layout algorithm and 12-hour window logic from the blueprint
  • Implement partial event clipping and column-scoped current-time indicator

PR Type

Enhancement, Tests, Documentation


Description

  • Replace Vue app with custom elements

  • Add reusable weekly, daily, schedule views

  • Refactor iCal fetching with timezone filtering

  • Add screenshot coverage and shared tooling


Diagram Walkthrough

flowchart LR
  app["Framework-free calendar app"]
  fetch["Timezone-aware iCal fetcher"]
  views["`schedule`, `weekly`, and `daily` views"]
  shared["Shared layout and rendering utilities"]
  tests["Screenshot e2e coverage"]
  app -- "selects active mode" --> views
  app -- "loads events" --> fetch
  fetch -- "supplies parsed events" --> views
  shared -- "supports rendering" --> views
  tests -- "verifies modes and sizes" --> views
Loading

File Walkthrough

Relevant files
Enhancement
15 files
main.ts
Bootstrap framework-free calendar and refresh cycles         
+65/-35 
index.html
Compose app shell with auto-scaler views                                 
+28/-4   
types.ts
Define local calendar event and mode types                             
+15/-0   
style.css
Add base layout and active view styling                                   
+52/-0   
weekly-calendar-view.ts
Render reusable weekly calendar web component                       
+253/-0 
weekly-calendar-view-utils.ts
Add weekly windowing, formatting, and safety helpers         
+190/-0 
event-layout.ts
Compute overlapping event clusters and column spans           
+181/-0 
weekly-calendar-view-styles.ts
Style weekly headers, events, and indicator                           
+234/-0 
daily-calendar-view.ts
Render daily calendar using shared layouts                             
+191/-0 
daily-calendar-view-styles.ts
Style daily view grid and events                                                 
+175/-0 
schedule-calendar-view.ts
Render schedule view for upcoming events                                 
+218/-0 
schedule-calendar-view-styles.ts
Style schedule columns and event cards                                     
+118/-0 
calendar-view-utils.ts
Share time gutter and event element builders                         
+85/-0   
index.ts
Export reusable calendar view components                                 
+4/-0     
register.ts
Auto-register calendar custom elements globally                   
+3/-0     
Error handling
1 files
events.ts
Refactor iCal fetching around explicit timezone                   
+25/-33 
Tests
1 files
screenshots.spec.ts
Capture screenshot baselines across modes and sizes           
+176/-0 
Configuration changes
1 files
package.json
Adopt shared scripts and remove Vue tooling                           
+25/-56 
Documentation
1 files
README.md
Document new setup, configuration, and screenshots             
+44/-38 
Dependencies
1 files
package.json
Add `dayjs` runtime dependency for components                       
+1/-0     
Additional files
56 files
.ignore +1/-0     
extensions.json +0/-9     
tsconfig.json +0/-4     
vue.spec.ts +0/-56   
eslint.config.ts +0/-34   
playwright.config.ts +0/-14   
screenly.yml +1/-1     
screenly_qc.yml +1/-1     
daily-1080x1920.webp [link]   
daily-1280x720.webp [link]   
daily-1920x1080.webp [link]   
daily-2160x3840.webp [link]   
daily-2160x4096.webp [link]   
daily-3840x2160.webp [link]   
daily-4096x2160.webp [link]   
daily-480x800.webp [link]   
daily-720x1280.webp [link]   
daily-800x480.webp [link]   
schedule-1080x1920.webp [link]   
schedule-1280x720.webp [link]   
schedule-1920x1080.webp [link]   
schedule-2160x3840.webp [link]   
schedule-2160x4096.webp [link]   
schedule-3840x2160.webp [link]   
schedule-4096x2160.webp [link]   
schedule-480x800.webp [link]   
schedule-720x1280.webp [link]   
schedule-800x480.webp [link]   
weekly-1080x1920.webp [link]   
weekly-1280x720.webp [link]   
weekly-1920x1080.webp [link]   
weekly-2160x3840.webp [link]   
weekly-2160x4096.webp [link]   
weekly-3840x2160.webp [link]   
weekly-4096x2160.webp [link]   
weekly-480x800.webp [link]   
weekly-720x1280.webp [link]   
weekly-800x480.webp [link]   
App.vue +0/-111 
main.scss +0/-84   
App.spec.ts +0/-49   
constants.ts +0/-1     
calendar.ts +0/-157 
settings.ts +0/-85   
test-setup.ts +0/-3     
utils.ts +0/-3     
tsconfig.app.json +0/-17   
tsconfig.json +0/-14   
tsconfig.node.json +0/-19   
tsconfig.vitest.json +0/-11   
vite.config.ts +0/-54   
vitest.config.ts +0/-15   
index.ts +1/-0     
index.ts +1/-0     
vite-env.d.ts +5/-0     
index.ts +2/-0     

- Migrate from Vue 3 + Pinia to framework-free Web Components
- Add reusable weekly-calendar-view custom element to edge-apps-library

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nicomiguelino nicomiguelino self-assigned this Mar 2, 2026
@github-actions
Copy link

github-actions bot commented Mar 2, 2026

PR Reviewer Guide 🔍

(Review updated until commit 60f9ed0)

Here are some key observations to aid the review process:

⏱️ Estimated effort to review: 4 🔵🔵🔵🔵⚪
🧪 PR contains tests
🔒 No security concerns identified
⚡ Recommended focus areas for review

Range mismatch

The fetch window for schedule mode still resolves to the current month, while the new schedule UI shows today and tomorrow. On the last day of a month, tomorrow's events can fall outside the fetched range and disappear from the schedule view.

const getDateRangeForViewMode = (viewMode: ViewMode, timezone: string) => {
  const nowInTimezone = dayjs().tz(timezone)
  const todayInTimezone = nowInTimezone.startOf('day')

  let startDate: Date
  let endDate: Date

  if (viewMode === VIEW_MODE.DAILY) {
    startDate = todayInTimezone.toDate()
    endDate = todayInTimezone.add(1, 'day').toDate()
  } else if (viewMode === VIEW_MODE.WEEKLY) {
    const weekStart = todayInTimezone.startOf('week')
    startDate = weekStart.toDate()
    endDate = weekStart.add(7, 'days').toDate()
  } else {
    const monthStart = todayInTimezone.startOf('month')
    startDate = monthStart.toDate()
    endDate = monthStart.add(1, 'month').toDate()
  }
Overnight events

Window filtering only keeps events whose start date matches the rendered day. Events that begin before midnight and continue into the visible day or 12-hour window will be dropped instead of being clipped into view.

return events.filter((event) => {
  if (event.isAllDay) return false
  const eventStart = dayjs(event.startTime).tz(tz)
  if (eventStart.format('YYYY-MM-DD') !== dayDateStr) return false
  const startH = eventStart.hour() + eventStart.minute() / 60
  const endDt = dayjs(event.endTime).tz(tz)
  const endH = endDt.hour() + endDt.minute() / 60
  const normStart = startH < windowStartHour ? startH + 24 : startH
  const normEnd = endH <= windowStartHour ? endH + 24 : endH
  return normStart < normalizedWindowEnd && normEnd > windowStartHour
Key collision

Event layout lookup keys are derived only from start time, end time, and title. Distinct events with identical timestamps and titles will overwrite each other in the layout map, which can cause overlapping events to render in the same slot.

export const getEventKey = (event: CalendarEvent): string =>
  `${event.startTime}|${event.endTime}|${event.title || ''}`

@github-actions
Copy link

github-actions bot commented Mar 2, 2026

PR Code Suggestions ✨

Latest suggestions up to 60f9ed0
Explore these optional code suggestions:

CategorySuggestion                                                                                                                                    Impact
Possible issue
Fix overlapping window filtering

This filter drops events that overlap the visible window but started before
windowStartHour, and it also hides overnight events that began on the previous day.
Compare the event's actual start/end timestamps against the day's window instead of
requiring the start date to equal dayDateStr.

edge-apps/edge-apps-library/src/components/weekly-calendar-view/weekly-calendar-view-utils.ts [151-171]

 export function filterEventsForWindow(
   events: CalendarEvent[],
   dayDateStr: string,
   windowStartHour: number,
   tz: string,
 ): CalendarEvent[] {
-  const windowEndHour = (windowStartHour + 12) % 24
-  const normalizedWindowEnd =
-    windowEndHour <= windowStartHour ? windowEndHour + 24 : windowEndHour
+  const dayStart = dayjs.tz(`${dayDateStr}T00:00:00`, tz)
+  const windowStart = dayStart.hour(windowStartHour).minute(0).second(0).millisecond(0)
+  const windowEnd = windowStart.add(12, 'hour')
+
   return events.filter((event) => {
     if (event.isAllDay) return false
+
     const eventStart = dayjs(event.startTime).tz(tz)
-    if (eventStart.format('YYYY-MM-DD') !== dayDateStr) return false
-    const startH = eventStart.hour() + eventStart.minute() / 60
-    const endDt = dayjs(event.endTime).tz(tz)
-    const endH = endDt.hour() + endDt.minute() / 60
-    const normStart = startH < windowStartHour ? startH + 24 : startH
-    const normEnd = endH <= windowStartHour ? endH + 24 : endH
-    return normStart < normalizedWindowEnd && normEnd > windowStartHour
+    const eventEnd = dayjs(event.endTime).tz(tz)
+
+    return eventStart.isBefore(windowEnd) && eventEnd.isAfter(windowStart)
   })
 }
Suggestion importance[1-10]: 8

__

Why: This correctly identifies that filterEventsForWindow excludes events that overlap the visible 12-hour window when they start before windowStartHour, including cross-midnight overlaps. Comparing full start/end datetimes against the computed window is a meaningful correctness fix for both daily and weekly rendering.

Medium
Always signal readiness

A failure in initialization before the final line prevents signalReady() from ever
running, which can leave the Screenly app stuck in a loading state. Wrap startup in
try/finally so readiness is always signaled even when locale, timezone, or DOM setup
fails.

edge-apps/calendar/src/main.ts [25-75]

 document.addEventListener('DOMContentLoaded', async () => {
-  const scaler = document.querySelector('auto-scaler')
-  scaler?.addEventListener('scalechange', centerAutoScalerVertically)
-  window.addEventListener('resize', centerAutoScalerVertically)
-  centerAutoScalerVertically()
-  setupErrorHandling()
-  setupTheme()
+  try {
+    const scaler = document.querySelector('auto-scaler')
+    scaler?.addEventListener('scalechange', centerAutoScalerVertically)
+    window.addEventListener('resize', centerAutoScalerVertically)
+    centerAutoScalerVertically()
+    setupErrorHandling()
+    setupTheme()
 
-  const calendarMode = (screenly.settings.calendar_mode as string) || 'schedule'
+    const calendarMode = (screenly.settings.calendar_mode as string) || 'schedule'
 
-  const scheduleEl = document.getElementById(
-    'schedule-calendar',
-  ) as ScheduleCalendarView
-  const weeklyEl = document.getElementById(
-    'weekly-calendar',
-  ) as WeeklyCalendarView
-  const dailyEl = document.getElementById('daily-calendar') as DailyCalendarView
+    const scheduleEl = document.getElementById(
+      'schedule-calendar',
+    ) as ScheduleCalendarView
+    const weeklyEl = document.getElementById(
+      'weekly-calendar',
+    ) as WeeklyCalendarView
+    const dailyEl = document.getElementById('daily-calendar') as DailyCalendarView
 
-  const activeEl =
-    calendarMode === 'daily'
-      ? dailyEl
-      : calendarMode === 'weekly'
-        ? weeklyEl
-        : scheduleEl
+    const activeEl =
+      calendarMode === 'daily'
+        ? dailyEl
+        : calendarMode === 'weekly'
+          ? weeklyEl
+          : scheduleEl
 
-  activeEl.classList.add('active')
+    activeEl.classList.add('active')
 
-  const timezone = await getTimeZone()
-  const locale = await getLocale()
-  activeEl.setAttribute('timezone', timezone)
-  activeEl.setAttribute('locale', locale)
+    const timezone = await getTimeZone()
+    const locale = await getLocale()
+    activeEl.setAttribute('timezone', timezone)
+    activeEl.setAttribute('locale', locale)
 
-  const tick = () => {
-    activeEl.now = new Date()
+    const tick = () => {
+      activeEl.now = new Date()
+    }
+    tick()
+    setInterval(tick, 30_000)
+
+    const refresh = async () => {
+      try {
+        const events = await fetchCalendarEventsFromICal({ timezone })
+        activeEl.events = events
+      } catch (error) {
+        console.error('Failed to fetch calendar events:', error)
+      }
+    }
+    await refresh()
+    setInterval(refresh, EVENTS_REFRESH_INTERVAL)
+  } catch (error) {
+    console.error('Failed to initialize calendar:', error)
+  } finally {
+    signalReady()
   }
-  tick()
-  setInterval(tick, 30_000)
-
-  const refresh = async () => {
-    try {
-      const events = await fetchCalendarEventsFromICal({ timezone })
-      activeEl.events = events
-    } catch (error) {
-      console.error('Failed to fetch calendar events:', error)
-    }
-  }
-  await refresh()
-  setInterval(refresh, EVENTS_REFRESH_INTERVAL)
-
-  signalReady()
 })
Suggestion importance[1-10]: 7

__

Why: This is a sound resilience improvement because an exception before the final signalReady() can leave the app stuck loading. Wrapping initialization in try/finally preserves Screenly readiness behavior without changing the main flow of src/main.ts.

Medium
Include ongoing events

This excludes events that are already in progress, so an active meeting disappears
from the schedule as soon as its start time passes. Filter on endTime > now and
startTime < startOfTomorrow so ongoing events remain visible until they actually
end.

edge-apps/edge-apps-library/src/components/schedule-calendar-view/schedule-calendar-view.ts [73-79]

 const todayAll = this._events
   .filter((e) => {
     if (e.isAllDay) return false
     const start = dayjs(e.startTime).tz(tz)
-    return start.isAfter(nowInTz) && start.isBefore(startOfTomorrow)
+    const end = dayjs(e.endTime).tz(tz)
+    return end.isAfter(nowInTz) && start.isBefore(startOfTomorrow)
   })
   .sort(sortByStart)
Suggestion importance[1-10]: 6

__

Why: The current todayAll filter removes events as soon as their start time passes, so ongoing items vanish from schedule-calendar-view before they end. Using endTime to keep active events visible improves schedule accuracy, though the impact is limited to one view.

Low

Previous suggestions

Suggestions up to commit 7378c5c
CategorySuggestion                                                                                                                                    Impact
Possible issue
Include overlapping events in range

The current range filter only includes events whose start is inside the range,
which drops events that start before the window but overlap into it (common for long
meetings). Filter by range overlap (start < endDate && end > startDate) so ongoing
events are included.

edge-apps/calendar-new/src/events.ts [83-99]

 const event = new ical.Event(vevent)
 const eventStart = event.startDate.toJSDate()
-const eventTimestamp = eventStart.getTime()
+const eventEnd = event.endDate?.toJSDate?.() ?? eventStart
 
-if (eventTimestamp >= endTimestamp || eventTimestamp < startTimestamp) {
+const eventStartTs = eventStart.getTime()
+const eventEndTs = eventEnd.getTime()
+
+// Include events that overlap the requested window
+if (eventStartTs >= endTimestamp || eventEndTs <= startTimestamp) {
   return
 }
-
-const eventEnd = event.endDate.toJSDate()
 
 events.push({
   title: event.summary || 'Busy',
   startTime: eventStart.toISOString(),
   endTime: eventEnd.toISOString(),
   isAllDay: event.startDate.isDate,
 })
Suggestion importance[1-10]: 8

__

Why: The current filter only checks whether an event’s start time falls within [startDate, endDate), which incorrectly drops events that begin before the window but overlap into it. The proposed overlap check fixes a real correctness issue in fetchCalendarEventsFromICal() and the improved_code reflects the intended logic.

Medium
Avoid layout key collisions

Using getEventKey() can collide when multiple events share the same start/end/title,
causing incorrect layout lookups (overlaps rendered wrong). Store layouts keyed by
the event object reference instead (e.g., WeakMap<CalendarEvent, EventLayout>),
since the same objects are used during the render pass.

edge-apps/edge-apps-library/src/components/weekly-calendar-view/weekly-calendar-view.ts [5-355]

 import {
   type CalendarEvent,
   type EventLayout,
   findEventClusters,
   calculateClusterLayouts,
-  getEventKey,
 } from './event-layout.js'
 ...
-private _getEventLayouts(): Map<string, EventLayout> {
+private _getEventLayouts(): WeakMap<CalendarEvent, EventLayout> {
   const tz = this._timezone
   const weekStartDate = dayjs(this._getWeekStart()).tz(tz)
-  const layoutMap = new Map<string, EventLayout>()
+  const layoutMap = new WeakMap<CalendarEvent, EventLayout>()
   ...
-        layoutMap.set(getEventKey(event), layout)
+        layoutMap.set(event, layout)
   ...
   return layoutMap
 }
 ...
-    const key = getEventKey(event)
-    const layout = eventLayouts.get(key) ?? {
+    const layout = eventLayouts.get(event) ?? {
       event,
       column: 0,
       columnSpan: 1,
       totalColumns: 1,
     }
Suggestion importance[1-10]: 7

__

Why: Keying layouts by getEventKey() can collide when multiple events share the same startTime/endTime/title, causing eventLayouts.get(key) to return the wrong EventLayout. Switching to a WeakMap<CalendarEvent, EventLayout> keyed by the event object reference avoids collisions and fits the current flow where the same event objects are passed through clustering and rendering.

Medium
Reduce costly rerenders frequency

Updating now every second forces a full calendar re-render each second (the
component rebuilds the entire DOM), which can cause unnecessary CPU usage and jank.
Update on minute boundaries instead, which is sufficient for the time indicator and
dramatically reduces work.

edge-apps/calendar-new/src/main.ts [27-32]

 const tick = () => {
   calendarEl.now = new Date()
 }
 tick()
-setInterval(tick, 1000)
 
+const scheduleNextMinuteTick = () => {
+  const now = new Date()
+  const msUntilNextMinute =
+    (60 - now.getSeconds()) * 1000 - now.getMilliseconds()
+
+  setTimeout(() => {
+    tick()
+    setInterval(tick, 60_000)
+  }, msUntilNextMinute)
+}
+
+scheduleNextMinuteTick()
+
Suggestion importance[1-10]: 6

__

Why: Updating calendarEl.now every second triggers WeeklyCalendarView’s full _render() each second, which is unnecessarily expensive since the UI only needs minute-level updates for the time indicator. The suggested minute-boundary scheduling is a reasonable performance improvement, though not strictly required for correctness.

Low

nicomiguelino and others added 18 commits March 10, 2026 16:16
- Fix missing error cause in events.ts
- Extract CSS and utility functions into separate files to satisfy max-lines rules
- Add e2e screenshots

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… file

- Update `.this-week-title` to Inter Regular (weight 400), normal style, centered, with letter-spacing
- Remove unused `weekly-calendar-view.css` (CSS lives in `weekly-calendar-view-styles.ts`)
- Increase day name font size to 0.98rem with line-height 1.333
- Increase day date font size to 1.469rem with line-height 1.556
- Add opacity 0.8 to today's day name
- Increase day header height and time gutter padding-top to 5.225rem
- Increase time gutter width to 6.5rem and padding-right to 1rem
- Match time label font size to day name (0.98rem)
- Set day-body overflow to visible so the time indicator dot is not clipped
- Adjust current time indicator dot left offset to -0.27rem
- Remove horizontal margin from .header to fix app header alignment
- Force landscape orientation with letterbox bars and vertical centering
- Fix app header margins and compact event display for short events
- Fix timezone-aware day header date and locale-aware day names
- Match Figma design tokens for event card and title styles
- Replace --calendar-accent-color with --theme-color-primary
- Style app-header background and text color from theme
- Make weekly-calendar-view background transparent
- Add `daily-calendar-view` Web Component with same styling as weekly view
- Add `calendar-view-utils.ts` with shared `buildTimeGutter` and `buildEventElement`
- Extract `filterEventsForWindow` into shared utils to eliminate duplication
- Support `calendar_mode` setting to switch between weekly and daily views

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `schedule-calendar-view` Web Component showing today/tomorrow events
- Move `calendar-view-utils.ts` to components root (shared by all views)
- Fix `generateTimeSlots` to use configured timezone for time labels
- Support `schedule` as default `calendar_mode` in calendar app

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add per-mode screenshot loops (schedule, weekly, daily)
- Rename files from `WxH.png` to `{mode}-WxH.png`
- Enrich ICS mock data with more events for schedule view
- Set screenly_color_accent to #2E8B57 in mock settings

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move icon.svg from static/ to static/img/
- Update icon URL in manifest files to match new path
- Remove unused bg.webp from static/images/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Rename calendar-new to calendar, replacing the old Vue 3/Pinia app
- Add schedule, weekly, and daily calendar views as Web Components
- Remove Vue, Vite, and blueprint dependencies
- Update build tooling to use edge-apps-scripts

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the Calendar edge app from a Vue 3 + Pinia implementation to framework-free Web Components, and introduces reusable calendar view components in edge-apps-library (daily/weekly/schedule) with shared event layout + rendering utilities.

Changes:

  • Add <weekly-calendar-view>, <daily-calendar-view>, and <schedule-calendar-view> Web Components (plus shared event layout + DOM builder utilities) to edge-apps-library.
  • Rewrite the Calendar app to render those components from plain HTML/CSS/TS, including new screenshot-test coverage and updated assets.
  • Remove Vue/Vite/Vitest/Pinia scaffolding from the Calendar app and update manifests/docs accordingly.

Reviewed changes

Copilot reviewed 46 out of 87 changed files in this pull request and generated 7 comments.

Show a summary per file
File Description
edge-apps/edge-apps-library/src/components/weekly-calendar-view/weekly-calendar-view.ts New weekly view Web Component rendering a 7-day grid with event layout + current-time indicator.
edge-apps/edge-apps-library/src/components/weekly-calendar-view/weekly-calendar-view-utils.ts Shared helpers for windowing, slot generation, event styling/clipping, and safe attribute setting.
edge-apps/edge-apps-library/src/components/weekly-calendar-view/weekly-calendar-view-styles.ts Shadow-DOM CSS for the weekly view.
edge-apps/edge-apps-library/src/components/weekly-calendar-view/index.ts Public exports for weekly view component + event type.
edge-apps/edge-apps-library/src/components/weekly-calendar-view/event-layout.ts Event overlap clustering + column layout algorithm for time-grid views.
edge-apps/edge-apps-library/src/components/vite-env.d.ts Add *.css?inline module typing for component CSS imports.
edge-apps/edge-apps-library/src/components/schedule-calendar-view/schedule-calendar-view.ts New schedule list view Web Component (today + tomorrow, capped).
edge-apps/edge-apps-library/src/components/schedule-calendar-view/schedule-calendar-view-styles.ts Shadow-DOM CSS for the schedule view.
edge-apps/edge-apps-library/src/components/schedule-calendar-view/index.ts Public export for schedule view component.
edge-apps/edge-apps-library/src/components/daily-calendar-view/daily-calendar-view.ts New daily view Web Component (12-hour window, event layout, current-time indicator).
edge-apps/edge-apps-library/src/components/daily-calendar-view/daily-calendar-view-styles.ts Shadow-DOM CSS for the daily view.
edge-apps/edge-apps-library/src/components/daily-calendar-view/index.ts Public export for daily view component.
edge-apps/edge-apps-library/src/components/calendar-view-utils.ts Shared DOM builders for time gutter + event cards used by daily/weekly views.
edge-apps/edge-apps-library/src/components/register.ts Register new calendar custom elements alongside existing components.
edge-apps/edge-apps-library/src/components/index.ts Export new calendar view components (and CalendarEvent type) from the library entrypoint.
edge-apps/edge-apps-library/package.json Add dayjs dependency needed by the new components/utilities.
edge-apps/edge-apps-library/bun.lock Lockfile update for added dependency.
edge-apps/calendar/src/types.ts New local types (CalendarEvent, ViewMode, VIEW_MODE) for the rewritten app.
edge-apps/calendar/src/main.ts Rewrite app bootstrap to use Web Components, theme/error setup, and periodic ticking/refresh.
edge-apps/calendar/src/events.ts Update iCal fetching/parsing to be framework-free and accept explicit timezone input.
edge-apps/calendar/src/css/style.css New global app styles (layout + view switching via .active).
edge-apps/calendar/index.html Replace Vue mount point with static layout using auto-scaler, app-header, and calendar view elements.
edge-apps/calendar/package.json Switch scripts/tooling to edge-apps-scripts workflow; remove Vue/Pinia/Vitest plumbing.
edge-apps/calendar/README.md Update deployment/dev/testing/screenshot instructions for the new architecture.
edge-apps/calendar/e2e/screenshots.spec.ts Add Playwright-based screenshot generation test across modes and resolutions.
edge-apps/calendar/screenly.yml Update manifest icon URL path.
edge-apps/calendar/screenly_qc.yml Update QC manifest icon URL path.
edge-apps/calendar/.ignore Add ignore file for deployment packaging (node_modules).
edge-apps/calendar/.gitignore Add gitignore for build artifacts/logs/etc.
edge-apps/calendar/vitest.config.ts Remove Vitest config (no longer using Vitest).
edge-apps/calendar/vite.config.ts Remove Vite config (now handled by edge-apps-scripts).
edge-apps/calendar/tsconfig.vitest.json Remove Vitest TS config.
edge-apps/calendar/tsconfig.node.json Remove node/tooling TS config.
edge-apps/calendar/tsconfig.json Remove TS project references for the prior Vue setup.
edge-apps/calendar/tsconfig.app.json Remove Vue app TS config.
edge-apps/calendar/src/utils.ts Remove re-export utilities tied to the old blueprint/Vue setup.
edge-apps/calendar/src/test-setup.ts Remove prior Vitest setup.
edge-apps/calendar/src/stores/settings.ts Remove Pinia settings store.
edge-apps/calendar/src/stores/calendar.ts Remove Pinia calendar store.
edge-apps/calendar/src/constants.ts Remove old constants re-export.
edge-apps/calendar/src/components/tests/App.spec.ts Remove Vue unit test.
edge-apps/calendar/src/assets/main.scss Remove old SCSS styling tied to Vue blueprint layout.
edge-apps/calendar/src/App.vue Remove Vue root component.
edge-apps/calendar/playwright.config.ts Remove old Playwright config (now using shared screenshot helpers).
edge-apps/calendar/eslint.config.ts Remove Vue/Vitest/Playwright-specific ESLint config (now via edge-apps-scripts).
edge-apps/calendar/e2e/vue.spec.ts Remove old Vue-focused Playwright test.
edge-apps/calendar/e2e/tsconfig.json Remove old e2e TS config.
edge-apps/calendar/.vscode/extensions.json Remove Vue/Vitest editor recommendations.
edge-apps/calendar/screenshots/weekly-800x480.webp Add updated weekly-mode screenshot artifact.
edge-apps/calendar/screenshots/weekly-720x1280.webp Add updated weekly-mode screenshot artifact.
edge-apps/calendar/screenshots/weekly-480x800.webp Add updated weekly-mode screenshot artifact.
edge-apps/calendar/screenshots/schedule-800x480.webp Add updated schedule-mode screenshot artifact.
edge-apps/calendar/screenshots/schedule-720x1280.webp Add updated schedule-mode screenshot artifact.
edge-apps/calendar/screenshots/schedule-480x800.webp Add updated schedule-mode screenshot artifact.
edge-apps/calendar/screenshots/daily-800x480.webp Add updated daily-mode screenshot artifact.
edge-apps/calendar/screenshots/daily-720x1280.webp Add updated daily-mode screenshot artifact.
edge-apps/calendar/screenshots/daily-480x800.webp Add updated daily-mode screenshot artifact.
edge-apps/calendar/screenshots/daily-1280x720.webp Add updated daily-mode screenshot artifact.
edge-apps/calendar/screenshots/daily-1080x1920.webp Add updated daily-mode screenshot artifact.
edge-apps/calendar/static/images/enable-google-calendar-api.png Include static documentation image asset for setup instructions.
edge-apps/calendar/static/images/authorization-code.png Include static documentation image asset for setup instructions.
edge-apps/calendar/src/assets/font/Aeonik-Regular.woff2 Include font asset (legacy/compat).
edge-apps/calendar/src/assets/font/Aeonik-Regular.woff Include font asset (legacy/compat).
edge-apps/calendar/public/fonts/Aeonik-Regular.woff2 Include font asset served from public/.
edge-apps/calendar/public/fonts/Aeonik-Regular.woff Include font asset served from public/.
edge-apps/calendar/public/favicon.ico Include app favicon asset.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

nicomiguelino and others added 3 commits March 18, 2026 07:12
- Add white variant of screenly.svg to e2e/
- Set screenly_logo_light to a base64 data URI in screenshot tests
- Regenerate screenshots

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Throttle now tick from 1s to 30s to reduce unnecessary re-renders
- Replace JSON.parse for bypass_cors with getSettingWithDefault
- Replace toLocaleString/parseInt with dayjs for hour/minute extraction
- Move customElements.define into each calendar view component file
- Remove redundant side-effect imports and define blocks from register.ts
- Hoist ALLOWED_ATTRIBUTES to module-level constant in weekly-calendar-view-utils

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nicomiguelino nicomiguelino marked this pull request as ready for review March 18, 2026 18:07
@github-actions
Copy link

Persistent review updated to latest commit 60f9ed0

nicomiguelino and others added 5 commits March 18, 2026 12:32
…cture

- Replace Vue 3 + Pinia with vanilla TS using edge-apps-library components
- Rewrite event fetching to use Google Calendar API with OAuth token management
- Add token refresh loop with exponential backoff
- Use getCredentials(), getSettingWithDefault() from shared library
- Add color-coding support via Google Calendar colors API
- Add Playwright screenshot tests with Google API route mocks

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Change icon path from `src/img/icon.svg` to `static/img/icon.svg`

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Use regex route patterns instead of glob for Google API mocks
- Add mock access_token setting to bypass getCredentials() in tests
- Regenerate screenshots with events properly populated

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add `centerAutoScalerVertically` to `utils/screen.ts` with tests
- Add `getDateRangeForViewMode` to new `utils/calendar.ts` with tests
- Add `CalendarViewMode` type and `CALENDAR_VIEW_MODE` constant to `types/index.ts`
- Remove duplicated definitions from `google-calendar` and `calendar`

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Move weekly/daily/schedule views into calendar-views/ in edge-apps-library
- Move event-layout.ts and calendar-view-utils.ts to calendar-views/ root
- Remove redundant types.ts from calendar app
- Extend CalendarEvent from base type in google-calendar types.ts
- Fix getDateRangeForViewMode to use Date.now() for testability

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@nicomiguelino nicomiguelino requested a review from Copilot March 19, 2026 05:49
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates the calendar and google-calendar edge apps from Vue/Pinia to framework-free Web Components, while extracting reusable calendar view components and time/date utilities into @screenly/edge-apps and adding Playwright-based screenshot coverage.

Changes:

  • Replace the Vue app shells with plain HTML/CSS/TS that render <schedule-calendar-view>, <weekly-calendar-view>, and <daily-calendar-view>.
  • Add reusable calendar view Web Components + shared layout/windowing/date-range utilities to edge-apps-library.
  • Add screenshot E2E tests and commit screenshot baselines across supported resolutions.

Reviewed changes

Copilot reviewed 85 out of 168 changed files in this pull request and generated 8 comments.

Show a summary per file
File Description
edge-apps/google-calendar/vitest.config.ts Remove Vitest config (Vue-era tooling).
edge-apps/google-calendar/vite.config.ts Remove Vite+Vue config (migrating to shared scripts/tooling).
edge-apps/google-calendar/tsconfig.vitest.json Remove Vitest TS config.
edge-apps/google-calendar/tsconfig.node.json Remove node TS config for legacy tooling files.
edge-apps/google-calendar/tsconfig.json Remove TS project references used by Vue/Vite/Vitest setup.
edge-apps/google-calendar/tsconfig.app.json Remove Vue app TS config.
edge-apps/google-calendar/src/utils.ts Remove legacy blueprint utility re-exports + token fetch helper.
edge-apps/google-calendar/src/types.ts Add local CalendarEvent type extending library event type.
edge-apps/google-calendar/src/test-setup.ts Remove Vitest global screenly mock (tests moved away from Vitest).
edge-apps/google-calendar/src/stores/settings.ts Remove Pinia settings store (Vue-era).
edge-apps/google-calendar/src/stores/calendar.ts Remove Pinia calendar store and refresh loops (Vue-era).
edge-apps/google-calendar/src/main.ts New TS bootstrap: selects active view element, sets locale/timezone, handles token refresh + event refresh.
edge-apps/google-calendar/src/img/icon.svg Remove legacy icon location.
edge-apps/google-calendar/src/events.ts Refactor Google API event fetch to use shared settings/date-range helpers + explicit timezone parameter.
edge-apps/google-calendar/src/css/style.css Add framework-free app shell CSS (header/content + active view).
edge-apps/google-calendar/src/constants.ts Remove blueprint calendar constants re-export.
edge-apps/google-calendar/src/components/tests/App.spec.ts Remove Vue component unit test.
edge-apps/google-calendar/src/colors.ts Minor refactor/simplification of colors fetch + caching logic.
edge-apps/google-calendar/src/assets/main.scss Remove Vue-era SCSS shell styling.
edge-apps/google-calendar/playwright.config.ts Remove legacy Playwright config (moving to shared scripts).
edge-apps/google-calendar/package.json Switch to shared edge-apps-scripts, remove Vue deps, add workspace library + scripts incl. screenshots.
edge-apps/google-calendar/index.html Replace Vue mount point with <auto-scaler> + header + calendar view elements.
edge-apps/google-calendar/eslint.config.ts Remove Vue-era ESLint config.
edge-apps/google-calendar/e2e/vue.spec.ts Remove Vue-focused E2E test.
edge-apps/google-calendar/e2e/tsconfig.json Remove E2E TS config (shared tooling).
edge-apps/google-calendar/e2e/screenshots.spec.ts Add screenshot E2E coverage across modes/resolutions with API mocks.
edge-apps/google-calendar/e2e/screenly.svg Add SVG asset for screenshot branding mock.
edge-apps/google-calendar/README.md Update docs for new setup/scripts (but currently mismatched vs Google API configuration).
edge-apps/google-calendar/.vscode/extensions.json Remove Vue/Vitest/Volar extension recommendations.
edge-apps/google-calendar/.ignore Add ignore for Screenly packaging (node_modules).
edge-apps/google-calendar/.gitignore Simplify ignore list (but drops screenshot PNG ignore).
edge-apps/google-calendar/.gitattributes Remove repo-local attributes file.
edge-apps/google-calendar/.editorconfig Remove repo-local editorconfig.
edge-apps/google-calendar/screenly.yml Update icon URL to new static path.
edge-apps/google-calendar/screenly_qc.yml Update icon URL to new static path.
edge-apps/google-calendar/screenshots/daily-1080x1920.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/daily-1280x720.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/daily-1920x1080.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/daily-2160x3840.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/daily-2160x4096.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/daily-3840x2160.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/daily-4096x2160.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/daily-480x800.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/daily-720x1280.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/daily-800x480.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/schedule-1080x1920.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/schedule-1280x720.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/schedule-1920x1080.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/schedule-2160x3840.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/schedule-2160x4096.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/schedule-3840x2160.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/schedule-4096x2160.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/schedule-480x800.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/schedule-720x1280.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/schedule-800x480.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/weekly-1080x1920.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/weekly-1280x720.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/weekly-1920x1080.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/weekly-2160x3840.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/weekly-2160x4096.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/weekly-3840x2160.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/weekly-4096x2160.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/weekly-480x800.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/weekly-720x1280.webp Add screenshot baseline.
edge-apps/google-calendar/screenshots/weekly-800x480.webp Add screenshot baseline.
edge-apps/calendar/vitest.config.ts Remove Vitest config (Vue-era tooling).
edge-apps/calendar/vite.config.ts Remove Vite+Vue config (migrating to shared scripts/tooling).
edge-apps/calendar/tsconfig.vitest.json Remove Vitest TS config.
edge-apps/calendar/tsconfig.node.json Remove node TS config for legacy tooling files.
edge-apps/calendar/tsconfig.json Remove TS project references used by Vue/Vite/Vitest setup.
edge-apps/calendar/tsconfig.app.json Remove Vue app TS config.
edge-apps/calendar/src/utils.ts Remove legacy blueprint utility re-exports.
edge-apps/calendar/src/test-setup.ts Remove blueprint test setup.
edge-apps/calendar/src/stores/settings.ts Remove Pinia settings store (Vue-era).
edge-apps/calendar/src/stores/calendar.ts Remove Pinia calendar store (Vue-era).
edge-apps/calendar/src/main.ts New TS bootstrap: selects active view element, sets locale/timezone, refreshes iCal events into the active view.
edge-apps/calendar/src/events.ts Refactor iCal fetch to use shared settings/date-range helper + explicit timezone parameter.
edge-apps/calendar/src/css/style.css Add framework-free app shell CSS (header/content + active view).
edge-apps/calendar/src/constants.ts Remove blueprint calendar constants re-export.
edge-apps/calendar/src/components/tests/App.spec.ts Remove Vue component unit test.
edge-apps/calendar/src/assets/main.scss Remove Vue-era SCSS shell styling.
edge-apps/calendar/src/App.vue Remove Vue app component.
edge-apps/calendar/playwright.config.ts Remove legacy Playwright config (moving to shared scripts).
edge-apps/calendar/package.json Switch to shared edge-apps-scripts, remove Vue deps, add scripts incl. screenshots.
edge-apps/calendar/index.html Replace Vue mount point with <auto-scaler> + header + calendar view elements.
edge-apps/calendar/eslint.config.ts Remove Vue-era ESLint config.
edge-apps/calendar/e2e/vue.spec.ts Remove Vue-focused E2E test.
edge-apps/calendar/e2e/tsconfig.json Remove E2E TS config (shared tooling).
edge-apps/calendar/e2e/screenshots.spec.ts Add screenshot E2E coverage across modes/resolutions with iCal mocks.
edge-apps/calendar/e2e/screenly.svg Add SVG asset for screenshot branding mock.
edge-apps/calendar/README.md Update docs for new setup/scripts + configuration + screenshots.
edge-apps/calendar/.vscode/extensions.json Remove Vue/Vitest/Volar extension recommendations.
edge-apps/calendar/.ignore Add ignore for Screenly packaging (node_modules).
edge-apps/calendar/.gitignore Add minimal ignore list (but drops screenshot PNG ignore).
edge-apps/calendar/screenly.yml Update icon URL to new static path.
edge-apps/calendar/screenly_qc.yml Update icon URL to new static path.
edge-apps/calendar/screenshots/daily-1080x1920.webp Add screenshot baseline.
edge-apps/calendar/screenshots/daily-1280x720.webp Add screenshot baseline.
edge-apps/calendar/screenshots/daily-1920x1080.webp Add screenshot baseline.
edge-apps/calendar/screenshots/daily-2160x3840.webp Add screenshot baseline.
edge-apps/calendar/screenshots/daily-2160x4096.webp Add screenshot baseline.
edge-apps/calendar/screenshots/daily-3840x2160.webp Add screenshot baseline.
edge-apps/calendar/screenshots/daily-4096x2160.webp Add screenshot baseline.
edge-apps/calendar/screenshots/daily-480x800.webp Add screenshot baseline.
edge-apps/calendar/screenshots/daily-720x1280.webp Add screenshot baseline.
edge-apps/calendar/screenshots/daily-800x480.webp Add screenshot baseline.
edge-apps/calendar/screenshots/schedule-1080x1920.webp Add screenshot baseline.
edge-apps/calendar/screenshots/schedule-1280x720.webp Add screenshot baseline.
edge-apps/calendar/screenshots/schedule-1920x1080.webp Add screenshot baseline.
edge-apps/calendar/screenshots/schedule-2160x3840.webp Add screenshot baseline.
edge-apps/calendar/screenshots/schedule-2160x4096.webp Add screenshot baseline.
edge-apps/calendar/screenshots/schedule-3840x2160.webp Add screenshot baseline.
edge-apps/calendar/screenshots/schedule-4096x2160.webp Add screenshot baseline.
edge-apps/calendar/screenshots/schedule-480x800.webp Add screenshot baseline.
edge-apps/calendar/screenshots/schedule-720x1280.webp Add screenshot baseline.
edge-apps/calendar/screenshots/schedule-800x480.webp Add screenshot baseline.
edge-apps/calendar/screenshots/weekly-1080x1920.webp Add screenshot baseline.
edge-apps/calendar/screenshots/weekly-1280x720.webp Add screenshot baseline.
edge-apps/calendar/screenshots/weekly-1920x1080.webp Add screenshot baseline.
edge-apps/calendar/screenshots/weekly-2160x3840.webp Add screenshot baseline.
edge-apps/calendar/screenshots/weekly-2160x4096.webp Add screenshot baseline.
edge-apps/calendar/screenshots/weekly-3840x2160.webp Add screenshot baseline.
edge-apps/calendar/screenshots/weekly-4096x2160.webp Add screenshot baseline.
edge-apps/calendar/screenshots/weekly-480x800.webp Add screenshot baseline.
edge-apps/calendar/screenshots/weekly-720x1280.webp Add screenshot baseline.
edge-apps/calendar/screenshots/weekly-800x480.webp Add screenshot baseline.
edge-apps/edge-apps-library/src/utils/screen.ts Add centerAutoScalerVertically() helper for orientation-constrained layouts.
edge-apps/edge-apps-library/src/utils/screen.test.ts Add unit tests for centerAutoScalerVertically().
edge-apps/edge-apps-library/src/utils/index.ts Export new calendar utilities.
edge-apps/edge-apps-library/src/utils/calendar.ts Add timezone-aware date range computation per view mode.
edge-apps/edge-apps-library/src/utils/calendar.test.ts Add unit tests for getDateRangeForViewMode().
edge-apps/edge-apps-library/src/types/index.ts Add CalendarViewMode + CALENDAR_VIEW_MODE.
edge-apps/edge-apps-library/src/components/vite-env.d.ts Add *.css?inline module typing.
edge-apps/edge-apps-library/src/components/register.ts Register calendar view custom elements globally.
edge-apps/edge-apps-library/src/components/index.ts Export calendar view components + event types.
edge-apps/edge-apps-library/src/components/calendar-views/event-layout.ts Add event overlap clustering + column/span layout algorithm.
edge-apps/edge-apps-library/src/components/calendar-views/calendar-view-utils.ts Add shared time gutter + event element builders for calendar views.
edge-apps/edge-apps-library/src/components/calendar-views/weekly-calendar-view/weekly-calendar-view.ts Add <weekly-calendar-view> implementation.
edge-apps/edge-apps-library/src/components/calendar-views/weekly-calendar-view/weekly-calendar-view-utils.ts Add weekly windowing/time-slot/event-style helpers + attribute safety helper.
edge-apps/edge-apps-library/src/components/calendar-views/weekly-calendar-view/weekly-calendar-view-styles.ts Add weekly calendar component styles.
edge-apps/edge-apps-library/src/components/calendar-views/weekly-calendar-view/index.ts Export weekly view + calendar event type.
edge-apps/edge-apps-library/src/components/calendar-views/daily-calendar-view/daily-calendar-view.ts Add <daily-calendar-view> implementation.
edge-apps/edge-apps-library/src/components/calendar-views/daily-calendar-view/daily-calendar-view-styles.ts Add daily calendar component styles.
edge-apps/edge-apps-library/src/components/calendar-views/daily-calendar-view/index.ts Export daily view.
edge-apps/edge-apps-library/src/components/calendar-views/schedule-calendar-view/schedule-calendar-view.ts Add <schedule-calendar-view> implementation.
edge-apps/edge-apps-library/src/components/calendar-views/schedule-calendar-view/schedule-calendar-view-styles.ts Add schedule view component styles.
edge-apps/edge-apps-library/src/components/calendar-views/schedule-calendar-view/index.ts Export schedule view.
edge-apps/edge-apps-library/package.json Add dayjs dependency to support new calendar/date utilities.
edge-apps/edge-apps-library/bun.lock Lockfile update for dayjs dependency.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +157 to +170
const windowEndHour = (windowStartHour + 12) % 24
const normalizedWindowEnd =
windowEndHour <= windowStartHour ? windowEndHour + 24 : windowEndHour
return events.filter((event) => {
if (event.isAllDay) return false
const eventStart = dayjs(event.startTime).tz(tz)
if (eventStart.format('YYYY-MM-DD') !== dayDateStr) return false
const startH = eventStart.hour() + eventStart.minute() / 60
const endDt = dayjs(event.endTime).tz(tz)
const endH = endDt.hour() + endDt.minute() / 60
const normStart = startH < windowStartHour ? startH + 24 : startH
const normEnd = endH <= windowStartHour ? endH + 24 : endH
return normStart < normalizedWindowEnd && normEnd > windowStartHour
})
Comment on lines +66 to +92
const windowSize = 12
const windowEndHour = (windowStartHour + windowSize) % 24

const startDt = dayjs(event.startTime).tz(tz)
const endDt = dayjs(event.endTime).tz(tz)

const startHour = startDt.hour() + startDt.minute() / 60
const endHour = endDt.hour() + endDt.minute() / 60

const normalizedWindowEnd =
windowEndHour <= windowStartHour ? windowEndHour + 24 : windowEndHour
const normalizedStart =
startHour < windowStartHour ? startHour + 24 : startHour
const normalizedEnd = endHour <= windowStartHour ? endHour + 24 : endHour

const visibleStart = Math.max(normalizedStart, windowStartHour)
const visibleEnd = Math.min(normalizedEnd, normalizedWindowEnd)

const topPct = ((visibleStart - windowStartHour) / windowSize) * 100
const heightPct = Math.max(
((visibleEnd - visibleStart) / windowSize) * 100,
0.5,
)

const clippedTop = normalizedStart < windowStartHour
const clippedBottom = normalizedEnd > normalizedWindowEnd

Comment on lines +12 to +14

const LOGO_DATA_URL = `data:image/svg+xml;base64,${Buffer.from(
fs.readFileSync(path.join(import.meta.dirname, 'screenly.svg'), 'utf-8'),
Comment on lines +13 to +15
const LOGO_DATA_URL = `data:image/svg+xml;base64,${Buffer.from(
fs.readFileSync(path.join(import.meta.dirname, 'screenly.svg'), 'utf-8'),
).toString('base64')}`
Comment on lines +9 to +37
## Deployment

## Create an Edge App Instance via CLI
Create and deploy the Edge App:

```bash
screenly edge-app instance create --name=EDGE_APP_INSTANCE_NAME
screenly edge-app create --name calendar --in-place
bun run deploy
screenly edge-app instance create
```

## Deployment
Configure the required settings:

```bash
bun run deploy
screenly edge-app setting set ical_url=<YOUR_ICAL_URL>
screenly edge-app setting set bypass_cors=true
```

## Configuration

| Setting | Description | Type | Default |
| ------------------- | ------------------------------------------------------------------------------------------------------ | -------- | ---------- |
| `ical_url` | iCal feed URL for your calendar (required) | secret | - |
| `calendar_mode` | View mode: `schedule`, `weekly`, or `daily` | optional | `schedule` |
| `bypass_cors` | Enable CORS bypass for iCal URLs that require it | optional | `true` |
| `override_locale` | Override the default locale (e.g. `fr`, `de`) | optional | `en` |
| `override_timezone` | Override the default timezone (e.g. `America/New_York`). Defaults to the system timezone if left blank | optional | - |
| `theme` | Visual theme: `light` or `dark` | optional | `light` |
| `display_errors` | Display errors on screen for debugging purposes | optional | `false` |
| `sentry_dsn` | Sentry DSN for error tracking and monitoring | optional | - |
Comment on lines +192 to +245
private _render() {
const shadow = this.shadowRoot!
const tz = this._timezone
const locale = this._locale
const now = this._now

const nowInTz = dayjs(now).tz(tz)
const currentHour = nowInTz.hour()
const currentMinute = nowInTz.minute()
const windowStartHour = getWindowStartHour(currentHour)
const timeSlots = generateTimeSlots(windowStartHour, now, locale, tz)
const weekStart = this._getWeekStart()
const eventLayouts = this._getEventLayouts()
const todayStr = nowInTz.format('YYYY-MM-DD')
const currentSlotIndex = timeSlots.findIndex(
(slot) => slot.hour === currentHour,
)
const timeIndicatorPct =
currentSlotIndex >= 0
? ((currentSlotIndex + currentMinute / 60) / 12) * 100
: -1

shadow.innerHTML = `<style>${COMPONENT_CSS}</style>`

const container = document.createElement('div')
container.className = 'weekly-calendar-container'
const title = document.createElement('p')
title.className = 'this-week-title'
title.textContent = 'This week'
container.appendChild(title)

const weekGrid = document.createElement('div')
weekGrid.className = 'week-grid'
weekGrid.appendChild(buildTimeGutter(timeSlots))

const daysGrid = document.createElement('div')
daysGrid.className = 'days-grid'
for (let dayIdx = 0; dayIdx < 7; dayIdx++) {
daysGrid.appendChild(
this._buildDayColumn(
dayIdx,
weekStart,
windowStartHour,
todayStr,
timeIndicatorPct,
eventLayouts,
),
)
}

weekGrid.appendChild(daysGrid)
container.appendChild(weekGrid)
shadow.appendChild(container)
}
node_modules/
dist/
*.log
.DS_Store
Comment on lines +1 to 4
node_modules/
dist/
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*

node_modules
.DS_Store
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants