Related
I have a query which is similar to the following.
const TODAY = new Date().setHours(0, 0, 0, 0);
const studentAttendances = await STUDENT_ATTENDANCES.findAll({
where: {
punch_in: { [Op.gt]: TODAY },
},
attributes: ['id', 'student_id', 'arrived_time'],
include: [
{
model: STUDENTS,
attributes: ['name'],
},
],
raw: true,
nest: true,
});
The current output given is an array of objects which look like the following.
{
"id": 1041,
"student_id": 16,
"arrived_time": "2019-05-29T08:29:41.000Z",
"student": {
"name": "Tom"
}
},
Instead of having a nested object as above how do i make the student name itself be an attribute of the main object ? Example as follows.
{
"id": 1041,
"student_id": 16,
"arrived_time": "2019-05-29T08:29:41.000Z",
"student": "Tom"
},
I hope to do this through sequelize without using any JS loops
Something like this should work, assuming your singular model name is "Student":
const studentAttendances = await STUDENT_ATTENDANCES.findAll({
where: {
punch_in: { [Op.gt]: TODAY },
},
attributes: [
[sequelize.col('Student.name'), 'studentName'], // will give you name as 'studentName'
'id', 'student_id', 'arrived_time'
],
include: [
{
model: STUDENTS,
attributes: [], // empty this out
},
]
});
I think you can handle it with pure javascript :
studentAttendances = studentAttendances.get({plain: true})
for(student in studentAttendances){
studentAttendances[student].student = studentAttendances[student].student.name
}
So I've got the code to express my spreadsheet data in a pivot table, but I need the values to show as a percentage of column total. It seems that there's a property to achieve that result, but I don't know how to integrate that into the script.
https://developers.google.com/apps-script/reference/spreadsheet/pivot-value-display-type
function addPivotTable3(spreadsheetId3, pivotSourceDataSheetId3, destinationSheetId3)
{
var ss = SpreadsheetApp.getActiveSpreadsheet();
var sheetName = "Sheet3";
var pivotTableParams = {};
// The source indicates the range of data you want to put in the table.
// optional arguments: startRowIndex, startColumnIndex, endRowIndex, endColumnIndex
pivotTableParams.source = {
sheetId: ss.getSheetByName(sheetName).getSheetId()
};
// Group rows, the 'sourceColumnOffset' corresponds to the column number in the source range
// eg: 0 to group by the first column
pivotTableParams.rows = [{
sourceColumnOffset: 2,
sortOrder: "ASCENDING"
}];
// Defines how a value in a pivot table should be calculated.
pivotTableParams.values = [{
summarizeFunction: "SUM",
displayType: "PERCENT_OF_COLUMN_TOTAL",
sourceColumnOffset: 3
}];
var requests = [{
'updateCells': {
'rows': {
'values': [
{
'pivotTable': {
'source': {
'sheetId': pivotSourceDataSheetId3,
'startRowIndex': 0,
'startColumnIndex': 0,
'endRowIndex': 94,
'endColumnIndex': 4,
},
'rows': [
{
'sourceColumnOffset': 2,
'showTotals': true,
'sortOrder': 'ASCENDING',
'valueBucket': {
'buckets': [
{
'stringValue': 'BAE Stages',
},
],
},
},
{
'sourceColumnOffset': 94,
'showTotals': true,
'sortOrder': 'ASCENDING',
'valueBucket': {},
},
],
'columns': [
{
'sourceColumnOffset': 0,
'sortOrder': 'ASCENDING',
'showTotals': true,
'valueBucket': {},
},
],
'values': [
{
'summarizeFunction': "SUM",
'sourceColumnOffset': 3,
//'displayType': "PERCENT_OF_COLUMN_TOTAL",
//This line triggers a JSON erorr
},
],
'valueLayout': 'HORIZONTAL',
},
},
],
},
'start': {
'sheetId': destinationSheetId3,
'rowIndex': 0,
'columnIndex': 0,
},
'fields': 'pivotTable',
},
}];
var response =
Sheets.Spreadsheets.batchUpdate({'requests': requests}, spreadsheetId3);
}
Well, I didn't know either and the documentation is soooooo mysterious.
I was about to give up then I came across this: https://developers.google.com/sheets/api/reference/rest/v4/spreadsheets#PivotValueCalculatedDisplayType
Eventually I worked out your line should be:
'calculatedDisplayType' : "PERCENT_OF_COLUMN_TOTAL",
(On the above webpage is PivotValueCalculatedDisplayType and within the table is the ENUM you mentioned, "PERCENT_OF_COLUMN_TOTAL"
I had a hunch that since we are in pivot table/value part of the object, we don't need the PivotValue ... so we're left with calculatedDisplayType.
Phew.
I am new to JSON and mvc so here is my issue. I am currently working on graphs using highcharts. I have a controller which returns a JSON object.
public JsonResult _GetChart_TrendPublicationTypeDetailed_Data(int
yearToDisplay)
{
//Types of publications to be considered
string[] publication_types = new string[] { "article", "book", "book_section", "conference_proceedings" };
//Get the list of outputs with usp authors
var uspPubs = _uspAuthoredPublications();
//List of years for which to display the data
List<int> yearRange = _getListOfYears(yearToDisplay, yearRangeFactor_10);
//Get the data
var data = from eprint_summary in localDB.Summary
where
eprint_summary.Year > (yearToDisplay - yearRangeFactor_10)
&& eprint_summary.Year <= yearToDisplay
&& publication_types.Contains(eprint_summary.TypeCode)
&& uspPubs.Contains(eprint_summary.EprintId)
//&& eprint_summary.refereed == "TRUE" //TODO: Confirm whether we need this filter in our counts
group eprint_summary by new { eprint_summary.Year, eprint_summary.TypeDesc } into typeTrend
orderby typeTrend.Key.Year, typeTrend.Key.TypeDesc
select new
{
Year = typeTrend.Key.Year,
Type = typeTrend.Key.TypeDesc,
Count = typeTrend.Count()
};
//Extract the series data
List<object> countData = new List<object>();
foreach (var item in data.ToList().Select(y => y.Type).Distinct().OrderBy(y => y))
{
List<int> yearlyData = new List<int>();
foreach (var year in yearRange)
{
var rec = data
.Where(y => y.Type == item)
.Where(y => y.Year == year)
.Select(y => y.Count).ToArray();
yearlyData.Add(
rec == null || rec.Length == 0 ? 0 : rec[0]
);
}
countData.Add(
new
{
name = item, //Name of the series
data = yearlyData.ToArray() //Array of data
}
);
}
//Form the json object using the series data and labels
return Json(
new
{
labels = yearRange.ToArray(),
series = countData
},
JsonRequestBehavior.AllowGet
);
}
The above is my JSON in controller.
I have my view as below where I am getting the JSON object but I do not know how to append to my graph as series. How would I convert the JSON object to something that the series accepts.
var seriesData = ' ';
var test = ' ';
function ajaxCall() {
$.ajax({
type: "post",
datatype: "Json",
async: true,
url: '#Url.Action("_GetChart_TrendPublicationTypeDetailed_Data", "ResearchCharts")',
data: { yearToDisplay: '#(DateTime.Now.AddYears(-1).Year.ToString())' },
success: function (data) {
seriesData = data;
test = seriesData.series;
//bindChart(test);
//alert(JSON.stringify(seriesData));
alert(JSON.stringify(test));
},
error: function () {
alert("An error occurred.");
}
});
}
//functions call
ajaxCall();
bindChart(test);
function bindChart(test) {
var test2 = [{ "name": "Book", "data": [14, 17, 9, 10, 6, 19, 6, 8, 0, 4] }, { "name": "Book Chapter", "data": [65, 74, 44, 66, 9, 23, 36, 51, 53, 36] }, { "name": "Conference Proceedings", "data": [15, 17, 27, 30, 28, 54, 35, 43, 50, 35] }, { "name": "Journal Article", "data": [178, 162, 133, 139, 133, 191, 160, 194, 149, 169] }];
$('#chartTrendsPublicationTypeDetailed').highcharts({
chart: {
type: 'line'
},
title: {
text: 'My data'
},
xAxis: {
categories: ['2007', '2008', '2009', '2010', '2011', '2012', '2013', '2014', '2015', '2016']
},
series: test2//[{ "name": "Book", "data": [14, 17, 9, 10, 6, 19, 6, 8, 0, 4] }, { "name": "Book Chapter", "data": [65, 74, 44, 66, 9, 23, 36, 51, 53, 36] }, { "name": "Conference Proceedings", "data": [15, 17, 27, 30, 28, 54, 35, 43, 50, 35] }, { "name": "Journal Article", "data": [178, 162, 133, 139, 133, 191, 160, 194, 149, 169] }]
});
Please help, just need to somehow pass the data to highcharts.
in the picture, I have added the series manually and it works, but I need to pass in a variable which the series property accepts.
Old Highcharts rendering code:
$('#chartTrendsPublicationRankDetailed').highcharts({
chart: {
type: 'line'
},
title: {
text: 'My data'
},
xAxis: {
categories: labels
},
series: seriesData
});
New Highcharts rendering code. This accepts my JSON objects successfully and renders the graphs.
function bindChartItemType(seriesData, labels) {
var chart = new Highcharts.Chart({
chart: {
renderTo: 'chartTrendsPublicationTypeDetailed',
type: 'line',
height: 500,
width: 500
},
credits: {
enabled: false
},
title: {
text: 'Trend of Publications by Item Type'
},
xAxis: {
categories: labels,
title: {
text: '<b>Year</b>'
}
},
yAxis: {
min:0,
title: {
text: '<b># of publications</b>'
}
},
series: seriesData
});
}
Feel free to add anything you like in the comments.
Regards
Shafraz Buksh
I am attempting to pull data out of json like this, which is imported as "values"
{
"content": {
"person": [
{
"name": "Test"
"age" : "24:
}
]
}
}
I am using .map like below but getting the error .default.map is not a function I believe it is because i have objects not arrays, i've tried a bunch of stuff including object.keys but i'm getting errors all over the place, any direction would be appreciated.
import values from './sample.json'
const vals = values.map((myval, index) => {
const items = person.items.map((item, i) => {
return (
<div>{item.name}</div>
)
})
return (
<div>{items}</div>
)
})
I think your data and code have some errors. But after fixing those and also changing the name from 'person' to 'people' if that's what you are after, here's the code that does what you are trying to do:
var data = {
content: {
people: [
{
name: "Test",
age: 24,
},
{
name: "Foo",
age: 25,
},
],
},
};
var App = React.createClass({
render: function () {
var people = data.content.people.map(function (person) {
return <div>{person.name}</div>;
});
return <div>{people}</div>;
},
});
ReactDOM.render(<App />, document.getElementById("app"));
And here's the JSBin for that: https://jsbin.com/coyalec/2/edit?html,js,output
Update: I'm updating the answer with more detailed example. It now deals with data more generically, like it doesn't assume what are the entries of 'contents' and such, but it knows that each type like 'people' or 'pets' are an array.
var data = {
content: {
people: [
{
name: "Test",
age: 24,
},
{
name: "Foo",
age: 25,
},
],
pets: [
{
name: "Sweety",
age: 3,
},
{
name: "Kitty",
age: 5,
},
],
},
};
var App = React.createClass({
render: function () {
// Get the keys in data.content. This will return ['people', 'pets']
var contentKeys = Object.keys(data.content);
// Now start iterating through these keys and use those keys to
// retrieve the underlying arrays and then extract the name field
var allNames = contentKeys.map((t) =>
data.content[t].map((e) => <div>{e.name}</div>)
);
return <div>{allNames}</div>;
},
});
ReactDOM.render(<App />, document.getElementById("app"));
And here's the latest JSBin: https://jsbin.com/coyalec/4/edit?html,js,output
Let's say I have an invoice and an invoice item. I'd like to show a list of invoices in a grid on the top and below I want to show the corresponding invoice items to the selected invoice. I have the SQL and JSON part down fine. I query the invoices, query the invoices items for all invoices returned (only 2 queries). Then I match up the items with their invoices. And finally I convert this into JSON. It would look something like this.
{
"success": true,
"results": 2,
"rows": [
{
"data": {"id": 1, "invoiceDate": "2010-01-01", "total": "101.00" },
"invoiceItems": [
{"id": 11, "invoiceID": 1, "item": "baseball", "subtotal": "50.00" },
{"id": 12, "invoiceID": 1, "item": "bat", "subtotal": "51.00" }
]
},
{
"data": {"id": 2, "invoiceDate": "2010-02-02", "total": "102.00" },
"invoiceItems": [
{"id": 21, "invoiceID": 2, "item": "hat", "subtotal": "52.00" },
{"id": 22, "invoiceID": 2, "item": "baseball", "subtotal": "50.00" }
]
}
]
}
So when I select invoice 1 in the top grid, I want to see items 11 and 12 displayed in the botton grid. And then show 21 and 22 when invoice 2 is selected. I'd like to NOT have to return to the server every time I toggle between invoices.
And then finally, I'd love to be able to track which ones have changes so that I can send data back to be persisted.
How is this all possible using Ext JS? I've yet to see a working master detail example using Ext JS.
This is certainly possible with ExtJS and I suggest ExtJS provides tools to help.
However, you might be encountering trouble if you are trying to use a single store to contain your JSON records. I recall reading (I searched for a reference, but was unable to find it) you should think of a store as a single database table rather than trying to store parent/child information in one store.
So, I humbly suggest you store your invoices in one store and your invoice items in a second store, link the child invoice items to the parent invoice via some reference (invoice ID), and use these two stores to support two different grids (or whatever widget) - one for invoices and a second for invoice items. When a user clicks on an invoice, your listener (event handler) would update the invoice items grid/widget appropriately.
This would be my approach.
in that case, you need two readers as code below:
var reader2 = new Ext.data.JsonReader({
root: 'invoiceItems',
fields: [{name: 'id', type:'int'},
{name: 'invoiceID', type:'int'},
{name: 'item', type:'string'},
{name: 'subtotal': type:'float'}]
});
var reader = new Ext.data.JsonReader({
idProperty: 'id',
totalProperty: 'results',
successProperty: "success",
root: 'rows',
fields: [
{name: 'id', type:'int'},
{name: 'invoiceDate', type:'date'},
{name: 'total', type:'float'},
{name: 'invoiceItems', convert: function(v, n){ return reader2.readRecords(n).records;} }//v: value, n: data;
]
});
var conn = new Ext.data.Connection({
timeout : 120000,
url: 'address-path-to-get-json-data',
method : 'POST'
});
var dproxy = new Ext.data.HttpProxy(conn);
var gstore = new Ext.data.Store({
proxy: dproxy,
reader: reader,
sortInfo:{field: 'id', direction: "DESC"}
});
and here is code you need to render the grid
var numrender = function(value, cell, rec, rowIndex, colIndex, store){
if(value*1>0){
return Ext.util.Format.number( value, '0,000.00');
}else return '-';
}
var invoicedetail = function(value, cell, rec, rowIndex, colIndex, store) {
var html = '<div class="itemdetail">{0} - {1} - {2} - {3}</div>';
var re = '';
Ext.each(value,function(item,index){
re += String.format(html,item.get('id'),item.get('invoiceID'),item.get('item'),item.get('subtotal'));
});
return re;
}
var cm = [
new Ext.grid.RowNumberer({header:"No.", width: 30}),
{header: "ID", align: 'left',sortable:true, width: 40, dataIndex: 'id'},
{header: "Invoice Date", align: 'left',sortable:true, width: 40, dataIndex: 'invoiceDate'},
{header: "Total", align: 'right', width: 30, dataIndex: 'total', renderer: numrender},
{header: "Invoice Items", align: 'left',sortable:false, id:'col_detail', width: 100, dataIndex: 'invoiceItems', renderer: invoicedetail}
];
var grid = new Ext.grid.GridPanel({
id:'invoices',
store: gstore,
columns: cm,
enableHdMenu: false,
loadMask: {msg:'Loading Invoices ...'},
enableColumnResize:false,
stripeRows: true,
viewConfig: { autoFill: true },
columnLines : true,
autoExpandColumn: 'col_detail',
renderTo:'grid-wrapper'
});
gstore.load();
or you might be interested in looking at this treegrid:
http://www.max-bazhenov.com/dev/ux.maximgb.tg/index.php
This is certainly possible however you aren't really mapping the sub-objects rather than just expecting them to be there...
Consider this test case (stick it into FireBug and you should see the results..)
var store = new Ext.data.JsonStore({
data: {
success: true, result: [
{
test: {prop1: 1, prop2: 2}
}]
},
root: 'result',
fields: ['test']
});
console.log(store.getRange()[0].data.test.prop1); // prints "1"
In your instance you would do something like this in your row select event...
//assume "this" = your panel containing your Grid (at position 0) and another Grid (at position 1)
var selectedRowRecord = this.get(0).getSelectionModel().getSelected();
var invoiceItemsStore = this.get(1).getStore();
invoiceItemsStore.removeAll();
invoiceItemsStore.loadData(selectedRowRecord.data.invoiceItems);
Hope this helps.
Stuart