Issue
There is one nice looking Gantt chart available with example for Asp.net. However I am having hard times to understand how it can be done in Blazor with razor pages. Can somebody give me some hints how to proceed?
I have placed jsgantt.js and jsgantt.css into wwwroot and also added references in index.html.
But then how to handle that part? Also I guess data should better come from json?
<%@ Page Title="" Language="C#" MasterPageFile="~/Site.Master" AutoEventWireup="true" CodeBehind="Gantt.aspx.cs" Inherits="Links2.WebUI.Gannt" %>
<asp:Content ID="Content1" ContentPlaceHolderID="MainContent" runat="server">
<link href="assets/css/jsgantt.css" rel="stylesheet" type="text/css"/>
<script src="Scripts/jsgantt.js" type="text/javascript"></script>
<script src="https://code.jquery.com/jquery-git.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jspdf/0.9.0rc1/jspdf.min.js"></script>
<style>
.box {
display: inline-block;
height: 20px;
width: 20px;
border: 2px solid;
}
.chartlegend
{
border:1px solid none;
text-align:right;
margin-bottom: 30px;
}
.chartlegenditem
{
float: right;
margin-right: 1%;
filter: alpha(opacity=90);
opacity: 0.9;
margin-top: 1px;
}
.body-content {
width: 1800px !important;
}
</style>
<%--<input type="button" id="click" value="Export to PDF"/>--%>
<div class="chartlegend" id="ChartLegendDIV" style="width:1800;"></div>
<div style="position:relative" class="gantt" id="GanttChartDIV"></div>
<asp:HiddenField ID="HiddenField" runat="server" />
<script type="text/javascript">
var colourList = {
L1:
{
Title: 'Executing',
Colour: '#50C13A'
},
L2:
{
Title: 'At Risk',
Colour: '#F7E438'
},
L3:
{
Title: 'To Do',
Colour: '#A9A9A9'
},
L4:
{
Title: 'On Hold',
Colour: '#2F4F4F'
},
L5:
{
Title: 'Planning',
Colour: '#3A84C3'
},
L6:
{
Title: 'Late',
Colour: '#C43A3A'
},
L7:
{
Title: 'Initiating',
Colour: '#F0F8FF'
},
L8:
{
Title: 'Complete',
Colour: '#000000'
}
};
colorize = function (colorList)
{
var container = document.getElementById('ChartLegendDIV');
for (var key in colorList) {
var details = colorList[key];
var boxContainer = document.createElement("DIV");
boxContainer.className = 'chartlegenditem';
var box = document.createElement("DIV");
var label = document.createElement("SPAN");
label.innerHTML = details['Title'];
box.className = "box";
box.style.backgroundColor = details['Colour'];
boxContainer.appendChild(box);
boxContainer.appendChild(label);
container.appendChild(boxContainer);
}
}
colorize(colourList);
var g = new JSGantt.GanttChart(document.getElementById('GanttChartDIV'), 'month');
var list = document.getElementById('<%= HiddenField.ClientID %>').value;
var result = JSON.parse(list);
vShowRes = document.querySelector('#vShowRes:checked') ? 1 : 0;
vShowCost = document.querySelector('#vShowCost:checked') ? 1 : 0;
vShowComp = document.querySelector('#vShowComp:checked') ? 1 : 0;
vShowDur = document.querySelector('#vShowDur:checked') ? 1 : 0;
vShowStartDate = document.querySelector('#vShowStartDate:checked') ? 1 : 0;
vShowEndDate = document.querySelector('#vShowEndDate:checked') ? 1 : 0;
vShowPlanStartDate = document.querySelector('#vShowPlanStartDate:checked') ? 1 : 0;
vShowPlanEndDate = document.querySelector('#vShowPlanEndDate:checked') ? 1 : 0;
vShowTaskInfoLink = document.querySelector('#vShowTaskInfoLink:checked') ? 1 : 0;
vShowEndWeekDate = document.querySelector('#vShowEndWeekDate:checked') ? 1 : 0;
g.setOptions({
vCaptionType: 'Complete', // Set to Show Caption : None,Caption,Resource,Duration,Complete,
vQuarterColWidth: 46,
vAdditionalHeaders: { // Add data columns to your table
ID:
{
title: 'ID'
},
PM:
{
title: 'PM'
},
Sponsor:
{
title: 'Sponsor'
}
},
vDayMajorDateDisplayFormat: 'mon yyyy - Week ww',
});
//g.AddTaskItemObject({
// pID: 1,
// pName: "Define Chart <strong>API</strong>",
// pStart: "2017-02-25",
// pEnd: "2017-03-17",
// pPlanStart: "2017-04-01",
// pPlanEnd: "2017-04-15 12:00",
// pClass: "ggroupblack",
// pLink: "",
// pMile: 0,
// pRes: "Brian",
// pComp: 0,
// pGroup: 1,
// pParent: 0,
// pOpen: 1,
// pDepend: "",
// pCaption: "",
// pCost: 1000,
// pNotes: "Some Notes text",
// category: "My Category",
// sector: "Finance"
//});
// or passing parameters
g.setShowRes(0);
g.setShowStartDate(0);
g.setShowEndDate(0);
g.setShowComp(0);
g.setShowDur(0);
g.setScrollTo("today");
g.setFormatArr('Month', 'Quarter');
g.setTooltipDelay(200);
g.AddTaskItem(new JSGantt.TaskItem(1, 'Core', '', '', 'ggroupblack', '', 0, 'Padraic', 0, 1, 0, 1, '', '', '', 'Padraic', g));
g.AddTaskItem(new JSGantt.TaskItem(2, 'SHP', '', '', 'ggroupblack', '', 0, 'Padraic', 0, 1, 0, 1, '', '', '', 'Padraic', g));
//g.AddTaskItem(new JSGantt.TaskItem(3, 'Undefined', '', '', 'ggroupblack', '', 0, 'Padraic', 0, 1, 0, 1, '', '', '', 'Padraic', g));
g.AddTaskItem(new JSGantt.TaskItem(4, 'DES', '', '', 'ggroupblack', '', 0, 'Padraic', 0, 1, 1, 1, '', '', '', 'Padraic', g));
g.AddTaskItem(new JSGantt.TaskItem(5, 'SES', '', '', 'ggroupblack', '', 0, 'Padraic', 0, 1, 1, 1, '', '', '', 'Padraic', g));
g.AddTaskItem(new JSGantt.TaskItem(6, 'SDC', '', '', 'ggroupblack', '', 0, 'Padraic', 0, 1, 1, 1, '', '', '', 'Padraic', g));
g.AddTaskItem(new JSGantt.TaskItem(7, 'PCT', '', '', 'ggroupblack', '', 0, 'Padraic', 0, 1, 1, 1, '', '', '', 'Padraic', g));
g.AddTaskItem(new JSGantt.TaskItem(8, 'PTA', '', '', 'ggroupblack', '', 0, 'Padraic', 0, 1, 1, 1, '', '', '', 'Padraic', g));
var IsFirstIteration = true;
var IsUndefinedTypePresent = false;
for (var i = 0; i < result.length; i++)
{
var statusColour = 'gtaskblack';
var row = result[i];
var name = row["Name"];
var id = row["ID"];
var start = row["Start"].split('T')[0];
var finish = row["Finish"].split('T')[0];
var percentageComplete = row["PercentageComplete"];
var status = row["Status"];
var cValue = row["CValue"];
var pm = row["ProjectManager"];
var sponsor = row["Sponsor"];
var valuestream = row["ValueStream"];
var comments = row["Comments"];
// Set the parent as undefined by default.
var parent = 3;
if (row["SubParent"] != 9) {
parent = row["SubParent"];
}
else
{
parent = row["Parent"];
}
if (IsFirstIteration)
{
parent = 3;
IsFirstIteration = false;
}
if (parent == 3 && !IsUndefinedTypePresent)
{
g.AddTaskItem(new JSGantt.TaskItem(3, 'Undefined', '', '', 'ggroupblack', '', 0, 'Padraic', 0, 1, 0, 1, '', '', '', 'Padraic', g));
IsUndefinedTypePresent = true;
}
//if (percentageComplete == 0)
//{
// percentageComplete = 0.001;
//}
switch (cValue) {
// Executing
case 333:
statusColour = 'gtaskgreen';
break;
// At Risk
case 334:
statusColour = 'gtaskyellow';
break;
// Late
case 335:
statusColour = 'gtaskred';
break;
// On Hold
case 336:
statusColour = 'gtaskslategray';
break;
// Planning
case 337:
statusColour = 'gtaskblue';
break;
// To Do
case 338:
statusColour = 'gtaskgray';
break;
// Initiating
case 350:
statusColour = 'gtaskaliceblue';
break;
// Complete
case 351:
statusColour = 'gtaskblack';
break;
default:
statusColour = 'gtaskpink';
break;
}
g.AddTaskItemObject(
{
pID: i + 8,
pName: name,
pStart: start,
pEnd: finish,
pLink: '',
pClass: statusColour,
pMile: 0,
pRes: pm,
pComp: percentageComplete,
pGroup: 0,
pParent: parent,
pOpen: 1,
pNotes: comments,
ID: id,
PM: pm,
Sponsor: sponsor
}
);
}
g.Draw()
document.write("<br><br><br><br>");
//document.getElementById("click").onclick = function ()
//{
// // Default export is a4 paper, portrait, using milimeters for units
// var doc = new jsPDF();
// //doc.addHTML($('GanttChartDIV')[0], 15, 15, {
// // 'background': '#fff',
// //});
// doc.fromHTML($('GanttChartDIV').html(), 10, 10, {'width' : 340});
// doc.save("Test.pdf");
// //var doc = new jsPDF();
// //doc.addHTML($('#content')[0], 15, 15, {
// // 'background': '#fff',
// // }, function() {
// // doc.save('sample-file.pdf');
// //});
//}
</script>
</asp:Content>
Repo can be found here: https://github.com/jsGanttImproved/jsgantt-improved
Solution
Blazor can talk with javascript through Microsoft.JSInterop.IJSRuntime.
You can create a javascript function in your index.html to show Gantt, then call it from your blazor code.
Here is an example. I simply implement the example from https://github.com/jsGanttImproved/jsgantt-improved.
First, in you index.html, include jsgantt css and js, and prepare a function to be called from blazor. It is kind of an api exposed to blazor to show Gantt.
I assume you save jsgantt files under wwwroot/content folder.
<head>
...
<link rel="stylesheet" href="content/jsgantt.css">
<script src="content/jsgantt.js"></script>
<script>
showGantt = (chartDivID, settingOption, taskItems) => {
var g = new JSGantt.GanttChart(document.getElementById(chartDivID), 'day');
g.setOptions(settingOption);
taskItems.forEach(taskItem => {
g.AddTaskItemObject(taskItem);
});
g.Draw();
}
</script>
</head>
Then in your razor file, you add a DIV to show Gantt, prepare chart data and pass them to javascript function defined above. That is it!
...
@inject Microsoft.JSInterop.IJSRuntime _jsRuntime
<button @onclick="ShowGantt">Show Gantt</button>
<div style="position:relative" class="gantt" id="GanttChartDIV"></div>
@code{
private async Task ShowGantt()
{
var options = new
{
vCaptionType = "Complete", // Set to Show Caption : None,Caption,Resource,Duration,Complete,
vQuarterColWidth = 36,
vDateTaskDisplayFormat = "day dd month yyyy", // Shown in tool tip box
vDayMajorDateDisplayFormat = "mon yyyy - Week ww",// Set format to dates in the "Major" header of the "Day" view
vWeekMinorDateDisplayFormat = "dd mon", // Set format to display dates in the "Minor" header of the "Week" view
vLang = "en",
vShowTaskInfoLink = 1, // Show link in tool tip (0/1)
vShowEndWeekDate = 0, // Show/Hide the date for the last day of the week in header for daily
vAdditionalHeaders = new
{ // Add data columns to your table
category = new
{
title = "Category"
},
sector = new
{
title = "Sector"
}
},
vUseSingleCell = 10000, // Set the threshold cell per table row (Helps performance for large data.
vFormatArr = new string[] { "Day", "Week", "Month", "Quarter" }, // Even with setUseSingleCell using Hour format on such a large chart can cause issues in some browsers,
};
var taskItems = new[]{
new {
pID = 1,
pName = "Define Chart <strong>API</strong>",
pStart = "2017-02-25",
pEnd = "2017-03-17",
pPlanStart = "2017-04-01",
pPlanEnd = "2017-04-15 12:00",
pClass = "ggroupblack",
pLink = "",
pMile = 0,
pRes = "Brian",
pComp = 0,
pGroup = 0,
pParent = 0,
pOpen = 1,
pDepend = "",
pCaption = "",
pCost = 1000,
pNotes = "Some Notes text",
category = "My Category",
sector = "Finance"
},
new {
pID = 2,
pName = "Develop Chart <strong>API</strong>",
pStart = "2017-03-01",
pEnd = "2017-04-29",
pPlanStart = "2017-04-01",
pPlanEnd = "2017-04-15 12:00",
pClass = "ggroupblack",
pLink = "",
pMile = 0,
pRes = "Brian",
pComp = 0,
pGroup = 0,
pParent = 0,
pOpen = 1,
pDepend = "",
pCaption = "",
pCost = 1000,
pNotes = "Some Notes text",
category = "My Category",
sector = "Finance"
}
};
await _jsRuntime.InvokeVoidAsync("showGantt", new object[] { "GanttChartDIV", options, taskItems });
}
}
Answered By – ch_g
Answer Checked By – Mildred Charles (BugsFixing Admin)