d3.js Gantt Timeline_v2
by alketraz
HTML
<body>
<h1>Timeline</h1>
<br />
<p>
<strong>Request</strong>
</p>
<ul>
<li>Activity within the same group should be placed on the same line</li>
</ul>
<br />
<strong>Issue / Ideal</strong>
<ul>
<li>This results in the last mysql activity overlapping with the one above</li>
<li>If possible, in this case the last mySql should be on its own line, so the database group would have 3 rows, 2 x mysql and 1 x postgresql</li>
</ul>
<script type="text/javascript" src="https://d3js.org/d3.v5.min.js"></script>
<script src="https://d3js.org/d3-array.v2.min.js"></script>
</body>
CSS
*,
*::before,
*::after {
padding: 0;
margin: 0;
box-sizing: border-box;
}
svg {
border: thin solid lightgray;
background-color: lightcyan;
}
.svg-container {
display: block;
position: absolute;
width: 100%;
height: 90%;
}
.svg-content-responsive {
display: inline-block;
position: absolute;
top: 0;
left: 0;
max-height: 100%;
margin: 10px;
}
rect.activity {
opacity: 0.8;
stroke: black;
stroke-opacity: 0.8;
}
rect.frontend {
fill: orange;
}
rect.operations {
fill: blueviolet;
}
rect.devops {
fill: aqua;
}
rect.backend {
fill: salmon;
}
rect.database {
fill: green;
}
rect.marketing {
fill: rgb(255, 207, 14);
}
.tick line {
visibility: hidden;
}
g.swimlane-activity rect {
stroke: white;
stroke-width: 2px;
opacity: 0.5;
}
JavaScript
let settings = [
{
group: "operations",
colour: "rgba(0, 0, 0, 0.1)",
},
{
group: "devops",
colour: "rgba(0, 0, 255, 0.1)",
},
{
group: "frontend",
colour: "rgba(0, 255, 0, 0.1)",
},
{
group: "database",
colour: "rgba(255, 0, 0, 0.1)",
},
];
const projects = [
{
id: "1",
activity: "foo",
group: "operations",
start_date: "2018-01-01",
end_date: "2019-12-31",
},
{
id: "2",
activity: "bar",
group: "operations",
start_date: "2020-10-31",
end_date: "2020-11-09",
},
{
id: "3",
activity: "foo",
group: "operations",
start_date: "2020-05-09",
end_date: "2020-08-09",
},
{
id: "4",
activity: "foo",
group: "devops",
start_date: "2018-04-01",
end_date: "2020-12-31",
},
{
id: "5",
activity: "bar",
group: "devops",
start_date: "2018-01-01",
end_date: "2019-09-30",
},
{
id: "6",
activity: "foo",
group: "frontend",
start_date: "2017-01-01",
end_date: "2019-01-31",
},
{
id: "9",
activity: "mysql",
group: "database",
start_date: "2015-01-01",
end_date: "2015-09-15",
},
{
id: "10",
activity: "postgresql",
group: "database",
start_date: "2016-01-01",
end_date: "2017-12-31",
},
{
id: "11",
activity: "mysql",
group: "database",
start_date: "2018-05-01",
end_date: "2018-12-31",
},
{
id: "12",
activity: "mysql",
group: "database",
start_date: "2018-09-01",
end_date: "2019-12-31",
},
];
// Process data
projects.sort((a, b) => d3.ascending(a.start_date, b.start_date));
Array.prototype.groupBy = function (props) {
var arr = this;
var partialResult = {};
arr.forEach((el) => {
var grpObj = {};
props.forEach((prop) => {
grpObj[prop] = el[prop];
});
var key = JSON.stringify(grpObj);
if (!partialResult[key]) partialResult[key] = [];
partialResult[key].push(el);
});
...