Kendo UI Chart - Visualize count of returned JSON fields - json

I want to display the counts of specific retrieved fields in my pie/donut chart.
I'm retrieving data via REST and the result is in json format. The source is a list repeating values:
Example: In the following list, I'd like to get a present the number (count) of completed responses; perhaps in a second chart present the breakdown of responses by location.
var userResponse = [
{ User: "Bob Smith", Status: "Completed", Location: "USA" },
{ User: "Jim Smith", Status: "In-Progress", Location: "USA" },
{ User: "Jane Smith", Status: "Completed", Location: "USA" },
{ User: "Bill Smith", Status: "Completed", Location: "Japan" },
{ User: "Kate Smith", Status: "In-Progress", Location: "Japan" },
{ User: "Sam Smith", Status: "In-Progress", Location: "USA" },
]
My Initialization currently looks like this:
$('#targetChart').kendoChart({
dataSource: {
data: data.d.results,
group: {
field: "Location",
},
},
seriesDefaults: {
type: "donut",
},
series: [{
field: 'Id',
categoryField: 'Location',
}],
});

You can easily transform the data. Read it into a DataSource object grouping by location and filtering for completed only. Then fetch the data and create an array of the counts for each location:
var pieData = [];
var respDS = new kendo.data.DataSource({
data: userResponse,
group: {
field: "Location",
},
filter: {
field: "Status",
operator: "eq",
value: "Completed" },
});
respDS.fetch(function(){
var view = respDS.view();
for (var i=0; i<view.length; i++){
var item = {};
item.Location = view[i].value;
item.Count = view[i].items.length;
pieData.push(item);
}
});
You end up with:
[
{Location: "Japan", Count: 1},
{Location: "USA", Count: 2},
]
This can then be bound to a pie/donut.
DEMO

Related

ExtJS model associations with jsonapi specification

