Renamed js-ext files
WIP: project task grid and gantt chart
This commit is contained in:
parent
fc4f172e15
commit
d30d60ae91
|
@ -11,4 +11,6 @@ cd..
|
|||
|
||||
type ryzjsext.min.tmp >> ryzjsext.min.js
|
||||
|
||||
move ryzjsext.min.js build/ryzjsext.min.js
|
||||
|
||||
del ryzjsext.min.tmp
|
|
@ -13,6 +13,6 @@ Date.prototype.toCString=function(a){a=a.replace("fffffff",this.getMilliseconds(
|
|||
a=a.replace("MMM","{3}");a=a.replace("ddd","{4}");a=a.replace("fff",this.getMilliseconds().toString().padStart(3,"0"));a=a.replace("zzz","");a=a.replace("yy",this.getFullYear().toString().slice(-2));a=a.replace("MM",(this.getMonth()+1).toString().padStart(2,"0"));a=a.replace("dd",this.getDate().toString().padStart(2,"0"));a=a.replace("HH",this.getHours().toString().padStart(2,"0"));a=a.replace("hh",(12<this.getHours()?this.getHours()-12:this.getHours()).toString().padStart(2,"0"));a=a.replace("mm",
|
||||
this.getMinutes().toString().padStart(2,"0"));a=a.replace("ss",this.getSeconds().toString().padStart(2,"0"));a=a.replace("ff",this.getMilliseconds().toString().padStart(2,"0"));a=a.replace("tt","{5}");a=a.replace("zz","");a=a.replace("y",this.getFullYear().toString());a=a.replace("M",(this.getMonth()+1).toString());a=a.replace("d",this.getDate().toString());a=a.replace("H",this.getHours().toString());a=a.replace("h",(12<this.getHours()?this.getHours()-12:this.getHours()).toString());a=a.replace("m",
|
||||
this.getMinutes().toString());a=a.replace("s",this.getSeconds().toString());a=a.replace("z","");a=a.replace("t","{6}");a=a.replace("Z","");a=a.replace("{1}",this.toLocaleString("default",{month:"long"}));a=a.replace("{2}",this.toLocaleString("default",{weekday:"long"}));a=a.replace("{3}",this.toLocaleString("default",{month:"short"}));a=a.replace("{4}",this.toLocaleString("default",{weekday:"short"}));a=a.replace("{5}",12<=this.getHours()?"PM":"AM");return a=a.replace("{6}",12<=this.getHours()?"P":
|
||||
"A")};Document.ready=async function(a){(async function(){"loading"!==document.readyState?a():document.addEventListener("DOMContentLoaded",function(){a()})})()};Math.randomN=function(a,b){a=Math.ceil(a);b=Math.floor(b);return Math.floor(Math.random()*(b-a)+a)};Math.average=function(a){let b=0;a.forEach(c=>{b+=parseFloat(c)});return Math.round(b/a.length)};String.isNullOrUndefined=function(a){return"undefined"==typeof a||null==a?!0:!1};String.isNullOrWhitespace=function(a){return String.isNullOrUndefined(a)?!0:"string"==typeof a?0>=a.trim().length:0>=a.toString().trim().length};String.joinIfNotNullOrWhitespace=function(a,...b){let c="";for(let d=0;d<b.length;d++)String.isNullOrWhitespace(b[d])||(String.isNullOrWhitespace(c)||(c+=a),c+=b[d]);return c};String.prototype.contains=function(...a){for(let b of a)if(this==b)return!0;return!1};
|
||||
"A")};Document.ready=async function(a){(async function(){"loading"!==document.readyState?a():document.addEventListener("DOMContentLoaded",function(){a()})})()};Math.randomN=function(a,b){a=Math.ceil(a);b=Math.floor(b);return Math.floor(Math.random()*(b-a)+a)};Math.average=function(a){let b=0;a.forEach(c=>{b+=parseFloat(c)});return Math.round(b/a.length)};Math.half=function(a){return a/2};class Rectangle{constructor(a,b,c,d){this.X=a;this.Y=b;this.W=c;this.H=d}static containsPoint(a,b){const c=a.X+a.W,d=a.Y+a.H;return b.X>=a.X&&b.X<=c&&b.Y>=a.Y&&b.Y<=d}static combine(a,b){const c=Math.max(a.Y+a.H,b.Y+b.H),d={X:Math.min(a.X,b.X),Y:Math.min(a.Y,b.Y),W:0,H:0};d.W=Math.max(a.X+a.W,b.X+b.W)-d.X;d.H=c-d.Y;return d}};String.isNullOrUndefined=function(a){return"undefined"==typeof a||null==a?!0:!1};String.isNullOrWhitespace=function(a){return String.isNullOrUndefined(a)?!0:"string"==typeof a?0>=a.trim().length:0>=a.toString().trim().length};String.joinIfNotNullOrWhitespace=function(a,...b){let c="";for(let d=0;d<b.length;d++)String.isNullOrWhitespace(b[d])||(String.isNullOrWhitespace(c)||(c+=a),c+=b[d]);return c};String.prototype.contains=function(...a){for(let b of a)if(this==b)return!0;return!1};
|
||||
String.prototype.containsCI=function(...a){for(let b of a)if(this.toLowerCase()==b.toLowerCase())return!0;return!1};String.prototype.encodeHtmlLinks=function(){return value.replace(/(http[s]{0,1}:\/\/[^\s]+)/g,"<a href='$1'>$1</a>")};String.prototype.toTitleCase=function(){let a;a=this.replace(/([A-Z]{1})/g," $1");a=a.trim();return a=a.charAt(0).toUpperCase()+a.substr(1)};String.prototype.getFilename=function(){return this.substring(this.lastIndexOf("/")+1)};Window.goToTop=function(){Window.scrollTo(0,0)};
|
||||
Window.fragment={get:function(){if(!window.location.hash)return null;const a=window.location.hash.indexOf("?");return 0>a?window.location.hash.substring(1):window.location.hash.substring(1,a)},getQuery:function(){if(!window.location.hash)return null;var a=window.location.hash;a=a.indexOf("?");if(0>a)return null;a=hasQueryString.substring(a+1);a=new URLSearchParams(a);const b={};for(const [c,d]of a.entries())b[c]=d;return b},clear:function(){location.hash="";history.replaceState("","",location.pathname)}};
|
|
@ -0,0 +1,179 @@
|
|||
class Canvas {
|
||||
_container = null;
|
||||
_ctx = null;
|
||||
_padding = {
|
||||
Top: 0,
|
||||
Right: 0,
|
||||
Bottom: 0,
|
||||
Left: 0
|
||||
};
|
||||
|
||||
|
||||
constructor(el) {
|
||||
const a = this;
|
||||
|
||||
a._container = el;
|
||||
a._ctx = null;
|
||||
|
||||
a.#initialiseComponents();
|
||||
}
|
||||
|
||||
#initialiseComponents() {
|
||||
const a = this;
|
||||
|
||||
if (a._container == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
a._container.innerHTML = "<canvas></canvas>";
|
||||
|
||||
a.Width = a.Width;
|
||||
a.Height = a.Height;
|
||||
|
||||
a.Clear();
|
||||
}
|
||||
|
||||
|
||||
get Height() {
|
||||
const a = this;
|
||||
|
||||
if (a._container == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const h = (a._container.offsetHeight || a._container.innerHeight || a._container.clientHeight);
|
||||
|
||||
return h;
|
||||
}
|
||||
|
||||
set Height(value) {
|
||||
const a = this;
|
||||
|
||||
if (a._container == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
a._container.style.height = value + "px";
|
||||
|
||||
const canvas = a._container.getElementsByTagName("canvas")[0];
|
||||
canvas.style.height = value + "px";
|
||||
|
||||
a._ctx = canvas.getContext("2d");
|
||||
a._ctx.canvas.height = value;
|
||||
}
|
||||
|
||||
get Width() {
|
||||
const a = this;
|
||||
|
||||
if (a._container == null) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const w = (a._container.offsetWidth || a._container.innerWidth || a._container.clientWidth);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
set Width(value) {
|
||||
const a = this;
|
||||
|
||||
if (a._container == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
a._container.style.width = value + "px";
|
||||
|
||||
const canvas = a._container.getElementsByTagName("canvas")[0];
|
||||
canvas.style.width = value + "px";
|
||||
|
||||
a._ctx = canvas.getContext("2d");
|
||||
a._ctx.canvas.width = value;
|
||||
}
|
||||
|
||||
get Size() {
|
||||
const a = this;
|
||||
|
||||
return {
|
||||
W: a.Width,
|
||||
H: a.Height
|
||||
};
|
||||
}
|
||||
|
||||
get ClientRectangle() {
|
||||
const a = this;
|
||||
|
||||
return {
|
||||
X: a._padding.Left,
|
||||
Y: a._padding.Top,
|
||||
W: (a.Width - (a._padding.Left + a._padding.Right)),
|
||||
H: (a.Height - (a._padding.Top + a._padding.Bottom))
|
||||
};
|
||||
}
|
||||
|
||||
get Rectangle() {
|
||||
const a = this;
|
||||
|
||||
return {
|
||||
X: 0,
|
||||
Y: 0,
|
||||
W: a.Width,
|
||||
H: a.Height
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Clear() {
|
||||
const a = this;
|
||||
|
||||
if (a._ctx == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
a._ctx.clearRect(0, 0, a._ctx.canvas.width, a._ctx.canvas.height);
|
||||
}
|
||||
|
||||
DrawRectangle(rectangle, penColour, penWidth) {
|
||||
const a = this;
|
||||
|
||||
if (a._ctx == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Adjust for pen discrepancy
|
||||
rectangle.X += 0.5;
|
||||
rectangle.Y += 0.5;
|
||||
rectangle.W -= penWidth;
|
||||
rectangle.H -= penWidth;
|
||||
|
||||
a._ctx.beginPath();
|
||||
a._ctx.strokeStyle = penColour;
|
||||
a._ctx.lineWidth = penWidth;
|
||||
a._ctx.rect(rectangle.X, rectangle.Y, rectangle.W, rectangle.H);
|
||||
|
||||
//a.ctx.fillStyle = 'yellow';
|
||||
//a.ctx.fill();
|
||||
a._ctx.stroke();
|
||||
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
MeasureText(font, value) {
|
||||
const a = this;
|
||||
|
||||
if (a._ctx == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
a._ctx.font = font;
|
||||
|
||||
const size = a._ctx.measureText(value);
|
||||
|
||||
return {
|
||||
X: a.half(size.width),
|
||||
Y: a.half(size.fontBoundingBoxAscent),
|
||||
W: size.width,
|
||||
H: size.fontBoundingBoxAscent
|
||||
};
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
class Rectangle {
|
||||
constructor(x, y, w, h) {
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
this.W = w;
|
||||
this.H = h;
|
||||
}
|
||||
|
||||
static containsPoint(rectangle, point) {
|
||||
const x2 = (rectangle.X + rectangle.W);
|
||||
const y2 = (rectangle.Y + rectangle.H);
|
||||
|
||||
return ((point.X >= rectangle.X) && (point.X <= x2) && (point.Y >= rectangle.Y) && (point.Y <= y2));
|
||||
}
|
||||
|
||||
static combine(rect1, rect2) {
|
||||
const x2 = Math.max((rect1.X + rect1.W), (rect2.X + rect2.W));
|
||||
const y2 = Math.max((rect1.Y + rect1.H), (rect2.Y + rect2.H));
|
||||
|
||||
const rect = {
|
||||
X: Math.min(rect1.X, rect2.X),
|
||||
Y: Math.min(rect1.Y, rect2.Y),
|
||||
W: 0,
|
||||
H: 0
|
||||
};
|
||||
|
||||
rect.W = x2 - rect.X;
|
||||
rect.H = y2 - rect.Y;
|
||||
|
||||
return rect;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
Canvas = {};
|
||||
|
||||
|
||||
Canvas.create = function (el) {
|
||||
el.innerHTML = "<canvas></canvas>";
|
||||
|
||||
const canvas = el.getElementsByTagName("canvas")[0];
|
||||
const width = (el.innerWidth || el.clientWidth);
|
||||
const height = (el.innerHeight || el.clientHeight);
|
||||
|
||||
canvas.style.width = width + "px";
|
||||
canvas.style.height = height + "px";
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.canvas.width = width;
|
||||
ctx.canvas.height = height;
|
||||
|
||||
return ctx;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class RyzCanvas {
|
||||
constructor(el) {
|
||||
const a = this;
|
||||
|
||||
a.Container = el;
|
||||
a.CTX = Canvas.create(el);
|
||||
a.Padding = {
|
||||
Top: 0,
|
||||
Right: 0,
|
||||
Bottom: 0,
|
||||
Left: 0
|
||||
};
|
||||
|
||||
a.Clear();
|
||||
}
|
||||
|
||||
|
||||
get Width() {
|
||||
return this.CTX.canvas.width;
|
||||
}
|
||||
|
||||
get Height() {
|
||||
return this.CTX.canvas.height;
|
||||
}
|
||||
|
||||
get Rectangle() {
|
||||
return {
|
||||
X: this.Padding.Left,
|
||||
Y: this.Padding.Top,
|
||||
W: (this.Width - (this.Padding.Left + this.Padding.Right)),
|
||||
H: (this.Height - (this.Padding.Top + this.Padding.Bottom))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Clear() {
|
||||
const a = this;
|
||||
|
||||
a.CTX.clearRect(0, 0, a.CTX.canvas.width, a.CTX.canvas.height);
|
||||
}
|
||||
|
||||
DrawRectangle(rectangle, penColour, penWidth) {
|
||||
const a = this;
|
||||
|
||||
// Adjust for pen discrepancy
|
||||
rectangle.X += 0.5;
|
||||
rectangle.Y += 0.5;
|
||||
rectangle.W -= penWidth;
|
||||
rectangle.H -= penWidth;
|
||||
|
||||
a.CTX.beginPath();
|
||||
a.CTX.strokeStyle = penColour;
|
||||
a.CTX.lineWidth = penWidth;
|
||||
a.CTX.rect(rectangle.X, rectangle.Y, rectangle.W, rectangle.H);
|
||||
|
||||
//a.ctx.fillStyle = 'yellow';
|
||||
//a.ctx.fill();
|
||||
a.CTX.stroke();
|
||||
|
||||
return rectangle;
|
||||
}
|
||||
|
||||
MeasureText(font, value) {
|
||||
const a = this;
|
||||
|
||||
a.CTX.font = font;
|
||||
const size = a.CTX.measureText(value);
|
||||
|
||||
return {
|
||||
X: a.half(size.width),
|
||||
Y: a.half(size.fontBoundingBoxAscent),
|
||||
W: size.width,
|
||||
H: size.fontBoundingBoxAscent
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
class Rectangle {
|
||||
constructor(x, y, w, h) {
|
||||
this.X = x;
|
||||
this.Y = y;
|
||||
this.W = w;
|
||||
this.H = h;
|
||||
}
|
||||
|
||||
static containsPoint(rectangle, point) {
|
||||
const x2 = (rectangle.X + rectangle.W);
|
||||
const y2 = (rectangle.Y + rectangle.H);
|
||||
|
||||
return ((point.X >= rectangle.X) && (point.X <= x2) && (point.Y >= rectangle.Y) && (point.Y <= y2));
|
||||
}
|
||||
|
||||
static combine(rect1, rect2) {
|
||||
const x2 = Math.max((rect1.X + rect1.W), (rect2.X + rect2.W));
|
||||
const y2 = Math.max((rect1.Y + rect1.H), (rect2.Y + rect2.H));
|
||||
|
||||
const rect = {
|
||||
X: Math.min(rect1.X, rect2.X),
|
||||
Y: Math.min(rect1.Y, rect2.Y),
|
||||
W: 0,
|
||||
H: 0
|
||||
};
|
||||
|
||||
rect.W = x2 - rect.X;
|
||||
rect.H = y2 - rect.Y;
|
||||
|
||||
return rect;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// Rectangle.containsPoint = function (rectangle, point) {
|
||||
// const x2 = (rectangle.X + rectangle.W);
|
||||
// const y2 = (rectangle.Y + rectangle.H);
|
||||
|
||||
// return ((point.X >= rectangle.X) && (point.X <= x2) && (point.Y >= rectangle.Y) && (point.Y <= y2));
|
||||
// };
|
||||
|
||||
// Rectangle.combine = function(rect1, rect2) {
|
||||
// const x2 = Math.max((rect1.X + rect1.W), (rect2.X + rect2.W));
|
||||
// const y2 = Math.max((rect1.Y + rect1.H), (rect2.Y + rect2.H));
|
||||
|
||||
// const rect = {
|
||||
// X: Math.min(rect1.X, rect2.X),
|
||||
// Y: Math.min(rect1.Y, rect2.Y),
|
||||
// W: 0,
|
||||
// H: 0
|
||||
// };
|
||||
|
||||
// rect.W = x2 - rect.X;
|
||||
// rect.H = y2 - rect.Y;
|
||||
|
||||
// return rect;
|
||||
// };
|
||||
|
||||
|
||||
|
||||
|
||||
// class RyzRectangle {
|
||||
// constructor(x, y, w, h) {
|
||||
// const a = this;
|
||||
|
||||
// a.X = x;
|
||||
// a.Y = y;
|
||||
// a.W = w;
|
||||
// a.H = h;
|
||||
// }
|
||||
|
||||
|
||||
// ContainsPoint(point) {
|
||||
// const a = this;
|
||||
|
||||
// return Rectangle.containsPoint(a.ToModel, point);
|
||||
// }
|
||||
|
||||
// ToModel() {
|
||||
// const a = this;
|
||||
|
||||
// return {
|
||||
// X: a.X,
|
||||
// Y: a.Y,
|
||||
// W: a.W,
|
||||
// H: a.H
|
||||
// };
|
||||
// }
|
||||
|
||||
// ToString() {
|
||||
// const a = this;
|
||||
|
||||
// return "x = " + a.X + ", y = " + a.Y + ", w = " + a.W + ", h = " + a.H;
|
||||
// }
|
||||
|
||||
// }
|
|
@ -0,0 +1,71 @@
|
|||
class RyzGanttChart extends Canvas {
|
||||
constructor(el, options) {
|
||||
super(el);
|
||||
|
||||
const a = this;
|
||||
|
||||
a.Options = Object.assign(a.DefaultOptions, options);
|
||||
|
||||
a.#initialiseComponents();
|
||||
}
|
||||
|
||||
#initialiseComponents() {
|
||||
const a = this;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
get DefaultOptions() {
|
||||
return {
|
||||
DayWidth: 100,
|
||||
RowHeight: 28,
|
||||
HeaderRowHeight: 40
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
// Clear() {
|
||||
// super.Clear();
|
||||
|
||||
// const a = this;
|
||||
|
||||
// a.Invalidate();
|
||||
// }
|
||||
|
||||
// Invalidate() {
|
||||
// const a = this;
|
||||
// a._padding.Left = 3;
|
||||
|
||||
// a.DrawRectangle(a.ClientRectangle, "#B8B8B8", 1);
|
||||
// }
|
||||
|
||||
Load(project) {
|
||||
const a = this;
|
||||
|
||||
a.Clear();
|
||||
|
||||
if (project == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
const tasks = project.ExportTasks();
|
||||
const width = (project.Duration * a.Options.DayWidth);
|
||||
const height = (tasks.length * a.Options.RowHeight) + a.Options.HeaderRowHeight;
|
||||
|
||||
console.log(tasks.length);
|
||||
console.log(height);
|
||||
|
||||
a.Width = width;
|
||||
a.Height = height;
|
||||
|
||||
|
||||
// a.Invalidate();
|
||||
}
|
||||
|
||||
// SetOptions(options) {
|
||||
|
||||
// }
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
class ProjectTaskGrid {
|
||||
constructor(el) {
|
||||
const a = this;
|
||||
|
||||
a.Container = el;
|
||||
|
||||
a.Columns = [
|
||||
null,
|
||||
null,
|
||||
"Task Name",
|
||||
"Duration",
|
||||
"Start",
|
||||
"Finish",
|
||||
"Predecessor",
|
||||
"Resource Names",
|
||||
null
|
||||
];
|
||||
|
||||
a.#initialiseComponents();
|
||||
}
|
||||
|
||||
#initialiseComponents() {
|
||||
const a = this;
|
||||
|
||||
let htmlContent = "";
|
||||
htmlContent += "<table class='ryz-project'>";
|
||||
htmlContent += a.#renderTHead();
|
||||
htmlContent += "<tbody>";
|
||||
htmlContent += a.#renderPlaceholder();
|
||||
htmlContent += "</tbody>";
|
||||
htmlContent += "</table>";
|
||||
|
||||
a.Container.innerHTML = htmlContent;
|
||||
}
|
||||
|
||||
|
||||
Render(model) {
|
||||
const a = this;
|
||||
|
||||
let htmlContent = "";
|
||||
htmlContent += "<table class='ryz-project'>";
|
||||
htmlContent += a.#renderTHead();
|
||||
htmlContent += "<tbody>";
|
||||
|
||||
model.forEach(e => {
|
||||
htmlContent += a.#renderRow(e);
|
||||
});
|
||||
|
||||
htmlContent += "</tbody>";
|
||||
htmlContent += "</table>";
|
||||
|
||||
a.Container.innerHTML = htmlContent;
|
||||
}
|
||||
|
||||
|
||||
#renderTHead() {
|
||||
const a = this;
|
||||
|
||||
let htmlContent = "";
|
||||
htmlContent += "<thead>";
|
||||
htmlContent += "<tr>";
|
||||
|
||||
a.Columns.forEach(e => {
|
||||
htmlContent += "<th>" + (e ?? "") + "</th>";
|
||||
});
|
||||
|
||||
htmlContent += "</tr>";
|
||||
htmlContent += "</thead>";
|
||||
|
||||
return htmlContent;
|
||||
}
|
||||
|
||||
#renderPlaceholder() {
|
||||
const a = this;
|
||||
|
||||
let htmlContent = "";
|
||||
htmlContent += "<tr>";
|
||||
htmlContent += "<td></td>";
|
||||
htmlContent += "<td colspan='" + (a.Columns.length - 1) + "' class='c'>Loading...</td>";
|
||||
htmlContent += "</tr>";
|
||||
|
||||
return htmlContent;
|
||||
}
|
||||
|
||||
#renderRow(e) {
|
||||
const a = this;
|
||||
|
||||
let htmlContent = "";
|
||||
|
||||
if (e.IsCollated == true) {
|
||||
htmlContent += "<tr class='b'>";
|
||||
} else {
|
||||
htmlContent += "<tr>";
|
||||
}
|
||||
|
||||
htmlContent += "<td class='c'>" + e.Order + "</td>";
|
||||
htmlContent += "<td></td>";
|
||||
htmlContent += "<td>";
|
||||
|
||||
for (let i=0; i<e.Level; i++) {
|
||||
htmlContent += "<span class='i'></span>";
|
||||
}
|
||||
|
||||
htmlContent += e.Name;
|
||||
htmlContent += "</td>";
|
||||
htmlContent += "<td>" + e.Duration + " day" + (parseInt(e.Duration) == 1 ? "" : "s") + "</td>";
|
||||
htmlContent += "<td class='c'>" + new Date(e.StartDate).toLocaleDateString() + "</td>";
|
||||
htmlContent += "<td class='c'>" + new Date(e.FinishDate).toLocaleDateString() + "</td>";
|
||||
htmlContent += "<td class='c'>" + (e.PredecessorTaskNo ?? "") + "</td>";
|
||||
htmlContent += "<td></td>";
|
||||
htmlContent += "<td></td>";
|
||||
htmlContent += "</tr>";
|
||||
|
||||
return htmlContent;
|
||||
}
|
||||
|
||||
}
|
|
@ -7,11 +7,13 @@
|
|||
<meta name="description" content="" />
|
||||
<meta name="keyword" content="" />
|
||||
|
||||
<script src="ryzjsext.min.js"></script>
|
||||
<script src="javascript-extensions/ryz-js-ext-canvas.js"></script>
|
||||
<script src="javascript-extensions/ryz-js-ext-rectangle.js"></script>
|
||||
<script src="build/ryzjsext.min.js"></script>
|
||||
<script src="canvas.js"></script>
|
||||
<!-- <script src="ryz-js-ext-rectangle.js"></script> -->
|
||||
|
||||
<script src="ryzproj.js"></script>
|
||||
<script src="project-taskgrid.js"></script>
|
||||
<script src="project-ganttchart.js"></script>
|
||||
<link href="ryzproj.css" rel="stylesheet" />
|
||||
|
||||
<title></title>
|
||||
|
@ -32,159 +34,136 @@ body {
|
|||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script>
|
||||
|
||||
var project1 = new RyzProject({ Name: "New Project 1" });
|
||||
|
||||
project1.AddTask({
|
||||
ID: 1,
|
||||
Name: "Task A",
|
||||
StartDelay: 0,
|
||||
Duration: 1,
|
||||
PredecessorTaskID: null,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 2,
|
||||
Name: "Task B",
|
||||
StartDelay: 1,
|
||||
Duration: 1,
|
||||
PredecessorTaskID: 1,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 5,
|
||||
Name: "Task B1",
|
||||
StartDelay: 4,
|
||||
Duration: 1,
|
||||
PredecessorTaskID: 2,
|
||||
IsCollated: true,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 6,
|
||||
Name: "Task B11",
|
||||
StartDelay: 0,
|
||||
Duration: 1,
|
||||
PredecessorTaskID: null,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: 5
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 7,
|
||||
Name: "Task B12",
|
||||
StartDelay: 0,
|
||||
Duration: 7,
|
||||
PredecessorTaskID: null,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: 5,
|
||||
Progress: 50
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 8,
|
||||
Name: "Task E",
|
||||
StartDelay: 3,
|
||||
Duration: 1,
|
||||
PredecessorTaskID: null,
|
||||
IsCollated: true,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 9,
|
||||
Name: "Task E1",
|
||||
StartDelay: 3,
|
||||
Duration: 1,
|
||||
PredecessorTaskID: null,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: 8
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 3,
|
||||
Name: "Task C",
|
||||
StartDelay: 5,
|
||||
Duration: 1,
|
||||
PredecessorTaskID: 8,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 4,
|
||||
Name: "Task D",
|
||||
StartDelay: 1,
|
||||
Duration: 1,
|
||||
PredecessorTaskID: 3,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.Invalidate();
|
||||
|
||||
// console.log(gantt1.ExportTasks());
|
||||
|
||||
Document.ready(async function() {
|
||||
const taskGrid1 = document.getElementById("projectTaskGrid1");
|
||||
const ganttChart1 = document.getElementById("projectGanttChart1");
|
||||
|
||||
|
||||
console.log(new Date(project1.StartDate).toLocaleDateString() + " - " + new Date(project1.FinishDate).toLocaleDateString());
|
||||
|
||||
console.log(project1.Duration);
|
||||
|
||||
taskGrid1.innerHTML = project1.RenderTaskGrid();
|
||||
|
||||
project1.RenderGanttChart(ganttChart1);
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="row">
|
||||
<div class="column">
|
||||
|
||||
<table class="ryz-project">
|
||||
<thead>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th></th>
|
||||
<th>Task Name</th>
|
||||
<th>Duration</th>
|
||||
<th>Start</th>
|
||||
<th>Finish</th>
|
||||
<th>Predecessor</th>
|
||||
<th>Resource Names</th>
|
||||
<th></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="projectTaskGrid1">
|
||||
<tr>
|
||||
<td></td>
|
||||
<td colspan="8" class="c">Loading...</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<div class="column" id="taskGrid1">
|
||||
|
||||
</div>
|
||||
<div class="column">
|
||||
<div class="column" style="overflow: auto;">
|
||||
|
||||
<div id="projectGanttChart1" style="width:100%; height: 100%;"></div>
|
||||
<!-- <div style="width:100%; height: 100%; overflow: scroll;"> -->
|
||||
<div id="ganttChart1" style="width:100%; height: 100%;"></div>
|
||||
<!-- </div> -->
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script>
|
||||
|
||||
Document.ready(async function() {
|
||||
var project1 = new RyzProject({ Name: "New Project 1" });
|
||||
var taskGrid1 = null;
|
||||
var ganttChart1 = null;
|
||||
|
||||
|
||||
project1.AddTask({
|
||||
ID: 1,
|
||||
Name: "Task A",
|
||||
StartDelay: 0,
|
||||
Duration: Math.randomN(1, 30),
|
||||
PredecessorTaskID: null,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 2,
|
||||
Name: "Task B",
|
||||
StartDelay: Math.randomN(0, 5),
|
||||
Duration: Math.randomN(1, 30),
|
||||
PredecessorTaskID: 1,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 5,
|
||||
Name: "Task B1",
|
||||
StartDelay: Math.randomN(0, 5),
|
||||
Duration: Math.randomN(1, 30),
|
||||
PredecessorTaskID: 2,
|
||||
IsCollated: true,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 6,
|
||||
Name: "Task B11",
|
||||
StartDelay: Math.randomN(0, 5),
|
||||
Duration: Math.randomN(1, 30),
|
||||
PredecessorTaskID: null,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: 5
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 7,
|
||||
Name: "Task B12",
|
||||
StartDelay: Math.randomN(0, 5),
|
||||
Duration: Math.randomN(1, 30),
|
||||
PredecessorTaskID: null,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: 5,
|
||||
Progress: 50
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 8,
|
||||
Name: "Task E",
|
||||
StartDelay: Math.randomN(0, 5),
|
||||
Duration: Math.randomN(1, 30),
|
||||
PredecessorTaskID: null,
|
||||
IsCollated: true,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 9,
|
||||
Name: "Task E1",
|
||||
StartDelay: Math.randomN(0, 5),
|
||||
Duration: Math.randomN(1, 30),
|
||||
PredecessorTaskID: null,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: 8
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 3,
|
||||
Name: "Task C",
|
||||
StartDelay: Math.randomN(0, 5),
|
||||
Duration: Math.randomN(1, 30),
|
||||
PredecessorTaskID: 8,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.AddTask({
|
||||
ID: 4,
|
||||
Name: "Task D",
|
||||
StartDelay: Math.randomN(0, 5),
|
||||
Duration: Math.randomN(1, 30),
|
||||
PredecessorTaskID: 3,
|
||||
IsCollated: false,
|
||||
CollatedTaskID: null
|
||||
});
|
||||
|
||||
project1.Invalidate();
|
||||
console.log(new Date(project1.StartDate).toLocaleDateString() + " - " + new Date(project1.FinishDate).toLocaleDateString() + " [" + project1.Duration + "]");
|
||||
|
||||
|
||||
const taskData = project1.ExportTasks();
|
||||
|
||||
if (taskGrid1 == null) taskGrid1 = new ProjectTaskGrid(document.getElementById("taskGrid1"));
|
||||
taskGrid1.Render(taskData);
|
||||
|
||||
if (ganttChart1 == null) ganttChart1 = new RyzGanttChart(document.getElementById("ganttChart1"), {});
|
||||
ganttChart1.Load(project1);
|
||||
|
||||
|
||||
});
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
74
ryzproj.js
74
ryzproj.js
|
@ -1,15 +1,3 @@
|
|||
class RyzGanttChart extends RyzCanvas {
|
||||
constructor(el) {
|
||||
super(el);
|
||||
|
||||
this.Padding.Left = 3;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
class RyzProject {
|
||||
constructor(options) {
|
||||
const a = this;
|
||||
|
@ -361,55 +349,6 @@ class RyzProject {
|
|||
a.Tasks.sortTree("Tasks", "StartDelay");
|
||||
}
|
||||
|
||||
RenderTaskGrid() {
|
||||
const a = this;
|
||||
let htmlContent = "";
|
||||
|
||||
const result = a.ExportTasks();
|
||||
result.forEach(e => {
|
||||
if (e.IsCollated == true) {
|
||||
htmlContent += "<tr class='b'>";
|
||||
} else {
|
||||
htmlContent += "<tr>";
|
||||
}
|
||||
|
||||
htmlContent += "<td class='c'>" + e.Order + "</td>";
|
||||
htmlContent += "<td></td>";
|
||||
htmlContent += "<td>";
|
||||
|
||||
for (let i=0; i<e.Level; i++) {
|
||||
htmlContent += "<span class='i'></span>";
|
||||
}
|
||||
|
||||
htmlContent += e.Name;
|
||||
htmlContent += "</td>";
|
||||
htmlContent += "<td>" + e.Duration + " day" + (parseInt(e.Duration) == 1 ? "" : "s") + "</td>";
|
||||
htmlContent += "<td class='c'>" + new Date(e.StartDate).toLocaleDateString() + "</td>";
|
||||
htmlContent += "<td class='c'>" + new Date(e.FinishDate).toLocaleDateString() + "</td>";
|
||||
htmlContent += "<td class='c'>" + (e.PredecessorTaskNo ?? "") + "</td>";
|
||||
htmlContent += "<td></td>";
|
||||
htmlContent += "<td></td>";
|
||||
htmlContent += "</tr>";
|
||||
});
|
||||
|
||||
return htmlContent;
|
||||
}
|
||||
|
||||
RenderGanttChart(el) {
|
||||
const a = this;
|
||||
|
||||
const ganttCanvas = new RyzGanttChart(el);
|
||||
|
||||
|
||||
ganttCanvas.DrawRectangle(ganttCanvas.Rectangle, "#B8B8B8", 1);
|
||||
|
||||
ganttCanvas.DrawRectangle({ X: 50, Y: 50, W: 100, H: 100 }, "#B8B8B8", 3);
|
||||
|
||||
// console.log(ganttCanvas.Width);
|
||||
|
||||
|
||||
}
|
||||
|
||||
#log(message) {
|
||||
console.log(message);
|
||||
}
|
||||
|
@ -432,7 +371,7 @@ class RyzProject {
|
|||
|
||||
let workHours = 0;
|
||||
let date = new Date(array[i].StartDate);
|
||||
for (let i=0; i<array[i].Duration; i++) {
|
||||
for (let x=0; x<array[i].Duration; x++) {
|
||||
const d = date.getDay();
|
||||
|
||||
workHours += a.Project.WorkHours[d];
|
||||
|
@ -463,11 +402,15 @@ class RyzProject {
|
|||
let node2 = array.select("CollatedTaskID", array[index].ID);
|
||||
if (node2.length <= 0) {
|
||||
// No children
|
||||
array[index].Duration = 0;
|
||||
|
||||
return new Date(array[index].StartDate);
|
||||
}
|
||||
|
||||
// Not ready, calculation pending
|
||||
if (node2.any("FinishDate", null)) {
|
||||
array[index].Duration = 0;
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -480,10 +423,7 @@ class RyzProject {
|
|||
|
||||
array[index].Progress = Math.average(node2.toList("Progress"));
|
||||
array[index].FinishDate = new Date(node2FinishDate);
|
||||
array[index].Duration = Date.diffDays(array[index].StartDate, array[index].FinishDate);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
Loading…
Reference in New Issue