@primeui/scheduler-core 0.0.1-alpha.1
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/LICENSE +23 -0
- package/README.md +1 -0
- package/dist/calendar/index.d.mts +57 -0
- package/dist/calendar/index.mjs +1 -0
- package/dist/chunk-2B3YLWHA.mjs +196 -0
- package/dist/chunk-2THQAZ26.mjs +1669 -0
- package/dist/chunk-5KORIWDT.mjs +41 -0
- package/dist/chunk-5N4ZOBJV.mjs +866 -0
- package/dist/chunk-6OZAPQZ5.mjs +229 -0
- package/dist/chunk-6PK5WSKT.mjs +369 -0
- package/dist/chunk-6VYWVIGM.mjs +1170 -0
- package/dist/chunk-AAVM7UCG.mjs +100 -0
- package/dist/chunk-C7ADJGNV.mjs +157 -0
- package/dist/chunk-DYW6WUHE.mjs +277 -0
- package/dist/chunk-F5W5HD7S.mjs +285 -0
- package/dist/chunk-FIBAZFC4.mjs +871 -0
- package/dist/chunk-HPC5B3AR.mjs +558 -0
- package/dist/chunk-KQGRXTP5.mjs +650 -0
- package/dist/chunk-NMX4BW42.mjs +672 -0
- package/dist/chunk-NX46LPLF.mjs +440 -0
- package/dist/chunk-NZGJN7HG.mjs +314 -0
- package/dist/chunk-QDMZBJDV.mjs +251 -0
- package/dist/chunk-QR2SVYAD.mjs +1144 -0
- package/dist/chunk-SYJ5O4KH.mjs +136 -0
- package/dist/chunk-TNKJPFGI.mjs +569 -0
- package/dist/chunk-UMAMDBU4.mjs +1 -0
- package/dist/chunk-W2SJW3QQ.mjs +3925 -0
- package/dist/chunk-WFUJWDST.mjs +352 -0
- package/dist/chunk-XUBQ2IQS.mjs +1 -0
- package/dist/chunk-ZUKUKGNK.mjs +613 -0
- package/dist/controllers/index.d.mts +384 -0
- package/dist/controllers/index.mjs +13 -0
- package/dist/date-D_CjQPmM.d.mts +74 -0
- package/dist/display-format-CLVvRt4I.d.mts +57 -0
- package/dist/event/index.d.mts +267 -0
- package/dist/event/index.mjs +8 -0
- package/dist/event-surface-_R_LHD95.d.mts +21 -0
- package/dist/event.positioning-BdzAVPk7.d.mts +51 -0
- package/dist/event.utils-QSNdd-3W.d.mts +35 -0
- package/dist/index.d.mts +1128 -0
- package/dist/index.mjs +1022 -0
- package/dist/interaction/index.d.mts +442 -0
- package/dist/interaction/index.mjs +9 -0
- package/dist/month/index.d.mts +104 -0
- package/dist/month/index.mjs +6 -0
- package/dist/overlay-BYM9B6nC.d.mts +64 -0
- package/dist/resource/index.d.mts +172 -0
- package/dist/resource/index.mjs +1 -0
- package/dist/selection-CO_98HdS.d.mts +56 -0
- package/dist/time-grid/index.d.mts +92 -0
- package/dist/time-grid/index.mjs +13 -0
- package/dist/timeline/index.d.mts +165 -0
- package/dist/timeline/index.mjs +6 -0
- package/dist/touch-BhsMWsjf.d.mts +69 -0
- package/dist/utils/index.d.mts +494 -0
- package/dist/utils/index.mjs +17 -0
- package/dist/views/index.d.mts +51 -0
- package/dist/views/index.mjs +8 -0
- package/dist/views/timeline/index.d.mts +37 -0
- package/dist/views/timeline/index.mjs +4 -0
- package/dist/year/index.d.mts +70 -0
- package/dist/year/index.mjs +6 -0
- package/package.json +58 -0
|
@@ -0,0 +1,3925 @@
|
|
|
1
|
+
import { hasSelection, canDropEventWithResourceConstraints } from './chunk-NX46LPLF.mjs';
|
|
2
|
+
import { getView } from './chunk-ZUKUKGNK.mjs';
|
|
3
|
+
import { canSelect, isRangeWithinBusinessHours } from './chunk-HPC5B3AR.mjs';
|
|
4
|
+
import { parseRRule, serializeRRule, expandRRule } from './chunk-FIBAZFC4.mjs';
|
|
5
|
+
import { getTimezoneOffset, getDatePartsInTimezone, isValidTimezone, createDateInTimezone } from './chunk-QDMZBJDV.mjs';
|
|
6
|
+
import { startOfDay, endOfDay } from './chunk-WFUJWDST.mjs';
|
|
7
|
+
import { createSchedulerDateFormatter } from './chunk-TNKJPFGI.mjs';
|
|
8
|
+
import { resolveSchedulerCalendarModeForView, getSchedulerCalendarAdapter } from './chunk-DYW6WUHE.mjs';
|
|
9
|
+
|
|
10
|
+
// src/utils/locale.ts
|
|
11
|
+
var defaultText = {
|
|
12
|
+
today: "Today",
|
|
13
|
+
month: "Month",
|
|
14
|
+
week: "Week",
|
|
15
|
+
day: "Day",
|
|
16
|
+
year: "Year",
|
|
17
|
+
agenda: "Agenda",
|
|
18
|
+
dateView: "Date",
|
|
19
|
+
allDay: "All day",
|
|
20
|
+
noEvents: "No events",
|
|
21
|
+
moreEvents: (count) => `+${count} more`,
|
|
22
|
+
eventCount: (count) => count === 1 ? "1 event" : `${count} events`,
|
|
23
|
+
selectedCount: (count) => `${count} selected`,
|
|
24
|
+
weekLabel: "W",
|
|
25
|
+
prevMonth: "Previous month",
|
|
26
|
+
nextMonth: "Next month",
|
|
27
|
+
prevYear: "Previous year",
|
|
28
|
+
nextYear: "Next year",
|
|
29
|
+
prevWeek: "Previous week",
|
|
30
|
+
nextWeek: "Next week",
|
|
31
|
+
prevDay: "Previous day",
|
|
32
|
+
nextDay: "Next day",
|
|
33
|
+
timeline: "Timeline",
|
|
34
|
+
customRange: "Custom Range",
|
|
35
|
+
save: "Save",
|
|
36
|
+
cancel: "Cancel",
|
|
37
|
+
clear: "Clear",
|
|
38
|
+
edit: "Edit",
|
|
39
|
+
delete: "Delete",
|
|
40
|
+
close: "Close",
|
|
41
|
+
confirm: "Confirm",
|
|
42
|
+
addEvent: "Add Event",
|
|
43
|
+
actionsUnavailable: "Actions unavailable",
|
|
44
|
+
newEvent: "New Event",
|
|
45
|
+
editEvent: "Edit Event",
|
|
46
|
+
deleteEvent: "Delete Event",
|
|
47
|
+
deleteConfirmation: "Are you sure you want to delete this event?",
|
|
48
|
+
title: "Title",
|
|
49
|
+
from: "From",
|
|
50
|
+
to: "To",
|
|
51
|
+
location: "Location",
|
|
52
|
+
description: "Description",
|
|
53
|
+
allDayEvent: "All-day event",
|
|
54
|
+
resources: "Resources",
|
|
55
|
+
repeat: "Repeat",
|
|
56
|
+
repeatEvery: "Repeat every",
|
|
57
|
+
never: "Never",
|
|
58
|
+
daily: "Daily",
|
|
59
|
+
weekly: "Weekly",
|
|
60
|
+
monthly: "Monthly",
|
|
61
|
+
yearly: "Yearly",
|
|
62
|
+
endBy: "End by",
|
|
63
|
+
endAfter: "End after",
|
|
64
|
+
noEndDate: "No end date",
|
|
65
|
+
occurrences: "occurrences",
|
|
66
|
+
editRecurringEvent: "Edit recurring event",
|
|
67
|
+
deleteRecurringEvent: "Delete recurring event",
|
|
68
|
+
recurrenceScopeThis: "This event",
|
|
69
|
+
recurrenceScopeThisDescription: "Only this occurrence will be affected.",
|
|
70
|
+
recurrenceScopeFuture: "This and following events",
|
|
71
|
+
recurrenceScopeFutureDescription: "This occurrence and all after it will be affected.",
|
|
72
|
+
recurrenceScopeAll: "All events in the series",
|
|
73
|
+
recurrenceScopeAllDescription: "Every occurrence in the series will be affected."
|
|
74
|
+
};
|
|
75
|
+
var fallbackFirstDayOfWeekByLocale = {
|
|
76
|
+
en: 0,
|
|
77
|
+
"en-US": 0,
|
|
78
|
+
"en-GB": 1,
|
|
79
|
+
de: 1,
|
|
80
|
+
fr: 1,
|
|
81
|
+
es: 1,
|
|
82
|
+
it: 1,
|
|
83
|
+
pt: 0,
|
|
84
|
+
nl: 1,
|
|
85
|
+
pl: 1,
|
|
86
|
+
ru: 1,
|
|
87
|
+
ja: 0,
|
|
88
|
+
zh: 0,
|
|
89
|
+
"zh-CN": 0,
|
|
90
|
+
"zh-TW": 0,
|
|
91
|
+
ko: 0,
|
|
92
|
+
ar: 0,
|
|
93
|
+
he: 0,
|
|
94
|
+
tr: 1
|
|
95
|
+
};
|
|
96
|
+
var fallbackRtlLocales = /* @__PURE__ */ new Set(["ar", "he"]);
|
|
97
|
+
var locales = {
|
|
98
|
+
en: {
|
|
99
|
+
code: "en",
|
|
100
|
+
text: defaultText
|
|
101
|
+
},
|
|
102
|
+
"en-US": {
|
|
103
|
+
code: "en-US",
|
|
104
|
+
text: defaultText
|
|
105
|
+
},
|
|
106
|
+
"en-GB": {
|
|
107
|
+
code: "en-GB",
|
|
108
|
+
text: defaultText
|
|
109
|
+
},
|
|
110
|
+
de: {
|
|
111
|
+
code: "de",
|
|
112
|
+
text: {
|
|
113
|
+
today: "Heute",
|
|
114
|
+
month: "Monat",
|
|
115
|
+
week: "Woche",
|
|
116
|
+
day: "Tag",
|
|
117
|
+
year: "Jahr",
|
|
118
|
+
agenda: "Agenda",
|
|
119
|
+
allDay: "Ganzt\xE4gig",
|
|
120
|
+
noEvents: "Keine Termine",
|
|
121
|
+
moreEvents: (count) => `+${count} weitere`,
|
|
122
|
+
eventCount: (count) => count === 1 ? "1 Termin" : `${count} Termine`,
|
|
123
|
+
weekLabel: "KW",
|
|
124
|
+
prevMonth: "Vorheriger Monat",
|
|
125
|
+
nextMonth: "N\xE4chster Monat",
|
|
126
|
+
prevYear: "Vorheriges Jahr",
|
|
127
|
+
nextYear: "N\xE4chstes Jahr",
|
|
128
|
+
prevWeek: "Vorherige Woche",
|
|
129
|
+
nextWeek: "N\xE4chste Woche",
|
|
130
|
+
prevDay: "Vorheriger Tag",
|
|
131
|
+
nextDay: "N\xE4chster Tag",
|
|
132
|
+
timeline: "Zeitachse",
|
|
133
|
+
customRange: "Benutzerdefiniert",
|
|
134
|
+
save: "Speichern",
|
|
135
|
+
cancel: "Abbrechen",
|
|
136
|
+
delete: "L\xF6schen",
|
|
137
|
+
close: "Schlie\xDFen",
|
|
138
|
+
confirm: "Best\xE4tigen",
|
|
139
|
+
newEvent: "Neuer Termin",
|
|
140
|
+
editEvent: "Termin bearbeiten",
|
|
141
|
+
deleteEvent: "Termin l\xF6schen",
|
|
142
|
+
deleteConfirmation: "M\xF6chten Sie diesen Termin wirklich l\xF6schen?",
|
|
143
|
+
title: "Titel",
|
|
144
|
+
from: "Von",
|
|
145
|
+
to: "Bis",
|
|
146
|
+
location: "Ort",
|
|
147
|
+
description: "Beschreibung",
|
|
148
|
+
allDayEvent: "Ganzt\xE4giger Termin",
|
|
149
|
+
resources: "Ressourcen",
|
|
150
|
+
repeat: "Wiederholen",
|
|
151
|
+
repeatEvery: "Wiederholen alle",
|
|
152
|
+
never: "Nie",
|
|
153
|
+
daily: "T\xE4glich",
|
|
154
|
+
weekly: "W\xF6chentlich",
|
|
155
|
+
monthly: "Monatlich",
|
|
156
|
+
yearly: "J\xE4hrlich",
|
|
157
|
+
endBy: "Endet am",
|
|
158
|
+
endAfter: "Endet nach",
|
|
159
|
+
noEndDate: "Kein Enddatum",
|
|
160
|
+
occurrences: "Wiederholungen"
|
|
161
|
+
}
|
|
162
|
+
},
|
|
163
|
+
fr: {
|
|
164
|
+
code: "fr",
|
|
165
|
+
text: {
|
|
166
|
+
today: "Aujourd'hui",
|
|
167
|
+
month: "Mois",
|
|
168
|
+
week: "Semaine",
|
|
169
|
+
day: "Jour",
|
|
170
|
+
year: "Ann\xE9e",
|
|
171
|
+
agenda: "Agenda",
|
|
172
|
+
allDay: "Toute la journ\xE9e",
|
|
173
|
+
noEvents: "Aucun \xE9v\xE9nement",
|
|
174
|
+
moreEvents: (count) => `+${count} autre${count > 1 ? "s" : ""}`,
|
|
175
|
+
eventCount: (count) => count === 1 ? "1 \xE9v\xE9nement" : `${count} \xE9v\xE9nements`,
|
|
176
|
+
weekLabel: "Sem.",
|
|
177
|
+
prevMonth: "Mois pr\xE9c\xE9dent",
|
|
178
|
+
nextMonth: "Mois suivant",
|
|
179
|
+
prevYear: "Ann\xE9e pr\xE9c\xE9dente",
|
|
180
|
+
nextYear: "Ann\xE9e suivante",
|
|
181
|
+
prevWeek: "Semaine pr\xE9c\xE9dente",
|
|
182
|
+
nextWeek: "Semaine suivante",
|
|
183
|
+
prevDay: "Jour pr\xE9c\xE9dent",
|
|
184
|
+
nextDay: "Jour suivant",
|
|
185
|
+
timeline: "Chronologie",
|
|
186
|
+
customRange: "Plage personnalis\xE9e",
|
|
187
|
+
save: "Enregistrer",
|
|
188
|
+
cancel: "Annuler",
|
|
189
|
+
delete: "Supprimer",
|
|
190
|
+
close: "Fermer",
|
|
191
|
+
confirm: "Confirmer",
|
|
192
|
+
newEvent: "Nouvel \xE9v\xE9nement",
|
|
193
|
+
editEvent: "Modifier l'\xE9v\xE9nement",
|
|
194
|
+
deleteEvent: "Supprimer l'\xE9v\xE9nement",
|
|
195
|
+
deleteConfirmation: "Voulez-vous vraiment supprimer cet \xE9v\xE9nement ?",
|
|
196
|
+
title: "Titre",
|
|
197
|
+
from: "De",
|
|
198
|
+
to: "\xC0",
|
|
199
|
+
location: "Lieu",
|
|
200
|
+
description: "Description",
|
|
201
|
+
allDayEvent: "\xC9v\xE9nement sur toute la journ\xE9e",
|
|
202
|
+
resources: "Ressources",
|
|
203
|
+
repeat: "R\xE9p\xE9ter",
|
|
204
|
+
repeatEvery: "R\xE9p\xE9ter tous les",
|
|
205
|
+
never: "Jamais",
|
|
206
|
+
daily: "Quotidien",
|
|
207
|
+
weekly: "Hebdomadaire",
|
|
208
|
+
monthly: "Mensuel",
|
|
209
|
+
yearly: "Annuel",
|
|
210
|
+
endBy: "Fin le",
|
|
211
|
+
endAfter: "Fin apr\xE8s",
|
|
212
|
+
noEndDate: "Pas de date de fin",
|
|
213
|
+
occurrences: "occurrences"
|
|
214
|
+
}
|
|
215
|
+
},
|
|
216
|
+
es: {
|
|
217
|
+
code: "es",
|
|
218
|
+
text: {
|
|
219
|
+
today: "Hoy",
|
|
220
|
+
month: "Mes",
|
|
221
|
+
week: "Semana",
|
|
222
|
+
day: "D\xEDa",
|
|
223
|
+
year: "A\xF1o",
|
|
224
|
+
agenda: "Agenda",
|
|
225
|
+
allDay: "Todo el d\xEDa",
|
|
226
|
+
noEvents: "Sin eventos",
|
|
227
|
+
moreEvents: (count) => `+${count} m\xE1s`,
|
|
228
|
+
eventCount: (count) => count === 1 ? "1 evento" : `${count} eventos`,
|
|
229
|
+
weekLabel: "Sem.",
|
|
230
|
+
prevMonth: "Mes anterior",
|
|
231
|
+
nextMonth: "Mes siguiente",
|
|
232
|
+
prevYear: "A\xF1o anterior",
|
|
233
|
+
nextYear: "A\xF1o siguiente",
|
|
234
|
+
prevWeek: "Semana anterior",
|
|
235
|
+
nextWeek: "Semana siguiente",
|
|
236
|
+
prevDay: "D\xEDa anterior",
|
|
237
|
+
nextDay: "D\xEDa siguiente",
|
|
238
|
+
timeline: "L\xEDnea de tiempo",
|
|
239
|
+
customRange: "Rango personalizado",
|
|
240
|
+
save: "Guardar",
|
|
241
|
+
cancel: "Cancelar",
|
|
242
|
+
delete: "Eliminar",
|
|
243
|
+
close: "Cerrar",
|
|
244
|
+
confirm: "Confirmar",
|
|
245
|
+
newEvent: "Nuevo evento",
|
|
246
|
+
editEvent: "Editar evento",
|
|
247
|
+
deleteEvent: "Eliminar evento",
|
|
248
|
+
deleteConfirmation: "\xBFEst\xE1 seguro de que desea eliminar este evento?",
|
|
249
|
+
title: "T\xEDtulo",
|
|
250
|
+
from: "Desde",
|
|
251
|
+
to: "Hasta",
|
|
252
|
+
location: "Ubicaci\xF3n",
|
|
253
|
+
description: "Descripci\xF3n",
|
|
254
|
+
allDayEvent: "Evento de todo el d\xEDa",
|
|
255
|
+
resources: "Recursos",
|
|
256
|
+
repeat: "Repetir",
|
|
257
|
+
repeatEvery: "Repetir cada",
|
|
258
|
+
never: "Nunca",
|
|
259
|
+
daily: "Diario",
|
|
260
|
+
weekly: "Semanal",
|
|
261
|
+
monthly: "Mensual",
|
|
262
|
+
yearly: "Anual",
|
|
263
|
+
endBy: "Finalizar el",
|
|
264
|
+
endAfter: "Finalizar despu\xE9s de",
|
|
265
|
+
noEndDate: "Sin fecha de fin",
|
|
266
|
+
occurrences: "repeticiones"
|
|
267
|
+
}
|
|
268
|
+
},
|
|
269
|
+
it: {
|
|
270
|
+
code: "it",
|
|
271
|
+
text: {
|
|
272
|
+
today: "Oggi",
|
|
273
|
+
month: "Mese",
|
|
274
|
+
week: "Settimana",
|
|
275
|
+
day: "Giorno",
|
|
276
|
+
year: "Anno",
|
|
277
|
+
agenda: "Agenda",
|
|
278
|
+
allDay: "Tutto il giorno",
|
|
279
|
+
noEvents: "Nessun evento",
|
|
280
|
+
moreEvents: (count) => `+${count} altr${count > 1 ? "i" : "o"}`,
|
|
281
|
+
eventCount: (count) => count === 1 ? "1 evento" : `${count} eventi`,
|
|
282
|
+
weekLabel: "Sett.",
|
|
283
|
+
prevMonth: "Mese precedente",
|
|
284
|
+
nextMonth: "Mese successivo",
|
|
285
|
+
prevYear: "Anno precedente",
|
|
286
|
+
nextYear: "Anno successivo",
|
|
287
|
+
prevWeek: "Settimana precedente",
|
|
288
|
+
nextWeek: "Settimana successiva",
|
|
289
|
+
prevDay: "Giorno precedente",
|
|
290
|
+
nextDay: "Giorno successivo",
|
|
291
|
+
timeline: "Cronologia",
|
|
292
|
+
customRange: "Intervallo personalizzato",
|
|
293
|
+
save: "Salva",
|
|
294
|
+
cancel: "Annulla",
|
|
295
|
+
delete: "Elimina",
|
|
296
|
+
close: "Chiudi",
|
|
297
|
+
confirm: "Conferma",
|
|
298
|
+
newEvent: "Nuovo evento",
|
|
299
|
+
editEvent: "Modifica evento",
|
|
300
|
+
deleteEvent: "Elimina evento",
|
|
301
|
+
deleteConfirmation: "Sei sicuro di voler eliminare questo evento?",
|
|
302
|
+
title: "Titolo",
|
|
303
|
+
from: "Da",
|
|
304
|
+
to: "A",
|
|
305
|
+
location: "Luogo",
|
|
306
|
+
description: "Descrizione",
|
|
307
|
+
allDayEvent: "Evento giornata intera",
|
|
308
|
+
resources: "Risorse",
|
|
309
|
+
repeat: "Ripeti",
|
|
310
|
+
repeatEvery: "Ripeti ogni",
|
|
311
|
+
never: "Mai",
|
|
312
|
+
daily: "Giornaliero",
|
|
313
|
+
weekly: "Settimanale",
|
|
314
|
+
monthly: "Mensile",
|
|
315
|
+
yearly: "Annuale",
|
|
316
|
+
endBy: "Termina il",
|
|
317
|
+
endAfter: "Termina dopo",
|
|
318
|
+
noEndDate: "Nessuna data di fine",
|
|
319
|
+
occurrences: "ripetizioni"
|
|
320
|
+
}
|
|
321
|
+
},
|
|
322
|
+
pt: {
|
|
323
|
+
code: "pt",
|
|
324
|
+
text: {
|
|
325
|
+
today: "Hoje",
|
|
326
|
+
month: "M\xEAs",
|
|
327
|
+
week: "Semana",
|
|
328
|
+
day: "Dia",
|
|
329
|
+
year: "Ano",
|
|
330
|
+
agenda: "Agenda",
|
|
331
|
+
allDay: "Dia inteiro",
|
|
332
|
+
noEvents: "Sem eventos",
|
|
333
|
+
moreEvents: (count) => `+${count} mais`,
|
|
334
|
+
eventCount: (count) => count === 1 ? "1 evento" : `${count} eventos`,
|
|
335
|
+
weekLabel: "Sem.",
|
|
336
|
+
prevMonth: "M\xEAs anterior",
|
|
337
|
+
nextMonth: "Pr\xF3ximo m\xEAs",
|
|
338
|
+
prevYear: "Ano anterior",
|
|
339
|
+
nextYear: "Pr\xF3ximo ano",
|
|
340
|
+
prevWeek: "Semana anterior",
|
|
341
|
+
nextWeek: "Pr\xF3xima semana",
|
|
342
|
+
prevDay: "Dia anterior",
|
|
343
|
+
nextDay: "Pr\xF3ximo dia",
|
|
344
|
+
timeline: "Linha do tempo",
|
|
345
|
+
customRange: "Intervalo personalizado",
|
|
346
|
+
save: "Salvar",
|
|
347
|
+
cancel: "Cancelar",
|
|
348
|
+
delete: "Excluir",
|
|
349
|
+
close: "Fechar",
|
|
350
|
+
confirm: "Confirmar",
|
|
351
|
+
newEvent: "Novo evento",
|
|
352
|
+
editEvent: "Editar evento",
|
|
353
|
+
deleteEvent: "Excluir evento",
|
|
354
|
+
deleteConfirmation: "Tem certeza de que deseja excluir este evento?",
|
|
355
|
+
title: "T\xEDtulo",
|
|
356
|
+
from: "De",
|
|
357
|
+
to: "At\xE9",
|
|
358
|
+
location: "Local",
|
|
359
|
+
description: "Descri\xE7\xE3o",
|
|
360
|
+
allDayEvent: "Evento de dia inteiro",
|
|
361
|
+
resources: "Recursos",
|
|
362
|
+
repeat: "Repetir",
|
|
363
|
+
repeatEvery: "Repetir a cada",
|
|
364
|
+
never: "Nunca",
|
|
365
|
+
daily: "Di\xE1rio",
|
|
366
|
+
weekly: "Semanal",
|
|
367
|
+
monthly: "Mensal",
|
|
368
|
+
yearly: "Anual",
|
|
369
|
+
endBy: "Terminar em",
|
|
370
|
+
endAfter: "Terminar ap\xF3s",
|
|
371
|
+
noEndDate: "Sem data de t\xE9rmino",
|
|
372
|
+
occurrences: "repeti\xE7\xF5es"
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
nl: {
|
|
376
|
+
code: "nl",
|
|
377
|
+
text: {
|
|
378
|
+
today: "Vandaag",
|
|
379
|
+
month: "Maand",
|
|
380
|
+
week: "Week",
|
|
381
|
+
day: "Dag",
|
|
382
|
+
year: "Jaar",
|
|
383
|
+
agenda: "Agenda",
|
|
384
|
+
allDay: "Hele dag",
|
|
385
|
+
noEvents: "Geen evenementen",
|
|
386
|
+
moreEvents: (count) => `+${count} meer`,
|
|
387
|
+
eventCount: (count) => count === 1 ? "1 afspraak" : `${count} afspraken`,
|
|
388
|
+
weekLabel: "Wk",
|
|
389
|
+
prevMonth: "Vorige maand",
|
|
390
|
+
nextMonth: "Volgende maand",
|
|
391
|
+
prevYear: "Vorig jaar",
|
|
392
|
+
nextYear: "Volgend jaar",
|
|
393
|
+
prevWeek: "Vorige week",
|
|
394
|
+
nextWeek: "Volgende week",
|
|
395
|
+
prevDay: "Vorige dag",
|
|
396
|
+
nextDay: "Volgende dag",
|
|
397
|
+
timeline: "Tijdlijn",
|
|
398
|
+
customRange: "Aangepast bereik",
|
|
399
|
+
save: "Opslaan",
|
|
400
|
+
cancel: "Annuleren",
|
|
401
|
+
delete: "Verwijderen",
|
|
402
|
+
close: "Sluiten",
|
|
403
|
+
confirm: "Bevestigen",
|
|
404
|
+
newEvent: "Nieuw evenement",
|
|
405
|
+
editEvent: "Evenement bewerken",
|
|
406
|
+
deleteEvent: "Evenement verwijderen",
|
|
407
|
+
deleteConfirmation: "Weet u zeker dat u dit evenement wilt verwijderen?",
|
|
408
|
+
title: "Titel",
|
|
409
|
+
from: "Van",
|
|
410
|
+
to: "Tot",
|
|
411
|
+
location: "Locatie",
|
|
412
|
+
description: "Beschrijving",
|
|
413
|
+
allDayEvent: "Evenement hele dag",
|
|
414
|
+
resources: "Bronnen",
|
|
415
|
+
repeat: "Herhalen",
|
|
416
|
+
repeatEvery: "Herhaal elke",
|
|
417
|
+
never: "Nooit",
|
|
418
|
+
daily: "Dagelijks",
|
|
419
|
+
weekly: "Wekelijks",
|
|
420
|
+
monthly: "Maandelijks",
|
|
421
|
+
yearly: "Jaarlijks",
|
|
422
|
+
endBy: "Eindigt op",
|
|
423
|
+
endAfter: "Eindigt na",
|
|
424
|
+
noEndDate: "Geen einddatum",
|
|
425
|
+
occurrences: "herhalingen"
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
pl: {
|
|
429
|
+
code: "pl",
|
|
430
|
+
text: {
|
|
431
|
+
today: "Dzi\u015B",
|
|
432
|
+
month: "Miesi\u0105c",
|
|
433
|
+
week: "Tydzie\u0144",
|
|
434
|
+
day: "Dzie\u0144",
|
|
435
|
+
year: "Rok",
|
|
436
|
+
agenda: "Agenda",
|
|
437
|
+
allDay: "Ca\u0142y dzie\u0144",
|
|
438
|
+
noEvents: "Brak wydarze\u0144",
|
|
439
|
+
moreEvents: (count) => `+${count} wi\u0119cej`,
|
|
440
|
+
eventCount: (count) => {
|
|
441
|
+
if (count === 1) return "1 wydarzenie";
|
|
442
|
+
const lastDigit = count % 10;
|
|
443
|
+
const lastTwo = count % 100;
|
|
444
|
+
if (lastDigit >= 2 && lastDigit <= 4 && (lastTwo < 12 || lastTwo > 14)) return `${count} wydarzenia`;
|
|
445
|
+
return `${count} wydarze\u0144`;
|
|
446
|
+
},
|
|
447
|
+
weekLabel: "Tydz.",
|
|
448
|
+
prevMonth: "Poprzedni miesi\u0105c",
|
|
449
|
+
nextMonth: "Nast\u0119pny miesi\u0105c",
|
|
450
|
+
prevYear: "Poprzedni rok",
|
|
451
|
+
nextYear: "Nast\u0119pny rok",
|
|
452
|
+
prevWeek: "Poprzedni tydzie\u0144",
|
|
453
|
+
nextWeek: "Nast\u0119pny tydzie\u0144",
|
|
454
|
+
prevDay: "Poprzedni dzie\u0144",
|
|
455
|
+
nextDay: "Nast\u0119pny dzie\u0144",
|
|
456
|
+
timeline: "O\u015B czasu",
|
|
457
|
+
customRange: "Zakres niestandardowy",
|
|
458
|
+
save: "Zapisz",
|
|
459
|
+
cancel: "Anuluj",
|
|
460
|
+
delete: "Usu\u0144",
|
|
461
|
+
close: "Zamknij",
|
|
462
|
+
confirm: "Potwierd\u017A",
|
|
463
|
+
newEvent: "Nowe wydarzenie",
|
|
464
|
+
editEvent: "Edytuj wydarzenie",
|
|
465
|
+
deleteEvent: "Usu\u0144 wydarzenie",
|
|
466
|
+
deleteConfirmation: "Czy na pewno chcesz usun\u0105\u0107 to wydarzenie?",
|
|
467
|
+
title: "Tytu\u0142",
|
|
468
|
+
from: "Od",
|
|
469
|
+
to: "Do",
|
|
470
|
+
location: "Lokalizacja",
|
|
471
|
+
description: "Opis",
|
|
472
|
+
allDayEvent: "Wydarzenie ca\u0142odniowe",
|
|
473
|
+
resources: "Zasoby",
|
|
474
|
+
repeat: "Powt\xF3rz",
|
|
475
|
+
repeatEvery: "Powtarzaj co",
|
|
476
|
+
never: "Nigdy",
|
|
477
|
+
daily: "Codziennie",
|
|
478
|
+
weekly: "Co tydzie\u0144",
|
|
479
|
+
monthly: "Co miesi\u0105c",
|
|
480
|
+
yearly: "Co rok",
|
|
481
|
+
endBy: "Zako\u0144cz dnia",
|
|
482
|
+
endAfter: "Zako\u0144cz po",
|
|
483
|
+
noEndDate: "Bez daty ko\u0144cowej",
|
|
484
|
+
occurrences: "powt\xF3rze\u0144"
|
|
485
|
+
}
|
|
486
|
+
},
|
|
487
|
+
ru: {
|
|
488
|
+
code: "ru",
|
|
489
|
+
text: {
|
|
490
|
+
today: "\u0421\u0435\u0433\u043E\u0434\u043D\u044F",
|
|
491
|
+
month: "\u041C\u0435\u0441\u044F\u0446",
|
|
492
|
+
week: "\u041D\u0435\u0434\u0435\u043B\u044F",
|
|
493
|
+
day: "\u0414\u0435\u043D\u044C",
|
|
494
|
+
year: "\u0413\u043E\u0434",
|
|
495
|
+
agenda: "\u041F\u043E\u0432\u0435\u0441\u0442\u043A\u0430",
|
|
496
|
+
allDay: "\u0412\u0435\u0441\u044C \u0434\u0435\u043D\u044C",
|
|
497
|
+
noEvents: "\u041D\u0435\u0442 \u0441\u043E\u0431\u044B\u0442\u0438\u0439",
|
|
498
|
+
moreEvents: (count) => `+${count} \u0435\u0449\u0451`,
|
|
499
|
+
eventCount: (count) => {
|
|
500
|
+
const lastDigit = count % 10;
|
|
501
|
+
const lastTwo = count % 100;
|
|
502
|
+
if (lastTwo >= 11 && lastTwo <= 19) return `${count} \u0441\u043E\u0431\u044B\u0442\u0438\u0439`;
|
|
503
|
+
if (lastDigit === 1) return `${count} \u0441\u043E\u0431\u044B\u0442\u0438\u0435`;
|
|
504
|
+
if (lastDigit >= 2 && lastDigit <= 4) return `${count} \u0441\u043E\u0431\u044B\u0442\u0438\u044F`;
|
|
505
|
+
return `${count} \u0441\u043E\u0431\u044B\u0442\u0438\u0439`;
|
|
506
|
+
},
|
|
507
|
+
weekLabel: "\u041D\u0435\u0434.",
|
|
508
|
+
prevMonth: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u043C\u0435\u0441\u044F\u0446",
|
|
509
|
+
nextMonth: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u043C\u0435\u0441\u044F\u0446",
|
|
510
|
+
prevYear: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u0433\u043E\u0434",
|
|
511
|
+
nextYear: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0433\u043E\u0434",
|
|
512
|
+
prevWeek: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0430\u044F \u043D\u0435\u0434\u0435\u043B\u044F",
|
|
513
|
+
nextWeek: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0430\u044F \u043D\u0435\u0434\u0435\u043B\u044F",
|
|
514
|
+
prevDay: "\u041F\u0440\u0435\u0434\u044B\u0434\u0443\u0449\u0438\u0439 \u0434\u0435\u043D\u044C",
|
|
515
|
+
nextDay: "\u0421\u043B\u0435\u0434\u0443\u044E\u0449\u0438\u0439 \u0434\u0435\u043D\u044C",
|
|
516
|
+
timeline: "\u0425\u0440\u043E\u043D\u043E\u043B\u043E\u0433\u0438\u044F",
|
|
517
|
+
customRange: "\u041F\u0440\u043E\u0438\u0437\u0432\u043E\u043B\u044C\u043D\u044B\u0439 \u0434\u0438\u0430\u043F\u0430\u0437\u043E\u043D",
|
|
518
|
+
save: "\u0421\u043E\u0445\u0440\u0430\u043D\u0438\u0442\u044C",
|
|
519
|
+
cancel: "\u041E\u0442\u043C\u0435\u043D\u0430",
|
|
520
|
+
delete: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C",
|
|
521
|
+
close: "\u0417\u0430\u043A\u0440\u044B\u0442\u044C",
|
|
522
|
+
confirm: "\u041F\u043E\u0434\u0442\u0432\u0435\u0440\u0434\u0438\u0442\u044C",
|
|
523
|
+
newEvent: "\u041D\u043E\u0432\u043E\u0435 \u0441\u043E\u0431\u044B\u0442\u0438\u0435",
|
|
524
|
+
editEvent: "\u0420\u0435\u0434\u0430\u043A\u0442\u0438\u0440\u043E\u0432\u0430\u0442\u044C \u0441\u043E\u0431\u044B\u0442\u0438\u0435",
|
|
525
|
+
deleteEvent: "\u0423\u0434\u0430\u043B\u0438\u0442\u044C \u0441\u043E\u0431\u044B\u0442\u0438\u0435",
|
|
526
|
+
deleteConfirmation: "\u0412\u044B \u0443\u0432\u0435\u0440\u0435\u043D\u044B, \u0447\u0442\u043E \u0445\u043E\u0442\u0438\u0442\u0435 \u0443\u0434\u0430\u043B\u0438\u0442\u044C \u044D\u0442\u043E \u0441\u043E\u0431\u044B\u0442\u0438\u0435?",
|
|
527
|
+
title: "\u041D\u0430\u0437\u0432\u0430\u043D\u0438\u0435",
|
|
528
|
+
from: "\u0421",
|
|
529
|
+
to: "\u041F\u043E",
|
|
530
|
+
location: "\u041C\u0435\u0441\u0442\u043E",
|
|
531
|
+
description: "\u041E\u043F\u0438\u0441\u0430\u043D\u0438\u0435",
|
|
532
|
+
allDayEvent: "\u0421\u043E\u0431\u044B\u0442\u0438\u0435 \u043D\u0430 \u0432\u0435\u0441\u044C \u0434\u0435\u043D\u044C",
|
|
533
|
+
resources: "\u0420\u0435\u0441\u0443\u0440\u0441\u044B",
|
|
534
|
+
repeat: "\u041F\u043E\u0432\u0442\u043E\u0440\u044F\u0442\u044C",
|
|
535
|
+
repeatEvery: "\u041F\u043E\u0432\u0442\u043E\u0440\u044F\u0442\u044C \u043A\u0430\u0436\u0434\u044B\u0435",
|
|
536
|
+
never: "\u041D\u0438\u043A\u043E\u0433\u0434\u0430",
|
|
537
|
+
daily: "\u0415\u0436\u0435\u0434\u043D\u0435\u0432\u043D\u043E",
|
|
538
|
+
weekly: "\u0415\u0436\u0435\u043D\u0435\u0434\u0435\u043B\u044C\u043D\u043E",
|
|
539
|
+
monthly: "\u0415\u0436\u0435\u043C\u0435\u0441\u044F\u0447\u043D\u043E",
|
|
540
|
+
yearly: "\u0415\u0436\u0435\u0433\u043E\u0434\u043D\u043E",
|
|
541
|
+
endBy: "\u041E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u0435",
|
|
542
|
+
endAfter: "\u041E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u0435 \u043F\u043E\u0441\u043B\u0435",
|
|
543
|
+
noEndDate: "\u0411\u0435\u0437 \u0434\u0430\u0442\u044B \u043E\u043A\u043E\u043D\u0447\u0430\u043D\u0438\u044F",
|
|
544
|
+
occurrences: "\u043F\u043E\u0432\u0442\u043E\u0440\u0435\u043D\u0438\u0439"
|
|
545
|
+
}
|
|
546
|
+
},
|
|
547
|
+
ja: {
|
|
548
|
+
code: "ja",
|
|
549
|
+
text: {
|
|
550
|
+
today: "\u4ECA\u65E5",
|
|
551
|
+
month: "\u6708",
|
|
552
|
+
week: "\u9031",
|
|
553
|
+
day: "\u65E5",
|
|
554
|
+
year: "\u5E74",
|
|
555
|
+
agenda: "\u4E88\u5B9A\u8868",
|
|
556
|
+
allDay: "\u7D42\u65E5",
|
|
557
|
+
noEvents: "\u4E88\u5B9A\u306A\u3057",
|
|
558
|
+
moreEvents: (count) => `\u4ED6${count}\u4EF6`,
|
|
559
|
+
eventCount: (count) => `${count}\u4EF6\u306E\u4E88\u5B9A`,
|
|
560
|
+
weekLabel: "\u9031",
|
|
561
|
+
prevMonth: "\u524D\u6708",
|
|
562
|
+
nextMonth: "\u7FCC\u6708",
|
|
563
|
+
prevYear: "\u524D\u5E74",
|
|
564
|
+
nextYear: "\u7FCC\u5E74",
|
|
565
|
+
prevWeek: "\u524D\u9031",
|
|
566
|
+
nextWeek: "\u7FCC\u9031",
|
|
567
|
+
prevDay: "\u524D\u65E5",
|
|
568
|
+
nextDay: "\u7FCC\u65E5",
|
|
569
|
+
timeline: "\u30BF\u30A4\u30E0\u30E9\u30A4\u30F3",
|
|
570
|
+
customRange: "\u30AB\u30B9\u30BF\u30E0\u7BC4\u56F2",
|
|
571
|
+
save: "\u4FDD\u5B58",
|
|
572
|
+
cancel: "\u30AD\u30E3\u30F3\u30BB\u30EB",
|
|
573
|
+
delete: "\u524A\u9664",
|
|
574
|
+
close: "\u9589\u3058\u308B",
|
|
575
|
+
confirm: "\u78BA\u8A8D",
|
|
576
|
+
newEvent: "\u65B0\u3057\u3044\u4E88\u5B9A",
|
|
577
|
+
editEvent: "\u4E88\u5B9A\u3092\u7DE8\u96C6",
|
|
578
|
+
deleteEvent: "\u4E88\u5B9A\u3092\u524A\u9664",
|
|
579
|
+
deleteConfirmation: "\u3053\u306E\u4E88\u5B9A\u3092\u524A\u9664\u3057\u3066\u3082\u3088\u308D\u3057\u3044\u3067\u3059\u304B\uFF1F",
|
|
580
|
+
title: "\u30BF\u30A4\u30C8\u30EB",
|
|
581
|
+
from: "\u958B\u59CB",
|
|
582
|
+
to: "\u7D42\u4E86",
|
|
583
|
+
location: "\u5834\u6240",
|
|
584
|
+
description: "\u8AAC\u660E",
|
|
585
|
+
allDayEvent: "\u7D42\u65E5\u306E\u4E88\u5B9A",
|
|
586
|
+
resources: "\u30EA\u30BD\u30FC\u30B9",
|
|
587
|
+
repeat: "\u7E70\u308A\u8FD4\u3057",
|
|
588
|
+
repeatEvery: "\u7E70\u308A\u8FD4\u3057\u9593\u9694",
|
|
589
|
+
never: "\u306A\u3057",
|
|
590
|
+
daily: "\u6BCE\u65E5",
|
|
591
|
+
weekly: "\u6BCE\u9031",
|
|
592
|
+
monthly: "\u6BCE\u6708",
|
|
593
|
+
yearly: "\u6BCE\u5E74",
|
|
594
|
+
endBy: "\u7D42\u4E86\u65E5",
|
|
595
|
+
endAfter: "\u56DE\u6570\u6307\u5B9A",
|
|
596
|
+
noEndDate: "\u7D42\u4E86\u65E5\u306A\u3057",
|
|
597
|
+
occurrences: "\u56DE"
|
|
598
|
+
}
|
|
599
|
+
},
|
|
600
|
+
zh: {
|
|
601
|
+
code: "zh",
|
|
602
|
+
text: {
|
|
603
|
+
today: "\u4ECA\u5929",
|
|
604
|
+
month: "\u6708",
|
|
605
|
+
week: "\u5468",
|
|
606
|
+
day: "\u65E5",
|
|
607
|
+
year: "\u5E74",
|
|
608
|
+
agenda: "\u65E5\u7A0B",
|
|
609
|
+
allDay: "\u5168\u5929",
|
|
610
|
+
noEvents: "\u65E0\u4E8B\u4EF6",
|
|
611
|
+
moreEvents: (count) => `\u8FD8\u6709${count}\u9879`,
|
|
612
|
+
eventCount: (count) => `${count}\u4E2A\u4E8B\u4EF6`,
|
|
613
|
+
weekLabel: "\u5468",
|
|
614
|
+
prevMonth: "\u4E0A\u4E2A\u6708",
|
|
615
|
+
nextMonth: "\u4E0B\u4E2A\u6708",
|
|
616
|
+
prevYear: "\u4E0A\u4E00\u5E74",
|
|
617
|
+
nextYear: "\u4E0B\u4E00\u5E74",
|
|
618
|
+
prevWeek: "\u4E0A\u5468",
|
|
619
|
+
nextWeek: "\u4E0B\u5468",
|
|
620
|
+
prevDay: "\u524D\u4E00\u5929",
|
|
621
|
+
nextDay: "\u540E\u4E00\u5929",
|
|
622
|
+
timeline: "\u65F6\u95F4\u7EBF",
|
|
623
|
+
customRange: "\u81EA\u5B9A\u4E49\u8303\u56F4",
|
|
624
|
+
save: "\u4FDD\u5B58",
|
|
625
|
+
cancel: "\u53D6\u6D88",
|
|
626
|
+
delete: "\u5220\u9664",
|
|
627
|
+
close: "\u5173\u95ED",
|
|
628
|
+
confirm: "\u786E\u8BA4",
|
|
629
|
+
newEvent: "\u65B0\u5EFA\u4E8B\u4EF6",
|
|
630
|
+
editEvent: "\u7F16\u8F91\u4E8B\u4EF6",
|
|
631
|
+
deleteEvent: "\u5220\u9664\u4E8B\u4EF6",
|
|
632
|
+
deleteConfirmation: "\u786E\u5B9A\u8981\u5220\u9664\u6B64\u4E8B\u4EF6\u5417\uFF1F",
|
|
633
|
+
title: "\u6807\u9898",
|
|
634
|
+
from: "\u4ECE",
|
|
635
|
+
to: "\u81F3",
|
|
636
|
+
location: "\u5730\u70B9",
|
|
637
|
+
description: "\u63CF\u8FF0",
|
|
638
|
+
allDayEvent: "\u5168\u5929\u4E8B\u4EF6",
|
|
639
|
+
resources: "\u8D44\u6E90",
|
|
640
|
+
repeat: "\u91CD\u590D",
|
|
641
|
+
repeatEvery: "\u91CD\u590D\u9891\u7387",
|
|
642
|
+
never: "\u4ECE\u4E0D",
|
|
643
|
+
daily: "\u6BCF\u5929",
|
|
644
|
+
weekly: "\u6BCF\u5468",
|
|
645
|
+
monthly: "\u6BCF\u6708",
|
|
646
|
+
yearly: "\u6BCF\u5E74",
|
|
647
|
+
endBy: "\u7ED3\u675F\u4E8E",
|
|
648
|
+
endAfter: "\u7ED3\u675F\u6B21\u6570",
|
|
649
|
+
noEndDate: "\u65E0\u7ED3\u675F\u65E5\u671F",
|
|
650
|
+
occurrences: "\u6B21"
|
|
651
|
+
}
|
|
652
|
+
},
|
|
653
|
+
"zh-CN": {
|
|
654
|
+
code: "zh-CN"
|
|
655
|
+
},
|
|
656
|
+
"zh-TW": {
|
|
657
|
+
code: "zh-TW",
|
|
658
|
+
text: {
|
|
659
|
+
today: "\u4ECA\u5929",
|
|
660
|
+
month: "\u6708",
|
|
661
|
+
week: "\u9031",
|
|
662
|
+
day: "\u65E5",
|
|
663
|
+
year: "\u5E74",
|
|
664
|
+
agenda: "\u884C\u4E8B\u66C6",
|
|
665
|
+
allDay: "\u5168\u5929",
|
|
666
|
+
noEvents: "\u7121\u4E8B\u4EF6",
|
|
667
|
+
moreEvents: (count) => `\u9084\u6709${count}\u9805`,
|
|
668
|
+
eventCount: (count) => `${count}\u500B\u4E8B\u4EF6`,
|
|
669
|
+
weekLabel: "\u9031",
|
|
670
|
+
prevMonth: "\u4E0A\u500B\u6708",
|
|
671
|
+
nextMonth: "\u4E0B\u500B\u6708",
|
|
672
|
+
prevYear: "\u4E0A\u4E00\u5E74",
|
|
673
|
+
nextYear: "\u4E0B\u4E00\u5E74",
|
|
674
|
+
prevWeek: "\u4E0A\u9031",
|
|
675
|
+
nextWeek: "\u4E0B\u9031",
|
|
676
|
+
prevDay: "\u524D\u4E00\u5929",
|
|
677
|
+
nextDay: "\u5F8C\u4E00\u5929",
|
|
678
|
+
timeline: "\u6642\u9593\u7DDA",
|
|
679
|
+
customRange: "\u81EA\u8A02\u7BC4\u570D",
|
|
680
|
+
save: "\u5132\u5B58",
|
|
681
|
+
cancel: "\u53D6\u6D88",
|
|
682
|
+
delete: "\u522A\u9664",
|
|
683
|
+
close: "\u95DC\u9589",
|
|
684
|
+
confirm: "\u78BA\u8A8D",
|
|
685
|
+
newEvent: "\u65B0\u589E\u4E8B\u4EF6",
|
|
686
|
+
editEvent: "\u7DE8\u8F2F\u4E8B\u4EF6",
|
|
687
|
+
deleteEvent: "\u522A\u9664\u4E8B\u4EF6",
|
|
688
|
+
deleteConfirmation: "\u78BA\u5B9A\u8981\u522A\u9664\u6B64\u4E8B\u4EF6\u55CE\uFF1F",
|
|
689
|
+
title: "\u6A19\u984C",
|
|
690
|
+
from: "\u5F9E",
|
|
691
|
+
to: "\u81F3",
|
|
692
|
+
location: "\u5730\u9EDE",
|
|
693
|
+
description: "\u63CF\u8FF0",
|
|
694
|
+
allDayEvent: "\u5168\u5929\u4E8B\u4EF6",
|
|
695
|
+
resources: "\u8CC7\u6E90",
|
|
696
|
+
repeat: "\u91CD\u8907",
|
|
697
|
+
repeatEvery: "\u91CD\u8907\u983B\u7387",
|
|
698
|
+
never: "\u5F9E\u4E0D",
|
|
699
|
+
daily: "\u6BCF\u5929",
|
|
700
|
+
weekly: "\u6BCF\u9031",
|
|
701
|
+
monthly: "\u6BCF\u6708",
|
|
702
|
+
yearly: "\u6BCF\u5E74",
|
|
703
|
+
endBy: "\u7D50\u675F\u65BC",
|
|
704
|
+
endAfter: "\u7D50\u675F\u6B21\u6578",
|
|
705
|
+
noEndDate: "\u7121\u7D50\u675F\u65E5\u671F",
|
|
706
|
+
occurrences: "\u6B21"
|
|
707
|
+
}
|
|
708
|
+
},
|
|
709
|
+
ko: {
|
|
710
|
+
code: "ko",
|
|
711
|
+
text: {
|
|
712
|
+
today: "\uC624\uB298",
|
|
713
|
+
month: "\uC6D4",
|
|
714
|
+
week: "\uC8FC",
|
|
715
|
+
day: "\uC77C",
|
|
716
|
+
year: "\uB144",
|
|
717
|
+
agenda: "\uC77C\uC815",
|
|
718
|
+
allDay: "\uC885\uC77C",
|
|
719
|
+
noEvents: "\uC77C\uC815 \uC5C6\uC74C",
|
|
720
|
+
moreEvents: (count) => `+${count}\uAC1C \uB354`,
|
|
721
|
+
eventCount: (count) => `${count}\uAC1C \uC77C\uC815`,
|
|
722
|
+
weekLabel: "\uC8FC",
|
|
723
|
+
prevMonth: "\uC774\uC804 \uB2EC",
|
|
724
|
+
nextMonth: "\uB2E4\uC74C \uB2EC",
|
|
725
|
+
prevYear: "\uC774\uC804 \uB144\uB3C4",
|
|
726
|
+
nextYear: "\uB2E4\uC74C \uB144\uB3C4",
|
|
727
|
+
prevWeek: "\uC774\uC804 \uC8FC",
|
|
728
|
+
nextWeek: "\uB2E4\uC74C \uC8FC",
|
|
729
|
+
prevDay: "\uC774\uC804 \uB0A0",
|
|
730
|
+
nextDay: "\uB2E4\uC74C \uB0A0",
|
|
731
|
+
timeline: "\uD0C0\uC784\uB77C\uC778",
|
|
732
|
+
customRange: "\uC0AC\uC6A9\uC790 \uC9C0\uC815 \uBC94\uC704",
|
|
733
|
+
save: "\uC800\uC7A5",
|
|
734
|
+
cancel: "\uCDE8\uC18C",
|
|
735
|
+
delete: "\uC0AD\uC81C",
|
|
736
|
+
close: "\uB2EB\uAE30",
|
|
737
|
+
confirm: "\uD655\uC778",
|
|
738
|
+
newEvent: "\uC0C8 \uC77C\uC815",
|
|
739
|
+
editEvent: "\uC77C\uC815 \uC218\uC815",
|
|
740
|
+
deleteEvent: "\uC77C\uC815 \uC0AD\uC81C",
|
|
741
|
+
deleteConfirmation: "\uC774 \uC77C\uC815\uC744 \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?",
|
|
742
|
+
title: "\uC81C\uBAA9",
|
|
743
|
+
from: "\uC2DC\uC791",
|
|
744
|
+
to: "\uC885\uB8CC",
|
|
745
|
+
location: "\uC7A5\uC18C",
|
|
746
|
+
description: "\uC124\uBA85",
|
|
747
|
+
allDayEvent: "\uC885\uC77C \uC77C\uC815",
|
|
748
|
+
resources: "\uB9AC\uC18C\uC2A4",
|
|
749
|
+
repeat: "\uBC18\uBCF5",
|
|
750
|
+
repeatEvery: "\uBC18\uBCF5 \uC8FC\uAE30",
|
|
751
|
+
never: "\uC548 \uD568",
|
|
752
|
+
daily: "\uB9E4\uC77C",
|
|
753
|
+
weekly: "\uB9E4\uC8FC",
|
|
754
|
+
monthly: "\uB9E4\uC6D4",
|
|
755
|
+
yearly: "\uB9E4\uB144",
|
|
756
|
+
endBy: "\uC885\uB8CC\uC77C",
|
|
757
|
+
endAfter: "\uD69F\uC218 \uD6C4 \uC885\uB8CC",
|
|
758
|
+
noEndDate: "\uC885\uB8CC\uC77C \uC5C6\uC74C",
|
|
759
|
+
occurrences: "\uD68C"
|
|
760
|
+
}
|
|
761
|
+
},
|
|
762
|
+
ar: {
|
|
763
|
+
code: "ar",
|
|
764
|
+
text: {
|
|
765
|
+
today: "\u0627\u0644\u064A\u0648\u0645",
|
|
766
|
+
month: "\u0634\u0647\u0631",
|
|
767
|
+
week: "\u0623\u0633\u0628\u0648\u0639",
|
|
768
|
+
day: "\u064A\u0648\u0645",
|
|
769
|
+
year: "\u0633\u0646\u0629",
|
|
770
|
+
agenda: "\u062C\u062F\u0648\u0644 \u0627\u0644\u0623\u0639\u0645\u0627\u0644",
|
|
771
|
+
allDay: "\u0637\u0648\u0627\u0644 \u0627\u0644\u064A\u0648\u0645",
|
|
772
|
+
noEvents: "\u0644\u0627 \u062A\u0648\u062C\u062F \u0623\u062D\u062F\u0627\u062B",
|
|
773
|
+
moreEvents: (count) => `+${count} \u0627\u0644\u0645\u0632\u064A\u062F`,
|
|
774
|
+
eventCount: (count) => {
|
|
775
|
+
if (count === 1) return "\u062D\u062F\u062B \u0648\u0627\u062D\u062F";
|
|
776
|
+
if (count === 2) return "\u062D\u062F\u062B\u0627\u0646";
|
|
777
|
+
if (count >= 3 && count <= 10) return `${count} \u0623\u062D\u062F\u0627\u062B`;
|
|
778
|
+
return `${count} \u062D\u062F\u062B\u064B\u0627`;
|
|
779
|
+
},
|
|
780
|
+
weekLabel: "\u0623",
|
|
781
|
+
prevMonth: "\u0627\u0644\u0634\u0647\u0631 \u0627\u0644\u0633\u0627\u0628\u0642",
|
|
782
|
+
nextMonth: "\u0627\u0644\u0634\u0647\u0631 \u0627\u0644\u062A\u0627\u0644\u064A",
|
|
783
|
+
prevYear: "\u0627\u0644\u0633\u0646\u0629 \u0627\u0644\u0633\u0627\u0628\u0642\u0629",
|
|
784
|
+
nextYear: "\u0627\u0644\u0633\u0646\u0629 \u0627\u0644\u062A\u0627\u0644\u064A\u0629",
|
|
785
|
+
prevWeek: "\u0627\u0644\u0623\u0633\u0628\u0648\u0639 \u0627\u0644\u0633\u0627\u0628\u0642",
|
|
786
|
+
nextWeek: "\u0627\u0644\u0623\u0633\u0628\u0648\u0639 \u0627\u0644\u062A\u0627\u0644\u064A",
|
|
787
|
+
prevDay: "\u0627\u0644\u064A\u0648\u0645 \u0627\u0644\u0633\u0627\u0628\u0642",
|
|
788
|
+
nextDay: "\u0627\u0644\u064A\u0648\u0645 \u0627\u0644\u062A\u0627\u0644\u064A",
|
|
789
|
+
timeline: "\u0627\u0644\u062C\u062F\u0648\u0644 \u0627\u0644\u0632\u0645\u0646\u064A",
|
|
790
|
+
customRange: "\u0646\u0637\u0627\u0642 \u0645\u062E\u0635\u0635",
|
|
791
|
+
save: "\u062D\u0641\u0638",
|
|
792
|
+
cancel: "\u0625\u0644\u063A\u0627\u0621",
|
|
793
|
+
delete: "\u062D\u0630\u0641",
|
|
794
|
+
close: "\u0625\u063A\u0644\u0627\u0642",
|
|
795
|
+
confirm: "\u062A\u0623\u0643\u064A\u062F",
|
|
796
|
+
newEvent: "\u062D\u062F\u062B \u062C\u062F\u064A\u062F",
|
|
797
|
+
editEvent: "\u062A\u0639\u062F\u064A\u0644 \u0627\u0644\u062D\u062F\u062B",
|
|
798
|
+
deleteEvent: "\u062D\u0630\u0641 \u0627\u0644\u062D\u062F\u062B",
|
|
799
|
+
deleteConfirmation: "\u0647\u0644 \u0623\u0646\u062A \u0645\u062A\u0623\u0643\u062F \u0645\u0646 \u062D\u0630\u0641 \u0647\u0630\u0627 \u0627\u0644\u062D\u062F\u062B\u061F",
|
|
800
|
+
title: "\u0627\u0644\u0639\u0646\u0648\u0627\u0646",
|
|
801
|
+
from: "\u0645\u0646",
|
|
802
|
+
to: "\u0625\u0644\u0649",
|
|
803
|
+
location: "\u0627\u0644\u0645\u0648\u0642\u0639",
|
|
804
|
+
description: "\u0627\u0644\u0648\u0635\u0641",
|
|
805
|
+
allDayEvent: "\u062D\u062F\u062B \u0637\u0648\u0627\u0644 \u0627\u0644\u064A\u0648\u0645",
|
|
806
|
+
resources: "\u0627\u0644\u0645\u0648\u0627\u0631\u062F",
|
|
807
|
+
repeat: "\u062A\u0643\u0631\u0627\u0631",
|
|
808
|
+
repeatEvery: "\u062A\u0643\u0631\u0627\u0631 \u0643\u0644",
|
|
809
|
+
never: "\u0623\u0628\u062F\u0627\u064B",
|
|
810
|
+
daily: "\u064A\u0648\u0645\u064A\u0627\u064B",
|
|
811
|
+
weekly: "\u0623\u0633\u0628\u0648\u0639\u064A\u0627\u064B",
|
|
812
|
+
monthly: "\u0634\u0647\u0631\u064A\u0627\u064B",
|
|
813
|
+
yearly: "\u0633\u0646\u0648\u064A\u0627\u064B",
|
|
814
|
+
endBy: "\u064A\u0646\u062A\u0647\u064A \u0641\u064A",
|
|
815
|
+
endAfter: "\u064A\u0646\u062A\u0647\u064A \u0628\u0639\u062F",
|
|
816
|
+
noEndDate: "\u0628\u062F\u0648\u0646 \u062A\u0627\u0631\u064A\u062E \u0627\u0646\u062A\u0647\u0627\u0621",
|
|
817
|
+
occurrences: "\u0645\u0631\u0627\u062A"
|
|
818
|
+
}
|
|
819
|
+
},
|
|
820
|
+
he: {
|
|
821
|
+
code: "he",
|
|
822
|
+
text: {
|
|
823
|
+
today: "\u05D4\u05D9\u05D5\u05DD",
|
|
824
|
+
month: "\u05D7\u05D5\u05D3\u05E9",
|
|
825
|
+
week: "\u05E9\u05D1\u05D5\u05E2",
|
|
826
|
+
day: "\u05D9\u05D5\u05DD",
|
|
827
|
+
year: "\u05E9\u05E0\u05D4",
|
|
828
|
+
agenda: "\u05E1\u05D3\u05E8 \u05D9\u05D5\u05DD",
|
|
829
|
+
allDay: "\u05DB\u05DC \u05D4\u05D9\u05D5\u05DD",
|
|
830
|
+
noEvents: "\u05D0\u05D9\u05DF \u05D0\u05D9\u05E8\u05D5\u05E2\u05D9\u05DD",
|
|
831
|
+
moreEvents: (count) => `+${count} \u05E0\u05D5\u05E1\u05E4\u05D9\u05DD`,
|
|
832
|
+
eventCount: (count) => count === 1 ? "\u05D0\u05D9\u05E8\u05D5\u05E2 \u05D0\u05D7\u05D3" : `${count} \u05D0\u05D9\u05E8\u05D5\u05E2\u05D9\u05DD`,
|
|
833
|
+
weekLabel: "\u05E9\u05F3",
|
|
834
|
+
prevMonth: "\u05D4\u05D7\u05D5\u05D3\u05E9 \u05D4\u05E7\u05D5\u05D3\u05DD",
|
|
835
|
+
nextMonth: "\u05D4\u05D7\u05D5\u05D3\u05E9 \u05D4\u05D1\u05D0",
|
|
836
|
+
prevYear: "\u05D4\u05E9\u05E0\u05D4 \u05D4\u05E7\u05D5\u05D3\u05DE\u05EA",
|
|
837
|
+
nextYear: "\u05D4\u05E9\u05E0\u05D4 \u05D4\u05D1\u05D0\u05D4",
|
|
838
|
+
prevWeek: "\u05D4\u05E9\u05D1\u05D5\u05E2 \u05D4\u05E7\u05D5\u05D3\u05DD",
|
|
839
|
+
nextWeek: "\u05D4\u05E9\u05D1\u05D5\u05E2 \u05D4\u05D1\u05D0",
|
|
840
|
+
prevDay: "\u05D4\u05D9\u05D5\u05DD \u05D4\u05E7\u05D5\u05D3\u05DD",
|
|
841
|
+
nextDay: "\u05D4\u05D9\u05D5\u05DD \u05D4\u05D1\u05D0",
|
|
842
|
+
timeline: "\u05E6\u05D9\u05E8 \u05D6\u05DE\u05DF",
|
|
843
|
+
customRange: "\u05D8\u05D5\u05D5\u05D7 \u05DE\u05D5\u05EA\u05D0\u05DD",
|
|
844
|
+
save: "\u05E9\u05DE\u05D5\u05E8",
|
|
845
|
+
cancel: "\u05D1\u05D9\u05D8\u05D5\u05DC",
|
|
846
|
+
delete: "\u05DE\u05D7\u05E7",
|
|
847
|
+
close: "\u05E1\u05D2\u05D5\u05E8",
|
|
848
|
+
confirm: "\u05D0\u05D9\u05E9\u05D5\u05E8",
|
|
849
|
+
newEvent: "\u05D0\u05D9\u05E8\u05D5\u05E2 \u05D7\u05D3\u05E9",
|
|
850
|
+
editEvent: "\u05E2\u05E8\u05D5\u05DA \u05D0\u05D9\u05E8\u05D5\u05E2",
|
|
851
|
+
deleteEvent: "\u05DE\u05D7\u05E7 \u05D0\u05D9\u05E8\u05D5\u05E2",
|
|
852
|
+
deleteConfirmation: "\u05D4\u05D0\u05DD \u05D0\u05EA\u05D4 \u05D1\u05D8\u05D5\u05D7 \u05E9\u05D1\u05E8\u05E6\u05D5\u05E0\u05DA \u05DC\u05DE\u05D7\u05D5\u05E7 \u05D0\u05D9\u05E8\u05D5\u05E2 \u05D6\u05D4?",
|
|
853
|
+
title: "\u05DB\u05D5\u05EA\u05E8\u05EA",
|
|
854
|
+
from: "\u05DE",
|
|
855
|
+
to: "\u05E2\u05D3",
|
|
856
|
+
location: "\u05DE\u05D9\u05E7\u05D5\u05DD",
|
|
857
|
+
description: "\u05EA\u05D9\u05D0\u05D5\u05E8",
|
|
858
|
+
allDayEvent: "\u05D0\u05D9\u05E8\u05D5\u05E2 \u05D9\u05D5\u05DD \u05E9\u05DC\u05DD",
|
|
859
|
+
resources: "\u05DE\u05E9\u05D0\u05D1\u05D9\u05DD",
|
|
860
|
+
repeat: "\u05D7\u05D6\u05D5\u05E8",
|
|
861
|
+
repeatEvery: "\u05D7\u05D6\u05D5\u05E8 \u05DB\u05DC",
|
|
862
|
+
never: "\u05D0\u05E3 \u05E4\u05E2\u05DD",
|
|
863
|
+
daily: "\u05D9\u05D5\u05DE\u05D9",
|
|
864
|
+
weekly: "\u05E9\u05D1\u05D5\u05E2\u05D9",
|
|
865
|
+
monthly: "\u05D7\u05D5\u05D3\u05E9\u05D9",
|
|
866
|
+
yearly: "\u05E9\u05E0\u05EA\u05D9",
|
|
867
|
+
endBy: "\u05DE\u05E1\u05EA\u05D9\u05D9\u05DD \u05D1",
|
|
868
|
+
endAfter: "\u05DE\u05E1\u05EA\u05D9\u05D9\u05DD \u05D0\u05D7\u05E8\u05D9",
|
|
869
|
+
noEndDate: "\u05DC\u05DC\u05D0 \u05EA\u05D0\u05E8\u05D9\u05DA \u05E1\u05D9\u05D5\u05DD",
|
|
870
|
+
occurrences: "\u05E4\u05E2\u05DE\u05D9\u05DD"
|
|
871
|
+
}
|
|
872
|
+
},
|
|
873
|
+
tr: {
|
|
874
|
+
code: "tr",
|
|
875
|
+
text: {
|
|
876
|
+
today: "Bug\xFCn",
|
|
877
|
+
month: "Ay",
|
|
878
|
+
week: "Hafta",
|
|
879
|
+
day: "G\xFCn",
|
|
880
|
+
year: "Y\u0131l",
|
|
881
|
+
agenda: "Ajanda",
|
|
882
|
+
allDay: "T\xFCm g\xFCn",
|
|
883
|
+
noEvents: "Etkinlik yok",
|
|
884
|
+
moreEvents: (count) => `+${count} daha`,
|
|
885
|
+
eventCount: (count) => `${count} etkinlik`,
|
|
886
|
+
weekLabel: "Hf",
|
|
887
|
+
prevMonth: "\xD6nceki ay",
|
|
888
|
+
nextMonth: "Sonraki ay",
|
|
889
|
+
prevYear: "\xD6nceki y\u0131l",
|
|
890
|
+
nextYear: "Sonraki y\u0131l",
|
|
891
|
+
prevWeek: "\xD6nceki hafta",
|
|
892
|
+
nextWeek: "Sonraki hafta",
|
|
893
|
+
prevDay: "\xD6nceki g\xFCn",
|
|
894
|
+
nextDay: "Sonraki g\xFCn",
|
|
895
|
+
timeline: "Zaman \xE7izelgesi",
|
|
896
|
+
customRange: "\xD6zel aral\u0131k",
|
|
897
|
+
save: "Kaydet",
|
|
898
|
+
cancel: "\u0130ptal",
|
|
899
|
+
delete: "Sil",
|
|
900
|
+
close: "Kapat",
|
|
901
|
+
confirm: "Onayla",
|
|
902
|
+
newEvent: "Yeni etkinlik",
|
|
903
|
+
editEvent: "Etkinli\u011Fi d\xFCzenle",
|
|
904
|
+
deleteEvent: "Etkinli\u011Fi sil",
|
|
905
|
+
deleteConfirmation: "Bu etkinli\u011Fi silmek istedi\u011Finizden emin misiniz?",
|
|
906
|
+
title: "Ba\u015Fl\u0131k",
|
|
907
|
+
from: "Ba\u015Flang\u0131\xE7",
|
|
908
|
+
to: "Biti\u015F",
|
|
909
|
+
location: "Konum",
|
|
910
|
+
description: "A\xE7\u0131klama",
|
|
911
|
+
allDayEvent: "T\xFCm g\xFCn etkinli\u011Fi",
|
|
912
|
+
resources: "Kaynaklar",
|
|
913
|
+
repeat: "Tekrarla",
|
|
914
|
+
repeatEvery: "Tekrar s\u0131kl\u0131\u011F\u0131",
|
|
915
|
+
never: "Asla",
|
|
916
|
+
daily: "G\xFCnl\xFCk",
|
|
917
|
+
weekly: "Haftal\u0131k",
|
|
918
|
+
monthly: "Ayl\u0131k",
|
|
919
|
+
yearly: "Y\u0131ll\u0131k",
|
|
920
|
+
endBy: "Biti\u015F tarihi",
|
|
921
|
+
endAfter: "Sonra bitir",
|
|
922
|
+
noEndDate: "Biti\u015F tarihi yok",
|
|
923
|
+
occurrences: "tekrar"
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
};
|
|
927
|
+
function getBaseLocale(locale) {
|
|
928
|
+
return locale.split("-")[0];
|
|
929
|
+
}
|
|
930
|
+
function getLocaleLookup(locale) {
|
|
931
|
+
const baseLocale = getBaseLocale(locale);
|
|
932
|
+
return locale === baseLocale ? [locale] : [locale, baseLocale];
|
|
933
|
+
}
|
|
934
|
+
function getIntlLocaleInfo(locale) {
|
|
935
|
+
const LocaleConstructor = Intl.Locale;
|
|
936
|
+
if (!LocaleConstructor) return void 0;
|
|
937
|
+
try {
|
|
938
|
+
return new LocaleConstructor(locale);
|
|
939
|
+
} catch {
|
|
940
|
+
return void 0;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
function normalizeFirstDayOfWeek(value) {
|
|
944
|
+
if (value === void 0) return void 0;
|
|
945
|
+
if (value === 7) return 0;
|
|
946
|
+
if (value >= 0 && value <= 6) return value;
|
|
947
|
+
return void 0;
|
|
948
|
+
}
|
|
949
|
+
function getIntlFirstDayOfWeek(locale) {
|
|
950
|
+
return normalizeFirstDayOfWeek(getIntlLocaleInfo(locale)?.weekInfo?.firstDay);
|
|
951
|
+
}
|
|
952
|
+
function getFallbackFirstDayOfWeek(locale) {
|
|
953
|
+
for (const candidate of getLocaleLookup(locale)) {
|
|
954
|
+
const firstDayOfWeek = fallbackFirstDayOfWeekByLocale[candidate];
|
|
955
|
+
if (firstDayOfWeek !== void 0) return firstDayOfWeek;
|
|
956
|
+
}
|
|
957
|
+
return void 0;
|
|
958
|
+
}
|
|
959
|
+
function getIntlRtl(locale) {
|
|
960
|
+
const direction = getIntlLocaleInfo(locale)?.textInfo?.direction;
|
|
961
|
+
return direction ? direction === "rtl" : void 0;
|
|
962
|
+
}
|
|
963
|
+
function getFallbackRtl(locale) {
|
|
964
|
+
for (const candidate of getLocaleLookup(locale)) {
|
|
965
|
+
if (fallbackRtlLocales.has(candidate)) return true;
|
|
966
|
+
}
|
|
967
|
+
return void 0;
|
|
968
|
+
}
|
|
969
|
+
function getLocaleConfig(locale) {
|
|
970
|
+
const baseLocale = getBaseLocale(locale);
|
|
971
|
+
const config = locales[locale] || locales[baseLocale] || locales["en"];
|
|
972
|
+
const baseConfig = locales[baseLocale] || locales["en"];
|
|
973
|
+
return {
|
|
974
|
+
code: config.code || locale,
|
|
975
|
+
text: { ...defaultText, ...config.text || baseConfig.text || {} },
|
|
976
|
+
rtl: config.rtl ?? baseConfig.rtl ?? getIntlRtl(locale) ?? getFallbackRtl(locale) ?? false,
|
|
977
|
+
firstDayOfWeek: config.firstDayOfWeek ?? baseConfig.firstDayOfWeek ?? getIntlFirstDayOfWeek(locale) ?? getFallbackFirstDayOfWeek(locale) ?? 0
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
function getSchedulerText(locale) {
|
|
981
|
+
return getLocaleConfig(locale).text;
|
|
982
|
+
}
|
|
983
|
+
function resolveSchedulerText(locale, overrides) {
|
|
984
|
+
return {
|
|
985
|
+
...getSchedulerText(locale),
|
|
986
|
+
...overrides ?? {}
|
|
987
|
+
};
|
|
988
|
+
}
|
|
989
|
+
function isRTL(locale) {
|
|
990
|
+
return getLocaleConfig(locale).rtl;
|
|
991
|
+
}
|
|
992
|
+
function getDefaultFirstDayOfWeek(locale) {
|
|
993
|
+
return getLocaleConfig(locale).firstDayOfWeek;
|
|
994
|
+
}
|
|
995
|
+
function registerLocale(code, config) {
|
|
996
|
+
locales[code] = {
|
|
997
|
+
...locales[code],
|
|
998
|
+
...config,
|
|
999
|
+
code
|
|
1000
|
+
};
|
|
1001
|
+
}
|
|
1002
|
+
function getAvailableLocales() {
|
|
1003
|
+
return Object.keys(locales);
|
|
1004
|
+
}
|
|
1005
|
+
var defaultSchedulerText = defaultText;
|
|
1006
|
+
|
|
1007
|
+
// src/utils/export.ts
|
|
1008
|
+
function toDate(d) {
|
|
1009
|
+
return d instanceof Date ? d : new Date(d);
|
|
1010
|
+
}
|
|
1011
|
+
function formatDateToICS(date, allDay) {
|
|
1012
|
+
if (allDay) {
|
|
1013
|
+
const year2 = date.getFullYear();
|
|
1014
|
+
const month2 = String(date.getMonth() + 1).padStart(2, "0");
|
|
1015
|
+
const day2 = String(date.getDate()).padStart(2, "0");
|
|
1016
|
+
return `${year2}${month2}${day2}`;
|
|
1017
|
+
}
|
|
1018
|
+
const year = date.getUTCFullYear();
|
|
1019
|
+
const month = String(date.getUTCMonth() + 1).padStart(2, "0");
|
|
1020
|
+
const day = String(date.getUTCDate()).padStart(2, "0");
|
|
1021
|
+
const hours = String(date.getUTCHours()).padStart(2, "0");
|
|
1022
|
+
const minutes = String(date.getUTCMinutes()).padStart(2, "0");
|
|
1023
|
+
const seconds = String(date.getUTCSeconds()).padStart(2, "0");
|
|
1024
|
+
return `${year}${month}${day}T${hours}${minutes}${seconds}Z`;
|
|
1025
|
+
}
|
|
1026
|
+
function formatDateInTzForICS(date, timezone) {
|
|
1027
|
+
const parts = getDatePartsInTimezone(date, timezone);
|
|
1028
|
+
const year = parts.year;
|
|
1029
|
+
const month = String(parts.month + 1).padStart(2, "0");
|
|
1030
|
+
const day = String(parts.day).padStart(2, "0");
|
|
1031
|
+
const hours = String(parts.hour).padStart(2, "0");
|
|
1032
|
+
const minutes = String(parts.minute).padStart(2, "0");
|
|
1033
|
+
const seconds = String(parts.second).padStart(2, "0");
|
|
1034
|
+
return `${year}${month}${day}T${hours}${minutes}${seconds}`;
|
|
1035
|
+
}
|
|
1036
|
+
function formatOffsetForICS(offsetMinutes) {
|
|
1037
|
+
const sign = offsetMinutes <= 0 ? "+" : "-";
|
|
1038
|
+
const absMinutes = Math.abs(offsetMinutes);
|
|
1039
|
+
const hours = String(Math.floor(absMinutes / 60)).padStart(2, "0");
|
|
1040
|
+
const minutes = String(absMinutes % 60).padStart(2, "0");
|
|
1041
|
+
return `${sign}${hours}${minutes}`;
|
|
1042
|
+
}
|
|
1043
|
+
function generateVTimezone(timezone) {
|
|
1044
|
+
if (timezone === "UTC") {
|
|
1045
|
+
return ["BEGIN:VTIMEZONE", "TZID:UTC", "BEGIN:STANDARD", "DTSTART:19700101T000000", "TZOFFSETFROM:+0000", "TZOFFSETTO:+0000", "END:STANDARD", "END:VTIMEZONE"];
|
|
1046
|
+
}
|
|
1047
|
+
const lines = [];
|
|
1048
|
+
lines.push("BEGIN:VTIMEZONE");
|
|
1049
|
+
lines.push(`TZID:${timezone}`);
|
|
1050
|
+
const jan = new Date((/* @__PURE__ */ new Date()).getFullYear(), 0, 15);
|
|
1051
|
+
const jul = new Date((/* @__PURE__ */ new Date()).getFullYear(), 6, 15);
|
|
1052
|
+
const janOffset = getTimezoneOffset(jan, timezone);
|
|
1053
|
+
const julOffset = getTimezoneOffset(jul, timezone);
|
|
1054
|
+
if (janOffset === julOffset) {
|
|
1055
|
+
lines.push("BEGIN:STANDARD");
|
|
1056
|
+
lines.push("DTSTART:19700101T000000");
|
|
1057
|
+
lines.push(`TZOFFSETFROM:${formatOffsetForICS(janOffset)}`);
|
|
1058
|
+
lines.push(`TZOFFSETTO:${formatOffsetForICS(janOffset)}`);
|
|
1059
|
+
lines.push("END:STANDARD");
|
|
1060
|
+
} else {
|
|
1061
|
+
const stdOffset = Math.max(janOffset, julOffset);
|
|
1062
|
+
const dstOffset = Math.min(janOffset, julOffset);
|
|
1063
|
+
const dstInJul = julOffset < janOffset;
|
|
1064
|
+
lines.push("BEGIN:STANDARD");
|
|
1065
|
+
lines.push(`DTSTART:${dstInJul ? "19701101T020000" : "19700301T020000"}`);
|
|
1066
|
+
lines.push(`TZOFFSETFROM:${formatOffsetForICS(dstOffset)}`);
|
|
1067
|
+
lines.push(`TZOFFSETTO:${formatOffsetForICS(stdOffset)}`);
|
|
1068
|
+
lines.push("END:STANDARD");
|
|
1069
|
+
lines.push("BEGIN:DAYLIGHT");
|
|
1070
|
+
lines.push(`DTSTART:${dstInJul ? "19700301T020000" : "19701101T020000"}`);
|
|
1071
|
+
lines.push(`TZOFFSETFROM:${formatOffsetForICS(stdOffset)}`);
|
|
1072
|
+
lines.push(`TZOFFSETTO:${formatOffsetForICS(dstOffset)}`);
|
|
1073
|
+
lines.push("END:DAYLIGHT");
|
|
1074
|
+
}
|
|
1075
|
+
lines.push("END:VTIMEZONE");
|
|
1076
|
+
return lines;
|
|
1077
|
+
}
|
|
1078
|
+
function escapeICSText(text) {
|
|
1079
|
+
return text.replace(/\\/g, "\\\\").replace(/;/g, "\\;").replace(/,/g, "\\,").replace(/\n/g, "\\n");
|
|
1080
|
+
}
|
|
1081
|
+
function foldICSLine(line) {
|
|
1082
|
+
const maxLength = 75;
|
|
1083
|
+
if (line.length <= maxLength) return line;
|
|
1084
|
+
const lines = [];
|
|
1085
|
+
let remaining = line;
|
|
1086
|
+
while (remaining.length > maxLength) {
|
|
1087
|
+
lines.push(remaining.slice(0, maxLength));
|
|
1088
|
+
remaining = " " + remaining.slice(maxLength);
|
|
1089
|
+
}
|
|
1090
|
+
if (remaining) lines.push(remaining);
|
|
1091
|
+
return lines.join("\r\n");
|
|
1092
|
+
}
|
|
1093
|
+
function generateUID(event) {
|
|
1094
|
+
const explicitUid = event.metadata?.uid;
|
|
1095
|
+
if (typeof explicitUid === "string" && explicitUid.trim().length > 0) {
|
|
1096
|
+
return explicitUid.trim();
|
|
1097
|
+
}
|
|
1098
|
+
if (event.id !== null && event.id !== void 0) {
|
|
1099
|
+
return `${String(event.id)}@primeui-scheduler`;
|
|
1100
|
+
}
|
|
1101
|
+
return `event-${Date.now()}@primeui-scheduler`;
|
|
1102
|
+
}
|
|
1103
|
+
function rruleToICS(rrule) {
|
|
1104
|
+
if (typeof rrule === "string") {
|
|
1105
|
+
return rrule.replace(/^RRULE:/i, "").trim();
|
|
1106
|
+
}
|
|
1107
|
+
return serializeRRule(rrule);
|
|
1108
|
+
}
|
|
1109
|
+
function isStartOfDay(date) {
|
|
1110
|
+
return date.getHours() === 0 && date.getMinutes() === 0 && date.getSeconds() === 0 && date.getMilliseconds() === 0;
|
|
1111
|
+
}
|
|
1112
|
+
function getAllDayExclusiveEndDate(start, end, durationMinutes) {
|
|
1113
|
+
const startDay = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
1114
|
+
if (end) {
|
|
1115
|
+
const endDate = toDate(end);
|
|
1116
|
+
const endDay = new Date(endDate.getFullYear(), endDate.getMonth(), endDate.getDate());
|
|
1117
|
+
if (isStartOfDay(endDate) && endDate.getTime() > startDay.getTime()) {
|
|
1118
|
+
return endDay;
|
|
1119
|
+
}
|
|
1120
|
+
const exclusive2 = new Date(endDay);
|
|
1121
|
+
exclusive2.setDate(exclusive2.getDate() + 1);
|
|
1122
|
+
return exclusive2;
|
|
1123
|
+
}
|
|
1124
|
+
if (durationMinutes && durationMinutes > 0) {
|
|
1125
|
+
const days = Math.max(1, Math.ceil(durationMinutes / (24 * 60)));
|
|
1126
|
+
const exclusive2 = new Date(startDay);
|
|
1127
|
+
exclusive2.setDate(exclusive2.getDate() + days);
|
|
1128
|
+
return exclusive2;
|
|
1129
|
+
}
|
|
1130
|
+
const exclusive = new Date(startDay);
|
|
1131
|
+
exclusive.setDate(exclusive.getDate() + 1);
|
|
1132
|
+
return exclusive;
|
|
1133
|
+
}
|
|
1134
|
+
function getRecurrenceId(event) {
|
|
1135
|
+
if (event.recurrenceId) {
|
|
1136
|
+
return event.recurrenceId;
|
|
1137
|
+
}
|
|
1138
|
+
const recurrenceId = event.metadata?.recurrenceId;
|
|
1139
|
+
if (recurrenceId instanceof Date || typeof recurrenceId === "string") {
|
|
1140
|
+
return recurrenceId;
|
|
1141
|
+
}
|
|
1142
|
+
return void 0;
|
|
1143
|
+
}
|
|
1144
|
+
function toDateSafe(value) {
|
|
1145
|
+
if (!value) return null;
|
|
1146
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
1147
|
+
return isNaN(date.getTime()) ? null : date;
|
|
1148
|
+
}
|
|
1149
|
+
function getSeriesUidForException(event) {
|
|
1150
|
+
const recurringEventId = event.metadata?.recurringEventId;
|
|
1151
|
+
if (recurringEventId !== void 0 && recurringEventId !== null) {
|
|
1152
|
+
return `${String(recurringEventId)}@primeui-scheduler`;
|
|
1153
|
+
}
|
|
1154
|
+
return null;
|
|
1155
|
+
}
|
|
1156
|
+
function dedupeDates(values) {
|
|
1157
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1158
|
+
const result = [];
|
|
1159
|
+
for (const value of values) {
|
|
1160
|
+
const date = toDateSafe(value);
|
|
1161
|
+
const key = date ? date.toISOString() : String(value);
|
|
1162
|
+
if (seen.has(key)) {
|
|
1163
|
+
continue;
|
|
1164
|
+
}
|
|
1165
|
+
seen.add(key);
|
|
1166
|
+
result.push(value);
|
|
1167
|
+
}
|
|
1168
|
+
return result;
|
|
1169
|
+
}
|
|
1170
|
+
function buildExportEventEntries(events) {
|
|
1171
|
+
const entries = [];
|
|
1172
|
+
for (const event of events) {
|
|
1173
|
+
const eventRecurrenceId = getRecurrenceId(event);
|
|
1174
|
+
const uid = eventRecurrenceId ? getSeriesUidForException(event) ?? generateUID(event) : generateUID(event);
|
|
1175
|
+
entries.push({
|
|
1176
|
+
event,
|
|
1177
|
+
uid,
|
|
1178
|
+
recurrenceId: eventRecurrenceId
|
|
1179
|
+
});
|
|
1180
|
+
const seriesExceptions = event.exceptions;
|
|
1181
|
+
if (!seriesExceptions || seriesExceptions.length === 0) {
|
|
1182
|
+
continue;
|
|
1183
|
+
}
|
|
1184
|
+
for (const exception of seriesExceptions) {
|
|
1185
|
+
const recurrenceId = exception.recurrenceId ?? exception.originalStart;
|
|
1186
|
+
const mergedExceptionEvent = {
|
|
1187
|
+
...event,
|
|
1188
|
+
...exception.event,
|
|
1189
|
+
id: `${String(event.id)}-exception-${String(recurrenceId)}`,
|
|
1190
|
+
rrule: void 0,
|
|
1191
|
+
exdate: void 0,
|
|
1192
|
+
rdate: void 0,
|
|
1193
|
+
recurrenceId
|
|
1194
|
+
};
|
|
1195
|
+
entries.push({
|
|
1196
|
+
event: mergedExceptionEvent,
|
|
1197
|
+
uid,
|
|
1198
|
+
recurrenceId
|
|
1199
|
+
});
|
|
1200
|
+
}
|
|
1201
|
+
}
|
|
1202
|
+
return entries;
|
|
1203
|
+
}
|
|
1204
|
+
function getExpansionRange(events, dateRange) {
|
|
1205
|
+
if (dateRange) {
|
|
1206
|
+
return {
|
|
1207
|
+
start: toDate(dateRange.start),
|
|
1208
|
+
end: toDate(dateRange.end)
|
|
1209
|
+
};
|
|
1210
|
+
}
|
|
1211
|
+
if (events.length === 0) {
|
|
1212
|
+
const now = /* @__PURE__ */ new Date();
|
|
1213
|
+
const end = new Date(now);
|
|
1214
|
+
end.setFullYear(end.getFullYear() + 1);
|
|
1215
|
+
return { start: now, end };
|
|
1216
|
+
}
|
|
1217
|
+
let minStart = toDate(events[0].start);
|
|
1218
|
+
let maxEnd = events[0].end ? toDate(events[0].end) : toDate(events[0].start);
|
|
1219
|
+
for (const event of events) {
|
|
1220
|
+
const eventStart = toDate(event.start);
|
|
1221
|
+
const eventEnd = event.end ? toDate(event.end) : eventStart;
|
|
1222
|
+
if (eventStart.getTime() < minStart.getTime()) {
|
|
1223
|
+
minStart = eventStart;
|
|
1224
|
+
}
|
|
1225
|
+
if (eventEnd.getTime() > maxEnd.getTime()) {
|
|
1226
|
+
maxEnd = eventEnd;
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
const oneYearFromStart = new Date(minStart);
|
|
1230
|
+
oneYearFromStart.setFullYear(oneYearFromStart.getFullYear() + 1);
|
|
1231
|
+
return {
|
|
1232
|
+
start: minStart,
|
|
1233
|
+
end: maxEnd.getTime() > oneYearFromStart.getTime() ? maxEnd : oneYearFromStart
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1236
|
+
function expandRecurringEventsForExport(events, options) {
|
|
1237
|
+
if (!options.expandRecurring) {
|
|
1238
|
+
return events;
|
|
1239
|
+
}
|
|
1240
|
+
const { start, end } = getExpansionRange(events, options.dateRange);
|
|
1241
|
+
const expanded = [];
|
|
1242
|
+
for (const event of events) {
|
|
1243
|
+
if (!event.rrule) {
|
|
1244
|
+
expanded.push(event);
|
|
1245
|
+
continue;
|
|
1246
|
+
}
|
|
1247
|
+
const occurrences = expandRRule(event, start, end);
|
|
1248
|
+
for (const occurrence of occurrences) {
|
|
1249
|
+
expanded.push({
|
|
1250
|
+
...event,
|
|
1251
|
+
id: occurrence.id,
|
|
1252
|
+
title: occurrence.title,
|
|
1253
|
+
start: occurrence.start,
|
|
1254
|
+
end: occurrence.end,
|
|
1255
|
+
allDay: occurrence.allDay,
|
|
1256
|
+
color: occurrence.color,
|
|
1257
|
+
textColor: occurrence.textColor,
|
|
1258
|
+
className: occurrence.className,
|
|
1259
|
+
editable: occurrence.editable,
|
|
1260
|
+
draggable: occurrence.draggable,
|
|
1261
|
+
resizable: occurrence.resizable,
|
|
1262
|
+
timezone: occurrence.timezone,
|
|
1263
|
+
resourceId: occurrence.resourceId,
|
|
1264
|
+
resourceIds: occurrence.resourceIds,
|
|
1265
|
+
categoryId: occurrence.categoryId,
|
|
1266
|
+
categoryIds: occurrence.categoryIds,
|
|
1267
|
+
rrule: void 0,
|
|
1268
|
+
exdate: void 0,
|
|
1269
|
+
rdate: void 0,
|
|
1270
|
+
metadata: {
|
|
1271
|
+
...event.metadata ?? {},
|
|
1272
|
+
...occurrence.metadata ?? {},
|
|
1273
|
+
recurringEventId: occurrence.recurringEventId,
|
|
1274
|
+
recurrenceId: occurrence.recurrenceId instanceof Date ? occurrence.recurrenceId.toISOString() : occurrence.recurrenceId,
|
|
1275
|
+
originalId: occurrence.originalId
|
|
1276
|
+
}
|
|
1277
|
+
});
|
|
1278
|
+
}
|
|
1279
|
+
}
|
|
1280
|
+
return expanded;
|
|
1281
|
+
}
|
|
1282
|
+
function filterEvents(events, options) {
|
|
1283
|
+
let filtered = [...events];
|
|
1284
|
+
if (options.includeRecurring === false) {
|
|
1285
|
+
filtered = filtered.filter((event) => !event.rrule);
|
|
1286
|
+
}
|
|
1287
|
+
filtered = expandRecurringEventsForExport(filtered, options);
|
|
1288
|
+
if (options.dateRange) {
|
|
1289
|
+
const start = toDate(options.dateRange.start);
|
|
1290
|
+
const end = toDate(options.dateRange.end);
|
|
1291
|
+
filtered = filtered.filter((event) => {
|
|
1292
|
+
const eventStart = toDate(event.start);
|
|
1293
|
+
const eventEnd = event.end ? toDate(event.end) : eventStart;
|
|
1294
|
+
return eventStart <= end && eventEnd >= start;
|
|
1295
|
+
});
|
|
1296
|
+
}
|
|
1297
|
+
if (options.resourceIds && options.resourceIds.length > 0) {
|
|
1298
|
+
const resourceSet = new Set(options.resourceIds.map(String));
|
|
1299
|
+
filtered = filtered.filter((event) => {
|
|
1300
|
+
if (event.resourceId && resourceSet.has(String(event.resourceId))) {
|
|
1301
|
+
return true;
|
|
1302
|
+
}
|
|
1303
|
+
if (event.resourceIds) {
|
|
1304
|
+
return event.resourceIds.some((id) => resourceSet.has(String(id)));
|
|
1305
|
+
}
|
|
1306
|
+
return false;
|
|
1307
|
+
});
|
|
1308
|
+
}
|
|
1309
|
+
if (options.categoryIds && options.categoryIds.length > 0) {
|
|
1310
|
+
const categorySet = new Set(options.categoryIds.map(String));
|
|
1311
|
+
filtered = filtered.filter((event) => {
|
|
1312
|
+
if (event.categoryId && categorySet.has(String(event.categoryId))) {
|
|
1313
|
+
return true;
|
|
1314
|
+
}
|
|
1315
|
+
if (event.categoryIds) {
|
|
1316
|
+
return event.categoryIds.some((id) => categorySet.has(String(id)));
|
|
1317
|
+
}
|
|
1318
|
+
return false;
|
|
1319
|
+
});
|
|
1320
|
+
}
|
|
1321
|
+
return filtered;
|
|
1322
|
+
}
|
|
1323
|
+
function exportToIcal(events, options = {}) {
|
|
1324
|
+
const { prodId = "-//PrimeUI//Scheduler//EN", calendarName = "Scheduler Export", includeTimezone = true, method = "PUBLISH", filename = "schedule.ics", ...filterOptions } = options;
|
|
1325
|
+
const filteredEvents = filterEvents(events, { ...filterOptions });
|
|
1326
|
+
const lines = ["BEGIN:VCALENDAR", "VERSION:2.0", foldICSLine(`PRODID:${prodId}`), foldICSLine(`X-WR-CALNAME:${escapeICSText(calendarName)}`), `METHOD:${method}`];
|
|
1327
|
+
if (includeTimezone) {
|
|
1328
|
+
const usedTimezones = /* @__PURE__ */ new Set();
|
|
1329
|
+
for (const event of filteredEvents) {
|
|
1330
|
+
if (event.timezone && !event.allDay) {
|
|
1331
|
+
usedTimezones.add(event.timezone);
|
|
1332
|
+
}
|
|
1333
|
+
}
|
|
1334
|
+
if (usedTimezones.size === 0) {
|
|
1335
|
+
usedTimezones.add("UTC");
|
|
1336
|
+
}
|
|
1337
|
+
for (const tz of usedTimezones) {
|
|
1338
|
+
lines.push(...generateVTimezone(tz));
|
|
1339
|
+
}
|
|
1340
|
+
}
|
|
1341
|
+
const exportEntries = buildExportEventEntries(filteredEvents);
|
|
1342
|
+
for (const entry of exportEntries) {
|
|
1343
|
+
const event = entry.event;
|
|
1344
|
+
lines.push("BEGIN:VEVENT");
|
|
1345
|
+
lines.push(foldICSLine(`UID:${entry.uid}`));
|
|
1346
|
+
const now = /* @__PURE__ */ new Date();
|
|
1347
|
+
lines.push(`DTSTAMP:${formatDateToICS(now)}`);
|
|
1348
|
+
const start = toDate(event.start);
|
|
1349
|
+
const eventTz = event.timezone;
|
|
1350
|
+
const recurrenceId = entry.recurrenceId;
|
|
1351
|
+
if (recurrenceId) {
|
|
1352
|
+
const recurrenceDate = toDate(recurrenceId);
|
|
1353
|
+
if (event.allDay) {
|
|
1354
|
+
lines.push(`RECURRENCE-ID;VALUE=DATE:${formatDateToICS(recurrenceDate, true)}`);
|
|
1355
|
+
} else if (eventTz) {
|
|
1356
|
+
lines.push(`RECURRENCE-ID;TZID=${eventTz}:${formatDateInTzForICS(recurrenceDate, eventTz)}`);
|
|
1357
|
+
} else {
|
|
1358
|
+
lines.push(`RECURRENCE-ID:${formatDateToICS(recurrenceDate)}`);
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
if (event.allDay) {
|
|
1362
|
+
const allDayStart = new Date(start.getFullYear(), start.getMonth(), start.getDate());
|
|
1363
|
+
const allDayExclusiveEnd = getAllDayExclusiveEndDate(start, event.end, event.duration);
|
|
1364
|
+
lines.push(`DTSTART;VALUE=DATE:${formatDateToICS(allDayStart, true)}`);
|
|
1365
|
+
lines.push(`DTEND;VALUE=DATE:${formatDateToICS(allDayExclusiveEnd, true)}`);
|
|
1366
|
+
} else if (eventTz) {
|
|
1367
|
+
lines.push(`DTSTART;TZID=${eventTz}:${formatDateInTzForICS(start, eventTz)}`);
|
|
1368
|
+
} else {
|
|
1369
|
+
lines.push(`DTSTART:${formatDateToICS(start)}`);
|
|
1370
|
+
}
|
|
1371
|
+
if (!event.allDay && event.end) {
|
|
1372
|
+
const end = toDate(event.end);
|
|
1373
|
+
if (eventTz) {
|
|
1374
|
+
lines.push(`DTEND;TZID=${eventTz}:${formatDateInTzForICS(end, eventTz)}`);
|
|
1375
|
+
} else {
|
|
1376
|
+
lines.push(`DTEND:${formatDateToICS(end)}`);
|
|
1377
|
+
}
|
|
1378
|
+
} else if (!event.allDay && event.duration) {
|
|
1379
|
+
const durationHours = Math.floor(event.duration / 60);
|
|
1380
|
+
const durationMinutes = event.duration % 60;
|
|
1381
|
+
lines.push(`DURATION:PT${durationHours}H${durationMinutes}M`);
|
|
1382
|
+
}
|
|
1383
|
+
lines.push(foldICSLine(`SUMMARY:${escapeICSText(event.title)}`));
|
|
1384
|
+
if (event.metadata?.description) {
|
|
1385
|
+
lines.push(foldICSLine(`DESCRIPTION:${escapeICSText(String(event.metadata.description))}`));
|
|
1386
|
+
}
|
|
1387
|
+
if (event.metadata?.location) {
|
|
1388
|
+
lines.push(foldICSLine(`LOCATION:${escapeICSText(String(event.metadata.location))}`));
|
|
1389
|
+
}
|
|
1390
|
+
if (!recurrenceId && event.rrule) {
|
|
1391
|
+
lines.push(foldICSLine(`RRULE:${rruleToICS(event.rrule)}`));
|
|
1392
|
+
}
|
|
1393
|
+
const seriesExceptions = !recurrenceId ? event.exceptions : void 0;
|
|
1394
|
+
const exceptionRecurrenceDates = (seriesExceptions ?? []).map((exception) => toDateSafe(exception.recurrenceId ?? exception.originalStart)).filter((date) => date !== null);
|
|
1395
|
+
const combinedExdates = dedupeDates([...event.exdate ?? [], ...exceptionRecurrenceDates]);
|
|
1396
|
+
if (!recurrenceId && combinedExdates.length > 0) {
|
|
1397
|
+
if (event.allDay) {
|
|
1398
|
+
const exdates = combinedExdates.map((d) => formatDateToICS(toDate(d), true)).join(",");
|
|
1399
|
+
lines.push(foldICSLine(`EXDATE;VALUE=DATE:${exdates}`));
|
|
1400
|
+
} else if (eventTz) {
|
|
1401
|
+
const exdates = combinedExdates.map((d) => formatDateInTzForICS(toDate(d), eventTz)).join(",");
|
|
1402
|
+
lines.push(foldICSLine(`EXDATE;TZID=${eventTz}:${exdates}`));
|
|
1403
|
+
} else {
|
|
1404
|
+
const exdates = combinedExdates.map((d) => formatDateToICS(toDate(d))).join(",");
|
|
1405
|
+
lines.push(foldICSLine(`EXDATE:${exdates}`));
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
if (!recurrenceId && event.rdate && event.rdate.length > 0) {
|
|
1409
|
+
if (event.allDay) {
|
|
1410
|
+
const rdates = event.rdate.map((d) => formatDateToICS(toDate(d), true)).join(",");
|
|
1411
|
+
lines.push(foldICSLine(`RDATE;VALUE=DATE:${rdates}`));
|
|
1412
|
+
} else if (eventTz) {
|
|
1413
|
+
const rdates = event.rdate.map((d) => formatDateInTzForICS(toDate(d), eventTz)).join(",");
|
|
1414
|
+
lines.push(foldICSLine(`RDATE;TZID=${eventTz}:${rdates}`));
|
|
1415
|
+
} else {
|
|
1416
|
+
const rdates = event.rdate.map((d) => formatDateToICS(toDate(d))).join(",");
|
|
1417
|
+
lines.push(foldICSLine(`RDATE:${rdates}`));
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
if (event.metadata?.organizer) {
|
|
1421
|
+
lines.push(foldICSLine(`ORGANIZER:${String(event.metadata.organizer)}`));
|
|
1422
|
+
}
|
|
1423
|
+
if (event.metadata?.attendees && Array.isArray(event.metadata.attendees)) {
|
|
1424
|
+
for (const attendee of event.metadata.attendees) {
|
|
1425
|
+
lines.push(foldICSLine(`ATTENDEE:${attendee}`));
|
|
1426
|
+
}
|
|
1427
|
+
}
|
|
1428
|
+
if (event.metadata?.status) {
|
|
1429
|
+
const status = String(event.metadata.status).toUpperCase();
|
|
1430
|
+
if (["TENTATIVE", "CONFIRMED", "CANCELLED"].includes(status)) {
|
|
1431
|
+
lines.push(`STATUS:${status}`);
|
|
1432
|
+
}
|
|
1433
|
+
}
|
|
1434
|
+
if (event.metadata?.priority) {
|
|
1435
|
+
const priority = Number(event.metadata.priority);
|
|
1436
|
+
if (priority >= 0 && priority <= 9) {
|
|
1437
|
+
lines.push(`PRIORITY:${priority}`);
|
|
1438
|
+
}
|
|
1439
|
+
}
|
|
1440
|
+
if (event.className) {
|
|
1441
|
+
lines.push(foldICSLine(`CATEGORIES:${event.className}`));
|
|
1442
|
+
}
|
|
1443
|
+
if (event.metadata?.url) {
|
|
1444
|
+
lines.push(foldICSLine(`URL:${String(event.metadata.url)}`));
|
|
1445
|
+
}
|
|
1446
|
+
lines.push("END:VEVENT");
|
|
1447
|
+
}
|
|
1448
|
+
lines.push("END:VCALENDAR");
|
|
1449
|
+
const data = lines.join("\r\n");
|
|
1450
|
+
return {
|
|
1451
|
+
data,
|
|
1452
|
+
filename,
|
|
1453
|
+
mimeType: "text/calendar;charset=utf-8",
|
|
1454
|
+
size: new Blob([data]).size
|
|
1455
|
+
};
|
|
1456
|
+
}
|
|
1457
|
+
function exportToJson(events, options = {}, resources, categories) {
|
|
1458
|
+
const { pretty = true, includeResources = false, includeCategories = false, schemaVersion = "2.0.0", metadata, filename = "schedule.json", ...filterOptions } = options;
|
|
1459
|
+
const filteredEvents = filterEvents(events, { ...filterOptions });
|
|
1460
|
+
const exportData = {
|
|
1461
|
+
version: "1.0",
|
|
1462
|
+
schemaVersion,
|
|
1463
|
+
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1464
|
+
events: filteredEvents.map((event) => ({
|
|
1465
|
+
...event,
|
|
1466
|
+
start: toDate(event.start).toISOString(),
|
|
1467
|
+
end: event.end ? toDate(event.end).toISOString() : void 0,
|
|
1468
|
+
exdate: event.exdate?.map((d) => toDate(d).toISOString())
|
|
1469
|
+
}))
|
|
1470
|
+
};
|
|
1471
|
+
if (metadata) {
|
|
1472
|
+
exportData.metadata = metadata;
|
|
1473
|
+
}
|
|
1474
|
+
if (includeResources && resources) {
|
|
1475
|
+
exportData.resources = resources;
|
|
1476
|
+
}
|
|
1477
|
+
if (includeCategories && categories) {
|
|
1478
|
+
exportData.categories = categories;
|
|
1479
|
+
}
|
|
1480
|
+
const data = pretty ? JSON.stringify(exportData, null, 2) : JSON.stringify(exportData);
|
|
1481
|
+
return {
|
|
1482
|
+
data,
|
|
1483
|
+
filename,
|
|
1484
|
+
mimeType: "application/json",
|
|
1485
|
+
size: new Blob([data]).size
|
|
1486
|
+
};
|
|
1487
|
+
}
|
|
1488
|
+
function escapeCSVField(value, delimiter, quoteAll) {
|
|
1489
|
+
const needsQuotes = quoteAll || value.includes(delimiter) || value.includes('"') || value.includes("\n") || value.includes("\r");
|
|
1490
|
+
if (needsQuotes) {
|
|
1491
|
+
return `"${value.replace(/"/g, '""')}"`;
|
|
1492
|
+
}
|
|
1493
|
+
return value;
|
|
1494
|
+
}
|
|
1495
|
+
function formatDateForCSV(date, format) {
|
|
1496
|
+
if (format === "iso") {
|
|
1497
|
+
return date.toISOString();
|
|
1498
|
+
}
|
|
1499
|
+
if (format === "locale") {
|
|
1500
|
+
return date.toLocaleString();
|
|
1501
|
+
}
|
|
1502
|
+
return date.toISOString();
|
|
1503
|
+
}
|
|
1504
|
+
function formatDisplayDateForCSV(date, allDay, calendarDisplayConfig) {
|
|
1505
|
+
const formatter = createSchedulerDateFormatter({
|
|
1506
|
+
...calendarDisplayConfig,
|
|
1507
|
+
locale: calendarDisplayConfig?.locale ?? "en"
|
|
1508
|
+
});
|
|
1509
|
+
return formatter.format(
|
|
1510
|
+
date,
|
|
1511
|
+
allDay ? {
|
|
1512
|
+
dateStyle: "medium"
|
|
1513
|
+
} : {
|
|
1514
|
+
dateStyle: "medium",
|
|
1515
|
+
timeStyle: "short"
|
|
1516
|
+
}
|
|
1517
|
+
);
|
|
1518
|
+
}
|
|
1519
|
+
var DEFAULT_CSV_COLUMNS = ["id", "title", "start", "end", "allDay", "color", "resourceId", "categoryId"];
|
|
1520
|
+
function exportToCsv(events, options = {}) {
|
|
1521
|
+
const { delimiter = ",", includeHeaders = true, dateFormat = "iso", columns = DEFAULT_CSV_COLUMNS, quoteAll = false, filename = "schedule.csv", calendarDisplayConfig, ...filterOptions } = options;
|
|
1522
|
+
const filteredEvents = filterEvents(events, { ...filterOptions });
|
|
1523
|
+
const rows = [];
|
|
1524
|
+
if (includeHeaders) {
|
|
1525
|
+
rows.push(columns.map((col) => escapeCSVField(col, delimiter, quoteAll)).join(delimiter));
|
|
1526
|
+
}
|
|
1527
|
+
for (const event of filteredEvents) {
|
|
1528
|
+
const row = columns.map((col) => {
|
|
1529
|
+
let value;
|
|
1530
|
+
switch (col) {
|
|
1531
|
+
case "id":
|
|
1532
|
+
value = event.id;
|
|
1533
|
+
break;
|
|
1534
|
+
case "title":
|
|
1535
|
+
value = event.title;
|
|
1536
|
+
break;
|
|
1537
|
+
case "start":
|
|
1538
|
+
value = formatDateForCSV(toDate(event.start), dateFormat);
|
|
1539
|
+
break;
|
|
1540
|
+
case "end":
|
|
1541
|
+
value = event.end ? formatDateForCSV(toDate(event.end), dateFormat) : "";
|
|
1542
|
+
break;
|
|
1543
|
+
case "startLabel":
|
|
1544
|
+
value = formatDisplayDateForCSV(toDate(event.start), event.allDay, calendarDisplayConfig);
|
|
1545
|
+
break;
|
|
1546
|
+
case "endLabel":
|
|
1547
|
+
value = event.end ? formatDisplayDateForCSV(toDate(event.end), event.allDay, calendarDisplayConfig) : "";
|
|
1548
|
+
break;
|
|
1549
|
+
case "allDay":
|
|
1550
|
+
value = event.allDay ? "true" : "false";
|
|
1551
|
+
break;
|
|
1552
|
+
case "duration":
|
|
1553
|
+
value = event.duration ?? "";
|
|
1554
|
+
break;
|
|
1555
|
+
case "color":
|
|
1556
|
+
value = event.color ?? "";
|
|
1557
|
+
break;
|
|
1558
|
+
case "textColor":
|
|
1559
|
+
value = event.textColor ?? "";
|
|
1560
|
+
break;
|
|
1561
|
+
case "borderColor":
|
|
1562
|
+
value = event.borderColor ?? "";
|
|
1563
|
+
break;
|
|
1564
|
+
case "className":
|
|
1565
|
+
value = event.className ?? "";
|
|
1566
|
+
break;
|
|
1567
|
+
case "editable":
|
|
1568
|
+
value = event.editable !== false ? "true" : "false";
|
|
1569
|
+
break;
|
|
1570
|
+
case "draggable":
|
|
1571
|
+
value = event.draggable !== false ? "true" : "false";
|
|
1572
|
+
break;
|
|
1573
|
+
case "resizable":
|
|
1574
|
+
value = event.resizable !== false ? "true" : "false";
|
|
1575
|
+
break;
|
|
1576
|
+
case "resourceId":
|
|
1577
|
+
value = event.resourceId ?? "";
|
|
1578
|
+
break;
|
|
1579
|
+
case "resourceIds":
|
|
1580
|
+
value = event.resourceIds?.join(";") ?? "";
|
|
1581
|
+
break;
|
|
1582
|
+
case "categoryId":
|
|
1583
|
+
value = event.categoryId ?? "";
|
|
1584
|
+
break;
|
|
1585
|
+
case "categoryIds":
|
|
1586
|
+
value = event.categoryIds?.join(";") ?? "";
|
|
1587
|
+
break;
|
|
1588
|
+
case "timezone":
|
|
1589
|
+
value = event.timezone ?? "";
|
|
1590
|
+
break;
|
|
1591
|
+
case "rrule":
|
|
1592
|
+
value = event.rrule ? typeof event.rrule === "string" ? event.rrule : rruleToICS(event.rrule) : "";
|
|
1593
|
+
break;
|
|
1594
|
+
case "exdate":
|
|
1595
|
+
value = event.exdate ? event.exdate.map((d) => toDate(d).toISOString()).join(";") : "";
|
|
1596
|
+
break;
|
|
1597
|
+
default:
|
|
1598
|
+
if (col.startsWith("metadata.")) {
|
|
1599
|
+
const propName = col.slice("metadata.".length);
|
|
1600
|
+
value = event.metadata?.[propName] ?? "";
|
|
1601
|
+
} else if (event.metadata?.[col] !== void 0) {
|
|
1602
|
+
value = event.metadata[col];
|
|
1603
|
+
} else {
|
|
1604
|
+
value = "";
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
const stringValue = value === null || value === void 0 ? "" : String(value);
|
|
1608
|
+
return escapeCSVField(stringValue, delimiter, quoteAll);
|
|
1609
|
+
});
|
|
1610
|
+
rows.push(row.join(delimiter));
|
|
1611
|
+
}
|
|
1612
|
+
const data = rows.join("\n");
|
|
1613
|
+
return {
|
|
1614
|
+
data,
|
|
1615
|
+
filename,
|
|
1616
|
+
mimeType: delimiter === " " ? "text/tab-separated-values" : "text/csv",
|
|
1617
|
+
size: new Blob([data]).size
|
|
1618
|
+
};
|
|
1619
|
+
}
|
|
1620
|
+
function prepareXlsxData(events, options = {}, resources, categories) {
|
|
1621
|
+
const { sheets = ["events"], columns = {}, sheetNames = {}, ...filterOptions } = options;
|
|
1622
|
+
const result = { sheets: [] };
|
|
1623
|
+
if (sheets.includes("events")) {
|
|
1624
|
+
const eventColumns = columns.events || DEFAULT_CSV_COLUMNS;
|
|
1625
|
+
const filteredEvents = filterEvents(events, { ...filterOptions });
|
|
1626
|
+
const eventRows = filteredEvents.map(
|
|
1627
|
+
(event) => eventColumns.map((col) => {
|
|
1628
|
+
switch (col) {
|
|
1629
|
+
case "start":
|
|
1630
|
+
return toDate(event.start).toISOString();
|
|
1631
|
+
case "end":
|
|
1632
|
+
return event.end ? toDate(event.end).toISOString() : "";
|
|
1633
|
+
case "allDay":
|
|
1634
|
+
return event.allDay ?? false;
|
|
1635
|
+
default:
|
|
1636
|
+
return event[col] ?? "";
|
|
1637
|
+
}
|
|
1638
|
+
})
|
|
1639
|
+
);
|
|
1640
|
+
result.sheets.push({
|
|
1641
|
+
name: sheetNames.events || "Events",
|
|
1642
|
+
headers: eventColumns,
|
|
1643
|
+
rows: eventRows
|
|
1644
|
+
});
|
|
1645
|
+
}
|
|
1646
|
+
if (sheets.includes("resources") && resources) {
|
|
1647
|
+
const resourceColumns = columns.resources || ["id", "title", "color"];
|
|
1648
|
+
const resourceRows = resources.map((resource) => resourceColumns.map((col) => resource[col] ?? ""));
|
|
1649
|
+
result.sheets.push({
|
|
1650
|
+
name: sheetNames.resources || "Resources",
|
|
1651
|
+
headers: resourceColumns,
|
|
1652
|
+
rows: resourceRows
|
|
1653
|
+
});
|
|
1654
|
+
}
|
|
1655
|
+
if (sheets.includes("categories") && categories) {
|
|
1656
|
+
const categoryColumns = columns.categories || ["id", "name", "color"];
|
|
1657
|
+
const categoryRows = categories.map((category) => categoryColumns.map((col) => category[col] ?? ""));
|
|
1658
|
+
result.sheets.push({
|
|
1659
|
+
name: sheetNames.categories || "Categories",
|
|
1660
|
+
headers: categoryColumns,
|
|
1661
|
+
rows: categoryRows
|
|
1662
|
+
});
|
|
1663
|
+
}
|
|
1664
|
+
return result;
|
|
1665
|
+
}
|
|
1666
|
+
async function exportToXlsx(events, options = {}, adapter, resources, categories) {
|
|
1667
|
+
const { filename = "schedule.xlsx" } = options;
|
|
1668
|
+
const data = prepareXlsxData(events, options, resources, categories);
|
|
1669
|
+
const workbook = adapter.createWorkbook();
|
|
1670
|
+
for (const sheet of data.sheets) {
|
|
1671
|
+
const sheetData = [sheet.headers, ...sheet.rows];
|
|
1672
|
+
adapter.addSheet(workbook, sheet.name, sheetData);
|
|
1673
|
+
}
|
|
1674
|
+
const blob = await adapter.toBlob(workbook);
|
|
1675
|
+
return {
|
|
1676
|
+
data: blob,
|
|
1677
|
+
filename,
|
|
1678
|
+
mimeType: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
1679
|
+
size: blob.size
|
|
1680
|
+
};
|
|
1681
|
+
}
|
|
1682
|
+
function preparePdfData(events, options = {}, resources, categories) {
|
|
1683
|
+
const { headerText, dateRange, fields = ["title", "start", "end", "resourceId"], ...filterOptions } = options;
|
|
1684
|
+
const filteredEvents = filterEvents(events, { ...filterOptions });
|
|
1685
|
+
const headers = fields.map((field) => {
|
|
1686
|
+
switch (field) {
|
|
1687
|
+
case "id":
|
|
1688
|
+
return "ID";
|
|
1689
|
+
case "title":
|
|
1690
|
+
return "Title";
|
|
1691
|
+
case "start":
|
|
1692
|
+
return "Start";
|
|
1693
|
+
case "end":
|
|
1694
|
+
return "End";
|
|
1695
|
+
case "allDay":
|
|
1696
|
+
return "All Day";
|
|
1697
|
+
case "resourceId":
|
|
1698
|
+
return "Resource";
|
|
1699
|
+
case "categoryId":
|
|
1700
|
+
return "Category";
|
|
1701
|
+
default:
|
|
1702
|
+
return field.charAt(0).toUpperCase() + field.slice(1);
|
|
1703
|
+
}
|
|
1704
|
+
});
|
|
1705
|
+
const resourceMap = /* @__PURE__ */ new Map();
|
|
1706
|
+
if (resources) {
|
|
1707
|
+
for (const resource of resources) {
|
|
1708
|
+
resourceMap.set(resource.id, resource.title);
|
|
1709
|
+
}
|
|
1710
|
+
}
|
|
1711
|
+
const categoryMap = /* @__PURE__ */ new Map();
|
|
1712
|
+
if (categories) {
|
|
1713
|
+
for (const category of categories) {
|
|
1714
|
+
categoryMap.set(category.id, category.name);
|
|
1715
|
+
}
|
|
1716
|
+
}
|
|
1717
|
+
const rows = filteredEvents.map(
|
|
1718
|
+
(event) => fields.map((field) => {
|
|
1719
|
+
switch (field) {
|
|
1720
|
+
case "start":
|
|
1721
|
+
return toDate(event.start).toLocaleString();
|
|
1722
|
+
case "end":
|
|
1723
|
+
return event.end ? toDate(event.end).toLocaleString() : "";
|
|
1724
|
+
case "allDay":
|
|
1725
|
+
return event.allDay ? "Yes" : "No";
|
|
1726
|
+
case "resourceId":
|
|
1727
|
+
if (event.resourceId) {
|
|
1728
|
+
return resourceMap.get(event.resourceId) || String(event.resourceId);
|
|
1729
|
+
}
|
|
1730
|
+
return "";
|
|
1731
|
+
case "categoryId":
|
|
1732
|
+
if (event.categoryId) {
|
|
1733
|
+
return categoryMap.get(event.categoryId) || String(event.categoryId);
|
|
1734
|
+
}
|
|
1735
|
+
return "";
|
|
1736
|
+
default:
|
|
1737
|
+
return String(event[field] ?? "");
|
|
1738
|
+
}
|
|
1739
|
+
})
|
|
1740
|
+
);
|
|
1741
|
+
let title = headerText;
|
|
1742
|
+
let dateRangeStr;
|
|
1743
|
+
if (dateRange) {
|
|
1744
|
+
dateRangeStr = `${toDate(dateRange.start).toLocaleDateString()} - ${toDate(dateRange.end).toLocaleDateString()}`;
|
|
1745
|
+
if (title) {
|
|
1746
|
+
title = title.replace("{{ dateRange }}", dateRangeStr);
|
|
1747
|
+
}
|
|
1748
|
+
}
|
|
1749
|
+
return { headers, rows, title, dateRange: dateRangeStr };
|
|
1750
|
+
}
|
|
1751
|
+
async function exportToPdf(events, options = {}, adapter, resources, categories) {
|
|
1752
|
+
const { filename = "schedule.pdf" } = options;
|
|
1753
|
+
const data = preparePdfData(events, options, resources, categories);
|
|
1754
|
+
const doc = adapter.createDocument(options);
|
|
1755
|
+
if (data.title) {
|
|
1756
|
+
adapter.addText(doc, data.title, { fontSize: 16, bold: true });
|
|
1757
|
+
}
|
|
1758
|
+
adapter.addTable(doc, data.headers, data.rows);
|
|
1759
|
+
const blob = await adapter.toBlob(doc);
|
|
1760
|
+
return {
|
|
1761
|
+
data: blob,
|
|
1762
|
+
filename,
|
|
1763
|
+
mimeType: "application/pdf",
|
|
1764
|
+
size: blob.size
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
function exportScheduler(events, options, resources, categories) {
|
|
1768
|
+
switch (options.format) {
|
|
1769
|
+
case "ical":
|
|
1770
|
+
return exportToIcal(events, options);
|
|
1771
|
+
case "json":
|
|
1772
|
+
return exportToJson(events, options, resources, categories);
|
|
1773
|
+
case "csv":
|
|
1774
|
+
return exportToCsv(events, options);
|
|
1775
|
+
default:
|
|
1776
|
+
throw new Error(`Export format "${options.format}" requires an adapter. Use exportToXlsx or exportToPdf with appropriate adapter.`);
|
|
1777
|
+
}
|
|
1778
|
+
}
|
|
1779
|
+
|
|
1780
|
+
// src/utils/import.ts
|
|
1781
|
+
function generateId() {
|
|
1782
|
+
return `import-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`;
|
|
1783
|
+
}
|
|
1784
|
+
function parseICSDate(value, options = {}) {
|
|
1785
|
+
value = value.trim();
|
|
1786
|
+
const { isAllDay = false, tzid, defaultTimezone } = options;
|
|
1787
|
+
const ensureValidDate = (date) => {
|
|
1788
|
+
if (isNaN(date.getTime())) {
|
|
1789
|
+
throw new Error(`Invalid ICS date: ${value}`);
|
|
1790
|
+
}
|
|
1791
|
+
return date;
|
|
1792
|
+
};
|
|
1793
|
+
if (isAllDay || value.length === 8) {
|
|
1794
|
+
const year = parseInt(value.slice(0, 4), 10);
|
|
1795
|
+
const month = parseInt(value.slice(4, 6), 10) - 1;
|
|
1796
|
+
const day = parseInt(value.slice(6, 8), 10);
|
|
1797
|
+
return ensureValidDate(new Date(year, month, day));
|
|
1798
|
+
}
|
|
1799
|
+
if (value.endsWith("Z")) {
|
|
1800
|
+
const year = parseInt(value.slice(0, 4), 10);
|
|
1801
|
+
const month = parseInt(value.slice(4, 6), 10) - 1;
|
|
1802
|
+
const day = parseInt(value.slice(6, 8), 10);
|
|
1803
|
+
const hours = parseInt(value.slice(9, 11), 10);
|
|
1804
|
+
const minutes = parseInt(value.slice(11, 13), 10);
|
|
1805
|
+
const seconds = parseInt(value.slice(13, 15), 10);
|
|
1806
|
+
return ensureValidDate(new Date(Date.UTC(year, month, day, hours, minutes, seconds)));
|
|
1807
|
+
}
|
|
1808
|
+
if (value.includes("T")) {
|
|
1809
|
+
const year = parseInt(value.slice(0, 4), 10);
|
|
1810
|
+
const month = parseInt(value.slice(4, 6), 10) - 1;
|
|
1811
|
+
const day = parseInt(value.slice(6, 8), 10);
|
|
1812
|
+
const hours = parseInt(value.slice(9, 11), 10);
|
|
1813
|
+
const minutes = parseInt(value.slice(11, 13), 10);
|
|
1814
|
+
const seconds = parseInt(value.slice(13, 15), 10) || 0;
|
|
1815
|
+
const effectiveTimezone = tzid && isValidTimezone(tzid) ? tzid : defaultTimezone && isValidTimezone(defaultTimezone) ? defaultTimezone : void 0;
|
|
1816
|
+
if (effectiveTimezone) {
|
|
1817
|
+
return ensureValidDate(createDateInTimezone(effectiveTimezone, year, month, day, hours, minutes, seconds));
|
|
1818
|
+
}
|
|
1819
|
+
return ensureValidDate(new Date(year, month, day, hours, minutes, seconds));
|
|
1820
|
+
}
|
|
1821
|
+
return ensureValidDate(new Date(value));
|
|
1822
|
+
}
|
|
1823
|
+
function unescapeICSText(text) {
|
|
1824
|
+
return text.replace(/\\n/g, "\n").replace(/\\,/g, ",").replace(/\\;/g, ";").replace(/\\\\/g, "\\");
|
|
1825
|
+
}
|
|
1826
|
+
function normalizeLineEndings(content) {
|
|
1827
|
+
return content.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
1828
|
+
}
|
|
1829
|
+
function unfoldICSContent(content) {
|
|
1830
|
+
const rawLines = normalizeLineEndings(content).split("\n");
|
|
1831
|
+
const unfolded = [];
|
|
1832
|
+
for (const rawLine of rawLines) {
|
|
1833
|
+
if (rawLine.length === 0) {
|
|
1834
|
+
unfolded.push("");
|
|
1835
|
+
continue;
|
|
1836
|
+
}
|
|
1837
|
+
if ((rawLine.startsWith(" ") || rawLine.startsWith(" ")) && unfolded.length > 0) {
|
|
1838
|
+
unfolded[unfolded.length - 1] += rawLine.slice(1);
|
|
1839
|
+
continue;
|
|
1840
|
+
}
|
|
1841
|
+
if (unfolded.length > 0 && unfolded[unfolded.length - 1].endsWith("=")) {
|
|
1842
|
+
unfolded[unfolded.length - 1] = unfolded[unfolded.length - 1].slice(0, -1) + rawLine;
|
|
1843
|
+
continue;
|
|
1844
|
+
}
|
|
1845
|
+
unfolded.push(rawLine);
|
|
1846
|
+
}
|
|
1847
|
+
return unfolded;
|
|
1848
|
+
}
|
|
1849
|
+
function decodeQuotedPrintable(value, charset = "utf-8") {
|
|
1850
|
+
const cleaned = value.replace(/=\r?\n/g, "");
|
|
1851
|
+
const bytes = [];
|
|
1852
|
+
for (let i = 0; i < cleaned.length; i++) {
|
|
1853
|
+
const char = cleaned[i];
|
|
1854
|
+
if (char === "=" && i + 2 < cleaned.length) {
|
|
1855
|
+
const hex = cleaned.slice(i + 1, i + 3);
|
|
1856
|
+
if (/^[0-9A-Fa-f]{2}$/.test(hex)) {
|
|
1857
|
+
bytes.push(parseInt(hex, 16));
|
|
1858
|
+
i += 2;
|
|
1859
|
+
continue;
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
bytes.push(char.charCodeAt(0));
|
|
1863
|
+
}
|
|
1864
|
+
try {
|
|
1865
|
+
return new TextDecoder(charset).decode(new Uint8Array(bytes));
|
|
1866
|
+
} catch {
|
|
1867
|
+
return new TextDecoder("utf-8").decode(new Uint8Array(bytes));
|
|
1868
|
+
}
|
|
1869
|
+
}
|
|
1870
|
+
function decodeICSValue(value, params, options) {
|
|
1871
|
+
const encoding = params.ENCODING?.toUpperCase();
|
|
1872
|
+
const charset = params.CHARSET || "utf-8";
|
|
1873
|
+
if (encoding === "QUOTED-PRINTABLE" && options.decodeQuotedPrintable !== false) {
|
|
1874
|
+
return decodeQuotedPrintable(value, charset);
|
|
1875
|
+
}
|
|
1876
|
+
return value;
|
|
1877
|
+
}
|
|
1878
|
+
function readFileAsText(file, charset) {
|
|
1879
|
+
return new Promise((resolve, reject) => {
|
|
1880
|
+
const reader = new FileReader();
|
|
1881
|
+
reader.onload = () => {
|
|
1882
|
+
if (reader.result instanceof ArrayBuffer) {
|
|
1883
|
+
try {
|
|
1884
|
+
resolve(new TextDecoder(charset || "utf-8").decode(new Uint8Array(reader.result)));
|
|
1885
|
+
} catch {
|
|
1886
|
+
resolve(new TextDecoder("utf-8").decode(new Uint8Array(reader.result)));
|
|
1887
|
+
}
|
|
1888
|
+
} else {
|
|
1889
|
+
resolve(String(reader.result ?? ""));
|
|
1890
|
+
}
|
|
1891
|
+
};
|
|
1892
|
+
reader.onerror = () => reject(new Error("Failed to read file"));
|
|
1893
|
+
reader.readAsArrayBuffer(file);
|
|
1894
|
+
});
|
|
1895
|
+
}
|
|
1896
|
+
function parseICSLine(line) {
|
|
1897
|
+
const colonIndex = line.indexOf(":");
|
|
1898
|
+
if (colonIndex === -1) {
|
|
1899
|
+
return { property: "", params: {}, value: line };
|
|
1900
|
+
}
|
|
1901
|
+
const propertyPart = line.slice(0, colonIndex);
|
|
1902
|
+
const value = line.slice(colonIndex + 1);
|
|
1903
|
+
const semicolonIndex = propertyPart.indexOf(";");
|
|
1904
|
+
let property;
|
|
1905
|
+
const params = {};
|
|
1906
|
+
if (semicolonIndex === -1) {
|
|
1907
|
+
property = propertyPart.toUpperCase();
|
|
1908
|
+
} else {
|
|
1909
|
+
property = propertyPart.slice(0, semicolonIndex).toUpperCase();
|
|
1910
|
+
const paramString = propertyPart.slice(semicolonIndex + 1);
|
|
1911
|
+
const paramPairs = paramString.split(";");
|
|
1912
|
+
for (const pair of paramPairs) {
|
|
1913
|
+
const [key, val] = pair.split("=");
|
|
1914
|
+
if (key && val) {
|
|
1915
|
+
params[key.toUpperCase()] = val.replace(/^"|"$/g, "");
|
|
1916
|
+
}
|
|
1917
|
+
}
|
|
1918
|
+
}
|
|
1919
|
+
return { property, params, value };
|
|
1920
|
+
}
|
|
1921
|
+
function convertAllDayExclusiveEndToInclusive(endExclusive, start) {
|
|
1922
|
+
const inclusive = new Date(endExclusive.getFullYear(), endExclusive.getMonth(), endExclusive.getDate());
|
|
1923
|
+
inclusive.setDate(inclusive.getDate() - 1);
|
|
1924
|
+
if (start && inclusive.getTime() < start.getTime()) {
|
|
1925
|
+
const sameDay = new Date(start);
|
|
1926
|
+
sameDay.setHours(23, 59, 59, 999);
|
|
1927
|
+
return sameDay;
|
|
1928
|
+
}
|
|
1929
|
+
inclusive.setHours(23, 59, 59, 999);
|
|
1930
|
+
return inclusive;
|
|
1931
|
+
}
|
|
1932
|
+
function parseICSDurationMinutes(value) {
|
|
1933
|
+
const match = value.match(/^P(?:(\d+)W)?(?:(\d+)D)?(?:T(?:(\d+)H)?(?:(\d+)M)?(?:(\d+)S)?)?$/i);
|
|
1934
|
+
if (!match) {
|
|
1935
|
+
return null;
|
|
1936
|
+
}
|
|
1937
|
+
const weeks = parseInt(match[1] || "0", 10);
|
|
1938
|
+
const days = parseInt(match[2] || "0", 10);
|
|
1939
|
+
const hours = parseInt(match[3] || "0", 10);
|
|
1940
|
+
const minutes = parseInt(match[4] || "0", 10);
|
|
1941
|
+
const seconds = parseInt(match[5] || "0", 10);
|
|
1942
|
+
const totalMinutes = weeks * 7 * 24 * 60 + days * 24 * 60 + hours * 60 + minutes + Math.round(seconds / 60);
|
|
1943
|
+
return totalMinutes > 0 ? totalMinutes : null;
|
|
1944
|
+
}
|
|
1945
|
+
function finalizeImportedEvent(currentEvent, options) {
|
|
1946
|
+
if (!currentEvent.title || !currentEvent.start) {
|
|
1947
|
+
return null;
|
|
1948
|
+
}
|
|
1949
|
+
const start = currentEvent.start instanceof Date ? currentEvent.start : new Date(currentEvent.start);
|
|
1950
|
+
const defaultDuration = options.defaultDuration && options.defaultDuration > 0 ? options.defaultDuration : 60;
|
|
1951
|
+
if (!currentEvent.end) {
|
|
1952
|
+
if (typeof currentEvent.duration === "number" && currentEvent.duration > 0) {
|
|
1953
|
+
currentEvent.end = new Date(start.getTime() + currentEvent.duration * 60 * 1e3);
|
|
1954
|
+
} else if (currentEvent.allDay) {
|
|
1955
|
+
const endOfDay2 = new Date(start);
|
|
1956
|
+
endOfDay2.setHours(23, 59, 59, 999);
|
|
1957
|
+
currentEvent.end = endOfDay2;
|
|
1958
|
+
} else {
|
|
1959
|
+
currentEvent.end = new Date(start.getTime() + defaultDuration * 60 * 1e3);
|
|
1960
|
+
}
|
|
1961
|
+
}
|
|
1962
|
+
return currentEvent;
|
|
1963
|
+
}
|
|
1964
|
+
function getEventUID(event) {
|
|
1965
|
+
const uid = event.metadata?.uid;
|
|
1966
|
+
return typeof uid === "string" ? uid : void 0;
|
|
1967
|
+
}
|
|
1968
|
+
function normalizeRecurringExceptions(events, options) {
|
|
1969
|
+
if (options.preserveExceptionEvents) {
|
|
1970
|
+
return events;
|
|
1971
|
+
}
|
|
1972
|
+
const mastersByUid = /* @__PURE__ */ new Map();
|
|
1973
|
+
for (const event of events) {
|
|
1974
|
+
const uid = getEventUID(event);
|
|
1975
|
+
if (!uid || !event.rrule || event.recurrenceId) {
|
|
1976
|
+
continue;
|
|
1977
|
+
}
|
|
1978
|
+
mastersByUid.set(uid, event);
|
|
1979
|
+
}
|
|
1980
|
+
const normalized = [];
|
|
1981
|
+
for (const event of events) {
|
|
1982
|
+
const uid = getEventUID(event);
|
|
1983
|
+
const recurrenceIdRaw = event.recurrenceId;
|
|
1984
|
+
if (!uid || !recurrenceIdRaw) {
|
|
1985
|
+
normalized.push(event);
|
|
1986
|
+
continue;
|
|
1987
|
+
}
|
|
1988
|
+
const master = mastersByUid.get(uid);
|
|
1989
|
+
if (!master) {
|
|
1990
|
+
normalized.push(event);
|
|
1991
|
+
continue;
|
|
1992
|
+
}
|
|
1993
|
+
const recurrenceIdDate = recurrenceIdRaw instanceof Date ? recurrenceIdRaw : new Date(recurrenceIdRaw);
|
|
1994
|
+
const exceptionEvent = {
|
|
1995
|
+
title: event.title,
|
|
1996
|
+
start: event.start,
|
|
1997
|
+
end: event.end,
|
|
1998
|
+
duration: event.duration,
|
|
1999
|
+
allDay: event.allDay,
|
|
2000
|
+
color: event.color,
|
|
2001
|
+
textColor: event.textColor,
|
|
2002
|
+
className: event.className,
|
|
2003
|
+
editable: event.editable,
|
|
2004
|
+
draggable: event.draggable,
|
|
2005
|
+
resizable: event.resizable,
|
|
2006
|
+
timezone: event.timezone,
|
|
2007
|
+
resourceId: event.resourceId,
|
|
2008
|
+
resourceIds: event.resourceIds,
|
|
2009
|
+
categoryId: event.categoryId,
|
|
2010
|
+
categoryIds: event.categoryIds,
|
|
2011
|
+
metadata: { ...event.metadata ?? {} }
|
|
2012
|
+
};
|
|
2013
|
+
const existingExceptions = master.exceptions ?? [];
|
|
2014
|
+
existingExceptions.push({
|
|
2015
|
+
recurrenceId: recurrenceIdDate,
|
|
2016
|
+
originalStart: recurrenceIdDate,
|
|
2017
|
+
event: exceptionEvent
|
|
2018
|
+
});
|
|
2019
|
+
master.exceptions = existingExceptions;
|
|
2020
|
+
const existingExdate = master.exdate ?? [];
|
|
2021
|
+
master.exdate = [...existingExdate, recurrenceIdDate];
|
|
2022
|
+
}
|
|
2023
|
+
return normalized;
|
|
2024
|
+
}
|
|
2025
|
+
function importFromIcal(content, options = {}) {
|
|
2026
|
+
return new Promise((resolve) => {
|
|
2027
|
+
const processContent = (icsContent) => {
|
|
2028
|
+
const events = [];
|
|
2029
|
+
const errors = [];
|
|
2030
|
+
const warnings = [];
|
|
2031
|
+
const lines = unfoldICSContent(icsContent);
|
|
2032
|
+
let inEvent = false;
|
|
2033
|
+
let currentEvent = {};
|
|
2034
|
+
let lineNumber = 0;
|
|
2035
|
+
for (const line of lines) {
|
|
2036
|
+
lineNumber++;
|
|
2037
|
+
if (!line.trim()) continue;
|
|
2038
|
+
const { property, params, value } = parseICSLine(line);
|
|
2039
|
+
const decodedValue = decodeICSValue(value, params, options);
|
|
2040
|
+
if (property === "BEGIN" && decodedValue.toUpperCase() === "VEVENT") {
|
|
2041
|
+
inEvent = true;
|
|
2042
|
+
currentEvent = { id: generateId() };
|
|
2043
|
+
continue;
|
|
2044
|
+
}
|
|
2045
|
+
if (property === "END" && decodedValue.toUpperCase() === "VEVENT") {
|
|
2046
|
+
const finalized = finalizeImportedEvent(currentEvent, options);
|
|
2047
|
+
if (finalized) {
|
|
2048
|
+
events.push(finalized);
|
|
2049
|
+
} else {
|
|
2050
|
+
errors.push({
|
|
2051
|
+
line: lineNumber,
|
|
2052
|
+
message: "Event missing required fields (SUMMARY or DTSTART)",
|
|
2053
|
+
raw: JSON.stringify(currentEvent)
|
|
2054
|
+
});
|
|
2055
|
+
}
|
|
2056
|
+
inEvent = false;
|
|
2057
|
+
currentEvent = {};
|
|
2058
|
+
continue;
|
|
2059
|
+
}
|
|
2060
|
+
if (!inEvent) continue;
|
|
2061
|
+
switch (property) {
|
|
2062
|
+
case "UID":
|
|
2063
|
+
if (!currentEvent.metadata) currentEvent.metadata = {};
|
|
2064
|
+
currentEvent.metadata.uid = unescapeICSText(decodedValue);
|
|
2065
|
+
break;
|
|
2066
|
+
case "SUMMARY":
|
|
2067
|
+
currentEvent.title = unescapeICSText(decodedValue);
|
|
2068
|
+
break;
|
|
2069
|
+
case "DTSTART": {
|
|
2070
|
+
const isAllDay = params.VALUE === "DATE";
|
|
2071
|
+
const tzid = params.TZID;
|
|
2072
|
+
try {
|
|
2073
|
+
currentEvent.start = parseICSDate(decodedValue, {
|
|
2074
|
+
isAllDay,
|
|
2075
|
+
tzid,
|
|
2076
|
+
defaultTimezone: options.timezone
|
|
2077
|
+
});
|
|
2078
|
+
currentEvent.allDay = isAllDay;
|
|
2079
|
+
if (!isAllDay && tzid) {
|
|
2080
|
+
currentEvent.timezone = tzid;
|
|
2081
|
+
} else if (!isAllDay && options.timezone) {
|
|
2082
|
+
currentEvent.timezone = options.timezone;
|
|
2083
|
+
}
|
|
2084
|
+
} catch {
|
|
2085
|
+
errors.push({
|
|
2086
|
+
line: lineNumber,
|
|
2087
|
+
field: "DTSTART",
|
|
2088
|
+
message: `Invalid date format: ${value}`,
|
|
2089
|
+
raw: line
|
|
2090
|
+
});
|
|
2091
|
+
}
|
|
2092
|
+
break;
|
|
2093
|
+
}
|
|
2094
|
+
case "DTEND": {
|
|
2095
|
+
const isAllDay = params.VALUE === "DATE";
|
|
2096
|
+
const tzid = params.TZID || currentEvent.timezone;
|
|
2097
|
+
try {
|
|
2098
|
+
const parsedEnd = parseICSDate(decodedValue, {
|
|
2099
|
+
isAllDay,
|
|
2100
|
+
tzid,
|
|
2101
|
+
defaultTimezone: options.timezone
|
|
2102
|
+
});
|
|
2103
|
+
currentEvent.end = isAllDay ? convertAllDayExclusiveEndToInclusive(parsedEnd, currentEvent.start) : parsedEnd;
|
|
2104
|
+
} catch {
|
|
2105
|
+
errors.push({
|
|
2106
|
+
line: lineNumber,
|
|
2107
|
+
field: "DTEND",
|
|
2108
|
+
message: `Invalid date format: ${value}`,
|
|
2109
|
+
raw: line
|
|
2110
|
+
});
|
|
2111
|
+
}
|
|
2112
|
+
break;
|
|
2113
|
+
}
|
|
2114
|
+
case "DURATION": {
|
|
2115
|
+
const durationMinutes = parseICSDurationMinutes(decodedValue);
|
|
2116
|
+
if (durationMinutes !== null) {
|
|
2117
|
+
currentEvent.duration = durationMinutes;
|
|
2118
|
+
}
|
|
2119
|
+
break;
|
|
2120
|
+
}
|
|
2121
|
+
case "RECURRENCE-ID": {
|
|
2122
|
+
const isAllDay = params.VALUE === "DATE";
|
|
2123
|
+
const tzid = params.TZID || currentEvent.timezone;
|
|
2124
|
+
try {
|
|
2125
|
+
currentEvent.recurrenceId = parseICSDate(decodedValue, {
|
|
2126
|
+
isAllDay,
|
|
2127
|
+
tzid,
|
|
2128
|
+
defaultTimezone: options.timezone
|
|
2129
|
+
});
|
|
2130
|
+
} catch {
|
|
2131
|
+
warnings.push({
|
|
2132
|
+
line: lineNumber,
|
|
2133
|
+
field: "RECURRENCE-ID",
|
|
2134
|
+
message: `Invalid recurrence id: ${decodedValue}`,
|
|
2135
|
+
raw: line
|
|
2136
|
+
});
|
|
2137
|
+
}
|
|
2138
|
+
break;
|
|
2139
|
+
}
|
|
2140
|
+
case "DESCRIPTION":
|
|
2141
|
+
if (!currentEvent.metadata) currentEvent.metadata = {};
|
|
2142
|
+
currentEvent.metadata.description = unescapeICSText(decodedValue);
|
|
2143
|
+
break;
|
|
2144
|
+
case "LOCATION":
|
|
2145
|
+
if (!currentEvent.metadata) currentEvent.metadata = {};
|
|
2146
|
+
currentEvent.metadata.location = unescapeICSText(decodedValue);
|
|
2147
|
+
break;
|
|
2148
|
+
case "RRULE":
|
|
2149
|
+
if (options.parseRecurrence !== false) {
|
|
2150
|
+
const parsedRRule = parseRRule(decodedValue);
|
|
2151
|
+
if (parsedRRule) {
|
|
2152
|
+
currentEvent.rrule = parsedRRule;
|
|
2153
|
+
} else {
|
|
2154
|
+
warnings.push({
|
|
2155
|
+
line: lineNumber,
|
|
2156
|
+
field: "RRULE",
|
|
2157
|
+
message: "Invalid recurrence rule",
|
|
2158
|
+
raw: line
|
|
2159
|
+
});
|
|
2160
|
+
}
|
|
2161
|
+
} else {
|
|
2162
|
+
warnings.push({
|
|
2163
|
+
line: lineNumber,
|
|
2164
|
+
message: "Recurrence rule ignored (parseRecurrence is false)",
|
|
2165
|
+
raw: line
|
|
2166
|
+
});
|
|
2167
|
+
}
|
|
2168
|
+
break;
|
|
2169
|
+
case "EXDATE": {
|
|
2170
|
+
const isAllDay = params.VALUE === "DATE";
|
|
2171
|
+
const tzid = params.TZID || currentEvent.timezone;
|
|
2172
|
+
const dates = decodedValue.split(",").map((d) => {
|
|
2173
|
+
try {
|
|
2174
|
+
return parseICSDate(d.trim(), {
|
|
2175
|
+
isAllDay,
|
|
2176
|
+
tzid,
|
|
2177
|
+
defaultTimezone: options.timezone
|
|
2178
|
+
});
|
|
2179
|
+
} catch {
|
|
2180
|
+
return null;
|
|
2181
|
+
}
|
|
2182
|
+
}).filter((d) => d !== null);
|
|
2183
|
+
currentEvent.exdate = dates;
|
|
2184
|
+
break;
|
|
2185
|
+
}
|
|
2186
|
+
case "RDATE": {
|
|
2187
|
+
const isAllDay = params.VALUE === "DATE";
|
|
2188
|
+
const tzid = params.TZID || currentEvent.timezone;
|
|
2189
|
+
const dates = decodedValue.split(",").map((d) => {
|
|
2190
|
+
try {
|
|
2191
|
+
return parseICSDate(d.trim(), {
|
|
2192
|
+
isAllDay,
|
|
2193
|
+
tzid,
|
|
2194
|
+
defaultTimezone: options.timezone
|
|
2195
|
+
});
|
|
2196
|
+
} catch {
|
|
2197
|
+
return null;
|
|
2198
|
+
}
|
|
2199
|
+
}).filter((d) => d !== null);
|
|
2200
|
+
currentEvent.rdate = dates;
|
|
2201
|
+
break;
|
|
2202
|
+
}
|
|
2203
|
+
case "STATUS":
|
|
2204
|
+
if (!currentEvent.metadata) currentEvent.metadata = {};
|
|
2205
|
+
currentEvent.metadata.status = decodedValue.toLowerCase();
|
|
2206
|
+
break;
|
|
2207
|
+
case "PRIORITY":
|
|
2208
|
+
if (!currentEvent.metadata) currentEvent.metadata = {};
|
|
2209
|
+
currentEvent.metadata.priority = parseInt(decodedValue, 10);
|
|
2210
|
+
break;
|
|
2211
|
+
case "CATEGORIES":
|
|
2212
|
+
currentEvent.className = unescapeICSText(decodedValue);
|
|
2213
|
+
break;
|
|
2214
|
+
case "URL":
|
|
2215
|
+
if (!currentEvent.metadata) currentEvent.metadata = {};
|
|
2216
|
+
currentEvent.metadata.url = decodedValue;
|
|
2217
|
+
break;
|
|
2218
|
+
case "ORGANIZER":
|
|
2219
|
+
if (!currentEvent.metadata) currentEvent.metadata = {};
|
|
2220
|
+
currentEvent.metadata.organizer = decodedValue;
|
|
2221
|
+
break;
|
|
2222
|
+
case "ATTENDEE":
|
|
2223
|
+
if (!currentEvent.metadata) currentEvent.metadata = {};
|
|
2224
|
+
if (!currentEvent.metadata.attendees) {
|
|
2225
|
+
currentEvent.metadata.attendees = [];
|
|
2226
|
+
}
|
|
2227
|
+
currentEvent.metadata.attendees.push(decodedValue);
|
|
2228
|
+
break;
|
|
2229
|
+
}
|
|
2230
|
+
}
|
|
2231
|
+
const normalizedEvents = normalizeRecurringExceptions(events, options);
|
|
2232
|
+
resolve({
|
|
2233
|
+
events: normalizedEvents,
|
|
2234
|
+
errors,
|
|
2235
|
+
warnings,
|
|
2236
|
+
totalProcessed: normalizedEvents.length + errors.length,
|
|
2237
|
+
successCount: normalizedEvents.length,
|
|
2238
|
+
errorCount: errors.length
|
|
2239
|
+
});
|
|
2240
|
+
};
|
|
2241
|
+
if (typeof content === "string") {
|
|
2242
|
+
processContent(content);
|
|
2243
|
+
} else {
|
|
2244
|
+
readFileAsText(content, options.charset).then((text) => {
|
|
2245
|
+
processContent(text);
|
|
2246
|
+
}).catch(() => {
|
|
2247
|
+
resolve({
|
|
2248
|
+
events: [],
|
|
2249
|
+
errors: [{ message: "Failed to read file" }],
|
|
2250
|
+
warnings: [],
|
|
2251
|
+
totalProcessed: 0,
|
|
2252
|
+
successCount: 0,
|
|
2253
|
+
errorCount: 1
|
|
2254
|
+
});
|
|
2255
|
+
});
|
|
2256
|
+
}
|
|
2257
|
+
});
|
|
2258
|
+
}
|
|
2259
|
+
var DEFAULT_COLUMN_MAPPING = {
|
|
2260
|
+
id: "id",
|
|
2261
|
+
title: "title",
|
|
2262
|
+
summary: "title",
|
|
2263
|
+
name: "title",
|
|
2264
|
+
start: "start",
|
|
2265
|
+
startdate: "start",
|
|
2266
|
+
"start date": "start",
|
|
2267
|
+
starttime: "start",
|
|
2268
|
+
"start time": "start",
|
|
2269
|
+
end: "end",
|
|
2270
|
+
enddate: "end",
|
|
2271
|
+
"end date": "end",
|
|
2272
|
+
endtime: "end",
|
|
2273
|
+
"end time": "end",
|
|
2274
|
+
allday: "allDay",
|
|
2275
|
+
"all day": "allDay",
|
|
2276
|
+
color: "color",
|
|
2277
|
+
background: "color",
|
|
2278
|
+
textcolor: "textColor",
|
|
2279
|
+
"text color": "textColor",
|
|
2280
|
+
bordercolor: "borderColor",
|
|
2281
|
+
"border color": "borderColor",
|
|
2282
|
+
resource: "resourceId",
|
|
2283
|
+
resourceid: "resourceId",
|
|
2284
|
+
"resource id": "resourceId",
|
|
2285
|
+
category: "categoryId",
|
|
2286
|
+
categoryid: "categoryId",
|
|
2287
|
+
"category id": "categoryId",
|
|
2288
|
+
description: "metadata.description",
|
|
2289
|
+
location: "metadata.location",
|
|
2290
|
+
url: "metadata.url"
|
|
2291
|
+
};
|
|
2292
|
+
function parseCSVLine(line, delimiter) {
|
|
2293
|
+
const result = [];
|
|
2294
|
+
let current = "";
|
|
2295
|
+
let inQuotes = false;
|
|
2296
|
+
let i = 0;
|
|
2297
|
+
while (i < line.length) {
|
|
2298
|
+
const char = line[i];
|
|
2299
|
+
const nextChar = line[i + 1];
|
|
2300
|
+
if (inQuotes) {
|
|
2301
|
+
if (char === '"' && nextChar === '"') {
|
|
2302
|
+
current += '"';
|
|
2303
|
+
i += 2;
|
|
2304
|
+
} else if (char === '"') {
|
|
2305
|
+
inQuotes = false;
|
|
2306
|
+
i++;
|
|
2307
|
+
} else {
|
|
2308
|
+
current += char;
|
|
2309
|
+
i++;
|
|
2310
|
+
}
|
|
2311
|
+
} else {
|
|
2312
|
+
if (char === '"') {
|
|
2313
|
+
inQuotes = true;
|
|
2314
|
+
i++;
|
|
2315
|
+
} else if (char === delimiter) {
|
|
2316
|
+
result.push(current);
|
|
2317
|
+
current = "";
|
|
2318
|
+
i++;
|
|
2319
|
+
} else {
|
|
2320
|
+
current += char;
|
|
2321
|
+
i++;
|
|
2322
|
+
}
|
|
2323
|
+
}
|
|
2324
|
+
}
|
|
2325
|
+
result.push(current);
|
|
2326
|
+
return result;
|
|
2327
|
+
}
|
|
2328
|
+
function parseDate(value, dateFormat) {
|
|
2329
|
+
if (!value || value.trim() === "") return null;
|
|
2330
|
+
const isoMatch = value.match(/^\d{4}-\d{2}-\d{2}(T\d{2}:\d{2}:\d{2})?/);
|
|
2331
|
+
const format = dateFormat?.toLowerCase();
|
|
2332
|
+
if (!format || format === "iso") {
|
|
2333
|
+
if (!isoMatch && format === "iso") {
|
|
2334
|
+
return null;
|
|
2335
|
+
}
|
|
2336
|
+
const date = new Date(value);
|
|
2337
|
+
if (!isNaN(date.getTime())) return date;
|
|
2338
|
+
}
|
|
2339
|
+
const usMatch = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{2,4})(?:\s+(\d{1,2}):(\d{2})(?::(\d{2}))?(?:\s*(AM|PM))?)?/i);
|
|
2340
|
+
if ((!format || format === "us" || format === "mdy") && usMatch) {
|
|
2341
|
+
const [, month, day, year, hours = "0", minutes = "0", seconds = "0", ampm] = usMatch;
|
|
2342
|
+
let yearNum = parseInt(year, 10);
|
|
2343
|
+
if (yearNum < 100) yearNum += 2e3;
|
|
2344
|
+
let hoursNum = parseInt(hours, 10);
|
|
2345
|
+
if (ampm?.toUpperCase() === "PM" && hoursNum !== 12) hoursNum += 12;
|
|
2346
|
+
if (ampm?.toUpperCase() === "AM" && hoursNum === 12) hoursNum = 0;
|
|
2347
|
+
return new Date(yearNum, parseInt(month, 10) - 1, parseInt(day, 10), hoursNum, parseInt(minutes, 10), parseInt(seconds, 10));
|
|
2348
|
+
}
|
|
2349
|
+
const euMatch = value.match(/^(\d{1,2})\.(\d{1,2})\.(\d{2,4})(?:\s+(\d{1,2}):(\d{2})(?::(\d{2}))?)?/);
|
|
2350
|
+
if ((!format || format === "eu" || format === "dmy") && euMatch) {
|
|
2351
|
+
const [, day, month, year, hours = "0", minutes = "0", seconds = "0"] = euMatch;
|
|
2352
|
+
let yearNum = parseInt(year, 10);
|
|
2353
|
+
if (yearNum < 100) yearNum += 2e3;
|
|
2354
|
+
return new Date(yearNum, parseInt(month, 10) - 1, parseInt(day, 10), parseInt(hours, 10), parseInt(minutes, 10), parseInt(seconds, 10));
|
|
2355
|
+
}
|
|
2356
|
+
if (!format || format === "locale") {
|
|
2357
|
+
const date = new Date(value);
|
|
2358
|
+
if (!isNaN(date.getTime())) return date;
|
|
2359
|
+
}
|
|
2360
|
+
return null;
|
|
2361
|
+
}
|
|
2362
|
+
function importFromCsv(content, options = {}) {
|
|
2363
|
+
return new Promise((resolve) => {
|
|
2364
|
+
const processContent = (csvContent) => {
|
|
2365
|
+
const { delimiter = ",", hasHeaders = true, dateFormat, columnMapping = {}, skipEmptyRows = true } = options;
|
|
2366
|
+
const events = [];
|
|
2367
|
+
const errors = [];
|
|
2368
|
+
const warnings = [];
|
|
2369
|
+
const lines = csvContent.split(/\r?\n/);
|
|
2370
|
+
if (lines.length === 0) {
|
|
2371
|
+
resolve({
|
|
2372
|
+
events: [],
|
|
2373
|
+
errors: [{ message: "Empty CSV content" }],
|
|
2374
|
+
warnings: [],
|
|
2375
|
+
totalProcessed: 0,
|
|
2376
|
+
successCount: 0,
|
|
2377
|
+
errorCount: 1
|
|
2378
|
+
});
|
|
2379
|
+
return;
|
|
2380
|
+
}
|
|
2381
|
+
let headers = [];
|
|
2382
|
+
let dataStartIndex = 0;
|
|
2383
|
+
if (hasHeaders) {
|
|
2384
|
+
headers = parseCSVLine(lines[0], delimiter).map((h) => h.trim().toLowerCase());
|
|
2385
|
+
dataStartIndex = 1;
|
|
2386
|
+
}
|
|
2387
|
+
const mergedMapping = { ...DEFAULT_COLUMN_MAPPING, ...columnMapping };
|
|
2388
|
+
const fieldMapping = /* @__PURE__ */ new Map();
|
|
2389
|
+
for (let i = 0; i < headers.length; i++) {
|
|
2390
|
+
const header = headers[i];
|
|
2391
|
+
const mappedField = mergedMapping[header] || header;
|
|
2392
|
+
fieldMapping.set(i, mappedField);
|
|
2393
|
+
}
|
|
2394
|
+
for (let lineIndex = dataStartIndex; lineIndex < lines.length; lineIndex++) {
|
|
2395
|
+
const line = lines[lineIndex];
|
|
2396
|
+
if (skipEmptyRows && !line.trim()) continue;
|
|
2397
|
+
const values = parseCSVLine(line, delimiter);
|
|
2398
|
+
const event = { id: generateId() };
|
|
2399
|
+
for (let i = 0; i < values.length; i++) {
|
|
2400
|
+
const field = fieldMapping.get(i) || (hasHeaders ? headers[i] : `field_${i}`);
|
|
2401
|
+
const value = values[i]?.trim();
|
|
2402
|
+
if (!value) continue;
|
|
2403
|
+
if (field.startsWith("metadata.")) {
|
|
2404
|
+
if (!event.metadata) event.metadata = {};
|
|
2405
|
+
const propName = field.slice("metadata.".length);
|
|
2406
|
+
event.metadata[propName] = value;
|
|
2407
|
+
continue;
|
|
2408
|
+
}
|
|
2409
|
+
switch (field) {
|
|
2410
|
+
case "id":
|
|
2411
|
+
event.id = value;
|
|
2412
|
+
break;
|
|
2413
|
+
case "title":
|
|
2414
|
+
event.title = value;
|
|
2415
|
+
break;
|
|
2416
|
+
case "start": {
|
|
2417
|
+
const startDate = parseDate(value, dateFormat);
|
|
2418
|
+
if (startDate) {
|
|
2419
|
+
event.start = startDate;
|
|
2420
|
+
} else {
|
|
2421
|
+
errors.push({
|
|
2422
|
+
line: lineIndex + 1,
|
|
2423
|
+
field: "start",
|
|
2424
|
+
message: `Invalid date: ${value}`,
|
|
2425
|
+
raw: line
|
|
2426
|
+
});
|
|
2427
|
+
}
|
|
2428
|
+
break;
|
|
2429
|
+
}
|
|
2430
|
+
case "end": {
|
|
2431
|
+
const endDate = parseDate(value, dateFormat);
|
|
2432
|
+
if (endDate) {
|
|
2433
|
+
event.end = endDate;
|
|
2434
|
+
} else {
|
|
2435
|
+
warnings.push({
|
|
2436
|
+
line: lineIndex + 1,
|
|
2437
|
+
field: "end",
|
|
2438
|
+
message: `Invalid date: ${value}`,
|
|
2439
|
+
raw: line
|
|
2440
|
+
});
|
|
2441
|
+
}
|
|
2442
|
+
break;
|
|
2443
|
+
}
|
|
2444
|
+
case "allDay":
|
|
2445
|
+
event.allDay = ["true", "1", "yes"].includes(value.toLowerCase());
|
|
2446
|
+
break;
|
|
2447
|
+
case "duration":
|
|
2448
|
+
event.duration = parseInt(value, 10);
|
|
2449
|
+
break;
|
|
2450
|
+
case "color":
|
|
2451
|
+
event.color = value;
|
|
2452
|
+
break;
|
|
2453
|
+
case "textColor":
|
|
2454
|
+
event.textColor = value;
|
|
2455
|
+
break;
|
|
2456
|
+
case "borderColor":
|
|
2457
|
+
event.borderColor = value;
|
|
2458
|
+
break;
|
|
2459
|
+
case "className":
|
|
2460
|
+
event.className = value;
|
|
2461
|
+
break;
|
|
2462
|
+
case "editable":
|
|
2463
|
+
event.editable = ["true", "1", "yes"].includes(value.toLowerCase());
|
|
2464
|
+
break;
|
|
2465
|
+
case "draggable":
|
|
2466
|
+
event.draggable = ["true", "1", "yes"].includes(value.toLowerCase());
|
|
2467
|
+
break;
|
|
2468
|
+
case "resizable":
|
|
2469
|
+
event.resizable = ["true", "1", "yes"].includes(value.toLowerCase());
|
|
2470
|
+
break;
|
|
2471
|
+
case "resourceId":
|
|
2472
|
+
event.resourceId = value;
|
|
2473
|
+
break;
|
|
2474
|
+
case "resourceIds":
|
|
2475
|
+
event.resourceIds = value.split(";").map((v) => v.trim());
|
|
2476
|
+
break;
|
|
2477
|
+
case "categoryId":
|
|
2478
|
+
event.categoryId = value;
|
|
2479
|
+
break;
|
|
2480
|
+
case "categoryIds":
|
|
2481
|
+
event.categoryIds = value.split(";").map((v) => v.trim());
|
|
2482
|
+
break;
|
|
2483
|
+
case "timezone":
|
|
2484
|
+
event.timezone = value;
|
|
2485
|
+
break;
|
|
2486
|
+
case "rrule": {
|
|
2487
|
+
const parsedRRule = parseRRule(value);
|
|
2488
|
+
event.rrule = parsedRRule ?? value;
|
|
2489
|
+
break;
|
|
2490
|
+
}
|
|
2491
|
+
case "exdate":
|
|
2492
|
+
event.exdate = value.split(";").map((v) => parseDate(v.trim(), dateFormat)).filter((d) => d !== null);
|
|
2493
|
+
break;
|
|
2494
|
+
case "rdate":
|
|
2495
|
+
event.rdate = value.split(";").map((v) => parseDate(v.trim(), dateFormat)).filter((d) => d !== null);
|
|
2496
|
+
break;
|
|
2497
|
+
default:
|
|
2498
|
+
if (!event.metadata) event.metadata = {};
|
|
2499
|
+
event.metadata[field] = value;
|
|
2500
|
+
}
|
|
2501
|
+
}
|
|
2502
|
+
if (event.title && event.start) {
|
|
2503
|
+
events.push(event);
|
|
2504
|
+
} else {
|
|
2505
|
+
errors.push({
|
|
2506
|
+
line: lineIndex + 1,
|
|
2507
|
+
message: "Missing required fields (title or start)",
|
|
2508
|
+
raw: line
|
|
2509
|
+
});
|
|
2510
|
+
}
|
|
2511
|
+
}
|
|
2512
|
+
resolve({
|
|
2513
|
+
events,
|
|
2514
|
+
errors,
|
|
2515
|
+
warnings,
|
|
2516
|
+
totalProcessed: events.length + errors.length,
|
|
2517
|
+
successCount: events.length,
|
|
2518
|
+
errorCount: errors.length
|
|
2519
|
+
});
|
|
2520
|
+
};
|
|
2521
|
+
if (typeof content === "string") {
|
|
2522
|
+
processContent(content);
|
|
2523
|
+
} else {
|
|
2524
|
+
const reader = new FileReader();
|
|
2525
|
+
reader.onload = () => {
|
|
2526
|
+
processContent(reader.result);
|
|
2527
|
+
};
|
|
2528
|
+
reader.onerror = () => {
|
|
2529
|
+
resolve({
|
|
2530
|
+
events: [],
|
|
2531
|
+
errors: [{ message: "Failed to read file" }],
|
|
2532
|
+
warnings: [],
|
|
2533
|
+
totalProcessed: 0,
|
|
2534
|
+
successCount: 0,
|
|
2535
|
+
errorCount: 1
|
|
2536
|
+
});
|
|
2537
|
+
};
|
|
2538
|
+
reader.readAsText(content);
|
|
2539
|
+
}
|
|
2540
|
+
});
|
|
2541
|
+
}
|
|
2542
|
+
function convertDates(obj, dateFields) {
|
|
2543
|
+
const result = { ...obj };
|
|
2544
|
+
for (const field of dateFields) {
|
|
2545
|
+
if (result[field] && typeof result[field] === "string") {
|
|
2546
|
+
const date = new Date(result[field]);
|
|
2547
|
+
if (!isNaN(date.getTime())) {
|
|
2548
|
+
result[field] = date;
|
|
2549
|
+
}
|
|
2550
|
+
}
|
|
2551
|
+
}
|
|
2552
|
+
if (result.exdate && Array.isArray(result.exdate)) {
|
|
2553
|
+
result.exdate = result.exdate.map((d) => {
|
|
2554
|
+
const date = new Date(d);
|
|
2555
|
+
return isNaN(date.getTime()) ? d : date;
|
|
2556
|
+
});
|
|
2557
|
+
}
|
|
2558
|
+
if (result.rdate && Array.isArray(result.rdate)) {
|
|
2559
|
+
result.rdate = result.rdate.map((d) => {
|
|
2560
|
+
const date = new Date(d);
|
|
2561
|
+
return isNaN(date.getTime()) ? d : date;
|
|
2562
|
+
});
|
|
2563
|
+
}
|
|
2564
|
+
return result;
|
|
2565
|
+
}
|
|
2566
|
+
function getJsonSchemaVersion(data) {
|
|
2567
|
+
if (typeof data.schemaVersion === "string") {
|
|
2568
|
+
return data.schemaVersion;
|
|
2569
|
+
}
|
|
2570
|
+
if (typeof data.version === "string") {
|
|
2571
|
+
return data.version;
|
|
2572
|
+
}
|
|
2573
|
+
return "1.0";
|
|
2574
|
+
}
|
|
2575
|
+
function applyJsonMigrations(data, options, warnings) {
|
|
2576
|
+
const targetVersion = options.schemaVersion;
|
|
2577
|
+
const hooks = options.migrationHooks;
|
|
2578
|
+
if (!targetVersion || !hooks) {
|
|
2579
|
+
return data;
|
|
2580
|
+
}
|
|
2581
|
+
const currentVersion = getJsonSchemaVersion(data);
|
|
2582
|
+
if (currentVersion === targetVersion) {
|
|
2583
|
+
return data;
|
|
2584
|
+
}
|
|
2585
|
+
const directKey = `${currentVersion}->${targetVersion}`;
|
|
2586
|
+
const hook = hooks[directKey] || hooks[currentVersion];
|
|
2587
|
+
if (!hook) {
|
|
2588
|
+
warnings.push({
|
|
2589
|
+
field: "schemaVersion",
|
|
2590
|
+
message: `No migration hook found for ${currentVersion} to ${targetVersion}`
|
|
2591
|
+
});
|
|
2592
|
+
return data;
|
|
2593
|
+
}
|
|
2594
|
+
const migrated = hook(data);
|
|
2595
|
+
migrated.schemaVersion = targetVersion;
|
|
2596
|
+
return migrated;
|
|
2597
|
+
}
|
|
2598
|
+
function importFromJson(content, options = {}) {
|
|
2599
|
+
return new Promise((resolve) => {
|
|
2600
|
+
const processContent = (jsonContent) => {
|
|
2601
|
+
const { dateFields = ["start", "end"], validateSchema = false } = options;
|
|
2602
|
+
const events = [];
|
|
2603
|
+
const resources = [];
|
|
2604
|
+
const categories = [];
|
|
2605
|
+
const errors = [];
|
|
2606
|
+
const warnings = [];
|
|
2607
|
+
let data;
|
|
2608
|
+
try {
|
|
2609
|
+
data = JSON.parse(jsonContent);
|
|
2610
|
+
} catch (e) {
|
|
2611
|
+
resolve({
|
|
2612
|
+
events: [],
|
|
2613
|
+
errors: [{ message: `Invalid JSON: ${e.message}` }],
|
|
2614
|
+
warnings: [],
|
|
2615
|
+
totalProcessed: 0,
|
|
2616
|
+
successCount: 0,
|
|
2617
|
+
errorCount: 1
|
|
2618
|
+
});
|
|
2619
|
+
return;
|
|
2620
|
+
}
|
|
2621
|
+
let eventArray = [];
|
|
2622
|
+
if (Array.isArray(data)) {
|
|
2623
|
+
eventArray = data;
|
|
2624
|
+
} else if (typeof data === "object" && data !== null) {
|
|
2625
|
+
const obj = applyJsonMigrations(data, options, warnings);
|
|
2626
|
+
if (Array.isArray(obj.events)) {
|
|
2627
|
+
eventArray = obj.events;
|
|
2628
|
+
}
|
|
2629
|
+
if (Array.isArray(obj.resources)) {
|
|
2630
|
+
resources.push(...obj.resources);
|
|
2631
|
+
}
|
|
2632
|
+
if (Array.isArray(obj.categories)) {
|
|
2633
|
+
categories.push(...obj.categories);
|
|
2634
|
+
}
|
|
2635
|
+
}
|
|
2636
|
+
for (let i = 0; i < eventArray.length; i++) {
|
|
2637
|
+
const item = eventArray[i];
|
|
2638
|
+
if (typeof item !== "object" || item === null) {
|
|
2639
|
+
errors.push({
|
|
2640
|
+
index: i,
|
|
2641
|
+
message: "Invalid event format",
|
|
2642
|
+
raw: JSON.stringify(item)
|
|
2643
|
+
});
|
|
2644
|
+
continue;
|
|
2645
|
+
}
|
|
2646
|
+
const eventData = convertDates(item, dateFields);
|
|
2647
|
+
if (validateSchema) {
|
|
2648
|
+
if (typeof eventData.title !== "string") {
|
|
2649
|
+
errors.push({
|
|
2650
|
+
index: i,
|
|
2651
|
+
field: "title",
|
|
2652
|
+
message: 'Invalid schema: "title" must be a string',
|
|
2653
|
+
raw: JSON.stringify(item)
|
|
2654
|
+
});
|
|
2655
|
+
continue;
|
|
2656
|
+
}
|
|
2657
|
+
const startValue = eventData.start;
|
|
2658
|
+
const isValidStart = startValue instanceof Date || typeof startValue === "string" && !isNaN(new Date(startValue).getTime());
|
|
2659
|
+
if (!isValidStart) {
|
|
2660
|
+
errors.push({
|
|
2661
|
+
index: i,
|
|
2662
|
+
field: "start",
|
|
2663
|
+
message: 'Invalid schema: "start" must be a valid date value',
|
|
2664
|
+
raw: JSON.stringify(item)
|
|
2665
|
+
});
|
|
2666
|
+
continue;
|
|
2667
|
+
}
|
|
2668
|
+
if (eventData.allDay !== void 0 && typeof eventData.allDay !== "boolean") {
|
|
2669
|
+
warnings.push({
|
|
2670
|
+
index: i,
|
|
2671
|
+
field: "allDay",
|
|
2672
|
+
message: 'Schema warning: "allDay" should be a boolean',
|
|
2673
|
+
raw: JSON.stringify(item)
|
|
2674
|
+
});
|
|
2675
|
+
}
|
|
2676
|
+
}
|
|
2677
|
+
if (!eventData.title || !eventData.start) {
|
|
2678
|
+
errors.push({
|
|
2679
|
+
index: i,
|
|
2680
|
+
message: "Missing required fields (title or start)",
|
|
2681
|
+
raw: JSON.stringify(item)
|
|
2682
|
+
});
|
|
2683
|
+
continue;
|
|
2684
|
+
}
|
|
2685
|
+
if (!eventData.id) {
|
|
2686
|
+
eventData.id = generateId();
|
|
2687
|
+
}
|
|
2688
|
+
events.push(eventData);
|
|
2689
|
+
}
|
|
2690
|
+
resolve({
|
|
2691
|
+
events,
|
|
2692
|
+
resources: resources.length > 0 ? resources : void 0,
|
|
2693
|
+
categories: categories.length > 0 ? categories : void 0,
|
|
2694
|
+
errors,
|
|
2695
|
+
warnings,
|
|
2696
|
+
totalProcessed: events.length + errors.length,
|
|
2697
|
+
successCount: events.length,
|
|
2698
|
+
errorCount: errors.length
|
|
2699
|
+
});
|
|
2700
|
+
};
|
|
2701
|
+
if (typeof content === "string") {
|
|
2702
|
+
processContent(content);
|
|
2703
|
+
} else {
|
|
2704
|
+
const reader = new FileReader();
|
|
2705
|
+
reader.onload = () => {
|
|
2706
|
+
processContent(reader.result);
|
|
2707
|
+
};
|
|
2708
|
+
reader.onerror = () => {
|
|
2709
|
+
resolve({
|
|
2710
|
+
events: [],
|
|
2711
|
+
errors: [{ message: "Failed to read file" }],
|
|
2712
|
+
warnings: [],
|
|
2713
|
+
totalProcessed: 0,
|
|
2714
|
+
successCount: 0,
|
|
2715
|
+
errorCount: 1
|
|
2716
|
+
});
|
|
2717
|
+
};
|
|
2718
|
+
reader.readAsText(content);
|
|
2719
|
+
}
|
|
2720
|
+
});
|
|
2721
|
+
}
|
|
2722
|
+
function detectImportFormat(filename) {
|
|
2723
|
+
const ext = filename.toLowerCase().split(".").pop();
|
|
2724
|
+
switch (ext) {
|
|
2725
|
+
case "ics":
|
|
2726
|
+
case "ical":
|
|
2727
|
+
return "ical";
|
|
2728
|
+
case "json":
|
|
2729
|
+
return "json";
|
|
2730
|
+
case "csv":
|
|
2731
|
+
case "tsv":
|
|
2732
|
+
return "csv";
|
|
2733
|
+
default:
|
|
2734
|
+
return null;
|
|
2735
|
+
}
|
|
2736
|
+
}
|
|
2737
|
+
async function importScheduler(file, options) {
|
|
2738
|
+
const format = detectImportFormat(file.name);
|
|
2739
|
+
if (!format) {
|
|
2740
|
+
return {
|
|
2741
|
+
events: [],
|
|
2742
|
+
errors: [{ message: `Unsupported file format: ${file.name}` }],
|
|
2743
|
+
warnings: [],
|
|
2744
|
+
totalProcessed: 0,
|
|
2745
|
+
successCount: 0,
|
|
2746
|
+
errorCount: 1
|
|
2747
|
+
};
|
|
2748
|
+
}
|
|
2749
|
+
switch (format) {
|
|
2750
|
+
case "ical":
|
|
2751
|
+
return importFromIcal(file, options);
|
|
2752
|
+
case "json":
|
|
2753
|
+
return importFromJson(file, options);
|
|
2754
|
+
case "csv":
|
|
2755
|
+
return importFromCsv(file, options);
|
|
2756
|
+
}
|
|
2757
|
+
}
|
|
2758
|
+
function validateImportResult(result) {
|
|
2759
|
+
const isValid = result.successCount > 0 && result.errorCount === 0;
|
|
2760
|
+
const hasWarnings = result.warnings.length > 0;
|
|
2761
|
+
let summary = `Imported ${result.successCount} of ${result.totalProcessed} events.`;
|
|
2762
|
+
if (result.errorCount > 0) {
|
|
2763
|
+
summary += ` ${result.errorCount} errors.`;
|
|
2764
|
+
}
|
|
2765
|
+
if (hasWarnings) {
|
|
2766
|
+
summary += ` ${result.warnings.length} warnings.`;
|
|
2767
|
+
}
|
|
2768
|
+
return { isValid, summary };
|
|
2769
|
+
}
|
|
2770
|
+
function toDateValue(value) {
|
|
2771
|
+
if (!value) return null;
|
|
2772
|
+
const date = value instanceof Date ? value : new Date(value);
|
|
2773
|
+
return isNaN(date.getTime()) ? null : date;
|
|
2774
|
+
}
|
|
2775
|
+
function getEventEnd(event) {
|
|
2776
|
+
const start = toDateValue(event.start);
|
|
2777
|
+
if (!start) return null;
|
|
2778
|
+
const end = toDateValue(event.end);
|
|
2779
|
+
if (end) {
|
|
2780
|
+
return end;
|
|
2781
|
+
}
|
|
2782
|
+
if (typeof event.duration === "number" && event.duration > 0) {
|
|
2783
|
+
return new Date(start.getTime() + event.duration * 60 * 1e3);
|
|
2784
|
+
}
|
|
2785
|
+
if (event.allDay) {
|
|
2786
|
+
const endOfDay2 = new Date(start);
|
|
2787
|
+
endOfDay2.setHours(23, 59, 59, 999);
|
|
2788
|
+
return endOfDay2;
|
|
2789
|
+
}
|
|
2790
|
+
return new Date(start.getTime() + 60 * 60 * 1e3);
|
|
2791
|
+
}
|
|
2792
|
+
function eventsOverlap(a, b) {
|
|
2793
|
+
const aStart = toDateValue(a.start);
|
|
2794
|
+
const aEnd = getEventEnd(a);
|
|
2795
|
+
const bStart = toDateValue(b.start);
|
|
2796
|
+
const bEnd = getEventEnd(b);
|
|
2797
|
+
if (!aStart || !aEnd || !bStart || !bEnd) {
|
|
2798
|
+
return false;
|
|
2799
|
+
}
|
|
2800
|
+
return aStart < bEnd && aEnd > bStart;
|
|
2801
|
+
}
|
|
2802
|
+
function getEventMatchKey(event) {
|
|
2803
|
+
const uid = event.metadata?.uid;
|
|
2804
|
+
if (typeof uid === "string" && uid.trim().length > 0) {
|
|
2805
|
+
return `uid:${uid.trim()}`;
|
|
2806
|
+
}
|
|
2807
|
+
return `id:${String(event.id)}`;
|
|
2808
|
+
}
|
|
2809
|
+
function buildReportFromIssues(issues) {
|
|
2810
|
+
const errors = issues.filter((issue) => issue.severity === "error").length;
|
|
2811
|
+
const warnings = issues.filter((issue) => issue.severity === "warning").length;
|
|
2812
|
+
const infos = issues.filter((issue) => issue.severity === "info").length;
|
|
2813
|
+
return {
|
|
2814
|
+
summary: {
|
|
2815
|
+
errors,
|
|
2816
|
+
warnings,
|
|
2817
|
+
infos,
|
|
2818
|
+
total: issues.length,
|
|
2819
|
+
hasBlockingIssues: errors > 0
|
|
2820
|
+
},
|
|
2821
|
+
issues
|
|
2822
|
+
};
|
|
2823
|
+
}
|
|
2824
|
+
function defaultConflictPolicy(policy) {
|
|
2825
|
+
return {
|
|
2826
|
+
mode: policy?.mode ?? "warn",
|
|
2827
|
+
checkOverlap: policy?.checkOverlap ?? true,
|
|
2828
|
+
checkResourceConstraints: policy?.checkResourceConstraints ?? true,
|
|
2829
|
+
checkBusinessHours: policy?.checkBusinessHours ?? true
|
|
2830
|
+
};
|
|
2831
|
+
}
|
|
2832
|
+
function deriveRange(events) {
|
|
2833
|
+
if (events.length === 0) {
|
|
2834
|
+
return null;
|
|
2835
|
+
}
|
|
2836
|
+
let minStart = null;
|
|
2837
|
+
let maxEnd = null;
|
|
2838
|
+
for (const event of events) {
|
|
2839
|
+
const start = toDateValue(event.start);
|
|
2840
|
+
const end = getEventEnd(event);
|
|
2841
|
+
if (!start || !end) continue;
|
|
2842
|
+
if (!minStart || start < minStart) {
|
|
2843
|
+
minStart = start;
|
|
2844
|
+
}
|
|
2845
|
+
if (!maxEnd || end > maxEnd) {
|
|
2846
|
+
maxEnd = end;
|
|
2847
|
+
}
|
|
2848
|
+
}
|
|
2849
|
+
if (!minStart || !maxEnd) {
|
|
2850
|
+
return null;
|
|
2851
|
+
}
|
|
2852
|
+
return { start: minStart, end: maxEnd };
|
|
2853
|
+
}
|
|
2854
|
+
function mapResourcesAndCategories(importedEvents, options, issues) {
|
|
2855
|
+
const createdResources = /* @__PURE__ */ new Map();
|
|
2856
|
+
const createdCategories = /* @__PURE__ */ new Map();
|
|
2857
|
+
const resourceMap = options.resourceMapping ?? {};
|
|
2858
|
+
const categoryMap = options.categoryMapping ?? {};
|
|
2859
|
+
const existingResourceIds = new Set((options.existingResources ?? []).map((resource) => String(resource.id)));
|
|
2860
|
+
const existingCategoryIds = new Set((options.existingCategories ?? []).map((category) => String(category.id)));
|
|
2861
|
+
const mapSingleId = (id, mapping, existingIds, createMissing, kind, titleFactory) => {
|
|
2862
|
+
if (id === void 0 || id === null) return id;
|
|
2863
|
+
const key = String(id);
|
|
2864
|
+
const mapped = mapping[key];
|
|
2865
|
+
if (mapped !== void 0) {
|
|
2866
|
+
return mapped;
|
|
2867
|
+
}
|
|
2868
|
+
if (existingIds.has(key)) {
|
|
2869
|
+
return id;
|
|
2870
|
+
}
|
|
2871
|
+
if (!createMissing) {
|
|
2872
|
+
issues.push({
|
|
2873
|
+
severity: "warning",
|
|
2874
|
+
code: `${kind}_mapping_missing`,
|
|
2875
|
+
message: `Imported ${kind} "${key}" was not mapped to an existing ${kind}.`,
|
|
2876
|
+
fix: `Map "${key}" to an existing ${kind} or enable create-missing mode.`
|
|
2877
|
+
});
|
|
2878
|
+
return id;
|
|
2879
|
+
}
|
|
2880
|
+
if (kind === "resource") {
|
|
2881
|
+
if (!createdResources.has(key)) {
|
|
2882
|
+
createdResources.set(key, {
|
|
2883
|
+
id: key,
|
|
2884
|
+
title: titleFactory(key)
|
|
2885
|
+
});
|
|
2886
|
+
}
|
|
2887
|
+
} else {
|
|
2888
|
+
if (!createdCategories.has(key)) {
|
|
2889
|
+
createdCategories.set(key, {
|
|
2890
|
+
id: key,
|
|
2891
|
+
name: titleFactory(key),
|
|
2892
|
+
color: "#6b7280"
|
|
2893
|
+
});
|
|
2894
|
+
}
|
|
2895
|
+
}
|
|
2896
|
+
existingIds.add(key);
|
|
2897
|
+
return key;
|
|
2898
|
+
};
|
|
2899
|
+
const mappedEvents = importedEvents.map((event) => {
|
|
2900
|
+
const mappedResourceId = mapSingleId(event.resourceId, resourceMap, existingResourceIds, options.createMissingResources === true, "resource", (idValue) => `Resource ${idValue}`);
|
|
2901
|
+
const mappedCategoryId = mapSingleId(event.categoryId, categoryMap, existingCategoryIds, options.createMissingCategories === true, "category", (idValue) => `Category ${idValue}`);
|
|
2902
|
+
const mappedResourceIds = event.resourceIds?.map((id) => mapSingleId(id, resourceMap, existingResourceIds, options.createMissingResources === true, "resource", (idValue) => `Resource ${idValue}`)) ?? event.resourceIds;
|
|
2903
|
+
const mappedCategoryIds = event.categoryIds?.map((id) => mapSingleId(id, categoryMap, existingCategoryIds, options.createMissingCategories === true, "category", (idValue) => `Category ${idValue}`)) ?? event.categoryIds;
|
|
2904
|
+
return {
|
|
2905
|
+
...event,
|
|
2906
|
+
resourceId: mappedResourceId,
|
|
2907
|
+
resourceIds: mappedResourceIds?.filter((id) => id !== void 0),
|
|
2908
|
+
categoryId: mappedCategoryId,
|
|
2909
|
+
categoryIds: mappedCategoryIds?.filter((id) => id !== void 0)
|
|
2910
|
+
};
|
|
2911
|
+
});
|
|
2912
|
+
return {
|
|
2913
|
+
events: mappedEvents,
|
|
2914
|
+
createdResources: Array.from(createdResources.values()),
|
|
2915
|
+
createdCategories: Array.from(createdCategories.values())
|
|
2916
|
+
};
|
|
2917
|
+
}
|
|
2918
|
+
function evaluateConflictsForEvent(candidate, baseline, resources, policy, businessHours) {
|
|
2919
|
+
const issues = [];
|
|
2920
|
+
const severity = policy.mode === "reject" ? "error" : "warning";
|
|
2921
|
+
if (policy.checkOverlap) {
|
|
2922
|
+
const overlapTarget = baseline.find((existing) => {
|
|
2923
|
+
const sameResource = candidate.resourceId !== void 0 || existing.resourceId !== void 0 ? String(candidate.resourceId ?? "") === String(existing.resourceId ?? "") : true;
|
|
2924
|
+
return sameResource && eventsOverlap(candidate, existing);
|
|
2925
|
+
});
|
|
2926
|
+
if (overlapTarget) {
|
|
2927
|
+
issues.push({
|
|
2928
|
+
severity,
|
|
2929
|
+
code: "event_overlap",
|
|
2930
|
+
message: `Event "${candidate.title}" overlaps with "${overlapTarget.title}".`,
|
|
2931
|
+
fix: "Adjust start/end time, or set conflict policy to allow overlaps.",
|
|
2932
|
+
eventId: candidate.id
|
|
2933
|
+
});
|
|
2934
|
+
}
|
|
2935
|
+
}
|
|
2936
|
+
if (policy.checkBusinessHours && businessHours) {
|
|
2937
|
+
const start = toDateValue(candidate.start);
|
|
2938
|
+
const end = getEventEnd(candidate);
|
|
2939
|
+
if (start && end && !isRangeWithinBusinessHours(start, end, businessHours)) {
|
|
2940
|
+
issues.push({
|
|
2941
|
+
severity,
|
|
2942
|
+
code: "outside_business_hours",
|
|
2943
|
+
message: `Event "${candidate.title}" falls outside configured business hours.`,
|
|
2944
|
+
fix: "Adjust event time or update business hours policy.",
|
|
2945
|
+
eventId: candidate.id
|
|
2946
|
+
});
|
|
2947
|
+
}
|
|
2948
|
+
}
|
|
2949
|
+
if (policy.checkResourceConstraints && candidate.resourceId !== void 0) {
|
|
2950
|
+
const resource = resources.find((item) => String(item.id) === String(candidate.resourceId));
|
|
2951
|
+
if (resource) {
|
|
2952
|
+
const result = canDropEventWithResourceConstraints(candidate, resource, baseline, {
|
|
2953
|
+
enabled: true,
|
|
2954
|
+
mode: policy.mode === "reject" ? "prevent" : "warn",
|
|
2955
|
+
checkCapacity: true,
|
|
2956
|
+
checkOverlap: true,
|
|
2957
|
+
checkAvailability: true,
|
|
2958
|
+
checkDailyHours: true,
|
|
2959
|
+
checkEventDuration: true
|
|
2960
|
+
});
|
|
2961
|
+
for (const conflict of result.conflicts) {
|
|
2962
|
+
issues.push({
|
|
2963
|
+
severity: conflict.severity === "error" && policy.mode === "reject" ? "error" : "warning",
|
|
2964
|
+
code: `resource_${conflict.type}`,
|
|
2965
|
+
message: conflict.message,
|
|
2966
|
+
fix: "Review resource capacity/availability constraints.",
|
|
2967
|
+
eventId: candidate.id,
|
|
2968
|
+
resourceId: conflict.resourceId
|
|
2969
|
+
});
|
|
2970
|
+
}
|
|
2971
|
+
}
|
|
2972
|
+
}
|
|
2973
|
+
return issues;
|
|
2974
|
+
}
|
|
2975
|
+
function buildImportValidationReport(result, additionalIssues = []) {
|
|
2976
|
+
const issues = [];
|
|
2977
|
+
for (const error of result.errors) {
|
|
2978
|
+
issues.push({
|
|
2979
|
+
severity: "error",
|
|
2980
|
+
code: "import_error",
|
|
2981
|
+
message: error.message,
|
|
2982
|
+
fix: error.field ? `Fix field "${error.field}" in the import file.` : "Fix malformed rows in the import file and retry.",
|
|
2983
|
+
line: error.line,
|
|
2984
|
+
index: error.index,
|
|
2985
|
+
field: error.field,
|
|
2986
|
+
raw: error.raw
|
|
2987
|
+
});
|
|
2988
|
+
}
|
|
2989
|
+
for (const warning of result.warnings) {
|
|
2990
|
+
issues.push({
|
|
2991
|
+
severity: "warning",
|
|
2992
|
+
code: "import_warning",
|
|
2993
|
+
message: warning.message,
|
|
2994
|
+
fix: warning.field ? `Review field "${warning.field}" for this row.` : "Review warning details before applying import.",
|
|
2995
|
+
line: warning.line,
|
|
2996
|
+
index: warning.index,
|
|
2997
|
+
field: warning.field,
|
|
2998
|
+
raw: warning.raw
|
|
2999
|
+
});
|
|
3000
|
+
}
|
|
3001
|
+
const seenUid = /* @__PURE__ */ new Set();
|
|
3002
|
+
for (const event of result.events) {
|
|
3003
|
+
const key = getEventMatchKey(event);
|
|
3004
|
+
if (key.startsWith("uid:")) {
|
|
3005
|
+
if (seenUid.has(key)) {
|
|
3006
|
+
issues.push({
|
|
3007
|
+
severity: "warning",
|
|
3008
|
+
code: "duplicate_uid",
|
|
3009
|
+
message: `Duplicate UID detected for imported event "${event.title}".`,
|
|
3010
|
+
fix: "Prefer upsert-by-uid merge strategy, or normalize source UIDs.",
|
|
3011
|
+
eventId: event.id
|
|
3012
|
+
});
|
|
3013
|
+
} else {
|
|
3014
|
+
seenUid.add(key);
|
|
3015
|
+
}
|
|
3016
|
+
}
|
|
3017
|
+
}
|
|
3018
|
+
issues.push(...additionalIssues);
|
|
3019
|
+
return buildReportFromIssues(issues);
|
|
3020
|
+
}
|
|
3021
|
+
function previewImportMerge(existingEvents, importedEvents, options = {}) {
|
|
3022
|
+
const strategy = options.strategy ?? "append";
|
|
3023
|
+
const dryRun = options.dryRun ?? true;
|
|
3024
|
+
const policy = defaultConflictPolicy(options.conflictPolicy);
|
|
3025
|
+
const validationIssues = [];
|
|
3026
|
+
const resources = [...options.existingResources ?? []];
|
|
3027
|
+
const mappingResult = mapResourcesAndCategories(importedEvents, options, validationIssues);
|
|
3028
|
+
const normalizedImported = mappingResult.events;
|
|
3029
|
+
resources.push(...mappingResult.createdResources);
|
|
3030
|
+
const additions = [];
|
|
3031
|
+
const updates = [];
|
|
3032
|
+
const removals = [];
|
|
3033
|
+
const skipped = [];
|
|
3034
|
+
let mergedEvents = [...existingEvents];
|
|
3035
|
+
const attemptApply = (candidate, updateIndex, updateBefore) => {
|
|
3036
|
+
const baseline = [...mergedEvents];
|
|
3037
|
+
if (updateIndex !== void 0) {
|
|
3038
|
+
baseline.splice(updateIndex, 1);
|
|
3039
|
+
}
|
|
3040
|
+
const conflictIssues = evaluateConflictsForEvent(candidate, baseline, resources, policy, options.businessHours);
|
|
3041
|
+
if (conflictIssues.length > 0) {
|
|
3042
|
+
validationIssues.push(...conflictIssues);
|
|
3043
|
+
}
|
|
3044
|
+
const hasBlockingConflict = conflictIssues.some((issue) => issue.severity === "error");
|
|
3045
|
+
if (policy.mode === "reject" && hasBlockingConflict) {
|
|
3046
|
+
skipped.push(candidate);
|
|
3047
|
+
return;
|
|
3048
|
+
}
|
|
3049
|
+
if (updateIndex !== void 0 && updateBefore) {
|
|
3050
|
+
mergedEvents[updateIndex] = candidate;
|
|
3051
|
+
updates.push({
|
|
3052
|
+
before: updateBefore,
|
|
3053
|
+
after: candidate,
|
|
3054
|
+
matchKey: getEventMatchKey(candidate)
|
|
3055
|
+
});
|
|
3056
|
+
} else {
|
|
3057
|
+
mergedEvents.push(candidate);
|
|
3058
|
+
additions.push(candidate);
|
|
3059
|
+
}
|
|
3060
|
+
};
|
|
3061
|
+
if (strategy === "append") {
|
|
3062
|
+
for (const event of normalizedImported) {
|
|
3063
|
+
attemptApply(event);
|
|
3064
|
+
}
|
|
3065
|
+
} else if (strategy === "upsert-by-uid") {
|
|
3066
|
+
for (const event of normalizedImported) {
|
|
3067
|
+
const key = getEventMatchKey(event);
|
|
3068
|
+
const updateIndex = mergedEvents.findIndex((existing) => getEventMatchKey(existing) === key);
|
|
3069
|
+
if (updateIndex >= 0) {
|
|
3070
|
+
const before = mergedEvents[updateIndex];
|
|
3071
|
+
attemptApply(event, updateIndex, before);
|
|
3072
|
+
} else {
|
|
3073
|
+
attemptApply(event);
|
|
3074
|
+
}
|
|
3075
|
+
}
|
|
3076
|
+
} else {
|
|
3077
|
+
const range = options.range ?? deriveRange(normalizedImported);
|
|
3078
|
+
if (range) {
|
|
3079
|
+
const remaining = [];
|
|
3080
|
+
for (const existing of mergedEvents) {
|
|
3081
|
+
const start = toDateValue(existing.start);
|
|
3082
|
+
const end = getEventEnd(existing);
|
|
3083
|
+
if (!start || !end) {
|
|
3084
|
+
remaining.push(existing);
|
|
3085
|
+
continue;
|
|
3086
|
+
}
|
|
3087
|
+
const intersects = start <= range.end && end >= range.start;
|
|
3088
|
+
if (intersects) {
|
|
3089
|
+
removals.push(existing);
|
|
3090
|
+
} else {
|
|
3091
|
+
remaining.push(existing);
|
|
3092
|
+
}
|
|
3093
|
+
}
|
|
3094
|
+
mergedEvents = remaining;
|
|
3095
|
+
}
|
|
3096
|
+
for (const event of normalizedImported) {
|
|
3097
|
+
attemptApply(event);
|
|
3098
|
+
}
|
|
3099
|
+
}
|
|
3100
|
+
return {
|
|
3101
|
+
strategy,
|
|
3102
|
+
dryRun,
|
|
3103
|
+
mergedEvents,
|
|
3104
|
+
additions,
|
|
3105
|
+
updates,
|
|
3106
|
+
removals,
|
|
3107
|
+
skipped,
|
|
3108
|
+
createdResources: mappingResult.createdResources.length > 0 ? mappingResult.createdResources : void 0,
|
|
3109
|
+
createdCategories: mappingResult.createdCategories.length > 0 ? mappingResult.createdCategories : void 0,
|
|
3110
|
+
validation: buildReportFromIssues(validationIssues)
|
|
3111
|
+
};
|
|
3112
|
+
}
|
|
3113
|
+
function applyImportMerge(existingEvents, importedEvents, options = {}) {
|
|
3114
|
+
const preview = previewImportMerge(existingEvents, importedEvents, {
|
|
3115
|
+
...options,
|
|
3116
|
+
dryRun: false
|
|
3117
|
+
});
|
|
3118
|
+
return preview.mergedEvents;
|
|
3119
|
+
}
|
|
3120
|
+
|
|
3121
|
+
// src/utils/adaptive-rendering.ts
|
|
3122
|
+
var DENSITY_CONFIGS = {
|
|
3123
|
+
minimal: {
|
|
3124
|
+
rowHeight: 18,
|
|
3125
|
+
fontSize: 10,
|
|
3126
|
+
padding: 1,
|
|
3127
|
+
eventHeight: 16,
|
|
3128
|
+
lineHeight: 1.1
|
|
3129
|
+
},
|
|
3130
|
+
compact: {
|
|
3131
|
+
rowHeight: 24,
|
|
3132
|
+
fontSize: 12,
|
|
3133
|
+
padding: 2,
|
|
3134
|
+
eventHeight: 20,
|
|
3135
|
+
lineHeight: 1.2
|
|
3136
|
+
},
|
|
3137
|
+
standard: {
|
|
3138
|
+
rowHeight: 32,
|
|
3139
|
+
fontSize: 14,
|
|
3140
|
+
padding: 4,
|
|
3141
|
+
eventHeight: 26,
|
|
3142
|
+
lineHeight: 1.4
|
|
3143
|
+
},
|
|
3144
|
+
comfortable: {
|
|
3145
|
+
rowHeight: 48,
|
|
3146
|
+
fontSize: 16,
|
|
3147
|
+
padding: 8,
|
|
3148
|
+
eventHeight: 36,
|
|
3149
|
+
lineHeight: 1.5
|
|
3150
|
+
}
|
|
3151
|
+
};
|
|
3152
|
+
var DEFAULT_AUTO_HEIGHT_OPTIONS = {
|
|
3153
|
+
enabled: false,
|
|
3154
|
+
minHeight: 80,
|
|
3155
|
+
maxHeight: 400,
|
|
3156
|
+
eventMinHeight: 20,
|
|
3157
|
+
maxEventsVisible: 10,
|
|
3158
|
+
animateResize: true,
|
|
3159
|
+
animationDuration: 200
|
|
3160
|
+
};
|
|
3161
|
+
var DEFAULT_STACKING_OPTIONS = {
|
|
3162
|
+
mode: "stack",
|
|
3163
|
+
maxStack: 4,
|
|
3164
|
+
overflowMode: "more-link",
|
|
3165
|
+
moreText: (count) => `+${count} more`,
|
|
3166
|
+
scrollHeight: 200,
|
|
3167
|
+
showOverflowIndicator: true
|
|
3168
|
+
};
|
|
3169
|
+
var DEFAULT_ADAPTIVE_OPTIONS = {
|
|
3170
|
+
density: "standard",
|
|
3171
|
+
autoHeight: false,
|
|
3172
|
+
stacking: DEFAULT_STACKING_OPTIONS,
|
|
3173
|
+
responsiveBreakpoints: {
|
|
3174
|
+
compact: 600,
|
|
3175
|
+
comfortable: 1200
|
|
3176
|
+
},
|
|
3177
|
+
autoAdapt: false
|
|
3178
|
+
};
|
|
3179
|
+
function normalizeAutoHeightOptions(options) {
|
|
3180
|
+
if (options === void 0 || options === false) {
|
|
3181
|
+
return { ...DEFAULT_AUTO_HEIGHT_OPTIONS, enabled: false };
|
|
3182
|
+
}
|
|
3183
|
+
if (options === true) {
|
|
3184
|
+
return { ...DEFAULT_AUTO_HEIGHT_OPTIONS, enabled: true };
|
|
3185
|
+
}
|
|
3186
|
+
return {
|
|
3187
|
+
...DEFAULT_AUTO_HEIGHT_OPTIONS,
|
|
3188
|
+
...options,
|
|
3189
|
+
enabled: options.enabled ?? true
|
|
3190
|
+
};
|
|
3191
|
+
}
|
|
3192
|
+
function normalizeStackingOptions(options) {
|
|
3193
|
+
if (!options) {
|
|
3194
|
+
return { ...DEFAULT_STACKING_OPTIONS };
|
|
3195
|
+
}
|
|
3196
|
+
return {
|
|
3197
|
+
...DEFAULT_STACKING_OPTIONS,
|
|
3198
|
+
...options
|
|
3199
|
+
};
|
|
3200
|
+
}
|
|
3201
|
+
function normalizeAdaptiveOptions(options) {
|
|
3202
|
+
if (!options) {
|
|
3203
|
+
return { ...DEFAULT_ADAPTIVE_OPTIONS };
|
|
3204
|
+
}
|
|
3205
|
+
return {
|
|
3206
|
+
density: options.density ?? DEFAULT_ADAPTIVE_OPTIONS.density,
|
|
3207
|
+
autoHeight: normalizeAutoHeightOptions(options.autoHeight),
|
|
3208
|
+
stacking: normalizeStackingOptions(options.stacking),
|
|
3209
|
+
responsiveBreakpoints: {
|
|
3210
|
+
...DEFAULT_ADAPTIVE_OPTIONS.responsiveBreakpoints,
|
|
3211
|
+
...options.responsiveBreakpoints
|
|
3212
|
+
},
|
|
3213
|
+
autoAdapt: options.autoAdapt ?? DEFAULT_ADAPTIVE_OPTIONS.autoAdapt
|
|
3214
|
+
};
|
|
3215
|
+
}
|
|
3216
|
+
function getDensityConfig(density) {
|
|
3217
|
+
return DENSITY_CONFIGS[density] ?? DENSITY_CONFIGS.standard;
|
|
3218
|
+
}
|
|
3219
|
+
function getDensityCSSVars(density) {
|
|
3220
|
+
const config = getDensityConfig(density);
|
|
3221
|
+
return {
|
|
3222
|
+
"--p-scheduler-density-row-height": `${config.rowHeight}px`,
|
|
3223
|
+
"--p-scheduler-density-font-size": `${config.fontSize}px`,
|
|
3224
|
+
"--p-scheduler-density-padding": `${config.padding}px`,
|
|
3225
|
+
"--p-scheduler-density-event-height": `${config.eventHeight}px`,
|
|
3226
|
+
"--p-scheduler-density-line-height": String(config.lineHeight)
|
|
3227
|
+
};
|
|
3228
|
+
}
|
|
3229
|
+
function getDensityFromContainerWidth(width, breakpoints) {
|
|
3230
|
+
const compactBreakpoint = breakpoints.compact ?? 600;
|
|
3231
|
+
const comfortableBreakpoint = breakpoints.comfortable ?? 1200;
|
|
3232
|
+
if (width <= compactBreakpoint) {
|
|
3233
|
+
return "compact";
|
|
3234
|
+
}
|
|
3235
|
+
if (width >= comfortableBreakpoint) {
|
|
3236
|
+
return "comfortable";
|
|
3237
|
+
}
|
|
3238
|
+
return "standard";
|
|
3239
|
+
}
|
|
3240
|
+
function calculateAutoHeight(events, options, densityConfig) {
|
|
3241
|
+
if (!options.enabled) {
|
|
3242
|
+
return densityConfig.rowHeight;
|
|
3243
|
+
}
|
|
3244
|
+
const eventCount = events.length;
|
|
3245
|
+
const headerHeight = 28;
|
|
3246
|
+
const eventHeight = Math.max(densityConfig.eventHeight, options.eventMinHeight);
|
|
3247
|
+
const eventSpacing = densityConfig.padding;
|
|
3248
|
+
const visibleCount = Math.min(eventCount, options.maxEventsVisible);
|
|
3249
|
+
const eventsHeight = visibleCount * (eventHeight + eventSpacing);
|
|
3250
|
+
const hasOverflow = eventCount > options.maxEventsVisible;
|
|
3251
|
+
const overflowHeight = hasOverflow ? 20 : 0;
|
|
3252
|
+
const calculatedHeight = headerHeight + eventsHeight + overflowHeight + densityConfig.padding * 2;
|
|
3253
|
+
return Math.max(options.minHeight, Math.min(options.maxHeight, calculatedHeight));
|
|
3254
|
+
}
|
|
3255
|
+
function getVisibleEvents(events, stackingOptions, autoHeightOptions) {
|
|
3256
|
+
const maxVisible = autoHeightOptions.enabled ? autoHeightOptions.maxEventsVisible : stackingOptions.maxStack;
|
|
3257
|
+
if (stackingOptions.mode === "expand" || events.length <= maxVisible) {
|
|
3258
|
+
return { visible: events, overflow: [] };
|
|
3259
|
+
}
|
|
3260
|
+
if (stackingOptions.mode === "collapse") {
|
|
3261
|
+
return {
|
|
3262
|
+
visible: events.slice(0, 1),
|
|
3263
|
+
overflow: events.slice(1)
|
|
3264
|
+
};
|
|
3265
|
+
}
|
|
3266
|
+
const visibleCount = Math.max(0, maxVisible - (events.length > maxVisible ? 1 : 0));
|
|
3267
|
+
return {
|
|
3268
|
+
visible: events.slice(0, visibleCount),
|
|
3269
|
+
overflow: events.slice(visibleCount)
|
|
3270
|
+
};
|
|
3271
|
+
}
|
|
3272
|
+
function getMoreText(count, moreText) {
|
|
3273
|
+
if (typeof moreText === "function") {
|
|
3274
|
+
return moreText(count);
|
|
3275
|
+
}
|
|
3276
|
+
return moreText.replace("{count}", String(count));
|
|
3277
|
+
}
|
|
3278
|
+
function getStackedEventStyle(index, totalVisible, density, isStacked) {
|
|
3279
|
+
const config = getDensityConfig(density);
|
|
3280
|
+
if (!isStacked) {
|
|
3281
|
+
return {
|
|
3282
|
+
height: `${config.eventHeight}px`,
|
|
3283
|
+
marginBottom: `${config.padding}px`
|
|
3284
|
+
};
|
|
3285
|
+
}
|
|
3286
|
+
const stackOffset = 2;
|
|
3287
|
+
const zIndex = totalVisible - index;
|
|
3288
|
+
return {
|
|
3289
|
+
height: `${config.eventHeight}px`,
|
|
3290
|
+
marginTop: index === 0 ? "0" : `-${config.eventHeight - stackOffset}px`,
|
|
3291
|
+
zIndex: String(zIndex),
|
|
3292
|
+
position: "relative"
|
|
3293
|
+
};
|
|
3294
|
+
}
|
|
3295
|
+
function calculateCellRenderingInfo(date, events, options) {
|
|
3296
|
+
const autoHeightOptions = normalizeAutoHeightOptions(options.autoHeight);
|
|
3297
|
+
const stackingOptions = normalizeStackingOptions(options.stacking);
|
|
3298
|
+
const densityConfig = getDensityConfig(options.density);
|
|
3299
|
+
const { visible, overflow } = getVisibleEvents(events, stackingOptions, autoHeightOptions);
|
|
3300
|
+
const rowHeight = calculateAutoHeight(events, autoHeightOptions, densityConfig);
|
|
3301
|
+
return {
|
|
3302
|
+
date,
|
|
3303
|
+
events,
|
|
3304
|
+
visibleEvents: visible,
|
|
3305
|
+
overflowEvents: overflow,
|
|
3306
|
+
overflowCount: overflow.length,
|
|
3307
|
+
rowHeight,
|
|
3308
|
+
isExpanded: stackingOptions.mode === "expand",
|
|
3309
|
+
stackingMode: stackingOptions.mode
|
|
3310
|
+
};
|
|
3311
|
+
}
|
|
3312
|
+
function createAdaptiveRenderingState(containerWidth, containerHeight, events, options) {
|
|
3313
|
+
const autoHeightOptions = normalizeAutoHeightOptions(options.autoHeight);
|
|
3314
|
+
const stackingOptions = normalizeStackingOptions(options.stacking);
|
|
3315
|
+
let effectiveDensity = options.density;
|
|
3316
|
+
if (options.autoAdapt) {
|
|
3317
|
+
effectiveDensity = getDensityFromContainerWidth(containerWidth, options.responsiveBreakpoints);
|
|
3318
|
+
}
|
|
3319
|
+
const densityConfig = getDensityConfig(effectiveDensity);
|
|
3320
|
+
const { visible, overflow } = getVisibleEvents(events, stackingOptions, autoHeightOptions);
|
|
3321
|
+
const effectiveRowHeight = calculateAutoHeight(events, autoHeightOptions, densityConfig);
|
|
3322
|
+
return {
|
|
3323
|
+
effectiveDensity,
|
|
3324
|
+
effectiveRowHeight,
|
|
3325
|
+
visibleEventCount: visible.length,
|
|
3326
|
+
overflowCount: overflow.length,
|
|
3327
|
+
isAutoHeight: autoHeightOptions.enabled,
|
|
3328
|
+
containerWidth,
|
|
3329
|
+
containerHeight
|
|
3330
|
+
};
|
|
3331
|
+
}
|
|
3332
|
+
function getDensityClasses(density) {
|
|
3333
|
+
const classMap = {
|
|
3334
|
+
minimal: "p-scheduler-density-minimal",
|
|
3335
|
+
compact: "p-scheduler-density-compact",
|
|
3336
|
+
standard: "p-scheduler-density-standard",
|
|
3337
|
+
comfortable: "p-scheduler-density-comfortable"
|
|
3338
|
+
};
|
|
3339
|
+
return classMap[density] ?? classMap.standard;
|
|
3340
|
+
}
|
|
3341
|
+
function getStackingClasses(mode) {
|
|
3342
|
+
const classMap = {
|
|
3343
|
+
stack: "p-scheduler-stacking-stack",
|
|
3344
|
+
expand: "p-scheduler-stacking-expand",
|
|
3345
|
+
collapse: "p-scheduler-stacking-collapse"
|
|
3346
|
+
};
|
|
3347
|
+
return classMap[mode] ?? classMap.stack;
|
|
3348
|
+
}
|
|
3349
|
+
function getAutoHeightClasses(options, isExpanded) {
|
|
3350
|
+
const classes = [];
|
|
3351
|
+
if (options.enabled) {
|
|
3352
|
+
classes.push("p-scheduler-auto-height");
|
|
3353
|
+
if (options.animateResize) {
|
|
3354
|
+
classes.push("p-scheduler-auto-height-animated");
|
|
3355
|
+
}
|
|
3356
|
+
classes.push(isExpanded ? "p-scheduler-auto-height-expanded" : "p-scheduler-auto-height-collapsed");
|
|
3357
|
+
}
|
|
3358
|
+
return classes;
|
|
3359
|
+
}
|
|
3360
|
+
function getEventDensityClasses(density) {
|
|
3361
|
+
const classes = [];
|
|
3362
|
+
if (density === "compact") {
|
|
3363
|
+
classes.push("p-scheduler-event-compact");
|
|
3364
|
+
} else if (density === "comfortable") {
|
|
3365
|
+
classes.push("p-scheduler-event-comfortable");
|
|
3366
|
+
}
|
|
3367
|
+
return classes;
|
|
3368
|
+
}
|
|
3369
|
+
function calculateWeekViewAutoHeight(dayEvents, options) {
|
|
3370
|
+
const autoHeightOptions = normalizeAutoHeightOptions(options.autoHeight);
|
|
3371
|
+
if (!autoHeightOptions.enabled) {
|
|
3372
|
+
return 0;
|
|
3373
|
+
}
|
|
3374
|
+
const densityConfig = getDensityConfig(options.density);
|
|
3375
|
+
let maxHeight = autoHeightOptions.minHeight;
|
|
3376
|
+
for (const events of dayEvents.values()) {
|
|
3377
|
+
const cellHeight = calculateAutoHeight(events, autoHeightOptions, densityConfig);
|
|
3378
|
+
maxHeight = Math.max(maxHeight, cellHeight);
|
|
3379
|
+
}
|
|
3380
|
+
return maxHeight;
|
|
3381
|
+
}
|
|
3382
|
+
function calculateTimelineRowHeight(events, options) {
|
|
3383
|
+
const autoHeightOptions = normalizeAutoHeightOptions(options.autoHeight);
|
|
3384
|
+
const densityConfig = getDensityConfig(options.density);
|
|
3385
|
+
if (!autoHeightOptions.enabled) {
|
|
3386
|
+
return densityConfig.rowHeight;
|
|
3387
|
+
}
|
|
3388
|
+
return calculateAutoHeight(events, autoHeightOptions, densityConfig);
|
|
3389
|
+
}
|
|
3390
|
+
function calculateMaxOverlappingEvents(events) {
|
|
3391
|
+
if (events.length === 0) return 0;
|
|
3392
|
+
if (events.length === 1) return 1;
|
|
3393
|
+
const points = [];
|
|
3394
|
+
for (const evt of events) {
|
|
3395
|
+
const start = evt.left;
|
|
3396
|
+
const end = evt.left + evt.width;
|
|
3397
|
+
points.push({ x: start, type: "start" });
|
|
3398
|
+
points.push({ x: end, type: "end" });
|
|
3399
|
+
}
|
|
3400
|
+
points.sort((a, b) => {
|
|
3401
|
+
if (a.x !== b.x) return a.x - b.x;
|
|
3402
|
+
return a.type === "end" ? -1 : 1;
|
|
3403
|
+
});
|
|
3404
|
+
let maxConcurrent = 0;
|
|
3405
|
+
let current = 0;
|
|
3406
|
+
for (const point of points) {
|
|
3407
|
+
if (point.type === "start") {
|
|
3408
|
+
current++;
|
|
3409
|
+
maxConcurrent = Math.max(maxConcurrent, current);
|
|
3410
|
+
} else {
|
|
3411
|
+
current--;
|
|
3412
|
+
}
|
|
3413
|
+
}
|
|
3414
|
+
return maxConcurrent;
|
|
3415
|
+
}
|
|
3416
|
+
function assignEventLanes(events) {
|
|
3417
|
+
if (events.length === 0) return /* @__PURE__ */ new Map();
|
|
3418
|
+
const sorted = [...events].sort((a, b) => {
|
|
3419
|
+
if (a.left !== b.left) return a.left - b.left;
|
|
3420
|
+
return b.width - a.width;
|
|
3421
|
+
});
|
|
3422
|
+
const lanes = [];
|
|
3423
|
+
const eventLanes = /* @__PURE__ */ new Map();
|
|
3424
|
+
for (const evt of sorted) {
|
|
3425
|
+
const start = evt.left;
|
|
3426
|
+
const end = evt.left + evt.width;
|
|
3427
|
+
let assignedLane = -1;
|
|
3428
|
+
for (let i = 0; i < lanes.length; i++) {
|
|
3429
|
+
if (lanes[i].end <= start) {
|
|
3430
|
+
assignedLane = i;
|
|
3431
|
+
lanes[i].end = end;
|
|
3432
|
+
break;
|
|
3433
|
+
}
|
|
3434
|
+
}
|
|
3435
|
+
if (assignedLane === -1) {
|
|
3436
|
+
assignedLane = lanes.length;
|
|
3437
|
+
lanes.push({ end });
|
|
3438
|
+
}
|
|
3439
|
+
eventLanes.set(evt.event.id, assignedLane);
|
|
3440
|
+
}
|
|
3441
|
+
return eventLanes;
|
|
3442
|
+
}
|
|
3443
|
+
function calculateResourceRowAutoHeight(maxOverlapping, eventHeight, eventGap, rowPadding, minHeight) {
|
|
3444
|
+
if (maxOverlapping === 0) return minHeight;
|
|
3445
|
+
const calculatedHeight = rowPadding * 2 + maxOverlapping * eventHeight + (maxOverlapping - 1) * eventGap;
|
|
3446
|
+
return Math.max(minHeight, calculatedHeight);
|
|
3447
|
+
}
|
|
3448
|
+
|
|
3449
|
+
// src/utils/print-runtime.ts
|
|
3450
|
+
var landscapePrintViews = /* @__PURE__ */ new Set(["timelineDay", "timelineWeek", "timelineMonth", "timelineYear", "resourceTimelineDay", "resourceTimelineWeek", "resourceTimelineMonth", "resourceDay", "resourceWeek", "resourceMonth"]);
|
|
3451
|
+
var timelineLikePrintViews = /* @__PURE__ */ new Set(["timelineDay", "timelineWeek", "timelineMonth", "timelineYear", "resourceTimelineDay", "resourceTimelineWeek", "resourceTimelineMonth"]);
|
|
3452
|
+
var resourceLikePrintViews = /* @__PURE__ */ new Set(["resourceDay", "resourceWeek", "resourceMonth"]);
|
|
3453
|
+
var defaultViewLabels = {
|
|
3454
|
+
month: "Month",
|
|
3455
|
+
week: "Week",
|
|
3456
|
+
day: "Day",
|
|
3457
|
+
year: "Year",
|
|
3458
|
+
agenda: "Agenda",
|
|
3459
|
+
timelineDay: "Timeline Day",
|
|
3460
|
+
timelineWeek: "Timeline Week",
|
|
3461
|
+
timelineMonth: "Timeline Month",
|
|
3462
|
+
timelineYear: "Timeline Year",
|
|
3463
|
+
resourceTimelineDay: "Resource Day",
|
|
3464
|
+
resourceTimelineWeek: "Resource Week",
|
|
3465
|
+
resourceTimelineMonth: "Resource Month",
|
|
3466
|
+
resourceDay: "Resource Day",
|
|
3467
|
+
resourceWeek: "Resource Week",
|
|
3468
|
+
resourceMonth: "Resource Month",
|
|
3469
|
+
dateDay: "Date Day",
|
|
3470
|
+
dateWeek: "Date Week",
|
|
3471
|
+
dateMonth: "Date Month"
|
|
3472
|
+
};
|
|
3473
|
+
function clampPrintScaleFactor(value) {
|
|
3474
|
+
if (!Number.isFinite(value)) {
|
|
3475
|
+
return 1;
|
|
3476
|
+
}
|
|
3477
|
+
return Math.min(1.25, Math.max(0.6, value));
|
|
3478
|
+
}
|
|
3479
|
+
function resolvePrintOrientation(view, layout) {
|
|
3480
|
+
const requested = layout?.orientation ?? "auto";
|
|
3481
|
+
if (requested !== "auto") {
|
|
3482
|
+
return requested;
|
|
3483
|
+
}
|
|
3484
|
+
return landscapePrintViews.has(view) ? "landscape" : "portrait";
|
|
3485
|
+
}
|
|
3486
|
+
function resolvePrintScale(view, layout) {
|
|
3487
|
+
const requested = layout?.scale ?? "auto";
|
|
3488
|
+
if (typeof requested === "number") {
|
|
3489
|
+
return { mode: "standard", factor: clampPrintScaleFactor(requested) };
|
|
3490
|
+
}
|
|
3491
|
+
let mode = "standard";
|
|
3492
|
+
if (requested === "auto") {
|
|
3493
|
+
if (timelineLikePrintViews.has(view)) {
|
|
3494
|
+
mode = "fit";
|
|
3495
|
+
} else if (resourceLikePrintViews.has(view)) {
|
|
3496
|
+
mode = "compact";
|
|
3497
|
+
}
|
|
3498
|
+
} else {
|
|
3499
|
+
mode = requested;
|
|
3500
|
+
}
|
|
3501
|
+
const factor = mode === "fit" ? 0.72 : mode === "compact" ? 0.86 : 1;
|
|
3502
|
+
return { mode, factor };
|
|
3503
|
+
}
|
|
3504
|
+
function formatPrintDateWithOptions(date, locale, timeZone, options, displayConfig) {
|
|
3505
|
+
try {
|
|
3506
|
+
return createSchedulerDateFormatter({
|
|
3507
|
+
...displayConfig,
|
|
3508
|
+
locale,
|
|
3509
|
+
timeZone: timeZone ?? displayConfig?.timeZone
|
|
3510
|
+
}).format(date, options);
|
|
3511
|
+
} catch {
|
|
3512
|
+
return createSchedulerDateFormatter({
|
|
3513
|
+
...displayConfig,
|
|
3514
|
+
locale,
|
|
3515
|
+
timeZone: void 0
|
|
3516
|
+
}).format(date, options);
|
|
3517
|
+
}
|
|
3518
|
+
}
|
|
3519
|
+
function formatPrintDateTime(date, locale, timeZone, displayConfig) {
|
|
3520
|
+
return formatPrintDateWithOptions(
|
|
3521
|
+
date,
|
|
3522
|
+
locale,
|
|
3523
|
+
timeZone,
|
|
3524
|
+
{
|
|
3525
|
+
dateStyle: "medium",
|
|
3526
|
+
timeStyle: "short"
|
|
3527
|
+
},
|
|
3528
|
+
displayConfig
|
|
3529
|
+
);
|
|
3530
|
+
}
|
|
3531
|
+
function formatPrintDate(date, locale, timeZone, displayConfig) {
|
|
3532
|
+
return formatPrintDateWithOptions(
|
|
3533
|
+
date,
|
|
3534
|
+
locale,
|
|
3535
|
+
timeZone,
|
|
3536
|
+
{
|
|
3537
|
+
dateStyle: "medium"
|
|
3538
|
+
},
|
|
3539
|
+
displayConfig
|
|
3540
|
+
);
|
|
3541
|
+
}
|
|
3542
|
+
function formatPrintRange(range, locale, timeZone, displayConfig) {
|
|
3543
|
+
const startLabel = formatPrintDate(range.start, locale, timeZone, displayConfig);
|
|
3544
|
+
const endLabel = formatPrintDate(range.end, locale, timeZone, displayConfig);
|
|
3545
|
+
if (startLabel === endLabel) {
|
|
3546
|
+
return startLabel;
|
|
3547
|
+
}
|
|
3548
|
+
return `${startLabel} - ${endLabel}`;
|
|
3549
|
+
}
|
|
3550
|
+
function resolvePrintFilters(input) {
|
|
3551
|
+
if (input.pageChromeOptions?.filters && input.pageChromeOptions.filters.length > 0) {
|
|
3552
|
+
return input.pageChromeOptions.filters;
|
|
3553
|
+
}
|
|
3554
|
+
if (!input.categoryFilterable || !input.activeCategoryIds || input.activeCategoryIds.length === 0) {
|
|
3555
|
+
return [];
|
|
3556
|
+
}
|
|
3557
|
+
const activeSet = new Set(input.activeCategoryIds);
|
|
3558
|
+
const labels = (input.categories ?? []).filter((cat) => activeSet.has(cat.id)).map((cat) => cat.name.trim()).filter(Boolean);
|
|
3559
|
+
if (labels.length === 0) {
|
|
3560
|
+
return [];
|
|
3561
|
+
}
|
|
3562
|
+
return [`Categories: ${labels.join(", ")}`];
|
|
3563
|
+
}
|
|
3564
|
+
function resolvePrintPageStyleRule(orientation, margin = "0.5in") {
|
|
3565
|
+
return `@media print { @page { size: ${orientation}; margin: ${margin}; } }`;
|
|
3566
|
+
}
|
|
3567
|
+
function getResolvedTimezoneLabel(pageChromeOptions, timezoneLabel) {
|
|
3568
|
+
if (pageChromeOptions.timezoneLabel) {
|
|
3569
|
+
return pageChromeOptions.timezoneLabel;
|
|
3570
|
+
}
|
|
3571
|
+
if (timezoneLabel) {
|
|
3572
|
+
return timezoneLabel;
|
|
3573
|
+
}
|
|
3574
|
+
return Intl.DateTimeFormat().resolvedOptions().timeZone || "Local";
|
|
3575
|
+
}
|
|
3576
|
+
function resolvePrintPageChromeState(input) {
|
|
3577
|
+
if (input.pageChrome === void 0 || input.pageChrome === false) {
|
|
3578
|
+
return null;
|
|
3579
|
+
}
|
|
3580
|
+
const options = typeof input.pageChrome === "object" ? input.pageChrome : {};
|
|
3581
|
+
if (options.enabled === false) {
|
|
3582
|
+
return null;
|
|
3583
|
+
}
|
|
3584
|
+
const filters = options.filters && options.filters.length > 0 ? options.filters : input.filters ?? [];
|
|
3585
|
+
const filtersLabel = options.filtersLabel ?? "Filters";
|
|
3586
|
+
const generatedAtLabel = options.generatedAtLabel ?? "Generated";
|
|
3587
|
+
const showGeneratedAt = options.showGeneratedAt !== false;
|
|
3588
|
+
const showTimezone = options.showTimezone !== false;
|
|
3589
|
+
const showFilters = options.showFilters !== false;
|
|
3590
|
+
const viewLabel = input.viewLabel ?? defaultViewLabels[input.view] ?? input.view;
|
|
3591
|
+
const now = input.now ?? /* @__PURE__ */ new Date();
|
|
3592
|
+
return {
|
|
3593
|
+
logoText: options.logoText?.trim() || null,
|
|
3594
|
+
logoUrl: options.logoUrl?.trim() || null,
|
|
3595
|
+
headerTitle: options.headerTitle?.trim() || input.title,
|
|
3596
|
+
headerSubtitle: options.headerSubtitle?.trim() || `${viewLabel} - ${formatPrintRange(input.range, input.locale, input.timezone, input.calendarDisplayConfig)}`,
|
|
3597
|
+
generatedAtText: showGeneratedAt ? `${generatedAtLabel}: ${formatPrintDateTime(now, input.locale, input.timezone, input.calendarDisplayConfig)}` : null,
|
|
3598
|
+
timezoneText: showTimezone ? `Timezone: ${getResolvedTimezoneLabel(options, input.timezoneLabel)}` : null,
|
|
3599
|
+
filtersText: showFilters && filters.length > 0 ? `${filtersLabel}: ${filters.join(" | ")}` : null,
|
|
3600
|
+
footerLeftText: options.footerLeft ?? "",
|
|
3601
|
+
footerCenterText: options.footerCenter ?? "",
|
|
3602
|
+
footerRightText: options.footerRight ?? "",
|
|
3603
|
+
showPageNumbers: options.showPageNumbers === true
|
|
3604
|
+
};
|
|
3605
|
+
}
|
|
3606
|
+
function resolvePrintRuntimeState(input) {
|
|
3607
|
+
const orientation = resolvePrintOrientation(input.view, input.options?.layout);
|
|
3608
|
+
const scale = resolvePrintScale(input.view, input.options?.layout);
|
|
3609
|
+
const pageChromeState = resolvePrintPageChromeState({
|
|
3610
|
+
...input.pageChromeContext,
|
|
3611
|
+
pageChrome: input.options?.pageChrome
|
|
3612
|
+
});
|
|
3613
|
+
return {
|
|
3614
|
+
orientation,
|
|
3615
|
+
scaleMode: scale.mode,
|
|
3616
|
+
scaleFactor: scale.factor,
|
|
3617
|
+
pageChromeState
|
|
3618
|
+
};
|
|
3619
|
+
}
|
|
3620
|
+
|
|
3621
|
+
// src/utils/print-session.controller.ts
|
|
3622
|
+
function resolvePrintSession(input) {
|
|
3623
|
+
const runtime = resolvePrintRuntimeState({
|
|
3624
|
+
view: input.view,
|
|
3625
|
+
options: input.options,
|
|
3626
|
+
pageChromeContext: input.pageChromeContext
|
|
3627
|
+
});
|
|
3628
|
+
return {
|
|
3629
|
+
orientation: runtime.orientation,
|
|
3630
|
+
scaleMode: runtime.scaleMode,
|
|
3631
|
+
scaleFactor: runtime.scaleFactor,
|
|
3632
|
+
pageChromeState: runtime.pageChromeState,
|
|
3633
|
+
pageStyleRule: resolvePrintPageStyleRule(runtime.orientation)
|
|
3634
|
+
};
|
|
3635
|
+
}
|
|
3636
|
+
function getIdlePrintSessionState() {
|
|
3637
|
+
return {
|
|
3638
|
+
orientation: "portrait",
|
|
3639
|
+
scaleMode: "standard",
|
|
3640
|
+
scaleFactor: 1,
|
|
3641
|
+
pageChromeState: null,
|
|
3642
|
+
pageStyleRule: ""
|
|
3643
|
+
};
|
|
3644
|
+
}
|
|
3645
|
+
function resolvePrintColorAction(colorOption, hadColorClass) {
|
|
3646
|
+
if (colorOption === true) {
|
|
3647
|
+
return { type: "set", restoreAction: hadColorClass ? "add" : "remove" };
|
|
3648
|
+
}
|
|
3649
|
+
if (colorOption === false) {
|
|
3650
|
+
return { type: "unset", restoreAction: hadColorClass ? "add" : "remove" };
|
|
3651
|
+
}
|
|
3652
|
+
return { type: "none" };
|
|
3653
|
+
}
|
|
3654
|
+
|
|
3655
|
+
// src/utils/view-runtime.ts
|
|
3656
|
+
var DATE_GROUPING_VIEWS = /* @__PURE__ */ new Set(["dateWeek", "dateMonth"]);
|
|
3657
|
+
var TIMELINE_LIKE_VIEWS = /* @__PURE__ */ new Set(["timelineDay", "timelineWeek", "timelineMonth", "timelineYear", "resourceTimelineDay", "resourceTimelineWeek", "resourceTimelineMonth"]);
|
|
3658
|
+
var RESOURCE_LIKE_VIEWS = /* @__PURE__ */ new Set(["resourceDay", "resourceWeek", "resourceMonth", "resourceTimelineDay", "resourceTimelineWeek", "resourceTimelineMonth"]);
|
|
3659
|
+
var TIMED_CREATE_VIEWS = /* @__PURE__ */ new Set(["week", "day", "timelineDay", "timelineWeek", "resourceTimelineDay", "resourceTimelineWeek", "resourceDay", "resourceWeek", "dateDay", "dateWeek"]);
|
|
3660
|
+
var TIMELINE_CREATE_VIEWS = /* @__PURE__ */ new Set(["timelineDay", "timelineWeek", "resourceTimelineDay", "resourceTimelineWeek"]);
|
|
3661
|
+
var DIRECT_TIME_SELECTION_VIEWS = /* @__PURE__ */ new Set(["day", "week"]);
|
|
3662
|
+
var WEEK_NUMBER_OF_DAYS_VIEWS = /* @__PURE__ */ new Set(["week", "timelineWeek", "resourceWeek", "resourceTimelineWeek"]);
|
|
3663
|
+
var MONTH_RANGE_VIEWS = /* @__PURE__ */ new Set(["month", "resourceMonth", "dateMonth"]);
|
|
3664
|
+
var TIMELINE_MONTH_RANGE_VIEWS = /* @__PURE__ */ new Set(["timelineMonth", "resourceTimelineMonth"]);
|
|
3665
|
+
var WEEK_RANGE_VIEWS = /* @__PURE__ */ new Set(["week", "timelineWeek", "resourceWeek", "resourceTimelineWeek", "dateWeek"]);
|
|
3666
|
+
var DAY_RANGE_VIEWS = /* @__PURE__ */ new Set(["day", "timelineDay", "resourceDay", "resourceTimelineDay", "dateDay"]);
|
|
3667
|
+
function isTimelineLikeView(view) {
|
|
3668
|
+
return TIMELINE_LIKE_VIEWS.has(view);
|
|
3669
|
+
}
|
|
3670
|
+
function isResourceLikeView(view) {
|
|
3671
|
+
return RESOURCE_LIKE_VIEWS.has(view);
|
|
3672
|
+
}
|
|
3673
|
+
function isTimedCreateView(view) {
|
|
3674
|
+
return TIMED_CREATE_VIEWS.has(view);
|
|
3675
|
+
}
|
|
3676
|
+
function isDirectTimeSelectionView(view) {
|
|
3677
|
+
return DIRECT_TIME_SELECTION_VIEWS.has(view);
|
|
3678
|
+
}
|
|
3679
|
+
function getSchedulerWeekendToggleView(view) {
|
|
3680
|
+
return null;
|
|
3681
|
+
}
|
|
3682
|
+
function resolveClickCreateEnd(start, view, slotDuration, timelineSlotDuration) {
|
|
3683
|
+
const minutes = TIMELINE_CREATE_VIEWS.has(view) ? timelineSlotDuration : slotDuration;
|
|
3684
|
+
const safeMinutes = Math.max(1, Number.isFinite(minutes) ? minutes : 1);
|
|
3685
|
+
return new Date(start.getTime() + safeMinutes * 6e4);
|
|
3686
|
+
}
|
|
3687
|
+
function resolveDaysOfWeekForView(input) {
|
|
3688
|
+
if (DATE_GROUPING_VIEWS.has(input.view)) {
|
|
3689
|
+
return input.dateGroupingDaysOfWeek;
|
|
3690
|
+
}
|
|
3691
|
+
return input.daysOfWeek;
|
|
3692
|
+
}
|
|
3693
|
+
function toAdapterDate(adapter, date) {
|
|
3694
|
+
return adapter.toDate(adapter.fromDate(date));
|
|
3695
|
+
}
|
|
3696
|
+
function resolveVisibleWeekRange(input) {
|
|
3697
|
+
const weekEnd = input.adapter.add(input.weekStart, { days: 6 });
|
|
3698
|
+
const activeDays = input.daysOfWeek?.filter((day) => Number.isInteger(day) && day >= 0 && day <= 6);
|
|
3699
|
+
if (!activeDays || activeDays.length === 0 || activeDays.length === 7) {
|
|
3700
|
+
return { start: input.weekStart, end: weekEnd };
|
|
3701
|
+
}
|
|
3702
|
+
let firstVisible = input.weekStart;
|
|
3703
|
+
let lastVisible = weekEnd;
|
|
3704
|
+
let hasVisibleDay = false;
|
|
3705
|
+
for (let i = 0; i < 7; i++) {
|
|
3706
|
+
const day = input.adapter.add(input.weekStart, { days: i });
|
|
3707
|
+
if (!activeDays.includes(input.adapter.getDayOfWeek(day))) {
|
|
3708
|
+
continue;
|
|
3709
|
+
}
|
|
3710
|
+
if (!hasVisibleDay) {
|
|
3711
|
+
firstVisible = day;
|
|
3712
|
+
hasVisibleDay = true;
|
|
3713
|
+
}
|
|
3714
|
+
lastVisible = day;
|
|
3715
|
+
}
|
|
3716
|
+
return { start: firstVisible, end: lastVisible };
|
|
3717
|
+
}
|
|
3718
|
+
function resolveCalendarAdapterForView(input) {
|
|
3719
|
+
const calendar = resolveSchedulerCalendarModeForView(input.calendar ?? "gregory", input.view);
|
|
3720
|
+
return getSchedulerCalendarAdapter(calendar, { locale: input.locale });
|
|
3721
|
+
}
|
|
3722
|
+
function resolveCalendarViewRange(input) {
|
|
3723
|
+
const adapter = resolveCalendarAdapterForView(input);
|
|
3724
|
+
const currentCalendarDate = adapter.fromDate(input.currentDate);
|
|
3725
|
+
if (MONTH_RANGE_VIEWS.has(input.view)) {
|
|
3726
|
+
const monthStart = adapter.startOfMonth(currentCalendarDate);
|
|
3727
|
+
const gridStart = adapter.startOfWeek(monthStart, input.firstDayOfWeek);
|
|
3728
|
+
const gridEnd = adapter.add(gridStart, { days: 41 });
|
|
3729
|
+
return { start: adapter.toDate(gridStart), end: adapter.toDate(gridEnd) };
|
|
3730
|
+
}
|
|
3731
|
+
if (TIMELINE_MONTH_RANGE_VIEWS.has(input.view)) {
|
|
3732
|
+
const monthStart = adapter.startOfMonth(currentCalendarDate);
|
|
3733
|
+
const monthEnd = adapter.endOfMonth(currentCalendarDate);
|
|
3734
|
+
return { start: adapter.toDate(monthStart), end: adapter.toDate(monthEnd) };
|
|
3735
|
+
}
|
|
3736
|
+
if (input.view === "year" || input.view === "timelineYear") {
|
|
3737
|
+
const yearStart = adapter.startOfMonth({ ...currentCalendarDate, month: 1, day: 1 });
|
|
3738
|
+
const yearEnd = adapter.endOfMonth({ ...currentCalendarDate, month: adapter.getMonthsInYear(currentCalendarDate), day: 1 });
|
|
3739
|
+
return { start: adapter.toDate(yearStart), end: adapter.toDate(yearEnd) };
|
|
3740
|
+
}
|
|
3741
|
+
if (WEEK_RANGE_VIEWS.has(input.view)) {
|
|
3742
|
+
const weekStart = adapter.startOfWeek(currentCalendarDate, input.firstDayOfWeek);
|
|
3743
|
+
const weekRange = resolveVisibleWeekRange({ adapter, weekStart, daysOfWeek: DATE_GROUPING_VIEWS.has(input.view) ? void 0 : input.daysOfWeek });
|
|
3744
|
+
return { start: adapter.toDate(weekRange.start), end: adapter.toDate(weekRange.end) };
|
|
3745
|
+
}
|
|
3746
|
+
if (DAY_RANGE_VIEWS.has(input.view)) {
|
|
3747
|
+
const day = toAdapterDate(adapter, input.currentDate);
|
|
3748
|
+
return { start: day, end: day };
|
|
3749
|
+
}
|
|
3750
|
+
if (input.view === "agenda") {
|
|
3751
|
+
const start = adapter.fromDate(startOfDay(input.currentDate));
|
|
3752
|
+
const end = adapter.add(start, { days: 30 });
|
|
3753
|
+
return { start: adapter.toDate(start), end: adapter.toDate(end) };
|
|
3754
|
+
}
|
|
3755
|
+
return { start: input.currentDate, end: input.currentDate };
|
|
3756
|
+
}
|
|
3757
|
+
function resolveCurrentViewRange(input) {
|
|
3758
|
+
const daysOfWeek = resolveDaysOfWeekForView({
|
|
3759
|
+
view: input.view,
|
|
3760
|
+
dateGroupingDaysOfWeek: input.dateGroupingDaysOfWeek,
|
|
3761
|
+
daysOfWeek: input.daysOfWeek
|
|
3762
|
+
});
|
|
3763
|
+
const viewOptions = {
|
|
3764
|
+
locale: input.locale,
|
|
3765
|
+
firstDayOfWeek: input.firstDayOfWeek,
|
|
3766
|
+
weekNumbers: input.weekNumbers,
|
|
3767
|
+
weekNumbering: input.weekNumbering,
|
|
3768
|
+
minDate: input.minDate ?? null,
|
|
3769
|
+
maxDate: input.maxDate ?? null,
|
|
3770
|
+
slotDuration: input.slotDuration,
|
|
3771
|
+
slotMinTime: input.slotMinTime,
|
|
3772
|
+
slotMaxTime: input.slotMaxTime,
|
|
3773
|
+
events: input.eventList,
|
|
3774
|
+
daysOfWeek,
|
|
3775
|
+
numberOfDays: input.numberOfDays,
|
|
3776
|
+
calendar: input.calendar
|
|
3777
|
+
};
|
|
3778
|
+
let range = resolveCalendarViewRange({
|
|
3779
|
+
view: input.view,
|
|
3780
|
+
currentDate: input.currentDate,
|
|
3781
|
+
locale: input.locale,
|
|
3782
|
+
calendar: input.calendar,
|
|
3783
|
+
firstDayOfWeek: input.firstDayOfWeek,
|
|
3784
|
+
daysOfWeek
|
|
3785
|
+
});
|
|
3786
|
+
if (range.start === input.currentDate && range.end === input.currentDate) {
|
|
3787
|
+
range = getView(input.view).getDateRange(input.currentDate, viewOptions);
|
|
3788
|
+
}
|
|
3789
|
+
if (input.numberOfDays && WEEK_NUMBER_OF_DAYS_VIEWS.has(input.view)) {
|
|
3790
|
+
const start = startOfDay(input.currentDate);
|
|
3791
|
+
const end = new Date(start.getTime() + (input.numberOfDays - 1) * 24 * 60 * 60 * 1e3);
|
|
3792
|
+
range = { start, end };
|
|
3793
|
+
}
|
|
3794
|
+
if (MONTH_RANGE_VIEWS.has(input.view)) {
|
|
3795
|
+
range = resolveCalendarViewRange({
|
|
3796
|
+
view: input.view,
|
|
3797
|
+
currentDate: input.currentDate,
|
|
3798
|
+
locale: input.locale,
|
|
3799
|
+
calendar: input.calendar,
|
|
3800
|
+
firstDayOfWeek: input.firstDayOfWeek,
|
|
3801
|
+
daysOfWeek
|
|
3802
|
+
});
|
|
3803
|
+
}
|
|
3804
|
+
return {
|
|
3805
|
+
start: startOfDay(range.start),
|
|
3806
|
+
end: endOfDay(range.end)
|
|
3807
|
+
};
|
|
3808
|
+
}
|
|
3809
|
+
|
|
3810
|
+
// src/utils/selection-runtime.ts
|
|
3811
|
+
function toDateOnlyString(date) {
|
|
3812
|
+
return date.toISOString().split("T")[0];
|
|
3813
|
+
}
|
|
3814
|
+
function canSelectForView(start, end, allDay, view, selectConstraint, selectAllow) {
|
|
3815
|
+
return canSelect(start, end, allDay, view, selectConstraint, selectAllow);
|
|
3816
|
+
}
|
|
3817
|
+
function resolveSelectionEmitOutcome(state, fallbackStart, fallbackEnd, allDay, view) {
|
|
3818
|
+
if (!hasSelection(state)) {
|
|
3819
|
+
return {
|
|
3820
|
+
type: "unselect",
|
|
3821
|
+
payload: { view }
|
|
3822
|
+
};
|
|
3823
|
+
}
|
|
3824
|
+
const selectedRange = allDay ? state.selectedRange : state.selectedTimeRange;
|
|
3825
|
+
const start = selectedRange?.start ?? fallbackStart;
|
|
3826
|
+
const end = selectedRange?.end ?? fallbackEnd;
|
|
3827
|
+
return {
|
|
3828
|
+
type: "select",
|
|
3829
|
+
payload: {
|
|
3830
|
+
start,
|
|
3831
|
+
end,
|
|
3832
|
+
startStr: allDay ? toDateOnlyString(start) : start.toISOString(),
|
|
3833
|
+
endStr: allDay ? toDateOnlyString(end) : end.toISOString(),
|
|
3834
|
+
view,
|
|
3835
|
+
allDay
|
|
3836
|
+
}
|
|
3837
|
+
};
|
|
3838
|
+
}
|
|
3839
|
+
|
|
3840
|
+
// src/utils/event-slot-density.ts
|
|
3841
|
+
var HEIGHT_THRESHOLDS = {
|
|
3842
|
+
minimal: 20,
|
|
3843
|
+
compact: 28,
|
|
3844
|
+
standard: 48
|
|
3845
|
+
};
|
|
3846
|
+
var WIDTH_THRESHOLDS = {
|
|
3847
|
+
minimal: 30,
|
|
3848
|
+
compact: 60
|
|
3849
|
+
};
|
|
3850
|
+
function resolveEventDensity(options) {
|
|
3851
|
+
const { availableHeight, availableWidth } = options;
|
|
3852
|
+
if (availableWidth !== void 0) {
|
|
3853
|
+
if (availableWidth < WIDTH_THRESHOLDS.minimal) return "minimal";
|
|
3854
|
+
if (availableWidth < WIDTH_THRESHOLDS.compact) return "compact";
|
|
3855
|
+
}
|
|
3856
|
+
if (availableHeight === void 0) return "standard";
|
|
3857
|
+
if (availableHeight < HEIGHT_THRESHOLDS.minimal) return "minimal";
|
|
3858
|
+
if (availableHeight < HEIGHT_THRESHOLDS.compact) return "compact";
|
|
3859
|
+
if (availableHeight < HEIGHT_THRESHOLDS.standard) return "standard";
|
|
3860
|
+
return "comfortable";
|
|
3861
|
+
}
|
|
3862
|
+
function resolveTimelineDefaultTextMode(_options) {
|
|
3863
|
+
return "title-time";
|
|
3864
|
+
}
|
|
3865
|
+
var TIMED_COLUMN_HEIGHT_THRESHOLD = 36;
|
|
3866
|
+
function resolveTimedColumnTextMode(options) {
|
|
3867
|
+
return options.availableHeight < TIMED_COLUMN_HEIGHT_THRESHOLD ? "title-only" : "title-time";
|
|
3868
|
+
}
|
|
3869
|
+
|
|
3870
|
+
// src/utils/lane-geometry.ts
|
|
3871
|
+
function resolveGroupedLaneGeometry(opts) {
|
|
3872
|
+
const dayCount = Math.max(1, Number.isFinite(opts.dayCount) ? Math.trunc(opts.dayCount) : 1);
|
|
3873
|
+
const resourceLeafCount = Math.max(0, Number.isFinite(opts.resourceLeafCount) ? Math.trunc(opts.resourceLeafCount) : 0);
|
|
3874
|
+
const { mode } = opts;
|
|
3875
|
+
const isDateGrouped = mode.startsWith("date-");
|
|
3876
|
+
const groupCount = isDateGrouped ? dayCount : resourceLeafCount;
|
|
3877
|
+
const leavesPerGroup = isDateGrouped ? resourceLeafCount : dayCount;
|
|
3878
|
+
const totalLeafColumns = groupCount * leavesPerGroup;
|
|
3879
|
+
const dateBase = opts.dateColumnMinWidth ?? "var(--p-scheduler-date-column-min-width, 80px)";
|
|
3880
|
+
const resBase = opts.resourceColumnMinWidth ?? "var(--p-scheduler-resource-column-min-width, 120px)";
|
|
3881
|
+
let colMinWidth;
|
|
3882
|
+
let groupMinWidth;
|
|
3883
|
+
let laneMinWidth;
|
|
3884
|
+
if (isDateGrouped) {
|
|
3885
|
+
colMinWidth = dateBase;
|
|
3886
|
+
groupMinWidth = leavesPerGroup > 1 ? `calc(${leavesPerGroup} * ${dateBase})` : dateBase;
|
|
3887
|
+
laneMinWidth = totalLeafColumns > 1 ? `calc(${totalLeafColumns} * ${dateBase})` : dateBase;
|
|
3888
|
+
} else {
|
|
3889
|
+
const dayMin = opts.resourceDayMinWidth ?? "var(--p-scheduler-resource-day-min-width, 56px)";
|
|
3890
|
+
const groupBase = opts.resourceGroupMinWidth ?? `var(--p-scheduler-resource-group-min-width, ${resBase})`;
|
|
3891
|
+
if (leavesPerGroup > 1) {
|
|
3892
|
+
colMinWidth = dayMin;
|
|
3893
|
+
groupMinWidth = `max(${groupBase}, calc(${leavesPerGroup} * ${dayMin}))`;
|
|
3894
|
+
} else {
|
|
3895
|
+
colMinWidth = groupBase;
|
|
3896
|
+
groupMinWidth = groupBase;
|
|
3897
|
+
}
|
|
3898
|
+
laneMinWidth = groupCount > 1 ? `calc(${groupCount} * ${groupMinWidth})` : groupMinWidth;
|
|
3899
|
+
}
|
|
3900
|
+
return {
|
|
3901
|
+
groupCount,
|
|
3902
|
+
leavesPerGroup,
|
|
3903
|
+
totalLeafColumns,
|
|
3904
|
+
cssVars: {
|
|
3905
|
+
"--p-scheduler-lane-group-count": String(groupCount),
|
|
3906
|
+
"--p-scheduler-lane-leaves-per-group": String(leavesPerGroup),
|
|
3907
|
+
"--p-scheduler-lane-col-min-width": colMinWidth,
|
|
3908
|
+
"--p-scheduler-lane-group-min-width": groupMinWidth,
|
|
3909
|
+
"--p-scheduler-lane-min-width": laneMinWidth
|
|
3910
|
+
}
|
|
3911
|
+
};
|
|
3912
|
+
}
|
|
3913
|
+
|
|
3914
|
+
// src/utils/more-popover.ts
|
|
3915
|
+
function sortMorePopoverEvents(events) {
|
|
3916
|
+
return [...events].sort((a, b) => {
|
|
3917
|
+
const aStart = typeof a.start === "string" ? new Date(a.start) : a.start;
|
|
3918
|
+
const bStart = typeof b.start === "string" ? new Date(b.start) : b.start;
|
|
3919
|
+
const timeDiff = aStart.getTime() - bStart.getTime();
|
|
3920
|
+
if (timeDiff !== 0) return timeDiff;
|
|
3921
|
+
return (a.title || "").localeCompare(b.title || "");
|
|
3922
|
+
});
|
|
3923
|
+
}
|
|
3924
|
+
|
|
3925
|
+
export { DEFAULT_ADAPTIVE_OPTIONS, DEFAULT_AUTO_HEIGHT_OPTIONS, DEFAULT_STACKING_OPTIONS, DENSITY_CONFIGS, applyImportMerge, assignEventLanes, buildImportValidationReport, calculateAutoHeight, calculateCellRenderingInfo, calculateMaxOverlappingEvents, calculateResourceRowAutoHeight, calculateTimelineRowHeight, calculateWeekViewAutoHeight, canSelectForView, clampPrintScaleFactor, createAdaptiveRenderingState, defaultSchedulerText, detectImportFormat, exportScheduler, exportToCsv, exportToIcal, exportToJson, exportToPdf, exportToXlsx, formatPrintDate, formatPrintDateTime, formatPrintRange, getAutoHeightClasses, getAvailableLocales, getDefaultFirstDayOfWeek, getDensityCSSVars, getDensityClasses, getDensityConfig, getDensityFromContainerWidth, getEventDensityClasses, getIdlePrintSessionState, getLocaleConfig, getMoreText, getSchedulerText, getSchedulerWeekendToggleView, getStackedEventStyle, getStackingClasses, getVisibleEvents, importFromCsv, importFromIcal, importFromJson, importScheduler, isDirectTimeSelectionView, isRTL, isResourceLikeView, isTimedCreateView, isTimelineLikeView, normalizeAdaptiveOptions, normalizeAutoHeightOptions, normalizeStackingOptions, preparePdfData, prepareXlsxData, previewImportMerge, registerLocale, resolveCalendarViewRange, resolveClickCreateEnd, resolveCurrentViewRange, resolveDaysOfWeekForView, resolveEventDensity, resolveGroupedLaneGeometry, resolvePrintColorAction, resolvePrintFilters, resolvePrintOrientation, resolvePrintPageChromeState, resolvePrintPageStyleRule, resolvePrintRuntimeState, resolvePrintScale, resolvePrintSession, resolveSchedulerText, resolveSelectionEmitOutcome, resolveTimedColumnTextMode, resolveTimelineDefaultTextMode, sortMorePopoverEvents, toDateOnlyString, validateImportResult };
|