|
|
|
@ -24,11 +24,10 @@ const axiosInstance = axios.create({
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
axiosInstance.interceptors.request.use(async (config) => { |
|
|
|
|
try{ |
|
|
|
|
try { |
|
|
|
|
$("body").addClass("loading"); |
|
|
|
|
} |
|
|
|
|
catch(e) |
|
|
|
|
{ |
|
|
|
|
catch (e) { |
|
|
|
|
$("body").removeClass("loading"); |
|
|
|
|
alert('Error request' + e); |
|
|
|
|
} |
|
|
|
@ -40,8 +39,7 @@ axiosInstance.interceptors.response.use(async (config) => {
|
|
|
|
|
try { |
|
|
|
|
$("body").removeClass("loading"); |
|
|
|
|
} |
|
|
|
|
catch(e) |
|
|
|
|
{ |
|
|
|
|
catch (e) { |
|
|
|
|
$("body").removeClass("loading"); |
|
|
|
|
alert('Error response' + e); |
|
|
|
|
} |
|
|
|
@ -65,17 +63,17 @@ $.ajaxSetup({
|
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
$(document).on({ |
|
|
|
|
ajaxStart: function(){ |
|
|
|
|
ajaxStart: function () { |
|
|
|
|
$("body").addClass("loading"); |
|
|
|
|
}, |
|
|
|
|
ajaxStop: function(){ |
|
|
|
|
ajaxStop: function () { |
|
|
|
|
$("body").removeClass("loading"); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
gantt.plugins({ |
|
|
|
|
drag_timeline: true, |
|
|
|
|
critical_path: true , |
|
|
|
|
critical_path: true, |
|
|
|
|
auto_scheduling: true |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
@ -84,8 +82,8 @@ 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+"/"; |
|
|
|
|
} else { |
|
|
|
|
base_url = base_url + "/"; |
|
|
|
|
} |
|
|
|
|
// gantt plugins
|
|
|
|
|
gantt.plugins({ |
|
|
|
@ -109,7 +107,7 @@ var colHeader = '<div class="gantt_grid_head_cell"><i style="margin-right:5px;"
|
|
|
|
|
var optionsContent = '<div class="align-left">'; |
|
|
|
|
optionsContent += '<i title="Add Activity" class="fa gantt_button_grid gantt_grid_add fa-plus icon-action f-blue-sky" onclick="clickGridButton(' + task.id + ', \'add\')"></i> '; |
|
|
|
|
optionsContent += '<i title="Delete Activity" class="fa gantt_button_grid gantt_grid_delete fa-times icon-action f-red" onclick="clickGridButton(' + task.id + ', \'delete\')"></i> '; |
|
|
|
|
optionsContent += '<i title="Add Milestone" class="fa gantt_button_grid gantt_grid_add fab fa-jira icon-action f-black" onclick="addMilestone('+task.id+')"></i> '; |
|
|
|
|
optionsContent += '<i title="Add Milestone" class="fa gantt_button_grid gantt_grid_add fab fa-jira icon-action f-black" onclick="addMilestone(' + task.id + ')"></i> '; |
|
|
|
|
optionsContent += !hasChild ? '<i title="Upload Document" class="fa gantt_button_grid gantt_grid_delete fa-file icon-action f-orange" onclick="clickGridButton(' + task.id + ', \'upload\')"></i> ' : ''; |
|
|
|
|
optionsContent += !hasChild ? '<i title="Show Comments" class="fa gantt_button_grid gantt_grid_delete fa-comment icon-action f-black" onclick="clickGridButton(' + task.id + ', \'comment\')"></i> ' : ''; |
|
|
|
|
optionsContent += !hasChild ? '<i title="Activity Location" class="fa fas gantt_button_grid gantt_grid_delete fa-map-marked icon-action f-green" onclick="openActivityMap(' + task.id + ')"></i> ' : ''; |
|
|
|
@ -125,16 +123,16 @@ var formatter = gantt.ext.formatters.durationFormatter({
|
|
|
|
|
format: "auto" |
|
|
|
|
}); |
|
|
|
|
|
|
|
|
|
var progressEditor = {type: "progressCustom", map_to: "progress", min:0, max: 100}; |
|
|
|
|
var costPlanningEditor = {type: "costPlanningEditor", map_to: "rencana_biaya", min:0}; |
|
|
|
|
var progressEditor = { type: "progressCustom", map_to: "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){ |
|
|
|
|
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)){ |
|
|
|
|
if (value) { |
|
|
|
|
for (var i = 0; i < list.length; i++) { |
|
|
|
|
if (list[i].key == parseInt(value)) { |
|
|
|
|
return list[i].label; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
@ -145,28 +143,28 @@ function satuanLabel(task){
|
|
|
|
|
// 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({ |
|
|
|
|
set_value: function(value, id, column, node){ |
|
|
|
|
var correctedValue = gantt.date.add(value, -1, "day"); |
|
|
|
|
return dateEditor.set_value.apply(this, [correctedValue, id, column, node]); |
|
|
|
|
}, |
|
|
|
|
get_value: function(id, column, node) { |
|
|
|
|
var selectedValue = dateEditor.get_value.apply(this, [id, column, node]); |
|
|
|
|
editEndDateTriggered = true; |
|
|
|
|
return gantt.date.add(selectedValue, 1, "day"); |
|
|
|
|
}, |
|
|
|
|
set_value: function (value, id, column, node) { |
|
|
|
|
var correctedValue = gantt.date.add(value, -1, "day"); |
|
|
|
|
return dateEditor.set_value.apply(this, [correctedValue, id, column, node]); |
|
|
|
|
}, |
|
|
|
|
get_value: function (id, column, node) { |
|
|
|
|
var selectedValue = dateEditor.get_value.apply(this, [id, column, node]); |
|
|
|
|
editEndDateTriggered = true; |
|
|
|
|
return gantt.date.add(selectedValue, 1, "day"); |
|
|
|
|
}, |
|
|
|
|
}, 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]); |
|
|
|
|
get_value: function (id, column, node) { |
|
|
|
|
var old_value = gantt.getTask(id); |
|
|
|
|
var modifiedValue = durationEditor.get_value.apply(this, [id, column, node]); |
|
|
|
|
editEndDateTriggered = true; |
|
|
|
|
if(old_value.duration == modifiedValue - 1){ |
|
|
|
|
editDurationTriggered = true; |
|
|
|
|
return modifiedValue; |
|
|
|
|
} |
|
|
|
|
return modifiedValue - 1; |
|
|
|
|
}, |
|
|
|
|
if (old_value.duration == modifiedValue - 1) { |
|
|
|
|
editDurationTriggered = true; |
|
|
|
|
return modifiedValue; |
|
|
|
|
} |
|
|
|
|
return modifiedValue - 1; |
|
|
|
|
}, |
|
|
|
|
}, durationEditor); |
|
|
|
|
|
|
|
|
|
const editor = { |
|
|
|
@ -182,11 +180,11 @@ const editor = {
|
|
|
|
|
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 }, |
|
|
|
|
bobot_planning: { type: "number", map_to: "bobot_planning", min: 0 }, |
|
|
|
|
human_resource: (`<div data-toggle="modal" data-target="#modal-hr">
|
|
|
|
|
|
|
|
|
|
</div>`), |
|
|
|
|
satuan:{type: "select", map_to: "satuan_id", options:gantt.serverList("satuan")} |
|
|
|
|
satuan: { type: "select", map_to: "satuan_id", options: gantt.serverList("satuan") } |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function addWithoutParent() { |
|
|
|
@ -257,11 +255,11 @@ function clickGridButton(id, action) {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
function createColumnsConfig(selectedColumns){ |
|
|
|
|
function createColumnsConfig(selectedColumns) { |
|
|
|
|
var newColumns = []; |
|
|
|
|
|
|
|
|
|
allColumns.forEach(function(column){ |
|
|
|
|
if(selectedColumns[column.name]){ |
|
|
|
|
allColumns.forEach(function (column) { |
|
|
|
|
if (selectedColumns[column.name]) { |
|
|
|
|
newColumns.push(column); |
|
|
|
|
} |
|
|
|
|
}); |
|
|
|
@ -270,159 +268,182 @@ function createColumnsConfig(selectedColumns){
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
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: "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 }, |
|
|
|
|
{ name: "start_date", label: "Start Date", align: "center", min_width: 80, editor: editor.start_date, resize: true }, |
|
|
|
|
{ name: "end_date", label: "Finish Date", align: "center", min_width: 80, editor: editor.end_date, resize: true }, |
|
|
|
|
{ name: "planned_start", label: "Planned Start", align: "center", min_width: 80, editor: editor.planned_start, resize: true, template: function (text) { |
|
|
|
|
if (!text.planned_start) { |
|
|
|
|
return text.start_date; |
|
|
|
|
{ |
|
|
|
|
name: "planned_start", label: "Planned Start", align: "center", min_width: 80, editor: editor.planned_start, resize: true, template: function (text) { |
|
|
|
|
if (!text.planned_start) { |
|
|
|
|
return text.start_date; |
|
|
|
|
} |
|
|
|
|
return text.planned_start; |
|
|
|
|
} |
|
|
|
|
return text.planned_start; |
|
|
|
|
} }, |
|
|
|
|
{ name: "planned_end", label: "Planned End", align: "center", min_width: 80, editor: editor.planned_end, resize: true, template: function (text) { |
|
|
|
|
if (!text.planned_end) { |
|
|
|
|
return text.end_date; |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
name: "planned_end", label: "Planned End", align: "center", min_width: 80, editor: editor.planned_end, resize: true, template: function (text) { |
|
|
|
|
if (!text.planned_end) { |
|
|
|
|
return text.end_date; |
|
|
|
|
} |
|
|
|
|
return text.planned_end; |
|
|
|
|
} |
|
|
|
|
return text.planned_end; |
|
|
|
|
} }, |
|
|
|
|
}, |
|
|
|
|
{ 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; |
|
|
|
|
{ |
|
|
|
|
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) |
|
|
|
|
} |
|
|
|
|
let html = ``; |
|
|
|
|
var assign_hr = text.assign_hr |
|
|
|
|
if(!assign_hr || !assign_hr.length){ |
|
|
|
|
html = `<span class="badge badge-pill badge-danger">Unassigned</span>`; |
|
|
|
|
}else{ |
|
|
|
|
if(assign_hr.length==1){ |
|
|
|
|
html = `<span class="text-capitalize badge badge-pill badge-primary">${assign_hr[0]}</span>`; |
|
|
|
|
}else{ |
|
|
|
|
assign_hr.forEach(function(val, index) { |
|
|
|
|
html += `<span class="text-capitalize badge badge-primary mr-1">${val.substr(0, 1)}</span>`; |
|
|
|
|
}); |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
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) |
|
|
|
|
} |
|
|
|
|
return `<div class="d-flex justify-content-center align-items-center" data-toggle="modal" data-target="#modal-hr" style="min-width:100%;height:100%;">
|
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
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 = `<span class="badge badge-pill badge-danger">Unassigned</span>`; |
|
|
|
|
} else { |
|
|
|
|
if (assign_hr.length == 1) { |
|
|
|
|
html = `<span class="text-capitalize badge badge-pill badge-primary">${assign_hr[0]}</span>`; |
|
|
|
|
} else { |
|
|
|
|
assign_hr.forEach(function (val, index) { |
|
|
|
|
html += `<span class="text-capitalize badge badge-primary mr-1">${val.substr(0, 1)}</span>`; |
|
|
|
|
}); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return `<div class="d-flex justify-content-center align-items-center" data-toggle="modal" data-target="#modal-hr" style="min-width:100%;height:100%;">
|
|
|
|
|
${html} |
|
|
|
|
</div>` |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
{ 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 = `<span class="badge badge-pill badge-danger">No Material</span>`; |
|
|
|
|
}else{ |
|
|
|
|
if(assign_material.length > 0 ){ |
|
|
|
|
html = `<span class="text-capitalize badge badge-pill badge-primary">See Material</span>`; |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return `<div class="d-flex justify-content-center align-items-center" data-toggle="modal" data-target="#modal-material" style="min-width:100%;height:100%;">
|
|
|
|
|
let html = ``; |
|
|
|
|
var assign_material = text.assign_material |
|
|
|
|
|
|
|
|
|
if (!assign_material || !assign_material.length) { |
|
|
|
|
html = `<span class="badge badge-pill badge-danger">No Material</span>`; |
|
|
|
|
} else { |
|
|
|
|
if (assign_material.length > 0) { |
|
|
|
|
html = `<span class="text-capitalize badge badge-pill badge-primary">See Material</span>`; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return `<div class="d-flex justify-content-center align-items-center" data-toggle="modal" data-target="#modal-material" style="min-width:100%;height:100%;">
|
|
|
|
|
${html} |
|
|
|
|
</div>` |
|
|
|
|
} }, |
|
|
|
|
{ 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 = `<span class="badge badge-pill badge-danger">No Overhead</span>`; |
|
|
|
|
}else{ |
|
|
|
|
if(assign_expense.length > 0 ){ |
|
|
|
|
html = `<span class="text-capitalize badge badge-pill badge-primary">See Overhead</span>`; |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return `<div class="d-flex justify-content-center align-items-center" data-toggle="modal" data-target="#modal-expense" style="min-width:100%;height:100%;">
|
|
|
|
|
let html = ``; |
|
|
|
|
var assign_expense = text.assign_expense |
|
|
|
|
|
|
|
|
|
if (!assign_expense || !assign_expense.length) { |
|
|
|
|
html = `<span class="badge badge-pill badge-danger">No Overhead</span>`; |
|
|
|
|
} else { |
|
|
|
|
if (assign_expense.length > 0) { |
|
|
|
|
html = `<span class="text-capitalize badge badge-pill badge-primary">See Overhead</span>`; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return `<div class="d-flex justify-content-center align-items-center" data-toggle="modal" data-target="#modal-expense" style="min-width:100%;height:100%;">
|
|
|
|
|
${html} |
|
|
|
|
</div>` |
|
|
|
|
} }, |
|
|
|
|
{ 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 = `<span class="badge badge-pill badge-danger">Unassigned</span>`;
|
|
|
|
|
}else{ |
|
|
|
|
if(assign_tools.length > 0 ){ |
|
|
|
|
html = `<span class="text-capitalize badge badge-pill badge-primary">Assigned</span>`; |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
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; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return `<div class="d-flex justify-content-center align-items-center" data-toggle="modal" data-target="#modal-tools" style="min-width:100%;height:100%;">
|
|
|
|
|
let html = ``; |
|
|
|
|
var assign_tools = text.assign_tools |
|
|
|
|
|
|
|
|
|
if (!assign_tools || !assign_tools.length) { |
|
|
|
|
// html = `<span class="badge badge-pill badge-danger">Unassigned</span>`;
|
|
|
|
|
} else { |
|
|
|
|
if (assign_tools.length > 0) { |
|
|
|
|
html = `<span class="text-capitalize badge badge-pill badge-primary">Assigned</span>`; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return `<div class="d-flex justify-content-center align-items-center" data-toggle="modal" data-target="#modal-tools" style="min-width:100%;height:100%;">
|
|
|
|
|
${html} |
|
|
|
|
</div>` |
|
|
|
|
} }, |
|
|
|
|
// { name: "status", label: "Status", align: "center", editor: editor.status, resize: true },
|
|
|
|
|
{ name: "bobot_planning", label: "Bobot Activity (%)", 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: "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:"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("Bobot 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; |
|
|
|
|
}, |
|
|
|
|
// { name: "status", label: "Status", align: "center", editor: editor.status, resize: true },
|
|
|
|
|
{ |
|
|
|
|
name: "bobot_planning", label: "Bobot Activity (%)", 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: "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: "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("Bobot 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 = `<span class="badge badge-pill badge-danger">No Report</span>`; |
|
|
|
|
}else{ |
|
|
|
|
html = `<span class="text-capitalize badge badge-pill badge-primary">See Report</span>`; |
|
|
|
|
} |
|
|
|
|
return `<div class="d-flex justify-content-center align-items-center" data-toggle="modal" data-target="#modal_report_activity" style="min-width:100%;height:100%;">
|
|
|
|
|
if (text.jobs_done == 0) { |
|
|
|
|
html = `<span class="badge badge-pill badge-danger">No Report</span>`; |
|
|
|
|
} else { |
|
|
|
|
html = `<span class="text-capitalize badge badge-pill badge-primary">See Report</span>`; |
|
|
|
|
} |
|
|
|
|
return `<div class="d-flex justify-content-center align-items-center" data-toggle="modal" data-target="#modal_report_activity" style="min-width:100%;height:100%;">
|
|
|
|
|
${html} |
|
|
|
|
</div>` |
|
|
|
|
} }, |
|
|
|
|
{ name: "satuan", label: "UOM", align: "center", min_width: 100, resize: true, editor:editor.satuan, template: satuanLabel }, |
|
|
|
|
} |
|
|
|
|
}, |
|
|
|
|
{ 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 |
|
|
|
@ -462,12 +483,12 @@ gantt.config.columns = createColumnsConfig({
|
|
|
|
|
assign_hr: true, |
|
|
|
|
material: true, |
|
|
|
|
tools: true, |
|
|
|
|
expenses: true, |
|
|
|
|
expenses: true, |
|
|
|
|
bobot_planning: true, |
|
|
|
|
progress: true, |
|
|
|
|
progress_actual: true, |
|
|
|
|
jumlah_pekerjaan: true, |
|
|
|
|
jobs_done:true, |
|
|
|
|
jobs_done: true, |
|
|
|
|
satuan: true, |
|
|
|
|
predecessor: true, |
|
|
|
|
updated_by: true |
|
|
|
@ -495,14 +516,14 @@ gantt.addTaskLayer({
|
|
|
|
|
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.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){ |
|
|
|
|
getRectangle: function (task, view) { |
|
|
|
|
if (task.planned_start && task.planned_end) { |
|
|
|
|
return gantt.getTaskPosition(task, task.planned_start, task.planned_end); |
|
|
|
|
} |
|
|
|
@ -521,41 +542,41 @@ gantt.templates.task_class = function (start, end, task) {
|
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
gantt.templates.task_end_date = function(date){ |
|
|
|
|
return gantt.templates.task_date(new Date(date.valueOf() - 1)); |
|
|
|
|
gantt.templates.task_end_date = function (date) { |
|
|
|
|
return gantt.templates.task_date(new Date(date.valueOf() - 1)); |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
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{ |
|
|
|
|
return gridDateToStr(date);
|
|
|
|
|
} |
|
|
|
|
gantt.templates.grid_date_format = function (date, column) { |
|
|
|
|
if (column === "end_date") { |
|
|
|
|
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 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 = "<b>Overdue: " + overdue + " days</b>"; |
|
|
|
|
return text; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
gantt.attachEvent("onTaskLoading", function(task){ |
|
|
|
|
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; |
|
|
|
@ -578,7 +599,7 @@ gantt.config.layout = {
|
|
|
|
|
{ resizer: true, width: 3 }, |
|
|
|
|
{ |
|
|
|
|
rows: [ |
|
|
|
|
{ view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer", scrollable: true}, |
|
|
|
|
{ view: "timeline", scrollX: "scrollHor", scrollY: "scrollVer", scrollable: true }, |
|
|
|
|
{ view: "scrollbar", id: "scrollHor", group: "horizontal" } |
|
|
|
|
] |
|
|
|
|
}, |
|
|
|
@ -609,25 +630,27 @@ gantt.templates.timeline_cell_class = function (task, date) {
|
|
|
|
|
var zoomConfig = { |
|
|
|
|
levels: [ |
|
|
|
|
{ |
|
|
|
|
name:"day", |
|
|
|
|
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"} |
|
|
|
|
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", |
|
|
|
|
name: "week", |
|
|
|
|
scale_height: 50, |
|
|
|
|
min_column_width:50, |
|
|
|
|
scales:[ |
|
|
|
|
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");
|
|
|
|
@ -635,20 +658,22 @@ var zoomConfig = {
|
|
|
|
|
// 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: "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", |
|
|
|
|
name: "month", |
|
|
|
|
scale_height: 50, |
|
|
|
|
min_column_width:120, |
|
|
|
|
scales:[ |
|
|
|
|
{unit: "month", format: "%F, %Y"}, |
|
|
|
|
min_column_width: 120, |
|
|
|
|
scales: [ |
|
|
|
|
{ unit: "month", format: "%F, %Y" }, |
|
|
|
|
// {unit: "week", format: "Week #%W"},
|
|
|
|
|
// {unit: "day", step: 1, format: "%j %D"}
|
|
|
|
|
] |
|
|
|
@ -682,21 +707,21 @@ 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; |
|
|
|
|
gantt.ext.zoom.attachEvent("onAfterZoom", function (level, config) { |
|
|
|
|
document.querySelector(".gantt_radio[value='" + config.name + "']").checked = true; |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
function zoomIn(){ |
|
|
|
|
function zoomIn() { |
|
|
|
|
gantt.ext.zoom.zoomIn(); |
|
|
|
|
} |
|
|
|
|
function zoomOut(){ |
|
|
|
|
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}); |
|
|
|
|
updateProperty({ zoom: event.target.value }); |
|
|
|
|
gantt.ext.zoom.setLevel(event.target.value); |
|
|
|
|
}; |
|
|
|
|
} |
|
|
|
@ -704,15 +729,19 @@ for (var i = 0; i < radios.length; i++) {
|
|
|
|
|
|
|
|
|
|
// 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" |
|
|
|
|
} |
|
|
|
|
}} |
|
|
|
|
{ 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; |
|
|
|
|