diff --git a/platform/commonUI/browse/bundle.js b/platform/commonUI/browse/bundle.js index 74c4059cab..a66285f572 100644 --- a/platform/commonUI/browse/bundle.js +++ b/platform/commonUI/browse/bundle.js @@ -92,6 +92,13 @@ define([ "reloadOnSearch": false } ], + "constants": [ + { + "key": "DEFAULT_PATH", + "value": "mine", + "priority": "fallback" + } + ], "controllers": [ { "key": "BrowseController", @@ -103,7 +110,8 @@ define([ "$q", "objectService", "navigationService", - "urlService" + "urlService", + "DEFAULT_PATH" ] }, { diff --git a/platform/commonUI/browse/src/BrowseController.js b/platform/commonUI/browse/src/BrowseController.js index e574c7a77a..d1d5aa92cc 100644 --- a/platform/commonUI/browse/src/BrowseController.js +++ b/platform/commonUI/browse/src/BrowseController.js @@ -34,7 +34,6 @@ define( "use strict"; var ROOT_ID = "ROOT", - DEFAULT_PATH = "mine", CONFIRM_MSG = "Unsaved changes will be lost if you leave this page."; /** @@ -47,9 +46,18 @@ define( * @memberof platform/commonUI/browse * @constructor */ - function BrowseController($scope, $route, $location, $q, objectService, navigationService, urlService) { + function BrowseController( + $scope, + $route, + $location, + $q, + objectService, + navigationService, + urlService, + defaultPath + ) { var path = [ROOT_ID].concat( - ($route.current.params.ids || DEFAULT_PATH).split("/") + ($route.current.params.ids || defaultPath).split("/") ); function isDirty(){ @@ -143,6 +151,12 @@ define( } else { doNavigate(nextObject, index + 1); } + } else if (index === 1 && c.length > 0) { + // Roots are in a top-level container that we don't + // want to be selected, so if we couldn't find an + // object at the path we wanted, at least select + // one of its children. + navigateTo(c[c.length - 1]); } else { // Couldn't find the next element of the path // so navigate to the last path object we did find diff --git a/platform/commonUI/browse/test/BrowseControllerSpec.js b/platform/commonUI/browse/test/BrowseControllerSpec.js index 582993e5a7..e4fad10544 100644 --- a/platform/commonUI/browse/test/BrowseControllerSpec.js +++ b/platform/commonUI/browse/test/BrowseControllerSpec.js @@ -40,6 +40,7 @@ define( mockUrlService, mockDomainObject, mockNextObject, + testDefaultRoot, controller; function mockPromise(value) { @@ -50,7 +51,21 @@ define( }; } + function instantiateController() { + controller = new BrowseController( + mockScope, + mockRoute, + mockLocation, + mockObjectService, + mockNavigationService, + mockUrlService, + testDefaultRoot + ); + } + beforeEach(function () { + testDefaultRoot = "some-root-level-domain-object"; + mockScope = jasmine.createSpyObj( "$scope", [ "$on", "$watch" ] @@ -101,41 +116,28 @@ define( ])); mockNextObject.useCapability.andReturn(undefined); mockNextObject.getId.andReturn("next"); - mockDomainObject.getId.andReturn("mine"); + mockDomainObject.getId.andReturn(testDefaultRoot); - controller = new BrowseController( - mockScope, - mockRoute, - mockLocation, - mockObjectService, - mockNavigationService, - mockUrlService - ); + instantiateController(); }); it("uses composition to set the navigated object, if there is none", function () { - controller = new BrowseController( - mockScope, - mockRoute, - mockLocation, - mockObjectService, - mockNavigationService, - mockUrlService - ); + instantiateController(); + expect(mockNavigationService.setNavigation) + .toHaveBeenCalledWith(mockDomainObject); + }); + + it("navigates to a root-level object, even when default path is not found", function () { + mockDomainObject.getId + .andReturn("something-other-than-the-" + testDefaultRoot); + instantiateController(); expect(mockNavigationService.setNavigation) .toHaveBeenCalledWith(mockDomainObject); }); it("does not try to override navigation", function () { mockNavigationService.getNavigation.andReturn(mockDomainObject); - controller = new BrowseController( - mockScope, - mockRoute, - mockLocation, - mockObjectService, - mockNavigationService, - mockUrlService - ); + instantiateController(); expect(mockScope.navigatedObject).toBe(mockDomainObject); }); @@ -162,14 +164,8 @@ define( }); it("uses route parameters to choose initially-navigated object", function () { - mockRoute.current.params.ids = "mine/next"; - controller = new BrowseController( - mockScope, - mockRoute, - mockLocation, - mockObjectService, - mockNavigationService - ); + mockRoute.current.params.ids = testDefaultRoot + "/next"; + instantiateController(); expect(mockScope.navigatedObject).toBe(mockNextObject); expect(mockNavigationService.setNavigation) .toHaveBeenCalledWith(mockNextObject); @@ -179,14 +175,8 @@ define( // Idea here is that if we get a bad path of IDs, // browse controller should traverse down it until // it hits an invalid ID. - mockRoute.current.params.ids = "mine/junk"; - controller = new BrowseController( - mockScope, - mockRoute, - mockLocation, - mockObjectService, - mockNavigationService - ); + mockRoute.current.params.ids = testDefaultRoot + "/junk"; + instantiateController(); expect(mockScope.navigatedObject).toBe(mockDomainObject); expect(mockNavigationService.setNavigation) .toHaveBeenCalledWith(mockDomainObject); @@ -196,14 +186,8 @@ define( // Idea here is that if we get a path which passes // through an object without a composition, browse controller // should stop at it since remaining IDs cannot be loaded. - mockRoute.current.params.ids = "mine/next/junk"; - controller = new BrowseController( - mockScope, - mockRoute, - mockLocation, - mockObjectService, - mockNavigationService - ); + mockRoute.current.params.ids = testDefaultRoot + "/next/junk"; + instantiateController(); expect(mockScope.navigatedObject).toBe(mockNextObject); expect(mockNavigationService.setNavigation) .toHaveBeenCalledWith(mockNextObject);