Using API 2.0, I am working on a super kanban board, and when rendering the card I want a button that will move the story to the next sprint.
I started with adding the iteration combo, but that is overkill. I can add the button and the code, but is there a way to get the next iteration?
I dont see anything out there, thought I would ask here before I started coding.
The kanban board is iteration specific, so i could move up a sprint or two and still want to push it forward, so figure I have to grab the current iteration and somehow get the next one...
Thoughts?
You can query for iterations where the start date is after today, ordered by start date. That should give you the next iteration in records[0]...
Ext.create('Rally.data.WsapiDataStore', {
model: 'Iteration',
fetch: ['Name', 'StartDate', 'EndDate'],
autoLoad: true,
sorters: [
{
property: 'StartDate'
direction: 'ASC'
}
],
filters: [
{
property: 'StartDate',
operator: '>',
value: Rally.util.DateTime.toIsoString(new Date())
}
],
listeners: {
load: function(store, records) {
var nextIteration = records[0];
}
}
});
Related
Using Tablulator (great product!), I am trying to keep the cursor from resetting to the first editable cell in the table after editing a cell. The replaceData function is updating the data element, and while the scroll position does not change, the cursor is reset. I'm not sure how to do this correctly. The documentation, while great, is silent about cursor position beyond the next(), etc methods, which I cannot quite get to work.
In my vue.js table definition component, I have a watch like this:
watch: {
tableData: {
handler: function (newData) {
this.tabulator.replaceData(newData);
},
deep: true,
}
},
and a cellEdited method inside mounted like this:
mounted() {
let self = this;
//todo Possibly validate that cater tips is less than total tips since cater tips is a portion of total tips
self.tabulator = new Tabulator(self.$refs.myTable, {
height: 380, // set height of table (in CSS or here)
placeholder: 'Click "Load Store Tips" to edit data',
data: self.tableData, //link data to table
reactiveData: true, //enable data reactivity
downloadConfig: {columnCalcs: false},
addRowPos:"bottom",
history:true,
layout: "fitDataFill",
initialSort:[
{column:"storeID", dir:"asc"},
],
//Define Table Columns
columns: [
{title: "Store ID", field: "storeID", sorter:"number"},
{title: "Store Tips", field: "inStore_tips", align: "right", formatter: "money", editor: "number", bottomCalc: "sum"},
{title: "Cater Tips", field: "cater_tips", align: "right", formatter: "money", editor: "number", bottomCalc: "sum"},
{title: "Client ID", field: "clientID"},
],
////////////////////////////////////////////////////////////////////////////
// When a cell is edited, write the data out to the server to ensure it is
// always in a saved state.
////////////////////////////////////////////////////////////////////////////
cellEdited: function (e, cell) {
//self.colPos = cell.getColumn(); //trying to save the cursor pos, but generating error
//self.rowPos = cell.getRow(); // generating error
self.PostTipsEventMethod();
}
});
Here is what I have tried:
Tried capturing the row and column position, and then setting that after the replaceData table render, and after the cellEdited method
Tried using the next() method to move the cursor to the next cell inside the cellEdited method, before and after the replaceData function.
Can someone guide me a bit further on this? I've searched through the tabulator element in the debugger trying to find the row and column numbers of the cell I'm editing, but so far, no joy. I guess I don't understand the lifecycle of the table rendering well enough.
Thank you!
I have inherited code that displays a graph of defects on a project. I have now took my project and split it into two projects, so that now there is a parent project and two children. The code (below) just accumulates the defects from the parent and does not include the data from the children.
snippet:
storeType: "Rally.data.lookback.SnapshotStore",
storeConfig: {
find: { _TypeHierarchy: "Defect", Children: null },
fetch: ["Severity", "State"], hydrate: ["Severity", "State"],
sort: { _ValidFrom: 1 },
filters: [{ property: "Project", value: context.getProject().ObjectID }, { property: "_TypeHierarchy", value: "Defect" }, { property: "Children", value: null}] },
So I'm pretty sure the problem is in this part "value: context.getProject().ObjectID" as it says to get the data from the current project (and not its children). How can I accomplish what I need?
Not sure if you're intending to get lookback (time series) data or current (WSAPI) data from Rally. Your code implies lookback so I will answer with that in mind.
You could try adding to your find clause (and removing the current Project filter):
"_ProjectHierarchy": { $in : [123] }
where 123 is the object id of your parent project. That should get defects from any projects that include you parent project in the hierarchy.
So Igor basically got it above, just writing as a post and not in a commet, this is the code that works - you can see why in the comments above. Please note - I did make one change over what he wrote, as when I used the "__At" it caused not all bugs to be counted - it looked like it only counted bugs since their last update time.
storeConfig: {
find: { _TypeHierarchy: "Defect", _ProjectHierarchy: context.getProject().ObjectID},
fetch: ["Severity", "State"], hydrate: ["Severity", "State"],
sort: { _ValidFrom: 1 },
},
I want to create a custom grid and only show userstories that have failed test cases. I checked the API docs and could not work it out.
I tried (TestCaseStatus < Complete) but did not get any results i also tried the same thing with defect status.
What is the specific syntax that i need to use?
In WS API documentation
TestCaseStatus attribute on HierarcicalRequirement object shows allowed values:
"NONE", "NONE_RUN", "SOME_RUN_SOME_NOT_PASSING", "SOME_RUN_ALL_PASSING", "ALL_RUN_NONE_PASSING", "ALL_RUN_ALL_PASSING"
If for example your custom app extends Rally.app.TimeboxScopedApp, and filters user stories by iteration, you may add another filter to exclude ALL_RUN_ALL_PASSING as follows:
onScopeChange: function() {
var filter = this.getContext().getTimeboxScope().getQueryFilter();
filter = filter.and({
property: 'TestCaseStatus',
operator: '<',
value: 'ALL_RUN_ALL_PASSING'
});
Ext.create('Rally.data.WsapiDataStore', {
model: 'UserStory',
fetch: ['FormattedID','Name','TestCases', 'TestCaseStatus'],
pageSize: 100,
autoLoad: true,
filters: [filter],
listeners: {
load: this._onDataLoaded,
scope: this
}
});
},
The full code is available in this github repo.
I'd like to put together a StoryMap app using Initiative (second level) portfolio items as the backbone (columns). To do this the app needs to query for all the second level portfolio items, and then use each PI as a column header in the rallycardboard.
I've gotten the cardboard to display the column headers correctly, but I have not been able to get it to display the cards, which should be the first level of portfolio items (PortfolioItem/Feature).
Here is my code so far:
launch: function() {
this._getInitiativeStore();
},
_getInitiativeStore: function() {
this.initiativeStore = Ext.create('Rally.data.wsapi.Store', {
model: 'PortfolioItem/Initiative',
fetch: ['Name', 'Children'],
autoLoad: true,
listeners: {
load: this._createCardBoard,
scope: this
}
});
},
_createCardBoard: function(store, records) {
var initiativeColumns = [];
Ext.each(records, function(record) {
initiativeColumns.push({
xtype: 'rallycardboardcolumn',
columnHeaderConfig: {
xtype: 'rallycardboardcolumnheader',
fieldToDisplay: 'Name',
record: record,
},
cardConfig: {
xtype: 'rallycard',
record: 'PortfolioItem/Feature'
},
fields: ['Name', 'Parent'],
valueField: 'Parent',
value: record.get('_ref') // BUG FIXED HERE. Was: record.get('Parent')
});
}, this);
var cardBoardConfig = {
xtype: 'rallycardboard',
types: ['PortfolioItem/Feature'],
columns: initiativeColumns,
attribute: 'Parent',
};
var cardBoard = this.add(cardBoardConfig);
console.log('cardboard', cardBoard);
}
I realize I am using this perhaps a bit differently than the authors have planned for, but I'm willing to extend the rallycardboard and rallycolumnheader objects with Ext.define if that's what it takes. I'm starting to look at the Rally source code but its slow going so far.
I was able to figure out the problem by using Ext.define() to override the cardboardcolumn getStoreFilter function to print out its filter value. Probably for somebody good with a browser debugger that would not have been necessary, but I'm not and it pinpointed the problem right away: The "value" field of the initiativeColumn configs should have been record.get('_ref'), not record.get('Parent'). I'll edit the code above so it works.
Now the basic board works great as a story map with portfolio items! Next step is to see if I can incorporate the concept of releases into the map.
Also, I think I found a bug in the 'rallycardboard' constructor-- if I pass it a context reference like: context: { project: 'project/XXX'} where XXX is an OID, it crashes. Instead I need to instantiate a context object and pass that. But that's inconsistent from other items like the wsapi store. Workaround is easy, but it is a bit annoying.
Baffled by this and not sure where to start looking.
I have a carousel which I load when the refresh event fires on my backing store:
Ext.define('Rb.store.Items', {
extend: 'Ext.data.Store',
requires: ['Rb.model.Item', 'Ext.data.proxy.Rest'],
config: {
storeId: 'itemstore',
model: 'Rb.model.Item',
proxy: {
type: 'rest',
url: '',
reader: {
type: 'json',
rootProperty: 'items'
}
},
autoLoad: false,
listeners:{
refresh: function( me, data, eOpts ){
console.log("refresh");
var carousel = Ext.ComponentQuery.query('rbdetailcarousel')[0];
carousel.removeAll(true);
console.log(carousel.getItems().getCount());
data.each(function(rec){
console.log(rec.data);
var rdcp = Ext.create('Rb.view.RbDetailCarouselPanel',{
cur_item: rec.data,
style: 'background-image:url(resources/startup/320x460.jpg);background-repeat:no-repeat;',
});
rdcp.items.get(1).setHtml(rec.data.name);
carousel.setActiveItem(rdcp);
});
carousel.setActiveItem(0);
}
}
}
});
My carousel is super simple:
Ext.define('Rb.view.RbDetailCarousel', {
extend: 'Ext.Carousel',
xtype: 'rbdetailcarousel',
config: {
itemId: 'rbdetailcarousel',
}
});
There are two things that are happening here that are strange:
When I call carousel.getItems().getCount(), right after the carousel.removeAll(true), I always get a return value of 1. If I inspect the carousel, there is still one item left in the carousel (it looks like it's the indicator??).
When I reload the store, it clears out all the items except the first one, so that as I refresh more and more I get repeats of the first item, then the remaining items added to the end. It seems as if the removeAll(true) is not removing that first item.
Any ideas on where I can look to solve this? I have a suspicion that I'm not grabbing the reference to the carousel correctly, because I shouldn't be getting back the indicator as one of the items in it, right?
Thanks
As hinted at by OhmzTech and answered on the sencha forum, I was adding items to my carousel which had duplicate itemId's. I'm still a little fuzzy on the standing of these ids (and to what extend they are used by the framework internally), apparently you don't want to have a single container with duplicate children itemIds.