Refactored to avoid ES6 as bundler will not handle private modifiers

Added build script for project
Added canvas to js-extensions
This commit is contained in:
Ray 2024-01-07 00:13:44 +00:00
parent a51b73ee5d
commit e062f56b65
15 changed files with 724 additions and 634 deletions

View File

@ -1,5 +1,6 @@
del ryzjsext.min.js
del ryzjsext.min.tmp
del build/ryzjsext.min.js
cd javascript-extensions

38
build-ryzproj.bat Normal file
View File

@ -0,0 +1,38 @@
del ryzproj.min.js
del ryzproj.min.tmp
del build/ryzproj.min.js
cd project
type version.txt >> ../ryzproj.min.js
"C:\B\Portable Files (dev)\Google Closure Compiler\closure-compiler-v20231112.jar" --js project.js --js_output_file ../ryzproj.min.tmp
cd..
type ryzproj.min.tmp >> ryzproj.min.js
move ryzproj.min.js build/ryzproj.min.js
del ryzproj.min.tmp
del ryzproj.bundle.min.js
del ryzproj.bundle.min.tmp
del ryzproj.bundle.min.js
cd project
type version-bundle.txt >> ../ryzproj.bundle.min.js
"C:\B\Portable Files (dev)\Google Closure Compiler\closure-compiler-v20231112.jar" --js *.js --js_output_file ../ryzproj.bundle.min.tmp
cd..
type ryzproj.bundle.min.tmp >> ryzproj.bundle.min.js
move ryzproj.bundle.min.js build/ryzproj.bundle.min.js
del ryzproj.bundle.min.tmp

16
build/ryzjsext.min.js vendored
View File

