Renamed js-ext files

WIP: project task grid and gantt chart
This commit is contained in:
Ray 2023-12-29 19:33:42 +00:00
parent fc4f172e15
commit d30d60ae91
17 changed files with 534 additions and 410 deletions

View File

@ -11,4 +11,6 @@ cd..
type ryzjsext.min.tmp >> ryzjsext.min.js
move ryzjsext.min.js build/ryzjsext.min.js
del ryzjsext.min.tmp

View File

@ -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)}};

179
canvas.js Normal file
View File

@ -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
};
}
}

View File

@ -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;
};
}

View File

@ -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
};
}
}

View File

@ -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;
// }
// }

71
project-ganttchart.js Normal file
View File

@ -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) {
// }
}

117
project-taskgrid.js Normal file
View File

@ -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;
}
}

View File

@ -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>

View File

@ -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);
}
}
}