Finding out how many status objects are in a store - json

I have a store called CreativeStore and inside one of the fields is Status. The data is sent as JSON. I created a variable that is getting the Creative store. How would I find out what the status is and how many statuses their are.
In my Creative Model I have a field
}, {
type: 'int',
name: 'Status'
}, {
In my View Controller I have a method that checks if the store I created for the Creative Model exists (It does) and I assign it to a var called test.
var test = this.getCreativeStore();
getCreativeStore: function () {
var creativeStore = this.getStore('creativeStore');
if (!creativeStore) {
this.logError('creativeStore is undefined');
}
return creativeStore;
}
How do I find out how many Statuses are in the variable test?

You can use collect:
Collects unique values for a particular dataIndex from this store.
For example:
test.collect('status').length;

var statusCount = 0;
test.each(function(record) {
// Your status value in myStatus
if(record.get('Status') === myStatus)
++statusCount;
});

Related

google-apps-script ContactsApp.getContact(email) migration to People API

How to write this simple line :
ContactsApp.getContact(email);
with the new People API ?
Thanks a lot !
Workflow:
Use people.connections.list to get the list of contacts of the requested user, specified via resourceName (people/me refers to the authenticated user).
Find the contact who has an email address like the one you are looking for.
Important notes:
Naturally, you won't get exactly the same information as in ContactsApp.getContact, since they are different API's. In this case, you'll get an instance of the Person resource.
You can choose which information should be populated on the retrieved person, using personFields (see the list of available fields here). Request multiple fields by providing a comma-separated string of fields (in the example below, emailAddresses and biographies are requested).
Code sample:
function getPerson(email) {
const resourceName = "people/me";
const optionalArgs = {
personFields: 'emailAddresses,biographies' // Add the person fields you want
}
const response = People.People.Connections.list(resourceName, optionalArgs);
const { connections } = response;
const person = connections.find(connection => {
return connection["emailAddresses"] && connection["emailAddresses"].some(emailAddress => emailAddress["value"] === email);
});
return person;
}

Unable to retrieve JSON array with AngularJS $resource

I've been trying retrieve values from JSON and so far, been unsuccessful. It does get called on the front-end when I refresh the page, but the information is not passing to the next method. I think the issue might be down to the promises.push... line, as I've tried to debug the method underneath and the information is not being passed on at all.
AngularJS:
var promises = [];
promises.push(SpringDataRestService.get({"collection": "subjects"}).$promise);
// Require each of these queries to complete before continuing
$q.all(promises).then(function (data) {
// Grab the first result
$scope.available = data[0].subjects;
$scope.selected = [];
// If this is an update, get the second result in set
if (data.length > 1) {
// For each permission that is assigned to this role, add ID (name) to selected
for (var i = 0; i < data[1].data.subjects.length; i++) {
var perm = data[1].data.subjects[i];
$scope.selected.push(perm.name);
}
}
$scope.tableEditOptions = new NgTableParams({}, {
dataset: $scope.available
});
$scope.available, 'name');
}).catch(function (data) {
// ERROR
});
JSON:
[
{
"name": "FWGWG",
"description": "WGWGWG",
"lockId": 0
},
{
"name": "QFQFQF",
"description": "QFQFQFQ",
"lockId": 0
}
]
I'm confident as well my for loop is wrong due to assigning the values as well, since I don't think it should be data.subjects, but I understand these threads are only 1 issue per question. Any help would be greatly appreicated.
Use the query method for arrays:
var promise = SpringDataRestService.query({"collection": "subjects"}).$promise;
promise.then(function (dataArr) {
console.log(dataArr);
//...
}).catch(function (errorResponse) {
console.log(errorResponse);
});
With the REST services, the get method returns a JavaScript object and the query method returns a JavaScript array.
From the Docs:
$resource Returns
A resource "class" object with methods for the default set of resource actions optionally extended with custom actions. The default set contains these actions:
{
'get': {method: 'GET'},
'save': {method: 'POST'},
'query': {method: 'GET', isArray: true},
'remove': {method: 'DELETE'},
'delete': {method: 'DELETE'}
}
...
It is important to realize that invoking a $resource object method immediately returns an empty reference (object or array depending on isArray). Once the data is returned from the server the existing reference is populated with the actual data.
For more information, see
AngularJS $resource Service API Reference

Getting auto-generated (via trigger) field from an insert in sequelize

I have a base controller for generic insert/update operations across the whole API, using only a table dictionary so we can use the same function to insert data into many tables.
The problem is there is a table that uses a correlative number generated via trigger, and when sequelize returns the inserted value, it includes the new ID but the correlative field returns empty, and I need it to show it on the interface.
I've thought of just querying the new field again to the API, or querying it on the same save function again when it includes these certain tables names, but is there a way to tell sequelize to "wait" for this new generated value and then return the data alright? Just like getting the new ID
Or maybe this needs to be fixed on the database? I don't have much experience in that field, but we are using MySQL if that helps.
function Init(models, dictionary) {
this.post = (req, res, next) => {
const { obj } = req.body;
const model = models[dictionary[obj._type]];
//Just stripping fields starting with "_"
const objClear = {};
for (const attr in obj) {
if (attr.charAt(0) !== '_') {
objClear[attr] = obj[attr];
}
}
//Saving
model.create(objClear).then(
(objSaved) => {
const data = {
obj: objSaved.get({ plain: true }),
action: 'inserted',
};
//I guess I could query the new row here again
res.json(data);
},
).catch(next);
};
}
module.exports = {
Init,
};
The response looks like:
{"obj":{"TOTAL":"0","ID":14,...,"TRANSACTION_NO":""},"action":"inserted"}
Where TRANSACTION_NO is the field generated with a trigger.
AFAIK, you have to query the new row unless you use Postgres (in which case you might try the Model.create option called "options.returning")
Two quick tests that did NOT solve the problem:
an afterCreate hook - the model still shows fields created by a trigger as null.
a model having a default value from a DB function - the model shows the function call,
not the result of the function (which does make it to the DB field).
Hope someone else has a solution!

