I have been struggling with this one for days now, really need some help. I need to apply gradient colors and some custom styling to our ChartJs bar chart, that contains call reporting data which comes from the back-end server. I found a way how to apply the styles and gradients, but can't figure out how to configure datasets to display correct data from the server, instead of some random numbers (eg. 10,20,30), like I tried for gradientGreen below. Any ideas?
//main html
<div class="row mb-4 mt-4">
<div class="col-9">
<h4 class="text-center">Call Distribution</h4>
#await Component.InvokeAsync("HourlyCallTotals", new { from = Model.From, to = Model.To, customer = Model.customer, site = Model.site })
</div>
//component html
#model CallReporter.ViewModels.BasicFilter
<div id="hourlyChart">
</div>
<script>
var HourlyCallData = #Html.RenderAction("HourlyTotals", "Calls", "", new { from = Model.from.ToString("s"), to = Model.to.ToString("s"), customer = Model.customer, site = Model.site })
</script>
//relevant part of JS function for Chart
function hoursChartAjax() {
var hourlyChart = $('#hourlyChart').html('<canvas width="400" height="300"></canvas>').find('canvas')[0].getContext('2d');
// set gradients for bars
let gradientGreen = hourlyChart.createLinearGradient(0, 0, 0, 400);
gradientGreen.addColorStop(0, '#66d8b0');
gradientGreen.addColorStop(1, '#1299ce');
let gradientBlue = hourlyChart.createLinearGradient(0, 0, 0, 400);
gradientBlue.addColorStop(0, '#1299ce');
gradientBlue.addColorStop(1, '#2544b7');
if (hourlyChart !== undefined) {
$.get(base + "Calls/HourlyTotals", { from: from.format(), to: to.format(), customer: currentCustomer.id, site: currentSite }, function (data) {
// set the default fonts for the chart
Chart.defaults.global.defaultFontFamily = 'Nunito';
Chart.defaults.global.defaultFontColor = '#787878';
Chart.defaults.global.defaultFontSize = 12;
var chart = new Chart(hourlyChart, {
type: 'bar',
data: {
labels: ['6AM', '9AM', '12AM', '3PM', '6PM', '9PM', '12PM'],
datasets: [
{
label: 'Total outgoing calls',
backgroundColor: gradientBlue,
data: HourlyCallData
},
{
label: 'Total incoming calls',
backgroundColor: gradientGreen,
data: [10, 20, 30]
}
]
},
//relevant part of back-end code that returns call data as Json
totalsContainer.Totals = allCallsHourly.OrderBy(x => x.Date).ToList();
return Json(new
{
labels = totalsContainer.Totals.Select(x => x.Date.ToString("hh tt")),
datasets = new List<object>() {
new { label = "Total Outgoing Calls", backgroundColor = "#1299CE", data = totalsContainer.Totals.Select(x => x.TotalOutgoingCalls) },
new { label = "Total Incoming Calls", backgroundColor = "#00B050", data = totalsContainer.Totals.Select(x => x.TotalIncomingCalls) } }
});
Attached img with console log and error, after trying solution below:
If the data comes formatted in the right way, you can just write this:
var chart = new Chart(hourlyChart, {
type: 'bar',
data: data: data
}
If not you could do it like so:
var chart = new Chart(hourlyChart, {
type: 'bar',
data: {
labels: data.labels,
datasets: [
{
label: data.datasets[0].label,
backgroundColor: gradientBlue,
data: data.datasets[0].data
},
{
label: data.datasets[1].label,
backgroundColor: gradientGreen,
data: data.datasets[1].data
}
]
}
}
Related
I have a model
class paidparking(models.Model):
adress = models.ForeignKey(Parking, on_delete=models.SET_NULL, null=True, verbose_name='Адрес парковки')
carnumber = models.CharField(max_length=150,verbose_name='Номер автомобиля')
amountoftime = models.IntegerField(verbose_name='Количество времени')
price = models.FloatField(verbose_name='Цена')
telephone = models.CharField(max_length=20,verbose_name='Номер телефона')
email = models.EmailField(verbose_name='Электронный адрес',null=True,blank=True )
datetimepaidparking = models.DateTimeField(auto_now_add=True, verbose_name='Дата и время оплаты')
expirationdate = models.DateField(null=True,verbose_name='Дата начала срока действия')
expirationtime = models.TimeField(null=True,verbose_name='Время начала срока действия')
enddateandtime = models.DateTimeField(null=True,blank=True,verbose_name='Окончание срока действия')
There is a function
startdate = datetime.strptime(request.POST['startdate'], '%d.%m.%Y')
enddate = datetime.strptime(request.POST['enddate'], '%d.%m.%Y')
paymentparking = paidparking.objects.filter(expirationdate__range=(startdate, enddate)).values('expirationdate',
'price')
In JS, I get this data and draw graphs
$.ajax({
type: "POST",
url: "date",
data: {
'startdate': finalDateStrStart, 'enddate': finalDateStrEnd,
},
dataType: "json",
cache: false,
success: function (data) {
if (data.result) {
var expirationdates = [];
var prices = [];
for (let i = 0; i < data.result.length; i++) {
expirationdates.push(data.result[i].expirationdate);
prices.push(data.result[i].price);
}
if(window.chart instanceof Chart)
{
window.chart.destroy();
}
var ctx = document.getElementById("line").getContext("2d");
var chart = new Chart(ctx, {
type: 'line',
data: {
labels: expirationdates,
datasets: [{
label: 'Оплата парковочных пространств',
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(144,204,244)',
data: prices,
}]
},
options: {
}
});
var ctx = document.getElementById("bar").getContext("2d");
var chart = new Chart(ctx, {
type: 'bar',
data: {
labels: expirationdates,
datasets: [{
label: 'Оплата парковочных пространств',
backgroundColor: 'rgb(144,204,244)',
borderColor: 'rgb(255, 99, 132)',
data: prices,
}]
},
options: {
}
});
}
}
});
return JsonResponse({'result': list(paymentparking)})
As a result, I get:
I need to make a query that would sum the values from the price field for the same date in the expirationdate field
Right now my query outputs all records if the expirationdate field falls within the date range between startdate and enddate
You have to use the trick with values and annotate as described very well here:
from django.db.models import Sum
qs = paidparking.objects.values('expirationdate').annotate(Sum('price'))
# if you want to order by date:
qs = qs.order_by('expirationdate')
This will output a queryset a list of dictionnaries containing expirationdate and price__sum as keys.
Edit:
For your question in the comment, just add the filter at the beginning of the query:
paidparking.objects.filter(expirationdate__range=(startdate, enddate)).values('expirationdate').annotate(Sum('price'))
You need to use annotate in django orm to get the output for the same.
from django.db.models import Sum
PaidParking.objects.values('expirationdate', 'price') \
.annotate(parking_price=Sum('price')) \
.order_by('-expirationdate')
I suppose this answer is suffice for the asked query.
Reference: For Basic understanding of the query how it works follow this link
I am getting super slow page loads (~10s on chrome, ~15 using firefox) when rendering a page with 10 Plotly charts (lines and bars) with very few data points on each chart (<100 per chart).
I'm not getting any errors, and my js code runs in ~300ms without errors (i used console.log() with timestamps). there is no network activity whilst waiting for the charts to render.
Am I doing something wrong?
The charts are rendered using a loop which calls a function with different parameters:
ajax call:
$.ajax({
method: "GET",
url: '/app/api/dashboard/data',
success: function(payload){
console.log('starting bal hist')
var bal_hist = JSON.parse(payload.balance_history);
balanceHistoryChart(elementID='balanceHistory', data=bal_hist);
console.log('ending bal hist')
var data = JSON.parse(payload.aggregated);
data = data.map(function(object) {
object.value_date = new Date(object.value_date);
return object
})
var allCategories = data.map(x => x.category);
var categories = new Set(allCategories);
console.log('starting loop')
for (var category of categories){
var chartID = category.toLowerCase().replace(' ','_') + '_chart';
console.log('starting catChart')
catChart(elementID=chartID, category=category, data=data)
console.log('ending catChart')
}
console.log('end loop')
},
error: function(error_data){
console.log("error")
console.log(error_data)
}
})
function that creates the plotly charts:
function catChart(elementID, category, data) {
let filterForCat = data.filter(obj => obj.category === category);
let dates = filterForCat.map(function(obj) {
return obj.value_date
});
let weeklyTotal = filterForCat.map(function(obj) {
return obj.weekly_total
});
let movingAv = filterForCat.map(function(obj) {
return obj.moving_av
});
var movingAvSeries = {
type: "scatter",
mode: "lines",
name: '4-week average',
x: dates,
y: movingAv,
line: {color: 'green'}
};
var weeklyTotalSeries = {
type: "bar",
name: 'weekly totals',
x: dates,
y: weeklyTotal,
line: {color: 'red'}
};
var layout = {
showlegend: false,
title: false,
margin: {
l: 30,
r: 20,
b: 20,
t: 20,
pad: 5
},
};
var data = [ movingAvSeries, weeklyTotalSeries ];
var config = {
responsive: true,
displayModeBar: false,
};
I have a plot.ly that inputs a number and digits to view the number of frequency. Per say you enter 111222333 and digits 1,2,3. It will display a bar graph of the repetition of each digit. Everything seems to work except one detail, whenever I add random numbers, the graph does not display in order. Here is an example
Below is my JS code:
function plotIt() {
event.preventDefault();
var entireNumber = document.getElementById('fullNumber').value.split("");
var number = document.getElementById('digit').value.split("");
var matchedNumbers = [];
entireNumber.forEach(digit => {
if (number.includes(digit)) {
matchedNumbers.push(digit);
}
});
var layout = {
categoryorder: 'category ascending',
xaxis: {
type: 'category',
title: 'Values',
},
yaxis: {
title: '# of repetitions'
},
title:'Count'
};
var histElements = {
x: matchedNumbers,
type: 'histogram',
marker: {
color: 'rgba(235, 77, 75,1.0);',
},
};
var data = [histElements];
//Using ID for div to plot the graph
Plotly.newPlot('graph', data, layout,{scrollZoom:true});
}
You are using categoryorder: 'category ascending' in layout which does not exist for histograms in Plotly. As of July 2018 you cannot sort categorical data in histograms. But simply sorting your array before passing it to Plotly should work.
function plotIt() {
var entireNumber = document.getElementById('fullNumber').value.split("");
var number = document.getElementById('digit').value.split("");
number.sort();
var matchedNumbers = [];
entireNumber.forEach(digit => {
if (number.includes(digit)) {
matchedNumbers.push(digit);
}
});
matchedNumbers.sort();
var layout = {
xaxis: {
type: 'category',
title: 'Values',
}
};
var histElements = {
x: matchedNumbers,
type: 'histogram'
};
var data = [histElements];
Plotly.newPlot('graph', data, layout);
}
var button = document.getElementById('button');
button.addEventListener("click", plotIt(), false);
<script src="https://cdn.plot.ly/plotly-latest.min.js"></script>
<form>
<input type='number' id='fullNumber' value='144445522123' >
<input type='number' id='digit' value='0123456789'>
</form>
<button type="button" id='button'>Plot me!</button>
<div id='graph'>
</div>
Here is chart script using chart. js i am using chart in mvc 4 chart are not show ,
data are shore in variable but when pass data from controller to view then data or not show in chart, error is system.string[] or in labels when i put in labels then array data are show when i check in browser console but error is something like this inactive is not define . please review the code tell me where i am wrong.
<script>
var PieChartData =
{
labels: [#ViewBag.b],
datasets: [{
label: 'ProductWise Sales Count',
backgroundColor: [
"#f990a7",
"#aad2ed",
"#9966FF",
"#99e5e5",
"#f7bd83",
],
borderWidth: 2,
data: [#ViewBag.a]
}]
};
window.onload = function () {
var ctx1 = document.getElementById("Piecanvas").getContext("2d");
window.myBar = new Chart(ctx1,
{
type: 'pie',
data: PieChartData,
options:
{
title:
{
display: true,
text: "ProductWise Sales Count"
},
responsive: true,
maintainAspectRatio: true
}
});
}
</script>
Now Here is Controler
ICharts _ICharts;
public ChartController()
{
_ICharts = new mchart();
}
[HttpGet]
public ActionResult PieChart()
{
try
{
float[] Total;
string[] status;
_ICharts.mTotalMember(out Total, out status);
ViewBag.a = Total;
ViewBag.b = status;
return View();
}
catch (Exception)
{
throw;
}
}
and this is my function
public class mchart : ICharts
{
public void mTotalMember(out float [] Total, out string[] Status)
{
using (SqlConnection con = new SqlConnection(ConfigurationManager.ConnectionStrings["Real"].ToString()))
{
var productdata = con.Query<Member>("Sp_testing", null, null, true, 0, CommandType.StoredProcedure).ToList();
var varTotal = (from temp in productdata
select temp.Percentage).ToArray();
var varStatus = (from temp in productdata
select temp.LeadStatus).ToArray();
Total = varTotal;
Status = varStatus;
}
}
}
Here is my function
void mTotalMember(out float[] Total, out string[] status);
Use JsonConvert.SerializeObject along with Html.Raw method to get a javascript array from the ViewBag item. You do not need to wrap it with [ and ] as the result of the expression #Html.Raw(JsonConvert.SerializeObject(ViewBag.b)) will be an array.
var myLabels = #Html.Raw(JsonConvert.SerializeObject(ViewBag.b));
var myData = #Html.Raw(JsonConvert.SerializeObject(ViewBag.a));
//Let's verify it
console.log(myLabels);
console.log(myData);
var PieChartData =
{
labels : myLabels,
datasets: [{
label: 'ProductWise Sales Count',
backgroundColor: [
"#f990a7",
"#aad2ed",
"#9966FF",
"#99e5e5",
"#f7bd83",
],
borderWidth: 2,
data: myData
}]
};
Ok I have a graph using Highcharts.JS that is populated by an api call providing it with XML data.
I have managed to get the data to push and display on the graph as such, but now I am having the issue of "What happens when there is no data for "x" component" In which I found out that it makes the whole graph blank until you click to hide "x" component on the legend.
So I was thinking that I could probably do some conditional to have it check if there is actually data in the array that is made from the XML.
<!DOCTYPE html>
<html>
<head>
<title>Graph</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script type="text/javascript" src="https://code.highcharts.com/highcharts.js"> </script>
<script>
$(document).ready(function() {
var sgaxml = 'https://sga.quickbase.com/db/bjmdensiu?apptoken=beadyrucxguavbx5isubd6iaqpe&act=API_DoQuery&query=%7B14.EX.%27_FID_9%7D&clist=7.24.25.26.27.28.29.30.31.32.33.34.35.36.37'
var options = {
chart: {
renderTo: 'container',
type: 'column'
},
title: {
text: 'Components Over Time'
},
xAxis: {
categories: []
},
yAxis: {
title: {
text: 'Concentration%'
}
},
series: []
};
// Load the data from the XML file
$.get(sgaxml, function(xml) {
// Split the lines
var xml = $(xml).find('record');
// Variables for the component series
var seriesH = {
name: 'Hydrogen',
data: []
};
var seriesHe = {
name: 'Helium',
data: []
};
var seriesO = {
name: 'Oxygen',
data: []
};
var seriesHs = {
name: 'Hydrogen Sulfide',
data: []
};
var seriesN = {
name: 'Nitrogen',
data: []
};
var seriesC = {
name: 'Carbon Dioxide',
data: []
};
var seriesM = {
name: 'Methane',
data: []
};
var seriesE = {
name: 'Ethane',
data: []
};
var seriesP = {
name: 'Propane',
data: []
};
var seriesIb = {
name: 'Iso-Butane',
data: []
};
var seriesNb = {
name: 'N-Butane',
data: []
};
var seriesIp = {
name: 'Iso-Pentane',
data: []
};
var seriesNp = {
name: 'N-Pentane',
data: []
};
var seriesHex = {
name: 'Hexanes+',
data: []
};
xml.each(function (i, record) {
options.xAxis.categories.push(new Date(parseInt($(record).find('sample_date').text())));
seriesH.data.push(parseFloat($(record).find('hydrogen').text()));
seriesHe.data.push(parseFloat($(record).find('helium').text()));
seriesO.data.push(parseFloat($(record).find('oxygen').text()));
seriesHs.data.push(parseFloat($(record).find('hydrogen_sulfide').text()));
seriesN.data.push(parseFloat($(record).find('nitrogen').text()));
seriesC.data.push(parseFloat($(record).find('co2').text()));
seriesM.data.push(parseFloat($(record).find('methane').text()));
seriesE.data.push(parseFloat($(record).find('ethane').text()));
seriesP.data.push(parseFloat($(record).find('propane').text()));
seriesIb.data.push(parseFloat($(record).find('iso_butane').text()));
seriesNb.data.push(parseFloat($(record).find('n_butane').text()));
seriesIp.data.push(parseFloat($(record).find('iso_pentane').text()));
seriesNp.data.push(parseFloat($(record).find('n_pentane').text()));
seriesHex.data.push(parseFloat($(record).find('hexanes_').text()));
});
console.log(seriesO);
options.series.push(seriesH);
options.series.push(seriesHe);
options.series.push(seriesO);
options.series.push(seriesHs);
options.series.push(seriesN);
options.series.push(seriesC);
options.series.push(seriesM);
options.series.push(seriesE);
options.series.push(seriesP);
options.series.push(seriesIb);
options.series.push(seriesNb);
options.series.push(seriesIp);
options.series.push(seriesNp);
options.series.push(seriesHex);
console.log('options: ', options);
var chart = new Highcharts.Chart(options);
});
});
</script>
</head>
<body>
<div id="container" style=" width: 1000px; height: 600px; margin: 0 auto "></div>
</body>
</html>
<!--
XML FROM CALL
=============
<qdbapi>
<action>API_DoQuery</action>
<errcode>0</errcode>
<errtext>No error</errtext>
<dbinfo>
<name>RESULT</name>
<desc/>
</dbinfo>
<variables>
<co2>Carbon Dioxide</co2>
<methane>methane</methane>
</variables>
<chdbids></chdbids>
<record>
<sample_date>1386892800000</sample_date>
<hydrogen>0.002</hydrogen>
<helium>0.114</helium>
<oxygen/>
<hydrogen_sulfide/>
<nitrogen>1.926</nitrogen>
<co2>0.454</co2>
<methane>82.163</methane>
<ethane>6.353</ethane>
<propane>4.760</propane>
<iso_butane>0.618</iso_butane>
<n_butane>1.819</n_butane>
<iso_pentane>0.491</iso_pentane>
<n_pentane>0.544</n_pentane>
<hexanes_>0.756</hexanes_>
<update_id>1408654196361</update_id>
</record>
<record>
<sample_date>1383782400000</sample_date>
<hydrogen>0.006</hydrogen>
<helium>0.038</helium>
<oxygen/>
<hydrogen_sulfide/>
<nitrogen>0.512</nitrogen>
<co2>0.844</co2>
<methane>83.178</methane>
<ethane>8.678</ethane>
<propane>3.631</propane>
<iso_butane>0.493</iso_butane>
<n_butane>1.097</n_butane>
<iso_pentane>0.342</iso_pentane>
<n_pentane>0.371</n_pentane>
<hexanes_>0.810</hexanes_>
<update_id>1408981434690</update_id>
</record>
<record>
<sample_date>1369699200000</sample_date>
<hydrogen>0.004</hydrogen>
<helium>0.060</helium>
<oxygen/>
<hydrogen_sulfide/>
<nitrogen>1.684</nitrogen>
<co2>0.443</co2>
<methane>77.742</methane>
<ethane>10.430</ethane>
<propane>6.842</propane>
<iso_butane>0.587</iso_butane>
<n_butane>1.482</n_butane>
<iso_pentane>0.232</iso_pentane>
<n_pentane>0.249</n_pentane>
<hexanes_>0.245</hexanes_>
<update_id>1408981112624</update_id>
</record>
</qdbapi>
I've attempted to us isnan() as I was told it would be doable with it, but that didn't have any results.
There is already a way to handle this in highcharts. See noData.
noData: {
style: {
fontWeight: 'bold',
fontSize: '15px',
color: '#303030'
}
}
You need to include an extra library (modules/no-data-to-display.js) from highcharts but it is dead simple.