Highcharts is working when not calling Gantt chart in other views. I've played around trying to get this Gantt chart to work. Looks like there is a conflict with import map only calling highcharts and highcharts.ganttChart is not found. I've tried added the src url through a script tag directly in the html view but still getting this error.
Error msg <
Uncaught (in promise) TypeError: Highcharts.ganttChart is not a function
>
Javascript controller
```
import {Controller} from "#hotwired/stimulus"
export default class extends Controller {
connect() {
let today = new Date(),
day = 1000 * 60 * 60 * 24;
today.setUTCHours(0);
today.setUTCMinutes(0);
today.setUTCSeconds(0);
today.setUTCMilliseconds(0);
today = today.getTime();
let dateFormat = Highcharts.dateFormat;
let series
let chart; // global
async function requestData() {
const response = await fetch('http://localhost:3000/api/v1/charts/index');
if (response.ok) {
const data = await response.json();
series = data.map(function (job, i) {
let data = job.deals.map(function (phase) {
return {
id: 'deal-' + i,
project: phase.project,
client: phase.client,
phase: phase.phase,
start: new Date(phase.from).getTime(),
end: new Date(phase.to).getTime(),
y: i
};
});
return {
name: job.name,
data: data,
current: job.deals[job.current]
};
});
setTimeout(requestData, 1000);
console.log(series);
chart = Highcharts.ganttChart('container', {
series: series,
title: {
text: 'Crew Schedule'
},
tooltip: {
pointFormat: '<span>Client {point.client}</span><br/>' +
'<span>Project: {point.project}</span><br/>' +
'<span>Phase: {point.phase}</span><br/>' +
'<span>From: {point.start:%e. %b}</span><br/><span>To: {point.end:%e. %b}</span>'
},
lang: {
accessibility: {
axis: {
xAxisDescriptionPlural: 'The chart has a two-part X axis showing time in both week numbers and days.',
yAxisDescriptionSingular: 'The chart has a tabular Y axis showing a data table row for each point.'
}
}
},
scrollbar: {
enabled: true
},
rangeSelector: {
enabled: true,
selected: 0
},
accessibility: {
keyboardNavigation: {
seriesNavigation: {
mode: 'serialize'
}
},
point: {
valueDescriptionFormat: 'Assigned to {point.project} from {point.x:%A, %B %e} to {point.x2:%A, %B %e}.'
},
series: {
descriptionFormatter: function (series) {
return series.name + ', job ' + (series.index + 1) + ' of ' + series.chart.series.length + '.';
}
}
},
xAxis: {
currentDateIndicator: true
},
navigator: {
enabled: true,
liveRedraw: true,
series: {
type: 'gantt',
pointPlacement: 0.5,
pointPadding: 0.25,
accessibility: {
enabled: false
}
},
yAxis: {
min: 0,
max: 3,
reversed: true,
categories: []
}
},
yAxis: {
type: 'category',
grid: {
columns: [{
title: {
text: 'Crew'
},
categories: series.map(function (s) {
return s.name;
})
}]
}
}
})
}
return chart;
}
window.addEventListener('load', (event) => {
requestData();
});
}
}
I am plotting a chart with ‘y’ axis being numeric values and ‘x’ axis being date time values.
I was able to process a JSON object of 3000 items. However, because of our business rules, we also need to display the time: hours + minutes in the chart’s tooltips.
This changed everything!
Now the chart takes about 15 seconds to plot 2000 records. This is unacceptable.
I can see clearly that when I remove the time part of my Date object the charts works perfectly. It is just when added the hours and minutes that performance gets affected.
Trying different things I realized that your charts should support the amount of data I am using since it is not massive.
We love the charts but performance is key for us to continue using your products.
Can you help me with this issue?
Please check this fiddle so you can understand my problem. Feel free to remove the hours and minutes variables from the DateUtc creation:
https://jsfiddle.net/17a3jry9/7/
Thanks in advance!
var pointStart = new Date();
var data = [{"date":"2017-11-08","time":"1712","perc":10},{"date":"2017-11-08","time":"1608","perc":10},{"date":"2017-11-08","time":"1506","perc":10},{"date":"2017-11-08","time":"1408","perc":10},{"date":"2017-11-08","time":"1309","perc":10},{"date":"2017-11-08","time":"1207","perc":10},{"date":"2017-11-08","time":"1110","perc":10},{"date":"2017-11-08","time":"1003","perc":10},{"date":"2017-11-08","time":"0910","perc":10},{"date":"2017-11-08","time":"0810","perc":10},{"date":"2017-11-08","time":"0708","perc":10},{"date":"2017-11-09","time":"1710","perc":10},{"date":"2017-11-09","time":"1604","perc":10},{"date":"2017-11-09","time":"1510","perc":10},{"date":"2017-11-09","time":"1406","perc":10},{"date":"2017-11-09","time":"1310","perc":10},{"date":"2017-11-09","time":"1205","perc":10},{"date":"2017-11-09","time":"1107","perc":10},{"date":"2017-11-09","time":"1010","perc":10},{"date":"2017-11-09","time":"0912","perc":10},{"date":"2017-11-09","time":"0806","perc":10}{"date":"2018-10-25","time":"0709","perc":10},{"date":"2018-10-25","time":"1009","perc":10},{"date":"2018-10-25","time":"1208","perc":10},{"date":"2018-10-25","time":"1309","perc":10},{"date":"2018-10-25","time":"1410","perc":10},{"date":"2018-10-25","time":"1510","perc":10},{"date":"2018-10-25","time":"1702","perc":10},{"date":"2018-10-26","time":"1409","perc":10},{"date":"2018-10-26","time":"0710","perc":10},{"date":"2018-10-26","time":"1505","perc":10},{"date":"2018-10-26","time":"1704","perc":10},{"date":"2018-10-29","time":"0708","perc":10},{"date":"2018-10-29","time":"1007","perc":10},{"date":"2018-10-29","time":"1208","perc":10},{"date":"2018-10-29","time":"1406","perc":10},{"date":"2018-10-29","time":"1509","perc":10},{"date":"2018-10-29","time":"1610","perc":10},{"date":"2018-10-30","time":"0710","perc":10},{"date":"2018-10-30","time":"1010","perc":10},{"date":"2018-10-30","time":"1207","perc":10},{"date":"2018-10-30","time":"1409","perc":10},{"date":"2018-10-30","time":"1510","perc":10},{"date":"2018-10-30","time":"1709","perc":10},{"date":"2018-10-31","time":"0708","perc":10},{"date":"2018-10-31","time":"1009","perc":10},{"date":"2018-10-31","time":"1206","perc":10},{"date":"2018-10-31","time":"1409","perc":10},{"date":"2018-10-31","time":"1509","perc":10},{"date":"2018-10-31","time":"1708","perc":10},{"date":"2018-11-01","time":"0707","perc":10},{"date":"2018-11-01","time":"1007","perc":10},{"date":"2018-11-01","time":"1108","perc":10},{"date":"2018-11-01","time":"1250","perc":10},{"date":"2018-11-01","time":"1509","perc":10},{"date":"2018-11-01","time":"1407","perc":10},{"date":"2018-11-01","time":"1709","perc":10},{"date":"2018-11-02","time":"0708","perc":10},{"date":"2018-11-02","time":"1007","perc":10},{"date":"2018-11-02","time":"1108","perc":10},{"date":"2018-11-02","time":"1210","perc":10},{"date":"2018-11-02","time":"1407","perc":10},{"date":"2018-11-02","time":"1509","perc":10},{"date":"2018-11-02","time":"1608","perc":10},{"date":"2018-11-02","time":"1715","perc":10},{"date":"2018-11-05","time":"0707","perc":10},{"date":"2018-11-05","time":"1007","perc":10},{"date":"2018-11-05","time":"1209","perc":10},{"date":"2018-11-05","time":"1408","perc":10},{"date":"2018-11-05","time":"1509","perc":10},{"date":"2018-11-05","time":"1611","perc":10},{"date":"2018-11-05","time":"1715","perc":10},{"date":"2018-11-06","time":"0708","perc":10},{"date":"2018-11-06","time":"1007","perc":10},{"date":"2018-11-06","time":"1201","perc":10},{"date":"2018-11-06","time":"1410","perc":10},{"date":"2018-11-06","time":"1510","perc":10},{"date":"2018-11-06","time":"1709","perc":10},{"date":"2018-11-07","time":"0708","perc":10},{"date":"2018-11-07","time":"1007","perc":10},{"date":"2018-11-07","time":"1209","perc":10},{"date":"2018-11-07","time":"1307","perc":10},{"date":"2018-11-07","time":"1410","perc":10},{"date":"2018-11-07","time":"1506","perc":10},{"date":"2018-11-07","time":"1708","perc":10},{"date":"2018-11-08","time":"0707","perc":10},{"date":"2018-11-08","time":"1009","perc":10},{"date":"2018-11-08","time":"1207","perc":10},{"date":"2018-11-08","time":"1309","perc":10},{"date":"2018-11-08","time":"1412","perc":10},{"date":"2018-11-08","time":"1508","perc":10}];
var newSeries = data.map(function (key) {
var utilDate = new Date(key.date);
var hours = parseInt(key.time.slice(0, 2));
var minutes = parseInt(key.time.slice(2, 4));
return { x: Date.UTC(utilDate.getFullYear(), utilDate.getMonth(), utilDate.getDate(), hours, minutes), y: key.perc, key: key.id };
});
Highcharts.stockChart('container', {
xAxis: {
type: 'datetime',
title: {
text: 'Date'
}
},
yAxis: {
title: {
text: 'Util (%)'
},
min: 0
},
tooltip: {
headerFormat: '<b>{point.x: %A, %b %e, %I:%M %p}</b><br>'
//pointFormat: '{point.x:%e. %b}: {point.y:.2f} m'
},
colors: ['teal', 'red'],
// Define the data points. All series have a dummy year
// of 1970/71 in order to be compared on the same x axis. Note
// that in JavaScript, months start at 0 for January, 1 for February etc.
series: [{
name: "Util",
data: newSeries
}],
title: {
text: 'Util Movement'
},
subtitle: {
text: ""
},
plotOptions: {
series: {
cursor: 'pointer',
turboThreshold: 10000,
point: {
events: {
}
},
label: {
connectorAllowed: false
},
pointStart: pointStart.getFullYear()
}
},
responsive: {
rules: [{
condition: {
maxWidth: 200
},
chartOptions: {
legend: {
layout: 'horizontal',
align: 'center',
verticalAlign: 'bottom'
}
}
}]
}
});
Please take a look to the browser console, you have information there about error: Highcharts error #15: www.highcharts.com/errors/15.
This means that you have unsorted data, so you need to sort them:
newSeries.sort(function(a, b){
return a.x - b.x
});
Live demo: https://jsfiddle.net/BlackLabel/onq0Lurx/
I am using High Charts and using a Line chart for visualization. I have some bad data in the series data which is replaced with nulls and my line on the trend is not connected (bad data is not plotted on the trend, hence disconnected line) which is fine.
My issue is that I have some good data in between some bad data like (bad,bad,good,bad,bad,good,bad) this good data is shown as tool tips on my trend but no data point is shown on the trend. Is there any configuration option with in high charts so that I could plot individual data points along with disconnected line?
As you may see in the trend image, that the line series is broken but there are still some valid data points among bad data points which are not visible on the trend.
Here is how I initialize my highchart
initializeChart() {
Highcharts.setOptions({global: { useUTC : false }});
let yAxesLoc = this.getYAxes(this.props.signals);
// Update the yAxes to use the unit abbrevation instead of the full name
let dfdArr = new Array();
yAxesLoc.forEach(function(yAxis) {
if(!yAxis.unitName) {
return;
}
dfdArr.push(AfModel.GetUnitByName(yAxis.unitName, function(unit) {
if (unit) {
yAxis.unit = unit.Abbreviation;
yAxis.title = {text: unit.Abbreviation};
}
}));
});
let that = this;
// Only all the units are loaded, then we initialize Highcharts
return $.when.apply(null, dfdArr)
.always(function() {
that.yAxes = yAxesLoc; // Set all the axis
that.colorGenerator = new ColorGenerator(); // Initialize a new color generator for this trend
that.chart = Highcharts.chart(that.state.chartDivId, {
credits: {
enabled: false
},
title: null,
chart: {
zoomType:'xy',
events: {
redraw: function(){
// Remove all frozen tooltips
if (that.cloneToolTip) {
that.chart.container.firstChild.removeChild(that.cloneToolTip);
that.cloneToolTip = null;
}
if (that.cloneToolTip2) {
that.cloneToolTip2.remove();
that.cloneToolTip2 = null;
}
}
}
},
xAxis: {
type:'datetime',
min: that.props.startDateTime.getTime(),
max: that.props.endDateTime.getTime(),
labels: {
rotation: 315,
formatter: function() {
return new Date(this.value).toString('dd-MMM-yy HH:mm')
}
}
},
tooltip: {
shared: true,
crosshairs: true,
valueDecimals: 2,
formatter: function(tooltip) {
return HcUtils.interpolatedTooltipFormatter.call(this, tooltip, function(yVal, series) {
return NumberUtils.isNumber(yVal) ?
(series.yAxis.userOptions.unit) ?
NumberUtils.round(yVal, 4) + " " + series.yAxis.userOptions.unit
: NumberUtils.round(yVal, 4)
: yVal;
});
}
},
yAxis: that.yAxes,
series: {
animation: false,
marker: {enabled: false}
},
plotOptions: {
line: {
animation: false,
marker: {
enabled:false
}
},
series: {
connectNulls: false,
connectorAllowed: false,
cursor: 'pointer',
point: {
events: {
// This event will freeze the tooltip when the user clicks
// Inspired by https://stackoverflow.com/questions/11476400/highcharts-keep-tooltip-showing-on-click
click: function() {
if (that.cloneToolTip) {
that.chart.container.firstChild.removeChild(that.cloneToolTip);
}
if (that.cloneToolTip2) {
that.cloneToolTip2.remove();
}
that.cloneToolTip = this.series.chart.tooltip.label.element.cloneNode(true);
that.chart.container.firstChild.appendChild(that.cloneToolTip);
that.cloneToolTip2 = $('.highcharts-tooltip').clone();
$(that.chart.container).append(that.cloneToolTip2);
}
}
}
}
}
});
})
}
Kindly suggest.
Thanks.
Highcharts draws a line only between two subsequent no-null points. Single points can be visualized as markers (which you disabled in your code).
Here's a live demo that shows this issue: http://jsfiddle.net/BlackLabel/khp0e8qr/
series: [{
data: [1, 2, null, 4, null, 1, 7],
marker: {
//enabled: false // uncomment to hide markers
}
}]
API reference: https://api.highcharts.com/highcharts/series.line.marker
It seems to work fine in the latest version of Highcharts. The data points are visible.
Please have a look
Visible points: https://codepen.io/samuellawrentz/pen/XqLZop?editors=0010
I am generating a Project Cumulative Flow Chart, which is based on the Project name that I fetch using a "find," however I can't get it working.
Here is the Problem:
1) The "Find" in my code is just fetching one kind of project name, "FE," however, I have a lot of other Project name such as FE, BE, VisualRF, etc. I am not sure what's going on
2) I return this to "storeConfig" inside the chart and then I want try to give "Name" to the "stateFieldName." This is not working! I don't see any graph at all.
Here is the code.
_chart2: function() {
var projectName = this.getContext().getProject()._refObjectName;
console.log("========");
console.log(projectName); <<<<<<<<<< This always prints one name'FE' (My project name are FE, BE, etc)
this.chart = {
xtype: 'rallychart',
storeType: 'Rally.data.lookback.SnapshotStore',
storeConfig: this._getStoreForChart2(),
calculatorType: 'Rally.example.CFDCalculator',
calculatorConfig: {
stateFieldName: this.getContext().getProject()._refObjectName, <<<<< I think usage is not fetching name of all projects
stateFieldValues: ['FE','BE','VisualRF']
},
width: 1000,
height: 600,
chartConfig: this._getChart2Config()
};
this.chartContainer.add(this.chart);
},
_getStoreForChart2: function() {
var obj1 = {
find: {
_TypeHierarchy: { '$in' : [ 'Defect' ] },
Children: null,
_ProjectHierarchy: this.getContext().getProject().ObjectID,
_ValidFrom: {'$gt': Rally.util.DateTime.toIsoString(Rally.util.DateTime.add(new Date(), 'day', -30)) },
State: "Open",
},
fetch: ['Severity','Project','ObjectID','FormattedID'],
hydrate: ['Severity','Project','ObjectID','FormattedID'],
sort: {
_ValidFrom: 1
},
context: this.getContext().getDataContext(),
limit: Infinity,
val: this.Name,
};
return obj1;
},
Though this should not matter but here is the code for the high chart function I am calling above
_getChart2Config: function() {
console.log("starting chart config");
return {
chart: {
zoomType: 'xy'
},
title: {
text: 'Chart2'
},
xAxis: {
tickmarkPlacement: 'on',
tickInterval: 20,
title: {
text: 'Date'
}
},
yAxis: [
{
title: {
text: 'Count'
}
}
],
plotOptions: {
series: {
marker: {
enabled: false
}
},
area: {
stacking: 'normal'
}
}
};
},
Down below you can see 'FE' getting printed:
Thanks a lot!
Kay
stateFieldName is the field which is used to calculate the CFD- usually ScheduleState or a custom dropdown field like KanbanState that captures your process. The stateFieldValues should be the values of that field (Defined, In-Progress, Accepted, Completed, etc.) This doesn't deal with projects at all. Definitely remember to include that field in your hydrate and fetch as well.