GanttSheet Progress Line

This sample demonstrates how to use the Progress Line API to compare task progress with the project current date or status date in a GanttSheet.

Progress Line The Progress Line is an analytical overlay drawn on the Gantt chart. It connects task progress points against a selected reference date, so you can compare the current progress of tasks with the project plan. This sample uses task complete data and exposes the Progress Line API through the side panel. It initializes the project current date and status date so the Progress Line is visible when the sample opens. You can then update the project dates and configure the Progress Line display, reference date, path type, line style, point style, and date label style. Project Dates The Progress Line references one project-level date at a time: project.currentDate project.statusDate The sample assigns both dates by default. You can update these dates from the side panel to see how the Progress Line changes. Date Gridlines The current date gridline and status date gridline use fixed styles in this sample. These gridlines are configured independently from the Progress Line. Progress Line API You can use ganttSheet.progressLine to set or get the Progress Line configuration. The available properties are: display: Indicates whether to display the Progress Line. referenceDate: Indicates which project date is used. The value can be "statusDate" or "currentDate". pathType: Indicates how the progress line path is drawn, including whether the path returns to the reference date and whether progress points are connected by an orthogonal or diagonal line. lineStyle: Indicates the Progress Line type and color. It uses GC.Spread.Sheets.GanttSheet.GanttGridlineType. pointStyle: Indicates the progress point shape and color. The shape uses GC.Spread.Sheets.GanttSheet.ProgressPointShape, which supports the same values as GC.Spread.Sheets.GanttSheet.TaskbarEndShape. dateLabelStyle: Indicates whether to display the date label and how the label is formatted.
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ var ganttSheet; var GanttGridlineType = GC.Spread.Sheets.GanttSheet.GanttGridlineType; var lineTypeMap = {}; lineTypeMap.thin = GanttGridlineType.thin; lineTypeMap.dashed = GanttGridlineType.dashed; lineTypeMap.dotted = GanttGridlineType.dotted; lineTypeMap.dashDot = GanttGridlineType.dashDot; lineTypeMap.empty = GanttGridlineType.empty; window.onload = function() { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 }); initSpread(spread); initSplitView(spread); }; function initSpread(spread) { spread.suspendPaint(); initGanttSheet(spread); spread.resumePaint(); } function initGanttSheet(spread) { var tableName = "Gantt_Mode"; var baseApiUrl = getBaseApiUrl(); var apiUrl = baseApiUrl + "/" + tableName; var dataManager = spread.dataManager(); var myTable = dataManager.addTable("myTable", { batch: true, remote: { read: { url: apiUrl }, batch: { url: apiUrl + "Collection" } }, schema: { hierarchy: { type: "Parent", column: "parentId" }, columns: { id: { isPrimaryKey: true }, taskNumber: { dataType: "rowOrder" } } } }); ganttSheet = spread.addSheetTab(0, "GanttSheet1", GC.Spread.Sheets.SheetType.ganttSheet); var view = myTable.addView("myView1", [ { value: "taskNumber", caption: "NO", width: 60 }, { value: "name", caption: "Task Name", width: 200 }, { value: "duration", caption: "Duration", width: 90 }, { value: "predecessors", caption: "Predecessors", width: 120 }, { value: "complete", caption: "% Complete", width: 100 } ]); view.fetch().then(function() { return ganttSheet.bindGanttView(view); }).then(function() { initDefaultProjectDates(); applyFixedGridlines(); applyProgressLine(); }); initSidePanel(); } function initDefaultProjectDates() { var projectStart = ganttSheet.project.startDate; var currentDate = addDays(projectStart, 4); var statusDate = addDays(projectStart, 7); ganttSheet.project.currentDate = currentDate; ganttSheet.project.statusDate = statusDate; document.getElementById("current-date").value = formatInputDate(currentDate); document.getElementById("status-date").value = formatInputDate(statusDate); } function applyFixedGridlines() { ganttSheet.gridlines.currentDate = { lineColor: "#4A8F40", lineType: GanttGridlineType.thin }; ganttSheet.gridlines.statusDate = { lineColor: "#5B9BD5", lineType: GanttGridlineType.dashDot }; } function initSidePanel() { document.getElementById("apply-progress-line").addEventListener("click", function() { applyProjectDates(); applyFixedGridlines(); applyProgressLine(); }); } function applyProjectDates() { var currentDateValue = document.getElementById("current-date").value; ganttSheet.project.currentDate = parseInputDate(currentDateValue); var statusDateValue = document.getElementById("status-date").value; ganttSheet.project.statusDate = parseInputDate(statusDateValue); } function applyProgressLine() { ganttSheet.suspendPaint(); ganttSheet.progressLine = { display: document.getElementById("display").checked, referenceDate: document.getElementById("reference-date").value, pathType: { returnToReferenceDate: document.getElementById("return-to-reference-date").checked, pointConnectionType: document.getElementById("point-connection-type").value }, lineStyle: { lineType: lineTypeMap[document.getElementById("line-type").value], lineColor: document.getElementById("line-color").value }, pointStyle: { shape: document.getElementById("point-shape").value, color: document.getElementById("point-color").value }, dateLabelStyle: { display: document.getElementById("label-display").checked, format: document.getElementById("label-format").value, font: document.getElementById("label-font").value } }; ganttSheet.resumePaint(); } function addDays(date, days) { var result = new Date(date); result.setDate(result.getDate() + days); return result; } function formatInputDate(date) { if (!date) { return ""; } var year = date.getFullYear(); var month = ("0" + (date.getMonth() + 1)).slice(-2); var day = ("0" + date.getDate()).slice(-2); return year + "-" + month + "-" + day; } function parseInputDate(value) { if (!value) { return null; } var parts = value.split("-"); return new Date(Number(parts[0]), Number(parts[1]) - 1, Number(parts[2])); } function getBaseApiUrl() { return window.location.href.match(/http.+spreadjs\/demos\//)[0] + 'server/api'; } function initSplitView(spread) { var host = document.getElementById("split-view"); var content = host.getElementsByClassName("split-content")[0]; var panel = host.getElementsByClassName("split-panel")[0]; new SplitView({ host: host, content: content, panel: panel, refreshContent: function() { spread.refresh(); } }); }
<!doctype html> <html style="height:100%;font-size:14px;"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/styles/gc.spread.sheets.excel2013white.css"> <link rel="stylesheet" type="text/css" href="$DEMOROOT$/spread/source/splitView/splitView.css"> <!-- Promise Polyfill for IE, https://www.npmjs.com/package/promise-polyfill --> <script src="https://cdn.jsdelivr.net/npm/promise-polyfill@8/dist/polyfill.min.js"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets/dist/gc.spread.sheets.all.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-tablesheet/dist/gc.spread.sheets.tablesheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/en/purejs/node_modules/@mescius/spread-sheets-ganttsheet/dist/gc.spread.sheets.ganttsheet.min.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/splitView/splitView.js" type="text/javascript"></script> <script src="$DEMOROOT$/spread/source/js/license.js" type="text/javascript"></script> <script src="app.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="styles.css"> </head> <body> <div id="split-view" class="sample-tutorial"> <div id="ss" class="sample-spreadsheets split-content"></div> <div class="options-container split-panel"> <div class="option-row option-title"> Config the progress line. </div> <div class="option-block"> <div class="option-row option-title"> Project Dates </div> <div class="option-row input-box"> <label for="current-date">Current Date</label> <input type="date" id="current-date" /> </div> <div class="option-row input-box"> <label for="status-date">Status Date</label> <input type="date" id="status-date" /> </div> </div> <div class="option-block"> <div class="option-row option-title"> Gridlines </div> <div class="option-row"> <span class="line-swatch current-date-line"></span> Current Date: green thin </div> <div class="option-row"> <span class="line-swatch status-date-line"></span> Status Date: blue dash-dot </div> </div> <div class="option-block"> <div class="option-row option-title"> Progress Line </div> <div class="option-row"> <label class="option-checkbox-label"> <input type="checkbox" id="display" checked /> Display </label> </div> <div class="option-row selection-box"> <label for="reference-date">Reference Date</label> <select id="reference-date"> <option value="statusDate" selected>statusDate</option> <option value="currentDate">currentDate</option> </select> </div> </div> <div class="option-block"> <div class="option-row option-title"> Path Type </div> <div class="option-row"> <label class="option-checkbox-label"> <input type="checkbox" id="return-to-reference-date" /> Return to reference date </label> </div> <div class="option-row selection-box"> <label for="point-connection-type">Connection</label> <select id="point-connection-type"> <option value="orthogonal" selected>orthogonal</option> <option value="diagonal">diagonal</option> </select> </div> </div> <div class="option-block"> <div class="option-row option-title"> Line Style </div> <div class="option-row selection-box"> <label for="line-type">Line Type</label> <select id="line-type"> <option value="thin" selected>thin</option> <option value="dashed">dashed</option> <option value="dotted">dotted</option> <option value="dashDot">dashDot</option> <option value="empty">empty</option> </select> </div> <div class="option-row input-box"> <label for="line-color">Color</label> <input type="text" id="line-color" value="#C0504D" /> <div class="option-info valid">* valid value: color string</div> </div> </div> <div class="option-block"> <div class="option-row option-title"> Point Style </div> <div class="option-row selection-box"> <label for="point-shape">Shape</label> <select id="point-shape"> <option value="arrowDown">arrowDown</option> <option value="arrowUp">arrowUp</option> <option value="caretDownTop">caretDownTop</option> <option value="caretUpBottom">caretUpBottom</option> <option value="circleDiamond" selected>circleDiamond</option> <option value="circle">circle</option> <option value="circleArrowDown">circleArrowDown</option> <option value="circleArrowUp">circleArrowUp</option> <option value="circleTriangleDown">circleTriangleDown</option> <option value="circleTriangleUp">circleTriangleUp</option> <option value="diamond">diamond</option> <option value="houseDown">houseDown</option> <option value="houseUp">houseUp</option> <option value="leftBracket">leftBracket</option> <option value="leftFade">leftFade</option> <option value="lineShape">lineShape</option> <option value="rightBracket">rightBracket</option> <option value="rightFade">rightFade</option> <option value="square">square</option> <option value="star">star</option> <option value="triangleDown">triangleDown</option> <option value="triangleLeft">triangleLeft</option> <option value="triangleRight">triangleRight</option> <option value="triangleUp">triangleUp</option> </select> </div> <div class="option-row input-box"> <label for="point-color">Color</label> <input type="text" id="point-color" value="#C0504D" /> <div class="option-info valid">* valid value: color string</div> </div> </div> <div class="option-block"> <div class="option-row option-title"> Date Label Style </div> <div class="option-row"> <label class="option-checkbox-label"> <input type="checkbox" id="label-display" checked /> Display </label> </div> <div class="option-row input-box"> <label for="label-format">Format</label> <input type="text" id="label-format" value="yyyy-MM-dd" /> </div> <div class="option-row input-box"> <label for="label-font">Font</label> <input type="text" id="label-font" value="10pt Calibri" /> </div> </div> <div class="option-block"> <div class="option-row"> <input type="button" id="apply-progress-line" class="option-button" value="Apply Progress Line"> </div> </div> </div> </div> </body> </html>
.sample-tutorial { width: 100%; height: 100%; } body, html { padding: 0; margin: 0; width: 100%; height: 100%; position: relative; overflow: hidden; } .sample-spreadsheets { width: 100%; height: 100%; } .options-container { float: right; width: 300px; padding: 12px; height: 100%; box-sizing: border-box; background: #fbfbfb; overflow: auto; box-shadow: inset 0px 0 4px 0 rgba(0,0,0,0.4); } .option-block { background: #fff; padding: 8px; margin: 12px 0; border-radius: 4px; border: 1px dashed #82bc00; box-shadow: 0px 0 6px 0 rgba(0,0,0,0.1); } .option-row { font-size: 14px; box-sizing: border-box; padding: 4px 0; color: #656565; } .option-title { font-weight: bold; color: #656565; } .option-info { font-size: 12px; color: #919191; margin-top: 6px; font-weight: normal; } .option-info.valid { color: #82bc00; } .option-button { width: 100%; padding: 0; line-height: 22px; background: #82bc00; color: #fff; transition: 0.3s; cursor: pointer; outline: none; border-radius: 4px; box-sizing: border-box; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); border: none; } .option-button:hover { background: #82bc00; color: #fff; box-shadow: 0 3px 8px 0 rgba(0,0,0,0.4); } .option-checkbox-label { cursor: pointer; } .selection-box { position: relative; } .selection-box > select { text-align: left; width: 100%; height: 20px; padding: 0; line-height: 20px; background: transparent; border: none; border-bottom: 2px solid #656565; color: #656565; transition: 0.3s; cursor: pointer; outline: none; box-sizing: border-box; } .selection-box > select > option { background: white; } .selection-box > select:focus { border-bottom: 2px solid #82bc00; color: #82bc00; box-shadow: 0 2px 6px 0 rgba(0,0,0,0.3); } .selection-box > label { position: absolute; cursor: pointer; font-size: 12px; color: #fff; background: #656565; padding: 0 4px; right: 0; top: 6px; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); } .input-box { position: relative; } .input-box > input[type=text], .input-box > input[type=date] { width: 100%; height: 22px; background: transparent; border: none; color: #656565; border-bottom: 2px solid #656565; outline: none; box-sizing: border-box; transition: 0.3s; } .input-box > input[type=text]:focus, .input-box > input[type=date]:focus { color: #82bc00; border-bottom: 2px solid #82bc00; } .input-box > input:disabled { color: #b0b0b0; border-bottom-color: #c9c9c9; } .input-box > label { cursor: pointer; position: absolute; right: 0; top: 5px; font-size: 12px; color: #fff; background: #656565; padding: 0 4px; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); } .line-swatch { display: inline-block; width: 36px; height: 0; margin-right: 6px; vertical-align: middle; } .current-date-line { border-top: 2px solid #4A8F40; } .status-date-line { border-top: 2px dashed #5B9BD5; border-top-style: dashed; }