Highcharts - Toggle between different data with dropdown box - meteor

The title of the question is a bit vague because its difficult to explain so please bear with me.
First off i'm using Meteor to build my application and the data is being fetched from MongoDB.
My MongoDB data looks like this:
And currently I have my highcharts large tree map pointing just to the 'BILL' category of the data. It works fine and renders the chart. The code for my chart looks like this (Unfortunately I cannot configure it to be a running working version) :
Template.chart.onCreated(function chartOnCreated() {
this.subscribe('someData');
});
Template.chart.onRendered(function chartOnRendered() {
this.autorun(() => {
if (this.subscriptionsReady()) {
const data = MyCollection.findOne({_id: "HaQpg4pxhkrGhJPsX"}).BILL;
var points = [],
categoryPoints,
categoryVal,
categoryI = 0,
issueTypePoints,
issueTypeI,
currencyPoints,
currencyI,
periodPoints,
periodI,
ECHoldingPoints,
ECHoldingI,
ECConcentrationPoints,
ECConcentrationI,
ECBPoints,
ECBI,
issueCountryPoints,
issueCountryI,
issueNamePoints,
issueNameI,
ISINPoints,
ISINI,
zeroI,
zeroPoints,
category,
issueType,
currency,
period,
ECHolding,
ECConcentration,
ECB,
issueCountry,
IssueName,
ISIN,
zero,
mil,
causeMil,
causeMilI;
for (category in data) {
if (data.hasOwnProperty(category)) {
categoryVal = 0;
categoryPoints = {
id: 'id_' + categoryI,
name: category,
color: Highcharts.getOptions().colors[categoryI]
};
issueTypeI = 0;
for (issueType in data[category]) {
if (data[category].hasOwnProperty(issueType)) {
issueTypePoints = {
id: categoryPoints.id + '_' + issueTypeI,
name: issueType,
parent: categoryPoints.id,
};
points.push(issueTypePoints);
currencyI = 0;
for (currency in data[category][issueType]) {
if (data[category][issueType].hasOwnProperty(currency)) {
currencyPoints = {
id: issueTypePoints.id + '_' + currencyI,
name: currency,
parent: issueTypePoints.id
};
points.push(currencyPoints);
periodI = 0;
for (period in data[category][issueType][currency]) {
if (data[category][issueType][currency].hasOwnProperty(period)) {
periodPoints = {
id: currencyPoints.id + '_' + periodI,
name: period,
parent: currencyPoints.id,
};
points.push(periodPoints);
ECHoldingI = 0;
for (ECHolding in data[category][issueType][currency][period]) {
if (data[category][issueType][currency][period].hasOwnProperty(ECHolding)) {
ECHoldingPoints = {
id: periodPoints.id + '_' + ECHoldingI,
name: ECHolding,
parent: periodPoints.id,
};
points.push(ECHoldingPoints);
ECConcentrationI = 0;
for (ECConcentration in data[category][issueType][currency][period][ECHolding]) {
if (data[category][issueType][currency][period][ECHolding].hasOwnProperty(ECConcentration)) {
ECConcentrationPoints = {
id: ECHoldingPoints.id + '_' + ECConcentrationI,
name: ECConcentration,
parent: ECHoldingPoints.id,
};
points.push(ECConcentrationPoints);
ECBI = 0;
for (ECB in data[category][issueType][currency][period][ECHolding][ECConcentration]) {
if (data[category][issueType][currency][period][ECHolding][ECConcentration].hasOwnProperty(ECB)) {
ECBPoints = {
id: ECConcentrationPoints.id + '_' + ECBI,
name: ECB,
parent: ECConcentrationPoints.id,
};
points.push(ECBPoints);
issueCountryI = 0;
for (issueCountry in data[category][issueType][currency][period][ECHolding][ECConcentration][ECB]) {
if (data[category][issueType][currency][period][ECHolding][ECConcentration][ECB].hasOwnProperty(issueCountry)) {
issueCountryPoints = {
id: ECBPoints.id + '_' + issueCountryI,
name: issueCountry,
parent: ECBPoints.id,
};
points.push(issueCountryPoints);
issueNameI = 0;
for (issueName in data[category][issueType][currency][period][ECHolding][ECConcentration][ECB][issueCountry]) {
if (data[category][issueType][currency][period][ECHolding][ECConcentration][ECB][issueCountry].hasOwnProperty(issueName)) {
issueNamePoints = {
id: issueCountryPoints.id + '_' + issueNameI,
name: issueName,
parent: issueCountryPoints.id,
};
points.push(issueNamePoints);
ISINI = 0;
for (ISIN in data[category][issueType][currency][period][ECHolding][ECConcentration][ECB][issueCountry][issueName]) {
if (data[category][issueType][currency][period][ECHolding][ECConcentration][ECB][issueCountry][issueName].hasOwnProperty(ISIN)) {
ISINPoints = {
id: issueNamePoints.id + '_' + ISINI,
name: ISIN,
parent: issueNamePoints.id,
};
points.push(ISINPoints);
causeMilI = 0;
for (mil in data[category][issueType][currency][period][ECHolding][ECConcentration][ECB][issueCountry][issueName][ISIN]) {
if (data[category][issueType][currency][period][ECHolding][ECConcentration][ECB][issueCountry][issueName][ISIN].hasOwnProperty(mil)) {
causeMil = {
id: ISINPoints.id + '_' + causeMilI,
name: mil,
parent: ISINPoints.id,
value: Math.round(+data[category][issueType][currency][period][ECHolding][ECConcentration][ECB][issueCountry][issueName][ISIN][mil])
};
categoryVal += causeMil.value;
points.push(causeMil);
causeMilI = causeMilI + 1;
}
}
ISINPoints = ISINPoints + 1;
}
}
issueNameI = issueNameI + 1;
}
}
issueCountryI = issueCountryI + 1;
}
}
ECBI = ECBI + 1;
}
}
ECConcentrationI = ECConcentrationI + 1;
}
}
ECHoldingI = ECHoldingI + 1;
}
}
periodI = periodI + 1;
}
}
currencyI = currencyI + 1;
}
}
issueTypeI = issueTypeI + 1;
}
}
categoryPoints.value = Math.round(categoryVal / issueTypeI);
points.push(categoryPoints);
categoryI = categoryI + 1;
}
}
Highcharts.chart('chart', {
credits: {
enabled: false
},
plotOptions: {
series: {
turboThreshold: 0,
boostThreshold: 0
}
},
series: [{
type: 'treemap',
layoutAlgorithm: 'squarified',
allowDrillToNode: true,
animationLimit: 1000,
dataLabels: {
enabled: false
},
levelIsConstant: false,
levels: [{
level: 1,
dataLabels: {
enabled: true,
},
borderWidth: 3
}],
data: points
}],
title: {
text: ''
},
},
);
}
});
});
<template name="chart">
<div id="chart" style="width: 450px; height: 260px; margin: 0 auto;"></div>
</template>
Here is a link to a JSFiddle of the chart too (But again this is not a working version just the code)
What I would like to have is a toggle drop down list containing 'BILL' 'BOND' 'MTN' and 'NOTE' and when the user selects an option the string here:
const data = MyCollection.findOne({_id: "HaQpg4pxhkrGhJPsX"}). <USERS SELECTION>;
The USERS SELECTION will be updated with their choice - For example .BILL - and the chart will render that data.
Can anybody help with how I would do that?
Many thanks,
G

