Multiple Queries Not Applying - rally

So I am making a custom HTML app that uses the Defect List Example (available here). I've added multiple queries to filter the results on the 3 queries/criterias that I need.
What I've noticed is that only the last query is being applied (e.g. only queryConfig[2] applies). I know this is the case because I will still have some defects with state 'Closed' showing up even though I want everything BUT closed states (as shown by queryConfig[1]).
Is there something that I'm doing wrong here? Here's the code for my queries below:
var queryConfig = [];
queryConfig[0] = {
type : 'defect',
key : 'defects',
query: '(c_DeliveryVersionIntroduced contains "Version 1.1")',
fetch: ['Name','State','Severity','FormattedID','Project','ObjectID']
};
queryConfig[1] = {
type : 'defect',
key : 'defects',
query: '(State != Closed)',
fetch: ['Name','State','Severity','FormattedID','Project','ObjectID']
};
queryConfig[2] = {
type: 'defect',
key: 'defects',
query: '(CreationDate = "Today-3")',
fetch: ['Name', 'State', 'Severity', 'FormattedID','Project','ObjectID']
};
var rallyDataSource = new rally.sdk.data.RallyDataSource('__WORKSPACE_OID__',
'__PROJECT_OID__',
'__PROJECT_SCOPING_UP__',
'__PROJECT_SCOPING_DOWN__');
rallyDataSource.findAll(queryConfig, displayDefects);

An SDK 1.0 query config array doesn't work additively like that. The query config array is used to run multiple queries at once via a single callback, and reference the results via different keys. For example:
var queryConfig = [];
queryConfig[0] = {
type : 'HierarchicalRequirement',
key : 'stories',
query: '(ScheduleState = Completed)',
fetch: 'Name,FormattedID'
};
queryConfig[1] = {
type : 'defect',
key : 'defects',
query: '(State = Fixed)',
fetch: 'Name,FormattedID'
};
var rallyDataSource;
rallyDataSource = new rally.sdk.data.RallyDataSource('__WORKSPACE_OID__',
'__PROJECT_OID__',
'__PROJECT_SCOPING_UP__',
'__PROJECT_SCOPING_DOWN__');
rallyDataSource.findAll(queryConfig, processResults);
}
In this situation, the processResults callback would receive results grouped as follows:
var processResults = function(results) {
var stories = results['stories'];
var defects = results['defects'];
};
By re-using the key 'defects', the results of the last entry in the queryConfig array clobber the previous queries.
To achieve your desired result, assuming you intend to AND your conditions together, you would need to implement a single query with multiple conditions, i.e.:
queryConfig = {
type : 'defect',
key : 'defects',
query: '(((c_DeliveryVersionIntroduced contains "Version 1.1") AND (State != Closed)) AND (CreationDate = today-3))',
fetch: 'Name,State,Severity,FormattedID,Project,ObjectID'
};
var rallyDataSource;
rallyDataSource = new rally.sdk.data.RallyDataSource('__WORKSPACE_OID__',
'__PROJECT_OID__',
'__PROJECT_SCOPING_UP__',
'__PROJECT_SCOPING_DOWN__');
rallyDataSource.findAll(queryConfig, processResults);
}

Related

How to run a BigQuery Script by Google App Scripts after a table is updated by another BigQuery script?

I have developed a quite code heavy and data heavy query for Google BigQuery which is why I have chosen to run it in multiple scripts (and create multiple tables). What I want is to run script b (and create table b) when tabel a is updated (by script a). I see only the option to set time events and I'm not that experienced with javascripting. Can someone provide an example?
Thanks in advance!
Guido
function saveQueryToTable() {
var sql = 'query-a';
var projectId = 'xxx';
var datasetId = 'xxx';
var tableId = 'xxx';
var job = {
configuration: {
query: {
query: sql,
writeDisposition:'WRITE_APPEND',
allowLargeResults: 'TRUE',
destinationTable: {
projectId: projectId,
datasetId: datasetId,
tableId: tableId
}
}
}
};
var queryResults = BigQuery.Jobs.insert(job, projectId);
Logger.log(queryResults.status);
}
function saveQueryToTable() {
var sql = 'query-b';
var projectId = 'xxx';
var datasetId = 'xxx';
var tableId = 'xxx';
var job = {
configuration: {
query: {
query: sql,
writeDisposition:'WRITE_APPEND',
allowLargeResults: 'TRUE',
destinationTable: {
projectId: projectId,
datasetId: datasetId,
tableId: tableId
}
}
}
};
var queryResults = BigQuery.Jobs.insert(job, projectId);
Logger.log(queryResults.status);
}

Create complex JSON objects