We are creating a new version our API (v2) adopting the JSON:API specification (https://jsonapi.org/). I'm not being able to port the ExtJS model associations (belongs_to) to the new pattern.
The ExtJS documentation only shows how to use a nested relation in the same root node (https://docs.sencha.com/extjs/4.2.2/#!/api/Ext.data.association.Association).
v1 data (sample):
{
"data": [
{
"id": 1,
"description": "Software Development",
"area_id": 1,
"area": {
"id": 1,
"code": "01",
"description": "Headquarters"
}
},
],
"meta": {
"success": true,
"count": 1
}
}
v2 data (sample):
{
"data": [
{
"id": "1",
"type": "maint_service_nature",
"attributes": {
"id": 1,
"description": "Software Development",
"area_id": 1
},
"relationships": {
"area": {
"data": {
"id": "1",
"type": "area"
}
}
}
}
],
"included": [
{
"id": "1",
"type": "area",
"attributes": {
"id": 1,
"code": "01",
"description": "Headquarters"
}
}
],
"meta": {
"success": true,
"count": 1
}
}
My model:
Ext.define('Suite.model.MaintServiceNature', {
extend: 'Ext.data.Model',
fields: [
{ desc: "Id", name: 'id', type: 'int', useNull: true },
{ desc: "Area", name: 'area_id', type: 'int', useNull: true },
{ desc: "Description", name: 'description', type: 'string', useNull: true, tableIdentification: true }
],
associations: [
{
type: 'belongsTo',
model: 'Suite.model.Area',
foreignKey: 'area_id',
associationKey: 'area',
instanceName: 'Area',
getterName: 'getArea',
setterName: 'setArea',
reader: {
type: 'json',
root: false
}
}
],
proxy: {
type: 'rest',
url: App.getConf('restBaseUrlV2') + '/maint_service_natures',
reader: {
type: 'json',
root: 'data',
record: 'attributes',
totalProperty: 'meta.count',
successProperty: 'meta.success',
messageProperty: 'meta.errors'
}
}
});
Any ideias on how to setup the association to work with the v2 data?
I'm honestly taking a stab at this one... I haven't used Ext JS 4 in years, and I wouldn't structure my JSON like JSON:API does, but I think the only way you can accomplish this is by rolling your own reader class. Given that you have generic properties for your data structure, this reader should work for all scenarios... although, I'm not too familiar with JSON:API, so I could be totally wrong. Either way, this is what I've come up with.
Ext.application({
name: 'Fiddle',
launch: function () {
Ext.define('MyReader', {
extend: 'Ext.data.reader.Json',
alias: 'reader.myReader',
root: 'data',
totalProperty: 'meta.count',
successProperty: 'meta.success',
messageProperty: 'meta.errors',
/**
* #override
*/
extractData: function (root) {
var me = this,
ModelClass = me.model,
length = root.length,
records = new Array(length),
dataConverter,
convertedValues, node, record, i;
for (i = 0; i < length; i++) {
node = root[i];
var attrs = node.attributes;
if (node.isModel) {
// If we're given a model instance in the data, just push it on
// without doing any conversion
records[i] = node;
} else {
// Create a record with an empty data object.
// Populate that data object by extracting and converting field values from raw data.
// Must pass the ID to use because we pass no data for the constructor to pluck an ID from
records[i] = record = new ModelClass(undefined, me.getId(attrs), attrs, convertedValues = {});
// If the server did not include an id in the response data, the Model constructor will mark the record as phantom.
// We need to set phantom to false here because records created from a server response using a reader by definition are not phantom records.
record.phantom = false;
// Use generated function to extract all fields at once
me.convertRecordData(convertedValues, attrs, record, me.applyDefaults);
if (me.implicitIncludes && record.associations.length) {
me.readAssociated(record, node);
}
}
}
return records;
}
});
Ext.define('Suite.model.Area', {
extend: 'Ext.data.Model',
fields: [{
name: 'type',
type: 'string'
}]
});
Ext.define('Suite.model.MaintServiceNature', {
extend: 'Ext.data.Model',
fields: [{
desc: "Id",
name: 'id',
type: 'int',
useNull: true
}, {
desc: "Area",
name: 'area_id',
type: 'int',
useNull: true
}, {
desc: "Description",
name: 'description',
type: 'string',
useNull: true,
tableIdentification: true
}],
associations: [{
type: 'belongsTo',
model: 'Suite.model.Area',
associatedName: 'Area',
foreignKey: 'area_id',
associationKey: 'relationships.area.data',
instanceName: 'Area',
getterName: 'getArea',
setterName: 'setArea'
}],
proxy: {
type: 'rest',
url: 'data1.json',
reader: {
type: 'myReader'
}
}
});
Suite.model.MaintServiceNature.load(null, {
callback: function (record) {
console.log(record.getData(true));
}
});
}
});

How to write Query to retrieve every subdocument array who matches

Here i need my explain my problem clearly. How can i write a query to retrieve every subdocument array who matches the condition using mongoose and nodejs.
this is my existing JSON:
[
{
_id: "568ccd6e646489f4106470ec",
area_name: "Padi",
warehouse_name: "Hapserve Online Water Service",
name: "Ganesh",
email: "ganesh#excrin.com",
mobile_no: "9042391491",
otp: "4466",
__v: 0,
date: "06-01-2016",
booking:
[
{
can_quantity: "4",
delivery_date: "06-01-2016",
delivery_timeslot: "10am-3pm",
subscription: "true",
subscription_type: "Weekly",
total_cost: "240",
order_id: "S13833",
can_name: "Tata Waters",
address: "15/A,Ramanrajan street,,Padi,Chennai",
can_cost: "240",
_id: "568ccd6e646489f4106470ee",
ordered_at: "2016-01-06T08:16:46.825Z",
status: "UnderProcess"
},
{
can_name: "Bisleri",
can_quantity: "4",
can_cost: "200",
delivery_date: "11-01-2016",
delivery_timeslot: "3pm-8pm",
order_id: "11537",
address: "27,Main Street,Padi,Chennai",
_id: "5693860edb988e241102d196",
ordered_at: "2016-01-11T10:38:06.749Z",
status: "UnderProcess"
}
]
},
{
_id: "56937fb8920629a0164604d8",
area_name: "Poonamallee",
warehouse_name: "Tata Waters",
name: "M.Kalaiselvan",
email: "kalai131192#gmail.com",
mobile_no: "9003321521",
otp: "2256",
__v: 0,
date: "2016-01-11T10:11:04.266Z",
booking:
[
{
can_quantity: "4",
delivery_date: "06-01-2016",
delivery_timeslot: "10am-3pm",
subscription: "true",
subscription_type: "Alternate",
total_cost: "640",
order_id: "S13406",
can_name: "Kinley",
address: "133,Bajanai koil street, Melmanagar,Poonamallee,Chennai",
can_cost: "160",
_id: "56937fb8920629a0164604da",
ordered_at: "11-01-2016",
status: "UnderProcess"
},
{
can_name: "Tata Waters",
can_quantity: "2",
can_cost: "120",
delivery_date: "11-01-2016",
delivery_timeslot: "10am-3pm",
order_id: "11387",
address: "140,Bajanai koil street, Melmanagar,Poonamallee,Chennai",
_id: "56937ff7920629a0164604dc",
ordered_at: "2016-01-11T10:12:07.719Z",
status: "UnderProcess"
},
{
can_name: "Bisleri",
can_quantity: "4",
can_cost: "200",
delivery_date: "12-01-2016",
delivery_timeslot: "10am-3pm",
order_id: "16853",
address: "140,Bajanai koil street, Melmanagar,Poonamallee,Chennai",
_id: "56938584db988e241102d194",
ordered_at: "2016-01-11T10:35:48.911Z",
status: "UnderProcess"
},
{
can_name: "Hapserve",
can_quantity: "6",
can_cost: "150",
delivery_date: "11-01-2016",
delivery_timeslot: "10am-3pm",
order_id: "17397",
address: "133,Bajanai koil street, Melmanagar,Poonamallee,Chennai",
_id: "569385bbdb988e241102d195",
ordered_at: "2016-01-11T10:36:43.918Z",
status: "UnderProcess"
},
{
can_name: "Bisleri",
can_quantity: "5",
can_cost: "250",
delivery_date: "11-01-2016",
delivery_timeslot: "10am-3pm",
order_id: "14218",
address: "133,Bajanai koil street, Melmanagar,Poonamallee,Chennai",
_id: "56939a13c898ef7c0cc882b0",
ordered_at: "2016-01-11T12:03:31.324Z",
status: "Cancelled"
}
]
}
]
Here i need to retrieve every document where delivery date is today
so this is my nodejs route
router.get('/booking-date/:date', function(req, res){
var id = req.params.date;
RegisterList.find({'booking.delivery_date':id}, {'booking.$':1}, function(err, docs){
if(err)
throw err;
res.json(docs);
});
});
while am using this am not able to get every data. only two data is retrieve from collection.
example if i search for a date 11-01-2016 am getting only one subdocument for
each parent id, but in the above json for date 11-01-2016. for one parent id has 2 subdocument for that date and another parent id has 1 subdocument for that date.
am not able to write mongoose query retrieve to every subdocument where matches done..
Help will be appreciated...
Sounds like you may want to try the aggregation framework where you can $project the booking array with a filter made possible using the $setDifference, $map and $cond operators.
The $map operator inspects each element within the booking array and the $cond operator returns only the wanted fields based on a true condtion, a false value is returned on the contrary instead of the array element. $setDifference operator then removes all false values from the array by comparing to another set with the [false] values, the final result is only the returned matches:
router.get('/booking-date/:date', function(req, res){
var id = req.params.date,
pipeline = [
{
"$match": { 'booking.delivery_date': id }
},
{
"$project": {
"booking": {
"$setDifference": [
{
"$map": {
"input": "$booking",
"as": "el",
"in": {
"$cond": [
{ "$eq": [ "$$el.delivery_date", id ] },
"$$el",
false
]
}
}
},
[false]
]
}
}
}
];
RegisterList.aggregate(pipeline, function(err, docs){
if(err) throw err;
res.json(docs);
});
});
The $ projection operator projects only first matching element, refer here
Project all subdocuments {bookings: 1},then filter subdocuments within your application.

Sort a store data based on inner JSON field sencha

i have a json in the following format:
{
"collection": [
{
"id": 4,
"tickets": [
{
"price": 40,
},
{
"price": 50,
}
],
},
{
"id": 1,
"tickets": [
{
"price": 10,
},
{
"price": 15,
}
]
},
]
}
STORE:
Ext.define("myProject.store.ABCs", {
extend: "Ext.data.Store",
config: {
model: "myProject.model.ABC",
autoLoad: false,
proxy: {
type: "ajax",
url: '', //myURL
reader: {
type: "json",
rootProperty: "collection", // this is the first collection
},
},
}
});
For this particular JSON i created the models as:
Ext.define("myProject.model.ABC", {
extend: "Ext.data.Model",
config: {
idProperty: "id",
fields:[
{name: "id", type: "int" },
],
hasMany: [
{
model: "myProject.model.XYZ",
name: "tickets",
associationKey: "tickets",
},
],
}
});
And second model as:
Ext.define("myProject.model.XYZ", {
extend: "Ext.data.Model",
config: {
// idProperty: "id",
fields:[
{name: "inner_id", type: "int" },
],
belongsTo: 'myProject.model.ABC'
}
});
This particular code creates a store and populates the models correctly.
var store = Ext.getStore('ABCs');
Now i want to sort this store based on store.tickets().getAt(0).get('price') that is sort the ABC records based on XYZ's first price property.
In the above json. ABC Records will be: [{id:4}, {id:1}]
But since first price in XYZ (40 > 10), i want to sort them and create [{id:1}, {id:4}]
Take a look at the Ext.util.Sorter class, where you can set a sorterFn. See the example at the top of the page - you should be able to simply write the logic for sorting records the way you describe.

Parsing Json with sencha

I have this format of json
[
{
"docid": "1",
"doc_title": "Dato' Dr.",
"doc_name": "xyz",
"doc_code": "001",
"doc_category": "3",
"doc_subcategory": "",
"id": "0"
},
{
"docid": "1",
"doc_title": "Dr.",
"doc_name": "ABC",
"doc_code": "002",
"doc_category": "4",
"doc_subcategory": "",
"id": "0"
}
]
there are multiple records, I have just included two records
This is my model and parsing code in sencha
Ext.define('User', {
extend: 'Ext.data.Model',
config: {
fields: [
{name: 'docid', type: 'string'},
{name: 'doc_title', type: 'string'},
{name: 'doc_name', type: 'string'},
{name: 'doc_code', type: 'string'},
{name: 'doc_category', type: 'string'},
{name: 'doc_subcategory', type: 'string'},
{name: 'id', type: 'string'},
]
}
});
parsing json
var store = Ext.create('Ext.data.Store',
{
autoLoad: true,
model: "User",
listeners:
{
beforeload: function (store,operation,eOpts)
{
}
},
proxy: {
type: 'ajax',
url : 'http://someurl/doctor/search',
reader: {
type: 'json',
rootProperty: 'users',
}
}
});
The problem I get only the last record from Json no matter how many records are there in the JSON.
and If I remove the id field (Notice the id fields in Json data) it works fine I can be able to have all records parsed.
Why it is doing so? How can I get all the records parsed with sencha?
I'm pretty sure the problem comes from the fat that your specifying a rootProperty in your proxy but they aren't any in you JSON. From that two choices :
Remove the rootProperty
or
Change the structure of your JSON file to something like this :
{
"users": [
{
"docid": "1",
"doc_title": "Dato' Dr.",
"doc_name": "xyz",
"doc_code": "001",
"doc_category": "3",
"doc_subcategory": "",
"id": "0"
},
{
"docid": "1",
"doc_title": "Dr.",
"doc_name": "ABC",
"doc_code": "002",
"doc_category": "4",
"doc_subcategory": "",
"id": "0"
}
]
}
Hope this helps

How do I structure data for Ext.DataView?

Similar to this question, I can't get my DataView to actually show data. I tried to restructure my store, but I think I'm missing something. Here's what I've got so far:
App, Model, Store
Ext.regApplication({
name: 'TestApp',
launch: function() {
this.viewport = new TestApp.views.Viewport();
}
});
TestApp.models.StoreMe = Ext.regModel('TestApp.models.StoreMe', {
fields: [
'id',
'name',
'age'
]
});
TestApp.stores.storeMe = new Ext.data.Store({
model: 'TestApp.models.StoreMe',
proxy: {
type: 'ajax',
url: 'data.json',
reader: {
type: 'json'
}
},
autoLoad: true
});
Viewport and DataView
TestApp.views.Viewport = Ext.extend(Ext.Panel, {
fullscreen: true,
layout: 'card',
items: [
{
id: 'dataView',
xtype: 'dataview',
store: TestApp.stores.storeMe,
itemSelector: 'div.dataViewItem',
emptyText: 'NO DATA',
tpl: '<tpl for "."><div class="dataViewItem">ID: {id}<br />Name: {name}<br />Age: {age}</div></tpl>'
}
]
});
JSON
[
{
"id": "1",
"name": "sam",
"age": "4"
},
{
"id": "2",
"name": "jack",
"age": "3"
},
{
"id": "3",
"name": "danny",
"age": "12"
}
]
Any ideas? All of the other questions that are similar to this use Ext.JsonStore, but the Sencha API docs say to do it this way.
UPDATE
The store is working fine. Here's what TestApp.stores.storeMe.data looks like:
Ext.util.MixedCollection
...
items: Array[3]
0: c
data: Object
age: "4"
id: "1"
name: "sam"
1: c
2: c
length: 3
__proto__: Array[0]
keys: Array[3]
length: 3
...
Seems you don't have the json structure with the root called "data"? Try the change your json to:
{
"data": [ {
"id": "1",
"name": "sam",
"age": "4"
}, {
"id": "2",
"name": "jack",
"age": "3"
}, {
"id": "3",
"name": "danny",
"age": "12"
} ]
}
And put a line -- root: 'data' -- in your reader.
I'm an idiot. I had:
tpl: '<tpl for "."><div class="dataViewItem">ID: {id}<br />Name: {name}<br />Age: {age}</div></tpl>'
I needed:
tpl: '<tpl for=".">...</tpl>'