You should try const data = MyCollection.findOne({_id: "HaQpg4pxhkrGhJPsX"})["<USERS SELECTION>"];
In javascript, you can access to a value of a certain JSON object field by many ways:
var obj = { key : 'value' }
var lookup = 'key'
console.log( obj.lookup ) //undefined
console.log( obj.key ) //value
console.log( obj[lookup] ) //value

Related

redux-persist, save only first 10 items using Transform

I'm trying to save only 2 items when persisting through redux-persist .
I'm perplexed why the following code won't work..
(it seems to save more than 2 items)
const myTransform = createTransform(
(inboundState, key) => {
let { openforum_threads } = inboundState
if (!openforum_threads) {
return inboundState
}
let { allIds } = openforum_threads
let STORE_NUM = 2
let storeIds = allIds.slice(0, STORE_NUM)
console.log('saving', storeIds)
let { byId } = openforum_threads
let storeById = {}
storeIds.map((id) => {
storeById[id] = byId[id]
})
openforum_threads = {
...openforum_threads,
allIds: storeIds,
byId: storeById
}
return { ...inboundState, openforum_threads}
},
(outboundState, key) => {
// convert mySet to an Array.
return outboundState
}
)

meteor template helpers function not working properly

I have 2 functions in Template.meetings.helpers, but only one function is working.
Template.meetings.helpers({
group: function() {
console.log('meeting id from helper group = ' + this.meetingId);
console.log('group id from helper group = ' + this.groupId);
return Groups.findOne({_id: this.groupId});
},
meeting: function() {
console.log('meeting id from helper meeting = ' + this.meetingId);
console.log('group id from helper meeting = ' + this.groupId);
return Meetings.findOne({_id: this.meetingId});
},
});
My console shows the following:
router.js:73 meetingId from router = ZKkLLvdCpRmrF7uXD
router.js:74 groupId from router = xFSzAHBEps2dSKcWM
meetings.js:26 meeting id from helper meeting = ZKkLLvdCpRmrF7uXD
meetings.js:27 group id from helper meeting = xFSzAHBEps2dSKcWM
router.js:
Router.route('/meetings/:_id/:groupId?', {
waitOn: function() {
return Meteor.subscribe('meeting');
return Meteor.subscribe('Group');
},
action: function () {
console.log('meetingId from router = ' + this.params._id);
console.log('groupId from router = ' + this.params.groupId);
this.render('meetings', {
data: {
meetingId: this.params._id,
groupId: this.params.groupId
}
});
},
onBeforeAction: function(){
var currentGroup = Members.find({
groupId: this.params.groupId,
memberId: Meteor.userId()
}).count();
Session.set('groupId', this.params.groupId);
var currentUser = Meteor.userId();
if(currentUser && currentGroup > 0){
this.next();
} else {
this.render("landingPage");
}
}
});
I can't figure out why the group: function() is not outputting to the console.
Any suggestions?