Hi I have a question to the azure mobile Service custom API script.
I have a custom script to create a JSON Response.
First step was to get flat objects.
Thsi is my code:
var sql = "SELECT [Project].[id] AS [ID]," +
"[Project].[Name] AS [Name]," +
"FROM [Project]";
request.service.mssql.query(sql, [], {
success: function(results) {
if (results.length === 0) {
response.json(statusCodes.OK, results);
return;
}
var resultSet = [];
results.forEach(function(poi) {
resultSet.push(
{
ID: poi.ID,
Name: poi.Name,
RelatedObjects:
{
[
**???**
]
},
});
})
response.json(statusCodes.OK, resultSet);
}
});
This works very well. Now I want to extend my result objects by some sub objects from a releated table. But not simple singel sub properties (this is easy via join), I want to add collections of sub properties selected from another table.
But I don't know how to get the second query into my code? :(
I think it has to be on "???" marked position.
I want to use this JSON self creating code because my result sets are much more complex as the example shows.
Please help!
Ok I solve it with this messi code...
I'm sure there is a more elegant way to do this but I don't found it yet.
var sql = "SELECT [Project].[ID]" +
",[Project].[Name]" +
"FROM [Project]";
var sql2 = "SELECT [ID]" +
",[UniqueSN]" +
",[Name]" +
"FROM [DataLogger]" +
"WHERE [DataLogger].[ProjectID] = ?";
request.service.mssql.query(sql, [id], {
success: function(results) {
var resultSet = [];
results.forEach(function(poi) {
var loggerResultSet = [];
request.service.mssql.query(sql2, [poi.ID], {
success: function(results2) {
results2.forEach(function(logger) {
loggerResultSet.push(
{
ID: logger.ID,
Name: logger.Name,
UniqueSN: logger.UniqueSN,
});
})
resultSet.push(
{
ID: poi.ID,
Name: poi.Name,
Logger: loggerResultSet,
});
response.json(statusCodes.OK, resultSet);
console.log(JSON.stringify(resultSet));
}
});
})
}
});

Rally Kanban # of days since first state?

