mirror of
https://github.com/nasa/openmct.git
synced 2024-12-19 05:07:52 +00:00
[Layout] Layout rebuilds after resize/reposition - Fixed potential race condition #32
This commit is contained in:
parent
424953c894
commit
db7224486c
@ -45,7 +45,8 @@ define(
|
|||||||
* @param {Scope} $scope the controller's Angular scope
|
* @param {Scope} $scope the controller's Angular scope
|
||||||
*/
|
*/
|
||||||
function LayoutController($scope) {
|
function LayoutController($scope) {
|
||||||
var self = this;
|
var self = this,
|
||||||
|
callbackCount = 0;
|
||||||
|
|
||||||
// Update grid size when it changed
|
// Update grid size when it changed
|
||||||
function updateGridSize(layoutGrid) {
|
function updateGridSize(layoutGrid) {
|
||||||
@ -91,23 +92,26 @@ define(
|
|||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
}
|
}
|
||||||
|
|
||||||
function getComposition(domainObject){
|
|
||||||
return domainObject.useCapability('composition');
|
|
||||||
}
|
|
||||||
|
|
||||||
function composeView (composition){
|
|
||||||
$scope.composition = composition;
|
|
||||||
return composition.map(function (object) {
|
|
||||||
return object.getId();
|
|
||||||
}) || [];
|
|
||||||
}
|
|
||||||
|
|
||||||
//Will fetch fully contextualized composed objects, and populate
|
//Will fetch fully contextualized composed objects, and populate
|
||||||
// scope with them.
|
// scope with them.
|
||||||
function refreshComposition(ids) {
|
function refreshComposition() {
|
||||||
return getComposition($scope.domainObject)
|
//Keep a track of how many composition callbacks have been made
|
||||||
.then(composeView)
|
var thisCount = ++callbackCount;
|
||||||
.then(function(ids){self.layoutPanels(ids);});
|
|
||||||
|
$scope.domainObject.useCapability('composition').then(function(composition){
|
||||||
|
var ids;
|
||||||
|
|
||||||
|
//Is this callback for the most recent composition
|
||||||
|
// request? If not, discard it. Prevents race condition
|
||||||
|
if (thisCount === callbackCount){
|
||||||
|
ids = composition.map(function (object) {
|
||||||
|
return object.getId();
|
||||||
|
}) || [];
|
||||||
|
|
||||||
|
$scope.composition = composition;
|
||||||
|
self.layoutPanels(ids);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// End drag; we don't want to put $scope into this
|
// End drag; we don't want to put $scope into this
|
||||||
|
@ -33,7 +33,8 @@ define(
|
|||||||
testConfiguration,
|
testConfiguration,
|
||||||
controller,
|
controller,
|
||||||
mockCompositionCapability,
|
mockCompositionCapability,
|
||||||
mockComposition;
|
mockComposition,
|
||||||
|
mockCompositionObjects;
|
||||||
|
|
||||||
function mockPromise(value){
|
function mockPromise(value){
|
||||||
return {
|
return {
|
||||||
@ -67,6 +68,7 @@ define(
|
|||||||
testModel = {};
|
testModel = {};
|
||||||
|
|
||||||
mockComposition = ["a", "b", "c"];
|
mockComposition = ["a", "b", "c"];
|
||||||
|
mockCompositionObjects = mockComposition.map(mockDomainObject);
|
||||||
|
|
||||||
testConfiguration = {
|
testConfiguration = {
|
||||||
panels: {
|
panels: {
|
||||||
@ -77,7 +79,7 @@ define(
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
mockCompositionCapability = mockPromise(mockComposition.map(mockDomainObject));
|
mockCompositionCapability = mockPromise(mockCompositionObjects);
|
||||||
|
|
||||||
mockScope.domainObject = mockDomainObject("mockDomainObject");
|
mockScope.domainObject = mockDomainObject("mockDomainObject");
|
||||||
mockScope.model = testModel;
|
mockScope.model = testModel;
|
||||||
@ -107,6 +109,30 @@ define(
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("Is robust to concurrent changes to composition", function () {
|
||||||
|
var secondMockComposition = ["a", "b", "c", "d"],
|
||||||
|
secondMockCompositionObjects = secondMockComposition.map(mockDomainObject),
|
||||||
|
firstCompositionCB,
|
||||||
|
secondCompositionCB;
|
||||||
|
|
||||||
|
spyOn(mockCompositionCapability, "then");
|
||||||
|
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||||
|
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||||
|
|
||||||
|
firstCompositionCB = mockCompositionCapability.then.calls[0].args[0];
|
||||||
|
secondCompositionCB = mockCompositionCapability.then.calls[1].args[0];
|
||||||
|
|
||||||
|
//Resolve promises in reverse order
|
||||||
|
secondCompositionCB(secondMockCompositionObjects);
|
||||||
|
firstCompositionCB(mockCompositionObjects);
|
||||||
|
|
||||||
|
//Expect the promise call that was initiated most recently to
|
||||||
|
// be the one used to populate scope, irrespective of order that
|
||||||
|
// it was eventually resolved
|
||||||
|
expect(mockScope.composition).toBe(secondMockCompositionObjects);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
it("provides styles for frames, from configuration", function () {
|
it("provides styles for frames, from configuration", function () {
|
||||||
mockScope.$watchCollection.mostRecentCall.args[1]();
|
mockScope.$watchCollection.mostRecentCall.args[1]();
|
||||||
expect(controller.getFrameStyle("a")).toEqual({
|
expect(controller.getFrameStyle("a")).toEqual({
|
||||||
|
Loading…
Reference in New Issue
Block a user