Summary Grid extjs

I want to get the summary of the column stay time on my grid. But I can't seem to understand or figure out how to use the summary grid in extjs. Could anyone please help me or guide me?
Here's my grid code:
Ext.ns('dlti.view.widget');
Ext.define('dlti.view.widget.PlaylistDetailsGrid' ,{
extend: 'Ext.grid.Panel',
id: 'playlist-details',
alias: 'widget.PlaylistDetailsGrid',
forceFit: true,
stripeRows: true,
selType: 'rowmodel',
autosync: true,
height: 150,
width: 950,
store: new dlti.store.PlaylistDetailsStore(),
columns: [
{
text: 'Filename',
dataIndex: 'filename',
renderer: function renderDescTarget(val, p, record) {
var desc = '';
desc = '<p style="color:#000;font-size:12px;">' + val + '</p>';
return desc;
}
},
{
text: 'Transition',
dataIndex: 'transition',
renderer: function renderDescTarget(val, p, record) {
var desc = '';
desc = '<p style="color:#000;font-size:12px;">' + val + '</p>';
return desc;
}
},
{
text: 'Stay Time',
dataIndex: 'timeframe',
renderer: function renderDescTarget(val, p, record) {
var desc = '';
desc = '<p style="color:#000;font-size:12px;">' + val + '</p>';
return desc;
}
}
]
});
You can specify summaryType and summaryRenderer like this:
summaryType: 'count',
summaryRenderer: function(value, summaryData, dataIndex) {
return ((value === 0 || value > 1) ? '(' + value + ' Tasks)' : '(1 Task)');
}
summaryType can have values like count, max, average, sum etc. and summaryRenderer is similar to the column renderer where you can give any custom logic for formatting the summary.

Asp.net webform with flot.js chart on return Json does not work

