summaryrefslogtreecommitdiff
path: root/assets/js/src
diff options
context:
space:
mode:
authorFrederic Guillot <fred@kanboard.net>2017-04-01 17:04:18 -0400
committerFrederic Guillot <fred@kanboard.net>2017-04-01 17:04:18 -0400
commit5cc488947305eea5b9762997222c84d6007761c8 (patch)
tree5f602bb06ade363aa40eda99b4fe9a61f592609f /assets/js/src
parent253d5a9331e4b4775066ec8cb9664da9a2aa6ac9 (diff)
Move Gantt charts to external plugin
Diffstat (limited to 'assets/js/src')
-rw-r--r--assets/js/src/Gantt.js489
1 files changed, 0 insertions, 489 deletions
diff --git a/assets/js/src/Gantt.js b/assets/js/src/Gantt.js
deleted file mode 100644
index cd6cac00..00000000
--- a/assets/js/src/Gantt.js
+++ /dev/null
@@ -1,489 +0,0 @@
-// Based on jQuery.ganttView v.0.8.8 Copyright (c) 2010 JC Grubbs - jc.grubbs@devmynd.com - MIT License
-Kanboard.Gantt = function(app) {
- this.app = app;
- this.data = [];
-
- this.options = {
- container: "#gantt-chart",
- showWeekends: true,
- allowMoves: true,
- allowResizes: true,
- cellWidth: 21,
- cellHeight: 31,
- slideWidth: 1000,
- vHeaderWidth: 200
- };
-};
-
-Kanboard.Gantt.prototype.execute = function() {
- if (this.app.hasId("gantt-chart")) {
- this.show();
- }
-};
-
-// Save record after a resize or move
-Kanboard.Gantt.prototype.saveRecord = function(record) {
- this.app.showLoadingIcon();
-
- $.ajax({
- cache: false,
- url: $(this.options.container).data("save-url"),
- contentType: "application/json",
- type: "POST",
- processData: false,
- data: JSON.stringify(record),
- complete: this.app.hideLoadingIcon.bind(this)
- });
-};
-
-// Build the Gantt chart
-Kanboard.Gantt.prototype.show = function() {
- this.data = this.prepareData($(this.options.container).data('records'));
-
- var minDays = Math.floor((this.options.slideWidth / this.options.cellWidth) + 5);
- var range = this.getDateRange(minDays);
- var startDate = range[0];
- var endDate = range[1];
- var container = $(this.options.container);
- var chart = jQuery("<div>", { "class": "ganttview" });
-
- chart.append(this.renderVerticalHeader());
- chart.append(this.renderSlider(startDate, endDate));
- container.append(chart);
-
- jQuery("div.ganttview-grid-row div.ganttview-grid-row-cell:last-child", container).addClass("last");
- jQuery("div.ganttview-hzheader-days div.ganttview-hzheader-day:last-child", container).addClass("last");
- jQuery("div.ganttview-hzheader-months div.ganttview-hzheader-month:last-child", container).addClass("last");
-
- if (! $(this.options.container).data('readonly')) {
- this.listenForBlockResize(startDate);
- this.listenForBlockMove(startDate);
- }
- else {
- this.options.allowResizes = false;
- this.options.allowMoves = false;
- }
-};
-
-// Render record list on the left
-Kanboard.Gantt.prototype.renderVerticalHeader = function() {
- var headerDiv = jQuery("<div>", { "class": "ganttview-vtheader" });
- var itemDiv = jQuery("<div>", { "class": "ganttview-vtheader-item" });
- var seriesDiv = jQuery("<div>", { "class": "ganttview-vtheader-series" });
-
- for (var i = 0; i < this.data.length; i++) {
- var content = jQuery("<span>")
- .append(jQuery("<i>", {"class": "fa fa-info-circle tooltip", "title": this.getVerticalHeaderTooltip(this.data[i])}))
- .append("&nbsp;");
-
- if (this.data[i].type == "task") {
- content.append(jQuery("<a>", {"href": this.data[i].link, "title": this.data[i].title}).text(this.data[i].title));
- }
- else {
- content
- .append(jQuery("<a>", {"href": this.data[i].board_link, "title": $(this.options.container).data("label-board-link")}).append('<i class="fa fa-th"></i>'))
- .append("&nbsp;")
- .append(jQuery("<a>", {"href": this.data[i].gantt_link, "title": $(this.options.container).data("label-gantt-link")}).append('<i class="fa fa-sliders"></i>'))
- .append("&nbsp;")
- .append(jQuery("<a>", {"href": this.data[i].link}).text(this.data[i].title));
- }
-
- seriesDiv.append(jQuery("<div>", {"class": "ganttview-vtheader-series-name"}).append(content));
- }
-
- itemDiv.append(seriesDiv);
- headerDiv.append(itemDiv);
-
- return headerDiv;
-};
-
-// Render right part of the chart (top header + grid + bars)
-Kanboard.Gantt.prototype.renderSlider = function(startDate, endDate) {
- var slideDiv = jQuery("<div>", {"class": "ganttview-slide-container"});
- var dates = this.getDates(startDate, endDate);
-
- slideDiv.append(this.renderHorizontalHeader(dates));
- slideDiv.append(this.renderGrid(dates));
- slideDiv.append(this.addBlockContainers());
- this.addBlocks(slideDiv, startDate);
-
- return slideDiv;
-};
-
-// Render top header (days)
-Kanboard.Gantt.prototype.renderHorizontalHeader = function(dates) {
- var headerDiv = jQuery("<div>", { "class": "ganttview-hzheader" });
- var monthsDiv = jQuery("<div>", { "class": "ganttview-hzheader-months" });
- var daysDiv = jQuery("<div>", { "class": "ganttview-hzheader-days" });
- var totalW = 0;
-
- for (var y in dates) {
- for (var m in dates[y]) {
- var w = dates[y][m].length * this.options.cellWidth;
- totalW = totalW + w;
-
- monthsDiv.append(jQuery("<div>", {
- "class": "ganttview-hzheader-month",
- "css": { "width": (w - 1) + "px" }
- }).append($.datepicker.regional[$("body").data('js-lang')].monthNames[m] + " " + y));
-
- for (var d in dates[y][m]) {
- daysDiv.append(jQuery("<div>", { "class": "ganttview-hzheader-day" }).append(dates[y][m][d].getDate()));
- }
- }
- }
-
- monthsDiv.css("width", totalW + "px");
- daysDiv.css("width", totalW + "px");
- headerDiv.append(monthsDiv).append(daysDiv);
-
- return headerDiv;
-};
-
-// Render grid
-Kanboard.Gantt.prototype.renderGrid = function(dates) {
- var gridDiv = jQuery("<div>", { "class": "ganttview-grid" });
- var rowDiv = jQuery("<div>", { "class": "ganttview-grid-row" });
-
- for (var y in dates) {
- for (var m in dates[y]) {
- for (var d in dates[y][m]) {
- var cellDiv = jQuery("<div>", { "class": "ganttview-grid-row-cell" });
- if (this.options.showWeekends && this.isWeekend(dates[y][m][d])) {
- cellDiv.addClass("ganttview-weekend");
- }
- rowDiv.append(cellDiv);
- }
- }
- }
- var w = jQuery("div.ganttview-grid-row-cell", rowDiv).length * this.options.cellWidth;
- rowDiv.css("width", w + "px");
- gridDiv.css("width", w + "px");
-
- for (var i = 0; i < this.data.length; i++) {
- gridDiv.append(rowDiv.clone());
- }
-
- return gridDiv;
-};
-
-// Render bar containers
-Kanboard.Gantt.prototype.addBlockContainers = function() {
- var blocksDiv = jQuery("<div>", { "class": "ganttview-blocks" });
-
- for (var i = 0; i < this.data.length; i++) {
- blocksDiv.append(jQuery("<div>", { "class": "ganttview-block-container" }));
- }
-
- return blocksDiv;
-};
-
-// Render bars
-Kanboard.Gantt.prototype.addBlocks = function(slider, start) {
- var rows = jQuery("div.ganttview-blocks div.ganttview-block-container", slider);
- var rowIdx = 0;
-
- for (var i = 0; i < this.data.length; i++) {
- var series = this.data[i];
- var size = this.daysBetween(series.start, series.end) + 1;
- var offset = this.daysBetween(start, series.start);
- var text = jQuery("<div>", {"class": "ganttview-block-text"});
-
- var block = jQuery("<div>", {
- "class": "ganttview-block tooltip" + (this.options.allowMoves ? " ganttview-block-movable" : ""),
- "title": this.getBarTooltip(series),
- "css": {
- "width": ((size * this.options.cellWidth) - 9) + "px",
- "margin-left": (offset * this.options.cellWidth) + "px"
- }
- }).append(text);
-
- if (size >= 2) {
- text.append(series.progress);
- }
-
- block.data("record", series);
- this.setBarColor(block, series);
-
- jQuery(rows[rowIdx]).append(block);
- rowIdx = rowIdx + 1;
- }
-};
-
-// Get tooltip for vertical header
-Kanboard.Gantt.prototype.getVerticalHeaderTooltip = function(record) {
- var tooltip = "";
-
- if (record.type == "task") {
- tooltip = jQuery("<span>")
- .append(jQuery("<strong>").text(record.column_title))
- .append(document.createTextNode(' (' + record.progress + ')'))
- .append(jQuery("<br>"))
- .append(document.createTextNode(record.title)).prop('outerHTML');
- }
- else {
- var types = ["project-manager", "project-member"];
-
- for (var index in types) {
- var type = types[index];
- if (! jQuery.isEmptyObject(record.users[type])) {
- var list = jQuery("<ul>");
-
- for (var user_id in record.users[type]) {
- if (user_id) {
- list.append(jQuery("<li>").text(record.users[type][user_id]));
- }
- }
-
- tooltip += "<p><strong>" + $(this.options.container).data("label-" + type) + "</strong></p>" + list.prop('outerHTML');
- }
- }
- }
-
- return tooltip;
-};
-
-// Get tooltip for bars
-Kanboard.Gantt.prototype.getBarTooltip = function(record) {
- var tooltip = "";
-
- if (record.not_defined) {
- tooltip = $(this.options.container).data("label-not-defined");
- }
- else {
- if (record.type == "task") {
- var assigneeLabel = $(this.options.container).data("label-assignee");
- tooltip += jQuery("<strong>").text(record.progress).prop('outerHTML');
- tooltip += "<br>";
- tooltip += jQuery('<span>').append(document.createTextNode(assigneeLabel + " " + (record.assignee ? record.assignee : ''))).prop('outerHTML');
- tooltip += "<br>";
- }
-
- tooltip += $(this.options.container).data("label-start-date") + " " + $.datepicker.formatDate('yy-mm-dd', record.start) + "<br/>";
- tooltip += $(this.options.container).data("label-end-date") + " " + $.datepicker.formatDate('yy-mm-dd', record.end);
- }
-
- return tooltip;
-};
-
-// Set bar color
-Kanboard.Gantt.prototype.setBarColor = function(block, record) {
- if (record.not_defined) {
- block.addClass("ganttview-block-not-defined");
- }
- else {
- block.css("background-color", record.color.background);
- block.css("border-color", record.color.border);
-
- if (record.progress != "0%") {
- block.append(jQuery("<div>", {
- "css": {
- "z-index": 0,
- "position": "absolute",
- "top": 0,
- "bottom": 0,
- "background-color": record.color.border,
- "width": record.progress,
- "opacity": 0.4
- }
- }));
- }
- }
-};
-
-// Setup jquery-ui resizable
-Kanboard.Gantt.prototype.listenForBlockResize = function(startDate) {
- var self = this;
-
- jQuery("div.ganttview-block", this.options.container).resizable({
- grid: this.options.cellWidth,
- handles: "e,w",
- delay: 300,
- stop: function() {
- var block = jQuery(this);
- self.updateDataAndPosition(block, startDate);
- self.saveRecord(block.data("record"));
- }
- });
-};
-
-// Setup jquery-ui drag and drop
-Kanboard.Gantt.prototype.listenForBlockMove = function(startDate) {
- var self = this;
-
- jQuery("div.ganttview-block", this.options.container).draggable({
- axis: "x",
- delay: 300,
- grid: [this.options.cellWidth, this.options.cellWidth],
- stop: function() {
- var block = jQuery(this);
- self.updateDataAndPosition(block, startDate);
- self.saveRecord(block.data("record"));
- }
- });
-};
-
-// Update the record data and the position on the chart
-Kanboard.Gantt.prototype.updateDataAndPosition = function(block, startDate) {
- var container = jQuery("div.ganttview-slide-container", this.options.container);
- var scroll = container.scrollLeft();
- var offset = block.offset().left - container.offset().left - 1 + scroll;
- var record = block.data("record");
-
- // Restore color for defined block
- record.not_defined = false;
- this.setBarColor(block, record);
-
- // Set new start date
- var daysFromStart = Math.round(offset / this.options.cellWidth);
- var newStart = this.addDays(this.cloneDate(startDate), daysFromStart);
- record.start = newStart;
-
- // Set new end date
- var width = block.outerWidth();
- var numberOfDays = Math.round(width / this.options.cellWidth) - 1;
- record.end = this.addDays(this.cloneDate(newStart), numberOfDays);
-
- if (record.type === "task" && numberOfDays > 0) {
- jQuery("div.ganttview-block-text", block).text(record.progress);
- }
-
- // Update tooltip
- block.attr("title", this.getBarTooltip(record));
-
- block.data("record", record);
-
- // Remove top and left properties to avoid incorrect block positioning,
- // set position to relative to keep blocks relative to scrollbar when scrolling
- block
- .css("top", "")
- .css("left", "")
- .css("position", "relative")
- .css("margin-left", offset + "px");
-};
-
-// Creates a 3 dimensional array [year][month][day] of every day
-// between the given start and end dates
-Kanboard.Gantt.prototype.getDates = function(start, end) {
- var dates = [];
- dates[start.getFullYear()] = [];
- dates[start.getFullYear()][start.getMonth()] = [start];
- var last = start;
-
- while (this.compareDate(last, end) == -1) {
- var next = this.addDays(this.cloneDate(last), 1);
-
- if (! dates[next.getFullYear()]) {
- dates[next.getFullYear()] = [];
- }
-
- if (! dates[next.getFullYear()][next.getMonth()]) {
- dates[next.getFullYear()][next.getMonth()] = [];
- }
-
- dates[next.getFullYear()][next.getMonth()].push(next);
- last = next;
- }
-
- return dates;
-};
-
-// Convert data to Date object
-Kanboard.Gantt.prototype.prepareData = function(data) {
- for (var i = 0; i < data.length; i++) {
- var start = new Date(data[i].start[0], data[i].start[1] - 1, data[i].start[2], 0, 0, 0, 0);
- data[i].start = start;
-
- var end = new Date(data[i].end[0], data[i].end[1] - 1, data[i].end[2], 0, 0, 0, 0);
- data[i].end = end;
- }
-
- return data;
-};
-
-// Get the start and end date from the data provided
-Kanboard.Gantt.prototype.getDateRange = function(minDays) {
- var minStart = new Date();
- var maxEnd = new Date();
-
- for (var i = 0; i < this.data.length; i++) {
- var start = new Date();
- start.setTime(Date.parse(this.data[i].start));
-
- var end = new Date();
- end.setTime(Date.parse(this.data[i].end));
-
- if (i == 0) {
- minStart = start;
- maxEnd = end;
- }
-
- if (this.compareDate(minStart, start) == 1) {
- minStart = start;
- }
-
- if (this.compareDate(maxEnd, end) == -1) {
- maxEnd = end;
- }
- }
-
- // Insure that the width of the chart is at least the slide width to avoid empty
- // whitespace to the right of the grid
- if (this.daysBetween(minStart, maxEnd) < minDays) {
- maxEnd = this.addDays(this.cloneDate(minStart), minDays);
- }
-
- // Always start one day before the minStart
- minStart.setDate(minStart.getDate() - 1);
-
- return [minStart, maxEnd];
-};
-
-// Returns the number of day between 2 dates
-Kanboard.Gantt.prototype.daysBetween = function(start, end) {
- if (! start || ! end) {
- return 0;
- }
-
- var count = 0, date = this.cloneDate(start);
-
- while (this.compareDate(date, end) == -1) {
- count = count + 1;
- this.addDays(date, 1);
- }
-
- return count;
-};
-
-// Return true if it's the weekend
-Kanboard.Gantt.prototype.isWeekend = function(date) {
- return date.getDay() % 6 == 0;
-};
-
-// Clone Date object
-Kanboard.Gantt.prototype.cloneDate = function(date) {
- return new Date(date.getTime());
-};
-
-// Add days to a Date object
-Kanboard.Gantt.prototype.addDays = function(date, value) {
- date.setDate(date.getDate() + value * 1);
- return date;
-};
-
-/**
- * Compares the first date to the second date and returns an number indication of their relative values.
- *
- * -1 = date1 is lessthan date2
- * 0 = values are equal
- * 1 = date1 is greaterthan date2.
- */
-Kanboard.Gantt.prototype.compareDate = function(date1, date2) {
- if (isNaN(date1) || isNaN(date2)) {
- throw new Error(date1 + " - " + date2);
- } else if (date1 instanceof Date && date2 instanceof Date) {
- return (date1 < date2) ? -1 : (date1 > date2) ? 1 : 0;
- } else {
- throw new TypeError(date1 + " - " + date2);
- }
-};