@ -1,13 +1,25 @@
/**
* Ray's JavaScript Extension
* @version v0.1.0.071 (2023/12/27 1551)
* @version v0.1.0.088 (2024/01/06 1933)
*/
Array.toFlatten=function(a,b,c){for(let d=0;d<a.length;d++)c.push(a[d]),0<a[d][b].length&&Array.toFlatten(a[d][b],b,c)};Array.prototype.addRange=function(a){if(null==a)return this;for(let b=0;b<a.length;b++)this.push(a[b]);return this};Array.prototype.any=function(a,b){return 0<this.count(a,b)};Array.prototype.copy=function(){return JSON.parse(JSON.stringify(this))};Array.prototype.count=function(a,b){let c=0;for(let d=0;d<this.length;d++)"undefined"!=typeof this[d][a]&&this[d][a]==b&&c++;return c};
Array.prototype.countMany=function(...a){let b=0;a.forEach(c=>{b+=this.count(c.propName,c.value)});return b};Array.prototype.flatten=function(a){let b=[];Array.toFlatten(this,a,b);return b};Array.prototype.index=function(a,b){for(let c=0;c<this.length;c++)if("undefined"!=typeof this[c][a]&&this[c][a]==b)return c;return-1};Array.prototype.insert=function(a,b){0>a?this.splice(0,0,b):a>=this.length?this.push(b):this.splice(a,0,b);return this};
Array.prototype.joinIfNotNullOrWhitespace=function(a){let b="";for(let c=0;c<this.length;c++)String.isNullOrWhitespace(this[c])||(String.isNullOrWhitespace(b)||(b+=a),b+=this[c]);return b};Array.prototype.first=function(a,b){for(let c=0;c<this.length;c++)if("undefined"!=typeof this[c][a]&&this[c][a]==b)return this[c];return null};Array.prototype.forEachTree=function(a,b){for(let c=0;c<this.length&&!1!==b(this[c])&&(0>=this[c][a].length||!1!==this[c][a].forEachTree(a,b));c++);};
Array.prototype.indexes=function(a,b){let c=[];for(let d=0;d<this.length;d++)"undefined"!=typeof this[d][a]&&this[d][a]==b&&c.push(d);return c};Array.prototype.orderBy=function(a){this.sort(function(b,c){return b[a]<c[a]?-1:b[a]>c[a]?1:0});return this};Array.prototype.orderByDesc=function(a){this.sort(function(b,c){return b[a]<c[a]?1:b[a]>c[a]?-1:0});return this};
Array.prototype.remove=function(a){let b=[];for(let c=0;c<this.length;c++)this[c]==a&&b.push(c);for(a=b.length-1;0<=a;a--)this.removeAt(b[a]);return this};Array.prototype.removeAt=function(a){if(0>a||a>=this.length)return this;this.splice(a,1);return this};Array.prototype.removeRange=function(a){for(let b=0;b<a.length;b++)this.remove(a[b]);return this};Array.prototype.select=function(a,b){let c=[];for(let d=0;d<this.length;d++)"undefined"!=typeof this[d][a]&&this[d][a]==b&&c.push(this[d]);return c};
Array.prototype.selectMany=function(...a){let b=this;a.forEach(c=>{b=b.select(c.propName,c.value)});return b};Array.prototype.toList=function(a){let b=[];this.forEach(c=>{b.push(c[a])});return b};Array.prototype.sortTree=function(a,b){this.orderBy(b);for(let c=0;c<this.length;c++)0>=this[c][a].length||this[c][a].orderBy(b)};Boolean.isFalse=function(a){return String.isNullOrUndefined(a)?!0:a.toString().containsCI("false","f","y","0","x")};Boolean.isTrue=function(a){return String.isNullOrUndefined(a)?!1:a.toString().containsCI("true","t","n","1","o")};Boolean.ifTrue=function(a,b,c){return Boolean.isTrue(a)?b:c};Date.addDays=function(a,b){a=new Date(a);a.addDays(b);return a};Date.addMonths=function(a,b){a=new Date(a);a.addMonths(b);return a};Date.addYears=function(a,b){a=new Date(a);a.addYears(b);return a};Date.max=function(a,b){return null==a?b:null==b?a:new Date(a)<=new Date(b)?new Date(b):new Date(a)};Date.min=function(a,b){return null==a?b:null==b?a:new Date(a)<=new Date(b)?new Date(a):new Date(b)};Date.diffDays=function(a,b){return Math.ceil(((new Date(b)).getTime()-(new Date(a)).getTime())/864E5)};
Array.prototype.selectMany=function(...a){let b=this;a.forEach(c=>{b=b.select(c.propName,c.value)});return b};Array.prototype.toList=function(a){let b=[];this.forEach(c=>{b.push(c[a])});return b};Array.prototype.sortTree=function(a,b){this.orderBy(b);for(let c=0;c<this.length;c++)0>=this[c][a].length||this[c][a].orderBy(b)};Boolean.isFalse=function(a){return String.isNullOrUndefined(a)?!0:a.toString().containsCI("false","f","y","0","x")};Boolean.isTrue=function(a){return String.isNullOrUndefined(a)?!1:a.toString().containsCI("true","t","n","1","o")};Boolean.ifTrue=function(a,b,c){return Boolean.isTrue(a)?b:c};class Canvas{constructor(a){this.container=a;this.canvasContainer=this.flowContainer=this.ctx=null;this.autoSize=!0;this.padding={Top:0,Right:0,Bottom:0,Left:0};this.initialiseComponents()}initialiseComponents(){null!=this.container&&(this.container.innerHTML="<div class='border'><canvas></canvas></div>",null!=this.container&&(this.container.style.width="100%",this.container.style.height="100%",this.flowContainer=this.container.getElementsByTagName("div")[0],this.canvasContainer=this.flowContainer.getElementsByTagName("canvas")[0],
this.ctx=this.canvasContainer.getContext("2d")),this.AutoSize=this.AutoSize,this.Width=this.Width,this.Height=this.Height,this.Clear())}get AutoSize(){return this.autoSize}set AutoSize(a){this.autoSize=a;null!=this.flowContainer&&(1==a?this.flowContainer.style.overflow="hidden":(this.flowContainer.style.overflowX=this.Width>=this.ClientWidth?"hidden":"auto",this.flowContainer.style.overflowY=this.Height>=this.ClientHeight?"hidden":"auto"))}get ClientHeight(){return null==this.canvasContainer?0:this.getHeight(this.canvasContainer)}set ClientHeight(a){null!=
this.canvasContainer&&(this.canvasContainer.style.height=a+"px");null!=this.ctx&&(this.ctx.canvas.height=a)}get ClientWidth(){return null==this.canvasContainer?0:this.getWidth(this.canvasContainer)}set ClientWidth(a){null!=this.canvasContainer&&(this.canvasContainer.style.width=a+"px");null!=this.ctx&&(this.ctx.canvas.width=a)}get Height(){return null==this.container?0:this.getHeight(this.container)}set Height(a){null!=this.container&&(this.container.style.height=a+"px");null!=this.flowContainer&&
(this.flowContainer.style.height=a+"px");1==this.AutoSize&&(this.ClientHeight=a)}get Width(){return null==this.container?0:this.getWidth(this.container)}set Width(a){null!=this.container&&(this.container.style.width=a+"px");null!=this.flowContainer&&(this.flowContainer.style.width=a+"px");1==this.AutoSize&&(this.ClientWidth=a)}get Size(){return{W:this.Width,H:this.Height}}get ClientRectangle(){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)}}get Rectangle(){return{X:0,Y:0,W:this.Width,H:this.Height}}Clear(){null!=this.ctx&&this.ctx.clearRect(0,0,this.ctx.canvas.width,this.ctx.canvas.height)}DrawArrowS(a,b,c){null!=this.ctx&&(c=Object.assign({LineWidth:1,LineDash:[],FillColour:null},c),a.X+=.5,a.Y+=.5,a.W-=c.LineWidth,a.H-=c.LineWidth,this.ctx.beginPath(),this.ctx.strokeStyle=b,this.ctx.lineWidth=c.LineWidth,this.ctx.setLineDash(c.LineDash),this.ctx.moveTo(a.X,a.Y),this.ctx.lineTo(a.X+a.W,a.Y),this.ctx.lineTo(a.X+
Math.half(a.W),a.Y+a.H),this.ctx.closePath(),null!=c.FillColour&&(this.ctx.fillStyle=c.FillColour,this.ctx.fill()),this.ctx.stroke())}DrawCircle(a,b,c,d,e){if(null!=this.ctx){e=Object.assign({LineWidth:1,LineDash:[],FillColour:null},e);a+=Math.half(c);b+=Math.half(c);var f=Math.half(c);Math.half(c);a+=.5;b+=.5;f-=Math.half(e.LineWidth);Math.half(e.LineWidth);this.ctx.beginPath();this.ctx.strokeStyle=d;this.ctx.lineWidth=e.LineWidth;this.ctx.setLineDash(e.LineDash);this.ctx.arc(a,b,f,0,2*Math.PI,!1);
this.ctx.closePath();null!=e.FillColour&&(this.ctx.fillStyle=e.FillColour,this.ctx.fill());this.ctx.stroke()}}DrawDiamond(a,b,c){null!=this.ctx&&(c=Object.assign({LineWidth:1,LineDash:[],FillColour:null},c),a.X+=.5,a.Y+=.5,a.W-=c.LineWidth,a.H-=c.LineWidth,this.ctx.beginPath(),this.ctx.strokeStyle=b,this.ctx.lineWidth=c.LineWidth,this.ctx.setLineDash(c.LineDash),this.ctx.moveTo(a.X+Math.half(a.W),a.Y),this.ctx.lineTo(a.X+a.W,a.Y+Math.half(a.H)),this.ctx.lineTo(a.X+Math.half(a.W),a.Y+a.H),this.ctx.lineTo(a.X,
a.Y+Math.half(a.H)),this.ctx.closePath(),null!=c.FillColour&&(this.ctx.fillStyle=c.FillColour,this.ctx.fill()),this.ctx.stroke())}DrawRectangle(a,b,c){null!=this.ctx&&(c=Object.assign({LineWidth:1,LineDash:[],FillColour:null},c),a.X+=.5,a.Y+=.5,a.W-=c.LineWidth,a.H-=c.LineWidth,this.ctx.beginPath(),this.ctx.strokeStyle=b,this.ctx.lineWidth=c.LineWidth,this.ctx.setLineDash(c.LineDash),this.ctx.rect(a.X,a.Y,a.W,a.H),null!=c.FillColour&&(this.ctx.fillStyle=c.FillColour,this.ctx.fill()),this.ctx.closePath(),
this.ctx.stroke())}DrawLine(a,b,c,d,e,f){null!=this.ctx&&(f=Object.assign({LineWidth:1,LineDash:[]},f),b-=.5,this.ctx.beginPath(),this.ctx.strokeStyle=e,this.ctx.lineWidth=f.LineWidth,this.ctx.setLineDash(f.LineDash),this.ctx.moveTo(a,b),this.ctx.lineTo(c,d),this.ctx.stroke())}DrawLines(a,b,c){if(null!=this.ctx&&null!=a&&!(0>=a.length)){c=Object.assign({LineWidth:1,LineDash:[]},c);this.ctx.beginPath();this.ctx.strokeStyle=b;this.ctx.lineWidth=c.LineWidth;this.ctx.setLineDash(c.LineDash);this.ctx.moveTo(a[0].X,
a[0].Y);for(b=1;b<a.length;b++)this.ctx.lineTo(a[b].X,a[b].Y);this.ctx.stroke()}}DrawHorizontalLine(a,b,c,d,e){null!=this.ctx&&(e=Object.assign({LineWidth:1,LineDash:[]},e),b-=.5,this.ctx.beginPath(),this.ctx.strokeStyle=d,this.ctx.lineWidth=e.LineWidth,this.ctx.setLineDash(e.LineDash),this.ctx.moveTo(a,b),this.ctx.lineTo(a+c,b),this.ctx.stroke())}DrawText(a,b,c,d,e,f){null!=this.ctx&&(f=Object.assign({Align:"left"},f),this.ctx.font=d,this.ctx.fillStyle=e,this.ctx.textAlign=f.Align,this.ctx.textBaseline=
"top",this.ctx.fillText(c,a,b))}DrawVerticalLine(a,b,c,d,e){null!=this.ctx&&(e=Object.assign({LineWidth:1,LineDash:[]},e),a-=.5,b-=e.LineWidth,this.ctx.beginPath(),this.ctx.strokeStyle=d,this.ctx.lineWidth=e.LineWidth,this.ctx.setLineDash(e.LineDash),this.ctx.moveTo(a,b),this.ctx.lineTo(a,b+c),this.ctx.stroke())}FillText(a,b,c,d,e){if(null!=this.ctx){e=Object.assign({Align:"center",VAlign:"middle"},e);this.ctx.font=c;this.ctx.fillStyle=d;this.ctx.textAlign=e.Align;this.ctx.textBaseline="top";c=this.ctx.measureText(b);
d=a.X+Math.half(a.W);var f=a.Y;switch(e.VAlign){case "center":case "middle":f+=Math.half(a.H-c.fontBoundingBoxDescent)+c.fontBoundingBoxAscent;break;case "bottom":f+=a.H-c.fontBoundingBoxDescent}this.ctx.fillText(b,d,f)}}Invalidate(){this.AutoSize=this.AutoSize;this.Width=this.Width;this.Height=this.Height}MeasureText(a,b){if(null==this.ctx)return null;this.ctx.font=a;a=this.ctx.measureText(b);return{W:a.width,H:Math.round(a.fontBoundingBoxDescent+a.fontBoundingBoxAscent)}}getWidth(a){return a.offsetWidth||
a.innerWidth||a.clientWidth}getHeight(a){return a.offsetHeight||a.innerHeight||a.clientHeight}};Date.addDays=function(a,b){a=new Date(a);a.addDays(b);return a};Date.addMonths=function(a,b){a=new Date(a);a.addMonths(b);return a};Date.addYears=function(a,b){a=new Date(a);a.addYears(b);return a};Date.max=function(a,b){return null==a?b:null==b?a:new Date(a)<=new Date(b)?new Date(b):new Date(a)};Date.min=function(a,b){return null==a?b:null==b?a:new Date(a)<=new Date(b)?new Date(a):new Date(b)};Date.diffDays=function(a,b){return Math.ceil(((new Date(b)).getTime()-(new Date(a)).getTime())/864E5)};
Date.today=function(){let a=new Date;a.setHours(0);a.setMinutes(0);a.setSeconds(0);a.setMilliseconds(0);return a};Date.prototype.addDays=function(a){this.setDate(this.getDate()+parseInt(a))};Date.prototype.addMonths=function(a){this.setMonth(this.getMonth()+parseInt(a))};Date.prototype.addYears=function(a){this.setFullYear(this.getFullYear()+parseInt(a))};
Date.prototype.toCString=function(a){a=a.replace("fffffff",this.getMilliseconds().toString().padStart(7,"0"));a=a.replace("ffffff",this.getMilliseconds().toString().padStart(6,"0"));a=a.replace("fffff",this.getMilliseconds().toString().padStart(5,"0"));a=a.replace("yyyy",this.getFullYear().toString().padStart(4,"0"));a=a.replace("MMMM","{1}");a=a.replace("dddd","{2}");a=a.replace("ffff",this.getMilliseconds().toString().padStart(4,"0"));a=a.replace("yyy",this.getFullYear().toString().padStart(3,"0"));
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",

24
build/ryzproj.bundle.min.js vendored Normal file
View File

@ -0,0 +1,24 @@
/**
* Ray's Projects (Bundled with TaskGrid and GanttChart)
* @version v0.1.0.104 (2023/12/27 1051)
*/
class RyzGanttChart{constructor(b,a){this.Canvas=new Canvas(b);this.Options=Object.assign(this.DefaultOptions,a);this.Debug=!1;this.StartDate=this.Project=null}get DefaultOptions(){return{DayWidth:24,HeaderRow:{Height:[21,21]},Row:{Height:28,Task:{Height:13,PaddingTop:6,BorderColour:"#555555",FillColour:"#9CC2E6"},CollatedTask:{Height:3,PaddingTop:11,BorderColour:"#555555",FillColour:"#555555"}},Line:{Margin:5,Colour:"#555555",Width:1,ArrowSize:5},DateFont:"7pt sans-serif",DateForeColour:"#636363",
BorderWidth:1,BorderColour:"#B8B8B8",BorderDashPattern:[1,3]}}get HeaderHeight(){return this.Options.HeaderRow.Height[0]+this.Options.HeaderRow.Height[1]}Invalidate(){this.Canvas.Clear();if(null!=this.Project){var b=this.Project.ExportTasks(),a=(this.Project.Duration+2)*this.Options.DayWidth,c=b.length*this.Options.Row.Height+this.HeaderHeight;this.AutoSize=!1;this.ClientWidth=a;this.ClientHeight=c;this.Canvas.Invalidate();this.drawChartLabel(this.Project);this.drawTasks(b);this.drawLines(b)}}Load(b){this.Canvas.Clear();
null!=b&&(this.Project=b,this.StartDate=new Date(b.StartDate),this.Invalidate())}drawChartLabel(b){var a=this.Canvas.ClientWidth;const c=this.Canvas.ClientHeight,e=b.Duration+2;let d=new Date(this.StartDate);d.addDays(-1);for(var f=1;f<e;f++)this.Canvas.DrawVerticalLine(this.Options.DayWidth*f,this.Options.HeaderRow.Height[0]+this.Options.BorderWidth,this.Options.HeaderRow.Height[1]-2*this.Options.BorderWidth,this.Options.BorderColour,{});this.Canvas.DrawHorizontalLine(0,this.Options.HeaderRow.Height[0],
a,this.Options.BorderColour);this.Canvas.DrawHorizontalLine(0,this.HeaderHeight-this.Options.BorderWidth,a,this.Options.BorderColour);for(a=0;a<e;a++){f=Date.addDays(d,a);const h=this.Options.DayWidth*a;if(1==f.getDate()){var k=this.Canvas.MeasureText(this.Options.DateFont,"#"),g=h+2;k=Math.half(this.Options.HeaderRow.Height[0]-k.H);this.Canvas.DrawText(g,k,f.toCString("MMMM"),this.Options.DateFont,this.Options.DateForeColour)}g={X:h,Y:this.Options.HeaderRow.Height[1],W:this.Options.DayWidth-this.Options.BorderWidth,
H:this.Options.HeaderRow.Height[1]-2*this.Options.BorderWidth};this.Canvas.FillText(g,f.getDate(),this.Options.DateFont,this.Options.DateForeColour);this.Debug&&this.Canvas.DrawRectangle(g,"red",{});g=c-this.Options.BorderWidth;b.Project.StartOfWeek==f.getDay()?this.Canvas.DrawVerticalLine(h,this.HeaderHeight,g,this.Options.BorderColour,{}):this.Canvas.DrawVerticalLine(h,this.HeaderHeight,g,this.Options.BorderColour,{LineDash:this.Options.BorderDashPattern})}}drawTasks(b){for(let a=0;a<b.length;a++){const c=
1==b[a].IsCollated?this.Options.Row.CollatedTask:this.Options.Row.Task,e=this.getTaskRectangle(b[a],c);0>=b[a].Duration?this.Canvas.DrawDiamond(e,c.BorderColour,{FillColour:c.FillColour}):this.Canvas.DrawRectangle(e,c.BorderColour,{FillColour:c.FillColour})}}drawLines(b){for(let e=0;e<b.length;e++){if(null==b[e].PredecessorTaskID)continue;if(null==b[e].PredecessorTaskNo)continue;var a=this.getTaskRectangle(b[e],1==b[e].IsCollated?this.Options.Row.CollatedTask:this.Options.Row.Task),c=b.first("Order",
b[e].PredecessorTaskNo);if(null==c)continue;c=this.getTaskRectangle(c,1==c.IsCollated?this.Options.Row.CollatedTask:this.Options.Row.Task);let d=[];d.push({X:c.X+c.W,Y:c.Y+Math.half(c.H)});d.push({X:a.X+this.Options.Line.Margin,Y:c.Y+Math.half(c.H)});d.push({X:a.X+this.Options.Line.Margin,Y:a.Y-this.Options.Line.Margin});d.push({X:a.X+this.Options.Line.Margin,Y:a.Y});this.Canvas.DrawLines(d,this.Options.Line.Colour,{LineWidth:this.Options.Line.Width});a={X:a.X+this.Options.Line.Margin-Math.half(this.Options.Line.ArrowSize),
Y:a.Y-this.Options.Line.ArrowSize,W:this.Options.Line.ArrowSize,H:this.Options.Line.ArrowSize};this.Canvas.DrawArrowS(a,this.Options.Line.Colour,{FillColour:this.Options.Line.Colour})}}getTaskRectangle(b,a){const c=b.Order-1;0>=b.Duration?(b={X:this.Options.DayWidth*(Date.diffDays(this.StartDate,b.StartDate)+1),Y:this.HeaderHeight+this.Options.Row.Height*c+a.PaddingTop,W:a.Height,H:a.Height},b.X-=Math.half(b.W)):b={X:this.Options.DayWidth*(Date.diffDays(this.StartDate,b.StartDate)+1),Y:this.HeaderHeight+
this.Options.Row.Height*c+a.PaddingTop,W:this.Options.DayWidth*b.Duration,H:a.Height};return b}};class RyzProject{constructor(b){this.Project=Object.assign(this.newProject,b);this.Tasks=[];this.initialiseComponents()}initialiseComponents(){}get NewTask(){return{ID:null,Name:"",Description:"",Tag:null,StartDelay:0,Duration:1,PredecessorTaskID:null,IsCollated:!1,CollatedTaskID:null,ActuWorkHours:null,Progress:0,Resources:[]}}get StartDate(){return new Date(this.Project.StartDate)}get FinishDate(){let b=new Date(this.Project.StartDate);this.ExportTasks().forEach(a=>{null!=a.FinishDate&&(b=Date.max(b,
a.FinishDate))});return b}get Duration(){return Date.diffDays(this.StartDate,this.FinishDate)}get newProject(){return{Name:"",Description:"",StartDate:Date.today(),Tag:null,StartOfWeek:1,WorkHours:[0,7.5,7.5,7.5,7.5,7.5,0]}}get newTaskNode(){return{Order:null,ID:null,Name:"",Description:"",Tag:null,StartDate:null,FinishDate:null,StartDelay:0,Duration:1,PredecessorTaskID:null,IsCollated:!1,CollatedTaskID:null,CalcWorkHours:0,ActuWorkHours:null,Progress:0,Resources:[],Level:0,PredecessorTaskNo:null,
Tasks:[]}}AddTask(b){b=Object.assign(this.NewTask,b);b=Object.assign(this.newTaskNode,b);if(null==b.PredecessorTaskID&&null==b.CollatedTaskID)this.Tasks.push(b);else if(null!=b.PredecessorTaskID){var a=this.FindTask(b.PredecessorTaskID);null!=a?a.Tasks.push(b):this.log("Task not found ("+b.PredecessorTaskID+")")}else null!=b.CollatedTaskID?(a=this.FindTask(b.CollatedTaskID),null!=a?a.Tasks.push(b):this.log("Task not found ("+b.CollatedTaskID+")")):this.log("Task not found ("+b.ID+")")}ClearTasks(){this.Tasks=
[]}ExportTasks(){let b=this.Tasks.copy().flatten("Tasks");for(var a=0;a<b.length;a++)b[a].Order=a+1,delete b[a].Tasks;return b}FindTask(b){let a=null;this.Tasks.forEachTree("Tasks",function(c){return c.ID==b?(a=c,!1):!0});return a}GetNodeType(b){return null==b?0:null==b.PredecessorTaskID&&null==b.CollatedTaskID&&0==b.IsCollated?1:null==b.PredecessorTaskID&&null==b.CollatedTaskID&&1==b.IsCollated?2:null!=b.PredecessorTaskID&&null==b.CollatedTaskID&&0==b.IsCollated?3:null!=b.PredecessorTaskID&&null==
b.CollatedTaskID&&1==b.IsCollated?4:null!=b.CollatedTaskID&&0==b.IsCollated?5:null!=b.CollatedTaskID&&1==b.IsCollated?6:0}Invalidate(){let b=!1;this.Recalculate()||(b=!1);return b}Recalculate(){let b=!1;this.Sort();let a=this.Tasks.flatten("Tasks");for(var c=0;c<a.length;c++)a[c].Order=c+1,a[c].StartDate=null,a[c].FinishDate=null,a[c].CalcWorkHours=null;for(var e=0;128>e;e++){if(0>=a.copy().countMany({propName:"StartDate",value:null},{propName:"FinishDate",value:null})){b=!0;break}this.log("Round "+
(e+1));for(c=0;c<a.length;c++)switch(this.GetNodeType(a[c])){case 1:a[c].StartDate=Date.addDays(this.Project.StartDate,a[c].StartDelay);a[c].FinishDate=Date.addDays(a[c].StartDate,a[c].Duration);break;case 2:a[c].StartDate=Date.addDays(this.Project.StartDate,a[c].StartDelay);a[c].Progress=0;this.recalculateCollatedTask(a,c);break;case 3:var d=a.first("ID",a[c].PredecessorTaskID);null!=d&&null!=d.FinishDate&&(a[c].StartDate=Date.addDays(d.FinishDate,a[c].StartDelay),a[c].FinishDate=Date.addDays(a[c].StartDate,
a[c].Duration));break;case 4:d=a.first("ID",a[c].PredecessorTaskID);null!=d&&null!=d.FinishDate&&(a[c].StartDate=Date.addDays(d.FinishDate,a[c].StartDelay),a[c].Progress=0,this.recalculateCollatedTask(a,c));break;case 5:d=a.first("ID",a[c].CollatedTaskID);null!=d&&null!=d.StartDate&&(a[c].StartDate=Date.addDays(d.StartDate,a[c].StartDelay),a[c].FinishDate=Date.addDays(a[c].StartDate,a[c].Duration),a[c].Level=d.Level+1);break;case 6:d=a.first("ID",a[c].CollatedTaskID),null!=d&&null!=d.StartDate&&(a[c].StartDate=
Date.addDays(d.StartDate,a[c].StartDelay),a[c].Progress=0,a[c].Level=d.Level+1,this.recalculateCollatedTask(a,c))}}this.recalculateWorkHours(a);this.recalculatePredecessorTaskNo(a);return b}Sort(){this.Tasks.sortTree("Tasks","StartDelay")}log(b){console.log(b)}recalculateWorkHours(b){for(var a=0;a<b.length;a++){if(null==b[a].StartDate)continue;if(null==b[a].FinishDate)continue;if(0>=b[a].Duration)continue;let c=0,e=new Date(b[a].StartDate);for(let d=0;d<b[a].Duration;d++){const f=e.getDay();c+=this.Project.WorkHours[f]}b[a].CalcWorkHours=
c}}recalculatePredecessorTaskNo(b){for(var a=0;a<b.length;a++){if(null==b[a].PredecessorTaskID)continue;const c=this.FindTask(b[a].PredecessorTaskID);null!=c&&(b[a].PredecessorTaskNo=c.Order)}}recalculateCollatedTask(b,a){let c=b.select("CollatedTaskID",b[a].ID);if(0>=c.length)return b[a].Duration=0,new Date(b[a].StartDate);if(c.any("FinishDate",null))return b[a].Duration=0,null;let e=new Date(b[a].StartDate);c.forEach(d=>{d.FinishDate>e&&(e=d.FinishDate)});b[a].Progress=Math.average(c.toList("Progress"));
b[a].FinishDate=new Date(e);b[a].Duration=Date.diffDays(b[a].StartDate,b[a].FinishDate)}};class ProjectTaskGrid{constructor(b){this.Container=b;this.Columns=[null,null,"Task Name","Duration","Start","Finish","Predecessor","Resource Names",null];this.initialiseComponents()}initialiseComponents(){let b;b="<table class='ryz-project'>"+this.renderTHead();b=b+"<tbody>"+this.renderPlaceholder();this.Container.innerHTML=b+"</tbody></table>"}Render(b){const a=this;let c="";c+="<table class='ryz-project'>";c+=a.renderTHead();c+="<tbody>";b.forEach(e=>{c+=a.renderRow(e)});c+="</tbody>";c+="</table>";
a.Container.innerHTML=c}renderTHead(){let b="";b+="<thead>";b+="<tr>";this.Columns.forEach(a=>{b+="<th>"+(a??"")+"</th>"});b+="</tr>";return b+="</thead>"}renderPlaceholder(){return"<tr><td></td><td colspan='"+(this.Columns.length-1+"' class='c'>Loading...</td></tr>")}renderRow(b){let a="";a=1==b.IsCollated?a+"<tr class='b'>":a+"<tr>";a+="<td class='c'>"+b.Order+"</td>";a+="<td></td><td>";for(let c=0;c<b.Level;c++)a+="<span class='i'></span>";a+=b.Name;a=a+"</td><td>"+(b.Duration+" day"+(1==parseInt(b.Duration)?
"":"s")+"</td>");a+="<td class='c'>"+(new Date(b.StartDate)).toLocaleDateString()+"</td>";a+="<td class='c'>"+(new Date(b.FinishDate)).toLocaleDateString()+"</td>";a+="<td class='c'>"+(b.PredecessorTaskNo??"")+"</td>";return a+"<td></td><td></td></tr>"}};

14
build/ryzproj.min.js vendored Normal file
View File

@ -0,0 +1,14 @@
/**
* Ray's Projects
* @version v0.1.0.104 (2023/12/27 1051)
*/
class RyzProject{constructor(b){this.Project=Object.assign(this.newProject,b);this.Tasks=[];this.initialiseComponents()}initialiseComponents(){}get NewTask(){return{ID:null,Name:"",Description:"",Tag:null,StartDelay:0,Duration:1,PredecessorTaskID:null,IsCollated:!1,CollatedTaskID:null,ActuWorkHours:null,Progress:0,Resources:[]}}get StartDate(){return new Date(this.Project.StartDate)}get FinishDate(){let b=new Date(this.Project.StartDate);this.ExportTasks().forEach(a=>{null!=a.FinishDate&&(b=Date.max(b,
a.FinishDate))});return b}get Duration(){return Date.diffDays(this.StartDate,this.FinishDate)}get newProject(){return{Name:"",Description:"",StartDate:Date.today(),Tag:null,StartOfWeek:1,WorkHours:[0,7.5,7.5,7.5,7.5,7.5,0]}}get newTaskNode(){return{Order:null,ID:null,Name:"",Description:"",Tag:null,StartDate:null,FinishDate:null,StartDelay:0,Duration:1,PredecessorTaskID:null,IsCollated:!1,CollatedTaskID:null,CalcWorkHours:0,ActuWorkHours:null,Progress:0,Resources:[],Level:0,PredecessorTaskNo:null,
Tasks:[]}}AddTask(b){b=Object.assign(this.NewTask,b);b=Object.assign(this.newTaskNode,b);if(null==b.PredecessorTaskID&&null==b.CollatedTaskID)this.Tasks.push(b);else if(null!=b.PredecessorTaskID){var a=this.FindTask(b.PredecessorTaskID);null!=a?a.Tasks.push(b):this.log("Task not found ("+b.PredecessorTaskID+")")}else null!=b.CollatedTaskID?(a=this.FindTask(b.CollatedTaskID),null!=a?a.Tasks.push(b):this.log("Task not found ("+b.CollatedTaskID+")")):this.log("Task not found ("+b.ID+")")}ClearTasks(){this.Tasks=
[]}ExportTasks(){let b=this.Tasks.copy().flatten("Tasks");for(var a=0;a<b.length;a++)b[a].Order=a+1,delete b[a].Tasks;return b}FindTask(b){let a=null;this.Tasks.forEachTree("Tasks",function(c){return c.ID==b?(a=c,!1):!0});return a}GetNodeType(b){return null==b?0:null==b.PredecessorTaskID&&null==b.CollatedTaskID&&0==b.IsCollated?1:null==b.PredecessorTaskID&&null==b.CollatedTaskID&&1==b.IsCollated?2:null!=b.PredecessorTaskID&&null==b.CollatedTaskID&&0==b.IsCollated?3:null!=b.PredecessorTaskID&&null==
b.CollatedTaskID&&1==b.IsCollated?4:null!=b.CollatedTaskID&&0==b.IsCollated?5:null!=b.CollatedTaskID&&1==b.IsCollated?6:0}Invalidate(){let b=!1;this.Recalculate()||(b=!1);return b}Recalculate(){let b=!1;this.Sort();let a=this.Tasks.flatten("Tasks");for(var c=0;c<a.length;c++)a[c].Order=c+1,a[c].StartDate=null,a[c].FinishDate=null,a[c].CalcWorkHours=null;for(var e=0;128>e;e++){if(0>=a.copy().countMany({propName:"StartDate",value:null},{propName:"FinishDate",value:null})){b=!0;break}this.log("Round "+
(e+1));for(c=0;c<a.length;c++)switch(this.GetNodeType(a[c])){case 1:a[c].StartDate=Date.addDays(this.Project.StartDate,a[c].StartDelay);a[c].FinishDate=Date.addDays(a[c].StartDate,a[c].Duration);break;case 2:a[c].StartDate=Date.addDays(this.Project.StartDate,a[c].StartDelay);a[c].Progress=0;this.recalculateCollatedTask(a,c);break;case 3:var d=a.first("ID",a[c].PredecessorTaskID);null!=d&&null!=d.FinishDate&&(a[c].StartDate=Date.addDays(d.FinishDate,a[c].StartDelay),a[c].FinishDate=Date.addDays(a[c].StartDate,
a[c].Duration));break;case 4:d=a.first("ID",a[c].PredecessorTaskID);null!=d&&null!=d.FinishDate&&(a[c].StartDate=Date.addDays(d.FinishDate,a[c].StartDelay),a[c].Progress=0,this.recalculateCollatedTask(a,c));break;case 5:d=a.first("ID",a[c].CollatedTaskID);null!=d&&null!=d.StartDate&&(a[c].StartDate=Date.addDays(d.StartDate,a[c].StartDelay),a[c].FinishDate=Date.addDays(a[c].StartDate,a[c].Duration),a[c].Level=d.Level+1);break;case 6:d=a.first("ID",a[c].CollatedTaskID),null!=d&&null!=d.StartDate&&(a[c].StartDate=
Date.addDays(d.StartDate,a[c].StartDelay),a[c].Progress=0,a[c].Level=d.Level+1,this.recalculateCollatedTask(a,c))}}this.recalculateWorkHours(a);this.recalculatePredecessorTaskNo(a);return b}Sort(){this.Tasks.sortTree("Tasks","StartDelay")}log(b){console.log(b)}recalculateWorkHours(b){for(var a=0;a<b.length;a++){if(null==b[a].StartDate)continue;if(null==b[a].FinishDate)continue;if(0>=b[a].Duration)continue;let c=0,e=new Date(b[a].StartDate);for(let d=0;d<b[a].Duration;d++){const f=e.getDay();c+=this.Project.WorkHours[f]}b[a].CalcWorkHours=
c}}recalculatePredecessorTaskNo(b){for(var a=0;a<b.length;a++){if(null==b[a].PredecessorTaskID)continue;const c=this.FindTask(b[a].PredecessorTaskID);null!=c&&(b[a].PredecessorTaskNo=c.Order)}}recalculateCollatedTask(b,a){let c=b.select("CollatedTaskID",b[a].ID);if(0>=c.length)return b[a].Duration=0,new Date(b[a].StartDate);if(c.any("FinishDate",null))return b[a].Duration=0,null;let e=new Date(b[a].StartDate);c.forEach(d=>{d.FinishDate>e&&(e=d.FinishDate)});b[a].Progress=Math.average(c.toList("Progress"));
b[a].FinishDate=new Date(e);b[a].Duration=Date.diffDays(b[a].StartDate,b[a].FinishDate)}};

544
canvas.js
View File

@ -1,544 +0,0 @@
class Canvas {
_container = null;
_flowContainer = null;
_canvasContainer = null;
_ctx = null;
_autoSize = true;
_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 = "<div class='border'><canvas></canvas></div>";
if (a._container != null) {
a._container.style.width = "100%";
a._container.style.height = "100%";
a._flowContainer = a._container.getElementsByTagName("div")[0];
a._canvasContainer = a._flowContainer.getElementsByTagName("canvas")[0];
a._ctx = a._canvasContainer.getContext("2d");
}
a.AutoSize = a.AutoSize;
a.Width = a.Width;
a.Height = a.Height;
a.Clear();
}
get AutoSize() {
return this._autoSize;
}
set AutoSize(value) {
const a = this;
a._autoSize = value;
if (a._flowContainer != null) {
if (value == true) {
a._flowContainer.style.overflow = "hidden";
} else {
a._flowContainer.style.overflowX = ((a.Width >= a.ClientWidth) ? "hidden" : "auto");
a._flowContainer.style.overflowY = ((a.Height >= a.ClientHeight) ? "hidden" : "auto");
}
}
}
get ClientHeight() {
const a = this;
if (a._canvasContainer == null) {
return 0;
}
return a.#getHeight(a._canvasContainer);
}
set ClientHeight(value) {
const a = this;
if (a._canvasContainer != null) a._canvasContainer.style.height = value + "px";
if (a._ctx != null) a._ctx.canvas.height = value;
}
get ClientWidth() {
const a = this;
if (a._canvasContainer == null) {
return 0;
}
return a.#getWidth(a._canvasContainer);
}
set ClientWidth(value) {
const a = this;
if (a._canvasContainer != null) a._canvasContainer.style.width = value + "px";
if (a._ctx != null) a._ctx.canvas.width = value;
}
get Height() {
const a = this;
if (a._container == null) {
return 0;
}
return a.#getHeight(a._container);
}
set Height(value) {
const a = this;
if (a._container != null) a._container.style.height = value + "px";
if (a._flowContainer != null) a._flowContainer.style.height = value + "px";
if (a.AutoSize == true) {
a.ClientHeight = value;
}
}
get Width() {
const a = this;
if (a._container == null) {
return 0;
}
return a.#getWidth(a._container);
}
set Width(value) {
const a = this;
if (a._container != null) a._container.style.width = value + "px";
if (a._flowContainer != null) a._flowContainer.style.width = value + "px";
if (a.AutoSize == true) {
a.ClientWidth = 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);
}
DrawArrowS(rectangle, penColour, options) {
const a = this;
if (a._ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: [],
FillColour: null
}, options);
// Adjust for pen discrepancy
rectangle.X += 0.5;
rectangle.Y += 0.5;
rectangle.W -= opt.LineWidth;
rectangle.H -= opt.LineWidth;
a._ctx.beginPath();
a._ctx.strokeStyle = penColour;
a._ctx.lineWidth = opt.LineWidth;
a._ctx.setLineDash(opt.LineDash);
a._ctx.moveTo(rectangle.X, rectangle.Y);
a._ctx.lineTo((rectangle.X + rectangle.W), rectangle.Y);
a._ctx.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H));
a._ctx.closePath();
if (opt.FillColour != null) {
a._ctx.fillStyle = opt.FillColour;
a._ctx.fill();
}
a._ctx.stroke();
}
DrawCircle(x, y, width, penColour, options) {
const a = this;
if (a._ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: [],
FillColour: null
}, options);
let rectangle = {
X: x + Math.half(width),
Y: y + Math.half(width),
W: Math.half(width),
H: Math.half(width)
};
// Adjust for pen discrepancy
rectangle.X += 0.5;
rectangle.Y += 0.5;
rectangle.W -= Math.half(opt.LineWidth);
rectangle.H -= Math.half(opt.LineWidth);
a._ctx.beginPath();
a._ctx.strokeStyle = penColour;
a._ctx.lineWidth = opt.LineWidth;
a._ctx.setLineDash(opt.LineDash);
a._ctx.arc(rectangle.X, rectangle.Y, rectangle.W, 0, 2 * Math.PI, false);
a._ctx.closePath();
if (opt.FillColour != null) {
a._ctx.fillStyle = opt.FillColour;
a._ctx.fill();
}
a._ctx.stroke();
}
DrawDiamond(rectangle, penColour, options) {
const a = this;
if (a._ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: [],
FillColour: null
}, options);
// Adjust for pen discrepancy
rectangle.X += 0.5;
rectangle.Y += 0.5;
rectangle.W -= opt.LineWidth;
rectangle.H -= opt.LineWidth;
a._ctx.beginPath();
a._ctx.strokeStyle = penColour;
a._ctx.lineWidth = opt.LineWidth;
a._ctx.setLineDash(opt.LineDash);
a._ctx.moveTo((rectangle.X + Math.half(rectangle.W)), rectangle.Y);
a._ctx.lineTo((rectangle.X + rectangle.W), (rectangle.Y + Math.half(rectangle.H)));
a._ctx.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H));
a._ctx.lineTo(rectangle.X, (rectangle.Y + Math.half(rectangle.H)));
a._ctx.closePath();
if (opt.FillColour != null) {
a._ctx.fillStyle = opt.FillColour;
a._ctx.fill();
}
a._ctx.stroke();
}
DrawRectangle(rectangle, penColour, options) {
const a = this;
if (a._ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: [],
FillColour: null
}, options);
// Adjust for pen discrepancy
rectangle.X += 0.5;
rectangle.Y += 0.5;
rectangle.W -= opt.LineWidth;
rectangle.H -= opt.LineWidth;
a._ctx.beginPath();
a._ctx.strokeStyle = penColour;
a._ctx.lineWidth = opt.LineWidth;
a._ctx.setLineDash(opt.LineDash);
a._ctx.rect(rectangle.X, rectangle.Y, rectangle.W, rectangle.H);
if (opt.FillColour != null) {
a._ctx.fillStyle = opt.FillColour;
a._ctx.fill();
}
a._ctx.closePath();
a._ctx.stroke();
return rectangle;
}
DrawLine(startX, startY, finishX, finishY, penColour, options) {
const a = this;
if (a._ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
startY -= 0.5;
// y -= penWidth;
a._ctx.beginPath();
a._ctx.strokeStyle = penColour;
a._ctx.lineWidth = opt.LineWidth;
a._ctx.setLineDash(opt.LineDash);
a._ctx.moveTo(startX, startY);
a._ctx.lineTo(finishX, finishY);
a._ctx.stroke();
}
DrawLines(points, penColour, options) {
const a = this;
if (a._ctx == null) {
return;
}
if (points == null) {
return;
}
if (points.length <= 0) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
a._ctx.beginPath();
a._ctx.strokeStyle = penColour;
a._ctx.lineWidth = opt.LineWidth;
a._ctx.setLineDash(opt.LineDash);
a._ctx.moveTo(points[0].X, points[0].Y);
for (let i=1; i<points.length; i++) {
a._ctx.lineTo(points[i].X, points[i].Y);
}
a._ctx.stroke();
}
DrawHorizontalLine(x, y, width, penColour, options) {
const a = this;
if (a._ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
y -= 0.5;
// y -= penWidth;
a._ctx.beginPath();
a._ctx.strokeStyle = penColour;
a._ctx.lineWidth = opt.LineWidth;
a._ctx.setLineDash(opt.LineDash);
a._ctx.moveTo(x, y);
a._ctx.lineTo((x + width), y);
a._ctx.stroke();
}
DrawText(x, y, text, font, foreColour, options) {
const a = this;
if (a._ctx == null) {
return;
}
const opt = Object.assign({
Align: "left"
}, options);
a._ctx.font = font;
a._ctx.fillStyle = foreColour;
a._ctx.textAlign = opt.Align;
a._ctx.textBaseline = "top";
a._ctx.fillText(text, x, y);
}
DrawVerticalLine(x, y, height, penColour, options) {
const a = this;
if (a._ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
x -= 0.5;
y -= opt.LineWidth;
a._ctx.beginPath();
a._ctx.strokeStyle = penColour;
a._ctx.lineWidth = opt.LineWidth;
a._ctx.setLineDash(opt.LineDash);
a._ctx.moveTo(x, y);
a._ctx.lineTo(x, (y + height));
a._ctx.stroke();
}
FillText(rectangle, text, font, foreColour, options) {
const a = this;
if (a._ctx == null) {
return;
}
const opt = Object.assign({
Align: "center",
VAlign: "middle"
}, options);
a._ctx.font = font;
a._ctx.fillStyle = foreColour;
a._ctx.textAlign = opt.Align;
// a._ctx.textBaseline = verticalAlign;
a._ctx.textBaseline = "top";
const size = a._ctx.measureText(text);
const x = rectangle.X + Math.half(rectangle.W);
let y = rectangle.Y;
switch (opt.VAlign) {
case "center":
case "middle":
y += Math.half((rectangle.H - size.fontBoundingBoxDescent)) + size.fontBoundingBoxAscent;
break;
case "bottom":
y += (rectangle.H - size.fontBoundingBoxDescent);
break;
case "top":
default:
break;
}
a._ctx.fillText(text, x, y);
}
Invalidate() {
const a = this;
a.AutoSize = a.AutoSize;
a.Width = a.Width;
a.Height = a.Height;
}
MeasureText(font, value) {
const a = this;
if (a._ctx == null) {
return null;
}
a._ctx.font = font;
const size = a._ctx.measureText(value);
return {
W: size.width,
H: Math.round(size.fontBoundingBoxDescent + size.fontBoundingBoxAscent)
};
}
#getWidth(el) {
const result = (el.offsetWidth || el.innerWidth || el.clientWidth);
return result;
}
#getHeight(el) {
const result = (el.offsetHeight || el.innerHeight || el.clientHeight);
return result;
}
}

