Rally App onLoad - extjs

I have a Rally app that requires considerable loading time and it has some loops containing Data Stores. I need to find a condition where the app has completed loading. Once the execution of the app is complete, I want to refresh my page. Is there something like onLoad() that I can use to notify that the app has loaded completely and then I could add window.location.reload at the bottom?

I would suggest using either a callback function, for a single data store, or a series of promises for multiple data stores. The former is pretty straight forward but this is how I usually handle the latter:
In this case, I'm simultaneously loading all the User Stories, Defects and Test Cases in the current scope, then when all the records have been loaded successfully, the "success" function will be called.
launch: function() {
Deft.Promise.all([
this.loadRecords('UserStory'),
this.loadRecords('Defect'),
this.loadRecords('TestCase')
]).then({
success: function(recordSets) {
// recordSets = [
// UserStoryRecords,
// DefectRecords,
// TestCaseRecords
// ];
},
failure: function() {
//Handle error loading the store here...
}
});
},
loadRecords: function(model) {
var deferred = Ext.create('Deft.Deferred');
Ext.create('Rally.data.WsapiDataStore', {
limit : Infinity,
model : model,
fetch : ['Name','ObjectID']
}).load({
callback : function(records, operation, success) {
if (operation.wasSuccessful()) {
deferred.resolve(records);
} else {
deferred.reject();
}
}
});
return deferred.promise;
}
Hope this helps!

Related

Extjs6 Custom js event

I have the following flow: before the app launches I want to check something on the server. Based on the response I want to make a decision. I've created an utility class that wraps my js event and also an app controller.
Bellow is app controller:
Ext.define('MyApp.controller.AppController', {
extend: 'Ext.app.Controller',
appEventDispatcher:function (){
// Create a dummy DOM element
var dummy = document.createTextNode('');
// Create custom wrappers with nicer names
this.off = dummy.removeEventListener.bind(dummy);
this.on = dummy.addEventListener.bind(dummy);
this.trigger = function(eventName, data){
if( !eventName ) return;
var e = new CustomEvent(eventName, {"detail":data});
dummy.dispatchEvent(e);
}
}
});
And my utility class:
Ext.define('MyApp.util.Util', {
statics : {
checkSomethingOnServer: function(customEvent){
var store = Ext.StoreManager.lookup('appStore');
store.load({
scope: this,
callback: function(records, operation, success){
if (success === true){
customEvent.trigger('success', true);
if (success === false)
debugger;
customEvent.trigger('fail', true);
}
}
});
}
}
});
Using the utility class I load a store. In the callback method, I trigger my custom event. This event is handled in the app.js file.
The code works in fiddle and also using app watch, when I want to build the code some errors are occurring complaining(syntax error).
I've created also a fiddle.
How to create a custom event in ExtJS and how to use it? I need the same behavior as with the js event but Extjs implementation.
In ExtJS, you would just attach an event listeners to the store with your custom event's name:
store.on('myownevent', function(success) {
console.log(success);
});
and your code may go ahead and fire events on the store by that name:
store.load({
scope: this,
callback: function(records, operation, success){
store.fireEvent('myownevent', success);
}
});
If no listener for that event is attached, nothing happens; if one or more listeners are attached, they are executed in the order of priority, for those with the same priority, in the order they were added.
https://fiddle.sencha.com/#view/editor&fiddle/21g7

when I resume app by Custom URL scheme first time,the window.handleOpenURL doesn't execute

When I start app by custom scheme url,event 'deviceready' trigger,and window.handleOpenURL in the getBillFromLink() execute;
then I open a webpage and resume the app from it,but window.handleOpenURL didn't execute;function onResume and getBillFromLink will execute;
but no matter how many times I resume the app from webpage after the first time,
window.handleOpenURL will execute normally;
Here are code:
$ionicPlatform.on("deviceready", function () {
document.addEventListener("resume", onResume, false);
getBillFromLink().then(function (data) {
//todo
});
});
function onResume() {
getBillFromLink().then(function (data) {
//todo
});
}
function getBillFromLink() {
var deferred = $q.defer();
$timeout(function() {
window.handleOpenURL = function(url){
if(!!url){
deferred.resolve(url);
}else{
deferred.reject(url);
}
};
}, 0);
return deferred.promise;
}
how could I deal with the trouble?
thanks for your advice and sorry for my poor English:-)
Your issue is not linked to custom-scheme-url plugin as your apps properly starts when you call your specific URL.
I assume that, once the app is already started; custom-scheme-url does not trigger again your function.
You have to use a backgroundmode plugin.
I suggest to use : https://github.com/katzer/cordova-plugin-background-mode
This plugin let s you define events when apps goes from background to active app. and more.

