$(function() { if(ganttPlans) { $('#ganttPlans .gantt-plan, #ganttContainer .gantt-row').remove(); initWaterfallGanttBlock(); } $('#ganttContainer').off('scroll').on('scroll', function(e) { $('#ganttPlans')[0].scrollTop = e.target.scrollTop; }); }); window.initWaterfallGanttBlock = function() { var ganttData = ganttPlans; if(!ganttData) return; var plans = []; var tasks = []; var plansMap = {}; var startDatetime = Number.MAX_SAFE_INTEGER; var endDatetime = 0; var minTimeGap = Number.MAX_SAFE_INTEGER; var $gantt = $('#' + waterfallGanttID); var ONE_DAY = 24 * 3600 * 1000; var TIME_GAP_STEP = 7; var MIN_COL_WIDTH = 60; $.each(ganttData, function(index, item) { plansMap[item.id] = item; if(item.type == 'plan' && item.parent == '0') { item.startDatetime = createDatetime(item.start_date); item.endDatetime = createDatetime(item.deadline); startDatetime = Math.min(startDatetime, item.startDatetime); endDatetime = Math.max(endDatetime, item.endDatetime); minTimeGap = Math.min(minTimeGap, endDatetime - startDatetime); item.tasks = []; item.completeTasks = []; item.progress = Number.parseFloat(item.taskProgress.replace('%', ''), 10); plans.push(item); } else if(item.type === 'task') { item.progress = Number.parseFloat(item.taskProgress.replace('%', ''), 10); tasks.push(item); } }); $.each(tasks, function(index, task) { var plan = plansMap[task.parent]; if(typeof(plan) == 'undefined') return; while(plan.parent > 0) { plan = plansMap[plan.parent]; if(typeof(plan) != 'object') return; } if(task.progress === 100) plan.completeTasks.push(task); plan.tasks.push(task); }); var $plans = $gantt.find('.gantt-plans'); var $ganttContainer = $gantt.find('.gantt-container'); var $ganttCanvas = $gantt.find('.gantt-canvas'); var themeColor = 'rgb(46, 127, 255)'; var canvasHeight = plans.length * 50 + 10; var days = Math.ceil((endDatetime - startDatetime) / ONE_DAY); minTimeGap = Math.max(1, Math.ceil(minTimeGap / ONE_DAY)); /* Update gantt plans and bars */ $.each(plans, function(index, plan) { var $plan = $('
'); $plan.append('
' + plan.name + '
' + (plan.milestonecode == '1' ? '' : '') + '
'); $plans.append($plan); var $bar = $('
'); $('
').css( { width: plan.progress + '%', background: themeColor, }).appendTo($bar); $bar.append('
' + progressLang + ' ' + plan.taskProgress + '
').attr('title', zui.formatDate(plan.startDatetime, 'yyyy-MM-dd') + '~' + zui.formatDate(plan.endDatetime, 'yyyy-MM-dd')); var $row = $('
').append($bar); $ganttCanvas.append($row); }); /* Layout gantt container */ $ganttContainer.css('left', $plans.width() + 15); $ganttCanvas.css('height', canvasHeight); /* Layout gantt */ var minWidth = $ganttContainer.width(); var timeGap = minTimeGap < TIME_GAP_STEP ? minTimeGap : Math.floor(minTimeGap / TIME_GAP_STEP) * TIME_GAP_STEP; var colsCount = Math.ceil(days / timeGap); var canvasWidth = Math.max(minWidth, colsCount * MIN_COL_WIDTH); var colWidth = Math.floor(canvasWidth / colsCount); var pxPerMs = colWidth / (timeGap * ONE_DAY); $ganttCanvas.css('width', canvasWidth).find('.gantt-col').remove(); for (var i = 0; i < colsCount; ++i) { var $col = $('
'); $col.css( { left: i * colWidth, width: colWidth, height: canvasHeight }); var colTime = startDatetime + i * timeGap * ONE_DAY; $col.append('
' + zui.formatDate(colTime, 'MM/dd') + '
'); $ganttCanvas.append($col); } $.each(plans, function(index, plan) { var $planRow = $gantt.find('.gantt-row[data-id="' + plan.id + '"]'); $planRow.find('.gantt-bar').css( { left: Math.floor((plan.startDatetime - startDatetime) * pxPerMs), width: Math.floor((plan.endDatetime - plan.startDatetime) * pxPerMs) }); }); $gantt.find('.gantt-today').css('left', (Date.now() - startDatetime) * pxPerMs); /** * Create date from string * * @param {String} dateStr like '2020-08-02' * @return {Number} Date timestramp */ function createDatetime(dateStr) { dateStr = dateStr.split('-'); var year = Number.parseInt(dateStr[0].length > 3 ? dateStr[0] : dateStr[2], 10); var month = Number.parseInt(dateStr[1], 10); var day = Number.parseInt(dateStr[2].length > 3 ? dateStr[0] : dateStr[2], 10); return new Date(year, month - 1, day).getTime(); } }