View File

@ -29,8 +29,6 @@ var dataSet = [
{ key: "c", value: "C3", num: 3, f: 3.3, date: new Date(2001, 3, 3) }
];
// let result = dataSet.index("key", "d");
//dataSet = dataSet.orderBy("date");
dataSet = dataSet.orderByDesc("date");
// console.log(result);

View File

@ -2,7 +2,8 @@
border-spacing: 0px;
border-collapse: separate;
cursor: default;
padding: 0px 0px 30px 0px
padding: 0px 0px 30px 0px;
width: 100%;
}
.ryz-project .b {

View File

@ -8,13 +8,12 @@
<meta name="keyword" content="" />
<script src="build/ryzjsext.min.js"></script>
<script src="canvas.js"></script>
<!-- <script src="ryz-js-ext-rectangle.js"></script> -->
<!-- <script src="build/ryzproj.min.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" />
<script src="build/ryzproj.bundle.min.js"></script>
<!-- <script src="project/task-grid.js"></script> -->
<!-- <script src="project/gantt-chart.js"></script> -->
<link href="demo-project.css" rel="stylesheet" />
<title></title>
@ -152,7 +151,6 @@ body {
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"));
@ -161,7 +159,6 @@ body {
if (ganttChart1 == null) ganttChart1 = new RyzGanttChart(document.getElementById("ganttChart1"), {});
ganttChart1.Load(project1);
});
</script>

View File

@ -0,0 +1,540 @@
class Canvas {
constructor(el) {
const a = this;
a.container = el;
a.ctx = null;
a.flowContainer = null;
a.canvasContainer = null;
a.autoSize = true;
a.padding = {
Top: 0,
Right: 0,
Bottom: 0,
Left: 0
};
a.initialiseComponents();
}
initialiseComponents() {
const a = this;
if (a.container == null) {
return;
}
a.container.innerHTML = "<div class='border'><canvas></canvas></div>";
if (a.container != null) {
a.container.style.width = "100%";
a.container.style.height = "100%";
a.flowContainer = a.container.getElementsByTagName("div")[0];
a.canvasContainer = a.flowContainer.getElementsByTagName("canvas")[0];
a.ctx = a.canvasContainer.getContext("2d");
}
a.AutoSize = a.AutoSize;
a.Width = a.Width;
a.Height = a.Height;
a.Clear();
}
get AutoSize() {
return this.autoSize;
}
set AutoSize(value) {
const a = this;
a.autoSize = value;
if (a.flowContainer != null) {
if (value == true) {
a.flowContainer.style.overflow = "hidden";
} else {
a.flowContainer.style.overflowX = ((a.Width >= a.ClientWidth) ? "hidden" : "auto");
a.flowContainer.style.overflowY = ((a.Height >= a.ClientHeight) ? "hidden" : "auto");
}
}
}
get ClientHeight() {
const a = this;
if (a.canvasContainer == null) {
return 0;
}
return a.getHeight(a.canvasContainer);
}
set ClientHeight(value) {
const a = this;
if (a.canvasContainer != null) a.canvasContainer.style.height = value + "px";
if (a.ctx != null) a.ctx.canvas.height = value;
}
get ClientWidth() {
const a = this;
if (a.canvasContainer == null) {
return 0;
}
return a.getWidth(a.canvasContainer);
}
set ClientWidth(value) {
const a = this;
if (a.canvasContainer != null) a.canvasContainer.style.width = value + "px";
if (a.ctx != null) a.ctx.canvas.width = value;
}
get Height() {
const a = this;
if (a.container == null) {
return 0;
}
return a.getHeight(a.container);
}
set Height(value) {
const a = this;
if (a.container != null) a.container.style.height = value + "px";
if (a.flowContainer != null) a.flowContainer.style.height = value + "px";
if (a.AutoSize == true) {
a.ClientHeight = value;
}
}
get Width() {
const a = this;
if (a.container == null) {
return 0;
}
return a.getWidth(a.container);
}
set Width(value) {
const a = this;
if (a.container != null) a.container.style.width = value + "px";
if (a.flowContainer != null) a.flowContainer.style.width = value + "px";
if (a.AutoSize == true) {
a.ClientWidth = 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);
}
DrawArrowS(rectangle, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: [],
FillColour: null
}, options);
// Adjust for pen discrepancy
rectangle.X += 0.5;
rectangle.Y += 0.5;
rectangle.W -= opt.LineWidth;
rectangle.H -= opt.LineWidth;
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo(rectangle.X, rectangle.Y);
a.ctx.lineTo((rectangle.X + rectangle.W), rectangle.Y);
a.ctx.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H));
a.ctx.closePath();
if (opt.FillColour != null) {
a.ctx.fillStyle = opt.FillColour;
a.ctx.fill();
}
a.ctx.stroke();
}
DrawCircle(x, y, width, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: [],
FillColour: null
}, options);
let rectangle = {
X: x + Math.half(width),
Y: y + Math.half(width),
W: Math.half(width),
H: Math.half(width)
};
// Adjust for pen discrepancy
rectangle.X += 0.5;
rectangle.Y += 0.5;
rectangle.W -= Math.half(opt.LineWidth);
rectangle.H -= Math.half(opt.LineWidth);
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.arc(rectangle.X, rectangle.Y, rectangle.W, 0, 2 * Math.PI, false);
a.ctx.closePath();
if (opt.FillColour != null) {
a.ctx.fillStyle = opt.FillColour;
a.ctx.fill();
}
a.ctx.stroke();
}
DrawDiamond(rectangle, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: [],
FillColour: null
}, options);
// Adjust for pen discrepancy
rectangle.X += 0.5;
rectangle.Y += 0.5;
rectangle.W -= opt.LineWidth;
rectangle.H -= opt.LineWidth;
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo((rectangle.X + Math.half(rectangle.W)), rectangle.Y);
a.ctx.lineTo((rectangle.X + rectangle.W), (rectangle.Y + Math.half(rectangle.H)));
a.ctx.lineTo((rectangle.X + Math.half(rectangle.W)), (rectangle.Y + rectangle.H));
a.ctx.lineTo(rectangle.X, (rectangle.Y + Math.half(rectangle.H)));
a.ctx.closePath();
if (opt.FillColour != null) {
a.ctx.fillStyle = opt.FillColour;
a.ctx.fill();
}
a.ctx.stroke();
}
DrawRectangle(rectangle, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: [],
FillColour: null
}, options);
// Adjust for pen discrepancy
rectangle.X += 0.5;
rectangle.Y += 0.5;
rectangle.W -= opt.LineWidth;
rectangle.H -= opt.LineWidth;
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.rect(rectangle.X, rectangle.Y, rectangle.W, rectangle.H);
if (opt.FillColour != null) {
a.ctx.fillStyle = opt.FillColour;
a.ctx.fill();
}
a.ctx.closePath();
a.ctx.stroke();
}
DrawLine(startX, startY, finishX, finishY, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
startY -= 0.5;
// y -= penWidth;
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo(startX, startY);
a.ctx.lineTo(finishX, finishY);
a.ctx.stroke();
}
DrawLines(points, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
if (points == null) {
return;
}
if (points.length <= 0) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo(points[0].X, points[0].Y);
for (let i=1; i<points.length; i++) {
a.ctx.lineTo(points[i].X, points[i].Y);
}
a.ctx.stroke();
}
DrawHorizontalLine(x, y, width, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
y -= 0.5;
// y -= penWidth;
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo(x, y);
a.ctx.lineTo((x + width), y);
a.ctx.stroke();
}
DrawText(x, y, text, font, foreColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
Align: "left"
}, options);
a.ctx.font = font;
a.ctx.fillStyle = foreColour;
a.ctx.textAlign = opt.Align;
a.ctx.textBaseline = "top";
a.ctx.fillText(text, x, y);
}
DrawVerticalLine(x, y, height, penColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
LineWidth: 1,
LineDash: []
}, options);
x -= 0.5;
y -= opt.LineWidth;
a.ctx.beginPath();
a.ctx.strokeStyle = penColour;
a.ctx.lineWidth = opt.LineWidth;
a.ctx.setLineDash(opt.LineDash);
a.ctx.moveTo(x, y);
a.ctx.lineTo(x, (y + height));
a.ctx.stroke();
}
FillText(rectangle, text, font, foreColour, options) {
const a = this;
if (a.ctx == null) {
return;
}
const opt = Object.assign({
Align: "center",
VAlign: "middle"
}, options);
a.ctx.font = font;
a.ctx.fillStyle = foreColour;
a.ctx.textAlign = opt.Align;
// a._ctx.textBaseline = verticalAlign;
a.ctx.textBaseline = "top";
const size = a.ctx.measureText(text);
const x = rectangle.X + Math.half(rectangle.W);
let y = rectangle.Y;
switch (opt.VAlign) {
case "center":
case "middle":
y += Math.half((rectangle.H - size.fontBoundingBoxDescent)) + size.fontBoundingBoxAscent;
break;
case "bottom":
y += (rectangle.H - size.fontBoundingBoxDescent);
break;
case "top":
default:
break;
}
a.ctx.fillText(text, x, y);
}
Invalidate() {
const a = this;
a.AutoSize = a.AutoSize;
a.Width = a.Width;
a.Height = a.Height;
}
MeasureText(font, value) {
const a = this;
if (a.ctx == null) {
return null;
}
a.ctx.font = font;
const size = a.ctx.measureText(value);
return {
W: size.width,
H: Math.round(size.fontBoundingBoxDescent + size.fontBoundingBoxAscent)
};
}
getWidth(el) {
const result = (el.offsetWidth || el.innerWidth || el.clientWidth);
return result;
}
getHeight(el) {
const result = (el.offsetHeight || el.innerHeight || el.clientHeight);
return result;
}
}

