refactor: code clean up
Signed-off-by: Sebastian Krupinski <krupinski01@gmail.com>
This commit is contained in:
+19
-20
@@ -62,18 +62,17 @@ const {
|
|||||||
editingCollection,
|
editingCollection,
|
||||||
collectionEditorMode,
|
collectionEditorMode,
|
||||||
collectionEditorType,
|
collectionEditorType,
|
||||||
isTaskView,
|
isTasksSection,
|
||||||
} = storeToRefs(chronoUiStore);
|
} = storeToRefs(chronoUiStore);
|
||||||
|
|
||||||
const { loadVisibleRange: loadVisibleRangeOperations } = chronoOperationsStore;
|
const { loadVisibleRange: loadVisibleRangeOperations } = chronoOperationsStore;
|
||||||
|
|
||||||
const {
|
const {
|
||||||
initialize,
|
initialize,
|
||||||
setViewMode,
|
selectSection,
|
||||||
setCurrentDate,
|
selectDate,
|
||||||
selectCalendar,
|
selectCollection,
|
||||||
openEditCalendar,
|
openEditCalendar,
|
||||||
selectTaskList,
|
|
||||||
openEditTaskList,
|
openEditTaskList,
|
||||||
createEventFromDate,
|
createEventFromDate,
|
||||||
startEditingSelectedEntity,
|
startEditingSelectedEntity,
|
||||||
@@ -120,10 +119,10 @@ async function onFilesSelected(event: Event) {
|
|||||||
if (files.length) await openImport(files)
|
if (files.length) await openImport(files)
|
||||||
}
|
}
|
||||||
|
|
||||||
function syncViewModeFromRoute() {
|
function selectSectionFromRoute() {
|
||||||
const routePath = route.path;
|
const routePath = route.path;
|
||||||
const mode = routePath.endsWith('/tasks') ? 'tasks' : 'calendar';
|
const section = routePath.endsWith('/tasks') ? 'tasks' : 'calendar';
|
||||||
setViewMode(mode);
|
selectSection(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleCalendarViewChange(view: CalendarViewType) {
|
function handleCalendarViewChange(view: CalendarViewType) {
|
||||||
@@ -150,16 +149,16 @@ watch(
|
|||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
try {
|
try {
|
||||||
syncViewModeFromRoute();
|
selectSectionFromRoute();
|
||||||
await initialize(isTaskView.value ? 'tasks' : 'calendar');
|
await initialize(isTasksSection.value ? 'tasks' : 'calendar');
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('[Chrono] - Failed to load data from ChronoManager:', error);
|
console.error('[Chrono] - Failed to load data from ChronoManager:', error);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
watch(() => route.fullPath, async () => {
|
watch(() => route.fullPath, async () => {
|
||||||
syncViewModeFromRoute();
|
selectSectionFromRoute();
|
||||||
if (isTaskView.value) {
|
if (isTasksSection.value) {
|
||||||
await ensureTasksLoaded();
|
await ensureTasksLoaded();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -187,7 +186,7 @@ watch(() => route.fullPath, async () => {
|
|||||||
|
|
||||||
<!-- View Switcher for Calendar -->
|
<!-- View Switcher for Calendar -->
|
||||||
<v-btn-toggle
|
<v-btn-toggle
|
||||||
v-if="!isTaskView"
|
v-if="!isTasksSection"
|
||||||
:model-value="calendarView"
|
:model-value="calendarView"
|
||||||
color="primary"
|
color="primary"
|
||||||
variant="outlined"
|
variant="outlined"
|
||||||
@@ -214,11 +213,11 @@ watch(() => route.fullPath, async () => {
|
|||||||
>
|
>
|
||||||
<div class="pa-4">
|
<div class="pa-4">
|
||||||
<CollectionList
|
<CollectionList
|
||||||
v-if="!isTaskView"
|
v-if="!isTasksSection"
|
||||||
:collections="collections"
|
:collections="collections"
|
||||||
:selected-collection="selectedCollection"
|
:selected-collection="selectedCollection"
|
||||||
type="calendar"
|
type="calendar"
|
||||||
@select="selectCalendar"
|
@select="selectCollection"
|
||||||
@edit="openEditCalendar"
|
@edit="openEditCalendar"
|
||||||
@toggle-visibility="toggleCalendarVisibility"
|
@toggle-visibility="toggleCalendarVisibility"
|
||||||
/>
|
/>
|
||||||
@@ -227,12 +226,12 @@ watch(() => route.fullPath, async () => {
|
|||||||
:collections="collections"
|
:collections="collections"
|
||||||
:selected-collection="selectedCollection"
|
:selected-collection="selectedCollection"
|
||||||
type="tasklist"
|
type="tasklist"
|
||||||
@select="selectTaskList"
|
@select="selectCollection"
|
||||||
@edit="openEditTaskList"
|
@edit="openEditTaskList"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<v-btn
|
<v-btn
|
||||||
v-if="!isTaskView"
|
v-if="!isTasksSection"
|
||||||
variant="tonal"
|
variant="tonal"
|
||||||
color="primary"
|
color="primary"
|
||||||
block
|
block
|
||||||
@@ -262,7 +261,7 @@ watch(() => route.fullPath, async () => {
|
|||||||
<input ref="fileInputRef" type="file" accept=".ics,text/calendar" multiple class="d-none" @change="onFilesSelected" />
|
<input ref="fileInputRef" type="file" accept=".ics,text/calendar" multiple class="d-none" @change="onFilesSelected" />
|
||||||
|
|
||||||
<!-- Mini Calendar Widget -->
|
<!-- Mini Calendar Widget -->
|
||||||
<v-card v-if="!isTaskView" class="mt-4" variant="outlined">
|
<v-card v-if="!isTasksSection" class="mt-4" variant="outlined">
|
||||||
<v-card-text class="pa-2">
|
<v-card-text class="pa-2">
|
||||||
<MiniCalendar v-model="currentDate" />
|
<MiniCalendar v-model="currentDate" />
|
||||||
</v-card-text>
|
</v-card-text>
|
||||||
@@ -299,7 +298,7 @@ watch(() => route.fullPath, async () => {
|
|||||||
<v-progress-linear v-if="loading" indeterminate color="primary" />
|
<v-progress-linear v-if="loading" indeterminate color="primary" />
|
||||||
|
|
||||||
<CalendarView
|
<CalendarView
|
||||||
v-if="!isTaskView"
|
v-if="!isTasksSection"
|
||||||
:view="calendarView"
|
:view="calendarView"
|
||||||
:current-date="currentDate"
|
:current-date="currentDate"
|
||||||
:calendars="calendars"
|
:calendars="calendars"
|
||||||
@@ -307,7 +306,7 @@ watch(() => route.fullPath, async () => {
|
|||||||
:initial-agenda-view-span="agendaViewSpan"
|
:initial-agenda-view-span="agendaViewSpan"
|
||||||
@event-click="editEvent"
|
@event-click="editEvent"
|
||||||
@date-click="createEventFromDate"
|
@date-click="createEventFromDate"
|
||||||
@update:current-date="setCurrentDate"
|
@update:current-date="selectDate"
|
||||||
@update:days-span="setDaysViewSpan"
|
@update:days-span="setDaysViewSpan"
|
||||||
@update:agenda-span="setAgendaViewSpan"
|
@update:agenda-span="setAgendaViewSpan"
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import { useEntitiesStore } from '@ChronoManager/stores/entitiesStore'
|
|||||||
import { useServicesStore } from '@ChronoManager/stores/servicesStore'
|
import { useServicesStore } from '@ChronoManager/stores/servicesStore'
|
||||||
import { useImportStore } from '@ChronoManager/stores/importStore'
|
import { useImportStore } from '@ChronoManager/stores/importStore'
|
||||||
import { EpochSpan } from '@/types/date'
|
import { EpochSpan } from '@/types/date'
|
||||||
|
import type { ChronoSection } from '@/types'
|
||||||
|
|
||||||
type ChronoEntityProperties = EventObject | TaskObject
|
type ChronoEntityProperties = EventObject | TaskObject
|
||||||
|
|
||||||
@@ -162,7 +163,7 @@ export const useChronoOperationsStore = defineStore('chronoOperationsStore', ()
|
|||||||
tasksLoaded.value = true
|
tasksLoaded.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initialize(viewMode: 'calendar' | 'tasks' = 'calendar') {
|
async function initialize(section: ChronoSection = 'calendar') {
|
||||||
loading.value = true
|
loading.value = true
|
||||||
try {
|
try {
|
||||||
if (!collectionsLoaded.value) {
|
if (!collectionsLoaded.value) {
|
||||||
@@ -171,7 +172,7 @@ export const useChronoOperationsStore = defineStore('chronoOperationsStore', ()
|
|||||||
collectionsLoaded.value = true
|
collectionsLoaded.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if (viewMode === 'tasks') {
|
if (section === 'tasks') {
|
||||||
await ensureTasksLoaded()
|
await ensureTasksLoaded()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+15
-19
@@ -5,12 +5,13 @@ import { EntityObject } from '@ChronoManager/models/entity'
|
|||||||
import { EventObject } from '@ChronoManager/models/event'
|
import { EventObject } from '@ChronoManager/models/event'
|
||||||
import { TaskObject } from '@ChronoManager/models/task'
|
import { TaskObject } from '@ChronoManager/models/task'
|
||||||
import type { ServiceObject } from '@ChronoManager/models/service'
|
import type { ServiceObject } from '@ChronoManager/models/service'
|
||||||
|
import type { ChronoSection } from '@/types'
|
||||||
import { useChronoOperationsStore } from '@/stores/chronoOperationsStore'
|
import { useChronoOperationsStore } from '@/stores/chronoOperationsStore'
|
||||||
|
|
||||||
export const useChronoUiStore = defineStore('chronoUiStore', () => {
|
export const useChronoUiStore = defineStore('chronoUiStore', () => {
|
||||||
const operationsStore = useChronoOperationsStore()
|
const operationsStore = useChronoOperationsStore()
|
||||||
|
|
||||||
const viewMode = ref<'calendar' | 'tasks'>('calendar')
|
const section = ref<ChronoSection>('calendar')
|
||||||
const currentDate = ref(new Date())
|
const currentDate = ref(new Date())
|
||||||
const sidebarVisible = ref(true)
|
const sidebarVisible = ref(true)
|
||||||
const selectedCollection = shallowRef<CollectionObject | null>(null)
|
const selectedCollection = shallowRef<CollectionObject | null>(null)
|
||||||
@@ -24,22 +25,18 @@ export const useChronoUiStore = defineStore('chronoUiStore', () => {
|
|||||||
const collectionEditorMode = ref<'create' | 'edit'>('create')
|
const collectionEditorMode = ref<'create' | 'edit'>('create')
|
||||||
const collectionEditorType = ref<'calendar' | 'tasklist'>('calendar')
|
const collectionEditorType = ref<'calendar' | 'tasklist'>('calendar')
|
||||||
|
|
||||||
const isTaskView = computed(() => viewMode.value === 'tasks')
|
const isTasksSection = computed(() => section.value === 'tasks')
|
||||||
|
|
||||||
function setViewMode(mode: 'calendar' | 'tasks') {
|
function selectSection(target: ChronoSection) {
|
||||||
viewMode.value = mode
|
section.value = target
|
||||||
}
|
}
|
||||||
|
|
||||||
function setCurrentDate(date: Date) {
|
function selectDate(date: Date) {
|
||||||
currentDate.value = new Date(date)
|
currentDate.value = new Date(date)
|
||||||
}
|
}
|
||||||
|
|
||||||
function selectCalendar(calendar: CollectionObject) {
|
function selectCollection(collection: CollectionObject) {
|
||||||
selectedCollection.value = calendar
|
selectedCollection.value = collection
|
||||||
}
|
|
||||||
|
|
||||||
function selectTaskList(list: CollectionObject) {
|
|
||||||
selectedCollection.value = list
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function openCollectionEditor(type: 'calendar' | 'tasklist') {
|
function openCollectionEditor(type: 'calendar' | 'tasklist') {
|
||||||
@@ -193,8 +190,8 @@ export const useChronoUiStore = defineStore('chronoUiStore', () => {
|
|||||||
await operationsStore.finishImport(refresh)
|
await operationsStore.finishImport(refresh)
|
||||||
}
|
}
|
||||||
|
|
||||||
async function initialize(viewMode: 'calendar' | 'tasks' = 'calendar') {
|
async function initialize(initialSection: ChronoSection = 'calendar') {
|
||||||
await operationsStore.initialize(viewMode)
|
await operationsStore.initialize(initialSection)
|
||||||
if (selectedCollection.value && !operationsStore.collections.some(
|
if (selectedCollection.value && !operationsStore.collections.some(
|
||||||
collection => collection.identifier === selectedCollection.value?.identifier,
|
collection => collection.identifier === selectedCollection.value?.identifier,
|
||||||
)) {
|
)) {
|
||||||
@@ -203,7 +200,7 @@ export const useChronoUiStore = defineStore('chronoUiStore', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
viewMode,
|
section,
|
||||||
currentDate,
|
currentDate,
|
||||||
sidebarVisible,
|
sidebarVisible,
|
||||||
selectedCollection,
|
selectedCollection,
|
||||||
@@ -216,11 +213,10 @@ export const useChronoUiStore = defineStore('chronoUiStore', () => {
|
|||||||
editingCollection,
|
editingCollection,
|
||||||
collectionEditorMode,
|
collectionEditorMode,
|
||||||
collectionEditorType,
|
collectionEditorType,
|
||||||
isTaskView,
|
isTasksSection,
|
||||||
setViewMode,
|
selectSection,
|
||||||
setCurrentDate,
|
selectDate,
|
||||||
selectCalendar,
|
selectCollection,
|
||||||
selectTaskList,
|
|
||||||
openCreateCalendar,
|
openCreateCalendar,
|
||||||
openCreateTaskList,
|
openCreateTaskList,
|
||||||
openEditCalendar,
|
openEditCalendar,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
// Local UI-specific types
|
// Local UI-specific types
|
||||||
|
export type ChronoSection = 'calendar' | 'tasks';
|
||||||
export type CalendarView = 'days' | 'month' | 'agenda';
|
export type CalendarView = 'days' | 'month' | 'agenda';
|
||||||
|
|
||||||
export interface ViewState {
|
export interface ViewState {
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import type { EntityObject } from '@ChronoManager/models/entity'
|
|||||||
import type { EventObject } from '@ChronoManager/models/event'
|
import type { EventObject } from '@ChronoManager/models/event'
|
||||||
import type { EventMutationObject } from '@ChronoManager/models/event-mutation'
|
import type { EventMutationObject } from '@ChronoManager/models/event-mutation'
|
||||||
import type { CalendarInstance } from '../types/instance'
|
import type { CalendarInstance } from '../types/instance'
|
||||||
import type { VisibleDateRange } from '../types'
|
|
||||||
import { parseCalendarDate, shiftLocalDays, startOfLocalDay } from './date'
|
import { parseCalendarDate, shiftLocalDays, startOfLocalDay } from './date'
|
||||||
import { EpochSpan } from '@/types/date'
|
import { EpochSpan } from '@/types/date'
|
||||||
|
|
||||||
@@ -96,7 +95,7 @@ function materializeInstance(
|
|||||||
durationDays: number | null,
|
durationDays: number | null,
|
||||||
recurring: boolean,
|
recurring: boolean,
|
||||||
mutation: EventMutationObject | undefined,
|
mutation: EventMutationObject | undefined,
|
||||||
range?: VisibleDateRange,
|
range?: EpochSpan,
|
||||||
): CalendarInstance | null {
|
): CalendarInstance | null {
|
||||||
if (mutation?.mutationExclusion === true) return null
|
if (mutation?.mutationExclusion === true) return null
|
||||||
|
|
||||||
@@ -208,7 +207,7 @@ function expandWeekly(
|
|||||||
start: Date,
|
start: Date,
|
||||||
durationMs: number,
|
durationMs: number,
|
||||||
durationDays: number | null,
|
durationDays: number | null,
|
||||||
range: VisibleDateRange,
|
range: EpochSpan,
|
||||||
mutations: Map<number, EventMutationObject>,
|
mutations: Map<number, EventMutationObject>,
|
||||||
): CalendarInstance[] {
|
): CalendarInstance[] {
|
||||||
const pattern = (entity.properties as EventObject).pattern!
|
const pattern = (entity.properties as EventObject).pattern!
|
||||||
@@ -227,13 +226,13 @@ function expandWeekly(
|
|||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
const intervalWeekStart = shiftLocalDays(weekStart, week * interval * 7)
|
const intervalWeekStart = shiftLocalDays(weekStart, week * interval * 7)
|
||||||
if (intervalWeekStart.getTime() >= range.endMs) break
|
if (intervalWeekStart.getTime() >= range.end) break
|
||||||
|
|
||||||
for (const weekday of weekdays) {
|
for (const weekday of weekdays) {
|
||||||
const candidate = shiftLocalDays(intervalWeekStart, weekday - 1)
|
const candidate = shiftLocalDays(intervalWeekStart, weekday - 1)
|
||||||
const candidateMs = candidate.getTime()
|
const candidateMs = candidate.getTime()
|
||||||
if (candidateMs < start.getTime()) continue
|
if (candidateMs < start.getTime()) continue
|
||||||
if (candidateMs >= range.endMs) return instances
|
if (candidateMs >= range.end) return instances
|
||||||
if (concludesMs !== null && candidateMs > concludesMs) return instances
|
if (concludesMs !== null && candidateMs > concludesMs) return instances
|
||||||
|
|
||||||
occurrenceCount += 1
|
occurrenceCount += 1
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import {
|
|||||||
describe('calendar visible ranges', () => {
|
describe('calendar visible ranges', () => {
|
||||||
it('uses a half-open range for a day span', () => {
|
it('uses a half-open range for a day span', () => {
|
||||||
const range = daysVisibleRange(new Date(2026, 5, 15, 13, 45), 7)
|
const range = daysVisibleRange(new Date(2026, 5, 15, 13, 45), 7)
|
||||||
const start = new Date(range.startMs)
|
const start = new Date(range.start)
|
||||||
const end = new Date(range.endMs)
|
const end = new Date(range.end)
|
||||||
|
|
||||||
expect([start.getFullYear(), start.getMonth(), start.getDate(), start.getHours()])
|
expect([start.getFullYear(), start.getMonth(), start.getDate(), start.getHours()])
|
||||||
.toEqual([2026, 5, 15, 0])
|
.toEqual([2026, 5, 15, 0])
|
||||||
@@ -20,8 +20,8 @@ describe('calendar visible ranges', () => {
|
|||||||
|
|
||||||
it('uses calendar-day arithmetic across a daylight-saving boundary', () => {
|
it('uses calendar-day arithmetic across a daylight-saving boundary', () => {
|
||||||
const range = daysVisibleRange(new Date(2026, 2, 8, 12), 1)
|
const range = daysVisibleRange(new Date(2026, 2, 8, 12), 1)
|
||||||
const start = new Date(range.startMs)
|
const start = new Date(range.start)
|
||||||
const end = new Date(range.endMs)
|
const end = new Date(range.end)
|
||||||
|
|
||||||
expect(start.getHours()).toBe(0)
|
expect(start.getHours()).toBe(0)
|
||||||
expect(end.getHours()).toBe(0)
|
expect(end.getHours()).toBe(0)
|
||||||
@@ -30,8 +30,8 @@ describe('calendar visible ranges', () => {
|
|||||||
|
|
||||||
it('includes every leading and trailing day rendered by a month grid', () => {
|
it('includes every leading and trailing day rendered by a month grid', () => {
|
||||||
const range = monthGridVisibleRange(new Date(2026, 5, 15))
|
const range = monthGridVisibleRange(new Date(2026, 5, 15))
|
||||||
const start = new Date(range.startMs)
|
const start = new Date(range.start)
|
||||||
const end = new Date(range.endMs)
|
const end = new Date(range.end)
|
||||||
|
|
||||||
expect([start.getFullYear(), start.getMonth(), start.getDate()]).toEqual([2026, 4, 31])
|
expect([start.getFullYear(), start.getMonth(), start.getDate()]).toEqual([2026, 4, 31])
|
||||||
expect([end.getFullYear(), end.getMonth(), end.getDate()]).toEqual([2026, 6, 5])
|
expect([end.getFullYear(), end.getMonth(), end.getDate()]).toEqual([2026, 6, 5])
|
||||||
@@ -39,8 +39,8 @@ describe('calendar visible ranges', () => {
|
|||||||
|
|
||||||
it('calculates a leap-year February grid', () => {
|
it('calculates a leap-year February grid', () => {
|
||||||
const range = monthGridVisibleRange(new Date(2024, 1, 29))
|
const range = monthGridVisibleRange(new Date(2024, 1, 29))
|
||||||
const start = new Date(range.startMs)
|
const start = new Date(range.start)
|
||||||
const end = new Date(range.endMs)
|
const end = new Date(range.end)
|
||||||
|
|
||||||
expect([start.getFullYear(), start.getMonth(), start.getDate()]).toEqual([2024, 0, 28])
|
expect([start.getFullYear(), start.getMonth(), start.getDate()]).toEqual([2024, 0, 28])
|
||||||
expect([end.getFullYear(), end.getMonth(), end.getDate()]).toEqual([2024, 2, 3])
|
expect([end.getFullYear(), end.getMonth(), end.getDate()]).toEqual([2024, 2, 3])
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ describe('entity instance expansion', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(instance.durationMs).toBe(60 * 60 * 1000)
|
expect(instance.durationMs).toBe(60 * 60 * 1000)
|
||||||
expect(new Date(instance.startMs).getHours()).toBe(9)
|
expect(new Date(instance.start).getHours()).toBe(9)
|
||||||
expect(new Date(instance.dayStartMs).getHours()).toBe(0)
|
expect(new Date(instance.dayStartMs).getHours()).toBe(0)
|
||||||
expect(instance.instanceId).toBeNull()
|
expect(instance.instanceId).toBeNull()
|
||||||
expect(instance.multiDay).toBe(false)
|
expect(instance.multiDay).toBe(false)
|
||||||
@@ -54,7 +54,7 @@ describe('entity instance expansion', () => {
|
|||||||
eventEntity('all-day', localIso(2026, 5, 20), localIso(2026, 5, 21), true),
|
eventEntity('all-day', localIso(2026, 5, 20), localIso(2026, 5, 21), true),
|
||||||
)
|
)
|
||||||
|
|
||||||
const end = new Date(instance.endMs)
|
const end = new Date(instance.end)
|
||||||
expect([end.getDate(), end.getHours()]).toEqual([21, 0])
|
expect([end.getDate(), end.getHours()]).toEqual([21, 0])
|
||||||
expect(new Date(instance.dayStartMs).getDate()).toBe(20)
|
expect(new Date(instance.dayStartMs).getDate()).toBe(20)
|
||||||
expect(instance.multiDay).toBe(false)
|
expect(instance.multiDay).toBe(false)
|
||||||
@@ -65,9 +65,9 @@ describe('entity instance expansion', () => {
|
|||||||
eventEntity('utc-all-day', '2025-03-27T00:00:00+00:00', '2025-03-28T00:00:00+00:00', true),
|
eventEntity('utc-all-day', '2025-03-27T00:00:00+00:00', '2025-03-28T00:00:00+00:00', true),
|
||||||
)
|
)
|
||||||
|
|
||||||
const start = new Date(instance.startMs)
|
const start = new Date(instance.start)
|
||||||
expect([start.getMonth(), start.getDate(), start.getHours()]).toEqual([2, 27, 0])
|
expect([start.getMonth(), start.getDate(), start.getHours()]).toEqual([2, 27, 0])
|
||||||
expect(new Date(instance.endMs).getDate()).toBe(28)
|
expect(new Date(instance.end).getDate()).toBe(28)
|
||||||
})
|
})
|
||||||
|
|
||||||
it('gives a zero-duration event a queryable minimum duration', () => {
|
it('gives a zero-duration event a queryable minimum duration', () => {
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ describe('daily recurrence', () => {
|
|||||||
daysVisibleRange(new Date(2026, 5, 4), 6),
|
daysVisibleRange(new Date(2026, 5, 4), 6),
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(instances.map(instance => new Date(instance.startMs).getDate())).toEqual([5, 7, 9])
|
expect(instances.map(instance => new Date(instance.start).getDate())).toEqual([5, 7, 9])
|
||||||
expect(instances.every(instance => instance.durationMs === 60 * 60 * 1000)).toBe(true)
|
expect(instances.every(instance => instance.durationMs === 60 * 60 * 1000)).toBe(true)
|
||||||
expect(new Set(instances.map(instance => instance.key)).size).toBe(3)
|
expect(new Set(instances.map(instance => instance.key)).size).toBe(3)
|
||||||
})
|
})
|
||||||
@@ -71,7 +71,7 @@ describe('daily recurrence', () => {
|
|||||||
daysVisibleRange(new Date(2026, 5, 1), 5),
|
daysVisibleRange(new Date(2026, 5, 1), 5),
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(instances.map(instance => new Date(instance.startMs).getDate())).toEqual([1, 2, 3])
|
expect(instances.map(instance => new Date(instance.start).getDate())).toEqual([1, 2, 3])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('preserves local wall-clock time across daylight-saving changes', () => {
|
it('preserves local wall-clock time across daylight-saving changes', () => {
|
||||||
@@ -85,7 +85,7 @@ describe('daily recurrence', () => {
|
|||||||
daysVisibleRange(new Date(2026, 2, 7), 3),
|
daysVisibleRange(new Date(2026, 2, 7), 3),
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(instances.map(instance => new Date(instance.startMs).getHours())).toEqual([9, 9, 9])
|
expect(instances.map(instance => new Date(instance.start).getHours())).toEqual([9, 9, 9])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('preserves exclusive calendar-day duration for recurring timeless events', () => {
|
it('preserves exclusive calendar-day duration for recurring timeless events', () => {
|
||||||
@@ -107,9 +107,9 @@ describe('daily recurrence', () => {
|
|||||||
)
|
)
|
||||||
|
|
||||||
expect(instances).toHaveLength(3)
|
expect(instances).toHaveLength(3)
|
||||||
expect(instances.map(instance => new Date(instance.startMs).getHours())).toEqual([0, 0, 0])
|
expect(instances.map(instance => new Date(instance.start).getHours())).toEqual([0, 0, 0])
|
||||||
expect(instances.map(instance => {
|
expect(instances.map(instance => {
|
||||||
const end = new Date(instance.endMs)
|
const end = new Date(instance.end)
|
||||||
return [end.getDate(), end.getHours()]
|
return [end.getDate(), end.getHours()]
|
||||||
})).toEqual([[8, 0], [9, 0], [10, 0]])
|
})).toEqual([[8, 0], [9, 0], [10, 0]])
|
||||||
})
|
})
|
||||||
@@ -128,7 +128,7 @@ describe('weekly recurrence', () => {
|
|||||||
daysVisibleRange(new Date(2026, 5, 1), 10),
|
daysVisibleRange(new Date(2026, 5, 1), 10),
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(instances.map(instance => new Date(instance.startMs).getDate())).toEqual([1, 3, 8, 10])
|
expect(instances.map(instance => new Date(instance.start).getDate())).toEqual([1, 3, 8, 10])
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -150,7 +150,7 @@ describe('recurrence mutations', () => {
|
|||||||
daysVisibleRange(new Date(2026, 5, 1), 3),
|
daysVisibleRange(new Date(2026, 5, 1), 3),
|
||||||
)
|
)
|
||||||
|
|
||||||
expect(instances.map(instance => new Date(instance.startMs).getDate())).toEqual([1, 3])
|
expect(instances.map(instance => new Date(instance.start).getDate())).toEqual([1, 3])
|
||||||
})
|
})
|
||||||
|
|
||||||
it('moves and restyles a modified occurrence without duplicating it', () => {
|
it('moves and restyles a modified occurrence without duplicating it', () => {
|
||||||
@@ -178,7 +178,7 @@ describe('recurrence mutations', () => {
|
|||||||
const moved = instances.find(instance => instance.instanceId === sourceId)
|
const moved = instances.find(instance => instance.instanceId === sourceId)
|
||||||
|
|
||||||
expect(instances).toHaveLength(2)
|
expect(instances).toHaveLength(2)
|
||||||
expect(new Date(moved!.startMs).getHours()).toBe(14)
|
expect(new Date(moved!.start).getHours()).toBe(14)
|
||||||
expect(moved!.durationMs).toBe(2 * 60 * 60 * 1000)
|
expect(moved!.durationMs).toBe(2 * 60 * 60 * 1000)
|
||||||
expect(moved!.label).toBe('Moved standup')
|
expect(moved!.label).toBe('Moved standup')
|
||||||
expect(moved!.color).toBe('#abcdef')
|
expect(moved!.color).toBe('#abcdef')
|
||||||
|
|||||||
Reference in New Issue
Block a user