Skip to content

Commit

Permalink
Fix events clustering for multi day timeline & added range and date n…
Browse files Browse the repository at this point in the history
…ormalization
  • Loading branch information
GeorgeHop committed Feb 2, 2022
1 parent 20f5632 commit 56d029a
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 27 deletions.
63 changes: 36 additions & 27 deletions src/Timetable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {Text, useWindowDimensions, View, ScrollView} from "react-native";
import NowLine from "./components/NowLine";
import {clusterizer, prepareTimetable, setClusterWidth, setNodesPosition} from "./helpers/eventsPreparer";
import {hours} from "./constants/constants";
import {dateRangesOverlap, daysDiff, minDiff, validateRange} from "./helpers/date";
import {dateRangesOverlap, daysDiff, minDiff, normalizeTime, validateRange} from "./helpers/date";

const shouldRenderHeaders = (columnsAmount, headersEnabled) => headersEnabled === undefined ? columnsAmount > 1 : headersEnabled;

Expand Down Expand Up @@ -59,8 +59,8 @@ export default function Timetable(props) {

const [items, setItems] = React.useState([]);
const [range, setRange] = React.useState({
from: new Date(props.date || props.range?.from),
till: new Date(props.date || props.range?.till),
from: normalizeTime(props.date || props.range?.from),
till: normalizeTime(props.date || props.range?.till, 23, 59, 59, 999),
});

const fromHour = props.hasOwnProperty('fromHour') ? props.fromHour : 0;
Expand Down Expand Up @@ -110,8 +110,8 @@ export default function Timetable(props) {

/* Update range on props change */
React.useEffect(() => {
const from = props.date || props.range?.from;
const till = props.date || props.range?.till;
const from = normalizeTime(props.date || props.range?.from);
const till = normalizeTime(props.date || props.range?.till, 23, 59, 59, 999);

if (!from || !till)
return;
Expand All @@ -129,25 +129,34 @@ export default function Timetable(props) {

let positionedEvents = [];

const {preparedEvents, minutes} = prepareTimetable(props.items, startProperty, endProperty, itemMinHeight);
const clusteredTimetable = clusterizer(preparedEvents, minutes);
setClusterWidth(clusteredTimetable, columnWidth);
setNodesPosition(clusteredTimetable);

for (let nodeId in clusteredTimetable.nodes) {
let node = clusteredTimetable.nodes[nodeId];
let data = node?.data;

const itemStart = new Date(data?.[startProperty]);
const itemEnd = new Date(data?.[endProperty]);
const itemMinEnd = new Date(itemStart);
itemMinEnd.setMinutes(itemStart.getMinutes() + itemMinHeight);
const daysTotal = daysDiff(itemStart, itemEnd) + 1;

columnDays.forEach((columnDay, columnIndex) => {
if (!dateRangesOverlap(columnDay.start, columnDay.end, itemStart, itemEnd))
return;

columnDays.forEach((columnDay, columnIndex) => {
const normalizedStartDate = new Date(normalizeTime(columnDay?.date));
const normalizedEndDate = new Date(normalizeTime(columnDay?.date, 23, 59, 59, 999));

// Filter event by column date
const filteredItems = props?.items.filter(item => dateRangesOverlap(normalizedStartDate, normalizedEndDate, new Date(item[startProperty]), new Date(item[endProperty])));

// If length === 0 skip process
if (!filteredItems?.length)
return;

const {
preparedEvents,
minutes
} = prepareTimetable(filteredItems, startProperty, endProperty, itemMinHeight);
const clusteredTimetable = clusterizer(preparedEvents, minutes);
setClusterWidth(clusteredTimetable, columnWidth);
setNodesPosition(clusteredTimetable);

for (let nodeId in clusteredTimetable.nodes) {
let node = clusteredTimetable.nodes[nodeId];
let data = node?.data;

const itemStart = new Date(data?.[startProperty]);
const itemEnd = new Date(data?.[endProperty]);
const itemMinEnd = new Date(itemStart);
itemMinEnd.setMinutes(itemStart.getMinutes() + itemMinHeight);
const daysTotal = daysDiff(itemStart, itemEnd) + 1;
const neighboursCount = Object.keys(node?.neighbours).length;
const start = Math.max(+columnDay.start, +itemStart); // card begins either at column's beginning or item's start time, whatever is greater
const end = Math.min(+columnDay.end + 1, Math.max(+itemEnd, +itemMinEnd)); // card ends either at column's end or item's end time, whatever is lesser
Expand Down Expand Up @@ -175,16 +184,16 @@ export default function Timetable(props) {
item: node.data,
daysTotal,
style: {
position: 'absolute',
position: 'absolute',
zIndex: 3,
top,
left,
height,
width
},
});
});
}
}
});

setItems(positionedEvents);
}, [
Expand Down
6 changes: 6 additions & 0 deletions src/helpers/date.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,9 @@ export const validateRange = ({date, range}) => {
console.error(`Invalid type of property ${key}. Expected nothing, instance of Date or ISO string, got ${value}`);
}
};

export const normalizeTime = (date, hours = 0, min = 0, sec = 0, ms = 0) => {
let preparedDate = new Date(date).setUTCHours(hours, min, sec, ms);

return new Date(preparedDate).toISOString();
};

0 comments on commit 56d029a

Please sign in to comment.