Skip to content

Commit

Permalink
Merge pull request #23 from HE-Arc/3-create-logic-of-milestone-placement
Browse files Browse the repository at this point in the history
Create logic of milestone placement
  • Loading branch information
theory-of-evrth authored Dec 5, 2024
2 parents fae62db + 452a89c commit 05a38c4
Show file tree
Hide file tree
Showing 5 changed files with 77 additions and 40 deletions.
2 changes: 1 addition & 1 deletion timeliner/app/Models/Node.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ class Node extends Model

public function milestones()
{
return $this->hasMany(Milestone::class, 'node');
return $this->hasMany(Milestone::class, 'node'); //->sortBy('date');
}
}
29 changes: 16 additions & 13 deletions timeliner/resources/css/timelinestyle.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,31 +10,36 @@
background-repeat: repeat-x;
background-position-y: center;
position: relative;
display: flex;
/*width: 100%;*/
overflow: visible;
}

.milestones-container {

position: relative;
display: flex;
align-items: center;
justify-content: flex-start;
width: auto;
}

.milestone {
flex-shrink: 0;
display: inline-block;
/*flex-shrink: 0;*/
display: flex;
cursor: pointer;
position: relative;
}

.milestone-icon {
width: 50px;
height: 50px;
width: 2em;
height: 2em;
border-radius: 50%;
background-color: #313131;
color: white;
display: flex;
justify-content: center;
align-items: center;
font-size: 24px;
font-size: 2em;
transition: transform 0.3s ease;
}

Expand All @@ -49,31 +54,29 @@
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
max-width: 250px;
max-width: 10em;
width: auto;
z-index: 100;
}

/* When the milestone is hovered, display the info */
.milestone:hover .milestone-info {
display: block;
}

/* Styling for the content panel */
.milestone-content {
background-color: white;
border-radius: 8px;
padding: 10px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
border-radius: 0.5rem;
padding: 1rem;
box-shadow: 0 2rem 2rem rgba(0, 0, 0, 0.1);
opacity: 0;
animation: fadeIn 0.3s forwards;
}

/* Optional: Fade-in animation */
@keyframes fadeIn {
from {
opacity: 0;
transform: translateY(10px);
transform: translateY(1rem);
}
to {
opacity: 1;
Expand Down
74 changes: 51 additions & 23 deletions timeliner/resources/js/timelinelistener.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,39 +21,67 @@ document.addEventListener('DOMContentLoaded', () => {
return;
}

// Calculate date range for proportional spacing
const minDate = new Date(Math.min(...dates));
const maxDate = new Date(Math.max(...dates));
let timelineWidth = 100;
updateTimelineWidth(timelineWidth); //

console.log("mindate " + minDate);
console.log("maxdate " + maxDate);
const timelineSlider = document.getElementById('timelineSlider');

nodes.forEach(node => {
const milestones = node.querySelectorAll('.milestone');
// listener for the change of the slider, to readjust timeline output
timelineSlider.addEventListener('input', (event) => {
timelineWidth = event.target.value;
timelineWidthValue.textContent = timelineWidth;
updateTimelineWidth(timelineWidth);
});

// readjust output of the timeline
function updateTimelineWidth(newWidth) {

// Calculate date range for proportional spacing
const minDate = new Date(Math.min(...dates));
const maxDate = new Date(Math.max(...dates));

const totalDays = (maxDate - minDate) / (1000 * 60 * 60 * 24);
console.log("mindate " + minDate);
console.log("maxdate " + maxDate);

nodes.forEach(node => {
const milestones = node.querySelectorAll('.milestone');

milestones.forEach((milestone, index) => {
let prevMilestoneDate;
if (index === 0) {
prevMilestoneDate = minDate;
}
else{
prevMilestoneDate = parseDate(milestones[index - 1].dataset.date);
}
const currentMilestoneDate = parseDate(milestone.dataset.date);
const totalDays = (maxDate - minDate) / (1000 * 60 * 60 * 24);

const daysDifference = (currentMilestoneDate - prevMilestoneDate) / (1000 * 60 * 60 * 24);
const gapPercentage = (daysDifference / totalDays) * 100;
const totalTimelineWidth = newWidth;
const scalingFactor = totalTimelineWidth / totalDays;

console.log("milestones length: " + milestones.length);
console.log(prevMilestoneDate + " percentage is " + gapPercentage +"index"+index);
milestone.style.marginLeft = `${gapPercentage}%`;
let offset;
let cumulativePosition = 32;

milestones.forEach((milestone, index) => {
let prevMilestoneDate;
offset = milestone.offsetWidth / 2;
if (index === 0) {
prevMilestoneDate = minDate;
} else {
prevMilestoneDate = parseDate(milestones[index - 1].dataset.date);
}

const currentMilestoneDate = parseDate(milestone.dataset.date);
const daysDifference = (currentMilestoneDate - prevMilestoneDate) / (1000 * 60 * 60 * 24);

// Calculate the value as pixels defined by scaling factor set by user
const gapInPixels = daysDifference * scalingFactor;

cumulativePosition += gapInPixels*totalTimelineWidth;

// Position this milestone based on cumulative gap and center it.
milestone.style.position = "absolute";
milestone.style.left = `${cumulativePosition - offset}px`;
});

// adjust node and milestone containers width (needed since the milestones are placed via absolute position)
node.style.width = `${cumulativePosition + (milestones.length+1)*offset}px`;
const milestonesContainer = document.querySelector('.milestones-container');
milestonesContainer.style.width = `${cumulativePosition}px`;
});
});
}
});


Expand Down
6 changes: 3 additions & 3 deletions timeliner/resources/views/timeline/partials/node.blade.php
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@

<!-- TODO : make width be fetched and calculated proportionately -->
<div class="node w-[100%] flex space-x-4" style="--line-color: {{$node->color}};" data-milestones="{{$node->milestones}}">
<div class="node w-[100%] space-x-4" style="--line-color: {{$node->color}};" data-milestones="{{$node->milestones}}">
<div class="p-4 w-[100px] rounded" style="background-color: {{$node->color}}">{{$node->name}}</div>
<!-- TODO : make milestones evenly distributed over the node and aligned -->
<div class="milestones-container flex" data-min-date="{{ $node->milestones->min('date') }}" data-max-date="{{ $node->milestones->max('date') }}">

<div class="milestones-container" data-min-date="{{ $node->milestones->min('date') }}" data-max-date="{{ $node->milestones->max('date') }}">

@foreach($node->milestones as $milestone)
@include("timeline.partials.milestone", ["milestone"=>$milestone])
Expand Down
6 changes: 6 additions & 0 deletions timeliner/resources/views/timeline/timeline.blade.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@
@endforeach
</div>

<div class="p-2 text-gray-500 border border-gray rounded-lg">
<label for="timelineSlider">Adjust Timeline Scaling</label>
<input type="range" id="timelineSlider" min="30" max="200" value="100" step="1">
<span id="timelineWidthValue">100</span>
</div>


<!-- Comments to this timeline section -->

Expand Down

0 comments on commit 05a38c4

Please sign in to comment.