I am using ASP.NET webforms for flot charts I connected to database in test.aspx.cs file using [Webmethod] where I can return json.
I stored the return value both in textarea and $.plot(placeholder, [and also here], options) It does not print the graph in placeholder however when I do:
var data = past
the value of textarea here and run applicationn it prints to me the value.
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static List<string> GetLocation(string location)
{
List<string> result = new List<string>();
StringBuilder strQuery = new StringBuilder();
strQuery.Append("SELECT Location.Nome_Location, DATEPART(day, Statistiche.Data_Statistica) AS SDay, COUNT(Statistiche.ID_Tabella) AS Stats");
strQuery.Append(" FROM Statistiche INNER JOIN Tabelle ON Statistiche.ID_Tabella = Tabelle.ID_Tabella INNER JOIN");
strQuery.Append(" Location ON Statistiche.ID_Colonna_Statistica = Location.ID_Location");
strQuery.Append(" WHERE (Statistiche.ID_Tabella = 2) AND (Statistiche.ID_Box = 60) AND (Location.Nome_Location = 'Albilò')");
strQuery.Append("GROUP BY Location.Nome_Location, DATEPART(day, Statistiche.Data_Statistica)");
string query = strQuery.ToString();
SqlConnection con = new SqlConnection("");
SqlCommand cmd = new SqlCommand(query, con);
con.Open();
int counter = 1;
SqlDataReader dr = cmd.ExecuteReader();
while (dr.Read())
{
if (counter == 1)
{
result.Add("[{'label': 'Europe (EU27)','data':[[" + dr["SDay"].ToString() + "," + dr["Stats"].ToString() + "]");
}
else
result.Add("[" + dr["SDay"].ToString() + "," + dr["Stats"].ToString() + "]");
if (counter==31)
{
result.Add("[" + dr["SDay"].ToString() + "," + dr["Stats"].ToString() + "]]}]");
}
counter++;
}
return result;
}
$.ajax({
type: "POST",
async: true,
contentType: "application/json; charset=utf-8",
dataType: "json",
url: "test.aspx/GetLocation",
data: "{'location':'Albilò'}",
success: function drawChart(msg) {
var options = { lines: { show: true }, points: { show: true }, xaxis: { tickDecimals: 0, tickSize: 1} };
var ddata = [];
var data = msg.d;
for (var i = 0; i < 32; i++) {
ddata.push(data[i]);
}
var placeholder = $("#placeholder");
$("#txtvalue").val(ddata);
var datad = $("#txtvalue").text();
$.plot(placeholder, ddata, options);
},
error: function () {
alert("call is called111");
}
});
First of all, why do you create JSON yourself? You've already specified to return JSON in you attributes.
Refactore method to return simple array of POCO objects like
[Serializable]
public class pocoObject
{
public string Label;
..
}
Then your method should just return list of object and have attributes set up:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static List<pocoObject> GetLocation(string location)
{
...
return result; // result is list of pocoObjects
}
Flot.js is rather sensitive to data you set as source, so after this take a look at data in firebug, it should be correct json formatted data. So please visit wiki and also compare your data to working samples.
This how you can initiliaze legend names of you plot:
$(function () {
var d1 = [];
for (var i = 0; i < Math.PI * 2; i += 0.25)
d1.push([i, Math.sin(i)]);
var d2 = [];
for (var i = 0; i < Math.PI * 2; i += 0.25)
d2.push([i, Math.cos(i)]);
var d3 = [];
for (var i = 0; i < Math.PI * 2; i += 0.1)
d3.push([i, Math.tan(i)]);
$.plot($("#placeholder"), [
{ label: "sin(x)", data: d1},
{ label: "cos(x)", data: d2},
{ label: "tan(x)", data: d3}
], {
series: {
lines: { show: true },
points: { show: true }
},
xaxis: {
ticks: [0, [Math.PI/2, "\u03c0/2"], [Math.PI, "\u03c0"], [Math.PI * 3/2, "3\u03c0/2"], [Math.PI * 2, "2\u03c0"]]
},
yaxis: {
ticks: 10,
min: -2,
max: 2
},
grid: {
backgroundColor: { colors: ["#fff", "#eee"] }
}
});
});

web grid server pagination trigger multiple controller call when changing page