Is there a way to calculate the number of days since the card has been in the first state? Lets use say I use a custom field \for the kanban states. 1,2,3,4 If a card is in state 3 then how long has it been since # 1?
I am not sure of a way to automate it or flag items but if you review the US/DE in question just take a quick look at the revision history.
Any changes in state should be logged in the history.
Use Lookback API to access historic data.
Lookback API allows to see what any work item or collection of work items looked like in the past. This is different from using WS API directly, which can provide you with the current state of objects, but does not have historical data.
LBAPI documentation is available here
Here is an example that builds a grid of stories with a Kanban state. When a story's row is double-clicked, the time this story has spent in three Kanban states is calculated and a grid is built to show the values:
Ext.define('CustomApp', {
extend: 'Rally.app.App',
componentCls: 'app',
launch: function(){
var x = Ext.create('Rally.data.lookback.SnapshotStore', {
fetch : ['Name','c_Kanban','_UnformattedID', '_TypeHierarchy'],
filters : [{
property : '__At',
value : 'current'
},
{
property : '_TypeHierarchy',
value : 'HierarchicalRequirement'
},
{
property : '_ProjectHierarchy',
value : 22222
},
{
property : 'c_Kanban', //get stories with Kanban state
operator : 'exists',
value : true
}
],
hydrate: ['_TypeHierarchy', 'c_Kanban'],
listeners: {
load: this.onStoriesLoaded,
scope: this
}
}).load({
params : {
compress : true,
removeUnauthorizedSnapshots : true
}
});
},
//make grid of stories with Kanban state
onStoriesLoaded: function(store, data){
var that = this;
var stories = [];
var id;
Ext.Array.each(data, function(record) {
var artifactType = record.get('_TypeHierarchy');
if (artifactType[artifactType.length - 1] == "HierarchicalRequirement") {
id = 'US' + record.get('_UnformattedID');
} else if (artifactType[artifactType.length - 1] == "Defect") {
id = 'DE' + record.get('_UnformattedID');
}
stories.push({
Name: record.get('Name'),
FormattedID: id,
UnformattedID: record.get('_UnformattedID'),
c_Kanban: record.get('c_Kanban')
});
console.log(stories);
});
var myStore = Ext.create('Rally.data.custom.Store', {
data: stories
});
if (!this.down('#allStoriesGrid')) {
this.add({
xtype: 'rallygrid',
id: 'allStoriesGrid',
store: myStore,
width: 500,
columnCfgs: [
{
text: 'Formatted ID', dataIndex: 'FormattedID',
},
{
text: 'Name', dataIndex: 'Name', flex: 1,
},
{
text: 'Kanban', dataIndex: 'c_Kanban'
}
],
listeners: {
celldblclick: function( grid, td, cellIndex, record, tr, rowIndex){
id = grid.getStore().getAt(rowIndex).get('UnformattedID');
console.log('id', id);
that.getStoryModel(id); //to eventually build a grid of Kanban allowed values
}
}
});
}else{
this.down('#allStoriesGrid').reconfigure(myStore);
}
},
getStoryModel:function(id){
console.log('get story model');
var that = this;
this.arr=[];
//get a model of user story
Rally.data.ModelFactory.getModel({
type: 'User Story',
context: {
workspace: '/workspace/11111',
project: 'project/22222'
},
success: function(model){
//Get store instance for the allowed values
var allowedValuesStore = model.getField('c_Kanban').getAllowedValueStore( );
that.getDropdownValues(allowedValuesStore, id);
}
});
},
getDropdownValues:function(allowedValuesStore, id){
var that = this;
//load data into the store
allowedValuesStore.load({
scope: this,
callback: function(records, operation, success){
_.each(records, function(val){
//AllowedAttributeValue object in WS API has StringValue
var v = val.get('StringValue');
that.arr.push(v);
});
console.log('arr', this.arr);
that.getStoryById(id); //former makeStore
}
});
},
getStoryById:function(id){
var that = this;
var snapStore = Ext.create('Rally.data.lookback.SnapshotStore', {
fetch: ['c_Kanban', 'Blocked'],
hydrate:['c_Kanban','Blocked'],
filters : [
{
property : '_UnformattedID',
value : id //15
}
],
sorters:[
{
property : '_ValidTo',
direction : 'ASC'
}
]
});
snapStore.load({
params: {
compress: true,
removeUnauthorizedSnapshots : true
},
callback : function(records, operation, success) {
that.onDataLoaded(records, id);
}
});
},
onDataLoaded:function(records, id){
var times = [];
var measure = 'second';
//-----------------------backlog
var backlog = _.filter(records, function(record) {
return record.get('c_Kanban') === 'backlog';
});
console.log('backlog',backlog);
var cycleTimeFromBacklogToInProgress = '';
if (_.size(backlog) > 0) {
var backlog1 = _.first(backlog);
var backlog2 = _.last(backlog);
var backlogDate1 = new Date(backlog1.get('_ValidFrom'));
if (backlog2.get('_ValidTo') === "9999-01-01T00:00:00.000Z") { //infinity
backlogDate2 = new Date(); //now
}
else{
var backlogDate2 = new Date(backlog2.get('_ValidTo'));
}
cycleTimeFromBacklogToInProgress = Rally.util.DateTime.getDifference(backlogDate2,backlogDate1, measure );
}
times.push(cycleTimeFromBacklogToInProgress);
//console.log(cycleTimeFromBacklogToInProgress);
//----------------------in progress
var inProgress = _.filter(records, function(record) {
return record.get('c_Kanban') === 'in-progress';
});
console.log('in-progress',inProgress);
var cycleTimeFromInProgressToDone = '';
if (_.size(inProgress) > 0) {
var inProgress1 = _.first(inProgress);
var inProgress2 = _.last(inProgress);
var inProgressDate1 = new Date(inProgress1.get('_ValidFrom'));
if (inProgress2.get('_ValidTo') === "9999-01-01T00:00:00.000Z") { //infinity
inProgressDate2 = new Date(); //now
}
else{
var inProgressDate2 = new Date(inProgress2.get('_ValidTo'));
}
cycleTimeFromInProgressToDone = Rally.util.DateTime.getDifference(inProgressDate2,inProgressDate1, measure );
}
times.push(cycleTimeFromInProgressToDone);
//console.log(cycleTimeFromInProgressToDone);
//------------------------done
var done = _.filter(records, function(record) {
return record.get('c_Kanban') === 'done';
});
console.log('done',done);
var cycleTimeFromDoneToReleased = '';
if (_.size(done) > 0) {
var done1 = _.first(done);
var done2 = _.last(done);
var doneDate1 = new Date(done1.get('_ValidFrom'));
if (done2.get('_ValidTo') === "9999-01-01T00:00:00.000Z") { //infinity
doneDate2 = new Date(); //now
}
else{
var doneDate2 = new Date(done2.get('_ValidTo'));
}
cycleTimeFromDoneToReleased = Rally.util.DateTime.getDifference(doneDate2,doneDate1, measure );
}
times.push(cycleTimeFromDoneToReleased);
//console.log(cycleTimeFromDoneToReleased);
/**********
skip first '' element of the this.arr and last 'released' element of this.arr because
do not care for cycle times in first and last kanban states
Originally: arr ["", "backlog", "in-progress", "done", "released"] ,shorten to: ["backlog", "in-progress", "done"]
**********/
this.arrShortened = _.without(this.arr, _.first(this.arr),_.last(this.arr)) ;
console.log('this.arrShortened with first and last skipped', this.arrShortened); //["backlog", "in-progress", "done"]
cycleTimes = _.zip(this.arrShortened, times);
//console.log('cycleTimes as multi-dimentional array', cycleTimes);
cycleTimes = _.object(cycleTimes);
//console.log('cycleTimes as object', cycleTimes); //cycleTimes as object Object {backlog: 89, in-progress: 237, done: 55}
var cycleTimesArray = [];
cycleTimesArray.push(cycleTimes);
console.log('cycleTimesArray',cycleTimesArray);
var store = Ext.create('Rally.data.custom.Store',{
data: cycleTimesArray,
pageSize: 100
});
var columnConfig = [];
_.each(cycleTimes,function(c,key){
var columnConfigElement = _.object(['text', 'dataIndex', 'flex'], ['time spent in ' + key, key, 1]);
columnConfig.push(columnConfigElement);
});
var title = 'Kanban cycle time for US' + id + ' in ' + measure + 's'
if (!this.grid) {
this.grid = this.add({
xtype: 'rallygrid',
title: title,
width: 500,
itemId: 'grid2',
store: store,
columnCfgs: columnConfig
});
}
else{
this.down('#grid2').reconfigure(store);
}
}
});

