Skip to content

Commit 0a3fb30

Browse files
gantt prototype
1 parent 25c05b4 commit 0a3fb30

File tree

3 files changed

+140
-0
lines changed

3 files changed

+140
-0
lines changed

src/common/GanttChart.jsx

Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
const DATA = [
2+
{
3+
id: 1,
4+
name: "Task 1",
5+
start: "2025-04-07T12:00:00Z",
6+
end: "2025-04-07T13:00:00Z",
7+
},
8+
{
9+
id: 2,
10+
name: "Task 2",
11+
start: "2025-04-07T13:00:00Z",
12+
end: "2025-04-07T14:00:00Z",
13+
},
14+
{
15+
id: 3,
16+
name: "Task 3",
17+
start: "2025-04-07T14:00:00Z",
18+
end: "2025-04-07T15:00:00Z",
19+
},
20+
{
21+
id: 4,
22+
name: "Task 4 very long name that should be truncated long name. lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.",
23+
start: "2025-04-07T15:00:00Z",
24+
end: "2025-04-07T16:00:00Z",
25+
},
26+
];
27+
28+
/**
29+
* GanttChart component
30+
*/
31+
const GanttChart = ({ data }) => {
32+
data = data || DATA;
33+
34+
// endDate is now or the max end date of the tasks
35+
let endDate = new Date();
36+
data.forEach((task) => {
37+
const taskEndDate = new Date(task.end);
38+
if (taskEndDate > endDate) {
39+
endDate = taskEndDate;
40+
}
41+
});
42+
43+
// startDate is now minus 1 day
44+
let startDate = new Date();
45+
startDate.setDate(startDate.getDate() - 1);
46+
data.forEach((task) => {
47+
const taskStartDate = new Date(task.start);
48+
if (taskStartDate < startDate) {
49+
startDate = taskStartDate;
50+
}
51+
});
52+
53+
// Get the number of hours between startDate and endDate
54+
const hours = Math.abs(endDate - startDate) / 36e5;
55+
56+
// Gantt chart with a floating sidebar and a scrollable chart
57+
return (
58+
<div className="flex flex-row">
59+
{/* Sidebar with task names */}
60+
<div className="w-1/4">
61+
<div className="h-[3rem] box-border border-b border-r"></div>
62+
{data.map((task) => (
63+
<div
64+
key={task.id}
65+
className="max-w-full h-[3rem] px-2 flex items-center box-border border-b border-l border-r"
66+
>
67+
<span className="truncate text-sm">{task.name}</span>
68+
</div>
69+
))}
70+
</div>
71+
72+
{/* Gantt chart */}
73+
<div
74+
className="w-3/4 overflow-x-scroll custom-scrollbar"
75+
ref={(el) => {
76+
if (el) {
77+
el.scrollLeft = el.scrollWidth;
78+
}
79+
}}
80+
>
81+
<div className="flex flex-col" style={{ width: `${hours * 100}px` }}>
82+
<div className="h-[3rem] border-b flex">
83+
{[...Array(hours).keys()].map((i) => (
84+
<div
85+
key={i}
86+
className="w-[100px] h-full box-border border-r flex items-center justify-center"
87+
>
88+
{new Date(startDate.getTime() + i * 36e5).toLocaleTimeString(
89+
"en-US",
90+
{
91+
hour: "2-digit",
92+
minute: "2-digit",
93+
}
94+
)}
95+
</div>
96+
))}
97+
</div>
98+
99+
{data.map((task) => (
100+
<div
101+
className="h-[3rem] box-border border-b flex items-center py-1"
102+
key={task.id}
103+
>
104+
<div
105+
className="bg-blue-700 text-white w-full max-w-full h-full flex items-center truncate rounded-sm"
106+
style={{
107+
width: `${
108+
((new Date(task.end) - new Date(task.start)) / 36e5) * 100
109+
}px`,
110+
marginLeft: `${
111+
((new Date(task.start) - startDate) / 36e5) * 90
112+
}px`,
113+
}}
114+
></div>
115+
</div>
116+
))}
117+
</div>
118+
</div>
119+
</div>
120+
);
121+
};
122+
123+
export default GanttChart;

src/layout/Router.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import { appActions } from "../store/appSlice";
2727
import { useEffect } from "react";
2828
import Footer from "./Footer";
2929
import TopAnnouncement from "./TopAnnouncement";
30+
import ExperimentGanttView from "../pages/ExperimentGanttView";
3031

3132
const router = createBrowserRouter(
3233
[
@@ -102,6 +103,10 @@ const router = createBrowserRouter(
102103
path: "/experiment/:expid/performance",
103104
element: <ExperimentPerformance />,
104105
},
106+
{
107+
path: "/experiment/:expid/gantt",
108+
element: <ExperimentGanttView />,
109+
}
105110
],
106111
},
107112
],

src/pages/ExperimentGanttView.jsx

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
2+
import GanttChart from "../common/GanttChart"
3+
4+
5+
const ExperimentGanttView = () => {
6+
return (
7+
<div className="w-full flex flex-col gap-4">
8+
<GanttChart />
9+
</div>
10+
)
11+
}
12+
export default ExperimentGanttView;

0 commit comments

Comments
 (0)