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_id = getUrlParameter("company_id"); const base_url_image = "https://project-api.ospro.id/assets/image/"; 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); });