View File

@ -1,4 +1,4 @@
/**
* Ray's JavaScript Extension
* @version v0.1.0.071 (2023/12/27 1551)
* @version v0.1.0.088 (2024/01/06 1933)
*/

View File

@ -1,22 +1,22 @@
class RyzGanttChart extends Canvas {
class RyzGanttChart {
constructor(el, options) {
super(el);
const a = this;
a.Canvas = new Canvas(el);
a.Options = Object.assign(a.DefaultOptions, options);
// a.Debug = true;
a.Debug = false;
a.Project = null;
a.StartDate = null;
a.#initialiseComponents();
// a.initialiseComponents();
}
#initialiseComponents() {
const a = this;
// initialiseComponents() {
// const a = this;
}
// }
get DefaultOptions() {
@ -60,17 +60,34 @@ class RyzGanttChart extends Canvas {
return a.Options.HeaderRow.Height[0] + a.Options.HeaderRow.Height[1];
}
// Invalidate() {
// const a = this;
// a._padding.Left = 3;
Invalidate() {
const a = this;
// a.DrawRectangle(a.ClientRectangle, "#B8B8B8", 1);
// }
a.Canvas.Clear();
if (a.Project == null) {
return;
}
const tasks = a.Project.ExportTasks();
const width = ((a.Project.Duration + 2) * a.Options.DayWidth);
const height = (tasks.length * a.Options.Row.Height) + a.HeaderHeight;
a.AutoSize = false;
a.ClientWidth = width;
a.ClientHeight = height;
a.Canvas.Invalidate();
a.drawChartLabel(a.Project);
a.drawTasks(tasks);
a.drawLines(tasks);
}
Load(project) {
const a = this;
a.Clear();
a.Canvas.Clear();
if (project == null) {
return;
@ -79,26 +96,14 @@ class RyzGanttChart extends Canvas {
a.Project = project;
a.StartDate = new Date(project.StartDate);
const tasks = project.ExportTasks();
const width = ((project.Duration + 2) * a.Options.DayWidth);
const height = (tasks.length * a.Options.Row.Height) + a.HeaderHeight;
a.AutoSize = false;
a.ClientWidth = width;
a.ClientHeight = height;
a.Invalidate();
a.#drawChartLabel(project);
a.#drawTasks(tasks);
a.#drawLines(tasks);
}
#drawChartLabel(project) {
drawChartLabel(project) {
const a = this;
const width = a.ClientWidth;
const height = a.ClientHeight;
const width = a.Canvas.ClientWidth;
const height = a.Canvas.ClientHeight;
const displayDays = project.Duration + 2;
let startDate = new Date(a.StartDate);
@ -106,11 +111,11 @@ class RyzGanttChart extends Canvas {
// Draw vertical lines
for (let i=1; i<displayDays; i++) {
a.DrawVerticalLine((a.Options.DayWidth * i), (a.Options.HeaderRow.Height[0] + a.Options.BorderWidth), (a.Options.HeaderRow.Height[1] - (a.Options.BorderWidth * 2)), a.Options.BorderColour, {});
a.Canvas.DrawVerticalLine((a.Options.DayWidth * i), (a.Options.HeaderRow.Height[0] + a.Options.BorderWidth), (a.Options.HeaderRow.Height[1] - (a.Options.BorderWidth * 2)), a.Options.BorderColour, {});
}
a.DrawHorizontalLine(0, a.Options.HeaderRow.Height[0], width, a.Options.BorderColour);
a.DrawHorizontalLine(0, (a.HeaderHeight - a.Options.BorderWidth), width, a.Options.BorderColour);
a.Canvas.DrawHorizontalLine(0, a.Options.HeaderRow.Height[0], width, a.Options.BorderColour);
a.Canvas.DrawHorizontalLine(0, (a.HeaderHeight - a.Options.BorderWidth), width, a.Options.BorderColour);
// Write dates
for (let i=0; i<displayDays; i++) {
@ -119,13 +124,13 @@ class RyzGanttChart extends Canvas {
// Draw month
if (date.getDate() == 1) {
const size = a.MeasureText(a.Options.DateFont, "#");
const size = a.Canvas.MeasureText(a.Options.DateFont, "#");
const monthPoint = {
X: (x + 2),
Y: Math.half(a.Options.HeaderRow.Height[0] - size.H)
};
a.DrawText(monthPoint.X, monthPoint.Y, date.toCString("MMMM"), a.Options.DateFont, a.Options.DateForeColour);
a.Canvas.DrawText(monthPoint.X, monthPoint.Y, date.toCString("MMMM"), a.Options.DateFont, a.Options.DateForeColour);
}
// Draw day
@ -136,38 +141,38 @@ class RyzGanttChart extends Canvas {
H: (a.Options.HeaderRow.Height[1] - (a.Options.BorderWidth * 2))
};
a.FillText(dateRectangle, date.getDate(), a.Options.DateFont, a.Options.DateForeColour);
a.Canvas.FillText(dateRectangle, date.getDate(), a.Options.DateFont, a.Options.DateForeColour);
if (a.Debug) a.DrawRectangle(dateRectangle, "red", {});
if (a.Debug) a.Canvas.DrawRectangle(dateRectangle, "red", {});
// Draw day-of-week guideline
const guidelineHeight = height - a.Options.BorderWidth;
if (project.Project.StartOfWeek == date.getDay()) {
// Draw start-of-the-week guideline
a.DrawVerticalLine(x, a.HeaderHeight, guidelineHeight, a.Options.BorderColour, {});
a.Canvas.DrawVerticalLine(x, a.HeaderHeight, guidelineHeight, a.Options.BorderColour, {});
} else {
a.DrawVerticalLine(x, a.HeaderHeight, guidelineHeight, a.Options.BorderColour, { LineDash: a.Options.BorderDashPattern });
a.Canvas.DrawVerticalLine(x, a.HeaderHeight, guidelineHeight, a.Options.BorderColour, { LineDash: a.Options.BorderDashPattern });
}
}
}
#drawTasks(tasks) {
drawTasks(tasks) {
const a = this;
for (let i=0; i<tasks.length; i++) {
const style = ((tasks[i].IsCollated == true) ? a.Options.Row.CollatedTask : a.Options.Row.Task);
const rectangle = a.#getTaskRectangle(tasks[i], style);
const rectangle = a.getTaskRectangle(tasks[i], style);
if (tasks[i].Duration <= 0) {
a.DrawDiamond(rectangle, style.BorderColour, { FillColour: style.FillColour });
a.Canvas.DrawDiamond(rectangle, style.BorderColour, { FillColour: style.FillColour });
} else {
a.DrawRectangle(rectangle, style.BorderColour, { FillColour: style.FillColour });
a.Canvas.DrawRectangle(rectangle, style.BorderColour, { FillColour: style.FillColour });
}
}
}
#drawLines(tasks) {
drawLines(tasks) {
const a = this;
for (let i=0; i<tasks.length; i++) {
@ -180,7 +185,7 @@ class RyzGanttChart extends Canvas {
}
const style = ((tasks[i].IsCollated == true) ? a.Options.Row.CollatedTask : a.Options.Row.Task);
const rectangle = a.#getTaskRectangle(tasks[i], style);
const rectangle = a.getTaskRectangle(tasks[i], style);
const predecessorTask = tasks.first("Order", tasks[i].PredecessorTaskNo);
if (predecessorTask == null) {
@ -188,7 +193,7 @@ class RyzGanttChart extends Canvas {
}
const predecessorStyle = ((predecessorTask.IsCollated == true) ? a.Options.Row.CollatedTask : a.Options.Row.Task);
const predecessorRectangle = a.#getTaskRectangle(predecessorTask, predecessorStyle);
const predecessorRectangle = a.getTaskRectangle(predecessorTask, predecessorStyle);
let points = [];
points.push({ X: (predecessorRectangle.X + predecessorRectangle.W), Y: (predecessorRectangle.Y + Math.half(predecessorRectangle.H)) });
@ -197,7 +202,7 @@ class RyzGanttChart extends Canvas {
points.push({ X: (rectangle.X + a.Options.Line.Margin), Y: (rectangle.Y - a.Options.Line.Margin) });
points.push({ X: (rectangle.X + a.Options.Line.Margin), Y: rectangle.Y });
a.DrawLines(points, a.Options.Line.Colour, { LineWidth: a.Options.Line.Width });
a.Canvas.DrawLines(points, a.Options.Line.Colour, { LineWidth: a.Options.Line.Width });
const arrowRectangle = {
X: (rectangle.X + a.Options.Line.Margin - Math.half(a.Options.Line.ArrowSize)),
@ -206,11 +211,11 @@ class RyzGanttChart extends Canvas {
H: a.Options.Line.ArrowSize
}
a.DrawArrowS(arrowRectangle, a.Options.Line.Colour, { FillColour: a.Options.Line.Colour });
a.Canvas.DrawArrowS(arrowRectangle, a.Options.Line.Colour, { FillColour: a.Options.Line.Colour });
}
}
#getTaskRectangle(task, style) {
getTaskRectangle(task, style) {
const a = this;
const i = (task.Order - 1);

View File

@ -1,15 +1,15 @@
class RyzProject {
constructor(options) {
const a = this;
const _options = Object.assign(a.#newProject, options);
const _options = Object.assign(a.newProject, options);
a.Project = _options;
a.Tasks = [];
a.#initialiseComponents();
a.initialiseComponents();
}
#initialiseComponents() {
initialiseComponents() {
const a = this;
}
@ -64,7 +64,7 @@ class RyzProject {
}
get #newProject() {
get newProject() {
return {
Name: "",
Description: "",
@ -75,7 +75,7 @@ class RyzProject {
};
}
get #newTaskNode() {
get newTaskNode() {
return {
Order: null,
ID: null,
@ -103,7 +103,7 @@ class RyzProject {
AddTask(task) {
const a = this;
const newTask = Object.assign(a.NewTask, task);
const newTaskNode = Object.assign(a.#newTaskNode, newTask);
const newTaskNode = Object.assign(a.newTaskNode, newTask);
if ((newTaskNode.PredecessorTaskID == null) && (newTaskNode.CollatedTaskID == null)) {
a.Tasks.push(newTaskNode);
@ -113,7 +113,7 @@ class RyzProject {
if (node != null) {
node.Tasks.push(newTaskNode);
} else {
a.#log("Task not found (" + newTaskNode.PredecessorTaskID + ")");
a.log("Task not found (" + newTaskNode.PredecessorTaskID + ")");
}
} else if (newTaskNode.CollatedTaskID != null) {
const node = a.FindTask(newTaskNode.CollatedTaskID);
@ -121,10 +121,10 @@ class RyzProject {
if (node != null) {
node.Tasks.push(newTaskNode);
} else {
a.#log("Task not found (" + newTaskNode.CollatedTaskID + ")");
a.log("Task not found (" + newTaskNode.CollatedTaskID + ")");
}
} else {
a.#log("Task not found (" + newTaskNode.ID + ")");
a.log("Task not found (" + newTaskNode.ID + ")");
}
}
@ -258,7 +258,7 @@ class RyzProject {
break;
}
a.#log("Round " + (x + 1));
a.log("Round " + (x + 1));
for (var i=0; i<result.length; i++) {
const nodeType = a.GetNodeType(result[i]);
@ -273,7 +273,7 @@ class RyzProject {
result[i].Progress = 0;
// update finish date, if possible
a.#recalculateCollatedTask(result, i);
a.recalculateCollatedTask(result, i);
break;
case 3: // task with parent
@ -294,7 +294,7 @@ class RyzProject {
result[i].Progress = 0;
// update finish date, if possible
a.#recalculateCollatedTask(result, i);
a.recalculateCollatedTask(result, i);
}
}
@ -319,7 +319,7 @@ class RyzProject {
result[i].Level = (node6.Level + 1);
// update finish date, if possible
a.#recalculateCollatedTask(result, i);
a.recalculateCollatedTask(result, i);
}
}
@ -331,10 +331,10 @@ class RyzProject {
}
// Calculate work-hours
a.#recalculateWorkHours(result);
a.recalculateWorkHours(result);
// Calculate predecessor
a.#recalculatePredecessorTaskNo(result);
a.recalculatePredecessorTaskNo(result);
return isSuccess;
}
@ -345,11 +345,11 @@ class RyzProject {
a.Tasks.sortTree("Tasks", "StartDelay");
}
#log(message) {
log(message) {
console.log(message);
}
#recalculateWorkHours(array) {
recalculateWorkHours(array) {
const a = this;
for (var i=0; i<array.length; i++) {
@ -377,7 +377,7 @@ class RyzProject {
}
}
#recalculatePredecessorTaskNo(array) {
recalculatePredecessorTaskNo(array) {
const a = this;
for (var i=0; i<array.length; i++) {
@ -394,7 +394,7 @@ class RyzProject {
}
}
#recalculateCollatedTask(array, index) {
recalculateCollatedTask(array, index) {
let node2 = array.select("CollatedTaskID", array[index].ID);
if (node2.length <= 0) {
// No children

View File

@ -16,17 +16,17 @@ class ProjectTaskGrid {
null
];
a.#initialiseComponents();
a.initialiseComponents();
}
#initialiseComponents() {
initialiseComponents() {
const a = this;
let htmlContent = "";
htmlContent += "<table class='ryz-project'>";
htmlContent += a.#renderTHead();
htmlContent += a.renderTHead();
htmlContent += "<tbody>";
htmlContent += a.#renderPlaceholder();
htmlContent += a.renderPlaceholder();
htmlContent += "</tbody>";
htmlContent += "</table>";
@ -39,11 +39,11 @@ class ProjectTaskGrid {
let htmlContent = "";
htmlContent += "<table class='ryz-project'>";
htmlContent += a.#renderTHead();
htmlContent += a.renderTHead();
htmlContent += "<tbody>";
model.forEach(e => {
htmlContent += a.#renderRow(e);
htmlContent += a.renderRow(e);
});
htmlContent += "</tbody>";
@ -53,7 +53,7 @@ class ProjectTaskGrid {
}
#renderTHead() {
renderTHead() {
const a = this;
let htmlContent = "";
@ -70,7 +70,7 @@ class ProjectTaskGrid {
return htmlContent;
}
#renderPlaceholder() {
renderPlaceholder() {
const a = this;
let htmlContent = "";
@ -82,7 +82,7 @@ class ProjectTaskGrid {
return htmlContent;
}
#renderRow(e) {
renderRow(e) {
const a = this;
let htmlContent = "";

View File

@ -0,0 +1,4 @@
/**
* Ray's Projects (Bundled with TaskGrid and GanttChart)
* @version v0.1.0.104 (2023/12/27 1051)
*/