dojo 1.8: populate select box with items from database including null values

Hi I just want to populate the select or comboBox.
I am able to populate both with the searchAttr to any string from JSON. But not so when there are null values.
JSON string :
[{"batch":"0000001000"},{"batch":"0000"},{"batch":""},{"batch":null}]
dojo code:
var selBatch = new ComboBox //located at the left side of the page and it is the second select box in a row
(
{ id:'ID_selBatch',
value:'',
searchAttr:'batch',
placeHolder:'Select...',
style:{width:'150px'},
}, 'node_selBatch'
);
on(selTest, 'change', function(valueCard)
{
var selectedTest = this.get('displayedValue');
var selBatch = registry.byId('ID_selBatch');
console.debug('Connecting to gatherbatches.php ...');
request.post('gatherbatches.php',
{ data:{nameDB:registry.byId('ID_selPCBA').value, nameCard : valueCard},
handleAs: "json"}).then
(
function(response)
{
var memoStore2 = new Memory({data:response});
selBatch.set('store', memoStore2);
selBatch.set('value','');
console.debug('List of batches per Test is completed! Good OK! ');
},
function(error)
{
alert("Batch's Error:"+error);
console.debug('Problem: Listing batches per Test in select Test is BAD!');
}
);
selBatch.startup();
});
Error :
TypeError: _32[this.searchAttr] is null
defer() -> _WidgetBase.js (line 331)
_3() -> dojo.js (line 15)
_f.hitch(this,fcn)(); -> _WidgetBase.js (line 331)
Please advise though it might strange to have null values populate in the select box but these null values are related to data in other columns in database, so the null values included so that I can apply mysql scripts later. Or do you have other better suggestion?
Clement
You can create a QueryFilter as in this jsfiddle to achieve what you want, but it might be simpler to have two data items. Your original model with possibly null batch properties, and the model you pass to the store which is used by the ComboBox.
But anyway, this can work:
function createQueryFilter(originalQuery, filter) {
return function () {
var originalResults = originalQuery.apply(this, arguments);
var results = originalResults.filter(filter);
return QueryResults(results);
};
}
and
var memoStore = new Memory({
data: data
});
memoStore.query = createQueryFilter(memoStore.query, function (item) {
console.log(item);
return !!item.batch;
});
and the dummy data:
function createData1() {
var data = [];
for (var i = 0; i < 10; i++) {
data.push({
name: "" + i,
batch: (0 === i % 2) ? "batch" + i : null
});
}
return data;
}
Screenshot. The odd numbered batch items are null in my example.

dojo ItemFileReadStore.getValue mixed return value is not handled as string

I'am using dojo.data.ItemFileReadStore to query a json file with data. the main purpose is finding translations at Js level.
The Json data has "id" the word and "t" the translation
function translate(word)
{
var json = '/my/language/path/es.json';
var reader = new dojo.data.ItemFileReadStore({
url: json
});
var queryObj = {};
queryObj["id"] = word;
reader.fetch({
query: queryObj,
onComplete: function(items, request){
if (items.length > 0) {
var t = reader.getValue(items[0], 't');
if (dojo.isString(t)) {
return t;
}
}
return word;
},
onError: function(error, request){
return word;
}
});
}
The return value is always a undefined wether there is a translation or not. any ideas?
I tried typecasting with no success.
You can do it like this:
function translate(wordId) {
var translatedWord= wordId;
var store = new dojo.data.ItemFileReadStore({ data: storeData });
store.fetch({ query: { id: wordId },
onItem: function (item) {
translatedWord= (store.getValue(item, 't'));
}
});
return translatedWord;
}