diff --git a/src/webui/app/components/entity-name.tsx b/src/webui/app/components/entity-name.tsx index deb88db68..6a11004e3 100644 --- a/src/webui/app/components/entity-name.tsx +++ b/src/webui/app/components/entity-name.tsx @@ -3,13 +3,12 @@ import { Typography } from "@mui/material"; interface EntityNameProps { compact?: boolean; - inline?: boolean name: EntityName; } -export function EntityNameComponent({ compact, inline, name }: EntityNameProps) { +export function EntityNameComponent({ compact, name }: EntityNameProps) { return ( - {name} + {name} ); } @@ -20,5 +19,3 @@ export function EntityNameOneLineComponent({ compact, name }: EntityNameProps) { ); } - - diff --git a/src/webui/app/routes/workspace/calendar.tsx b/src/webui/app/routes/workspace/calendar.tsx index 977ab4a63..e5bfac7ad 100644 --- a/src/webui/app/routes/workspace/calendar.tsx +++ b/src/webui/app/routes/workspace/calendar.tsx @@ -303,12 +303,31 @@ function ViewAsCalendarDaily(props: ViewAsProps) { const [containerWidth, setContainerWidth] = useState(250); useLayoutEffect(() => { if (!isBigScreen && typeof window !== "undefined") { - setContainerWidth(Math.max(250, window.innerWidth - 4 * theme.typography.htmlFontSize - 50)); + setContainerWidth( + Math.max( + 250, + window.innerWidth - 4 * theme.typography.htmlFontSize - 64 + ) + ); } else { setContainerWidth(250); } }, [isBigScreen, theme]); + const combinedTimeEventFullDays: Array = []; + for (const entry of props.scheduleEventFullDayEntries) { + combinedTimeEventFullDays.push({ + time_event: entry.time_event, + entry: entry, + }); + } + for (const entry of props.personEntries) { + combinedTimeEventFullDays.push({ + time_event: entry.birthday_time_event, + entry: entry, + }); + } + const combinedTimeEventInDay: Array = []; for (const entry of props.scheduleEventInDayEntries) { combinedTimeEventInDay.push({ @@ -325,13 +344,21 @@ function ViewAsCalendarDaily(props: ViewAsProps) { } } + const partitionedCombinedTimeEventFullDays = + combinedTimeEventFullDayEntryPartionByDay( + combinedTimeEventFullDays, + props.periodStartDate, + props.periodEndDate + ); + const thePartititionFullDays = + partitionedCombinedTimeEventFullDays[props.periodStartDate] || []; const partitionedCombinedTimeEventInDay = combinedTimeEventInDayEntryPartionByDay( combinedTimeEventInDay, props.periodStartDate, props.periodEndDate ); - const thePartition = + const thePartitionInDay = partitionedCombinedTimeEventInDay[props.periodStartDate] || []; const startOfDay = DateTime.fromISO(`${props.periodStartDate}T00:00:00`, { @@ -344,111 +371,166 @@ function ViewAsCalendarDaily(props: ViewAsProps) { return ( - {hours.map((hour, idx) => ( - - - {hour.toFormat("HH:mm")} - - - ))} - - {thePartition.map((entry, index) => { + {thePartititionFullDays.map((entry, index) => { switch (entry.time_event.namespace) { - case TimeEventNamespace.SCHEDULE_EVENT_IN_DAY: - const scheduleEntry = entry.entry as ScheduleInDayEventEntry; + case TimeEventNamespace.SCHEDULE_FULL_DAYS_BLOCK: + const fullDaysEntry = entry.entry as ScheduleFullDaysEventEntry; - const startTime = DateTime.fromISO( - `${scheduleEntry.time_event.start_date}T${scheduleEntry.time_event.start_time_in_day}`, - { zone: props.timezone } - ); - const endTime = startTime.plus({ - minutes: entry.time_event.duration_mins, - }); - const minutesSinceStartOfDay = startTime - .diff(startOfDay) - .as("minutes"); - - const textWidthInPx = measureText( - scheduleEntry.event.name, - theme.typography.htmlFontSize - ); - const clippedName = clipEventNameToWhatFits( - `[${startTime.toFormat("HH:mm")} - ${endTime.toFormat("HH:mm")}] ${scheduleEntry.event.name}`, + `[All Day] ${fullDaysEntry.event.name}`, theme.typography.htmlFontSize, - containerWidth, - minutesSinceStartOfDay, - scheduleEntry.time_event.duration_mins + containerWidth - 32, // A hack of sorts + 0, + 15 ); + console.log( + "containerWidth", + containerWidth, + "clippedName", + clippedName + ); return ( - - {/* {" "} - [{startTime.toFormat("HH:mm")} - {endTime.toFormat("HH:mm")}] - */} - ); - case TimeEventNamespace.INBOX_TASK: + case TimeEventNamespace.PERSON_BIRTHDAY: throw new Error("Not implemented"); default: throw new Error("Unexpected namespace"); } })} + + + {hours.map((hour, idx) => ( + + + {hour.toFormat("HH:mm")} + + + ))} + + {thePartitionInDay.map((entry, index) => { + switch (entry.time_event.namespace) { + case TimeEventNamespace.SCHEDULE_EVENT_IN_DAY: + const scheduleEntry = entry.entry as ScheduleInDayEventEntry; + + const startTime = DateTime.fromISO( + `${scheduleEntry.time_event.start_date}T${scheduleEntry.time_event.start_time_in_day}`, + { zone: props.timezone } + ); + const endTime = startTime.plus({ + minutes: entry.time_event.duration_mins, + }); + const minutesSinceStartOfDay = startTime + .diff(startOfDay) + .as("minutes"); + + const clippedName = clipEventNameToWhatFits( + `[${startTime.toFormat("HH:mm")} - ${endTime.toFormat( + "HH:mm" + )}] ${scheduleEntry.event.name}`, + theme.typography.htmlFontSize, + containerWidth, + minutesSinceStartOfDay, + scheduleEntry.time_event.duration_mins + ); + + return ( + + + + + + + + ); + + case TimeEventNamespace.INBOX_TASK: + throw new Error("Not implemented"); + + default: + throw new Error("Unexpected namespace"); + } + })} + ); } @@ -614,7 +696,7 @@ function CombinedTimeEventFullDaysRows({ return ( - [AllDay] + [All Day] 24 * 60) { finalDurationInMins = Math.max(15, 24 * 60 - minutesSinceStartOfDay); } return Math.max(2, finalDurationInMins / 15); } -function clipEventNameToWhatFits(name: string, fontSize: number, containerWidth: number, minutesSinceStartOfDay: number, durationInMins: number): string { - const durationInQuarters = computeTimeEventInDayDurationInQuarters(0, durationInMins); +function clipEventNameToWhatFits( + name: string, + fontSize: number, + containerWidth: number, + minutesSinceStartOfDay: number, + durationInMins: number +): string { + const durationInQuarters = computeTimeEventInDayDurationInQuarters( + 0, + durationInMins + ); const durationInHalfs = Math.max(1, Math.floor(durationInQuarters / 2)); const textWidthInPx = measureText(name, fontSize); const totalWidthInPx = containerWidth * durationInHalfs; @@ -662,7 +756,7 @@ function clipEventNameToWhatFits(name: string, fontSize: number, containerWidth: return name; } else { // Do some rough approximation here. - const maxChars = Math.floor(name.length * totalWidthInPx / textWidthInPx); + const maxChars = Math.floor((name.length * totalWidthInPx) / textWidthInPx); return name.substring(0, maxChars) + "..."; } } @@ -673,8 +767,14 @@ function calendarTimeEventInDayStartMinutesToRems(startMins: number): string { return `${startHours}rem`; } -function calendarTimeEventInDayDurationToRems(minutesSinceStartOfDay: number, durationMins: number): string { - const durationInQuarters =computeTimeEventInDayDurationInQuarters(minutesSinceStartOfDay, durationMins); +function calendarTimeEventInDayDurationToRems( + minutesSinceStartOfDay: number, + durationMins: number +): string { + const durationInQuarters = computeTimeEventInDayDurationInQuarters( + minutesSinceStartOfDay, + durationMins + ); return `${durationInQuarters}rem`; } diff --git a/src/webui/app/utils.ts b/src/webui/app/utils.ts index b763736ff..a35209143 100644 --- a/src/webui/app/utils.ts +++ b/src/webui/app/utils.ts @@ -1,8 +1,27 @@ -const STANDARD_WIDTHS = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0.2796875,0.2765625,0.3546875,0.5546875,0.5546875,0.8890625,0.665625,0.190625,0.3328125,0.3328125,0.3890625,0.5828125,0.2765625,0.3328125,0.2765625,0.3015625,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.5546875,0.2765625,0.2765625,0.584375,0.5828125,0.584375,0.5546875,1.0140625,0.665625,0.665625,0.721875,0.721875,0.665625,0.609375,0.7765625,0.721875,0.2765625,0.5,0.665625,0.5546875,0.8328125,0.721875,0.7765625,0.665625,0.7765625,0.721875,0.665625,0.609375,0.721875,0.665625,0.94375,0.665625,0.665625,0.609375,0.2765625,0.3546875,0.2765625,0.4765625,0.5546875,0.3328125,0.5546875,0.5546875,0.5,0.5546875,0.5546875,0.2765625,0.5546875,0.5546875,0.221875,0.240625,0.5,0.221875,0.8328125,0.5546875,0.5546875,0.5546875,0.5546875,0.3328125,0.5,0.2765625,0.5546875,0.5,0.721875,0.5,0.5,0.5,0.3546875,0.259375,0.353125,0.5890625] -const AVERAGE_WIDTH = 0.5279276315789471 +const STANDARD_WIDTHS = [ + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0.2796875, 0.2765625, 0.3546875, 0.5546875, 0.5546875, + 0.8890625, 0.665625, 0.190625, 0.3328125, 0.3328125, 0.3890625, 0.5828125, + 0.2765625, 0.3328125, 0.2765625, 0.3015625, 0.5546875, 0.5546875, 0.5546875, + 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.5546875, + 0.2765625, 0.2765625, 0.584375, 0.5828125, 0.584375, 0.5546875, 1.0140625, + 0.665625, 0.665625, 0.721875, 0.721875, 0.665625, 0.609375, 0.7765625, + 0.721875, 0.2765625, 0.5, 0.665625, 0.5546875, 0.8328125, 0.721875, 0.7765625, + 0.665625, 0.7765625, 0.721875, 0.665625, 0.609375, 0.721875, 0.665625, + 0.94375, 0.665625, 0.665625, 0.609375, 0.2765625, 0.3546875, 0.2765625, + 0.4765625, 0.5546875, 0.3328125, 0.5546875, 0.5546875, 0.5, 0.5546875, + 0.5546875, 0.2765625, 0.5546875, 0.5546875, 0.221875, 0.240625, 0.5, 0.221875, + 0.8328125, 0.5546875, 0.5546875, 0.5546875, 0.5546875, 0.3328125, 0.5, + 0.2765625, 0.5546875, 0.5, 0.721875, 0.5, 0.5, 0.5, 0.3546875, 0.259375, + 0.353125, 0.5890625, +]; +const AVERAGE_WIDTH = 0.5279276315789471; export function measureText(str: string, fontSize: number): number { - return Array.from(str).reduce( - (acc, cur) => acc + (STANDARD_WIDTHS[cur.charCodeAt(0)] ?? AVERAGE_WIDTH), 0 - ) * fontSize -} \ No newline at end of file + return ( + Array.from(str).reduce( + (acc, cur) => acc + (STANDARD_WIDTHS[cur.charCodeAt(0)] ?? AVERAGE_WIDTH), + 0 + ) * fontSize + ); +}