Task Operations

You can add, remove, indent, outdent, link, or unlink tasks. Try performing the tasks in the demo below to see how they change the GanttSheet chart.

Add Task You can add tasks in different ways: addTasks (data: number | ITaskData | ITaskData[] = 1, level?: number): GC.Spread.Sheets.GanttSheet.Task[]; insertTasks (taskNumber: number, data: number | ITaskData | ITaskData[] = 1, level?: number): GC.Spread.Sheets.GanttSheet.Task[]; Remove Task Tasks can also be removed in different ways: removeTasks (taskNumbers: number | number[]): void; removeTasksByRange (taskNumber: number, count = 1): void; Indent/Outdent Task You can also indent tasks with specific API: indentTasks (taskNumbers: number | number[]): void; indentTasksByRange (taskNumber: number, count = 1): void; outdentTasks (taskNumbers: number | number[]): void; outdentTasksByRange (taskNumber: number, count = 1): void;
/*REPLACE_MARKER*/ /*DO NOT DELETE THESE COMMENTS*/ var myTable; var ganttSheet; var roundBarsToWholeDays = true; window.onload = function() { var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"), { sheetCount: 0 }); initSpread(spread); initSplitView(spread); }; function initSpread(spread) { spread.suspendPaint(); initDataSource(spread); initGanttSheet(spread); spread.resumePaint(); } function initDataSource(spread) { var tableName = "Gantt_Id"; var baseApiUrl = getBaseApiUrl(); var apiUrl = baseApiUrl + "/" + tableName; var dataManager = spread.dataManager(); 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" } } } }); } function initGanttSheet(spread) { ganttSheet = spread.addSheetTab(0, "GanttSheet", GC.Spread.Sheets.SheetType.ganttSheet); var view = myTable.addView("ganttView", [ { value: "id", caption: "Id", width: 40 }, { 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 } ]); view.fetch().then(function() { ganttSheet.bindGanttView(view); }); initSidePanel(ganttSheet); } function initSidePanel(ganttSheet) { var addTaskItem = document.getElementById("add-task"); var addSummayItem = document.getElementById("add-summary"); var addMilestoneItem = document.getElementById("add-milestone"); var deleteItem = document.getElementById("delete-task"); var indentTaskItem = document.getElementById("indent-task"); var outdentTaskItem = document.getElementById("outdent-task"); var linkTaskItem = document.getElementById("link-task"); var unlinkTaskItem = document.getElementById("unlink-task"); var submitItem = document.getElementById("submit-changes"); var cancelItem = document.getElementById("cancel-changes"); addTaskItem.addEventListener("click", function() { ganttSheet.suspendPaint() addTask(); ganttSheet.resumePaint(); }); addSummayItem.addEventListener("click", function() { ganttSheet.suspendPaint() addSummary(); ganttSheet.resumePaint(); }); addMilestoneItem.addEventListener("click", function() { ganttSheet.suspendPaint() addMilestone(); ganttSheet.resumePaint(); }); deleteItem.addEventListener("click", function() { ganttSheet.suspendPaint() deleteTask(); ganttSheet.resumePaint(); }); indentTaskItem.addEventListener("click", function() { ganttSheet.suspendPaint() indentTask(); ganttSheet.resumePaint(); }); outdentTaskItem.addEventListener("click", function() { ganttSheet.suspendPaint() outdentTask(); ganttSheet.resumePaint(); }); linkTaskItem.addEventListener("click", function() { ganttSheet.suspendPaint() linkTask(); ganttSheet.resumePaint(); }); unlinkTaskItem.addEventListener("click", function() { ganttSheet.suspendPaint() unlinkTask(); ganttSheet.resumePaint(); }); submitItem.addEventListener("click", function() { ganttSheet.submitChanges(); }); cancelItem.addEventListener("click", function() { ganttSheet.cancelChanges(); }); function addTask() { var project = ganttSheet.project; var selections = ganttSheet.getSelections(); var insertedRow = Math.min(...selections.map(r => r.row), project.tasks.length) var rowCount = selections.map(r => r.rowCount).reduce((pre,current) => {return pre + current}); var taskData = createTaskDataList(rowCount, () => ({ name: "<New Task>" })); project.insertTasksByRow(insertedRow, taskData); } function addSummary() { var project = ganttSheet.project; var selectedRange = ganttSheet.getSelections()[0]; var insertedRow = selectedRange.row; var insertedTaskNumbers = ganttSheet.getTaskByRow(insertedRow).taskNumber || project.count; var selectedTasks = getSelectedRowIndexes().map((row) => ganttSheet.getTaskByRow(row)).filter((row) => !!row); if (selectedTasks.length == 0) { project.insertTasks(insertedTaskNumbers, [{ name: "<New Summary Task>" }, { name: "<New Task>" }]); project.indentTasks(insertedTaskNumbers + 1); } else { project.insertTasks(insertedTaskNumbers, { name: "<New Summary Task>" }, selectedTasks[0].level); project.indentTasks(selectedTasks.map((t) => t.taskNumber)); } ganttSheet.setSelection(insertedRow, -1, 1, -1); } function addMilestone() { var project = ganttSheet.project; var selections = ganttSheet.getSelections(); var rowCount = selections.map(r => r.rowCount).reduce((pre,current) => {return pre + current}); var insertedRow = Math.min(...selections.map(r => r.row), project.tasks.length); var taskData = createTaskDataList(rowCount, () => ({ name: "<New Milestone>", duration: 0 })); project.insertTasksByRow(insertedRow, taskData); ganttSheet.setSelection(insertedRow, -1, rowCount, -1); } function deleteTask() { var project = ganttSheet.project; var rowIds = getSelectedTaskNumbers(); project.removeTasks(rowIds); } function indentTask() { var project = ganttSheet.project; var rowIds = getSelectedTaskNumbers(); project.indentTasks(rowIds); } function outdentTask() { var project = ganttSheet.project; var rowIds = getSelectedTaskNumbers(); project.outdentTasks(rowIds); } function linkTask() { var project = ganttSheet.project; var links = []; var selections = ganttSheet.getSelections(); var previous = -1; for (var range of selections) { if (previous != -1) { links.push([previous, range.row]); } for (var row = range.row + 1; row < range.row + range.rowCount; row++) { links.push([row - 1, row]); } previous = range.row + range.rowCount - 1; } if (links.length <= 0) { return; } project.suspendSchedule(); for (var link of links) { var [fromTaskNumber, toTaskNumber] = link; try { project.addDependency({fromTaskNumber, toTaskNumber}); } catch (e) { } } project.resumeSchedule(); } function unlinkTask() { var project = ganttSheet.project; var taskNumbers = getSelectedTaskNumbers(); var dependencies = []; if (taskNumbers.length == 1) { var task = project.getTaskByRow(taskNumbers[0]); dependencies = [...task.predecessorDependencies, ...task.successorDependencies]; } else { var taskNumberSet = {}; for (var taskNumber of taskNumbers) { taskNumberSet[taskNumber] = true; } dependencies = project.dependencies.filter(dp => taskNumberSet[dp.from.taskNumber] && taskNumberSet[dp.to.taskNumber]); } if (dependencies.length >= 1) { project.removeDependency(dependencies); } } function getSelectedRowIndexes() { var rows = []; var selections = ganttSheet.getSelections(); for (var range of selections) { for (var row = range.row; row < range.row + range.rowCount; row++) { rows.push(row); } } return rows; } function getSelectedTaskNumbers() { return getSelectedRowIndexes().map(r => ganttSheet.getTaskByRow(r).taskNumber).filter((taskNumber) => !isNaN(taskNumber)); } function createTaskDataList(count, initializer) { var array = new Array(count); for (var index = 0; index < count; index++) { array[index] = initializer(); } return array; } } 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"> Operate the selected tasks. </div> <div class="option-block"> <div class="option-row"> <input type="button" id="add-task" class="option-button" value="Add Task" /> </div> <div class="option-row"> <input type="button" id="add-summary" class="option-button" value="Add Summary" /> </div> <div class="option-row"> <input type="button" id="add-milestone" class="option-button" value="Add Milestone" /> </div> </div> <div class="option-block"> <div class="option-row"> <input type="button" id="delete-task" class="option-button" value="Delete" /> </div> </div> <div class="option-block"> <div class="option-row"> <input type="button" id="indent-task" class="option-button" value="Indent" /> </div> <div class="option-row"> <input type="button" id="outdent-task" class="option-button" value="Outdent" /> </div> </div> <div class="option-block"> <div class="option-row"> <input type="button" id="link-task" class="option-button" value="Link" /> </div> <div class="option-row"> <input type="button" id="unlink-task" class="option-button" value="Unlink" /> </div> </div> <div class="option-block"> <div class="option-info">* Save or abort current ganttsheet changes.</div> <div class="option-row"> <input type="button" id="submit-changes" class="option-button" value="Submit Changes" /> </div> <div class="option-row"> <input type="button" id="cancel-changes" class="option-button" value="Cancel Changes" /> </div> </div> </div> </div> </html>
.options-container { float: right; width: 280px; 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-block.toggle { border: 1px dotted #f7a711; } .option-row { font-size: 14px; box-sizing: border-box; padding: 4px 0; } .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-info.toggle { color: #f7a711; } .option-button { width: 100%; padding: 0; line-height: 20px; 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 { background: #fff; border: 1px dashed #f7a711; color: #f7a711; padding: 2px 4px; transition: 0.3s; box-sizing: border-box; cursor: pointer; } .option-checkbox.active { color: #fff; background: #f7a711; box-shadow: 0 1px 4px 0 rgba(0,0,0,0.3); border-radius: 4px; } .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] { width: 100%; 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 { color: #82bc00; border-bottom: 2px solid #82bc00; } .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); }