@screenly/edge-apps 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/assets/fonts/Inter-Medium.woff2 +0 -0
- package/dist/assets/fonts/Inter-Regular.woff2 +0 -0
- package/dist/assets/fonts/Inter-SemiBold.woff2 +0 -0
- package/dist/assets/images/icons/chancesleet.svg +4 -0
- package/dist/assets/images/icons/clear-night.svg +5 -0
- package/dist/assets/images/icons/clear.svg +11 -0
- package/dist/assets/images/icons/cloudy.svg +4 -0
- package/dist/assets/images/icons/drizzle.svg +5 -0
- package/dist/assets/images/icons/fewdrops.svg +4 -0
- package/dist/assets/images/icons/fog.svg +6 -0
- package/dist/assets/images/icons/haze.svg +6 -0
- package/dist/assets/images/icons/mostly-cloudy-night.svg +7 -0
- package/dist/assets/images/icons/mostly-cloudy.svg +13 -0
- package/dist/assets/images/icons/partially-cloudy-night.svg +6 -0
- package/dist/assets/images/icons/partially-cloudy.svg +12 -0
- package/dist/assets/images/icons/partlysunny.svg +6 -0
- package/dist/assets/images/icons/rain-night.svg +8 -0
- package/dist/assets/images/icons/rainy.svg +6 -0
- package/dist/assets/images/icons/sleet-night.svg +14 -0
- package/dist/assets/images/icons/sleet.svg +4 -0
- package/dist/assets/images/icons/snow.svg +19 -0
- package/dist/assets/images/icons/thunderstorm-night.svg +9 -0
- package/dist/assets/images/icons/thunderstorm.svg +7 -0
- package/dist/assets/images/icons/windy.svg +6 -0
- package/dist/assets/images/screenly.svg +10 -0
- package/dist/components/app-header/app-header.d.ts +43 -0
- package/dist/components/app-header/app-header.d.ts.map +1 -0
- package/dist/components/app-header/app-header.js +244 -0
- package/dist/components/auto-scaler/auto-scaler.d.ts +65 -0
- package/dist/components/auto-scaler/auto-scaler.d.ts.map +1 -0
- package/dist/components/auto-scaler/auto-scaler.js +304 -0
- package/dist/components/brand-logo/brand-logo.d.ts +42 -0
- package/dist/components/brand-logo/brand-logo.d.ts.map +1 -0
- package/dist/components/brand-logo/brand-logo.js +209 -0
- package/dist/components/calendar-views/calendar-view-utils.d.ts +5 -0
- package/dist/components/calendar-views/calendar-view-utils.d.ts.map +1 -0
- package/dist/components/calendar-views/calendar-view-utils.js +73 -0
- package/dist/components/calendar-views/calendar-window-utils.d.ts +9 -0
- package/dist/components/calendar-views/calendar-window-utils.d.ts.map +1 -0
- package/dist/components/calendar-views/calendar-window-utils.js +57 -0
- package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view-styles.d.ts +2 -0
- package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view-styles.d.ts.map +1 -0
- package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view-styles.js +175 -0
- package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view.d.ts +21 -0
- package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view.d.ts.map +1 -0
- package/dist/components/calendar-views/daily-calendar-view/daily-calendar-view.js +130 -0
- package/dist/components/calendar-views/daily-calendar-view/index.d.ts +2 -0
- package/dist/components/calendar-views/daily-calendar-view/index.d.ts.map +1 -0
- package/dist/components/calendar-views/daily-calendar-view/index.js +1 -0
- package/dist/components/calendar-views/event-layout.d.ts +18 -0
- package/dist/components/calendar-views/event-layout.d.ts.map +1 -0
- package/dist/components/calendar-views/event-layout.js +139 -0
- package/dist/components/calendar-views/schedule-calendar-view/index.d.ts +2 -0
- package/dist/components/calendar-views/schedule-calendar-view/index.d.ts.map +1 -0
- package/dist/components/calendar-views/schedule-calendar-view/index.js +1 -0
- package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view-styles.d.ts +2 -0
- package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view-styles.d.ts.map +1 -0
- package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view-styles.js +118 -0
- package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view.d.ts +23 -0
- package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view.d.ts.map +1 -0
- package/dist/components/calendar-views/schedule-calendar-view/schedule-calendar-view.js +167 -0
- package/dist/components/calendar-views/weekly-calendar-view/index.d.ts +3 -0
- package/dist/components/calendar-views/weekly-calendar-view/index.d.ts.map +1 -0
- package/dist/components/calendar-views/weekly-calendar-view/index.js +1 -0
- package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-styles.d.ts +2 -0
- package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-styles.d.ts.map +1 -0
- package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-styles.js +234 -0
- package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-utils.d.ts +16 -0
- package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-utils.d.ts.map +1 -0
- package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view-utils.js +83 -0
- package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view.d.ts +26 -0
- package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view.d.ts.map +1 -0
- package/dist/components/calendar-views/weekly-calendar-view/weekly-calendar-view.js +220 -0
- package/dist/components/dev-tools/dev-tools.d.ts +48 -0
- package/dist/components/dev-tools/dev-tools.d.ts.map +1 -0
- package/dist/components/dev-tools/dev-tools.js +186 -0
- package/dist/components/index.d.ts +14 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +13 -0
- package/dist/components/register.d.ts +12 -0
- package/dist/components/register.d.ts.map +1 -0
- package/dist/components/register.js +11 -0
- package/dist/core/index.d.ts +30 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +77 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +8 -0
- package/dist/test/index.d.ts +3 -0
- package/dist/test/index.d.ts.map +1 -0
- package/dist/test/index.js +2 -0
- package/dist/test/mock.d.ts +23 -0
- package/dist/test/mock.d.ts.map +1 -0
- package/dist/test/mock.js +49 -0
- package/dist/test/screenshots.d.ts +120 -0
- package/dist/test/screenshots.d.ts.map +1 -0
- package/dist/test/screenshots.js +127 -0
- package/dist/test/setup.d.ts +2 -0
- package/dist/test/setup.d.ts.map +1 -0
- package/dist/test/setup.js +13 -0
- package/dist/types/index.d.ts +138 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +15 -0
- package/dist/utils/calendar.d.ts +28 -0
- package/dist/utils/calendar.d.ts.map +1 -0
- package/dist/utils/calendar.js +77 -0
- package/dist/utils/error-handling.d.ts +6 -0
- package/dist/utils/error-handling.d.ts.map +1 -0
- package/dist/utils/error-handling.js +16 -0
- package/dist/utils/html.d.ts +7 -0
- package/dist/utils/html.d.ts.map +1 -0
- package/dist/utils/html.js +13 -0
- package/dist/utils/index.d.ts +13 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +12 -0
- package/dist/utils/locale.d.ts +68 -0
- package/dist/utils/locale.d.ts.map +1 -0
- package/dist/utils/locale.js +318 -0
- package/dist/utils/metadata.d.ts +39 -0
- package/dist/utils/metadata.d.ts.map +1 -0
- package/dist/utils/metadata.js +66 -0
- package/dist/utils/oauth.d.ts +16 -0
- package/dist/utils/oauth.d.ts.map +1 -0
- package/dist/utils/oauth.js +42 -0
- package/dist/utils/screen.d.ts +26 -0
- package/dist/utils/screen.d.ts.map +1 -0
- package/dist/utils/screen.js +44 -0
- package/dist/utils/settings.d.ts +38 -0
- package/dist/utils/settings.d.ts.map +1 -0
- package/dist/utils/settings.js +89 -0
- package/dist/utils/template.d.ts +2 -0
- package/dist/utils/template.d.ts.map +1 -0
- package/dist/utils/template.js +6 -0
- package/dist/utils/theme.d.ts +47 -0
- package/dist/utils/theme.d.ts.map +1 -0
- package/dist/utils/theme.js +183 -0
- package/dist/utils/utm.d.ts +23 -0
- package/dist/utils/utm.d.ts.map +1 -0
- package/dist/utils/utm.js +30 -0
- package/dist/utils/weather.d.ts +84 -0
- package/dist/utils/weather.d.ts.map +1 -0
- package/dist/utils/weather.js +272 -0
- package/package.json +2 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,cAAc,kBAAkB,CAAA;AAGhC,cAAc,iBAAiB,CAAA;AAG/B,cAAc,uBAAuB,CAAA;AAGrC,cAAc,kBAAkB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
// Platform utilities (settings, theme, metadata, etc.)
|
|
2
|
+
export * from './utils/index.js';
|
|
3
|
+
// Core layout utilities (AutoScaler, etc.)
|
|
4
|
+
export * from './core/index.js';
|
|
5
|
+
// Web Components (AppHeader, AutoScaler, DevTools)
|
|
6
|
+
export * from './components/index.js';
|
|
7
|
+
// Types
|
|
8
|
+
export * from './types/index.js';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/test/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAA;AACzB,cAAc,YAAY,CAAA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ScreenlyObject, ScreenlyMetadata, ScreenlySettings } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Default mock metadata for testing
|
|
4
|
+
*/
|
|
5
|
+
export declare const mockMetadata: ScreenlyMetadata;
|
|
6
|
+
/**
|
|
7
|
+
* Default mock settings for testing
|
|
8
|
+
*/
|
|
9
|
+
export declare const mockSettings: ScreenlySettings;
|
|
10
|
+
/**
|
|
11
|
+
* Create a mock Screenly object for testing
|
|
12
|
+
*/
|
|
13
|
+
export declare function createMockScreenly(metadata?: Partial<ScreenlyMetadata>, settings?: Partial<ScreenlySettings>): ScreenlyObject;
|
|
14
|
+
/**
|
|
15
|
+
* Setup global screenly mock for testing
|
|
16
|
+
* Call this in your test setup to mock the global screenly object
|
|
17
|
+
*/
|
|
18
|
+
export declare function setupScreenlyMock(metadata?: Partial<ScreenlyMetadata>, settings?: Partial<ScreenlySettings>): ScreenlyObject;
|
|
19
|
+
/**
|
|
20
|
+
* Reset the global screenly mock
|
|
21
|
+
*/
|
|
22
|
+
export declare function resetScreenlyMock(): void;
|
|
23
|
+
//# sourceMappingURL=mock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock.d.ts","sourceRoot":"","sources":["../../src/test/mock.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EACjB,MAAM,mBAAmB,CAAA;AAI1B;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,gBAQ1B,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,EAAE,gBAM1B,CAAA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,EACxC,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,GACvC,cAAc,CAOhB;AAED;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,EACxC,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,GACvC,cAAc,CAIhB;AAED;;GAEG;AACH,wBAAgB,iBAAiB,IAAI,IAAI,CAExC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const global = globalThis;
|
|
2
|
+
/**
|
|
3
|
+
* Default mock metadata for testing
|
|
4
|
+
*/
|
|
5
|
+
export const mockMetadata = {
|
|
6
|
+
coordinates: [37.3861, -122.0839],
|
|
7
|
+
hostname: 'test-hostname',
|
|
8
|
+
location: 'Test Location',
|
|
9
|
+
hardware: 'test-hardware',
|
|
10
|
+
screenly_version: '1.0.0-test',
|
|
11
|
+
screen_name: 'Test Screen',
|
|
12
|
+
tags: ['test', 'development'],
|
|
13
|
+
};
|
|
14
|
+
/**
|
|
15
|
+
* Default mock settings for testing
|
|
16
|
+
*/
|
|
17
|
+
export const mockSettings = {
|
|
18
|
+
screenly_color_accent: '#972EFF',
|
|
19
|
+
screenly_color_light: '#ADAFBE',
|
|
20
|
+
screenly_color_dark: '#454BD2',
|
|
21
|
+
screenly_logo_light: '',
|
|
22
|
+
screenly_logo_dark: '',
|
|
23
|
+
};
|
|
24
|
+
/**
|
|
25
|
+
* Create a mock Screenly object for testing
|
|
26
|
+
*/
|
|
27
|
+
export function createMockScreenly(metadata = {}, settings = {}) {
|
|
28
|
+
return {
|
|
29
|
+
signalReadyForRendering: () => { },
|
|
30
|
+
metadata: { ...mockMetadata, ...metadata },
|
|
31
|
+
settings: { ...mockSettings, ...settings },
|
|
32
|
+
cors_proxy_url: 'http://localhost:8080',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Setup global screenly mock for testing
|
|
37
|
+
* Call this in your test setup to mock the global screenly object
|
|
38
|
+
*/
|
|
39
|
+
export function setupScreenlyMock(metadata = {}, settings = {}) {
|
|
40
|
+
const mock = createMockScreenly(metadata, settings);
|
|
41
|
+
global.screenly = mock;
|
|
42
|
+
return mock;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Reset the global screenly mock
|
|
46
|
+
*/
|
|
47
|
+
export function resetScreenlyMock() {
|
|
48
|
+
delete global.screenly;
|
|
49
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screenshot testing utilities and constants
|
|
3
|
+
*/
|
|
4
|
+
import type { ScreenlyMetadata, ScreenlyObject, ScreenlySettings } from '../types/index.js';
|
|
5
|
+
import { createMockScreenly } from './mock.js';
|
|
6
|
+
export { createMockScreenly };
|
|
7
|
+
/**
|
|
8
|
+
* Fixed date used for screenshot tests to ensure idempotent output.
|
|
9
|
+
* If tests rely on specific timestamps from mocked APIs, keep those mocks
|
|
10
|
+
* consistent with this value.
|
|
11
|
+
*/
|
|
12
|
+
export declare const FIXED_SCREENSHOT_DATE: Date;
|
|
13
|
+
interface PlaywrightRouteFulfillOptions {
|
|
14
|
+
status?: number;
|
|
15
|
+
contentType?: string;
|
|
16
|
+
body?: string;
|
|
17
|
+
}
|
|
18
|
+
interface PlaywrightRoute {
|
|
19
|
+
fulfill(options: PlaywrightRouteFulfillOptions): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Standard resolutions for screenshot testing
|
|
23
|
+
* Covers all supported Screenly player resolutions
|
|
24
|
+
*/
|
|
25
|
+
export declare const RESOLUTIONS: readonly [{
|
|
26
|
+
readonly width: 4096;
|
|
27
|
+
readonly height: 2160;
|
|
28
|
+
}, {
|
|
29
|
+
readonly width: 2160;
|
|
30
|
+
readonly height: 4096;
|
|
31
|
+
}, {
|
|
32
|
+
readonly width: 3840;
|
|
33
|
+
readonly height: 2160;
|
|
34
|
+
}, {
|
|
35
|
+
readonly width: 2160;
|
|
36
|
+
readonly height: 3840;
|
|
37
|
+
}, {
|
|
38
|
+
readonly width: 1920;
|
|
39
|
+
readonly height: 1080;
|
|
40
|
+
}, {
|
|
41
|
+
readonly width: 1080;
|
|
42
|
+
readonly height: 1920;
|
|
43
|
+
}, {
|
|
44
|
+
readonly width: 1280;
|
|
45
|
+
readonly height: 720;
|
|
46
|
+
}, {
|
|
47
|
+
readonly width: 720;
|
|
48
|
+
readonly height: 1280;
|
|
49
|
+
}, {
|
|
50
|
+
readonly width: 800;
|
|
51
|
+
readonly height: 480;
|
|
52
|
+
}, {
|
|
53
|
+
readonly width: 480;
|
|
54
|
+
readonly height: 800;
|
|
55
|
+
}];
|
|
56
|
+
/**
|
|
57
|
+
* Returns the screenshots output directory path, creating it if it doesn't exist.
|
|
58
|
+
* Resolves to `<cwd>/screenshots/`.
|
|
59
|
+
*/
|
|
60
|
+
export declare function getScreenshotsDir(): string;
|
|
61
|
+
/**
|
|
62
|
+
* Creates the screenly.js content string for Playwright route mocking
|
|
63
|
+
* @param screenlyObject - The Screenly object to inject into window.screenly
|
|
64
|
+
* @returns JavaScript content string for route mocking
|
|
65
|
+
*/
|
|
66
|
+
export declare function createScreenlyJsContent(screenlyObject: ScreenlyObject): string;
|
|
67
|
+
/**
|
|
68
|
+
* Creates a complete mock Screenly object with custom overrides and generates the JS content
|
|
69
|
+
* This is a convenience wrapper that combines createMockScreenly and createScreenlyJsContent
|
|
70
|
+
* @param metadata - Partial metadata overrides
|
|
71
|
+
* @param settings - Partial settings overrides
|
|
72
|
+
* @param corsProxyUrl - Custom CORS proxy URL (defaults to http://127.0.0.1:8080)
|
|
73
|
+
* @returns Object containing both the mock Screenly object and the JS content string
|
|
74
|
+
*/
|
|
75
|
+
export declare function createMockScreenlyForScreenshots(metadata?: Partial<ScreenlyMetadata>, settings?: Partial<ScreenlySettings>, corsProxyUrl?: string): {
|
|
76
|
+
mockScreenly: ScreenlyObject;
|
|
77
|
+
screenlyJsContent: string;
|
|
78
|
+
};
|
|
79
|
+
/**
|
|
80
|
+
* OpenWeather API mock data for Playwright route mocking
|
|
81
|
+
*/
|
|
82
|
+
export interface OpenWeatherMocks {
|
|
83
|
+
/** Mock data for reverse geocoding endpoint */
|
|
84
|
+
geocoding?: unknown;
|
|
85
|
+
/** Mock data for current weather endpoint */
|
|
86
|
+
weather?: unknown;
|
|
87
|
+
/** Mock data for forecast endpoint (optional) */
|
|
88
|
+
forecast?: unknown;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Setup OpenWeather API route mocks in Playwright
|
|
92
|
+
* @param page - Playwright page object
|
|
93
|
+
* @param mocks - Mock data for OpenWeather API endpoints
|
|
94
|
+
*/
|
|
95
|
+
export declare function setupOpenWeatherMocks(page: {
|
|
96
|
+
route: (url: string, handler: (route: PlaywrightRoute) => Promise<void>) => Promise<void>;
|
|
97
|
+
}, mocks: OpenWeatherMocks): Promise<void>;
|
|
98
|
+
/**
|
|
99
|
+
* Setup screenly.js route mock in Playwright
|
|
100
|
+
* @param page - Playwright page object
|
|
101
|
+
* @param screenlyJsContent - JavaScript content string for screenly.js
|
|
102
|
+
*/
|
|
103
|
+
export declare function setupScreenlyJsMock(page: {
|
|
104
|
+
route: (url: string, handler: (route: PlaywrightRoute) => Promise<void>) => Promise<void>;
|
|
105
|
+
}, screenlyJsContent: string): Promise<void>;
|
|
106
|
+
/**
|
|
107
|
+
* Freeze the browser clock to a fixed point in time before page load.
|
|
108
|
+
* Must be called before `page.goto()` to ensure the clock is set before
|
|
109
|
+
* any JavaScript runs. This makes screenshots idempotent regardless of
|
|
110
|
+
* when the test is executed.
|
|
111
|
+
*
|
|
112
|
+
* @param page - Playwright page object
|
|
113
|
+
* @param date - The date to freeze the clock at (defaults to FIXED_SCREENSHOT_DATE)
|
|
114
|
+
*/
|
|
115
|
+
export declare function setupClockMock(page: {
|
|
116
|
+
clock: {
|
|
117
|
+
setFixedTime(time: Date | number | string): Promise<void>;
|
|
118
|
+
};
|
|
119
|
+
}, date?: Date | number | string): Promise<void>;
|
|
120
|
+
//# sourceMappingURL=screenshots.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"screenshots.d.ts","sourceRoot":"","sources":["../../src/test/screenshots.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,gBAAgB,EACjB,MAAM,mBAAmB,CAAA;AAC1B,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AAE9C,OAAO,EAAE,kBAAkB,EAAE,CAAA;AAE7B;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,MAAmC,CAAA;AAErE,UAAU,6BAA6B;IACrC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,MAAM,CAAA;CACd;AAED,UAAU,eAAe;IACvB,OAAO,CAAC,OAAO,EAAE,6BAA6B,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/D;AAED;;;GAGG;AACH,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAWd,CAAA;AAEV;;;GAGG;AACH,wBAAgB,iBAAiB,IAAI,MAAM,CAI1C;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CACrC,cAAc,EAAE,cAAc,GAC7B,MAAM,CAKR;AAED;;;;;;;GAOG;AACH,wBAAgB,gCAAgC,CAC9C,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,EACxC,QAAQ,GAAE,OAAO,CAAC,gBAAgB,CAAM,EACxC,YAAY,SAA0B,GACrC;IAAE,YAAY,EAAE,cAAc,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,CAS7D;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+CAA+C;IAC/C,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,6CAA6C;IAC7C,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,iDAAiD;IACjD,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,IAAI,EAAE;IACJ,KAAK,EAAE,CACL,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,KAC/C,OAAO,CAAC,IAAI,CAAC,CAAA;CACnB,EACD,KAAK,EAAE,gBAAgB,GACtB,OAAO,CAAC,IAAI,CAAC,CAuCf;AAED;;;;GAIG;AACH,wBAAsB,mBAAmB,CACvC,IAAI,EAAE;IACJ,KAAK,EAAE,CACL,GAAG,EAAE,MAAM,EACX,OAAO,EAAE,CAAC,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,KAC/C,OAAO,CAAC,IAAI,CAAC,CAAA;CACnB,EACD,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,IAAI,CAAC,CAQf;AAED;;;;;;;;GAQG;AACH,wBAAsB,cAAc,CAClC,IAAI,EAAE;IACJ,KAAK,EAAE;QAAE,YAAY,CAAC,IAAI,EAAE,IAAI,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAA;CACrE,EACD,IAAI,GAAE,IAAI,GAAG,MAAM,GAAG,MAA8B,GACnD,OAAO,CAAC,IAAI,CAAC,CAEf"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Screenshot testing utilities and constants
|
|
3
|
+
*/
|
|
4
|
+
import fs from 'fs';
|
|
5
|
+
import path from 'path';
|
|
6
|
+
import { createMockScreenly } from './mock.js';
|
|
7
|
+
export { createMockScreenly };
|
|
8
|
+
/**
|
|
9
|
+
* Fixed date used for screenshot tests to ensure idempotent output.
|
|
10
|
+
* If tests rely on specific timestamps from mocked APIs, keep those mocks
|
|
11
|
+
* consistent with this value.
|
|
12
|
+
*/
|
|
13
|
+
export const FIXED_SCREENSHOT_DATE = new Date('2025-02-19T21:20:00Z');
|
|
14
|
+
/**
|
|
15
|
+
* Standard resolutions for screenshot testing
|
|
16
|
+
* Covers all supported Screenly player resolutions
|
|
17
|
+
*/
|
|
18
|
+
export const RESOLUTIONS = [
|
|
19
|
+
{ width: 4096, height: 2160 },
|
|
20
|
+
{ width: 2160, height: 4096 },
|
|
21
|
+
{ width: 3840, height: 2160 },
|
|
22
|
+
{ width: 2160, height: 3840 },
|
|
23
|
+
{ width: 1920, height: 1080 },
|
|
24
|
+
{ width: 1080, height: 1920 },
|
|
25
|
+
{ width: 1280, height: 720 },
|
|
26
|
+
{ width: 720, height: 1280 },
|
|
27
|
+
{ width: 800, height: 480 },
|
|
28
|
+
{ width: 480, height: 800 },
|
|
29
|
+
];
|
|
30
|
+
/**
|
|
31
|
+
* Returns the screenshots output directory path, creating it if it doesn't exist.
|
|
32
|
+
* Resolves to `<cwd>/screenshots/`.
|
|
33
|
+
*/
|
|
34
|
+
export function getScreenshotsDir() {
|
|
35
|
+
const dir = path.resolve('screenshots');
|
|
36
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
37
|
+
return dir;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Creates the screenly.js content string for Playwright route mocking
|
|
41
|
+
* @param screenlyObject - The Screenly object to inject into window.screenly
|
|
42
|
+
* @returns JavaScript content string for route mocking
|
|
43
|
+
*/
|
|
44
|
+
export function createScreenlyJsContent(screenlyObject) {
|
|
45
|
+
return `
|
|
46
|
+
window.screenly = ${JSON.stringify(screenlyObject, null, 2)};
|
|
47
|
+
window.screenly.signalReadyForRendering = function() {};
|
|
48
|
+
`;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Creates a complete mock Screenly object with custom overrides and generates the JS content
|
|
52
|
+
* This is a convenience wrapper that combines createMockScreenly and createScreenlyJsContent
|
|
53
|
+
* @param metadata - Partial metadata overrides
|
|
54
|
+
* @param settings - Partial settings overrides
|
|
55
|
+
* @param corsProxyUrl - Custom CORS proxy URL (defaults to http://127.0.0.1:8080)
|
|
56
|
+
* @returns Object containing both the mock Screenly object and the JS content string
|
|
57
|
+
*/
|
|
58
|
+
export function createMockScreenlyForScreenshots(metadata = {}, settings = {}, corsProxyUrl = 'http://127.0.0.1:8080') {
|
|
59
|
+
const mockScreenly = {
|
|
60
|
+
...createMockScreenly(metadata, settings),
|
|
61
|
+
cors_proxy_url: corsProxyUrl,
|
|
62
|
+
};
|
|
63
|
+
return {
|
|
64
|
+
mockScreenly,
|
|
65
|
+
screenlyJsContent: createScreenlyJsContent(mockScreenly),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Setup OpenWeather API route mocks in Playwright
|
|
70
|
+
* @param page - Playwright page object
|
|
71
|
+
* @param mocks - Mock data for OpenWeather API endpoints
|
|
72
|
+
*/
|
|
73
|
+
export async function setupOpenWeatherMocks(page, mocks) {
|
|
74
|
+
if (mocks.geocoding) {
|
|
75
|
+
await page.route('**/api.openweathermap.org/geo/1.0/reverse**', async (route) => {
|
|
76
|
+
await route.fulfill({
|
|
77
|
+
status: 200,
|
|
78
|
+
contentType: 'application/json',
|
|
79
|
+
body: JSON.stringify(mocks.geocoding),
|
|
80
|
+
});
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
if (mocks.weather) {
|
|
84
|
+
await page.route('**/api.openweathermap.org/data/2.5/weather**', async (route) => {
|
|
85
|
+
await route.fulfill({
|
|
86
|
+
status: 200,
|
|
87
|
+
contentType: 'application/json',
|
|
88
|
+
body: JSON.stringify(mocks.weather),
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
if (mocks.forecast) {
|
|
93
|
+
await page.route('**/api.openweathermap.org/data/2.5/forecast**', async (route) => {
|
|
94
|
+
await route.fulfill({
|
|
95
|
+
status: 200,
|
|
96
|
+
contentType: 'application/json',
|
|
97
|
+
body: JSON.stringify(mocks.forecast),
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Setup screenly.js route mock in Playwright
|
|
104
|
+
* @param page - Playwright page object
|
|
105
|
+
* @param screenlyJsContent - JavaScript content string for screenly.js
|
|
106
|
+
*/
|
|
107
|
+
export async function setupScreenlyJsMock(page, screenlyJsContent) {
|
|
108
|
+
await page.route('/screenly.js?version=1', async (route) => {
|
|
109
|
+
await route.fulfill({
|
|
110
|
+
status: 200,
|
|
111
|
+
contentType: 'application/javascript',
|
|
112
|
+
body: screenlyJsContent,
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Freeze the browser clock to a fixed point in time before page load.
|
|
118
|
+
* Must be called before `page.goto()` to ensure the clock is set before
|
|
119
|
+
* any JavaScript runs. This makes screenshots idempotent regardless of
|
|
120
|
+
* when the test is executed.
|
|
121
|
+
*
|
|
122
|
+
* @param page - Playwright page object
|
|
123
|
+
* @param date - The date to freeze the clock at (defaults to FIXED_SCREENSHOT_DATE)
|
|
124
|
+
*/
|
|
125
|
+
export async function setupClockMock(page, date = FIXED_SCREENSHOT_DATE) {
|
|
126
|
+
await page.clock.setFixedTime(date);
|
|
127
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../src/test/setup.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { JSDOM } from 'jsdom';
|
|
2
|
+
// Setup jsdom for DOM operations in tests
|
|
3
|
+
const dom = new JSDOM('<!DOCTYPE html><html><head></head><body></body></html>', {
|
|
4
|
+
url: 'http://localhost',
|
|
5
|
+
});
|
|
6
|
+
global.document = dom.window.document;
|
|
7
|
+
global.window = dom.window;
|
|
8
|
+
global.navigator = dom.window.navigator;
|
|
9
|
+
global.Node = dom.window.Node;
|
|
10
|
+
global.HTMLElement = dom.window.HTMLElement;
|
|
11
|
+
global.customElements = dom.window.customElements;
|
|
12
|
+
global.getComputedStyle = dom.window.getComputedStyle;
|
|
13
|
+
global.SVGSVGElement = dom.window.SVGSVGElement;
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hardware types for Screenly devices
|
|
3
|
+
*/
|
|
4
|
+
export declare enum Hardware {
|
|
5
|
+
Anywhere = "Anywhere",
|
|
6
|
+
RaspberryPi = "RaspberryPi",
|
|
7
|
+
ScreenlyPlayerMax = "ScreenlyPlayerMax",
|
|
8
|
+
Unknown = "Unknown"
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Screenly metadata provided by the Edge Apps runtime
|
|
12
|
+
*/
|
|
13
|
+
export interface ScreenlyMetadata {
|
|
14
|
+
/** GPS coordinates [latitude, longitude] */
|
|
15
|
+
coordinates: [number, number];
|
|
16
|
+
/** Hardware identifier */
|
|
17
|
+
hardware: string | undefined;
|
|
18
|
+
/** Device hostname */
|
|
19
|
+
hostname: string;
|
|
20
|
+
/** Physical location description */
|
|
21
|
+
location: string;
|
|
22
|
+
/** Screenly software version */
|
|
23
|
+
screenly_version: string;
|
|
24
|
+
/** Screen display name */
|
|
25
|
+
screen_name: string;
|
|
26
|
+
/** Tags associated with the screen */
|
|
27
|
+
tags: string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Screenly settings provided by the Edge Apps runtime
|
|
31
|
+
* This interface can be extended with custom settings
|
|
32
|
+
*/
|
|
33
|
+
export interface ScreenlySettings extends Record<string, unknown> {
|
|
34
|
+
/** Primary accent color for branding */
|
|
35
|
+
screenly_color_accent?: string;
|
|
36
|
+
/** Light theme color */
|
|
37
|
+
screenly_color_light?: string;
|
|
38
|
+
/** Dark theme color */
|
|
39
|
+
screenly_color_dark?: string;
|
|
40
|
+
/** Light theme logo URL */
|
|
41
|
+
screenly_logo_light?: string;
|
|
42
|
+
/** Dark theme logo URL */
|
|
43
|
+
screenly_logo_dark?: string;
|
|
44
|
+
/** Theme mode: light or dark */
|
|
45
|
+
theme?: 'light' | 'dark';
|
|
46
|
+
/** Sentry DSN for error tracking */
|
|
47
|
+
sentry_dsn?: string;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The global screenly object provided by screenly.js
|
|
51
|
+
*/
|
|
52
|
+
export interface ScreenlyObject {
|
|
53
|
+
/** Signal that the app is ready to be displayed */
|
|
54
|
+
signalReadyForRendering: () => void;
|
|
55
|
+
/** Device and screen metadata */
|
|
56
|
+
metadata: ScreenlyMetadata;
|
|
57
|
+
/** App settings and configuration */
|
|
58
|
+
settings: ScreenlySettings;
|
|
59
|
+
/** CORS proxy URL for fetching external resources */
|
|
60
|
+
cors_proxy_url: string;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Theme colors configuration
|
|
64
|
+
*/
|
|
65
|
+
export interface ThemeColors {
|
|
66
|
+
primary: string;
|
|
67
|
+
secondary: string;
|
|
68
|
+
tertiary: string;
|
|
69
|
+
background: string;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Branding configuration
|
|
73
|
+
*/
|
|
74
|
+
export interface BrandingConfig {
|
|
75
|
+
colors: ThemeColors;
|
|
76
|
+
logoUrl?: string;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Core UI/Layout types
|
|
80
|
+
*/
|
|
81
|
+
/**
|
|
82
|
+
* Orientation type for edge apps
|
|
83
|
+
*/
|
|
84
|
+
export type Orientation = 'landscape' | 'portrait' | 'auto';
|
|
85
|
+
/**
|
|
86
|
+
* Calendar view mode
|
|
87
|
+
*/
|
|
88
|
+
export type CalendarViewMode = 'daily' | 'weekly' | 'schedule';
|
|
89
|
+
export declare const CALENDAR_VIEW_MODE: {
|
|
90
|
+
DAILY: CalendarViewMode;
|
|
91
|
+
WEEKLY: CalendarViewMode;
|
|
92
|
+
SCHEDULE: CalendarViewMode;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Reference resolution configuration
|
|
96
|
+
*/
|
|
97
|
+
export interface ReferenceResolution {
|
|
98
|
+
width: number;
|
|
99
|
+
height: number;
|
|
100
|
+
orientation?: Orientation;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Safe zone configuration
|
|
104
|
+
*/
|
|
105
|
+
export interface SafeZoneConfig {
|
|
106
|
+
top?: number | string;
|
|
107
|
+
right?: number | string;
|
|
108
|
+
bottom?: number | string;
|
|
109
|
+
left?: number | string;
|
|
110
|
+
all?: number | string;
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* AutoScaler options
|
|
114
|
+
*/
|
|
115
|
+
export interface AutoScalerOptions {
|
|
116
|
+
padding?: number | string;
|
|
117
|
+
referenceWidth: number;
|
|
118
|
+
referenceHeight: number;
|
|
119
|
+
orientation?: Orientation;
|
|
120
|
+
centerContent?: boolean;
|
|
121
|
+
debounceMs?: number;
|
|
122
|
+
onScaleChange?: (scale: number) => void;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Edge app configuration
|
|
126
|
+
*/
|
|
127
|
+
export interface EdgeAppConfig {
|
|
128
|
+
referenceResolution: ReferenceResolution;
|
|
129
|
+
enableDevTools?: boolean;
|
|
130
|
+
}
|
|
131
|
+
declare global {
|
|
132
|
+
interface Window {
|
|
133
|
+
screenly: ScreenlyObject;
|
|
134
|
+
}
|
|
135
|
+
const screenly: ScreenlyObject;
|
|
136
|
+
}
|
|
137
|
+
export {};
|
|
138
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hardware types for Screenly devices
|
|
3
|
+
*/
|
|
4
|
+
export var Hardware;
|
|
5
|
+
(function (Hardware) {
|
|
6
|
+
Hardware["Anywhere"] = "Anywhere";
|
|
7
|
+
Hardware["RaspberryPi"] = "RaspberryPi";
|
|
8
|
+
Hardware["ScreenlyPlayerMax"] = "ScreenlyPlayerMax";
|
|
9
|
+
Hardware["Unknown"] = "Unknown";
|
|
10
|
+
})(Hardware || (Hardware = {}));
|
|
11
|
+
export const CALENDAR_VIEW_MODE = {
|
|
12
|
+
DAILY: 'daily',
|
|
13
|
+
WEEKLY: 'weekly',
|
|
14
|
+
SCHEDULE: 'schedule',
|
|
15
|
+
};
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { CalendarViewMode } from '../types/index.js';
|
|
2
|
+
import type { WeeklyCalendarView } from '../components/calendar-views/weekly-calendar-view/index.js';
|
|
3
|
+
import type { DailyCalendarView } from '../components/calendar-views/daily-calendar-view/index.js';
|
|
4
|
+
import type { ScheduleCalendarView } from '../components/calendar-views/schedule-calendar-view/index.js';
|
|
5
|
+
import type { CalendarEvent } from '../components/calendar-views/event-layout.js';
|
|
6
|
+
type CalendarViewElement = WeeklyCalendarView | DailyCalendarView | ScheduleCalendarView;
|
|
7
|
+
export declare function initCalendarApp(activeEl: CalendarViewElement, fetchEvents: (timezone: string) => Promise<CalendarEvent[]>): Promise<void>;
|
|
8
|
+
/**
|
|
9
|
+
* Read the `calendar_mode` setting and return the date range for the current
|
|
10
|
+
* view, anchored to today in the given timezone.
|
|
11
|
+
*
|
|
12
|
+
* The legacy `'monthly'` mode is treated as `'schedule'` since the schedule
|
|
13
|
+
* view replaced it.
|
|
14
|
+
*/
|
|
15
|
+
export declare function getCalendarDateRange(timezone: string): {
|
|
16
|
+
startDate: Date;
|
|
17
|
+
endDate: Date;
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Compute the start and end dates for the given calendar view mode,
|
|
21
|
+
* anchored to the current date in the specified timezone.
|
|
22
|
+
*/
|
|
23
|
+
export declare function getDateRangeForViewMode(viewMode: CalendarViewMode, timezone: string): {
|
|
24
|
+
startDate: Date;
|
|
25
|
+
endDate: Date;
|
|
26
|
+
};
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=calendar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"calendar.d.ts","sourceRoot":"","sources":["../../src/utils/calendar.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,4DAA4D,CAAA;AACpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2DAA2D,CAAA;AAClG,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,8DAA8D,CAAA;AACxG,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8CAA8C,CAAA;AAQjF,KAAK,mBAAmB,GACpB,kBAAkB,GAClB,iBAAiB,GACjB,oBAAoB,CAAA;AAKxB,wBAAsB,eAAe,CACnC,QAAQ,EAAE,mBAAmB,EAC7B,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,OAAO,CAAC,aAAa,EAAE,CAAC,GAC1D,OAAO,CAAC,IAAI,CAAC,CA6Bf;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG;IACtD,SAAS,EAAE,IAAI,CAAA;IACf,OAAO,EAAE,IAAI,CAAA;CACd,CAOA;AAED;;;GAGG;AACH,wBAAgB,uBAAuB,CACrC,QAAQ,EAAE,gBAAgB,EAC1B,QAAQ,EAAE,MAAM,GACf;IAAE,SAAS,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,IAAI,CAAA;CAAE,CAuBpC"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import dayjs from 'dayjs';
|
|
2
|
+
import utc from 'dayjs/plugin/utc';
|
|
3
|
+
import timezone from 'dayjs/plugin/timezone';
|
|
4
|
+
import { CALENDAR_VIEW_MODE } from '../types/index.js';
|
|
5
|
+
import { centerAutoScalerVertically } from './screen.js';
|
|
6
|
+
import { getLocale, getTimeZone } from './locale.js';
|
|
7
|
+
import { signalReady, getSettingWithDefault } from './settings.js';
|
|
8
|
+
dayjs.extend(utc);
|
|
9
|
+
dayjs.extend(timezone);
|
|
10
|
+
const EVENTS_REFRESH_INTERVAL = 10_000;
|
|
11
|
+
const NOW_TICK_INTERVAL = 30_000;
|
|
12
|
+
export async function initCalendarApp(activeEl, fetchEvents) {
|
|
13
|
+
const scaler = document.querySelector('auto-scaler');
|
|
14
|
+
scaler?.addEventListener('scalechange', centerAutoScalerVertically);
|
|
15
|
+
window.addEventListener('resize', centerAutoScalerVertically);
|
|
16
|
+
centerAutoScalerVertically();
|
|
17
|
+
const timezone = await getTimeZone();
|
|
18
|
+
const locale = await getLocale();
|
|
19
|
+
activeEl.setAttribute('timezone', timezone);
|
|
20
|
+
activeEl.setAttribute('locale', locale);
|
|
21
|
+
const tick = () => {
|
|
22
|
+
activeEl.now = new Date();
|
|
23
|
+
};
|
|
24
|
+
tick();
|
|
25
|
+
setInterval(tick, NOW_TICK_INTERVAL);
|
|
26
|
+
const refresh = async () => {
|
|
27
|
+
try {
|
|
28
|
+
const events = await fetchEvents(timezone);
|
|
29
|
+
activeEl.events = events;
|
|
30
|
+
}
|
|
31
|
+
catch (error) {
|
|
32
|
+
console.error('Failed to fetch calendar events:', error);
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
await refresh();
|
|
36
|
+
setInterval(refresh, EVENTS_REFRESH_INTERVAL);
|
|
37
|
+
signalReady();
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Read the `calendar_mode` setting and return the date range for the current
|
|
41
|
+
* view, anchored to today in the given timezone.
|
|
42
|
+
*
|
|
43
|
+
* The legacy `'monthly'` mode is treated as `'schedule'` since the schedule
|
|
44
|
+
* view replaced it.
|
|
45
|
+
*/
|
|
46
|
+
export function getCalendarDateRange(timezone) {
|
|
47
|
+
const viewMode = getSettingWithDefault('calendar_mode', 'schedule');
|
|
48
|
+
const mappedViewMode = viewMode === 'monthly'
|
|
49
|
+
? CALENDAR_VIEW_MODE.SCHEDULE
|
|
50
|
+
: viewMode;
|
|
51
|
+
return getDateRangeForViewMode(mappedViewMode, timezone);
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Compute the start and end dates for the given calendar view mode,
|
|
55
|
+
* anchored to the current date in the specified timezone.
|
|
56
|
+
*/
|
|
57
|
+
export function getDateRangeForViewMode(viewMode, timezone) {
|
|
58
|
+
const todayInTimezone = dayjs(Date.now()).tz(timezone).startOf('day');
|
|
59
|
+
if (viewMode === CALENDAR_VIEW_MODE.DAILY) {
|
|
60
|
+
return {
|
|
61
|
+
startDate: todayInTimezone.toDate(),
|
|
62
|
+
endDate: todayInTimezone.add(1, 'day').toDate(),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
if (viewMode === CALENDAR_VIEW_MODE.WEEKLY) {
|
|
66
|
+
const weekStart = todayInTimezone.startOf('week');
|
|
67
|
+
return {
|
|
68
|
+
startDate: weekStart.toDate(),
|
|
69
|
+
endDate: weekStart.add(7, 'days').toDate(),
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
const monthStart = todayInTimezone.startOf('month');
|
|
73
|
+
return {
|
|
74
|
+
startDate: monthStart.toDate(),
|
|
75
|
+
endDate: monthStart.add(1, 'month').toDate(),
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-handling.d.ts","sourceRoot":"","sources":["../../src/utils/error-handling.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,kBAAkB,IAAI,IAAI,CASzC"}
|