|
|
@ -6,7 +6,7 @@ var parts = []; |
|
|
|
var sCurvePayload = { |
|
|
|
var sCurvePayload = { |
|
|
|
period: 'week', |
|
|
|
period: 'week', |
|
|
|
project_id: proyekId, |
|
|
|
project_id: proyekId, |
|
|
|
gantt_id: ganttId |
|
|
|
gantt_id: ganttId |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function callback(response) { |
|
|
|
function callback(response) { |
|
|
@ -16,7 +16,7 @@ function callback(response) { |
|
|
|
function messageListener(event) { |
|
|
|
function messageListener(event) { |
|
|
|
if (event.data && event.data.action === 'sendUrl') { |
|
|
|
if (event.data && event.data.action === 'sendUrl') { |
|
|
|
const parentUrl = event.data.url; |
|
|
|
const parentUrl = event.data.url; |
|
|
|
const isHierarchy = event.data.isHierarchy; |
|
|
|
const isHierarchy = event.data.isHierarchy; |
|
|
|
|
|
|
|
|
|
|
|
// Split the remaining path by "/"
|
|
|
|
// Split the remaining path by "/"
|
|
|
|
parts = parentUrl.split("/"); |
|
|
|
parts = parentUrl.split("/"); |
|
|
@ -67,89 +67,147 @@ function getSCurveData() { |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
function toggleOverlay() { |
|
|
|
function toggleOverlay() { |
|
|
|
if(overlayControl.isOverlayVisible(lineOverlay)){ |
|
|
|
if (overlayControl.isOverlayVisible(lineOverlay)) { |
|
|
|
gantt.config.readonly = false; |
|
|
|
gantt.config.readonly = false; |
|
|
|
overlayControl.hideOverlay(lineOverlay); |
|
|
|
overlayControl.hideOverlay(lineOverlay); |
|
|
|
gantt.$root.classList.remove("overlay_visible"); |
|
|
|
gantt.$root.classList.remove("overlay_visible"); |
|
|
|
}else{ |
|
|
|
} else { |
|
|
|
gantt.config.readonly = true; |
|
|
|
gantt.config.readonly = true; |
|
|
|
overlayControl.showOverlay(lineOverlay); |
|
|
|
overlayControl.showOverlay(lineOverlay); |
|
|
|
gantt.$root.classList.add("overlay_visible"); |
|
|
|
gantt.$root.classList.add("overlay_visible"); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function getChartScaleRange(){ |
|
|
|
function getChartScaleRange() { |
|
|
|
var tasksRange = gantt.getSubtaskDates(); |
|
|
|
var tasksRange = gantt.getSubtaskDates(); |
|
|
|
var cells = []; |
|
|
|
var cells = []; |
|
|
|
var scale = gantt.getScale(); |
|
|
|
var scale = gantt.getScale(); |
|
|
|
if(!tasksRange.start_date){ |
|
|
|
if (!tasksRange.start_date) { |
|
|
|
return scale.trace_x; |
|
|
|
return scale.trace_x; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
scale.trace_x.forEach(function(date){ |
|
|
|
scale.trace_x.forEach(function (date) { |
|
|
|
// if(date >= tasksRange.start_date && date <= tasksRange.end_date){
|
|
|
|
// if(date >= tasksRange.start_date && date <= tasksRange.end_date){
|
|
|
|
// cells.push(date);
|
|
|
|
// cells.push(date);
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
cells.push(date); |
|
|
|
cells.push(date); |
|
|
|
}); |
|
|
|
}); |
|
|
|
return cells; |
|
|
|
return cells; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
function getProgressLine(){ |
|
|
|
function getProgressLine() { |
|
|
|
// As long as the progress data length is same with chart scale range (period) then it's fine.
|
|
|
|
// As long as the progress data length is same with chart scale range (period) then it's fine.
|
|
|
|
getSCurveData(); |
|
|
|
getSCurveData(); |
|
|
|
// console.log("apa ", return_first);
|
|
|
|
// console.log("apa ", return_first);
|
|
|
|
var cumulativePlannedDurations = return_first.data[0].data.percentagePlan; |
|
|
|
var cumulativePlannedDurations = return_first.data[0].data.percentagePlan; |
|
|
|
var cumulativeRealDurations = return_first.data[0].data.percentageReal; |
|
|
|
var cumulativeRealDurations = return_first.data[0].data.percentageReal; |
|
|
|
cumulativeRealDurations[cumulativeRealDurations.length - 1] = Math.ceil(cumulativeRealDurations[cumulativeRealDurations.length - 1]); |
|
|
|
cumulativeRealDurations[cumulativeRealDurations.length - 1] = Math.ceil(cumulativeRealDurations[cumulativeRealDurations.length - 1]); |
|
|
|
var maxPlan = cumulativePlannedDurations[cumulativePlannedDurations.length - 1] |
|
|
|
var maxPlan = cumulativePlannedDurations[cumulativePlannedDurations.length - 1] |
|
|
|
var maxReal = cumulativeRealDurations[cumulativeRealDurations.length - 1] |
|
|
|
var maxReal = cumulativeRealDurations[cumulativeRealDurations.length - 1] |
|
|
|
var dates = return_first.data[0].data.date; |
|
|
|
var dates = return_first.data[0].data.date; |
|
|
|
//jika summary s curve
|
|
|
|
// Determine the appropriate data points based on the Gantt chart zoom level
|
|
|
|
if (maxReal > 100 || maxPlan > 100) { |
|
|
|
var chartScaleRange = getChartScaleRange(); |
|
|
|
var plannedDurations = cumulativePlannedDurations.map((item) => { |
|
|
|
var zoomLevel = gantt.ext.zoom.getCurrentLevel(); |
|
|
|
return item/maxPlan*100; |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
var realDurations = cumulativeRealDurations.map((item) => { |
|
|
|
|
|
|
|
return item/maxPlan*100; |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
return {planned: plannedDurations, real: realDurations, dates: dates}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return {planned: cumulativePlannedDurations, real: cumulativeRealDurations, dates: dates}; |
|
|
|
// Adjust data points based on the zoom level
|
|
|
|
|
|
|
|
var plannedDurations, realDurations; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (zoomLevel === 2) { |
|
|
|
|
|
|
|
// Adjust data to monthly points
|
|
|
|
|
|
|
|
plannedDurations = adjustDataToZoom(dates, cumulativePlannedDurations, chartScaleRange, 2).data; |
|
|
|
|
|
|
|
realDurations = adjustDataToZoom(dates, cumulativeRealDurations, chartScaleRange, 2).data; |
|
|
|
|
|
|
|
dates = adjustDataToZoom(dates, cumulativeRealDurations, chartScaleRange, 2).dates; |
|
|
|
|
|
|
|
} else if (zoomLevel === 1) { |
|
|
|
|
|
|
|
// Adjust data to weekly points
|
|
|
|
|
|
|
|
plannedDurations = adjustDataToZoom(dates, cumulativePlannedDurations, chartScaleRange, 1).data; |
|
|
|
|
|
|
|
realDurations = adjustDataToZoom(dates, cumulativeRealDurations, chartScaleRange, 1).data; |
|
|
|
|
|
|
|
dates = adjustDataToZoom(dates, cumulativeRealDurations, chartScaleRange, 1).dates; |
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
|
|
// Default: Use daily data points
|
|
|
|
|
|
|
|
plannedDurations = cumulativePlannedDurations; |
|
|
|
|
|
|
|
realDurations = cumulativeRealDurations; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
if (maxReal > 100 || maxPlan > 100) { |
|
|
|
|
|
|
|
plannedDurations = plannedDurations.map((item) => { |
|
|
|
|
|
|
|
return item / maxPlan * 100; |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
realDurations = realDurations.map((item) => { |
|
|
|
|
|
|
|
return item / maxReal * 100; |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { planned: plannedDurations, real: realDurations, dates: dates }; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
function adjustDataToZoom(dates, data, chartScaleRange, zoomLevel) { |
|
|
|
|
|
|
|
// Implement logic to adjust data points based on the Gantt chart zoom level
|
|
|
|
|
|
|
|
// For example, if zoomLevel is 'month', aggregate daily data to monthly data
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Placeholder logic: This example assumes that the chartScaleRange is in days
|
|
|
|
|
|
|
|
var newData = []; |
|
|
|
|
|
|
|
var newDates = []; |
|
|
|
|
|
|
|
var aggregateValue = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (var i = 0; i < data.length; i++) { |
|
|
|
|
|
|
|
aggregateValue = data[i]; |
|
|
|
|
|
|
|
|
|
|
|
function getScalePaddings(values){ |
|
|
|
if (zoomLevel === 2 && i % 30 === 29) { |
|
|
|
|
|
|
|
// Aggregate data for each month (assuming 30 days in a month)
|
|
|
|
|
|
|
|
newData.push(aggregateValue); |
|
|
|
|
|
|
|
newDates.push(dates[i]); |
|
|
|
|
|
|
|
aggregateValue = 0; |
|
|
|
|
|
|
|
} else if (zoomLevel === 1 && (i + 1) % 7 === 0) { |
|
|
|
|
|
|
|
// Aggregate data for each week
|
|
|
|
|
|
|
|
newData.push(aggregateValue); |
|
|
|
|
|
|
|
newDates.push(dates[i]); |
|
|
|
|
|
|
|
aggregateValue = 0; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If there are remaining data points after the loop, add them to the result
|
|
|
|
|
|
|
|
if (aggregateValue > 0) { |
|
|
|
|
|
|
|
newData.push(aggregateValue); |
|
|
|
|
|
|
|
newDates.push(dates[data.length - 1]); |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return { |
|
|
|
|
|
|
|
data: newData, |
|
|
|
|
|
|
|
dates: newDates |
|
|
|
|
|
|
|
}; |
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
function getScalePaddings(values) { |
|
|
|
|
|
|
|
let zoom = gantt.ext.zoom.getCurrentLevel(); |
|
|
|
var scale = gantt.getScale(); |
|
|
|
var scale = gantt.getScale(); |
|
|
|
var dataRange = gantt.getSubtaskDates(); |
|
|
|
var dataRange = gantt.getSubtaskDates(); |
|
|
|
// let minDate = new Date();
|
|
|
|
// let minDate = new Date();
|
|
|
|
// let maxDate = new Date();
|
|
|
|
// let maxDate = new Date();
|
|
|
|
let minValueDate = new Date(values.dates[0]); |
|
|
|
let minValueDate = new Date(values.dates[0]); |
|
|
|
let maxValueDate = new Date(values.dates[values.dates.length -1]); |
|
|
|
let maxValueDate = new Date(values.dates[values.dates.length - 1]); |
|
|
|
|
|
|
|
|
|
|
|
// gantt.eachTask(function(task){
|
|
|
|
// gantt.eachTask(function(task){
|
|
|
|
// let plannedEarlier = task.planned_start < task.start_date;
|
|
|
|
// let plannedEarlier = task.planned_start < task.start_date;
|
|
|
|
// let plannedLater = task.planned_end > task.end_date;
|
|
|
|
// let plannedLater = task.planned_end > task.end_date;
|
|
|
|
|
|
|
|
|
|
|
|
// if (plannedEarlier) {
|
|
|
|
// if (plannedEarlier) {
|
|
|
|
// minDate = new Date(Math.min(minDate.getTime(), task.planned_start.getTime()));
|
|
|
|
// minDate = new Date(Math.min(minDate.getTime(), task.planned_start.getTime()));
|
|
|
|
// } else {
|
|
|
|
// } else {
|
|
|
|
// minDate = new Date(Math.min(minDate.getTime(), task.start_date.getTime()));
|
|
|
|
// minDate = new Date(Math.min(minDate.getTime(), task.start_date.getTime()));
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
|
|
|
|
|
|
|
|
// if (plannedLater) {
|
|
|
|
// if (plannedLater) {
|
|
|
|
// maxDate = new Date(Math.max(maxDate.getTime(), task.planned_end.getTime()));
|
|
|
|
// maxDate = new Date(Math.max(maxDate.getTime(), task.planned_end.getTime()));
|
|
|
|
// } else {
|
|
|
|
// } else {
|
|
|
|
// maxDate = new Date(Math.max(maxDate.getTime(), task.end_date.getTime()));
|
|
|
|
// maxDate = new Date(Math.max(maxDate.getTime(), task.end_date.getTime()));
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
// })
|
|
|
|
// })
|
|
|
|
|
|
|
|
|
|
|
|
var padding = { |
|
|
|
var padding = { |
|
|
|
left:0, |
|
|
|
left: 0, |
|
|
|
right:0 |
|
|
|
right: 0 |
|
|
|
}; |
|
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
if(dataRange.start_date){ |
|
|
|
if (dataRange.start_date) { |
|
|
|
var yScaleLabelsWidth = 48; |
|
|
|
var yScaleLabelsWidth = 48; |
|
|
|
// fine tune values in order to align chart with the scale range
|
|
|
|
// fine tune values in order to align chart with the scale range
|
|
|
|
padding.left = gantt.posFromDate(minValueDate); |
|
|
|
padding.left = gantt.posFromDate(minValueDate); |
|
|
@ -161,33 +219,33 @@ function getScalePaddings(values){ |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
var myChart; |
|
|
|
var myChart; |
|
|
|
var lineOverlay = overlayControl.addOverlay(function(container) { |
|
|
|
var lineOverlay = overlayControl.addOverlay(function (container) { |
|
|
|
var values = getProgressLine(); |
|
|
|
var values = getProgressLine(); |
|
|
|
var scaleLabels = []; |
|
|
|
var scaleLabels = []; |
|
|
|
|
|
|
|
|
|
|
|
// if(parts[2] && parts[2] == '1'){
|
|
|
|
// if(parts[2] && parts[2] == '1'){
|
|
|
|
// values.dates.forEach(function(date){
|
|
|
|
// values.dates.forEach(function(date){
|
|
|
|
// var dateScale = new Date(date);
|
|
|
|
// var dateScale = new Date(date);
|
|
|
|
// scaleLabels.push(dateToStr(dateScale));
|
|
|
|
// scaleLabels.push(dateToStr(dateScale));
|
|
|
|
// })
|
|
|
|
// })
|
|
|
|
// } else {
|
|
|
|
// } else {
|
|
|
|
// var chartScale = getChartScaleRange();
|
|
|
|
// var chartScale = getChartScaleRange();
|
|
|
|
|
|
|
|
|
|
|
|
// chartScale.forEach(function(date){
|
|
|
|
// chartScale.forEach(function(date){
|
|
|
|
// scaleLabels.push(dateToStr(date));
|
|
|
|
// scaleLabels.push(dateToStr(date));
|
|
|
|
// });
|
|
|
|
// });
|
|
|
|
// }
|
|
|
|
// }
|
|
|
|
values.dates.forEach(function(date){ |
|
|
|
values.dates.forEach(function (date) { |
|
|
|
var dateScale = new Date(date); |
|
|
|
var dateScale = new Date(date); |
|
|
|
scaleLabels.push(dateToStr(dateScale)); |
|
|
|
scaleLabels.push(dateToStr(dateScale)); |
|
|
|
}) |
|
|
|
}) |
|
|
|
var canvas = document.createElement("canvas"); |
|
|
|
var canvas = document.createElement("canvas"); |
|
|
|
container.appendChild(canvas); |
|
|
|
container.appendChild(canvas); |
|
|
|
canvas.style.height = container.offsetHeight + "px"; |
|
|
|
canvas.style.height = container.offsetHeight + "px"; |
|
|
|
canvas.style.width = container.offsetWidth + "px"; |
|
|
|
canvas.style.width = container.offsetWidth + "px"; |
|
|
|
|
|
|
|
|
|
|
|
var ctx = canvas.getContext("2d"); |
|
|
|
var ctx = canvas.getContext("2d"); |
|
|
|
if(myChart){ |
|
|
|
if (myChart) { |
|
|
|
myChart.destroy(); |
|
|
|
myChart.destroy(); |
|
|
|
} |
|
|
|
} |
|
|
|
myChart = new Chart(ctx, { |
|
|
|
myChart = new Chart(ctx, { |
|
|
@ -218,9 +276,9 @@ var lineOverlay = overlayControl.addOverlay(function(container) { |
|
|
|
layout: { |
|
|
|
layout: { |
|
|
|
padding: getScalePaddings(values) |
|
|
|
padding: getScalePaddings(values) |
|
|
|
}, |
|
|
|
}, |
|
|
|
onResize: function(chart, newSize) { |
|
|
|
onResize: function (chart, newSize) { |
|
|
|
var dataRange = gantt.getSubtaskDates(); |
|
|
|
var dataRange = gantt.getSubtaskDates(); |
|
|
|
if(dataRange.start_date){ |
|
|
|
if (dataRange.start_date) { |
|
|
|
// align chart with the scale range
|
|
|
|
// align chart with the scale range
|
|
|
|
chart.options.layout.padding = getScalePaddings(values); |
|
|
|
chart.options.layout.padding = getScalePaddings(values); |
|
|
|
} |
|
|
|
} |
|
|
@ -232,7 +290,7 @@ var lineOverlay = overlayControl.addOverlay(function(container) { |
|
|
|
mode: "index", |
|
|
|
mode: "index", |
|
|
|
intersect: false, |
|
|
|
intersect: false, |
|
|
|
callbacks: { |
|
|
|
callbacks: { |
|
|
|
label: function(tooltipItem, data) { |
|
|
|
label: function (tooltipItem, data) { |
|
|
|
var dataset = data.datasets[tooltipItem.datasetIndex]; |
|
|
|
var dataset = data.datasets[tooltipItem.datasetIndex]; |
|
|
|
return dataset.label + ": " + dataset.data[tooltipItem.index] + "%"; |
|
|
|
return dataset.label + ": " + dataset.data[tooltipItem.index] + "%"; |
|
|
|
} |
|
|
|
} |
|
|
@ -245,28 +303,28 @@ var lineOverlay = overlayControl.addOverlay(function(container) { |
|
|
|
scales: { |
|
|
|
scales: { |
|
|
|
xAxes: [{ |
|
|
|
xAxes: [{ |
|
|
|
labels: scaleLabels, |
|
|
|
labels: scaleLabels, |
|
|
|
gridLines:{ |
|
|
|
gridLines: { |
|
|
|
display: false |
|
|
|
display: false |
|
|
|
}, |
|
|
|
}, |
|
|
|
ticks: { |
|
|
|
ticks: { |
|
|
|
display: false |
|
|
|
display: false |
|
|
|
} |
|
|
|
} |
|
|
|
}, |
|
|
|
}, |
|
|
|
{ |
|
|
|
{ |
|
|
|
position:"top", |
|
|
|
position: "top", |
|
|
|
labels: scaleLabels, |
|
|
|
labels: scaleLabels, |
|
|
|
gridLines:{ |
|
|
|
gridLines: { |
|
|
|
display: false |
|
|
|
display: false |
|
|
|
}, |
|
|
|
}, |
|
|
|
ticks: { |
|
|
|
ticks: { |
|
|
|
display: false |
|
|
|
display: false |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
} |
|
|
|
], |
|
|
|
], |
|
|
|
yAxes: [{ |
|
|
|
yAxes: [{ |
|
|
|
display: true, |
|
|
|
display: true, |
|
|
|
gridLines: { |
|
|
|
gridLines: { |
|
|
|
display:false |
|
|
|
display: false |
|
|
|
}, |
|
|
|
}, |
|
|
|
ticks: { |
|
|
|
ticks: { |
|
|
|
display: true, |
|
|
|
display: true, |
|
|
|