Compare commits
	
		
			3 Commits
		
	
	
		
			feature/is
			...
			open627_re
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					a515ccfb61 | ||
| 
						 | 
					560897fe81 | ||
| 
						 | 
					e1d20e7275 | 
@@ -80,7 +80,6 @@ define([
 | 
			
		||||
                        "$scope",
 | 
			
		||||
                        "$route",
 | 
			
		||||
                        "$location",
 | 
			
		||||
                        "$q",
 | 
			
		||||
                        "objectService",
 | 
			
		||||
                        "navigationService",
 | 
			
		||||
                        "urlService"
 | 
			
		||||
@@ -202,6 +201,10 @@ define([
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "inspector-region",
 | 
			
		||||
                    "templateUrl": "templates/browse/inspector-region.html"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "view-region",
 | 
			
		||||
                    "templateUrl": "templates/view-region.html"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "services": [
 | 
			
		||||
 
 | 
			
		||||
@@ -47,11 +47,6 @@
 | 
			
		||||
        <div class="holder l-flex-col flex-elem grows l-object-wrapper-inner">
 | 
			
		||||
            <!-- Toolbar and Save/Cancel buttons -->
 | 
			
		||||
            <div class="l-edit-controls flex-elem l-flex-row flex-align-end">
 | 
			
		||||
                <mct-toolbar name="mctToolbar"
 | 
			
		||||
                             structure="toolbar.structure"
 | 
			
		||||
                             ng-model="toolbar.state"
 | 
			
		||||
                             class="flex-elem grows">
 | 
			
		||||
                </mct-toolbar>
 | 
			
		||||
                <mct-representation key="'edit-action-buttons'"
 | 
			
		||||
                                    mct-object="domainObject"
 | 
			
		||||
                                    class='flex-elem conclude-editing'>
 | 
			
		||||
 
 | 
			
		||||
@@ -63,7 +63,7 @@
 | 
			
		||||
                    <mct-split-pane class='l-object-and-inspector contents abs' anchor='right'>
 | 
			
		||||
                        <div class='split-pane-component t-object pane primary-pane left'>
 | 
			
		||||
                            <mct-representation mct-object="navigatedObject"
 | 
			
		||||
                                                key="'browse-object'"
 | 
			
		||||
                                                key="'view-region'"
 | 
			
		||||
                                                class="abs holder holder-object">
 | 
			
		||||
                            </mct-representation>
 | 
			
		||||
                        </div>
 | 
			
		||||
@@ -87,4 +87,3 @@
 | 
			
		||||
    </div>
 | 
			
		||||
    <mct-include key="'bottombar'"></mct-include>
 | 
			
		||||
</div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,14 +19,12 @@
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<div content="jquery-wrapper"
 | 
			
		||||
     class="abs holder-all edit-mode"
 | 
			
		||||
     ng-controller="EditController as editMode"
 | 
			
		||||
     mct-before-unload="editMode.getUnloadWarning()">
 | 
			
		||||
 | 
			
		||||
    <mct-representation key="'edit-object'" mct-object="editMode.navigatedObject()">
 | 
			
		||||
    </mct-representation>
 | 
			
		||||
 | 
			
		||||
    <mct-include key="'bottombar'"></mct-include>
 | 
			
		||||
 | 
			
		||||
</div>
 | 
			
		||||
<div ng-controller="RegionController as regionController">
 | 
			
		||||
    <div ng-repeat="part in regions.view.parts">
 | 
			
		||||
        <mct-representation
 | 
			
		||||
                key="part.content.key"
 | 
			
		||||
                mct-object="domainObject"
 | 
			
		||||
                ng-model="ngModel">
 | 
			
		||||
        </mct-representation>
 | 
			
		||||
    </div>
 | 
			
		||||
</div><!--/ PaneController -->
 | 
			
		||||
@@ -27,10 +27,9 @@
 | 
			
		||||
 */
 | 
			
		||||
define(
 | 
			
		||||
    [
 | 
			
		||||
        '../../../representation/src/gestures/GestureConstants',
 | 
			
		||||
        '../../edit/src/objects/EditableDomainObject'
 | 
			
		||||
        '../../../representation/src/gestures/GestureConstants'
 | 
			
		||||
    ],
 | 
			
		||||
    function (GestureConstants, EditableDomainObject) {
 | 
			
		||||
    function (GestureConstants) {
 | 
			
		||||
        "use strict";
 | 
			
		||||
 | 
			
		||||
        var ROOT_ID = "ROOT",
 | 
			
		||||
@@ -47,18 +46,11 @@ define(
 | 
			
		||||
         * @memberof platform/commonUI/browse
 | 
			
		||||
         * @constructor
 | 
			
		||||
         */
 | 
			
		||||
        function BrowseController($scope, $route, $location, $q, objectService, navigationService, urlService) {
 | 
			
		||||
        function BrowseController($scope, $route, $location, objectService, navigationService, urlService) {
 | 
			
		||||
            var path = [ROOT_ID].concat(
 | 
			
		||||
                ($route.current.params.ids || DEFAULT_PATH).split("/")
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            function isDirty(){
 | 
			
		||||
                var editorCapability = $scope.navigatedObject &&
 | 
			
		||||
                        $scope.navigatedObject.getCapability("editor"),
 | 
			
		||||
                    hasChanges = editorCapability && editorCapability.dirty();
 | 
			
		||||
                return hasChanges;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            function updateRoute(domainObject) {
 | 
			
		||||
                var priorRoute = $route.current,
 | 
			
		||||
                    // Act as if params HADN'T changed to avoid page reload
 | 
			
		||||
@@ -75,9 +67,7 @@ define(
 | 
			
		||||
                // urlService.urlForLocation used to adjust current
 | 
			
		||||
                // path to new, addressed, path based on
 | 
			
		||||
                // domainObject
 | 
			
		||||
                $location.path(urlService.urlForLocation("browse",
 | 
			
		||||
                    domainObject.hasCapability('editor') ?
 | 
			
		||||
                        domainObject.getOriginalObject() : domainObject));
 | 
			
		||||
                $location.path(urlService.urlForLocation("browse", domainObject));
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -89,17 +79,15 @@ define(
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (isDirty() && !confirm(CONFIRM_MSG)) {
 | 
			
		||||
                    $scope.treeModel.selectedObject = $scope.navigatedObject;
 | 
			
		||||
                    navigationService.setNavigation($scope.navigatedObject);
 | 
			
		||||
                } else {
 | 
			
		||||
                    if ($scope.navigatedObject && $scope.navigatedObject.hasCapability("editor")){
 | 
			
		||||
                        $scope.navigatedObject.getCapability("editor").cancel();
 | 
			
		||||
                    }
 | 
			
		||||
                if (navigationService.setNavigation(domainObject)) {
 | 
			
		||||
                    $scope.navigatedObject = domainObject;
 | 
			
		||||
                    $scope.treeModel.selectedObject = domainObject;
 | 
			
		||||
                    navigationService.setNavigation(domainObject);
 | 
			
		||||
                    updateRoute(domainObject);
 | 
			
		||||
                } else {
 | 
			
		||||
                    //If navigation was unsuccessful (ie. blocked), reset
 | 
			
		||||
                    // the selected object in the tree to the currently
 | 
			
		||||
                    // navigated object
 | 
			
		||||
                    $scope.treeModel.selectedObject = $scope.navigatedObject ;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
@@ -170,18 +158,13 @@ define(
 | 
			
		||||
                selectedObject: navigationService.getNavigation()
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            $scope.beforeUnloadWarning = function() {
 | 
			
		||||
                return isDirty() ?
 | 
			
		||||
                    "Unsaved changes will be lost if you leave this page." :
 | 
			
		||||
                    undefined;
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            // Listen for changes in navigation state.
 | 
			
		||||
            navigationService.addListener(setNavigation);
 | 
			
		||||
 | 
			
		||||
            // Also listen for changes which come from the tree
 | 
			
		||||
            // Also listen for changes which come from the tree. Changes in
 | 
			
		||||
            // the tree will trigger a change in browse navigation state.
 | 
			
		||||
            $scope.$watch("treeModel.selectedObject", setNavigation);
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            // Clean up when the scope is destroyed
 | 
			
		||||
            $scope.$on("$destroy", function () {
 | 
			
		||||
                navigationService.removeListener(setNavigation);
 | 
			
		||||
@@ -191,4 +174,3 @@ define(
 | 
			
		||||
        return BrowseController;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -22,11 +22,8 @@
 | 
			
		||||
/*global define,Promise*/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    [
 | 
			
		||||
        '../../../representation/src/gestures/GestureConstants',
 | 
			
		||||
        '../../edit/src/objects/EditableDomainObject'
 | 
			
		||||
    ],
 | 
			
		||||
    function (GestureConstants, EditableDomainObject) {
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
        "use strict";
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
@@ -57,10 +54,9 @@ define(
 | 
			
		||||
 | 
			
		||||
            function updateQueryParam(viewKey) {
 | 
			
		||||
                var unlisten,
 | 
			
		||||
                    priorRoute = $route.current,
 | 
			
		||||
                    isEditMode = $scope.domainObject && $scope.domainObject.hasCapability('editor');
 | 
			
		||||
                    priorRoute = $route.current;
 | 
			
		||||
 | 
			
		||||
                if (viewKey && !isEditMode) {
 | 
			
		||||
                if (viewKey) {
 | 
			
		||||
                    $location.search('view', viewKey);
 | 
			
		||||
                    unlisten = $scope.$on('$locationChangeSuccess', function () {
 | 
			
		||||
                        // Checks path to make sure /browse/ is at front
 | 
			
		||||
@@ -76,10 +72,6 @@ define(
 | 
			
		||||
            $scope.$watch('domainObject', setViewForDomainObject);
 | 
			
		||||
            $scope.$watch('representation.selected.key', updateQueryParam);
 | 
			
		||||
 | 
			
		||||
            $scope.cancelEditing = function() {
 | 
			
		||||
                navigationService.setNavigation($scope.domainObject.getDomainObject());
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            $scope.doAction = function (action){
 | 
			
		||||
                return $scope[action] && $scope[action]();
 | 
			
		||||
            };
 | 
			
		||||
@@ -89,4 +81,3 @@ define(
 | 
			
		||||
        return BrowseObjectController;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,9 +23,10 @@
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    [
 | 
			
		||||
        './InspectorRegion'
 | 
			
		||||
        './InspectorRegion',
 | 
			
		||||
        './ViewRegion'
 | 
			
		||||
    ],
 | 
			
		||||
    function (InspectorRegion) {
 | 
			
		||||
    function (InspectorRegion, ViewRegion) {
 | 
			
		||||
        "use strict";
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
@@ -53,6 +54,7 @@ define(
 | 
			
		||||
            var regions = type.getDefinition().regions || {};
 | 
			
		||||
 | 
			
		||||
            regions.inspector = regions.inspector || new InspectorRegion();
 | 
			
		||||
            regions.view = regions.view || new ViewRegion();
 | 
			
		||||
 | 
			
		||||
            type.getDefinition().regions = regions;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										73
									
								
								platform/commonUI/browse/src/ViewRegion.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										73
									
								
								platform/commonUI/browse/src/ViewRegion.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,73 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT Web, Copyright (c) 2014-2015, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT Web is licensed under the Apache License, Version 2.0 (the
 | 
			
		||||
 * "License"); you may not use this file except in compliance with the License.
 | 
			
		||||
 * You may obtain a copy of the License at
 | 
			
		||||
 * http://www.apache.org/licenses/LICENSE-2.0.
 | 
			
		||||
 *
 | 
			
		||||
 * Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 | 
			
		||||
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 | 
			
		||||
 * License for the specific language governing permissions and limitations
 | 
			
		||||
 * under the License.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT Web includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
/*global define,window*/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    [
 | 
			
		||||
        '../../regions/src/Region'
 | 
			
		||||
    ],
 | 
			
		||||
    function (Region) {
 | 
			
		||||
        "use strict";
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Defines the default View region. Captured in a class to
 | 
			
		||||
         * allow for modular extension and customization of regions based on
 | 
			
		||||
         * the typical case.
 | 
			
		||||
         * @memberOf platform/commonUI/regions
 | 
			
		||||
         * @constructor
 | 
			
		||||
         */
 | 
			
		||||
        function ViewRegion() {
 | 
			
		||||
            Region.call(this);
 | 
			
		||||
 | 
			
		||||
            this.buildRegion();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ViewRegion.prototype = Object.create(Region.prototype);
 | 
			
		||||
        ViewRegion.prototype.constructor = Region;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @private
 | 
			
		||||
         */
 | 
			
		||||
        ViewRegion.prototype.buildRegion = function() {
 | 
			
		||||
            var browseViewPart = {
 | 
			
		||||
                    name: 'browse-view',
 | 
			
		||||
                    title: 'Browse Object View',
 | 
			
		||||
                    modes: ['browse'],
 | 
			
		||||
                    content: {
 | 
			
		||||
                        key: 'browse-object'
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                editViewPart = {
 | 
			
		||||
                    name: 'edit-view',
 | 
			
		||||
                    title: 'Edit Object View',
 | 
			
		||||
                    modes: ['edit'],
 | 
			
		||||
                    content: {
 | 
			
		||||
                        key: 'edit-object'
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
            this.addPart(browseViewPart);
 | 
			
		||||
            this.addPart(editViewPart);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return ViewRegion;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
@@ -37,7 +37,7 @@ define(
 | 
			
		||||
         */
 | 
			
		||||
        function NavigationService() {
 | 
			
		||||
            this.navigated = undefined;
 | 
			
		||||
            this.callbacks = [];
 | 
			
		||||
            this.callbacks = {};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
@@ -50,26 +50,48 @@ define(
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Set the current navigation state. This will invoke listeners.
 | 
			
		||||
         * Changing the navigation state will be blocked if any of the
 | 
			
		||||
         * 'before' navigation state change listeners return 'false'.
 | 
			
		||||
         * @param {DomainObject} domainObject the domain object to navigate to
 | 
			
		||||
         */
 | 
			
		||||
        NavigationService.prototype.setNavigation = function (value) {
 | 
			
		||||
            var canNavigate = true;
 | 
			
		||||
            if (this.navigated !== value) {
 | 
			
		||||
                this.navigated = value;
 | 
			
		||||
                this.callbacks.forEach(function (callback) {
 | 
			
		||||
                    callback(value);
 | 
			
		||||
                });
 | 
			
		||||
                canNavigate = (this.callbacks.before || [])
 | 
			
		||||
                    .reduce(function (previous, callback) {
 | 
			
		||||
                        //Check whether the callback returned a value of
 | 
			
		||||
                        // 'false' indicating that navigation should not
 | 
			
		||||
                        // continue. All other return values will allow
 | 
			
		||||
                        // navigation to continue
 | 
			
		||||
                        return (callback(value)!==false) && previous;
 | 
			
		||||
                    }, true);
 | 
			
		||||
                if (canNavigate) {
 | 
			
		||||
                    this.navigated = value;
 | 
			
		||||
                    (this.callbacks.after || []).forEach(function (callback) {
 | 
			
		||||
                        callback(value);
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return canNavigate;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Listen for changes in navigation. The passed callback will
 | 
			
		||||
         * be invoked with the new domain object of navigation when
 | 
			
		||||
         * this changes.
 | 
			
		||||
         * this changes. Callbacks can be registered to listen to pre or
 | 
			
		||||
         * post-navigation events. The event to listen to is specified using
 | 
			
		||||
         * the event parameter. In the case of pre-navigation events
 | 
			
		||||
         * returning a false value will prevent the navigation event from
 | 
			
		||||
         * going ahead.
 | 
			
		||||
         * @param {function} callback the callback to invoke when
 | 
			
		||||
         *        navigation state changes
 | 
			
		||||
         * @param {string} [event=after] the navigation event to listen to.
 | 
			
		||||
         * One of 'before' or 'after'.
 | 
			
		||||
         */
 | 
			
		||||
        NavigationService.prototype.addListener = function (callback) {
 | 
			
		||||
            this.callbacks.push(callback);
 | 
			
		||||
        NavigationService.prototype.addListener = function (callback, event) {
 | 
			
		||||
            event = event || 'after';
 | 
			
		||||
            this.callbacks[event] = this.callbacks[event] || [];
 | 
			
		||||
            this.callbacks[event].push(callback);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
@@ -77,9 +99,12 @@ define(
 | 
			
		||||
         * @param {function} callback the callback which should
 | 
			
		||||
         *        no longer be invoked when navigation state
 | 
			
		||||
         *        changes
 | 
			
		||||
         * @param {string} [event=after] the navigation event that the
 | 
			
		||||
         * callback is registered to. One of 'before' or 'after'.
 | 
			
		||||
         */
 | 
			
		||||
        NavigationService.prototype.removeListener = function (callback) {
 | 
			
		||||
            this.callbacks = this.callbacks.filter(function (cb) {
 | 
			
		||||
        NavigationService.prototype.removeListener = function (callback, event) {
 | 
			
		||||
            event = event || 'after';
 | 
			
		||||
            this.callbacks[event] = this.callbacks[event].filter(function (cb) {
 | 
			
		||||
                return cb !== callback;
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
 
 | 
			
		||||
@@ -29,8 +29,7 @@ define(
 | 
			
		||||
    function (BrowseController) {
 | 
			
		||||
        "use strict";
 | 
			
		||||
 | 
			
		||||
        //TODO: Disabled for NEM Beta
 | 
			
		||||
        xdescribe("The browse controller", function () {
 | 
			
		||||
        describe("The browse controller", function () {
 | 
			
		||||
            var mockScope,
 | 
			
		||||
                mockRoute,
 | 
			
		||||
                mockLocation,
 | 
			
		||||
@@ -230,7 +229,10 @@ define(
 | 
			
		||||
                // prior to setting $route.current
 | 
			
		||||
                mockLocation.path.andReturn("/browse/");
 | 
			
		||||
 | 
			
		||||
                mockNavigationService.setNavigation.andReturn(true);
 | 
			
		||||
 | 
			
		||||
                // Exercise the Angular workaround
 | 
			
		||||
                mockNavigationService.addListener.mostRecentCall.args[0]();
 | 
			
		||||
                mockScope.$on.mostRecentCall.args[1]();
 | 
			
		||||
                expect(mockUnlisten).toHaveBeenCalled();
 | 
			
		||||
 | 
			
		||||
@@ -241,6 +243,32 @@ define(
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("after successful navigation event sets the selected tree " +
 | 
			
		||||
                "object", function () {
 | 
			
		||||
                mockScope.navigatedObject = mockDomainObject;
 | 
			
		||||
                mockNavigationService.setNavigation.andReturn(true);
 | 
			
		||||
 | 
			
		||||
                //Simulate a change in selected tree object
 | 
			
		||||
                mockScope.treeModel = {selectedObject: mockDomainObject};
 | 
			
		||||
                mockScope.$watch.mostRecentCall.args[1](mockNextObject);
 | 
			
		||||
 | 
			
		||||
                expect(mockScope.treeModel.selectedObject).toBe(mockNextObject);
 | 
			
		||||
                expect(mockScope.treeModel.selectedObject).not.toBe(mockDomainObject);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("after failed navigation event resets the selected tree" +
 | 
			
		||||
                " object", function () {
 | 
			
		||||
                mockScope.navigatedObject = mockDomainObject;
 | 
			
		||||
                mockNavigationService.setNavigation.andReturn(false);
 | 
			
		||||
 | 
			
		||||
                //Simulate a change in selected tree object
 | 
			
		||||
                mockScope.treeModel = {selectedObject: mockDomainObject};
 | 
			
		||||
                mockScope.$watch.mostRecentCall.args[1](mockNextObject);
 | 
			
		||||
 | 
			
		||||
                expect(mockScope.treeModel.selectedObject).not.toBe(mockNextObject);
 | 
			
		||||
                expect(mockScope.treeModel.selectedObject).toBe(mockDomainObject);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 
 | 
			
		||||
@@ -84,6 +84,24 @@ define(
 | 
			
		||||
                expect(callback).not.toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("adds listeners to the 'after' state by default", function(){
 | 
			
		||||
                expect(navigationService.callbacks.after).toBeUndefined();
 | 
			
		||||
                navigationService.addListener(function(){});
 | 
			
		||||
                expect(navigationService.callbacks.after).toBeDefined();
 | 
			
		||||
                expect(navigationService.callbacks.after.length).toBe(1);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("allows navigationService events to be prevented", function(){
 | 
			
		||||
                var callback = jasmine.createSpy("callback"),
 | 
			
		||||
                    navigationResult;
 | 
			
		||||
                callback.andReturn(false);
 | 
			
		||||
                navigationService.addListener(callback, "before");
 | 
			
		||||
                navigationResult = navigationService.setNavigation({});
 | 
			
		||||
                expect(callback).toHaveBeenCalled();
 | 
			
		||||
                expect(navigationResult).toBe(false);
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
);
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,10 @@
 | 
			
		||||
/*global define*/
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    "./src/controllers/EditController",
 | 
			
		||||
    "./src/controllers/EditActionController",
 | 
			
		||||
    "./src/controllers/EditPanesController",
 | 
			
		||||
    "./src/controllers/ElementsController",
 | 
			
		||||
    "./src/controllers/EditObjectController",
 | 
			
		||||
    "./src/directives/MCTBeforeUnload",
 | 
			
		||||
    "./src/actions/LinkAction",
 | 
			
		||||
    "./src/actions/EditAction",
 | 
			
		||||
@@ -38,10 +38,10 @@ define([
 | 
			
		||||
    "./src/representers/EditToolbarRepresenter",
 | 
			
		||||
    'legacyRegistry'
 | 
			
		||||
], function (
 | 
			
		||||
    EditController,
 | 
			
		||||
    EditActionController,
 | 
			
		||||
    EditPanesController,
 | 
			
		||||
    ElementsController,
 | 
			
		||||
    EditObjectController,
 | 
			
		||||
    MCTBeforeUnload,
 | 
			
		||||
    LinkAction,
 | 
			
		||||
    EditAction,
 | 
			
		||||
@@ -58,22 +58,7 @@ define([
 | 
			
		||||
 | 
			
		||||
    legacyRegistry.register("platform/commonUI/edit", {
 | 
			
		||||
        "extensions": {
 | 
			
		||||
            "routes": [
 | 
			
		||||
                {
 | 
			
		||||
                    "when": "/edit",
 | 
			
		||||
                    "templateUrl": "templates/edit.html"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "controllers": [
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "EditController",
 | 
			
		||||
                    "implementation": EditController,
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                        "$scope",
 | 
			
		||||
                        "$q",
 | 
			
		||||
                        "navigationService"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "EditActionController",
 | 
			
		||||
                    "implementation": EditActionController,
 | 
			
		||||
@@ -94,6 +79,14 @@ define([
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                        "$scope"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "EditObjectController",
 | 
			
		||||
                    "implementation": EditObjectController,
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                        "$scope",
 | 
			
		||||
                        "$location"
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "directives": [
 | 
			
		||||
@@ -101,7 +94,8 @@ define([
 | 
			
		||||
                    "key": "mctBeforeUnload",
 | 
			
		||||
                    "implementation": MCTBeforeUnload,
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                        "$window"
 | 
			
		||||
                        "$window",
 | 
			
		||||
                        "navigationService"
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
@@ -197,6 +191,9 @@ define([
 | 
			
		||||
                    "templateUrl": "templates/edit-object.html",
 | 
			
		||||
                    "uses": [
 | 
			
		||||
                        "view"
 | 
			
		||||
                    ],
 | 
			
		||||
                    "gestures": [
 | 
			
		||||
                        "drop"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
 
 | 
			
		||||
@@ -19,50 +19,51 @@
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<mct-representation key="'topbar-edit'"
 | 
			
		||||
                    mct-object="domainObject"
 | 
			
		||||
                    ng-model="representation">
 | 
			
		||||
</mct-representation>
 | 
			
		||||
<div class="holder edit-area abs">
 | 
			
		||||
    <mct-split-pane class='contents abs' anchor='right'>
 | 
			
		||||
        <div class='split-pane-component pane left edit-main'>
 | 
			
		||||
            <mct-toolbar name="mctToolbar"
 | 
			
		||||
                         structure="toolbar.structure"
 | 
			
		||||
                         ng-model="toolbar.state">
 | 
			
		||||
            </mct-toolbar>
 | 
			
		||||
            <mct-representation key="representation.selected.key"
 | 
			
		||||
                                toolbar="toolbar"
 | 
			
		||||
                                mct-object="representation.selected.key && domainObject"
 | 
			
		||||
                                class="holder abs object-holder work-area">
 | 
			
		||||
<div class="abs l-flex-col" ng-controller="EditObjectController as EditObjectController">
 | 
			
		||||
    <div mct-before-unload="EditObjectController.getUnloadWarning()"
 | 
			
		||||
         class="holder flex-elem l-flex-row object-browse-bar ">
 | 
			
		||||
        <div class="items-select left flex-elem l-flex-row grows">
 | 
			
		||||
            <mct-representation key="'back-arrow'"
 | 
			
		||||
                                mct-object="domainObject"
 | 
			
		||||
                                class="flex-elem l-back"></mct-representation>
 | 
			
		||||
            <mct-representation key="'object-header'"
 | 
			
		||||
                                mct-object="domainObject"
 | 
			
		||||
                                class="l-flex-row flex-elem grows object-header">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
        </div>
 | 
			
		||||
        <mct-splitter></mct-splitter>
 | 
			
		||||
        <div
 | 
			
		||||
            class='split-pane-component pane right edit-objects menus-to-left'
 | 
			
		||||
            ng-controller='EditPanesController as editPanes'
 | 
			
		||||
            >
 | 
			
		||||
            <mct-split-pane class='contents abs' anchor='bottom'>
 | 
			
		||||
                <div
 | 
			
		||||
                    class="abs pane top accordion"
 | 
			
		||||
                    ng-controller="ToggleController as toggle"
 | 
			
		||||
                    >
 | 
			
		||||
                    <mct-container key="accordion" label="Library">
 | 
			
		||||
                        <mct-representation key="'tree'"
 | 
			
		||||
                                            mct-object="editPanes.getRoot()">
 | 
			
		||||
                        </mct-representation>
 | 
			
		||||
                    </mct-container>
 | 
			
		||||
                </div>
 | 
			
		||||
                <mct-splitter></mct-splitter>
 | 
			
		||||
                <div
 | 
			
		||||
                    class="abs pane bottom accordion"
 | 
			
		||||
                    ng-controller="ToggleController as toggle"
 | 
			
		||||
                    >
 | 
			
		||||
                    <mct-container key="accordion" label="Elements">
 | 
			
		||||
                        <mct-representation key="'edit-elements'" mct-object="domainObject">
 | 
			
		||||
                        </mct-representation>
 | 
			
		||||
                    </mct-container>
 | 
			
		||||
                </div>
 | 
			
		||||
            </mct-split-pane>
 | 
			
		||||
        <div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
 | 
			
		||||
            <mct-representation key="'switcher'"
 | 
			
		||||
                                mct-object="domainObject"
 | 
			
		||||
                                ng-model="representation">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
            <!-- Temporarily, on mobile, the action buttons are hidden-->
 | 
			
		||||
            <mct-representation key="'action-group'"
 | 
			
		||||
                                mct-object="domainObject"
 | 
			
		||||
                                parameters="{ category: 'view-control' }"
 | 
			
		||||
                                class="mobile-hide">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
        </div>
 | 
			
		||||
    </mct-split-pane>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="holder l-flex-col flex-elem grows l-object-wrapper">
 | 
			
		||||
        <div class="holder l-flex-col flex-elem grows l-object-wrapper-inner">
 | 
			
		||||
            <!-- Toolbar and Save/Cancel buttons -->
 | 
			
		||||
            <div class="l-edit-controls flex-elem l-flex-row flex-align-end">
 | 
			
		||||
                <mct-toolbar name="mctToolbar"
 | 
			
		||||
                             structure="toolbar.structure"
 | 
			
		||||
                             ng-model="toolbar.state"
 | 
			
		||||
                             class="flex-elem grows">
 | 
			
		||||
                </mct-toolbar>
 | 
			
		||||
                <mct-representation key="'edit-action-buttons'"
 | 
			
		||||
                                    mct-object="domainObject"
 | 
			
		||||
                                    class='flex-elem conclude-editing'>
 | 
			
		||||
                </mct-representation>
 | 
			
		||||
 | 
			
		||||
            </div>
 | 
			
		||||
            <mct-representation key="representation.selected.key"
 | 
			
		||||
                                mct-object="representation.selected.key && domainObject"
 | 
			
		||||
                                class="abs flex-elem grows object-holder-main scroll"
 | 
			
		||||
                                toolbar="toolbar">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
        </div><!--/ l-object-wrapper-inner -->
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -72,13 +72,26 @@ define(
 | 
			
		||||
         * Enter edit mode.
 | 
			
		||||
         */
 | 
			
		||||
        EditAction.prototype.perform = function () {
 | 
			
		||||
            var editableObject;
 | 
			
		||||
            var self = this;
 | 
			
		||||
            if (!this.domainObject.hasCapability("editor")) {
 | 
			
		||||
                editableObject = new EditableDomainObject(this.domainObject, this.$q);
 | 
			
		||||
                editableObject.getCapability('status').set('editing', true);
 | 
			
		||||
                this.navigationService.setNavigation(editableObject);
 | 
			
		||||
                //TODO: This is only necessary because the drop gesture is
 | 
			
		||||
                // wrapping the object itself, need to refactor this later.
 | 
			
		||||
                // All responsibility for switching into edit mode should be
 | 
			
		||||
                // in the edit action, and not duplicated in the gesture
 | 
			
		||||
                this.domainObject = new EditableDomainObject(this.domainObject, this.$q);
 | 
			
		||||
            }
 | 
			
		||||
            //this.$location.path("/edit");
 | 
			
		||||
            this.navigationService.setNavigation(this.domainObject);
 | 
			
		||||
            this.domainObject.getCapability('status').set('editing', true);
 | 
			
		||||
 | 
			
		||||
            //Register a listener to automatically cancel this edit action
 | 
			
		||||
            //if the user navigates away from this object.
 | 
			
		||||
            function cancelEditing(navigatedTo){
 | 
			
		||||
                if (!navigatedTo || navigatedTo.getId() !== self.domainObject.getId()) {
 | 
			
		||||
                    self.domainObject.getCapability('editor').cancel();
 | 
			
		||||
                    self.navigationService.removeListener(cancelEditing);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            this.navigationService.addListener(cancelEditing);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
 
 | 
			
		||||
@@ -26,41 +26,44 @@
 | 
			
		||||
 * @namespace platform/commonUI/edit
 | 
			
		||||
 */
 | 
			
		||||
define(
 | 
			
		||||
    ["../objects/EditableDomainObject"],
 | 
			
		||||
    function (EditableDomainObject) {
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
        "use strict";
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Controller which is responsible for populating the scope for
 | 
			
		||||
         * Edit mode; introduces an editable version of the currently
 | 
			
		||||
         * navigated domain object into the scope.
 | 
			
		||||
         * Edit mode
 | 
			
		||||
         * @memberof platform/commonUI/edit
 | 
			
		||||
         * @constructor
 | 
			
		||||
         */
 | 
			
		||||
        function EditController($scope, $q, navigationService) {
 | 
			
		||||
            var self = this;
 | 
			
		||||
        function EditObjectController($scope, $location) {
 | 
			
		||||
            this.scope = $scope;
 | 
			
		||||
 | 
			
		||||
            function setNavigation(domainObject) {
 | 
			
		||||
                // Wrap the domain object such that all mutation is
 | 
			
		||||
                // confined to edit mode (until Save)
 | 
			
		||||
                self.navigatedDomainObject =
 | 
			
		||||
                    domainObject && new EditableDomainObject(domainObject, $q);
 | 
			
		||||
            var navigatedObject;
 | 
			
		||||
            function setViewForDomainObject(domainObject) {
 | 
			
		||||
 | 
			
		||||
                var locationViewKey = $location.search().view;
 | 
			
		||||
 | 
			
		||||
                function selectViewIfMatching(view) {
 | 
			
		||||
                    if (view.key === locationViewKey) {
 | 
			
		||||
                        $scope.representation = $scope.representation || {};
 | 
			
		||||
                        $scope.representation.selected = view;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (locationViewKey) {
 | 
			
		||||
                    ((domainObject && domainObject.useCapability('view')) || [])
 | 
			
		||||
                        .forEach(selectViewIfMatching);
 | 
			
		||||
                }
 | 
			
		||||
                navigatedObject = domainObject;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            setNavigation(navigationService.getNavigation());
 | 
			
		||||
            navigationService.addListener(setNavigation);
 | 
			
		||||
            $scope.$on("$destroy", function () {
 | 
			
		||||
                navigationService.removeListener(setNavigation);
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
            $scope.$watch('domainObject', setViewForDomainObject);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Get the domain object which is navigated-to.
 | 
			
		||||
         * @returns {DomainObject} the domain object that is navigated-to
 | 
			
		||||
         */
 | 
			
		||||
        EditController.prototype.navigatedObject = function () {
 | 
			
		||||
            return this.navigatedDomainObject;
 | 
			
		||||
        };
 | 
			
		||||
            $scope.doAction = function (action){
 | 
			
		||||
                return $scope[action] && $scope[action]();
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Get the warning to show if the user attempts to navigate
 | 
			
		||||
@@ -68,17 +71,20 @@ define(
 | 
			
		||||
         * @returns {string} the warning to show, or undefined if
 | 
			
		||||
         *          there are no unsaved changes
 | 
			
		||||
         */
 | 
			
		||||
        EditController.prototype.getUnloadWarning = function () {
 | 
			
		||||
            var navigatedObject = this.navigatedDomainObject,
 | 
			
		||||
        EditObjectController.prototype.getUnloadWarning = function () {
 | 
			
		||||
            var navigatedObject = this.scope.domainObject,
 | 
			
		||||
                editorCapability = navigatedObject &&
 | 
			
		||||
                    navigatedObject.getCapability("editor"),
 | 
			
		||||
                hasChanges = editorCapability && editorCapability.dirty();
 | 
			
		||||
                statusCapability = navigatedObject &&
 | 
			
		||||
                    navigatedObject.getCapability("status"),
 | 
			
		||||
                hasChanges = statusCapability && statusCapability.get('editing')
 | 
			
		||||
                    && editorCapability && editorCapability.dirty();
 | 
			
		||||
 | 
			
		||||
            return hasChanges ?
 | 
			
		||||
                "Unsaved changes will be lost if you leave this page." :
 | 
			
		||||
                undefined;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return EditController;
 | 
			
		||||
        return EditObjectController;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
@@ -35,7 +35,7 @@ define(
 | 
			
		||||
         * @constructor
 | 
			
		||||
         * @param $window the window
 | 
			
		||||
         */
 | 
			
		||||
        function MCTBeforeUnload($window) {
 | 
			
		||||
        function MCTBeforeUnload($window, navigationService) {
 | 
			
		||||
            var unloads = [],
 | 
			
		||||
                oldBeforeUnload = $window.onbeforeunload;
 | 
			
		||||
 | 
			
		||||
@@ -55,8 +55,23 @@ define(
 | 
			
		||||
                    return scope.$eval(attrs.mctBeforeUnload);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                function shouldAllowNavigation(){
 | 
			
		||||
                    // Get an unload message (if any)
 | 
			
		||||
                    var warning = unload();
 | 
			
		||||
                    // Prompt the user if there's an unload message
 | 
			
		||||
                    return !warning || $window.confirm(warning);
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Show a dialog before allowing a location change
 | 
			
		||||
                function checkNavigationEvent(event) {
 | 
			
		||||
                    // Return a false value to the navigationService to
 | 
			
		||||
                    // indicate that the navigation event should be prevented
 | 
			
		||||
                    return shouldAllowNavigation();
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Stop using this unload expression
 | 
			
		||||
                function removeUnload() {
 | 
			
		||||
                    navigationService.removeListener(checkNavigationEvent, "before");
 | 
			
		||||
                    unloads = unloads.filter(function (callback) {
 | 
			
		||||
                        return callback !== unload;
 | 
			
		||||
                    });
 | 
			
		||||
@@ -67,11 +82,8 @@ define(
 | 
			
		||||
 | 
			
		||||
                // Show a dialog before allowing a location change
 | 
			
		||||
                function checkLocationChange(event) {
 | 
			
		||||
                    // Get an unload message (if any)
 | 
			
		||||
                    var warning = unload();
 | 
			
		||||
                    // Prompt the user if there's an unload message
 | 
			
		||||
                    if (warning && !$window.confirm(warning)) {
 | 
			
		||||
                        // ...and prevent the route change if it was confirmed
 | 
			
		||||
                    if (!shouldAllowNavigation()) {
 | 
			
		||||
                        // Prevent the route change if it was confirmed
 | 
			
		||||
                        event.preventDefault();
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
@@ -90,6 +102,8 @@ define(
 | 
			
		||||
 | 
			
		||||
                // Also handle route changes
 | 
			
		||||
                scope.$on("$locationChangeStart", checkLocationChange);
 | 
			
		||||
 | 
			
		||||
                navigationService.addListener(checkNavigationEvent, "before");
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return {
 | 
			
		||||
 
 | 
			
		||||
@@ -22,89 +22,72 @@
 | 
			
		||||
/*global define,describe,it,expect,beforeEach,jasmine*/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    ["../../src/controllers/EditController"],
 | 
			
		||||
    function (EditController) {
 | 
			
		||||
    ["../../src/controllers/EditObjectController"],
 | 
			
		||||
    function (EditObjectController) {
 | 
			
		||||
        "use strict";
 | 
			
		||||
 | 
			
		||||
        describe("The Edit mode controller", function () {
 | 
			
		||||
            var mockScope,
 | 
			
		||||
                mockQ,
 | 
			
		||||
                mockNavigationService,
 | 
			
		||||
                mockObject,
 | 
			
		||||
                mockType,
 | 
			
		||||
                mockLocation,
 | 
			
		||||
                mockStatusCapability,
 | 
			
		||||
                mockCapabilities,
 | 
			
		||||
                controller;
 | 
			
		||||
 | 
			
		||||
            // Utility function; look for a $watch on scope and fire it
 | 
			
		||||
            function fireWatch(expr, value) {
 | 
			
		||||
                mockScope.$watch.calls.forEach(function (call) {
 | 
			
		||||
                    if (call.args[0] === expr) {
 | 
			
		||||
                        call.args[1](value);
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                mockScope = jasmine.createSpyObj(
 | 
			
		||||
                    "$scope",
 | 
			
		||||
                    [ "$on" ]
 | 
			
		||||
                );
 | 
			
		||||
                mockQ = jasmine.createSpyObj('$q', ['when', 'all']);
 | 
			
		||||
                mockNavigationService = jasmine.createSpyObj(
 | 
			
		||||
                    "navigationService",
 | 
			
		||||
                    [ "getNavigation", "addListener", "removeListener" ]
 | 
			
		||||
                    [ "$on", "$watch" ]
 | 
			
		||||
                );
 | 
			
		||||
                mockObject = jasmine.createSpyObj(
 | 
			
		||||
                    "domainObject",
 | 
			
		||||
                    [ "getId", "getModel", "getCapability", "hasCapability" ]
 | 
			
		||||
                    [ "getId", "getModel", "getCapability", "hasCapability", "useCapability" ]
 | 
			
		||||
                );
 | 
			
		||||
                mockType = jasmine.createSpyObj(
 | 
			
		||||
                    "type",
 | 
			
		||||
                    [ "hasFeature" ]
 | 
			
		||||
                );
 | 
			
		||||
                mockStatusCapability = jasmine.createSpyObj('statusCapability',
 | 
			
		||||
                    ["get"]
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                mockCapabilities = {
 | 
			
		||||
                    "type" : mockType,
 | 
			
		||||
                    "status": mockStatusCapability
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                mockLocation = jasmine.createSpyObj('$location',
 | 
			
		||||
                    ["search"]
 | 
			
		||||
                );
 | 
			
		||||
                mockLocation.search.andReturn({"view": "fixed"});
 | 
			
		||||
 | 
			
		||||
                mockNavigationService.getNavigation.andReturn(mockObject);
 | 
			
		||||
                mockObject.getId.andReturn("test");
 | 
			
		||||
                mockObject.getModel.andReturn({ name: "Test object" });
 | 
			
		||||
                mockObject.getCapability.andCallFake(function (key) {
 | 
			
		||||
                    return key === 'type' && mockType;
 | 
			
		||||
                    return mockCapabilities[key];
 | 
			
		||||
                });
 | 
			
		||||
                mockType.hasFeature.andReturn(true);
 | 
			
		||||
 | 
			
		||||
                controller = new EditController(
 | 
			
		||||
                mockScope.domainObject = mockObject;
 | 
			
		||||
 | 
			
		||||
                controller = new EditObjectController(
 | 
			
		||||
                    mockScope,
 | 
			
		||||
                    mockQ,
 | 
			
		||||
                    mockNavigationService
 | 
			
		||||
                    mockLocation
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("exposes the currently-navigated object", function () {
 | 
			
		||||
                expect(controller.navigatedObject()).toBeDefined();
 | 
			
		||||
                expect(controller.navigatedObject().getId()).toEqual("test");
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("adds an editor capability to the navigated object", function () {
 | 
			
		||||
                // Should provide an editor capability...
 | 
			
		||||
                expect(controller.navigatedObject().getCapability("editor"))
 | 
			
		||||
                    .toBeDefined();
 | 
			
		||||
                // Shouldn't have been the mock capability we provided
 | 
			
		||||
                expect(controller.navigatedObject().getCapability("editor"))
 | 
			
		||||
                    .not.toEqual(mockType);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("detaches its navigation listener when destroyed", function () {
 | 
			
		||||
                var navCallback = mockNavigationService
 | 
			
		||||
                        .addListener.mostRecentCall.args[0];
 | 
			
		||||
 | 
			
		||||
                expect(mockScope.$on).toHaveBeenCalledWith(
 | 
			
		||||
                    "$destroy",
 | 
			
		||||
                    jasmine.any(Function)
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                // Verify precondition
 | 
			
		||||
                expect(mockNavigationService.removeListener)
 | 
			
		||||
                    .not.toHaveBeenCalled();
 | 
			
		||||
 | 
			
		||||
                // Trigger destroy
 | 
			
		||||
                mockScope.$on.mostRecentCall.args[1]();
 | 
			
		||||
 | 
			
		||||
                // Listener should have been removed
 | 
			
		||||
                expect(mockNavigationService.removeListener)
 | 
			
		||||
                    .toHaveBeenCalledWith(navCallback);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("exposes a warning message for unload", function () {
 | 
			
		||||
                var obj = controller.navigatedObject(),
 | 
			
		||||
                var obj = mockObject,
 | 
			
		||||
                    mockEditor = jasmine.createSpyObj('editor', ['dirty']);
 | 
			
		||||
 | 
			
		||||
                // Normally, should be undefined
 | 
			
		||||
@@ -112,14 +95,32 @@ define(
 | 
			
		||||
 | 
			
		||||
                // Override the object's editor capability, make it look
 | 
			
		||||
                // like there are unsaved changes.
 | 
			
		||||
                obj.getCapability = jasmine.createSpy();
 | 
			
		||||
                obj.getCapability.andReturn(mockEditor);
 | 
			
		||||
                mockCapabilities.editor = mockEditor;
 | 
			
		||||
                mockEditor.dirty.andReturn(true);
 | 
			
		||||
                mockStatusCapability.get.andReturn(true);
 | 
			
		||||
 | 
			
		||||
                // Should have some warning message here now
 | 
			
		||||
                expect(controller.getUnloadWarning()).toEqual(jasmine.any(String));
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
            it("sets the active view from query parameters", function () {
 | 
			
		||||
                var testViews = [
 | 
			
		||||
                        { key: 'abc' },
 | 
			
		||||
                        { key: 'def', someKey: 'some value' },
 | 
			
		||||
                        { key: 'xyz' }
 | 
			
		||||
                    ];
 | 
			
		||||
 | 
			
		||||
                mockObject.useCapability.andCallFake(function (c) {
 | 
			
		||||
                    return (c === 'view') && testViews;
 | 
			
		||||
                });
 | 
			
		||||
                mockLocation.search.andReturn({ view: 'def' });
 | 
			
		||||
 | 
			
		||||
                fireWatch('domainObject', mockObject);
 | 
			
		||||
                expect(mockScope.representation.selected)
 | 
			
		||||
                    .toEqual(testViews[1]);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 
 | 
			
		||||
@@ -31,6 +31,7 @@ define(
 | 
			
		||||
                mockScope,
 | 
			
		||||
                testAttrs,
 | 
			
		||||
                mockEvent,
 | 
			
		||||
                mockNavigationService,
 | 
			
		||||
                directive;
 | 
			
		||||
 | 
			
		||||
            function fireListener(eventType, value) {
 | 
			
		||||
@@ -46,7 +47,8 @@ define(
 | 
			
		||||
                mockScope = jasmine.createSpyObj("$scope", ['$eval', '$on']);
 | 
			
		||||
                testAttrs = { mctBeforeUnload: "someExpression" };
 | 
			
		||||
                mockEvent = jasmine.createSpyObj("event", ["preventDefault"]);
 | 
			
		||||
                directive = new MCTBeforeUnload(mockWindow);
 | 
			
		||||
                mockNavigationService = jasmine.createSpyObj("navigationService", ["addListener", "removeListener"]);
 | 
			
		||||
                directive = new MCTBeforeUnload(mockWindow, mockNavigationService);
 | 
			
		||||
                directive.link(mockScope, {}, testAttrs);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
@@ -65,6 +67,10 @@ define(
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("listens for navigation changes", function () {
 | 
			
		||||
                expect(mockNavigationService.addListener).toHaveBeenCalledWith(jasmine.any(Function), "before");
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("listens for its scope's destroy event", function () {
 | 
			
		||||
                expect(mockScope.$on).toHaveBeenCalledWith(
 | 
			
		||||
                    "$destroy",
 | 
			
		||||
@@ -108,9 +114,10 @@ define(
 | 
			
		||||
            it("cleans up listeners when destroyed", function () {
 | 
			
		||||
                fireListener("$destroy", mockEvent);
 | 
			
		||||
                expect(mockWindow.onbeforeunload).toBeUndefined();
 | 
			
		||||
                expect(mockNavigationService.removeListener).toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
);
 | 
			
		||||
 
 | 
			
		||||
@@ -33,6 +33,8 @@ define(
 | 
			
		||||
                testRepresentation,
 | 
			
		||||
                mockDomainObject,
 | 
			
		||||
                mockPersistence,
 | 
			
		||||
                mockStatusCapability,
 | 
			
		||||
                mockCapabilities,
 | 
			
		||||
                representer;
 | 
			
		||||
 | 
			
		||||
            function mockPromise(value) {
 | 
			
		||||
@@ -57,11 +59,20 @@ define(
 | 
			
		||||
                ]);
 | 
			
		||||
                mockPersistence =
 | 
			
		||||
                    jasmine.createSpyObj("persistence", ["persist"]);
 | 
			
		||||
                mockStatusCapability =
 | 
			
		||||
                    jasmine.createSpyObj("statusCapability", ["get", "listen"]);
 | 
			
		||||
 | 
			
		||||
                mockCapabilities = {
 | 
			
		||||
                    "persistence": mockPersistence,
 | 
			
		||||
                    "status": mockStatusCapability
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                mockDomainObject.getModel.andReturn({});
 | 
			
		||||
                mockDomainObject.hasCapability.andReturn(true);
 | 
			
		||||
                mockDomainObject.useCapability.andReturn(true);
 | 
			
		||||
                mockDomainObject.getCapability.andReturn(mockPersistence);
 | 
			
		||||
                mockDomainObject.getCapability.andCallFake(function(capability){
 | 
			
		||||
                    return mockCapabilities[capability];
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                representer = new EditRepresenter(mockQ, mockLog, mockScope);
 | 
			
		||||
                representer.represent(testRepresentation, mockDomainObject);
 | 
			
		||||
@@ -101,4 +112,4 @@ define(
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
);
 | 
			
		||||
 
 | 
			
		||||
@@ -165,16 +165,14 @@ define(
 | 
			
		||||
                    if (shouldCreateVirtualPanel(domainObject, selectedObject)){
 | 
			
		||||
                        editableDomainObject = createVirtualPanel(domainObject, selectedObject);
 | 
			
		||||
                        if (editableDomainObject) {
 | 
			
		||||
                            navigationService.setNavigation(editableDomainObject);
 | 
			
		||||
                            editableDomainObject.getCapability('action').perform('edit');
 | 
			
		||||
                            broadcastDrop(id, event);
 | 
			
		||||
                            editableDomainObject.getCapability('status').set('editing', true);
 | 
			
		||||
                        }
 | 
			
		||||
                    } else {
 | 
			
		||||
                        $q.when(action && action.perform()).then(function (result) {
 | 
			
		||||
                            //Don't go into edit mode for folders
 | 
			
		||||
                            if (domainObjectType!=='folder') {
 | 
			
		||||
                                navigationService.setNavigation(editableDomainObject);
 | 
			
		||||
                                editableDomainObject.getCapability('status').set('editing', true);
 | 
			
		||||
                                editableDomainObject.getCapability('action').perform('edit');
 | 
			
		||||
                            }
 | 
			
		||||
                            broadcastDrop(id, event);
 | 
			
		||||
                        });
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user