Rally SDK: Retrieving all available State values for Defects - javascript

I want to retrieve all available State values for Rally Defect.
The following code works good for Features:
this.states = [];
this.stateStore = Ext.create('Ext.data.Store', {
fields: ['_ref', 'name']
});
Ext.create('Rally.data.wsapi.Store', {
model: 'State',
autoLoad: true,
filters: [
{
property: 'Enabled',
operation: '=',
value: true
},
{
property: 'TypeDef.Name',
operation: '=',
value: 'Feature'
}
],
listeners: {
load: function (store, data) {
for (var i = 0; i < data.length; i++) {
this.stateStore.add({ '_ref': data[i].data._ref, 'name': data[i].data.Name });
}
this.statesLoaded = true;
this._initialLoad();
},
scope: this
}
});
With this approach, we load all available State values for features. However, when I change 'Feature' TypeDef.Name filter to 'Defect', I get nothing despite the fact that there are many active States for Defect defined.
Does anybody know why this happens and how get State values for Defect?
Maybe Defects use some other states, not like features, suer stories etc?

In WS API there is a full State object that represents State of PortfolioItems. It is different from the State or ScheduleState of such artifacts as Defect or UserStory, which are only string values in the dropdown field. There is no such thing as State.Name for a Defect.
Using promises, this may look like this:
launch: function(){
this._getModel().then({
success: this._getAllowedValues,
scope:this
}).then({//...})
},
_getModel:function(){
return Rally.data.ModelFactory.getModel({
type:'Defect'
});
},
_getAllowedValues:function(model){
var deferred = Ext.create('Deft.Deferred');
var allowedStateValues = [];
model.getField('State').getAllowedValueStore().load({
callback: function(records,operation,success){
Ext.Array.each(records,function(allowedValue){
allowedStateValues.push(allowedValue.get('StringValue'));
});
if(success){
deferred.resolve(allowedStateValues);
}
else{
deferred.reject();
}
}
}) ;
return deferred.promise;
},//...
See this example that retrieves allowed values for Priority and Severity of defects. Since those allow null values, null values are removed in this app example, but State does not have null values so you may skip that step.

Related

How setup valuegetter for auto Group Column in Ag-Grid

I have autoGroupColumnDef and I want to setup text filter. But values of the column come from getDataPath method. But I need another value in the filter.
autoGroupColumnDef: {
headerName: "Systems",
filter: 'text',
valueGetter: function(params) {
var result = params.data.hospName || params.data.hospitalSystem;
return result;
},
cellRendererParams: {
suppressCount: true,
innerRenderer: function(params) {
var result = params.data.hospName || params.data.hospitalSystem;
return result;
}
}
},
After trying on couple of things,
Option 1: You can make use of [filterParams][1]. This only helps to play around with options/choices in the filterMenu..
function filterCellRenderer(params) {
//other than params.value nothing else will be there..
// params.data won't be there when its called from filter popup
return params.value+" Custom";
}
var gridOptions= {
...,
treeData: true,
components: {
...,
filterCellRenderer: filterCellRenderer
},
autoGroupColumnDef: {
...,
filterParams: {
cellRenderer: 'filterCellRenderer',
//values: ["A", "XYZ"] //you can feed directly specific values. These need to be part of filePath. Else filtering won't work.
}
}
}
Option 2: If you are looking for custom filter (tweak with GUI), or you want to post processing after it has been configured by ag-grid you can define the following:
var gridOptions = {
...
getMainMenuItems: getMainMenuItems,// function to build your own menu
postProcessPopup: function(params){
// edit the popup..
//params.type gives whether its column menu or not.
//params.ePopup gives handler to popup which you can modifiy.
},
...
}
OR you can build your own custom filter as described here

Using $http in Angular service for json data

I'm having a issue with angular services. The code included are 2 factory services. The values in the services are used to populate a slider in view.
I've tried for a day before asking. I've reviewed a couple posts here stackoverflow post and the post linked.
The first function references a $http GET to a json file. The second function are the values hard coded.
The slider program is able to display the required fields from gloveSize() with no issue.
But putting the exact same info in a json file the slider issues undefined.
function glvType($http) {
function getGloves() {
return $http.get('./assets/test.json').success(function (data) {
return data;
})
}
return { getGloves:getGloves }
}
function gloveSize() {
function getGloveSize() {
return [{ value: '10.50', legend: 'Youth Baseball' },
{ value: '11.00', legend: '2B/SS', id: 'bfbee3fb9893fc6d8555bbfa06176619' },
{ value: '11.25' },
{ value: '11.50', legend: 'Pitcher' },
{ value: '11.75', legend: '3B/Pitcher' },
{ value: '12.00' },
{ value: '12.25', legend: 'Softball Inf' },
{ value: '12.50', legend: 'Outfield' },
{ value: '12.75', legend: 'OF/1st Base' },
{ value: '13.00' }];
}
return { getGloveSize:getGloveSize }
}
In the glvType function console.log of the data is there. In the controller,following answer from other posts, understanding the concept of promise functionality.
Array [ Object, Object, Object, Object, Object, Object, Object, Object, Object, Object, 3 moreā€¦ ]
$scope.product = gloveSize.getGloveSize();
$scope.glvSpec = glvType.getGloves().then(function (data) {
$scope.gloveSpec = data;
for (var i; i < $scope.gloveSpec; i++) {
console.log($scope.gloveSpec[i].value);
}
});
From here, I tell the slider directive to pull array data from $scope.glvSpec, however the results contiue are undefined.
A console.log in the then(function) shows that the info is there.
Object { data: Array[13], status: 200, headers: fd/<(), config: Object, statusText: "OK" }
Lastly, the scope.product variable you see in code is how I pull the static function array into the controller. Adding this to the directive options, displays the values as designed.
Thanks for any guidance.
Change your getGloves() to return the $http call itself instead of using the success method to return data - then data will be available in your .then params:
function getGloves() {
return $http.get('./assets/test.json');
}
Your loop needs to be fixed like so:
for (var i = 0; i < $scope.gloveSpec.length; i++) {
console.log($scope.gloveSpec[i].value);
}
I've also put a plunker together for you to show you how you achieve this with angular.
Make your $http call in a service (DataService) and inject that into your component controller. Then you can ask the DataService for your data and handle accordingly.
http://plnkr.co/edit/ZJW12W4kk0paBshgtfIG?p=preview

Populate Backbone.js JSON response into nested collections inside nested collections/models

My problem is that I am just starting out with Backbone.js and are having trouble wrapping my head around a complex problem. I want to save a form that have infinite fields, and some of the fields also needs to have infinite options. I'm just worried I might have started at the wrong end with a JSON response, instead of building the models/collections first. Here is a short pseudocode of what I try to achieve.
id:
parent: <blockid>
fields: array(
id:
title:
helpertext
options: array(
id:
type:
value:
)
)
Currently I am working with a faked JSON response from the server, which I built from scratch, and now I want to divide it into models and collections on the client side.
//Fake a server response
var JSONresponse = {
"formid":"1",
"fields":[
{
"fieldid":"1",
"title":"Empty title",
"helper":"Helper text",
"type":"radio",
"options":[
{
"optionid":"1",
"value":"Empty option.."
},
{
"optionid":"2",
"value":"Empty option.."
}
]
},
{
// fieldid2
}
]
};
The idea is to add fields as I see fit, and then if the field type is radio/checkbox/ul/ol there must also be an "options" array within the field.
My work so far:
var app = {};
app.Models = {};
app.Collections = {};
app.View = {};
app.Models.Option = Backbone.Model.extend({
});
app.Collections.Options = Backbone.Collection.extend({
model: app.Models.Option
});
app.Models.Field = Backbone.Model.extend({
options: new app.Collections.Options()
});
app.Collections.Fields = Backbone.Collection.extend({
model: app.Models.Field
});
app.Models.Form = Backbone.Model.extend({
formid : "1",
fields: new app.Collections.Fields(),
initialize: function() {
}
});
How do I split up my JSON response into all these models and collections?
(Perhaps I should re-evaluate my approach, and go for something like form.fieldList and form.optionList[fieldListId] instead. If so, how would that look like?)
Edit: Here is a little jsfiddle after many fixes, but I still don't really know how to make the inner options list work.
The easiest solution would be using Backbone Relational or Backbone Associations.
The documentation should be enough to help you get started.
If you don't want to use a library you could override the parse function on the Form model.
app.Models.Form = Backbone.Model.extend({
defaults: {
fields: new app.Collections.Fields()
},
parse: function(response, options) {
return {
formid: response.formid,
fields: new app.Collections.Fields(_.map(response.fields, function(field) {
if (field.options) {
field.options = new app.Collections.Options(field.options);
}
return field;
}))
};
}
});
Now if you fetch a form from the server, the response will be parsed into an object graph of models and collections.
form.get('fields') will return an app.Collections.Fields collection. form.get('fields').first().get('options') will return an app.Collections.Options collection, if any options exist.
Also, you could create the form model like this:
var form = new app.Models.Form(JSONresponse, {
parse: true
});
This would result in the same object structure.
It's quite hard to handle the case of nested models and collections right in plain Backbone.
Easiest way of handling this will be something like this:
var Option = Nested.Model.extend({
idAttribute : 'optionid',
defaults : {
optionid : Integer
value : ""
}
});
var Field = Nested.Model.extend({
idAttribute : 'fieldid',
defaults : {
fieldid : Integer,
title : "",
helper : "",
type : "radio",
options : Option.Collection
}
});
var Form = Nested.Model.extend({
idAttribute : 'formid',
defaults : {
formid: Integer,
fields: Field.Collection
});
https://github.com/Volicon/backbone.nestedTypes
And that's it. Yep, you'll get direct access to the attributes as free bonus, just form.fields.first().options.first().value, without that get and set garbage.

What would cause difference between data after usage in ExtJS store

I use the function at the bottom to (re)create a store every time a grid within a (popup) window renders. However I don't understand why typeDetails is different from what gets logged on the longish line with Ext.pluck (based on https://stackoverflow.com/a/5709096/34806).
The former console log always prints what I expect, in the default case [{"label":"","value":""}], or when typeDetails is pre-populated something such as:
[{"label":"foo","value":"bar"},{"label":"what","value":"ever"}]
But the latter console.log always indicates an empty array, and I always get an empty grid. Could the line with pluck be at fault? That answer, though not the accepted or top-scoring, has been up-modded over 20. What else can I do to work through this.
listeners: {
render: {
fn: function (grid) {
var typeDetails = this.typeDetails || [{ 'label': '', 'value': ''}];
var store = Ext.create('Ext.data.Store', {
fields: ['label', 'value'],
data: [typeDetails]
});
console.log(Ext.encode(typeDetails));
console.log(Ext.encode(Ext.pluck(grid.store.data.items, 'data')));
grid.reconfigure(store);
}
}
}
UPDATE/OUTPUT
In response to Evan's comment "In the case where it defaults data, the store data will be [[{label: '', value: ''}]]" below is what is actually directly copied/pasted from my console:
[{"label":"","value":""}]
[]
However I think this is because the logging is before grid.reconfigure. Nevertheless shifting my console/logging as follows:
grid.reconfigure(store);
console.log(Ext.encode(this.typeDetails));
console.log(Ext.encode(typeDetails));
console.log(Ext.encode(Ext.pluck(grid.store.data.items, 'data')));
Results in the following mysterious output in the non-default case (when this.typeDetails is pre-populated):
[{"label":"foo","value":"bar"},{"label":"what","value":"ever"}]
[{"label":"foo","value":"bar"},{"label":"what","value":"ever"}]
[{"label":"","value":""}]
It's an editable grid, and the non-default values can only exist after the default empty row, so it's as though that empty row is being retained.
The following alternative approach works:
listeners: {
render: {
fn: function (grid) {
var store = Ext.create('Ext.data.Store', {
fields: ['label', 'value'],
data: []
});
if (this.typeDetails) {
for (var i = 0, n = this.typeDetails.length; i < n; i++) {
store.add(this.typeDetails[i]);
}
}
else {
store.add({ 'label': '', 'value': '' });
}
grid.reconfigure(store);
}
}
}

Foreign key populated with an object

I would like to make a relation between two models User and Task using backbone-relational.
The relation between the two models is the following:
taskModel.creator_id = userModel.id
// TaskModel
var TaskModel = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasOne,
key: 'creator',
keySource: 'creator_id',
relatedModel: Users
}
],
// some code
});
// Task collection
var TaskCollection = Backbone.Collection.extend({
model: TaskModel,
// some code
});
// User Model
var User = Backbone.RelationalModel.extend({
// some code
});
Actually the problem is in the collection.models, please see the attached images:
Please check this jsfiddle: http://jsfiddle.net/2bsE9/5/
var user = new User(),
task = new Task(),
tasks = new Tasks();
task.fetch();
user.fetch();
tasks.fetch();
console.log(user.attributes, task.attributes, tasks.models);
P.S.:
Actually I am using requireJs to get the UserModel, so I cannot include quotes in relatedModel value.
define([
'models/user',
'backbone',
'relationalModel'
], function (User) {
"use strict";
var Task = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasOne,
key: 'creator',
keySource: 'creator_id',
relatedModel: User
}
],
});
);
Edit 2:
http://jsfiddle.net/2bsE9/13/
I updated the jsfiddle to reflect the changes I suggested below. As long as you are calling toJSON on your task, what gets to the server is a json object with the creator_id property set to the actual id of the user. The keyDestination here is redundant as the documentation states it is set automatically if you use keySource.
Edit:
https://github.com/PaulUithol/Backbone-relational#keysource
https://github.com/PaulUithol/Backbone-relational#keydestination
https://github.com/PaulUithol/Backbone-relational#includeinjson
The combination of the three above might solve your issue.
var Task = Backbone.RelationalModel.extend({
relations: [
{
type: Backbone.HasOne,
// The User object can be accessed under the property 'creator'
key: 'creator',
// The User object will be fetched using the value supplied under the property 'creator_id'
keySource: 'creator_id',
// The User object will be serialized to the property 'creator_id'
keyDestination: 'creator_id',
// Only the '_id' property of the User object will be serialized
includeInJSON: Backbone.Model.prototype.idAttribute,
relatedModel: User
}
],
});
The documentation also states that the property specified by keySource or keyDestination should not be used by your code. The property cannot be accessed as an attribute.
Please try this and comment if that fixes your issue.
Btw, here is a nice blog post that uses backbone-relational end to end.
http://antoviaque.org/docs/tutorials/backbone-relational-tutorial/
Edit
Updated jsfiddle
The problem is that Backbone-Relational explicitly deletes the keySource to 'prevent leaky abstractions'. It has a hardcoded call to unset on the attribute, in Backbone-Relational:
// Explicitly clear 'keySource', to prevent a leaky abstraction if 'keySource' differs from 'key'.
if ( this.key !== this.keySource ) {
this.instance.unset( this.keySource, { silent: true } );
}
You will need to overwrite the unset method in your Task model:
var Task = Backbone.RelationalModel.extend({
urlRoot: ' ',
relations: [
{
type: Backbone.HasOne,
key: 'creator',
relatedModel: User,
keySource: 'creator_id'
}
],
unset: function(attr, options) {
if (attr == 'creator_id') {
return false;
}
// Original unset from Backbone.Model:
(options || (options = {})).unset = true;
return this.set(attr, null, options);
},
sync: function (method, model, options) {
options.success({
id: 1,
name: 'barTask',
creator_id: 1
});
}
});
Obvious problems with this approach are that you will need to modify your code if either Backbone changes its Backbone.Model.unset method or Backbone-Relational changes its keySource behavior.

Categories