@luckydye/calendar 1.1.2 → 1.1.3
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/calendar.js +1387 -1301
- package/package.json +1 -1
- package/src/CalDAVConfig.ts +25 -0
- package/src/CalendarIntegration.ts +1 -2
- package/src/CalendarInternal.ts +20 -1
- package/src/CalendarView.ts +474 -257
- package/src/GoogleCalendarSource.ts +0 -7
- package/src/InMemorySource.ts +0 -15
- package/src/InhouseBookingSource.ts +331 -46
- package/src/Keybinds.ts +46 -0
- package/src/app.css +28 -0
- package/src/app.ts +173 -63
package/package.json
CHANGED
package/src/CalDAVConfig.ts
CHANGED
|
@@ -11,6 +11,7 @@ interface CalDAVSourceConfig extends CalendarSource {
|
|
|
11
11
|
username: string;
|
|
12
12
|
password: string;
|
|
13
13
|
};
|
|
14
|
+
locked?: boolean;
|
|
14
15
|
}
|
|
15
16
|
|
|
16
17
|
interface ICalSource extends CalendarSource {
|
|
@@ -18,6 +19,7 @@ interface ICalSource extends CalendarSource {
|
|
|
18
19
|
credentials: {
|
|
19
20
|
url: string;
|
|
20
21
|
};
|
|
22
|
+
locked?: boolean;
|
|
21
23
|
}
|
|
22
24
|
|
|
23
25
|
interface GoogleSource extends CalendarSource {
|
|
@@ -28,6 +30,7 @@ interface GoogleSource extends CalendarSource {
|
|
|
28
30
|
tokenExpiry?: string;
|
|
29
31
|
calendarId?: string;
|
|
30
32
|
};
|
|
33
|
+
locked?: boolean;
|
|
31
34
|
}
|
|
32
35
|
|
|
33
36
|
interface InhouseSource extends CalendarSource {
|
|
@@ -37,6 +40,7 @@ interface InhouseSource extends CalendarSource {
|
|
|
37
40
|
employeeId: string;
|
|
38
41
|
unitId?: string;
|
|
39
42
|
};
|
|
43
|
+
locked?: boolean;
|
|
40
44
|
}
|
|
41
45
|
|
|
42
46
|
type ConfigurableSource = CalDAVSourceConfig | ICalSource | GoogleSource | InhouseSource;
|
|
@@ -132,6 +136,11 @@ export class CalDAVConfigElement extends LitElement {
|
|
|
132
136
|
cursor: pointer;
|
|
133
137
|
}
|
|
134
138
|
|
|
139
|
+
.source-locked {
|
|
140
|
+
cursor: pointer;
|
|
141
|
+
margin-left: 8px;
|
|
142
|
+
}
|
|
143
|
+
|
|
135
144
|
.source-actions {
|
|
136
145
|
display: flex;
|
|
137
146
|
gap: 8px;
|
|
@@ -463,6 +472,11 @@ export class CalDAVConfigElement extends LitElement {
|
|
|
463
472
|
this.saveSources();
|
|
464
473
|
}
|
|
465
474
|
|
|
475
|
+
toggleLocked(source: ConfigurableSource) {
|
|
476
|
+
source.locked = !source.locked;
|
|
477
|
+
this.saveSources();
|
|
478
|
+
}
|
|
479
|
+
|
|
466
480
|
saveForm() {
|
|
467
481
|
if (!this.formData.name?.trim()) {
|
|
468
482
|
alert('Please enter a calendar name');
|
|
@@ -496,6 +510,7 @@ export class CalDAVConfigElement extends LitElement {
|
|
|
496
510
|
},
|
|
497
511
|
color: this.formData.color || "#FF6E68",
|
|
498
512
|
enabled: this.formData.enabled ?? true,
|
|
513
|
+
locked: this.formData.locked ?? false,
|
|
499
514
|
} as CalDAVSourceConfig;
|
|
500
515
|
} else if (this.formData.type === "ical") {
|
|
501
516
|
if (!this.formData.credentials?.url) {
|
|
@@ -511,6 +526,7 @@ export class CalDAVConfigElement extends LitElement {
|
|
|
511
526
|
},
|
|
512
527
|
color: this.formData.color || "#FF6E68",
|
|
513
528
|
enabled: this.formData.enabled ?? true,
|
|
529
|
+
locked: this.formData.locked ?? false,
|
|
514
530
|
} as ICalSource;
|
|
515
531
|
} else if (this.formData.type === "google") {
|
|
516
532
|
if (!this.formData.credentials?.accessToken) {
|
|
@@ -530,6 +546,7 @@ export class CalDAVConfigElement extends LitElement {
|
|
|
530
546
|
},
|
|
531
547
|
color: this.formData.color || "#4285F4",
|
|
532
548
|
enabled: this.formData.enabled ?? true,
|
|
549
|
+
locked: this.formData.locked ?? false,
|
|
533
550
|
} as GoogleSource;
|
|
534
551
|
} else if (this.formData.type === "inhouse") {
|
|
535
552
|
if (!this.formData.credentials?.sessionCookie || !this.formData.credentials?.employeeId) {
|
|
@@ -548,6 +565,7 @@ export class CalDAVConfigElement extends LitElement {
|
|
|
548
565
|
},
|
|
549
566
|
color: this.formData.color || "#FF6E68",
|
|
550
567
|
enabled: this.formData.enabled ?? true,
|
|
568
|
+
locked: this.formData.locked ?? false,
|
|
551
569
|
} as InhouseSource;
|
|
552
570
|
} else {
|
|
553
571
|
return;
|
|
@@ -754,6 +772,13 @@ export class CalDAVConfigElement extends LitElement {
|
|
|
754
772
|
@change=${() => this.toggleEnabled(source)}
|
|
755
773
|
title="${source.enabled ? "Disable" : "Enable"} sync"
|
|
756
774
|
/>
|
|
775
|
+
<input
|
|
776
|
+
type="checkbox"
|
|
777
|
+
class="source-locked"
|
|
778
|
+
.checked=${source.locked}
|
|
779
|
+
@change=${() => this.toggleLocked(source)}
|
|
780
|
+
title="${source.locked ? "Unlock (allow editing)" : "Lock (read-only)"}"
|
|
781
|
+
/>
|
|
757
782
|
<div class="source-actions">
|
|
758
783
|
<button
|
|
759
784
|
class="icon-btn"
|
|
@@ -5,13 +5,13 @@ export interface Calendar {
|
|
|
5
5
|
name: string;
|
|
6
6
|
color: string;
|
|
7
7
|
enabled: boolean;
|
|
8
|
+
locked?: boolean;
|
|
8
9
|
sourceId: string;
|
|
9
10
|
sourceType: string;
|
|
10
11
|
calendarUrl?: string;
|
|
11
12
|
fetchEvents(): Promise<CalendarEvent[]>;
|
|
12
13
|
createEvent?(event: Omit<CalendarEvent, 'calendar' | 'color'>): Promise<CalendarEvent>;
|
|
13
14
|
updateEvent?(id: string, updates: Partial<CalendarEvent>): Promise<CalendarEvent>;
|
|
14
|
-
moveEvent?(id: string, newStart: Date, newEnd: Date): Promise<CalendarEvent>;
|
|
15
15
|
deleteEvent?(id: string): Promise<void>;
|
|
16
16
|
}
|
|
17
17
|
|
|
@@ -29,7 +29,6 @@ export interface CalendarSource {
|
|
|
29
29
|
fetchEvents(): Promise<CalendarEvent[]>;
|
|
30
30
|
createEvent?(event: Omit<CalendarEvent, 'calendar' | 'color'>): Promise<CalendarEvent>;
|
|
31
31
|
updateEvent?(id: string, updates: Partial<CalendarEvent>): Promise<CalendarEvent>;
|
|
32
|
-
moveEvent?(id: string, newStart: Date, newEnd: Date): Promise<CalendarEvent>;
|
|
33
32
|
deleteEvent?(id: string): Promise<void>;
|
|
34
33
|
}
|
|
35
34
|
|
package/src/CalendarInternal.ts
CHANGED
|
@@ -101,6 +101,8 @@ export class CalendarInternal {
|
|
|
101
101
|
|
|
102
102
|
enabledCalendars: Set<string> = new Set();
|
|
103
103
|
|
|
104
|
+
lockedCalendars: Set<string> = new Set();
|
|
105
|
+
|
|
104
106
|
storage?: CalendarStorage;
|
|
105
107
|
initPromise: Promise<void>;
|
|
106
108
|
|
|
@@ -193,6 +195,11 @@ export class CalendarInternal {
|
|
|
193
195
|
this.sendEvents();
|
|
194
196
|
}
|
|
195
197
|
|
|
198
|
+
setLockedCalendars(calendarIds: string[]) {
|
|
199
|
+
this.lockedCalendars = new Set(calendarIds);
|
|
200
|
+
this.sendEvents();
|
|
201
|
+
}
|
|
202
|
+
|
|
196
203
|
expandRecurringEvent(event: CalendarEvent): CalendarEvent[] {
|
|
197
204
|
if (!event.rrule) {
|
|
198
205
|
return [event];
|
|
@@ -252,8 +259,20 @@ export class CalendarInternal {
|
|
|
252
259
|
})
|
|
253
260
|
: baseEvents;
|
|
254
261
|
|
|
262
|
+
// Mark events from locked calendars as read-only
|
|
263
|
+
const lockedEvents = this.lockedCalendars.size > 0
|
|
264
|
+
? enabledEvents.map(e => {
|
|
265
|
+
const isLocked = (e.calendarId && this.lockedCalendars.has(e.calendarId)) ||
|
|
266
|
+
(e.sourceId && this.lockedCalendars.has(e.sourceId));
|
|
267
|
+
if (isLocked) {
|
|
268
|
+
return { ...e, readOnly: true };
|
|
269
|
+
}
|
|
270
|
+
return e;
|
|
271
|
+
})
|
|
272
|
+
: enabledEvents;
|
|
273
|
+
|
|
255
274
|
const expandedEvents: CalendarEvent[] = [];
|
|
256
|
-
for (const event of
|
|
275
|
+
for (const event of lockedEvents) {
|
|
257
276
|
const instances = this.expandRecurringEvent(event);
|
|
258
277
|
expandedEvents.push(...instances);
|
|
259
278
|
}
|