@agent-native/core 0.159.5 → 0.160.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/corpus/README.md +1 -1
- package/corpus/templates/assets/server/lib/generation.ts +10 -6
- package/corpus/templates/calendar/.agents/skills/event-management/SKILL.md +18 -4
- package/corpus/templates/calendar/actions/create-event.ts +4 -2
- package/corpus/templates/calendar/actions/event-action-helpers.ts +56 -9
- package/corpus/templates/calendar/actions/update-event.ts +1 -0
- package/corpus/templates/calendar/agent-native.config.ts +1 -0
- package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +8 -2
- package/corpus/templates/calendar/app/components/calendar/DayView.tsx +102 -68
- package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +150 -49
- package/corpus/templates/calendar/app/components/calendar/MonthView.tsx +57 -23
- package/corpus/templates/calendar/app/components/calendar/OutOfOfficeEvent.tsx +4 -1
- package/corpus/templates/calendar/app/components/calendar/TimezoneSwitchDialog.tsx +70 -0
- package/corpus/templates/calendar/app/components/calendar/WeekView.tsx +127 -88
- package/corpus/templates/calendar/app/components/calendar/WorkingLocationEditor.tsx +59 -25
- package/corpus/templates/calendar/app/hooks/use-event-drag.ts +55 -18
- package/corpus/templates/calendar/app/i18n-data.ts +60 -0
- package/corpus/templates/calendar/app/lib/all-day-layout.ts +16 -8
- package/corpus/templates/calendar/app/lib/calendar-drafts.ts +56 -0
- package/corpus/templates/calendar/app/lib/calendar-timezone.ts +351 -0
- package/corpus/templates/calendar/app/lib/event-layout.ts +14 -8
- package/corpus/templates/calendar/app/lib/out-of-office.ts +29 -61
- package/corpus/templates/calendar/app/lib/working-location.ts +34 -2
- package/corpus/templates/calendar/app/pages/CalendarView.tsx +317 -139
- package/corpus/templates/calendar/changelog/2026-08-13-calendar-stays-pinned-to-the-saved-timezone-and-asks-before-.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-13-working-locations-can-be-added-from-calendar-days-with-a-ful.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-14-choosing-office-or-other-when-adding-a-working-location-creates.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-14-creating-an-other-working-location-now-keeps-the-custom-name.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-14-timed-working-locations-keep-home-office-or-custom-titles.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-14-timed-working-locations-now-keep-a-home-office-or-custom-title.md +6 -0
- package/corpus/templates/calendar/changelog/2026-08-14-turning-a-midnight-ending-working-location-back-to-all-day.md +6 -0
- package/corpus/templates/calendar/server/lib/google-calendar.ts +22 -1
- package/dist/agent/engine/builder-engine.d.ts +16 -2
- package/dist/agent/engine/builder-engine.js +178 -115
- package/dist/agent/engine/builtin.js +13 -4
- package/dist/agent/engine/credential-errors.d.ts +23 -0
- package/dist/agent/engine/credential-errors.js +19 -0
- package/dist/agent/engine/error-detail.d.ts +15 -0
- package/dist/agent/engine/error-detail.js +29 -0
- package/dist/agent/engine/registry.d.ts +14 -3
- package/dist/agent/engine/registry.js +106 -61
- package/dist/agent/engine/types.d.ts +16 -0
- package/dist/agent/engine/types.js +9 -0
- package/dist/agent/production-agent.d.ts +7 -0
- package/dist/agent/production-agent.js +68 -31
- package/dist/agent/run-manager.js +30 -0
- package/dist/agent/thread-data-builder.js +4 -0
- package/dist/agent/tool-approval-migrations.d.ts +1 -0
- package/dist/agent/tool-approval-migrations.js +10 -0
- package/dist/agent/tool-approval-store.d.ts +5 -3
- package/dist/agent/tool-approval-store.js +11 -6
- package/dist/agent/types.d.ts +9 -0
- package/dist/cli/code-agent-connector.js +79 -7
- package/dist/cli/portal-transfer.d.ts +43 -0
- package/dist/cli/portal-transfer.js +201 -0
- package/dist/client/agent-chat-adapter.js +46 -15
- package/dist/client/error-format.js +25 -2
- package/dist/client/sse-event-processor.d.ts +2 -0
- package/dist/client/sse-event-processor.js +12 -1
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/jobs/background-automation-runner.js +9 -15
- package/dist/notifications/routes.d.ts +6 -6
- package/dist/observability/routes.d.ts +5 -5
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/secrets/register-framework-secrets.js +25 -0
- package/dist/secrets/routes.d.ts +9 -9
- package/dist/server/agent-chat-plugin.js +9 -2
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/credential-provider.d.ts +80 -0
- package/dist/server/credential-provider.js +168 -1
- package/dist/server/google-realtime-session.d.ts +1 -1
- package/dist/server/google-realtime-session.js +6 -6
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +6 -1
- package/dist/server/realtime-token.d.ts +1 -1
- package/dist/server/realtime-voice.js +12 -6
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/transcribe-voice.js +18 -16
- package/dist/transcription/builder-transcription.js +8 -4
- package/package.json +3 -3
|
@@ -1,7 +1,17 @@
|
|
|
1
1
|
import type { CalendarEvent } from "@shared/api";
|
|
2
|
-
import { parseISO, startOfDay
|
|
2
|
+
import { parseISO, startOfDay } from "date-fns";
|
|
3
3
|
import { useState, useRef, useCallback, useEffect } from "react";
|
|
4
4
|
|
|
5
|
+
import {
|
|
6
|
+
addCalendarDays,
|
|
7
|
+
dateKeyToDate,
|
|
8
|
+
dateKeyToTimezoneIso,
|
|
9
|
+
dateToCalendarDateKey,
|
|
10
|
+
getBrowserTimezone,
|
|
11
|
+
getEventDateKey,
|
|
12
|
+
getEventSegmentForCalendarDay,
|
|
13
|
+
} from "@/lib/calendar-timezone";
|
|
14
|
+
|
|
5
15
|
const SNAP_MINUTES = 15;
|
|
6
16
|
|
|
7
17
|
interface DragState {
|
|
@@ -48,6 +58,8 @@ export interface UseEventDragOptions {
|
|
|
48
58
|
onEventTimeChange: (eventId: string, newStart: Date, newEnd: Date) => void;
|
|
49
59
|
/** All events (to find the event being dragged) */
|
|
50
60
|
events: CalendarEvent[];
|
|
61
|
+
/** IANA timezone used by the visible calendar grid */
|
|
62
|
+
timezone?: string;
|
|
51
63
|
}
|
|
52
64
|
|
|
53
65
|
export function useEventDrag({
|
|
@@ -57,6 +69,7 @@ export function useEventDrag({
|
|
|
57
69
|
days,
|
|
58
70
|
onEventTimeChange,
|
|
59
71
|
events,
|
|
72
|
+
timezone = getBrowserTimezone(),
|
|
60
73
|
}: UseEventDragOptions) {
|
|
61
74
|
const [dragState, setDragState] = useState<DragState | null>(null);
|
|
62
75
|
const dragStateRef = useRef<DragState | null>(null);
|
|
@@ -127,10 +140,13 @@ export function useEventDrag({
|
|
|
127
140
|
// Compute current event position
|
|
128
141
|
const evStart = parseISO(event.start);
|
|
129
142
|
const evEnd = parseISO(event.end);
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
const
|
|
143
|
+
const eventDateKey =
|
|
144
|
+
getEventDateKey(event, timezone) ?? dateToCalendarDateKey(evStart);
|
|
145
|
+
const eventDay = days?.[dayIndex] ?? dateKeyToDate(eventDateKey);
|
|
146
|
+
const segment = getEventSegmentForCalendarDay(event, eventDay, timezone);
|
|
147
|
+
const startMinutes =
|
|
148
|
+
segment?.startMinutes ??
|
|
149
|
+
(evStart.getTime() - startOfDay(evStart).getTime()) / 60000;
|
|
134
150
|
const durationMinutes = (evEnd.getTime() - evStart.getTime()) / 60000;
|
|
135
151
|
|
|
136
152
|
const originalTop = Math.max(0, (startMinutes / 60) * hourHeight);
|
|
@@ -172,6 +188,7 @@ export function useEventDrag({
|
|
|
172
188
|
getScrollTop,
|
|
173
189
|
startHour,
|
|
174
190
|
hourHeight,
|
|
191
|
+
timezone,
|
|
175
192
|
],
|
|
176
193
|
);
|
|
177
194
|
|
|
@@ -288,20 +305,39 @@ export function useEventDrag({
|
|
|
288
305
|
pxToMinutes(state.currentHeight),
|
|
289
306
|
);
|
|
290
307
|
|
|
291
|
-
// Determine the base day
|
|
308
|
+
// Determine the base day in the visible calendar timezone.
|
|
292
309
|
const originalStart = parseISO(state.event.start);
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
const
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
)
|
|
304
|
-
|
|
310
|
+
const baseDay =
|
|
311
|
+
days && state.currentDayIndex !== state.startDayIndex
|
|
312
|
+
? days[state.currentDayIndex]
|
|
313
|
+
: dateKeyToDate(
|
|
314
|
+
getEventDateKey(state.event, timezone) ??
|
|
315
|
+
dateToCalendarDateKey(originalStart),
|
|
316
|
+
);
|
|
317
|
+
const baseDate = dateToCalendarDateKey(baseDay);
|
|
318
|
+
const startTotalMinutes = startHour * 60 + topMinutes;
|
|
319
|
+
const endTotalMinutes = startTotalMinutes + heightMinutes;
|
|
320
|
+
const toZonedIso = (totalMinutes: number) => {
|
|
321
|
+
const dayOffset = Math.floor(totalMinutes / (24 * 60));
|
|
322
|
+
const minuteOfDay = totalMinutes - dayOffset * 24 * 60;
|
|
323
|
+
const hour = Math.floor(minuteOfDay / 60);
|
|
324
|
+
const minute = Math.round(minuteOfDay % 60);
|
|
325
|
+
const normalizedMinute = minute === 60 ? 0 : minute;
|
|
326
|
+
const normalizedHour = minute === 60 ? hour + 1 : hour;
|
|
327
|
+
const time =
|
|
328
|
+
normalizedHour >= 24
|
|
329
|
+
? "00:00"
|
|
330
|
+
: `${String(normalizedHour).padStart(2, "0")}:${String(
|
|
331
|
+
normalizedMinute,
|
|
332
|
+
).padStart(2, "0")}`;
|
|
333
|
+
return dateKeyToTimezoneIso(
|
|
334
|
+
addCalendarDays(baseDate, dayOffset),
|
|
335
|
+
time,
|
|
336
|
+
timezone,
|
|
337
|
+
);
|
|
338
|
+
};
|
|
339
|
+
const newStart = new Date(toZonedIso(startTotalMinutes));
|
|
340
|
+
const newEnd = new Date(toZonedIso(endTotalMinutes));
|
|
305
341
|
|
|
306
342
|
onEventTimeChange(state.eventId, newStart, newEnd);
|
|
307
343
|
}
|
|
@@ -314,6 +350,7 @@ export function useEventDrag({
|
|
|
314
350
|
days,
|
|
315
351
|
startHour,
|
|
316
352
|
onEventTimeChange,
|
|
353
|
+
timezone,
|
|
317
354
|
]);
|
|
318
355
|
|
|
319
356
|
const cancelDrag = useCallback(() => {
|
|
@@ -664,6 +664,7 @@ const enUS = {
|
|
|
664
664
|
},
|
|
665
665
|
},
|
|
666
666
|
calendarView: {
|
|
667
|
+
addWorkingLocation: "Add working location",
|
|
667
668
|
addTitleBeforeCreate: "Add a title before creating the event",
|
|
668
669
|
calendarSettingsLoading:
|
|
669
670
|
"Calendar settings are still loading. Try again in a moment.",
|
|
@@ -692,6 +693,11 @@ const enUS = {
|
|
|
692
693
|
updatingEvent: "Updating event...",
|
|
693
694
|
updatingRecurringEvent: "Updating recurring event...",
|
|
694
695
|
week: "Week",
|
|
696
|
+
timezoneSwitchTitle: "Use your browser timezone?",
|
|
697
|
+
timezoneSwitchDescription:
|
|
698
|
+
"Calendar is pinned to {{savedTimezone}}, but your browser is in {{browserTimezone}}. Switch the calendar timezone?",
|
|
699
|
+
timezoneSwitchKeep: "Keep {{timezone}}",
|
|
700
|
+
timezoneSwitchSwitch: "Switch to {{timezone}}",
|
|
695
701
|
},
|
|
696
702
|
eventForm: {
|
|
697
703
|
addAttachment: "Add attachment",
|
|
@@ -8014,6 +8020,7 @@ const translatedCalendarRawBurnDown = {
|
|
|
8014
8020
|
yourInformation: "你的信息",
|
|
8015
8021
|
},
|
|
8016
8022
|
calendarView: {
|
|
8023
|
+
addWorkingLocation: "添加工作地点",
|
|
8017
8024
|
addTitleBeforeCreate: "创建事件前请添加标题",
|
|
8018
8025
|
calendarSettingsLoading: "日历设置仍在加载。请稍后再试。",
|
|
8019
8026
|
day: "日",
|
|
@@ -8041,6 +8048,11 @@ const translatedCalendarRawBurnDown = {
|
|
|
8041
8048
|
updatingEvent: "正在更新事件...",
|
|
8042
8049
|
updatingRecurringEvent: "正在更新重复事件...",
|
|
8043
8050
|
week: "周",
|
|
8051
|
+
timezoneSwitchTitle: "使用浏览器时区?",
|
|
8052
|
+
timezoneSwitchDescription:
|
|
8053
|
+
"日历固定为 {{savedTimezone}},但浏览器使用 {{browserTimezone}}。要切换日历时区吗?",
|
|
8054
|
+
timezoneSwitchKeep: "保留 {{timezone}}",
|
|
8055
|
+
timezoneSwitchSwitch: "切换到 {{timezone}}",
|
|
8044
8056
|
},
|
|
8045
8057
|
routeTitles: {
|
|
8046
8058
|
bookingLinks: "预约链接 — Calendar",
|
|
@@ -8183,6 +8195,7 @@ const translatedCalendarRawBurnDown = {
|
|
|
8183
8195
|
yourInformation: "Tu información",
|
|
8184
8196
|
},
|
|
8185
8197
|
calendarView: {
|
|
8198
|
+
addWorkingLocation: "Añadir ubicación de trabajo",
|
|
8186
8199
|
addTitleBeforeCreate: "Añade un título antes de crear el evento",
|
|
8187
8200
|
calendarSettingsLoading:
|
|
8188
8201
|
"La configuración del calendario aún se está cargando. Inténtalo de nuevo en un momento.",
|
|
@@ -8213,6 +8226,11 @@ const translatedCalendarRawBurnDown = {
|
|
|
8213
8226
|
updatingEvent: "Actualizando evento...",
|
|
8214
8227
|
updatingRecurringEvent: "Actualizando evento recurrente...",
|
|
8215
8228
|
week: "Semana",
|
|
8229
|
+
timezoneSwitchTitle: "¿Usar la zona horaria del navegador?",
|
|
8230
|
+
timezoneSwitchDescription:
|
|
8231
|
+
"El calendario está fijado en {{savedTimezone}}, pero tu navegador usa {{browserTimezone}}. ¿Cambiar la zona horaria del calendario?",
|
|
8232
|
+
timezoneSwitchKeep: "Mantener {{timezone}}",
|
|
8233
|
+
timezoneSwitchSwitch: "Cambiar a {{timezone}}",
|
|
8216
8234
|
},
|
|
8217
8235
|
routeTitles: {
|
|
8218
8236
|
bookingLinks: "Enlaces de reserva — Calendar",
|
|
@@ -8361,6 +8379,7 @@ const translatedCalendarRawBurnDown = {
|
|
|
8361
8379
|
yourInformation: "Vos informations",
|
|
8362
8380
|
},
|
|
8363
8381
|
calendarView: {
|
|
8382
|
+
addWorkingLocation: "Ajouter un lieu de travail",
|
|
8364
8383
|
addTitleBeforeCreate: "Ajoutez un titre avant de créer l'événement",
|
|
8365
8384
|
calendarSettingsLoading:
|
|
8366
8385
|
"Les paramètres du calendrier sont encore en cours de chargement. Réessayez dans un instant.",
|
|
@@ -8389,6 +8408,11 @@ const translatedCalendarRawBurnDown = {
|
|
|
8389
8408
|
updatingEvent: "Mise à jour de l'événement...",
|
|
8390
8409
|
updatingRecurringEvent: "Mise à jour de l'événement récurrent...",
|
|
8391
8410
|
week: "Semaine",
|
|
8411
|
+
timezoneSwitchTitle: "Utiliser le fuseau horaire du navigateur ?",
|
|
8412
|
+
timezoneSwitchDescription:
|
|
8413
|
+
"Le calendrier est fixé sur {{savedTimezone}}, mais votre navigateur utilise {{browserTimezone}}. Changer le fuseau horaire du calendrier ?",
|
|
8414
|
+
timezoneSwitchKeep: "Conserver {{timezone}}",
|
|
8415
|
+
timezoneSwitchSwitch: "Passer à {{timezone}}",
|
|
8392
8416
|
},
|
|
8393
8417
|
routeTitles: {
|
|
8394
8418
|
bookingLinks: "Liens de réservation — Calendar",
|
|
@@ -8539,6 +8563,7 @@ const translatedCalendarRawBurnDown = {
|
|
|
8539
8563
|
yourInformation: "Deine Informationen",
|
|
8540
8564
|
},
|
|
8541
8565
|
calendarView: {
|
|
8566
|
+
addWorkingLocation: "Arbeitsort hinzufügen",
|
|
8542
8567
|
addTitleBeforeCreate:
|
|
8543
8568
|
"Fügen Sie einen Titel hinzu, bevor Sie das Ereignis erstellen",
|
|
8544
8569
|
calendarSettingsLoading:
|
|
@@ -8569,6 +8594,11 @@ const translatedCalendarRawBurnDown = {
|
|
|
8569
8594
|
updatingEvent: "Ereignis wird aktualisiert...",
|
|
8570
8595
|
updatingRecurringEvent: "Wiederkehrendes Ereignis wird aktualisiert...",
|
|
8571
8596
|
week: "Woche",
|
|
8597
|
+
timezoneSwitchTitle: "Browser-Zeitzone verwenden?",
|
|
8598
|
+
timezoneSwitchDescription:
|
|
8599
|
+
"Der Kalender ist auf {{savedTimezone}} festgelegt, aber Ihr Browser verwendet {{browserTimezone}}. Kalenderzeitzone wechseln?",
|
|
8600
|
+
timezoneSwitchKeep: "{{timezone}} beibehalten",
|
|
8601
|
+
timezoneSwitchSwitch: "Zu {{timezone}} wechseln",
|
|
8572
8602
|
},
|
|
8573
8603
|
routeTitles: {
|
|
8574
8604
|
bookingLinks: "Buchungslinks — Calendar",
|
|
@@ -8718,6 +8748,7 @@ const translatedCalendarRawBurnDown = {
|
|
|
8718
8748
|
yourInformation: "あなたの情報",
|
|
8719
8749
|
},
|
|
8720
8750
|
calendarView: {
|
|
8751
|
+
addWorkingLocation: "勤務場所を追加",
|
|
8721
8752
|
addTitleBeforeCreate: "イベントを作成する前にタイトルを追加してください",
|
|
8722
8753
|
calendarSettingsLoading:
|
|
8723
8754
|
"カレンダー設定を読み込み中です。少し待ってからもう一度お試しください。",
|
|
@@ -8746,6 +8777,11 @@ const translatedCalendarRawBurnDown = {
|
|
|
8746
8777
|
updatingEvent: "イベントを更新中...",
|
|
8747
8778
|
updatingRecurringEvent: "繰り返しイベントを更新中...",
|
|
8748
8779
|
week: "週",
|
|
8780
|
+
timezoneSwitchTitle: "ブラウザのタイムゾーンを使用しますか?",
|
|
8781
|
+
timezoneSwitchDescription:
|
|
8782
|
+
"カレンダーは {{savedTimezone}} に固定されていますが、ブラウザは {{browserTimezone}} を使用しています。カレンダーのタイムゾーンを切り替えますか?",
|
|
8783
|
+
timezoneSwitchKeep: "{{timezone}} を維持",
|
|
8784
|
+
timezoneSwitchSwitch: "{{timezone}} に切り替え",
|
|
8749
8785
|
},
|
|
8750
8786
|
routeTitles: {
|
|
8751
8787
|
bookingLinks: "予約リンク — Calendar",
|
|
@@ -8890,6 +8926,7 @@ const translatedCalendarRawBurnDown = {
|
|
|
8890
8926
|
yourInformation: "내 정보",
|
|
8891
8927
|
},
|
|
8892
8928
|
calendarView: {
|
|
8929
|
+
addWorkingLocation: "근무 위치 추가",
|
|
8893
8930
|
addTitleBeforeCreate: "이벤트를 만들기 전에 제목을 추가하세요",
|
|
8894
8931
|
calendarSettingsLoading:
|
|
8895
8932
|
"캘린더 설정을 아직 불러오는 중입니다. 잠시 후 다시 시도하세요.",
|
|
@@ -8919,6 +8956,11 @@ const translatedCalendarRawBurnDown = {
|
|
|
8919
8956
|
updatingEvent: "이벤트 업데이트 중...",
|
|
8920
8957
|
updatingRecurringEvent: "반복 이벤트 업데이트 중...",
|
|
8921
8958
|
week: "주",
|
|
8959
|
+
timezoneSwitchTitle: "브라우저 시간대를 사용할까요?",
|
|
8960
|
+
timezoneSwitchDescription:
|
|
8961
|
+
"캘린더는 {{savedTimezone}}에 고정되어 있지만 브라우저는 {{browserTimezone}}을(를) 사용합니다. 캘린더 시간대를 전환할까요?",
|
|
8962
|
+
timezoneSwitchKeep: "{{timezone}} 유지",
|
|
8963
|
+
timezoneSwitchSwitch: "{{timezone}}(으)로 전환",
|
|
8922
8964
|
},
|
|
8923
8965
|
routeTitles: {
|
|
8924
8966
|
bookingLinks: "예약 링크 — Calendar",
|
|
@@ -9065,6 +9107,7 @@ const translatedCalendarRawBurnDown = {
|
|
|
9065
9107
|
yourInformation: "Suas informações",
|
|
9066
9108
|
},
|
|
9067
9109
|
calendarView: {
|
|
9110
|
+
addWorkingLocation: "Adicionar local de trabalho",
|
|
9068
9111
|
addTitleBeforeCreate: "Adicione um título antes de criar o evento",
|
|
9069
9112
|
calendarSettingsLoading:
|
|
9070
9113
|
"As configurações do calendário ainda estão carregando. Tente novamente em instantes.",
|
|
@@ -9094,6 +9137,11 @@ const translatedCalendarRawBurnDown = {
|
|
|
9094
9137
|
updatingEvent: "Atualizando evento...",
|
|
9095
9138
|
updatingRecurringEvent: "Atualizando evento recorrente...",
|
|
9096
9139
|
week: "Semana",
|
|
9140
|
+
timezoneSwitchTitle: "Usar o fuso horário do navegador?",
|
|
9141
|
+
timezoneSwitchDescription:
|
|
9142
|
+
"O calendário está fixado em {{savedTimezone}}, mas o navegador usa {{browserTimezone}}. Mudar o fuso horário do calendário?",
|
|
9143
|
+
timezoneSwitchKeep: "Manter {{timezone}}",
|
|
9144
|
+
timezoneSwitchSwitch: "Mudar para {{timezone}}",
|
|
9097
9145
|
},
|
|
9098
9146
|
routeTitles: {
|
|
9099
9147
|
bookingLinks: "Links de reserva — Calendar",
|
|
@@ -9240,6 +9288,7 @@ const translatedCalendarRawBurnDown = {
|
|
|
9240
9288
|
yourInformation: "आपकी जानकारी",
|
|
9241
9289
|
},
|
|
9242
9290
|
calendarView: {
|
|
9291
|
+
addWorkingLocation: "कार्य स्थान जोड़ें",
|
|
9243
9292
|
addTitleBeforeCreate: "इवेंट बनाने से पहले शीर्षक जोड़ें",
|
|
9244
9293
|
calendarSettingsLoading:
|
|
9245
9294
|
"कैलेंडर सेटिंग अभी लोड हो रही हैं। कृपया थोड़ी देर में फिर कोशिश करें।",
|
|
@@ -9268,6 +9317,11 @@ const translatedCalendarRawBurnDown = {
|
|
|
9268
9317
|
updatingEvent: "इवेंट अपडेट हो रहा है...",
|
|
9269
9318
|
updatingRecurringEvent: "दोहराया जाने वाला इवेंट अपडेट हो रहा है...",
|
|
9270
9319
|
week: "सप्ताह",
|
|
9320
|
+
timezoneSwitchTitle: "ब्राउज़र का टाइमज़ोन इस्तेमाल करें?",
|
|
9321
|
+
timezoneSwitchDescription:
|
|
9322
|
+
"कैलेंडर {{savedTimezone}} पर पिन है, लेकिन आपका ब्राउज़र {{browserTimezone}} पर है। कैलेंडर टाइमज़ोन बदलें?",
|
|
9323
|
+
timezoneSwitchKeep: "{{timezone}} रखें",
|
|
9324
|
+
timezoneSwitchSwitch: "{{timezone}} पर बदलें",
|
|
9271
9325
|
},
|
|
9272
9326
|
routeTitles: {
|
|
9273
9327
|
bookingLinks: "बुकिंग लिंक — Calendar",
|
|
@@ -9413,6 +9467,7 @@ const translatedCalendarRawBurnDown = {
|
|
|
9413
9467
|
yourInformation: "معلوماتك",
|
|
9414
9468
|
},
|
|
9415
9469
|
calendarView: {
|
|
9470
|
+
addWorkingLocation: "إضافة موقع العمل",
|
|
9416
9471
|
addTitleBeforeCreate: "أضف عنوانًا قبل إنشاء الحدث",
|
|
9417
9472
|
calendarSettingsLoading:
|
|
9418
9473
|
"لا تزال إعدادات التقويم قيد التحميل. حاول مرة أخرى بعد قليل.",
|
|
@@ -9441,6 +9496,11 @@ const translatedCalendarRawBurnDown = {
|
|
|
9441
9496
|
updatingEvent: "جارٍ تحديث الحدث...",
|
|
9442
9497
|
updatingRecurringEvent: "جارٍ تحديث الحدث المتكرر...",
|
|
9443
9498
|
week: "الأسبوع",
|
|
9499
|
+
timezoneSwitchTitle: "استخدام المنطقة الزمنية للمتصفح؟",
|
|
9500
|
+
timezoneSwitchDescription:
|
|
9501
|
+
"التقويم مثبت على {{savedTimezone}}، لكن متصفحك يستخدم {{browserTimezone}}. هل تريد تبديل المنطقة الزمنية للتقويم؟",
|
|
9502
|
+
timezoneSwitchKeep: "الاحتفاظ بـ {{timezone}}",
|
|
9503
|
+
timezoneSwitchSwitch: "التبديل إلى {{timezone}}",
|
|
9444
9504
|
},
|
|
9445
9505
|
routeTitles: {
|
|
9446
9506
|
bookingLinks: "روابط الحجز — Calendar",
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { CalendarEvent } from "@shared/api";
|
|
2
|
-
import { addDays, format, parseISO, startOfDay } from "date-fns";
|
|
3
2
|
|
|
3
|
+
import {
|
|
4
|
+
addCalendarDays,
|
|
5
|
+
dateToCalendarDateKey,
|
|
6
|
+
eventOverlapsCalendarDay,
|
|
7
|
+
getBrowserTimezone,
|
|
8
|
+
} from "@/lib/calendar-timezone";
|
|
4
9
|
import { getFullDayOutOfOfficeDateRange } from "@/lib/out-of-office";
|
|
5
10
|
import { isWorkingLocationEvent } from "@/lib/working-location";
|
|
6
11
|
|
|
@@ -37,22 +42,24 @@ export function partitionAllDayEvents(events: CalendarEvent[]) {
|
|
|
37
42
|
export function getAllDaySpan(
|
|
38
43
|
event: CalendarEvent,
|
|
39
44
|
days: Date[],
|
|
45
|
+
timezone: string = getBrowserTimezone(),
|
|
40
46
|
): Omit<AllDaySpan, "event"> | null {
|
|
41
|
-
const eventStart = parseISO(event.start);
|
|
42
|
-
const eventEnd = event.end ? parseISO(event.end) : addDays(eventStart, 1);
|
|
43
47
|
const outOfOfficeRange = getFullDayOutOfOfficeDateRange(event);
|
|
48
|
+
const eventStartDate = event.start.slice(0, 10);
|
|
49
|
+
const eventEndDate =
|
|
50
|
+
event.end?.slice(0, 10) ?? addCalendarDays(eventStartDate, 1);
|
|
44
51
|
|
|
45
52
|
let startCol = -1;
|
|
46
53
|
let endCol = -1;
|
|
47
54
|
|
|
48
55
|
for (let index = 0; index < days.length; index++) {
|
|
49
|
-
const
|
|
50
|
-
const dayEnd = addDays(dayStart, 1);
|
|
51
|
-
const dayDate = format(days[index], "yyyy-MM-dd");
|
|
56
|
+
const dayDate = dateToCalendarDateKey(days[index]);
|
|
52
57
|
const overlaps = outOfOfficeRange
|
|
53
58
|
? dayDate >= outOfOfficeRange.startDate &&
|
|
54
59
|
dayDate < outOfOfficeRange.endDateExclusive
|
|
55
|
-
:
|
|
60
|
+
: event.allDay
|
|
61
|
+
? eventStartDate <= dayDate && eventEndDate > dayDate
|
|
62
|
+
: eventOverlapsCalendarDay(event, days[index], timezone);
|
|
56
63
|
if (overlaps) {
|
|
57
64
|
if (startCol === -1) startCol = index;
|
|
58
65
|
endCol = index;
|
|
@@ -71,10 +78,11 @@ function compareSpans(a: AllDaySpan, b: AllDaySpan): number {
|
|
|
71
78
|
export function layoutAllDayEvents(
|
|
72
79
|
events: CalendarEvent[],
|
|
73
80
|
days: Date[],
|
|
81
|
+
timezone: string = getBrowserTimezone(),
|
|
74
82
|
): AllDayLayout {
|
|
75
83
|
const spans = events
|
|
76
84
|
.map((event) => {
|
|
77
|
-
const span = getAllDaySpan(event, days);
|
|
85
|
+
const span = getAllDaySpan(event, days, timezone);
|
|
78
86
|
return span ? { event, ...span } : null;
|
|
79
87
|
})
|
|
80
88
|
.filter((span): span is AllDaySpan => span !== null)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { CalendarEventDraft } from "@shared/api";
|
|
2
|
+
|
|
3
|
+
import { addCalendarDays, dateToCalendarDateKey } from "./calendar-timezone";
|
|
4
|
+
|
|
5
|
+
export function resolveDraftWorkingLocation(
|
|
6
|
+
draft: Pick<
|
|
7
|
+
CalendarEventDraft,
|
|
8
|
+
"workingLocationType" | "workingLocationLabel" | "location"
|
|
9
|
+
>,
|
|
10
|
+
): {
|
|
11
|
+
workingLocationType: "homeOffice" | "officeLocation" | "customLocation";
|
|
12
|
+
workingLocationLabel: string;
|
|
13
|
+
} {
|
|
14
|
+
return {
|
|
15
|
+
workingLocationType: draft.workingLocationType ?? "homeOffice",
|
|
16
|
+
// Drafts initialize `location` to "", so `??` would drop the Other name.
|
|
17
|
+
workingLocationLabel: (
|
|
18
|
+
draft.workingLocationLabel ||
|
|
19
|
+
draft.location ||
|
|
20
|
+
""
|
|
21
|
+
).trim(),
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export function buildWorkingLocationDraft({
|
|
26
|
+
id,
|
|
27
|
+
date,
|
|
28
|
+
accountEmail,
|
|
29
|
+
now = new Date().toISOString(),
|
|
30
|
+
}: {
|
|
31
|
+
id: string;
|
|
32
|
+
date: Date;
|
|
33
|
+
accountEmail?: string;
|
|
34
|
+
now?: string;
|
|
35
|
+
}): CalendarEventDraft {
|
|
36
|
+
const dateKey = dateToCalendarDateKey(date);
|
|
37
|
+
return {
|
|
38
|
+
id,
|
|
39
|
+
title: "",
|
|
40
|
+
description: "",
|
|
41
|
+
location: "",
|
|
42
|
+
start: dateKey,
|
|
43
|
+
end: addCalendarDays(dateKey, 1),
|
|
44
|
+
startTimeZone: undefined,
|
|
45
|
+
endTimeZone: undefined,
|
|
46
|
+
allDay: true,
|
|
47
|
+
eventType: "workingLocation",
|
|
48
|
+
workingLocationType: "homeOffice",
|
|
49
|
+
workingLocationLabel: "",
|
|
50
|
+
transparency: "transparent",
|
|
51
|
+
visibility: "public",
|
|
52
|
+
accountEmail,
|
|
53
|
+
createdAt: now,
|
|
54
|
+
updatedAt: now,
|
|
55
|
+
};
|
|
56
|
+
}
|