When I server-filter on "au" my web grid and change page, multiple call to the controller are done :
the first with 0 filtering,
the second with "a" filtering,
the third with "au" filtering.
My table load huge data so the first call is longer than others.
I see the grid displaying firstly the third call result, then the second, and finally the first call (this order correspond to the response time of my controller due to filter parameter)
Why are all that controller call made ?
Can't just my controller be called once with my total filter "au" ?
What should I do ?
Here is my grid :
$("#" + gridId).kendoGrid({
selectable: "row",
pageable: true,
filterable:true,
scrollable : true,
//scrollable: {
// virtual: true //false // Bug : Génère un affichage multiple...
//},
navigatable: true,
groupable: true,
sortable: {
mode: "multiple", // enables multi-column sorting
allowUnsort: true
},
dataSource: {
type: "json",
serverPaging: true,
serverSorting: true,
serverFiltering: true,
serverGrouping:false, // Ne fonctionne pas...
pageSize: '#ViewBag.Pagination',
transport: {
read: {
url: Procvalue + "/LOV",
type: "POST",
dataType: "json",
contentType: "application/json; charset=utf-8"
},
parameterMap: function (options, type) {
// Mise à jour du format d'envoi des paramètres
// pour qu'ils puissent être correctement interprétés côté serveur.
// Construction du paramètre sort :
if (options.sort != null) {
var sort = options.sort;
var sort2 = "";
for (i = 0; i < sort.length; i++) {
sort2 = sort2 + sort[i].field + '-' + sort[i].dir + '~';
}
options.sort = sort2;
}
if (options.group != null) {
var group = options.group;
var group2 = "";
for (i = 0; i < group.length; i++) {
group2 = group2 + group[i].field + '-' + group[i].dir + '~';
}
options.group = group2;
}
if (options.filter != null) {
var filter = options.filter.filters;
var filter2 = "";
for (i = 0; i < filter.length; i++) {
// Vérification si type colonne == string.
// Parcours des colonnes pour trouver celle qui a le même nom de champ.
var type = "";
for (j = 0 ; j < colonnes.length ; j++) {
if (colonnes[j].champ == filter[i].field) {
type = colonnes[j].type;
break;
}
}
if (filter2.length == 0) {
if (type == "string") { // Avec '' autour de la valeur.
filter2 = filter2 + filter[i].field + '~' + filter[i].operator + "~'" + filter[i].value + "'";
} else { // Sans '' autour de la valeur.
filter2 = filter2 + filter[i].field + '~' + filter[i].operator + "~" + filter[i].value;
}
} else {
if (type == "string") { // Avec '' autour de la valeur.
filter2 = filter2 + '~' + options.filter.logic + '~' + filter[i].field + '~' + filter[i].operator + "~'" + filter[i].value + "'";
}else{
filter2 = filter2 + '~' + options.filter.logic + '~' + filter[i].field + '~' + filter[i].operator + "~" + filter[i].value;
}
}
}
options.filter = filter2;
}
var json = JSON.stringify(options);
return json;
}
},
schema: {
data: function (data) {
return eval(data.data.Data);
},
total: function (data) {
return eval(data.data.Total);
}
},
filter: {
logic: "or",
filters:filtre(valeur)
}
},
columns: getColonnes(colonnes)
});
Here is my controller :
[HttpPost]
public ActionResult LOV([DataSourceRequest] DataSourceRequest request)
{
return Json(CProduitsManager.GetProduits().ToDataSourceResult(request));
}
The 3 correspond to the initial load (no filtering) and the following ones as you type in the condition of filter, similar in kendoAutocomplete but in kendoAutocomplete there are a couple of options (time and min length) that control when to send the requests (I couldn't find anything similar in grid).
If your problem is loading a huge amount of data I do recommend limiting the size of the data transmitted using pageSize in the DataSource definition. But, obviously, this is not a solution if what takes long is executing the query.
In such scenarios it is recommended to create a typing delay and thus perform a request when the user has stopped typing (unless he is typing slower than regular typing).
To create a delay I can suggest you the following:
<script type="text/javascript">
var globalTimeout = null;
$('#searchInput').keyup(function () {
if (globalTimeout != null) clearTimeout(globalTimeout);
globalTimeout = setTimeout(SearchFunc, 500);
});
function SearchFunc(){
globalTimeout = null;
$('#yourGridName').data('kendoGrid').dataSource.filter({ field:"theField",operator:"startswith",value:$('#searchInput').val() })
}
</script>

Resources