const ganttId = getUrlParameter("gantt_id");
const readOnly = getUrlParameter("ro");
const proyekId = getUrlParameter("proyek_id");
const timestamp = getUrlParameter("timestamp");
let base_url = getUrlParameter("base_url");
const role_name = getUrlParameter("role_name");
const company_name = getUrlParameter("company_name");
const base_url_image = `https://project-api.ospro.id/assets/${company_name}/`;
const ganttName = getUrlParameter("gantt_name");
// const base_url_image = `http://localhost:8444/generic-ospro-backend/assets/${company_name}/`;
const adwIntegrationUrl = "https://adw-api.ospro.id/api";
let userToVersionGanttId = 0
let activityId = 0;
let actionHappen = false;
let activityName = "";
let activityEarlyStart;
let activityEarlyFinish;
let token = getUrlParameter("token");
let forceDurationUpdateTriggered = false;
let editEndDateDurationTriggered = false;
if (!token || token == "") {
token = `eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJodHRwczpcL1wvYXBpLWl1Lm9zcHJvLmlkXC9hcGlcL2xvZ2luIiwiaWF0IjoxNjQ2ODA3OTA4LCJleHAiOjE2NDY4OTQzMDgsIm5iZiI6MTY0NjgwNzkwOCwianRpIjoiNmdtcEx3cjlob1JFZ0hSNSIsInN1YiI6MSwicHJ2IjoiMjNiZDVjODk0OWY2MDBhZGIzOWU3MDFjNDAwODcyZGI3YTU5NzZmNyJ9.1xB2rvTJ6Edf7l_8jRPOmoMYnf8f59Rd8jJghJ39xps`;
}
const axiosInstance = axios.create({
headers: {
"Authorization": `Bearer ${token}`,
"Content-type": "application/json"
}
});
const axiosInstanceMultipart = axios.create({
headers: {
"Content-Type": "multipart/form-data",
"Authorization": `Bearer ${token}`,
}
});
axiosInstance.interceptors.request.use(async (config) => {
try {
$("body").addClass("loading");
}
catch (e) {
$("body").removeClass("loading");
alert('Error request' + e);
}
return config;
});
axiosInstance.interceptors.response.use(async (config) => {
try {
$("body").removeClass("loading");
}
catch (e) {
$("body").removeClass("loading");
alert('Error response' + e);
}
return config;
});
const HEADER = {
headers:
{
'Authorization': `Bearer ${token}`,
"Content-type": `application/json`
}
};
$.ajaxSetup({
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${token}`
}
});
$(document).on({
ajaxStart: function () {
$("body").addClass("loading");
},
ajaxStop: function () {
$("body").removeClass("loading");
}
});
gantt.plugins({
drag_timeline: true,
critical_path: true,
auto_scheduling: true
});
gantt.config.date_format = "%Y-%m-%d %H:%i:%s";
gantt.config.auto_scheduling = true;
gantt.config.fit_tasks = true;
if (!base_url) {
base_url = `https://api-iu.ospro.id/api/`;
} else {
base_url = base_url + "/";
}
// gantt plugins
gantt.plugins({
marker: true,
fullscreen: true
});
// add today line
var dateToStr = gantt.date.date_to_str(gantt.config.task_date);
var markerId = gantt.addMarker({
start_date: new Date(),
css: "today",
text: "Today",
title: dateToStr(new Date())
});
gantt.getMarker(markerId); //->{css:"today", text:"Now", id:...}
var colHeader = '
',
colContent = function (task) {
var hasChild = gantt.hasChild(task.id);
var optionsContent = '';
optionsContent += ' ';
optionsContent += ' ';
optionsContent += ' ';
optionsContent += ' ';
optionsContent += !hasChild ? ' ' : '';
optionsContent += !hasChild ? ' ' : '';
optionsContent += !hasChild ? ' ' : '';
optionsContent += '
';
return (optionsContent);
};
let no = 4; // for temporary change with last id in database m_activity
var formatter = gantt.ext.formatters.durationFormatter({
enter: "day",
store: "day",
format: "auto"
});
var progressEditor = { type: "progressCustom", map_to: "progress", min: 0, max: 100 };
var baselineProgressEditor = { type: "baselineProgressCustom", map_to: "baseline_progress", min: 0, max: 100 };
var costPlanningEditor = { type: "costPlanningEditor", map_to: "rencana_biaya", min: 0 };
var linksFormatter = gantt.ext.formatters.linkFormatter({ durationFormatter: formatter });
function satuanLabel(task) {
var value = task.satuan_id;
var list = gantt.serverList("satuan");
if (value) {
for (var i = 0; i < list.length; i++) {
if (list[i].key == parseInt(value)) {
return list[i].label;
}
}
}
return "";
}
// use the default editor custom for end_date, but override set_value/get_value methods
var dateEditor = gantt.config.editor_types.date;
gantt.config.editor_types.end_date = gantt.mixin({
get_value: function (id, column, node) {
var selectedValue = dateEditor.get_value.apply(this, [id, column, node]);
editEndDateDurationTriggered = true;
return selectedValue;
},
}, dateEditor);
var durationEditor = gantt.config.editor_types.duration;
gantt.config.editor_types.duration = gantt.mixin({
get_value: function (id, column, node) {
var old_value = gantt.getTask(id);
var modifiedValue = durationEditor.get_value.apply(this, [id, column, node]);
editEndDateDurationTriggered = true;
if (old_value.duration == modifiedValue - 1) {
forceDurationUpdateTriggered = true;
return modifiedValue;
}
return modifiedValue - 1;
},
}, durationEditor);
const editor = {
text: { type: "text", map_to: "text" },
kode_sortname: { type: "text", map_to: "kode_sortname" },
start_date: { type: "date", map_to: "start_date", min: new Date(2018, 0, 1) },
end_date: { type: "end_date", map_to: "end_date", min: new Date(2018, 0, 1) },
planned_start: { type: "date", map_to: "planned_start", min: new Date(2018, 0, 1) },
planned_end: { type: "end_date", map_to: "planned_end", min: new Date(2018, 0, 1) },
planned_duration: { type: "duration", map_to: "planned_duration", min: 0, max: 365, formatter: formatter },
// early_start: { type: "date", map_to: "planned_start", min: new Date(2018, 0, 1) },
// early_end: { type: "end_date", map_to: "planned_start", min: new Date(2018, 0, 1) },
duration: { type: "duration", map_to: "duration", min: 0, max: 365, formatter: formatter },
cost: { type: "number", map_to: "rencana_biaya", min: 0 },
costActual: { type: "number", map_to: "biaya_actual", min: 0 },
status: { type: "text", map_to: "status" },
// job_count: { type: "number", map_to: "jumlah_pekerjaan", min: 0 },
job_unit: { type: "text", map_to: "satuan", min: 0 },
bobot_planning: { type: "number", map_to: "bobot_planning", min: 0 },
human_resource: (`
`),
satuan: { type: "select", map_to: "satuan_id", options: gantt.serverList("satuan") }
}
function addWithoutParent() {
var task = gantt.getTaskByIndex(0);
let start_date = new Date();
if (task) {
start_date = task.start_date;
}
var taskId = gantt.addTask({
id: no,
text: `New Activity`,
start_date: start_date,
biaya: 10000,
duration: 1
});
gantt.selectTask(taskId);
no = no + 1;
}
function addWithParent(id) {
var task = gantt.getTask(id);
let start_date = new Date();
if (task) {
start_date = task.start_date;
}
gantt.addTask({
id: no,
text: `New Activity`,
start_date: start_date,
duration: 0
}, id);
no = no + 1;
}
function clickGridButton(id, name, action) {
switch (action) {
case "edit":
gantt.showLightbox(id);
break;
case "add":
addWithParent(id);
break;
case "delete":
gantt.confirm({
title: gantt.locale.labels.confirm_deleting_title,
text: gantt.locale.labels.confirm_deleting,
callback: function (res) {
if (res)
gantt.deleteTask(id);
}
});
break;
case "set-baseline-activity":
setBaselineActivity(id, name);
break;
case "upload":
showDocuments(id);
break;
case "comment":
showComments(id);
break;
}
}
function createColumnsConfig(selectedColumns) {
var newColumns = [];
allColumns.forEach(function (column) {
if (selectedColumns[column.name]) {
newColumns.push(column);
}
});
return newColumns;
}
var allColumns = [
{ name: "action", label: colHeader, align: "left", min_width: 115, template: colContent, resize: true },
{ name: "kode_sortname", label: "Kode / Sortname", align: "center", min_width: 120, editor: editor.kode_sortname, resize: true },
{
name: "text",
label: "Activity",
tree: true,
min_width: 150,
editor: editor.text,
resize: true,
template: function (text) {
function truncateText(text, maxLength) {
if (text.length > maxLength) {
return text.substring(0, maxLength) + '...';
}
return text;
}
const truncatedText = truncateText(text.text, 30);
return `${truncatedText}`;
}
},
{
name: "planned_start", label: "Baseline Start", align: "center", min_width: 80, editor: editor.planned_start, resize: true, template: function (text) {
if (!text.planned_start) {
return moment(text.start_date).format("DD-MM-YYYY");
}
return moment(text.planned_start).format("DD-MM-YYYY");
}
},
{
name: "planned_end", label: "Baseline Finish", align: "center", min_width: 80, editor: editor.planned_end, resize: true, template: function (text) {
if (!text.planned_end) {
return moment(text.end_date).format("DD-MM-YYYY");
}
return moment(text.planned_end).format("DD-MM-YYYY");
}
},
{
name: "start_date", label: "Early Start", align: "center", min_width: 80, editor: editor.start_date, resize: true, template: function (text) {
return moment(text.start_date).format("DD-MM-YYYY");
}
},
{
name: "end_date", label: "Early Finish", align: "center", min_width: 80, editor: editor.end_date, resize: true, template: function (text) {
return moment(text.end_date).format("DD-MM-YYYY");
}
},
{
name: "actual_start", label: "Actual Start", align: "center", min_width: 80, resize: true, template: function (text) {
if (!text.actual_start) {
return '';
}
return moment(text.actual_start).format("DD-MM-YYYY");
}
},
{
name: "actual_end", label: "Actual Finish", align: "center", min_width: 80, resize: true, template: function (text) {
if (!text.actual_end) {
return '';
}
return moment(text.actual_end).format("DD-MM-YYYY");
}
},
{
name: "bobot_planning", label: "Bobot (%)", align: "center", editor: editor.bobot_planning, resize: true, min_width: 115, template: function (text) {
let bobot = parseFloat(text.bobot_planning);
if (bobot.toFixed(2) > 100) {
gantt.alert("Bobot tidak boleh lebih dari 100%!");
return;
}
if (!text.bobot_planning) {
return
}
let bobot_planning = parseFloat(text.bobot_planning);
return roundToTwo(bobot_planning);
}
},
{
name: "baseline_progress", label: "Baseline Progress (%)", align: "center", editor: baselineProgressEditor, min_width: 125, template: function (text) {
let today = new Date();
let start = text.planned_start ? new Date(text.planned_start) : new Date(text.start_date);
let end = text.planned_end ? new Date(text.planned_end) : new Date(text.end_date);
let todayDuration = gantt.calculateDuration({
start_date: start,
end_date: today
})
let endDuration = gantt.calculateDuration({
start_date: start,
end_date: end
})
if (todayDuration < 0) {
todayDuration = 0;
}
progress = todayDuration / endDuration * 100
if (todayDuration > endDuration) {
progress = 100;
}
return roundToTwo(progress);
}, resize: true
},
{
name: "progress", label: "Actual Progress (%)", align: "center", editor: progressEditor, min_width: 125, template: function (text) {
let progress = text.progress
progress = progress * 100
return roundToTwo(progress);
}, resize: true
},
{
name: "planned_duration", label: "Baseline Duration (Day)", align: "center", min_width: 50, resize: true, editor: editor.duration, template: function (text) {
let start;
let end;
text.planned_start ? start = text.planned_start : start = text.start_date;
text.planned_end ? end = text.planned_end : end = text.end_date;
let plannedDuration = gantt.calculateDuration({
start_date: new Date(start),
end_date: new Date(end)
})
return plannedDuration;
}
},
{ name: "duration", label: "Duration (Day)", align: "center", min_width: 50, resize: true, editor: editor.duration },
{
name: "rencana_biaya", label: "Cost Planning", align: "right", min_width: 100, resize: true, template: function (text) {
if (!text.rencana_biaya) {
return
}
let rencana_biaya = roundToTwo(text.rencana_biaya)
return "Rp. " + formatRupiah(rencana_biaya)
}
},
{
name: "cost_actual", label: "Cost Actual", align: "right", min_width: 100, resize: true, template: function (text) {
if (!text.biaya_actual) {
return
}
let biaya_actual = roundToTwo(text.biaya_actual)
return "Rp. " + formatRupiah(biaya_actual)
}
},
{
name: "assign_hr", label: "Assign To", align: "center", min_width: 150, resize: true, template: function (text) {
if (text.type == "project" || text.type == "milestone" || text.type == "header") {
return;
}
let html = ``;
var assign_hr = text.assign_hr
if (!assign_hr || !assign_hr.length) {
html = `Unassigned`;
} else {
if (assign_hr.length == 1) {
html = `${assign_hr[0]}`;
} else {
assign_hr.forEach(function (val, index) {
html += `${val.substr(0, 1)}`;
});
}
}
return `
${html}
`
}
},
{
name: "material", label: "Material", align: "center", min_width: 150, resize: true, template: function (text) {
if (text.type == "project" || text.type == "milestone" || text.type == "header") {
return;
}
let html = ``;
var assign_material = text.assign_material
if (!assign_material || !assign_material.length) {
html = `No Material`;
} else {
if (assign_material.length > 0) {
html = `See Material`;
}
}
return `
${html}
`
}
},
{
name: "expenses", label: "Overhead", align: "center", min_width: 150, resize: true, template: function (text) {
if (text.type == "project" || text.type == "milestone" || text.type == "header") {
return;
}
let html = ``;
var assign_expense = text.assign_expense
if (!assign_expense || !assign_expense.length) {
html = `No Overhead`;
} else {
if (assign_expense.length > 0) {
html = `See Overhead`;
}
}
return `
${html}
`
}
},
{
name: "tools", label: "Tools", align: "center", min_width: 150, resize: true, template: function (text) {
if (text.type == "project" || text.type == "milestone" || text.type == "header") {
return;
}
let html = ``;
var assign_tools = text.assign_tools
if (!assign_tools || !assign_tools.length) {
// html = `Unassigned`;
} else {
if (assign_tools.length > 0) {
html = `Assigned`;
}
}
return `
${html}
`
}
},
// { name: "status", label: "Status", align: "center", editor: editor.status, resize: true },
{
name: "progress_actual", label: "Total Actual Progress (%)", align: "center", min_width: 150, template: function (text) {
let progress = text.progress
progress = progress * 100
if (progress.toFixed(2) > 100) {
gantt.alert("Progress tidak boleh lebih dari 100%!");
return;
}
let bobot = text.bobot_planning
let actual = (progress * bobot) / 100
return roundToTwo(actual);
}, resize: true
},
// { name: "jumlah_pekerjaan", label: "Volume Plan", align: "center", min_width: 100, resize: true, editor: editor.job_count },
{
name: "jobs_done", label: "Report", align: "center", min_width: 100, resize: true, template: function (text) {
if (text.type == "project" || text.type == "milestone" || text.type == "header") {
return;
}
if (text.jobs_done == 0) {
html = `No Report`;
} else {
html = `See Report`;
}
return `
${html}
`
}
},
{ name: "satuan", label: "UOM", align: "center", min_width: 100, resize: true, editor: editor.satuan, template: satuanLabel },
{
name: "predecessor", label: "Predecessor", align: "center", min_width: 100, template: function (text) {
let links = text.$target
let dataRes = ``;
let no = 0;
if (links.length > 0) {
links.map((val, index) => {
if (no > 0) {
dataRes += `, `;
}
let link = gantt.getLink(val);
let type = getCodeLinkByType(link.type);
let source = link.source;
var wbs_code = gantt.getWBSCode(gantt.getTask(source));
dataRes += wbs_code + type;
no = no + 1;
});
}
return dataRes;
}, resize: true
},
{ name: "updated_by", label: "Last Updated By", align: "center", min_width: 100, resize: true }
];
// set default to show (true) , hide (false)
let columnShows = {
action: true,
kode_sortname: false,
text: true,
start_date: true,
end_date: true,
planned_start: false,
planned_end: false,
planned_duration: false,
actual_start: false,
actual_end: false,
duration: true,
rencana_biaya: true,
cost_actual: true,
assign_hr: true,
material: false,
tools: true,
expenses: true,
bobot_planning: true,
baseline_progress: false,
progress: true,
progress_actual: true,
// jumlah_pekerjaan: true,
jobs_done: true,
satuan: false,
predecessor: false,
updated_by: false
}
gantt.config.columns = createColumnsConfig({
action: true,
kode_sortname: true,
text: true,
start_date: true,
end_date: true,
planned_start: true,
planned_end: true,
planned_duration: true,
actual_start: true,
actual_end: true,
duration: true,
rencana_biaya: true,
cost_actual: true,
assign_hr: true,
material: true,
tools: true,
expenses: true,
bobot_planning: true,
baseline_progress: true,
progress: true,
progress_actual: true,
// jumlah_pekerjaan: true,
jobs_done: true,
satuan: true,
predecessor: true,
updated_by: true
});
gantt.config.reorder_grid_columns = true;
gantt.config.resize_rows = true;
gantt.config.grid_resize = true;
gantt.config.min_column_width = 50;
gantt.config.scale_height = 20;
gantt.config.order_branch = "marker";
gantt.config.order_branch = true;
gantt.config.order_branch_free = true;
gantt.config.open_tree_initially = true;
gantt.config.row_height = 30;
gantt.config.task_height = 20;
// adding baseline display
gantt.addTaskLayer({
renderer: {
render: function draw_planned(task) {
if (task.planned_start && task.planned_end) {
var sizes = gantt.getTaskPosition(task, task.planned_start, task.planned_end);
var el = document.createElement('div');
el.className = 'baseline';
el.style.left = sizes.left - 6 + 'px';
el.style.width = sizes.width + 10 + 'px';
el.style.height = sizes.height + 'px';
el.style.top = sizes.top + 2 + 'px';
return el;
}
return false;
},
getRectangle: function (task, view) {
if (task.planned_start && task.planned_end) {
return gantt.getTaskPosition(task, task.planned_start, task.planned_end);
}
return null;
}
}
});
gantt.templates.task_class = function (start, end, task) {
if (task.planned_end) {
var classes = ['has-baseline'];
if (end.getTime() > task.planned_end.getTime()) {
classes.push('overdue');
}
return classes.join(' ');
}
};
var gridDateToStr = gantt.date.date_to_str("%Y-%m-%d");
gantt.templates.grid_date_format = function (date, column) {
if (column === "end_date") {
return gridDateToStr(new Date(date.valueOf() - 1));
} else if (column === "planned_end") {
return gridDateToStr(new Date(date.valueOf() - 1));
} else {
return gridDateToStr(date);
}
}
gantt.templates.rightside_text = function (start, end, task) {
if (task.planned_end) {
if (end.getTime() > task.planned_end.getTime()) {
var plannedEndDate = gantt.calculateEndDate({
start_date: task.start_date,
duration: gantt.calculateDuration({
start_date: task.start_date,
end_date: task.planned_end
})
});
var overdue = gantt.calculateDuration({
start_date: plannedEndDate,
end_date: end,
task: task
}, 'day');
var text = "Overdue: " + overdue + " days";
return text;
}
}
};
gantt.attachEvent("onTaskLoading", function (task) {
task.planned_start = gantt.date.parseDate(task.planned_start, "xml_date");
task.planned_end = gantt.date.parseDate(task.planned_end, "xml_date");
return true;
});
gantt.config.autoscroll = true;
gantt.config.scroll_size = 30;
gantt.config.layout = {
css: "gantt_container",
cols: [
{
width: 400,
min_width: 300,
rows: [
{ view: "grid", scrollX: "gridScroll", scrollable: true, scrollY: "scrollVer" },
{ view: "scrollbar", id: "gridScroll", group: "horizontal" }
]
},
{ resizer: true, width: 3 },
{
rows: [
{ view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer", scrollable: true },
{ view: "scrollbar", id: "scrollHor", group: "horizontal" }
]
},
{ view: "scrollbar", id: "scrollVer" }
]
};
gantt.templates.grid_folder = function (item) {
return "";
};
gantt.templates.grid_file = function (item) {
return "";
};
// Set workdays
gantt.config.work_time = true;
gantt.config.duration_unit = "day";
gantt.templates.timeline_cell_class = function (task, date) {
if (!gantt.isWorkTime(date, 'day')) {
return ("holidays");
}
return "";
};
// Zoom Scales
var zoomConfig = {
levels: [
{
name: "day",
scale_height: 50,
min_column_width: 50,
scales: [
{
unit: "week", step: 1, format: function (date) {
var dateToStr = gantt.date.date_to_str("%d %M");
var endDate = gantt.date.add(date, -6, "day");
var weekNum = gantt.date.date_to_str("%W")(date);
var year = gantt.date.date_to_str("%Y")(date);
return "W#" + weekNum + ", " + dateToStr(date) + " - " + dateToStr(endDate) + " " + year;
}
},
{ unit: "day", step: 1, format: "%d %M" }
]
},
{
name: "week",
scale_height: 50,
min_column_width: 50,
scales: [
// {unit: "week", step: 1, format: function (date) {
// var dateToStr = gantt.date.date_to_str("%d %M");
// var endDate = gantt.date.add(date, -6, "day");
// var weekNum = gantt.date.date_to_str("%W")(date);
// var year = gantt.date.date_to_str("%Y")(date);
// return "#" + weekNum + ", " + dateToStr(date) + " - " + dateToStr(endDate) + " " + year;
// }},
{
unit: "week", step: 1, format: function (date) {
var weekNum = gantt.date.date_to_str("%W")(date);
return "W#" + weekNum;
}
},
{ unit: "month", format: "%F, %Y" },
// {unit: "day", step: 1, format: "%j %D"}
]
},
{
name: "month",
scale_height: 50,
min_column_width: 120,
scales: [
{ unit: "month", format: "%F, %Y" },
// {unit: "week", format: "Week #%W"},
// {unit: "day", step: 1, format: "%j %D"}
]
},
// {
// name:"quarter",
// height: 50,
// min_column_width:90,
// scales:[
// {unit: "month", step: 1, format: "%M"},
// {
// unit: "quarter", step: 1, format: function (date) {
// var dateToStr = gantt.date.date_to_str("%M");
// var endDate = gantt.date.add(gantt.date.add(date, 3, "month"), -1, "day");
// return dateToStr(date) + " - " + dateToStr(endDate);
// }
// }
// ]
// },
// {
// name:"year",
// scale_height: 50,
// min_column_width: 30,
// scales:[
// {unit: "year", step: 1, format: "%Y"}
// ]
// }
]
};
gantt.ext.zoom.init(zoomConfig);
gantt.ext.zoom.setLevel("month");
// trigger when zoomIn and zoomOut clicked
gantt.ext.zoom.attachEvent("onAfterZoom", function (level, config) {
document.querySelector(".gantt_radio[value='" + config.name + "']").checked = true;
})
function zoomIn() {
gantt.ext.zoom.zoomIn();
}
function zoomOut() {
gantt.ext.zoom.zoomOut()
}
var radios = document.getElementsByName("scale");
for (var i = 0; i < radios.length; i++) {
radios[i].onclick = function (event) {
updateProperty({ zoom: event.target.value });
gantt.ext.zoom.setLevel(event.target.value);
};
}
// end Zoom Scale function
// GANTT PERFORMANCE CONFIG RECOMMENDATION
gantt.config.scales = [
{ unit: "month", step: 1, format: "%F, %Y" },
{
unit: "week", step: 1, format: function (date) {
return "Week #" + gantt.date.getWeek(date);
}
},
{
unit: "day", step: 1, format: "%D", css: function (date) {
if (!gantt.isWorkTime({ date: date, unit: "day" })) {
return "weekend"
}
}
}
];
gantt.config.show_task_cells = false;
gantt.config.static_background = true;
gantt.config.branch_loading = true;
gantt.config.smart_scales = true;
gantt.config.smart_rendering = true;
// drag process
gantt.config.drag_progress = false;
gantt.config.sort = true;
// gantt initialization
$(document).ready(function () {
initializationProject();
getSatuan();
gantt.init("gantt_here");
linkLagEditor();
setTimeout(initializationColumn, 4500);
setTimeout(initialProperty, 4500);
});