Skip to content

Commit 79f09ff

Browse files
committed
expand time-range beyond settings if event would be hidden
1 parent 63aa471 commit 79f09ff

7 files changed

Lines changed: 73 additions & 35 deletions

File tree

src/components/timeline/CursorLine.vue

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
11
<script setup lang="ts">
22
import { settings } from '@/services/settings';
3-
import { timeInPercentOnTimeline } from '@/utils';
3+
44
import { DateTime } from 'luxon';
55
import { computed, onMounted, onUnmounted, ref } from 'vue';
66
7+
const props = defineProps<{
8+
startHour: number;
9+
endHour: number;
10+
}>();
11+
712
const hour = ref(DateTime.now().hour);
813
const minute = ref(DateTime.now().minute);
914
let interval: number;
1015
const today = DateTime.now();
1116
1217
const topPos = computed(() => {
13-
return `${timeInPercentOnTimeline(today.set({ hour: hour.value, minute: minute.value })) * 100}%`;
18+
const currentHour = hour.value + minute.value / 60;
19+
const position = (currentHour - props.startHour) / (props.endHour - props.startHour);
20+
return `${Math.max(0, Math.min(1, position)) * 100}%`;
1421
});
1522
1623
const timeFormat = computed(() => {

src/components/timeline/CursorToday.vue

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
<script setup lang="ts">
2-
import { timeInPercentOnTimeline } from '@/utils';
32
import { DateTime } from 'luxon';
43
import { computed, onMounted, onUnmounted, ref } from 'vue';
54
5+
const props = defineProps<{
6+
startHour: number;
7+
endHour: number;
8+
}>();
9+
610
const hour = ref(DateTime.now().hour);
711
const minute = ref(DateTime.now().minute);
812
let interval: number;
9-
const today = DateTime.now();
1013
1114
const topPos = computed(() => {
12-
return `${timeInPercentOnTimeline(today.set({ hour: hour.value, minute: minute.value })) * 100}%`;
15+
const currentHour = hour.value + minute.value / 60;
16+
const position = (currentHour - props.startHour) / (props.endHour - props.startHour);
17+
return `${Math.max(0, Math.min(1, position)) * 100}%`;
1318
});
1419
1520
function updateTime() {

src/components/timeline/DayTimeline.vue

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ const props = withDefaults(
4040
defineProps<{
4141
date: DateTime;
4242
events?: CalendarEvent[];
43+
startHour: number;
44+
endHour: number;
4345
}>(),
4446
{
4547
events: () => [],
@@ -93,9 +95,14 @@ const laidOutEvents = computed(function () {
9395
return layoutEvents(props.events);
9496
});
9597
98+
const rangeStartHour = computed(() => props.startHour);
99+
const rangeEndHour = computed(() => props.endHour);
100+
96101
const { drag, placeholderTop, placeholderHeight, placeholderSubtitle, dragStart } = useDraggingEvent(
97102
timelineRef,
98103
timelineDate,
104+
rangeStartHour,
105+
rangeEndHour,
99106
);
100107
101108
watchEffect(function (cleanup) {
@@ -437,11 +444,13 @@ function layoutEvents(events: CalendarEvent[]): LaidOutEvent[] {
437444
v-for="event in laidOutEvents"
438445
:key="event.id"
439446
:event="event"
447+
:start-hour="startHour"
448+
:end-hour="endHour"
440449
:style="event.layoutStyle"
441450
@click="eventModal.open(event)"
442451
/>
443452

444-
<CursorToday v-if="dateIsToday" />
453+
<CursorToday v-if="dateIsToday" :start-hour="startHour" :end-hour="endHour" />
445454
</div>
446455
</div>
447456
</template>

src/components/timeline/TimelineEvent.vue

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,24 @@
11
<script setup lang="ts">
22
import type { CalendarEvent } from '@/types/core';
33
import BaseEvent from '@/components/timeline/BaseEvent.vue';
4-
import { numberOfHours, timeRangeFormat } from '@/utils';
5-
import { settings } from '@/services/settings';
4+
import { timeRangeFormat } from '@/utils';
65
import { getTag } from '@/services/calendarCache';
76
87
interface Props {
98
event: CalendarEvent;
9+
startHour: number;
10+
endHour: number;
1011
}
1112
const props = defineProps<Props>();
1213
1314
// Calculates the start and end positions for event.
1415
function getEventPosition(event: CalendarEvent): { start: number; end: number } {
1516
const eventStartHours = event.from.hour + event.from.minute / 60;
1617
const eventEndHours = event.to.hour + event.to.minute / 60;
17-
const viewStart = settings.value.dayViewStartHour;
18+
const numberOfHours = props.endHour - props.startHour;
1819
19-
const start = Math.max(0, (eventStartHours - viewStart) / numberOfHours());
20-
const end = Math.min(1, (eventEndHours - viewStart) / numberOfHours());
20+
const start = Math.max(0, (eventStartHours - props.startHour) / numberOfHours);
21+
const end = Math.min(1, (eventEndHours - props.startHour) / numberOfHours);
2122
2223
return { start, end };
2324
}

src/components/timeline/XDaysView.vue

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,30 @@ const dates = computed(() => {
4242
});
4343
});
4444
45-
const hoursOnGrid = computed(() => {
46-
const start = settings.value.dayViewStartHour;
47-
const end = settings.value.dayViewEndHour;
45+
const timelineRange = computed(() => {
46+
const defaultStart = settings.value.dayViewStartHour;
47+
const configuredEnd = settings.value.dayViewEndHour;
48+
const defaultEnd = configuredEnd > defaultStart ? configuredEnd : configuredEnd + 24;
49+
50+
let startHour: number = defaultStart;
51+
let endHour: number = defaultEnd;
52+
53+
for (const events of eventsTimeline.value) {
54+
for (const event of events) {
55+
startHour = Math.min(startHour, Math.floor(event.from.hour + event.from.minute / 60));
56+
endHour = Math.max(endHour, Math.ceil(event.to.hour + event.to.minute / 60));
57+
}
58+
}
4859
49-
const result: string[] = [];
60+
return { startHour, endHour };
61+
});
5062
51-
const totalHours = end > start ? end - start : 24 - start + end;
63+
const hoursOnGrid = computed(() => {
64+
const { startHour, endHour } = timelineRange.value;
65+
const result: string[] = [];
5266
53-
for (let i = 0; i < totalHours; i++) {
54-
const current = (start + i) % 24;
67+
for (let i = 0; i < endHour - startHour; i++) {
68+
const current = (startHour + i) % 24;
5569
5670
// resolve formats manually ig
5771
if (settings.value.timeFormat === 'h12') {
@@ -130,7 +144,7 @@ async function updateData() {
130144
</div>
131145

132146
<div id="content">
133-
<CursorLine />
147+
<CursorLine :start-hour="timelineRange.startHour" :end-hour="timelineRange.endHour" />
134148

135149
<div class="hour-lines">
136150
<div
@@ -141,7 +155,14 @@ async function updateData() {
141155
></div>
142156
</div>
143157

144-
<DayTimeline v-for="(d, i) in dates" :key="d.toMillis()" :date="d" :events="eventsTimeline[i]" />
158+
<DayTimeline
159+
v-for="(d, i) in dates"
160+
:key="d.toMillis()"
161+
:date="d"
162+
:events="eventsTimeline[i]"
163+
:start-hour="timelineRange.startHour"
164+
:end-hour="timelineRange.endHour"
165+
/>
145166
</div>
146167
</div>
147168
</template>

src/composables/useDraggingEvent.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@ import type { Ref } from 'vue';
33
import type { CalendarEvent } from '@/types/core.ts';
44
import { DateTime } from 'luxon';
55
import { useMouse } from '@vueuse/core';
6-
import { numberOfHours, timeRangeFormat } from '@/utils';
6+
import { timeRangeFormat } from '@/utils';
77
import { useEventModal } from '@/composables/modals/useEventModal';
88
import { settings } from '@/services/settings';
99

10-
export function useDraggingEvent(timelineRef: Ref<HTMLElement | null>, date: Ref<DateTime>) {
10+
export function useDraggingEvent(
11+
timelineRef: Ref<HTMLElement | null>,
12+
date: Ref<DateTime>,
13+
startHour: Ref<number>,
14+
endHour: Ref<number>,
15+
) {
1116
const { y } = useMouse();
1217
const eventModal = useEventModal();
1318

@@ -16,7 +21,7 @@ export function useDraggingEvent(timelineRef: Ref<HTMLElement | null>, date: Ref
1621

1722
const snapToGridHeight = computed(() => {
1823
if (!timelineRef.value) return 0;
19-
return timelineRef.value.clientHeight / numberOfHours() / (60 / settings.value.dragPrecisionMinutes);
24+
return timelineRef.value.clientHeight / (endHour.value - startHour.value) / (60 / settings.value.dragPrecisionMinutes);
2025
});
2126

2227
const maxY = computed(() => timelineRef.value?.clientHeight ?? 0);
@@ -59,11 +64,11 @@ export function useDraggingEvent(timelineRef: Ref<HTMLElement | null>, date: Ref
5964
const endTotalMinutes = (startSlots + durationSlots) * settings.value.dragPrecisionMinutes;
6065

6166
const startTime = date.value
62-
.set({ hour: settings.value.dayViewStartHour, minute: 0 })
67+
.set({ hour: startHour.value, minute: 0 })
6368
.plus({ minutes: startTotalMinutes });
6469

6570
const endTime = date.value
66-
.set({ hour: settings.value.dayViewStartHour, minute: 0 })
71+
.set({ hour: startHour.value, minute: 0 })
6772
.plus({ minutes: endTotalMinutes });
6873

6974
return [startTime, endTime];

src/utils.ts

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -105,16 +105,6 @@ export function numberOfHours(): number {
105105
return (settings.value.dayViewEndHour - settings.value.dayViewStartHour + 24) % 24;
106106
}
107107

108-
/**
109-
* Returns 0.0-1.0 for the datetime parameter based on settings.dayViewStartHour.
110-
*/
111-
export function timeInPercentOnTimeline(datetime: DateTime): number {
112-
const viewStart = settings.value.dayViewStartHour;
113-
const startHours = datetime.hour + datetime.minute / 60;
114-
const percent = Math.max(0, (startHours - viewStart) / numberOfHours());
115-
return percent;
116-
}
117-
118108
/**
119109
* Returns true/false whether event is wholeDay/allDay.
120110
*/

0 commit comments

Comments
 (0)