Sencha Touch loading from store after login - race issue?

I intend to load data from server only after the user is Authenticated.
For simplicity, let us assume that the user is already authenticated.
I put the load data function call (that loads data from a store) in the Main.js initialize function as you can see below.
However, the getStore('storeId').load() function is async, which makes me worried in case the data store finished loading only after the Main view finished loading which might make the view load without the data (fix me if I am wrong, maybe sencha can deal with this, the view has reference to the storeId).
What is the best practice to target such issues?
Trivial solution: calling the store load synchronously, but does it make any difference? and just in case, how to do it? I tried to add synchronous variable set to true but doesn't work.
app.js
launch: function() {
// Destroy the #appLoadingIndicator element
Ext.fly('appLoadingIndicator').destroy();
Ext.Ajax.request({
url: MyApp.app.baseUrl + 'session/mobileCheckAuth',
method: "POST",
useDefaultXhrHeader: false,
withCredentials: true,
success: function(response, opts) {
if (response && response.status === 200) {
Ext.Viewport.add(Ext.create('MyApp.view.Main'));
} else {
Ext.Viewport.add(Ext.create('MyApp.view.LoginPanel'));
}
},
failure: function(response, opts) {
alert('Unexpected failure detected');
Ext.Viewport.add(Ext.create('MyApp.view.LoginPanel'));
}
});
},
Main.js
Ext.define('MyApp.view.Main', {
...
initialize: function() {
console.log('main.initialize');
this.callParent(arguments);
// Load app data
MyApp.utils.Functions.loadData();
}
There are two ways to solve this :
If your view consists of a grid, there will not be a race condition. If the grid renders before the store has finished loading, the grid will update itself with the new data that is added. For this to work, you have to declare the store as 'store: "mystore";' .
If you have a complex view that is not directly bound to the store, you have to load the store first, and in the on 'load' event of the store you initialize the rendering of the view.
store.load({callback: function(){
Ext.Viewport.add(Ext.create('MyApp.view.Main'}
});

Angular.js, $resource, how to manage multiple asynchronous requests

I am implementing a "copy on write" CRUD system meaning i never overwrite a database entry but mark as inactive and write a new record. When editing an existing record this means i write to the old record deactivating then create a new record. My controller code is below:
$scope.save = function() {
if(!$scope.newDevice){
var editDevice = $scope.device;
$scope.delete(editDevice);
$scope.device = {name: editDevice.name, type: editDevice.type, hash: editDevice.hash};
}
var newDevice = new DeviceService($scope.device);
newDevice = newDevice.$save(function(newDevice, putResponseHeaders) {
DeviceService.query({active : true}, function(devices){
$scope.devices = devices;
});
});
};
When i call to get the list of active devices with DeviceService.query({active : true} I still get the old record as active since it executes and returns before the delete method has been processed and returned.
I think i should be using promise maybe. How do i write this code to be better and work?
thanks
Yes, you want to use promises. You have two options:
Use the success/failure callbacks that all $resource methods supply. Note you're using this when you call $save. You could do the same when you call $delete on the resource, so that your remaining code only executes when the $delete() succeeds. These callbacks are automatically invoked when the $resource's built-in promise is resolved or rejected.
Make your $scope.delete() function return a promise. It sounds like this might be better, because you do not always want to make the delete request.
The code for #2 might look like this:
// this function use the '$q' service, which you need to inject
// in your controller
$scope.delete = function(item) {
var deferred = $q.defer();
item.$delete({},
function(response) {
// the delete succeeded, resolve the promise
deferred.resolve(response);
},
function(error) {
// failed, reject the promise
deferred.reject(error);
}
);
return deferred.promise;
}
$scope.save = function() {
if(!$scope.newDevice){
var editDevice = $scope.device;
$scope.delete(editDevice).then(function(response) {
$scope.device = {name: editDevice.name, type: editDevice.type, hash: editDevice.hash};
// now trigger the code to save the new device (or whatever)
$scope.doTheActualSave();
},
function(error) { });
} else {
// there was nothing to delete, just trigger the code to save
$scope.doTheActualSave();
}
};
$scope.doTheActualSave = function() {
var newDevice = new DeviceService($scope.device);
newDevice = newDevice.$save(function(newDevice, putResponseHeaders) {
DeviceService.query({active : true}, function(devices){
$scope.devices = devices;
});
});
}

How to handle async code in a backbone marionette initializer

I'm trying to put together backbone application using the marionette plugin, and am having some trouble getting initializers to work the way I expected them to. I have the following code:
var MyApp = new Backbone.Marionette.Application();
MyApp.addRegions({
region1 : '#div1',
region2 : '#div2'
});
MyApp.Resources = { };
MyApp.bind('initialize:before', function (options) {
// display a modal dialog for app initialization
options.initMessageId = noty({
text : 'Initializing MyApp (this should only take a second or two)',
layout : 'center',
speed : 1,
timeout : false,
modal : true,
closeOnSelfClick : false
});
});
MyApp.addInitializer(function (options) {
$.ajax({
url: options.apiUrl + '/my-app-api-module',
type: 'GET',
contentType: 'application/json; charset=utf-8',
success: function (results) {
MyApp.Resources.urls = results;
console.log(MyApp.Resources.urls); // <- THIS returns an object
}
});
});
MyApp.bind('initialize:after', function (options) {
// initialization is done...close the modal dialog
if (options.initMessageId) {
$.noty.close(options.initMessageId);
}
if (Backbone.history) {
Backbone.history.start();
}
console.log(MyApp.Resources.urls); // <- THIS returns 'undefined' BEFORE the console.log in the initializer above
});
Note in the code above that I have two console.log calls, one in the initializer, and one in the initialize:after handler. Both log the same object property. As you can see, what I'm experiencing is that the console.log call in the initialize:after handler is getting called before the one in the success handler of the initializer. I realize that this is because the initializer has an async call in it...what I need to know is, how can I make sure that all of the async code in my initializer(s) is complete before doing anything else in the application? Is there a good pattern for this? I've not found anything in the docs indicating how to handle this correctly.
Thanks.
how can I make sure that all of the async code in my initializer(s) is complete before doing anything else in the application?
Don't use the initialize:after event. Instead, trigger your own event from the success call, and then bind your app start up code from that one.
MyApp.addInitializer(function (options) {
$.ajax({
url: options.apiUrl + '/my-app-api-module',
type: 'GET',
contentType: 'application/json; charset=utf-8',
success: function (results) {
MyApp.Resources.urls = results;
// trigger custom event here
MyApp.vent.trigger("some:event:to:say:it:is:done")
}
});
});
// bind to your event here, instead of initialize:after
MyApp.vent.bind('some:event:to:say:it:is:done', function (options) {
// initialization is done...close the modal dialog
if (options.initMessageId) {
$.noty.close(options.initMessageId);
}
if (Backbone.history) {
Backbone.history.start();
}
console.log(MyApp.Resources.urls);
});
This way you are triggering an event after your async stuff has finished, meaning the code in the handler will not run until after the initial async call has returned and things are set up.
I wrote an override to the start method using jQuery deffereds so you can specify an Async initializer like authentication. The start method then waits til all deferreds are resolved and then finishes the start.
I replace marionette callbacks with my new sync callbacks class so I can use the regular methods calls in the app. Take a look at my solution and see if that helps at all. https://github.com/AlexmReynolds/Marionette.Callbacks
This can be used to accomplish tasks before the rest of your application begins.
Check the documentation.
// Create our Application
var app = new Mn.Application();
// Start history when our application is ready
app.on('start', function() {
Backbone.history.start();
});
// Load some initial data, and then start our application
loadInitialData().then(app.start);

Resources