getBulkProperties very slow

Following the advice given on one of my other questions (Get a list of all objects from loaded model), I added this code on my application to retrieve all properties from all objects:
function onGeometryLoadedEvent(viewer) {
var dbIds = Object.keys(
viewer.model.getData().instanceTree.nodeAccess.dbIdToIndex
);
this.viewer.model.getBulkProperties(
dbIds,
{
propFilter: false,
ignoreHidden: true
},
(objects) => console.log(objects),
() => console.log('error')
)
}
It correctly shows all the objects. The problem is it takes A LOT of time to complete (+1 minute), even for a model with just 10,000 objects.
Is this normal?
I really need the list of objects with their categories, I have to sort them after getting them to present a list of all the available categories and properties to the user.
I know I can use the Model Derivatives API, but I'd like to avoid it if possible.
Note that when you list all elements on the model it will include those that are not visible, like categories. If you need only elements on the model, then you need the leaf of the model. This article described it and the source code is below:
function getAllLeafComponents(viewer, callback) {
var cbCount = 0; // count pending callbacks
var components = []; // store the results
var tree; // the instance tree
function getLeafComponentsRec(parent) {
cbCount++;
if (tree.getChildCount(parent) != 0) {
tree.enumNodeChildren(parent, function (children) {
getLeafComponentsRec(children);
}, false);
} else {
components.push(parent);
}
if (--cbCount == 0) callback(components);
}
viewer.getObjectTree(function (objectTree) {
tree = objectTree;
var allLeafComponents = getLeafComponentsRec(tree.getRootId());
});
}
Now with the .getBulkProperties you can specify which property you want, so something like Category, right? So specify that, as shown at this article and used with the above .getAllLeafComponent function:
getAllLeafComponents(viewer, function (dbIds) {
viewer.model.getBulkProperties(dbIds, ['Category'],
function(elements){
// ToDo here
// this will only include leaf with Category property
})
})
And I would expect this to be faster than your original code, as I'm filtering elements and properties.

Using KnexJS to query X number of tables?

I have a unique situation here which I am having trouble solving in an elegant fashion.
A user passes up an array of signals which they want to export data for. This array can be 1 -> Any_Number so first I go fetch the table names (each signal stores data in a separate table) based on the signals passed and store those in an object.
The next step is to iterate over that object (which contains the table names I need to query), execute the query per table and store the results in an object which will be passed to next chain in the Promise. I haven't seen any examples online of good ways to handle this but I know it's a fairly unique scenario.
My code prior to attempting to add support for arrays of signals was simply the following:
exports.getRawDataForExport = function(data) {
return new Promise(function(resolve, reject) {
var getTableName = function() {
return knex('monitored_parameter')
.where('device_id', data.device_id)
.andWhere('internal_name', data.param)
.first()
.then(function(row) {
if(row) {
var resp = {"table" : 'monitored_parameter_data_' + row.id, "param" : row.display_name};
return resp;
}
});
}
var getData = function(runningResult) {
return knexHistory(runningResult.table)
.select('data_value as value', 'unit', 'created')
.then(function(rows) {
runningResult.data = rows;
return runningResult;
});
}
var createFile = function(runningResult) {
var fields = ['value', 'unit', 'created'],
csvFileName = filePathExport + runningResult.param + '_export.csv',
zipFileName = filePathExport + runningResult.param + '_export.gz';
var csv = json2csv({data : runningResult.data, fields : fields, doubleQuotes : ''});
fs.writeFileSync(csvFileName, csv);
// create streams for gZipping
var input = fs.createReadStream(csvFileName);
var output = fs.createWriteStream(zipFileName);
// gZip
input.pipe(gzip).pipe(output);
return zipFileName;
}
getTableName()
.then(getData)
.then(createFile)
.then(function(zipFile) {
resolve(zipFile);
});
});
}
Obviously that works fine for a single table and I have gotten the getTableName() and createFile() methods updated to handle arrays of data so this question only pertains to the getData() method.
Cheers!
This kind of problem is far from unique and, approached the right way, is very simply solved.
Don't rewrite any of the three internal functions.
Just purge the explicit promise construction antipattern from .getRawDataForExport() such that it returns a naturally occurring promise and propagates asynchronous errors to the caller.
return getTableName()
.then(getData)
.then(createFile);
Now, .getRawDataForExport() is the basic building-block for your multiple "gets".
Then, a design choice; parallel versus sequential operations. Both are very well documented.
Parallel:
exports.getMultiple = function(arrayOfSignals) {
return Promise.all(arrayOfSignals.map(getRawDataForExport));
};
Sequential:
exports.getMultiple = function(arrayOfSignals) {
return arrayOfSignals.reduce(function(promise, signal) {
return promise.then(function() {
return getRawDataForExport(signal);
});
}, Promise.resolve());
};
In the first instance, for best potential performance, try parallel.
If the server chokes, or is likely ever to choke, on parallel operations, choose sequential.