From a551ddfea89676f1c9305782ac16e2b15aa454e6 Mon Sep 17 00:00:00 2001 From: luciob Date: Thu, 26 Oct 2023 18:41:51 +0200 Subject: [PATCH 01/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20[Timeline]=20Fixed?= =?UTF-8?q?=20display=20for=20month=20unit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/utils/time-resolution.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/time-resolution.ts b/src/utils/time-resolution.ts index b092433..1db2588 100644 --- a/src/utils/time-resolution.ts +++ b/src/utils/time-resolution.ts @@ -152,7 +152,7 @@ export const displayAboveInterval = (interval: Interval, unit: Scale): string => case "week": return `${start.toFormat("MMM yyyy")} CW ${start.toFormat("WW")}`; case "month": - return start.toFormat("yyyy"); + return start.toFormat("MMM yyyy"); default: return "N/A"; } From 3f5415dd9b6af0e50448ec938020c85d7eb19f85 Mon Sep 17 00:00:00 2001 From: luciob Date: Thu, 26 Oct 2023 18:44:50 +0200 Subject: [PATCH 02/12] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20[Timeline]=20C?= =?UTF-8?q?urrently=20switch=20back=20to=20start/end=20unit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/grid/Cells/index.tsx | 8 ++++---- src/utils/time.ts | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/grid/Cells/index.tsx b/src/grid/Cells/index.tsx index 2a80bd4..8e51458 100644 --- a/src/grid/Cells/index.tsx +++ b/src/grid/Cells/index.tsx @@ -3,20 +3,20 @@ import React, { memo } from "react"; import { KonvaGroup } from "../../@konva"; import { useTimelineContext } from "../../timeline/TimelineContext"; import GridCell from "../Cell"; -import GridCellGroup from "../CellGroup"; +// import GridCellGroup from "../CellGroup"; interface GridCellsProps { height: number; } const GridCells = ({ height }: GridCellsProps) => { - const { aboveTimeBlocks, visibleTimeBlocks } = useTimelineContext(); + const { /*aboveTimeBlocks,*/ visibleTimeBlocks } = useTimelineContext(); return ( - {aboveTimeBlocks.map((column, index) => ( + {/* {aboveTimeBlocks.map((column, index) => ( - ))} + ))} */} {visibleTimeBlocks.map((column, index) => ( ))} diff --git a/src/utils/time.ts b/src/utils/time.ts index dd39040..489cb1b 100644 --- a/src/utils/time.ts +++ b/src/utils/time.ts @@ -52,7 +52,7 @@ export const getIntervalFromInternalTimeRange = ( timezone: string | undefined ): Interval => { const tz = timezone || "system"; - const startDateTime = DateTime.fromMillis(start, { zone: tz }).startOf(resolution.unitAbove); - const endDateTime = DateTime.fromMillis(end, { zone: tz }).endOf(resolution.unitAbove); + const startDateTime = DateTime.fromMillis(start, { zone: tz }).startOf(resolution.unit); + const endDateTime = DateTime.fromMillis(end, { zone: tz }).endOf(resolution.unit); return Interval.fromDateTimes(startDateTime, endDateTime); }; From ea9a047a5756bb30591db82605d7f6c5e4891c45 Mon Sep 17 00:00:00 2001 From: luciob Date: Thu, 26 Oct 2023 18:51:11 +0200 Subject: [PATCH 03/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20[Timeline]=20Print?= =?UTF-8?q?=20unit=20above=20of=20length=20=3D=20rowHeight?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/grid/CellGroup/index.tsx | 5 ++--- src/grid/Cells/index.tsx | 10 +++++----- 2 files changed, 7 insertions(+), 8 deletions(-) diff --git a/src/grid/CellGroup/index.tsx b/src/grid/CellGroup/index.tsx index 60edca7..857b3ca 100644 --- a/src/grid/CellGroup/index.tsx +++ b/src/grid/CellGroup/index.tsx @@ -7,11 +7,10 @@ import { displayAboveInterval } from "../../utils/time-resolution"; interface GridCellGroupProps { column: Interval; - height: number; index: number; } -const GridCellGroup = ({ column, height, index }: GridCellGroupProps) => { +const GridCellGroup = ({ column, index }: GridCellGroupProps) => { const { columnWidth, resolution: { sizeInUnits, unit, unitAbove }, @@ -21,7 +20,7 @@ const GridCellGroup = ({ column, height, index }: GridCellGroupProps) => { const cellLabel = useMemo(() => displayAboveInterval(column, unitAbove), [column, unitAbove]); - const points = useMemo(() => [0, 0, 0, height], [height]); + const points = useMemo(() => [0, 0, 0, rowHeight], [rowHeight]); const unitAboveInUnitBelow = useMemo( () => Duration.fromObject({ [unitAbove]: 1 }).as(unit) / sizeInUnits, diff --git a/src/grid/Cells/index.tsx b/src/grid/Cells/index.tsx index 8e51458..4e7f26f 100644 --- a/src/grid/Cells/index.tsx +++ b/src/grid/Cells/index.tsx @@ -3,20 +3,20 @@ import React, { memo } from "react"; import { KonvaGroup } from "../../@konva"; import { useTimelineContext } from "../../timeline/TimelineContext"; import GridCell from "../Cell"; -// import GridCellGroup from "../CellGroup"; +import GridCellGroup from "../CellGroup"; interface GridCellsProps { height: number; } const GridCells = ({ height }: GridCellsProps) => { - const { /*aboveTimeBlocks,*/ visibleTimeBlocks } = useTimelineContext(); + const { aboveTimeBlocks, visibleTimeBlocks } = useTimelineContext(); return ( - {/* {aboveTimeBlocks.map((column, index) => ( - - ))} */} + {aboveTimeBlocks.map((column, index) => ( + + ))} {visibleTimeBlocks.map((column, index) => ( ))} From 703f12c016a72a261b2ee510303269d081bd0a80 Mon Sep 17 00:00:00 2001 From: luciob Date: Thu, 26 Oct 2023 19:06:02 +0200 Subject: [PATCH 04/12] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20[Timeline]=20C?= =?UTF-8?q?hanged=20calculation=20of=20above=20blocks?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/timeline/TimelineContext.tsx | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/src/timeline/TimelineContext.tsx b/src/timeline/TimelineContext.tsx index 77a7b66..5707c78 100644 --- a/src/timeline/TimelineContext.tsx +++ b/src/timeline/TimelineContext.tsx @@ -4,7 +4,7 @@ import { DateTime, Interval } from "luxon"; import { addHeaderResource } from "../resources/utils/resources"; import { filterTasks, TaskData, validateTasks } from "../tasks/utils/tasks"; import { DEFAULT_GRID_COLUMN_WIDTH, DEFAULT_GRID_ROW_HEIGHT, MINIMUM_GRID_ROW_HEIGHT } from "../utils/dimensions"; -import { logDebug, logWarn } from "../utils/logger"; +import { logDebug, logError, logWarn } from "../utils/logger"; import { getValidTime, InternalTimeRange } from "../utils/time"; import { getIntervalFromInternalTimeRange } from "../utils/time"; import { getResolutionData, Resolution, ResolutionData } from "../utils/time-resolution"; @@ -195,7 +195,26 @@ export const TimelineProvider = ({ [interval, resolution] ); - const aboveTimeBlocks = useMemo(() => interval.splitBy({ [resolution.unitAbove]: 1 }), [interval, resolution]); + const aboveTimeBlocks = useMemo(() => { + const { unitAbove } = resolution; + const blocks: Interval[] = []; + const intervalStart = interval.start!; + const intervalEnd = interval.end!; + + let blockStart = intervalStart; + while (blockStart < intervalEnd) { + let blockEnd = blockStart.endOf(unitAbove); + if (blockEnd > intervalEnd) { + blockEnd = intervalEnd; + } + + logError("Adding Block", `${blockStart.toFormat("dd/MM/yy HH:mm")} > ${blockEnd.toFormat("dd/MM/yy HH:mm")}`); + blocks.push(Interval.fromDateTimes(blockStart, blockEnd)); + blockStart = blockEnd.startOf(unitAbove).plus({ [unitAbove]: 1 }); + } + + return blocks; + }, [interval, resolution]); const columnWidth = useMemo(() => { logDebug("TimelineProvider", "Calculating columnWidth..."); From f67d07743c6e07385306dd306679ee2c79c19cbb Mon Sep 17 00:00:00 2001 From: "krzysztof.grudzinski" Date: Tue, 31 Oct 2023 11:37:15 +0100 Subject: [PATCH 05/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20[TimeLine]=20Fixed?= =?UTF-8?q?=20display=20of=20unit=20above?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Closes: #140 --- src/KonvaTimeline/yearly-scenario.stories.tsx | 1 + src/grid/CellGroup/index.tsx | 39 +++++++++++++++---- src/grid/Cells/index.tsx | 27 +++++++++++-- src/timeline/TimelineContext.tsx | 1 - src/utils/time-resolution.ts | 33 +++++++++++++++- src/utils/time.ts | 4 +- 6 files changed, 90 insertions(+), 15 deletions(-) diff --git a/src/KonvaTimeline/yearly-scenario.stories.tsx b/src/KonvaTimeline/yearly-scenario.stories.tsx index 074e055..cd778cc 100644 --- a/src/KonvaTimeline/yearly-scenario.stories.tsx +++ b/src/KonvaTimeline/yearly-scenario.stories.tsx @@ -28,5 +28,6 @@ export const YearlyReport: Story = { args: { ...yearlyStoryData, resolution: "1day", + columnWidth: 120, }, }; diff --git a/src/grid/CellGroup/index.tsx b/src/grid/CellGroup/index.tsx index 857b3ca..1ba7921 100644 --- a/src/grid/CellGroup/index.tsx +++ b/src/grid/CellGroup/index.tsx @@ -8,9 +8,10 @@ import { displayAboveInterval } from "../../utils/time-resolution"; interface GridCellGroupProps { column: Interval; index: number; + dayInfo?: { thisMonth: number; untilNow: number }[]; } -const GridCellGroup = ({ column, index }: GridCellGroupProps) => { +const GridCellGroup = ({ column, index, dayInfo }: GridCellGroupProps) => { const { columnWidth, resolution: { sizeInUnits, unit, unitAbove }, @@ -22,22 +23,46 @@ const GridCellGroup = ({ column, index }: GridCellGroupProps) => { const points = useMemo(() => [0, 0, 0, rowHeight], [rowHeight]); - const unitAboveInUnitBelow = useMemo( - () => Duration.fromObject({ [unitAbove]: 1 }).as(unit) / sizeInUnits, - [sizeInUnits, unit, unitAbove] - ); + const unitAboveInUnitBelow = useMemo(() => { + if (unitAbove === "month") { + return Duration.fromObject({ ["day"]: dayInfo![index].thisMonth }).as("week") / sizeInUnits; + } + return Duration.fromObject({ [unitAbove]: 1 }).as(unit) / sizeInUnits; + }, [sizeInUnits, dayInfo, index, unitAbove, unit]); const unitAboveSpanInPx = useMemo(() => unitAboveInUnitBelow * columnWidth, [columnWidth, unitAboveInUnitBelow]); - const xPos = useMemo(() => index * unitAboveSpanInPx, [index, unitAboveSpanInPx]); + const xPos = useMemo(() => { + if (unitAbove === "month") { + const pxUntil = + index !== 0 ? Duration.fromObject({ ["day"]: dayInfo![index - 1].untilNow }).as("week") / sizeInUnits : 0; + const a = pxUntil * columnWidth; + return a + unitAboveSpanInPx; + } + return index * unitAboveSpanInPx; + }, [index, unitAboveSpanInPx, columnWidth, sizeInUnits, dayInfo, unitAbove]); const yPos = useMemo(() => rowHeight * 0.3, [rowHeight]); + const xPosLabel = useMemo(() => { + if (unitAbove === "month") { + return xPos - unitAboveSpanInPx; + } + return index * unitAboveSpanInPx; + }, [xPos, unitAboveSpanInPx, unitAbove, index]); + return ( - + ); }; diff --git a/src/grid/Cells/index.tsx b/src/grid/Cells/index.tsx index 4e7f26f..b4af254 100644 --- a/src/grid/Cells/index.tsx +++ b/src/grid/Cells/index.tsx @@ -2,6 +2,7 @@ import React, { memo } from "react"; import { KonvaGroup } from "../../@konva"; import { useTimelineContext } from "../../timeline/TimelineContext"; +import { daysInMonth, getMonth, getStartMonthsDay, getYear } from "../../utils/time-resolution"; import GridCell from "../Cell"; import GridCellGroup from "../CellGroup"; @@ -10,12 +11,32 @@ interface GridCellsProps { } const GridCells = ({ height }: GridCellsProps) => { - const { aboveTimeBlocks, visibleTimeBlocks } = useTimelineContext(); - + const { + interval, + aboveTimeBlocks, + visibleTimeBlocks, + resolution: { unitAbove }, + } = useTimelineContext(); + const dayInfo: { thisMonth: number; untilNow: number }[] = []; + if (unitAbove === "month") { + aboveTimeBlocks.forEach((column, index) => { + const month = getMonth(column); + const year = getYear(column); + const currentMonthDays = daysInMonth(Number(month), Number(year)); + if (index === 0) { + const startDay = getStartMonthsDay(interval.start!); + const daysToMonthEnd = currentMonthDays - Number(startDay) + 1; + dayInfo.push({ thisMonth: daysToMonthEnd, untilNow: daysToMonthEnd }); + return; + } + const n = dayInfo[index - 1].untilNow + currentMonthDays; + dayInfo.push({ thisMonth: currentMonthDays, untilNow: n }); + }); + } return ( {aboveTimeBlocks.map((column, index) => ( - + ))} {visibleTimeBlocks.map((column, index) => ( diff --git a/src/timeline/TimelineContext.tsx b/src/timeline/TimelineContext.tsx index 5707c78..c737830 100644 --- a/src/timeline/TimelineContext.tsx +++ b/src/timeline/TimelineContext.tsx @@ -212,7 +212,6 @@ export const TimelineProvider = ({ blocks.push(Interval.fromDateTimes(blockStart, blockEnd)); blockStart = blockEnd.startOf(unitAbove).plus({ [unitAbove]: 1 }); } - return blocks; }, [interval, resolution]); diff --git a/src/utils/time-resolution.ts b/src/utils/time-resolution.ts index 1db2588..7331dd2 100644 --- a/src/utils/time-resolution.ts +++ b/src/utils/time-resolution.ts @@ -1,4 +1,4 @@ -import { Interval } from "luxon"; +import { DateTime, Interval } from "luxon"; import { DEFAULT_GRID_COLUMN_WIDTH } from "./dimensions"; @@ -148,7 +148,7 @@ export const displayAboveInterval = (interval: Interval, unit: Scale): string => case "hour": return start.toFormat("dd/MM/yy HH:mm"); case "day": - return start.toFormat("ccc dd MMM yyyy"); + return start.toFormat("ccc dd yyyy"); case "week": return `${start.toFormat("MMM yyyy")} CW ${start.toFormat("WW")}`; case "month": @@ -158,6 +158,35 @@ export const displayAboveInterval = (interval: Interval, unit: Scale): string => } }; +export const getMonth = (interval: Interval): string => { + const { start } = interval; + if (!start) { + return "-"; + } + + return start.toFormat("M"); +}; +export const getYear = (interval: Interval): string => { + const { start } = interval; + if (!start) { + return "-"; + } + + return start.toFormat("yyyy"); +}; + +export const getStartMonthsDay = (start: DateTime): string => { + if (!start) { + return "-"; + } + + return start.toFormat("d"); +}; + +export const daysInMonth = (month: number, year: number) => { + return new Date(year, month, 0).getDate(); +}; + /** * Util to display an interval in a human readable format * @param interval the interval to display diff --git a/src/utils/time.ts b/src/utils/time.ts index 489cb1b..dd39040 100644 --- a/src/utils/time.ts +++ b/src/utils/time.ts @@ -52,7 +52,7 @@ export const getIntervalFromInternalTimeRange = ( timezone: string | undefined ): Interval => { const tz = timezone || "system"; - const startDateTime = DateTime.fromMillis(start, { zone: tz }).startOf(resolution.unit); - const endDateTime = DateTime.fromMillis(end, { zone: tz }).endOf(resolution.unit); + const startDateTime = DateTime.fromMillis(start, { zone: tz }).startOf(resolution.unitAbove); + const endDateTime = DateTime.fromMillis(end, { zone: tz }).endOf(resolution.unitAbove); return Interval.fromDateTimes(startDateTime, endDateTime); }; From 02c81d922f8980a5a3c1afd8381739a6f1a53d31 Mon Sep 17 00:00:00 2001 From: "krzysztof.grudzinski" Date: Tue, 31 Oct 2023 12:51:30 +0100 Subject: [PATCH 06/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20[timeLine]=20fixed?= =?UTF-8?q?=20start=20interval=20for=20week=20unit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Closes: #140 --- src/utils/time.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/utils/time.ts b/src/utils/time.ts index 2dc7a5a..ef1b521 100644 --- a/src/utils/time.ts +++ b/src/utils/time.ts @@ -71,7 +71,11 @@ export const getIntervalFromInternalTimeRange = ( timezone: string | undefined ): Interval => { const tz = timezone || "system"; - const startDateTime = DateTime.fromMillis(start, { zone: tz }).startOf(resolution.unitAbove); - const endDateTime = DateTime.fromMillis(end, { zone: tz }).endOf(resolution.unitAbove); + const startDateTime = DateTime.fromMillis(start, { zone: tz }).startOf( + resolution.unitAbove !== "month" ? resolution.unitAbove : resolution.unit + ); + const endDateTime = DateTime.fromMillis(end, { zone: tz }).endOf( + resolution.unitAbove !== "month" ? resolution.unitAbove : resolution.unit + ); return Interval.fromDateTimes(startDateTime, endDateTime); }; From 6f7b7b03aa493871f21fb1090b89250bca0fd42e Mon Sep 17 00:00:00 2001 From: "krzysztof.grudzinski" Date: Thu, 2 Nov 2023 17:41:02 +0100 Subject: [PATCH 07/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20[TimeLine]=20fixed?= =?UTF-8?q?=20display=20unitAbove=20when=20TZ=20change?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Closes: #140 --- src/KonvaTimeline/yearly-scenario.stories.tsx | 17 ++++++++++++++++- src/grid/CellGroup/index.tsx | 10 ++++++++-- src/grid/Cells/index.tsx | 14 +++++++++----- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/src/KonvaTimeline/yearly-scenario.stories.tsx b/src/KonvaTimeline/yearly-scenario.stories.tsx index cd778cc..f680f0c 100644 --- a/src/KonvaTimeline/yearly-scenario.stories.tsx +++ b/src/KonvaTimeline/yearly-scenario.stories.tsx @@ -27,7 +27,22 @@ const yearlyStoryData = generateStoryData({ export const YearlyReport: Story = { args: { ...yearlyStoryData, - resolution: "1day", + resolution: "30min", columnWidth: 120, + range: { + start: 1698357600000, + end: 1698966000000, + }, + tasks: [ + { + id: "1", + label: "1Novembre", + resourceId: "1", + time: { + start: 1698793200000, + end: 1700434800000, + }, + }, + ], }, }; diff --git a/src/grid/CellGroup/index.tsx b/src/grid/CellGroup/index.tsx index 1ba7921..655da1a 100644 --- a/src/grid/CellGroup/index.tsx +++ b/src/grid/CellGroup/index.tsx @@ -8,7 +8,7 @@ import { displayAboveInterval } from "../../utils/time-resolution"; interface GridCellGroupProps { column: Interval; index: number; - dayInfo?: { thisMonth: number; untilNow: number }[]; + dayInfo?: { thisMonth?: number; untilNow?: number; backHour: boolean; forNowHour: boolean }[]; } const GridCellGroup = ({ column, index, dayInfo }: GridCellGroupProps) => { @@ -30,7 +30,9 @@ const GridCellGroup = ({ column, index, dayInfo }: GridCellGroupProps) => { return Duration.fromObject({ [unitAbove]: 1 }).as(unit) / sizeInUnits; }, [sizeInUnits, dayInfo, index, unitAbove, unit]); - const unitAboveSpanInPx = useMemo(() => unitAboveInUnitBelow * columnWidth, [columnWidth, unitAboveInUnitBelow]); + const unitAboveSpanInPx = useMemo(() => { + return unitAboveInUnitBelow * columnWidth; + }, [columnWidth, unitAboveInUnitBelow]); const xPos = useMemo(() => { if (unitAbove === "month") { @@ -39,6 +41,10 @@ const GridCellGroup = ({ column, index, dayInfo }: GridCellGroupProps) => { const a = pxUntil * columnWidth; return a + unitAboveSpanInPx; } + if (unitAbove === "day" && dayInfo![index].forNowHour) { + return index * unitAboveSpanInPx + columnWidth / sizeInUnits; + } + return index * unitAboveSpanInPx; }, [index, unitAboveSpanInPx, columnWidth, sizeInUnits, dayInfo, unitAbove]); diff --git a/src/grid/Cells/index.tsx b/src/grid/Cells/index.tsx index b4af254..e94656a 100644 --- a/src/grid/Cells/index.tsx +++ b/src/grid/Cells/index.tsx @@ -17,22 +17,26 @@ const GridCells = ({ height }: GridCellsProps) => { visibleTimeBlocks, resolution: { unitAbove }, } = useTimelineContext(); - const dayInfo: { thisMonth: number; untilNow: number }[] = []; - if (unitAbove === "month") { + const dayInfo: { thisMonth?: number; untilNow?: number; backHour: boolean; forNowHour: boolean }[] = []; + if (unitAbove === "month" || unitAbove === "day") { aboveTimeBlocks.forEach((column, index) => { + const hrs = column.end!.diff(column.start!, "hour").hours; const month = getMonth(column); const year = getYear(column); const currentMonthDays = daysInMonth(Number(month), Number(year)); + const bchour = hrs > 24 ? true : false; if (index === 0) { const startDay = getStartMonthsDay(interval.start!); const daysToMonthEnd = currentMonthDays - Number(startDay) + 1; - dayInfo.push({ thisMonth: daysToMonthEnd, untilNow: daysToMonthEnd }); + dayInfo.push({ thisMonth: daysToMonthEnd, untilNow: daysToMonthEnd, backHour: bchour, forNowHour: false }); return; } - const n = dayInfo[index - 1].untilNow + currentMonthDays; - dayInfo.push({ thisMonth: currentMonthDays, untilNow: n }); + const forNowHour = dayInfo[index - 1].forNowHour ? true : dayInfo[index - 1].backHour ? true : false; + const n = dayInfo[index - 1].untilNow! + currentMonthDays; + dayInfo.push({ thisMonth: currentMonthDays, untilNow: n, backHour: bchour, forNowHour: forNowHour }); }); } + return ( {aboveTimeBlocks.map((column, index) => ( From d6f31e5a578ea18938c155921864c2087e5a6a06 Mon Sep 17 00:00:00 2001 From: "krzysztof.grudzinski" Date: Mon, 6 Nov 2023 15:25:59 +0100 Subject: [PATCH 08/12] =?UTF-8?q?fix:=20=F0=9F=90=9B=20[TimeLine]=20Fixed?= =?UTF-8?q?=20display=20of=20visibleTimeBlock=20with=20Tz?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Closes: #140 --- src/KonvaTimeline/yearly-scenario.stories.tsx | 11 ++- src/grid/Cell/index.tsx | 26 +++++- src/grid/CellGroup/index.tsx | 35 ++++++-- src/grid/Cells/index.tsx | 80 +++++++++++++++++-- 4 files changed, 136 insertions(+), 16 deletions(-) diff --git a/src/KonvaTimeline/yearly-scenario.stories.tsx b/src/KonvaTimeline/yearly-scenario.stories.tsx index f680f0c..50daee9 100644 --- a/src/KonvaTimeline/yearly-scenario.stories.tsx +++ b/src/KonvaTimeline/yearly-scenario.stories.tsx @@ -31,7 +31,7 @@ export const YearlyReport: Story = { columnWidth: 120, range: { start: 1698357600000, - end: 1698966000000, + end: 1712095200000, }, tasks: [ { @@ -43,6 +43,15 @@ export const YearlyReport: Story = { end: 1700434800000, }, }, + { + id: "2", + label: "26Marzo", + resourceId: "1", + time: { + start: 1711839600000, + end: 1711922399000, + }, + }, ], }, }; diff --git a/src/grid/Cell/index.tsx b/src/grid/Cell/index.tsx index edd2053..d6986ba 100644 --- a/src/grid/Cell/index.tsx +++ b/src/grid/Cell/index.tsx @@ -9,9 +9,13 @@ interface GridCellProps { column: Interval; height: number; index: number; + visibleDayInfo: { + backHour?: boolean; + nextHour?: boolean; + }; } -const GridCell = ({ column, height, index }: GridCellProps) => { +const GridCell = ({ column, height, index, visibleDayInfo }: GridCellProps) => { const { blocksOffset, columnWidth, @@ -22,7 +26,25 @@ const GridCell = ({ column, height, index }: GridCellProps) => { const cellLabel = useMemo(() => displayInterval(column, resolutionUnit), [column, resolutionUnit]); - const xPos = useMemo(() => columnWidth * (index + blocksOffset), [blocksOffset, columnWidth, index]); + const xPos = useMemo(() => { + if (resolutionUnit === "day") { + if (visibleDayInfo.backHour) { + return columnWidth * (index + blocksOffset) + columnWidth / 24; + } + if (visibleDayInfo.nextHour) { + return columnWidth * (index + blocksOffset) - columnWidth / 24; + } + } + if (resolutionUnit === "week") { + if (visibleDayInfo.backHour) { + return columnWidth * (index + blocksOffset) + columnWidth / 168; + } + if (visibleDayInfo.nextHour) { + return columnWidth * (index + blocksOffset) - columnWidth / 168; + } + } + return columnWidth * (index + blocksOffset); + }, [blocksOffset, columnWidth, index, visibleDayInfo, resolutionUnit]); const yPos = useMemo(() => rowHeight * 0.8, [rowHeight]); diff --git a/src/grid/CellGroup/index.tsx b/src/grid/CellGroup/index.tsx index 655da1a..5403195 100644 --- a/src/grid/CellGroup/index.tsx +++ b/src/grid/CellGroup/index.tsx @@ -8,7 +8,12 @@ import { displayAboveInterval } from "../../utils/time-resolution"; interface GridCellGroupProps { column: Interval; index: number; - dayInfo?: { thisMonth?: number; untilNow?: number; backHour: boolean; forNowHour: boolean }[]; + dayInfo?: { + thisMonth?: number; + untilNow?: number; + backHour: boolean; + nextHour: boolean; + }[]; } const GridCellGroup = ({ column, index, dayInfo }: GridCellGroupProps) => { @@ -38,11 +43,31 @@ const GridCellGroup = ({ column, index, dayInfo }: GridCellGroupProps) => { if (unitAbove === "month") { const pxUntil = index !== 0 ? Duration.fromObject({ ["day"]: dayInfo![index - 1].untilNow }).as("week") / sizeInUnits : 0; - const a = pxUntil * columnWidth; - return a + unitAboveSpanInPx; + if (dayInfo![index].backHour) { + const hourInMonthPx = columnWidth / 168; + return pxUntil * columnWidth + unitAboveSpanInPx + hourInMonthPx; + } + if (dayInfo![index].nextHour) { + const hourInMonthPx = columnWidth / 168; + return pxUntil * columnWidth + unitAboveSpanInPx - hourInMonthPx; + } + return pxUntil * columnWidth + unitAboveSpanInPx; } - if (unitAbove === "day" && dayInfo![index].forNowHour) { - return index * unitAboveSpanInPx + columnWidth / sizeInUnits; + if (unitAbove === "day") { + if (dayInfo![index].backHour) { + return index * unitAboveSpanInPx + columnWidth / sizeInUnits; + } + if (dayInfo![index].nextHour) { + return index * unitAboveSpanInPx - columnWidth / sizeInUnits; + } + } + if (unitAbove === "week") { + if (dayInfo![index].backHour) { + return index * unitAboveSpanInPx + columnWidth / 24; + } + if (dayInfo![index].nextHour) { + return index * unitAboveSpanInPx - columnWidth / 24; + } } return index * unitAboveSpanInPx; diff --git a/src/grid/Cells/index.tsx b/src/grid/Cells/index.tsx index e94656a..e585adc 100644 --- a/src/grid/Cells/index.tsx +++ b/src/grid/Cells/index.tsx @@ -17,25 +17,83 @@ const GridCells = ({ height }: GridCellsProps) => { visibleTimeBlocks, resolution: { unitAbove }, } = useTimelineContext(); - const dayInfo: { thisMonth?: number; untilNow?: number; backHour: boolean; forNowHour: boolean }[] = []; - if (unitAbove === "month" || unitAbove === "day") { + const dayInfo: { + thisMonth?: number; + untilNow?: number; + backHour: boolean; + nextHour: boolean; + }[] = []; + const visibleDayInfo: { + backHour?: boolean; + nextHour?: boolean; + }[] = []; + const tz = interval.start!.toISO()?.slice(-6); + if (unitAbove === "month" || unitAbove === "day" || unitAbove === "week") { aboveTimeBlocks.forEach((column, index) => { - const hrs = column.end!.diff(column.start!, "hour").hours; const month = getMonth(column); const year = getYear(column); const currentMonthDays = daysInMonth(Number(month), Number(year)); - const bchour = hrs > 24 ? true : false; if (index === 0) { const startDay = getStartMonthsDay(interval.start!); const daysToMonthEnd = currentMonthDays - Number(startDay) + 1; - dayInfo.push({ thisMonth: daysToMonthEnd, untilNow: daysToMonthEnd, backHour: bchour, forNowHour: false }); + dayInfo.push({ + thisMonth: daysToMonthEnd, + untilNow: daysToMonthEnd, + backHour: false, + nextHour: false, + }); return; } - const forNowHour = dayInfo[index - 1].forNowHour ? true : dayInfo[index - 1].backHour ? true : false; const n = dayInfo[index - 1].untilNow! + currentMonthDays; - dayInfo.push({ thisMonth: currentMonthDays, untilNow: n, backHour: bchour, forNowHour: forNowHour }); + const tzStart = column.start!.toISO()?.slice(-6); + if (tz !== tzStart) { + if (Number(tz?.slice(1, 3)) - Number(tzStart!.slice(1, 3)) > 0) { + dayInfo.push({ + thisMonth: currentMonthDays, + untilNow: n, + backHour: true, + nextHour: false, + }); + return; + } + dayInfo.push({ + thisMonth: currentMonthDays, + untilNow: n, + backHour: false, + nextHour: true, + }); + } + + dayInfo.push({ + thisMonth: currentMonthDays, + untilNow: n, + backHour: false, + nextHour: false, + }); }); } + visibleTimeBlocks.forEach((column) => { + const tzStart = column.start!.toISO()?.slice(-6); + + if (tz !== tzStart) { + if (Number(tz?.slice(1, 3)) - Number(tzStart!.slice(1, 3)) > 0) { + visibleDayInfo.push({ + backHour: true, + nextHour: false, + }); + return; + } + visibleDayInfo.push({ + backHour: false, + nextHour: true, + }); + } + visibleDayInfo.push({ + backHour: false, + nextHour: false, + }); + return; + }); return ( @@ -43,7 +101,13 @@ const GridCells = ({ height }: GridCellsProps) => { ))} {visibleTimeBlocks.map((column, index) => ( - + ))} ); From 9e8d987579957b67efd89113705b52fbda43a5ca Mon Sep 17 00:00:00 2001 From: "krzysztof.grudzinski" Date: Mon, 6 Nov 2023 16:58:57 +0100 Subject: [PATCH 09/12] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20Code=20refacto?= =?UTF-8?q?red?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Closes: #140 --- src/grid/Cell/index.tsx | 4 +- src/grid/CellGroup/index.tsx | 22 +++---- src/grid/Cells/index.tsx | 99 ++++++-------------------------- src/grid/Cells/utils.ts | 66 +++++++++++++++++++++ src/timeline/TimelineContext.tsx | 4 +- 5 files changed, 100 insertions(+), 95 deletions(-) create mode 100644 src/grid/Cells/utils.ts diff --git a/src/grid/Cell/index.tsx b/src/grid/Cell/index.tsx index d6986ba..512e88c 100644 --- a/src/grid/Cell/index.tsx +++ b/src/grid/Cell/index.tsx @@ -9,13 +9,13 @@ interface GridCellProps { column: Interval; height: number; index: number; - visibleDayInfo: { + hourInfo: { backHour?: boolean; nextHour?: boolean; }; } -const GridCell = ({ column, height, index, visibleDayInfo }: GridCellProps) => { +const GridCell = ({ column, height, index, hourInfo: visibleDayInfo }: GridCellProps) => { const { blocksOffset, columnWidth, diff --git a/src/grid/CellGroup/index.tsx b/src/grid/CellGroup/index.tsx index 5403195..3ed8cfc 100644 --- a/src/grid/CellGroup/index.tsx +++ b/src/grid/CellGroup/index.tsx @@ -11,12 +11,14 @@ interface GridCellGroupProps { dayInfo?: { thisMonth?: number; untilNow?: number; - backHour: boolean; - nextHour: boolean; }[]; + hourInfo?: { + backHour?: boolean; + nextHour?: boolean; + }; } -const GridCellGroup = ({ column, index, dayInfo }: GridCellGroupProps) => { +const GridCellGroup = ({ column, index, dayInfo, hourInfo }: GridCellGroupProps) => { const { columnWidth, resolution: { sizeInUnits, unit, unitAbove }, @@ -43,35 +45,35 @@ const GridCellGroup = ({ column, index, dayInfo }: GridCellGroupProps) => { if (unitAbove === "month") { const pxUntil = index !== 0 ? Duration.fromObject({ ["day"]: dayInfo![index - 1].untilNow }).as("week") / sizeInUnits : 0; - if (dayInfo![index].backHour) { + if (hourInfo!.backHour) { const hourInMonthPx = columnWidth / 168; return pxUntil * columnWidth + unitAboveSpanInPx + hourInMonthPx; } - if (dayInfo![index].nextHour) { + if (hourInfo!.nextHour) { const hourInMonthPx = columnWidth / 168; return pxUntil * columnWidth + unitAboveSpanInPx - hourInMonthPx; } return pxUntil * columnWidth + unitAboveSpanInPx; } if (unitAbove === "day") { - if (dayInfo![index].backHour) { + if (hourInfo!.backHour) { return index * unitAboveSpanInPx + columnWidth / sizeInUnits; } - if (dayInfo![index].nextHour) { + if (hourInfo!.nextHour) { return index * unitAboveSpanInPx - columnWidth / sizeInUnits; } } if (unitAbove === "week") { - if (dayInfo![index].backHour) { + if (hourInfo!.backHour) { return index * unitAboveSpanInPx + columnWidth / 24; } - if (dayInfo![index].nextHour) { + if (hourInfo!.nextHour) { return index * unitAboveSpanInPx - columnWidth / 24; } } return index * unitAboveSpanInPx; - }, [index, unitAboveSpanInPx, columnWidth, sizeInUnits, dayInfo, unitAbove]); + }, [index, unitAboveSpanInPx, columnWidth, sizeInUnits, dayInfo, unitAbove, hourInfo]); const yPos = useMemo(() => rowHeight * 0.3, [rowHeight]); diff --git a/src/grid/Cells/index.tsx b/src/grid/Cells/index.tsx index e585adc..bf7348d 100644 --- a/src/grid/Cells/index.tsx +++ b/src/grid/Cells/index.tsx @@ -1,11 +1,12 @@ -import React, { memo } from "react"; +import React, { memo, useMemo } from "react"; import { KonvaGroup } from "../../@konva"; import { useTimelineContext } from "../../timeline/TimelineContext"; -import { daysInMonth, getMonth, getStartMonthsDay, getYear } from "../../utils/time-resolution"; import GridCell from "../Cell"; import GridCellGroup from "../CellGroup"; +import { dayDetail, timeBlockTz } from "./utils"; + interface GridCellsProps { height: number; } @@ -17,88 +18,24 @@ const GridCells = ({ height }: GridCellsProps) => { visibleTimeBlocks, resolution: { unitAbove }, } = useTimelineContext(); - const dayInfo: { - thisMonth?: number; - untilNow?: number; - backHour: boolean; - nextHour: boolean; - }[] = []; - const visibleDayInfo: { - backHour?: boolean; - nextHour?: boolean; - }[] = []; - const tz = interval.start!.toISO()?.slice(-6); - if (unitAbove === "month" || unitAbove === "day" || unitAbove === "week") { - aboveTimeBlocks.forEach((column, index) => { - const month = getMonth(column); - const year = getYear(column); - const currentMonthDays = daysInMonth(Number(month), Number(year)); - if (index === 0) { - const startDay = getStartMonthsDay(interval.start!); - const daysToMonthEnd = currentMonthDays - Number(startDay) + 1; - dayInfo.push({ - thisMonth: daysToMonthEnd, - untilNow: daysToMonthEnd, - backHour: false, - nextHour: false, - }); - return; - } - const n = dayInfo[index - 1].untilNow! + currentMonthDays; - const tzStart = column.start!.toISO()?.slice(-6); - if (tz !== tzStart) { - if (Number(tz?.slice(1, 3)) - Number(tzStart!.slice(1, 3)) > 0) { - dayInfo.push({ - thisMonth: currentMonthDays, - untilNow: n, - backHour: true, - nextHour: false, - }); - return; - } - dayInfo.push({ - thisMonth: currentMonthDays, - untilNow: n, - backHour: false, - nextHour: true, - }); - } - - dayInfo.push({ - thisMonth: currentMonthDays, - untilNow: n, - backHour: false, - nextHour: false, - }); - }); - } - visibleTimeBlocks.forEach((column) => { - const tzStart = column.start!.toISO()?.slice(-6); - - if (tz !== tzStart) { - if (Number(tz?.slice(1, 3)) - Number(tzStart!.slice(1, 3)) > 0) { - visibleDayInfo.push({ - backHour: true, - nextHour: false, - }); - return; - } - visibleDayInfo.push({ - backHour: false, - nextHour: true, - }); - } - visibleDayInfo.push({ - backHour: false, - nextHour: false, - }); - return; - }); + const tz = useMemo(() => interval.start!.toISO()!.slice(-6), [interval]); + const dayInfo = useMemo( + () => dayDetail(unitAbove, aboveTimeBlocks, interval), + [unitAbove, aboveTimeBlocks, interval] + ); + const aboveHourInfo = useMemo(() => timeBlockTz(aboveTimeBlocks, tz), [tz, aboveTimeBlocks]); + const visibileHourInfo = useMemo(() => timeBlockTz(visibleTimeBlocks, tz), [tz, visibleTimeBlocks]); return ( {aboveTimeBlocks.map((column, index) => ( - + ))} {visibleTimeBlocks.map((column, index) => ( { column={column} height={height} index={index} - visibleDayInfo={visibleDayInfo[index]} + hourInfo={visibileHourInfo[index]} /> ))} diff --git a/src/grid/Cells/utils.ts b/src/grid/Cells/utils.ts new file mode 100644 index 0000000..65460ee --- /dev/null +++ b/src/grid/Cells/utils.ts @@ -0,0 +1,66 @@ +import { Interval } from "luxon"; + +import { daysInMonth, getMonth, getStartMonthsDay, getYear, Scale } from "../../utils/time-resolution"; + +interface visibleDayInfoProps { + backHour?: boolean; + nextHour?: boolean; +} + +export const timeBlockTz = (timeBlock: Interval[], initialTz?: string) => { + const dayInfoArray: visibleDayInfoProps[] = []; + timeBlock.forEach((column) => { + const tzStart = column.start!.toISO()?.slice(-6); + + if (initialTz !== tzStart) { + if (Number(initialTz?.slice(1, 3)) - Number(tzStart!.slice(1, 3)) > 0) { + dayInfoArray.push({ + backHour: true, + nextHour: false, + }); + return; + } + dayInfoArray.push({ + backHour: false, + nextHour: true, + }); + } + dayInfoArray.push({ + backHour: false, + nextHour: false, + }); + return; + }); + return dayInfoArray; +}; + +export const dayDetail = (unitAbove: Scale, aboveTimeBlocks: Interval[], interval: Interval) => { + if (unitAbove === "month") { + const dayInfo: { + thisMonth?: number; + untilNow?: number; + }[] = []; + aboveTimeBlocks.forEach((column, index) => { + const month = getMonth(column); + const year = getYear(column); + const currentMonthDays = daysInMonth(Number(month), Number(year)); + if (index === 0) { + const startDay = getStartMonthsDay(interval.start!); + const daysToMonthEnd = currentMonthDays - Number(startDay) + 1; + dayInfo.push({ + thisMonth: daysToMonthEnd, + untilNow: daysToMonthEnd, + }); + return; + } + const n = dayInfo[index - 1].untilNow! + currentMonthDays; + + dayInfo.push({ + thisMonth: currentMonthDays, + untilNow: n, + }); + }); + return dayInfo; + } + return []; +}; diff --git a/src/timeline/TimelineContext.tsx b/src/timeline/TimelineContext.tsx index a83b838..9f230b5 100644 --- a/src/timeline/TimelineContext.tsx +++ b/src/timeline/TimelineContext.tsx @@ -105,7 +105,7 @@ export const TimelineProvider = ({ columnWidth: externalColumnWidth, debug = false, displayTasksLabel = false, - dragResolution: externalDragResolution, + dragResolution: externalDragResolution = "1min", enableDrag = true, enableResize = true, headerLabel, @@ -116,7 +116,7 @@ export const TimelineProvider = ({ onTaskChange, tasks: externalTasks = [], range: externalRange, - resolution: externalResolution = "1min", + resolution: externalResolution = "1hrs", resources: externalResources, rowHeight: externalRowHeight, timezone: externalTimezone, From 982e6458b434fd8668d631ed0add4ee9621928cd Mon Sep 17 00:00:00 2001 From: "krzysztof.grudzinski" Date: Mon, 6 Nov 2023 17:04:36 +0100 Subject: [PATCH 10/12] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20Added=20type?= =?UTF-8?q?=20for=20HourInfo=20and=20DayInfo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Closes: #140 --- src/grid/Cells/utils.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/grid/Cells/utils.ts b/src/grid/Cells/utils.ts index 65460ee..e075e38 100644 --- a/src/grid/Cells/utils.ts +++ b/src/grid/Cells/utils.ts @@ -2,13 +2,18 @@ import { Interval } from "luxon"; import { daysInMonth, getMonth, getStartMonthsDay, getYear, Scale } from "../../utils/time-resolution"; -interface visibleDayInfoProps { +interface VisibleHourInfoProps { backHour?: boolean; nextHour?: boolean; } +interface DayDetailProps { + thisMonth?: number; + untilNow?: number; +} + export const timeBlockTz = (timeBlock: Interval[], initialTz?: string) => { - const dayInfoArray: visibleDayInfoProps[] = []; + const dayInfoArray: VisibleHourInfoProps[] = []; timeBlock.forEach((column) => { const tzStart = column.start!.toISO()?.slice(-6); @@ -36,10 +41,7 @@ export const timeBlockTz = (timeBlock: Interval[], initialTz?: string) => { export const dayDetail = (unitAbove: Scale, aboveTimeBlocks: Interval[], interval: Interval) => { if (unitAbove === "month") { - const dayInfo: { - thisMonth?: number; - untilNow?: number; - }[] = []; + const dayInfo: DayDetailProps[] = []; aboveTimeBlocks.forEach((column, index) => { const month = getMonth(column); const year = getYear(column); From a134be622a7560590f2b2c77615248de247f0fde Mon Sep 17 00:00:00 2001 From: "krzysztof.grudzinski" Date: Mon, 6 Nov 2023 17:30:42 +0100 Subject: [PATCH 11/12] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20Code=20refacot?= =?UTF-8?q?ring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Closes: #140 --- src/grid/Cell/index.tsx | 3 +++ src/grid/CellGroup/index.tsx | 8 ++++++++ src/grid/Cells/index.tsx | 6 ++++-- .../Cells/utils.ts => utils/timeBlockArray.ts} | 14 ++++++++++++-- 4 files changed, 27 insertions(+), 4 deletions(-) rename src/{grid/Cells/utils.ts => utils/timeBlockArray.ts} (97%) diff --git a/src/grid/Cell/index.tsx b/src/grid/Cell/index.tsx index 512e88c..a22a2a3 100644 --- a/src/grid/Cell/index.tsx +++ b/src/grid/Cell/index.tsx @@ -31,6 +31,7 @@ const GridCell = ({ column, height, index, hourInfo: visibleDayInfo }: GridCellP if (visibleDayInfo.backHour) { return columnWidth * (index + blocksOffset) + columnWidth / 24; } + if (visibleDayInfo.nextHour) { return columnWidth * (index + blocksOffset) - columnWidth / 24; } @@ -39,10 +40,12 @@ const GridCell = ({ column, height, index, hourInfo: visibleDayInfo }: GridCellP if (visibleDayInfo.backHour) { return columnWidth * (index + blocksOffset) + columnWidth / 168; } + if (visibleDayInfo.nextHour) { return columnWidth * (index + blocksOffset) - columnWidth / 168; } } + return columnWidth * (index + blocksOffset); }, [blocksOffset, columnWidth, index, visibleDayInfo, resolutionUnit]); diff --git a/src/grid/CellGroup/index.tsx b/src/grid/CellGroup/index.tsx index 3ed8cfc..936f722 100644 --- a/src/grid/CellGroup/index.tsx +++ b/src/grid/CellGroup/index.tsx @@ -34,6 +34,7 @@ const GridCellGroup = ({ column, index, dayInfo, hourInfo }: GridCellGroupProps) if (unitAbove === "month") { return Duration.fromObject({ ["day"]: dayInfo![index].thisMonth }).as("week") / sizeInUnits; } + return Duration.fromObject({ [unitAbove]: 1 }).as(unit) / sizeInUnits; }, [sizeInUnits, dayInfo, index, unitAbove, unit]); @@ -45,28 +46,35 @@ const GridCellGroup = ({ column, index, dayInfo, hourInfo }: GridCellGroupProps) if (unitAbove === "month") { const pxUntil = index !== 0 ? Duration.fromObject({ ["day"]: dayInfo![index - 1].untilNow }).as("week") / sizeInUnits : 0; + if (hourInfo!.backHour) { const hourInMonthPx = columnWidth / 168; return pxUntil * columnWidth + unitAboveSpanInPx + hourInMonthPx; } + if (hourInfo!.nextHour) { const hourInMonthPx = columnWidth / 168; return pxUntil * columnWidth + unitAboveSpanInPx - hourInMonthPx; } + return pxUntil * columnWidth + unitAboveSpanInPx; } + if (unitAbove === "day") { if (hourInfo!.backHour) { return index * unitAboveSpanInPx + columnWidth / sizeInUnits; } + if (hourInfo!.nextHour) { return index * unitAboveSpanInPx - columnWidth / sizeInUnits; } } + if (unitAbove === "week") { if (hourInfo!.backHour) { return index * unitAboveSpanInPx + columnWidth / 24; } + if (hourInfo!.nextHour) { return index * unitAboveSpanInPx - columnWidth / 24; } diff --git a/src/grid/Cells/index.tsx b/src/grid/Cells/index.tsx index bf7348d..be4b359 100644 --- a/src/grid/Cells/index.tsx +++ b/src/grid/Cells/index.tsx @@ -2,11 +2,10 @@ import React, { memo, useMemo } from "react"; import { KonvaGroup } from "../../@konva"; import { useTimelineContext } from "../../timeline/TimelineContext"; +import { dayDetail, timeBlockTz } from "../../utils/timeBlockArray"; import GridCell from "../Cell"; import GridCellGroup from "../CellGroup"; -import { dayDetail, timeBlockTz } from "./utils"; - interface GridCellsProps { height: number; } @@ -18,14 +17,17 @@ const GridCells = ({ height }: GridCellsProps) => { visibleTimeBlocks, resolution: { unitAbove }, } = useTimelineContext(); + const tz = useMemo(() => interval.start!.toISO()!.slice(-6), [interval]); const dayInfo = useMemo( () => dayDetail(unitAbove, aboveTimeBlocks, interval), [unitAbove, aboveTimeBlocks, interval] ); + const aboveHourInfo = useMemo(() => timeBlockTz(aboveTimeBlocks, tz), [tz, aboveTimeBlocks]); const visibileHourInfo = useMemo(() => timeBlockTz(visibleTimeBlocks, tz), [tz, visibleTimeBlocks]); + return ( {aboveTimeBlocks.map((column, index) => ( diff --git a/src/grid/Cells/utils.ts b/src/utils/timeBlockArray.ts similarity index 97% rename from src/grid/Cells/utils.ts rename to src/utils/timeBlockArray.ts index e075e38..7a19c4d 100644 --- a/src/grid/Cells/utils.ts +++ b/src/utils/timeBlockArray.ts @@ -1,6 +1,6 @@ import { Interval } from "luxon"; -import { daysInMonth, getMonth, getStartMonthsDay, getYear, Scale } from "../../utils/time-resolution"; +import { daysInMonth, getMonth, getStartMonthsDay, getYear, Scale } from "./time-resolution"; interface VisibleHourInfoProps { backHour?: boolean; @@ -14,6 +14,7 @@ interface DayDetailProps { export const timeBlockTz = (timeBlock: Interval[], initialTz?: string) => { const dayInfoArray: VisibleHourInfoProps[] = []; + timeBlock.forEach((column) => { const tzStart = column.start!.toISO()?.slice(-6); @@ -23,29 +24,36 @@ export const timeBlockTz = (timeBlock: Interval[], initialTz?: string) => { backHour: true, nextHour: false, }); + return; } + dayInfoArray.push({ backHour: false, nextHour: true, }); } + dayInfoArray.push({ backHour: false, nextHour: false, }); + return; }); + return dayInfoArray; }; export const dayDetail = (unitAbove: Scale, aboveTimeBlocks: Interval[], interval: Interval) => { if (unitAbove === "month") { const dayInfo: DayDetailProps[] = []; + aboveTimeBlocks.forEach((column, index) => { const month = getMonth(column); const year = getYear(column); const currentMonthDays = daysInMonth(Number(month), Number(year)); + if (index === 0) { const startDay = getStartMonthsDay(interval.start!); const daysToMonthEnd = currentMonthDays - Number(startDay) + 1; @@ -53,15 +61,17 @@ export const dayDetail = (unitAbove: Scale, aboveTimeBlocks: Interval[], interva thisMonth: daysToMonthEnd, untilNow: daysToMonthEnd, }); + return; } - const n = dayInfo[index - 1].untilNow! + currentMonthDays; + const n = dayInfo[index - 1].untilNow! + currentMonthDays; dayInfo.push({ thisMonth: currentMonthDays, untilNow: n, }); }); + return dayInfo; } return []; From def605cd93e4e60b3cbe0b74559dedbfa5ef5955 Mon Sep 17 00:00:00 2001 From: "krzysztof.grudzinski" Date: Mon, 6 Nov 2023 17:32:35 +0100 Subject: [PATCH 12/12] =?UTF-8?q?refactor:=20=F0=9F=92=A1=20Code=20refacto?= =?UTF-8?q?ring?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✅ Closes: #140 --- src/timeline/TimelineContext.tsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/timeline/TimelineContext.tsx b/src/timeline/TimelineContext.tsx index 9f230b5..c905b41 100644 --- a/src/timeline/TimelineContext.tsx +++ b/src/timeline/TimelineContext.tsx @@ -4,7 +4,7 @@ import { DateTime, Interval } from "luxon"; import { addHeaderResource } from "../resources/utils/resources"; import { filterTasks, TaskData, validateTasks } from "../tasks/utils/tasks"; import { DEFAULT_GRID_COLUMN_WIDTH, DEFAULT_GRID_ROW_HEIGHT, MINIMUM_GRID_ROW_HEIGHT } from "../utils/dimensions"; -import { logDebug, logError, logWarn } from "../utils/logger"; +import { logDebug, logWarn } from "../utils/logger"; import { getValidRangeTime, getValidTime, InternalTimeRange, isValidRangeTime } from "../utils/time"; import { getIntervalFromInternalTimeRange } from "../utils/time"; import { getResolutionData, Resolution, ResolutionData } from "../utils/time-resolution"; @@ -213,16 +213,18 @@ export const TimelineProvider = ({ const intervalEnd = interval.end!; let blockStart = intervalStart; + while (blockStart < intervalEnd) { let blockEnd = blockStart.endOf(unitAbove); + if (blockEnd > intervalEnd) { blockEnd = intervalEnd; } - logError("Adding Block", `${blockStart.toFormat("dd/MM/yy HH:mm")} > ${blockEnd.toFormat("dd/MM/yy HH:mm")}`); blocks.push(Interval.fromDateTimes(blockStart, blockEnd)); blockStart = blockEnd.startOf(unitAbove).plus({ [unitAbove]: 1 }); } + return blocks; }, [interval, resolution]);