mirror of
https://github.com/nasa/openmct.git
synced 2024-12-19 13:17:53 +00:00
Merge pull request #500 from nasa/open480
[New Edit Mode] Adding sub objects to Timelines
This commit is contained in:
commit
b0e4947bf0
@ -34,6 +34,7 @@ define([
|
||||
"./src/windowing/NewTabAction",
|
||||
"./src/windowing/FullscreenAction",
|
||||
"./src/creation/CreateActionProvider",
|
||||
"./src/creation/AddActionProvider",
|
||||
"./src/creation/CreationService",
|
||||
"./src/windowing/WindowTitler",
|
||||
'legacyRegistry'
|
||||
@ -50,6 +51,7 @@ define([
|
||||
NewTabAction,
|
||||
FullscreenAction,
|
||||
CreateActionProvider,
|
||||
AddActionProvider,
|
||||
CreationService,
|
||||
WindowTitler,
|
||||
legacyRegistry
|
||||
@ -272,6 +274,18 @@ define([
|
||||
"policyService"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "AddActionProvider",
|
||||
"provides": "actionService",
|
||||
"type": "provider",
|
||||
"implementation": AddActionProvider,
|
||||
"depends": [
|
||||
"$q",
|
||||
"typeService",
|
||||
"dialogService",
|
||||
"policyService"
|
||||
]
|
||||
},
|
||||
{
|
||||
"key": "CreationService",
|
||||
"provides": "creationService",
|
||||
|
139
platform/commonUI/browse/src/creation/AddAction.js
Normal file
139
platform/commonUI/browse/src/creation/AddAction.js
Normal file
@ -0,0 +1,139 @@
|
||||
/*****************************************************************************
|
||||
* 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,Promise*/
|
||||
|
||||
/**
|
||||
* Module defining AddAction. Created by ahenry on 01/21/16.
|
||||
*/
|
||||
define(
|
||||
[
|
||||
'./CreateWizard'
|
||||
],
|
||||
function (CreateWizard) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The Add Action is performed to create new instances of
|
||||
* domain objects of a specific type that are subobjects of an
|
||||
* object being edited. This is the action that is performed when a
|
||||
* user uses the Add menu option.
|
||||
*
|
||||
* @memberof platform/commonUI/browse
|
||||
* @implements {Action}
|
||||
* @constructor
|
||||
*
|
||||
* @param {Type} type the type of domain object to create
|
||||
* @param {DomainObject} parent the domain object that should
|
||||
* act as a container for the newly-created object
|
||||
* (note that the user will have an opportunity to
|
||||
* override this)
|
||||
* @param {ActionContext} context the context in which the
|
||||
* action is being performed
|
||||
* @param {DialogService} dialogService
|
||||
*/
|
||||
function AddAction(type, parent, context, $q, dialogService, policyService) {
|
||||
this.metadata = {
|
||||
key: 'add',
|
||||
glyph: type.getGlyph(),
|
||||
name: type.getName(),
|
||||
type: type.getKey(),
|
||||
description: type.getDescription(),
|
||||
context: context
|
||||
};
|
||||
|
||||
this.type = type;
|
||||
this.parent = parent;
|
||||
this.$q = $q;
|
||||
this.dialogService = dialogService;
|
||||
this.policyService = policyService;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Create a new object of the given type.
|
||||
* This will prompt for user input first.
|
||||
*
|
||||
* @returns {Promise} that will be resolved with the object that the
|
||||
* action was originally invoked on (ie. the 'parent')
|
||||
*/
|
||||
AddAction.prototype.perform = function () {
|
||||
var newModel = this.type.getInitialModel(),
|
||||
newObject,
|
||||
parentObject = this.parent,
|
||||
wizard;
|
||||
|
||||
newModel.type = this.type.getKey();
|
||||
newObject = parentObject.getCapability('instantiation').instantiate(newModel);
|
||||
newObject.useCapability('mutation', function(model){
|
||||
model.location = parentObject.getId();
|
||||
});
|
||||
|
||||
wizard = new CreateWizard(newObject, this.parent, this.policyService);
|
||||
|
||||
function populateObjectFromInput (formValue) {
|
||||
return wizard.populateObjectFromInput(formValue, newObject);
|
||||
}
|
||||
|
||||
function addToParent (populatedObject) {
|
||||
parentObject.getCapability('composition').add(populatedObject);
|
||||
return parentObject.getCapability('persistence').persist().then(function(){
|
||||
return parentObject;
|
||||
});
|
||||
}
|
||||
|
||||
function save(object) {
|
||||
/*
|
||||
It's necessary to persist the new sub-object in order
|
||||
that it can be retrieved for composition in the parent.
|
||||
Future refactoring that allows temporary objects to be
|
||||
retrieved from object services will make this unnecessary.
|
||||
*/
|
||||
return object.getCapability('editor').save(true);
|
||||
}
|
||||
|
||||
return this.dialogService
|
||||
.getUserInput(wizard.getFormStructure(false), wizard.getInitialFormValue())
|
||||
.then(populateObjectFromInput)
|
||||
.then(save)
|
||||
.then(addToParent);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Metadata associated with a Add action.
|
||||
* @typedef {ActionMetadata} AddActionMetadata
|
||||
* @property {string} type the key for the type of domain object
|
||||
* to be created
|
||||
*/
|
||||
|
||||
/**
|
||||
* Get metadata about this action.
|
||||
* @returns {AddActionMetadata} metadata about this action
|
||||
*/
|
||||
AddAction.prototype.getMetadata = function () {
|
||||
return this.metadata;
|
||||
};
|
||||
|
||||
return AddAction;
|
||||
}
|
||||
);
|
87
platform/commonUI/browse/src/creation/AddActionProvider.js
Normal file
87
platform/commonUI/browse/src/creation/AddActionProvider.js
Normal file
@ -0,0 +1,87 @@
|
||||
/*****************************************************************************
|
||||
* 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,Promise*/
|
||||
|
||||
/**
|
||||
* Module defining AddActionProvider.js. Created by ahenry on 01/21/16.
|
||||
*/
|
||||
define(
|
||||
["./AddAction"],
|
||||
function (AddAction) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The AddActionProvider is an ActionProvider which introduces
|
||||
* an Add action for creating sub objects.
|
||||
*
|
||||
* @memberof platform/commonUI/browse
|
||||
* @constructor
|
||||
* @implements {ActionService}
|
||||
*
|
||||
* @param {TypeService} typeService the type service, used to discover
|
||||
* available types
|
||||
* @param {DialogService} dialogService the dialog service, used by
|
||||
* specific Create actions to get user input to populate the
|
||||
* model of the newly-created domain object.
|
||||
* @param {CreationService} creationService the creation service (also
|
||||
* introduced in this bundle), responsible for handling actual
|
||||
* object creation.
|
||||
*/
|
||||
function AddActionProvider($q, typeService, dialogService, policyService) {
|
||||
this.typeService = typeService;
|
||||
this.dialogService = dialogService;
|
||||
this.$q = $q;
|
||||
this.policyService = policyService;
|
||||
}
|
||||
|
||||
AddActionProvider.prototype.getActions = function (actionContext) {
|
||||
var context = actionContext || {},
|
||||
key = context.key,
|
||||
destination = context.domainObject,
|
||||
self = this;
|
||||
|
||||
// We only provide Add actions, and we need a
|
||||
// domain object to serve as the container for the
|
||||
// newly-created object (although the user may later
|
||||
// make a different selection)
|
||||
if (key !== 'add' || !destination) {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Introduce one create action per type
|
||||
return this.typeService.listTypes().filter(function (type) {
|
||||
return self.policyService.allow("creation", type) && self.policyService.allow("composition", destination.getCapability('type'), type);
|
||||
}).map(function (type) {
|
||||
return new AddAction(
|
||||
type,
|
||||
destination,
|
||||
context,
|
||||
self.$q,
|
||||
self.dialogService,
|
||||
self.policyService
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return AddActionProvider;
|
||||
}
|
||||
);
|
@ -26,18 +26,21 @@ define(
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Construct a new CreateWizard.
|
||||
* A class for capturing user input data from an object creation
|
||||
* dialog, and populating a domain object with that data.
|
||||
*
|
||||
* @param {TypeImpl} type the type of domain object to be created
|
||||
* @param {DomainObject} domainObject the newly created object to
|
||||
* populate with user input
|
||||
* @param {DomainObject} parent the domain object to serve as
|
||||
* the initial parent for the created object, in the dialog
|
||||
* @memberof platform/commonUI/browse
|
||||
* @constructor
|
||||
*/
|
||||
function CreateWizard(type, parent, policyService, initialModel) {
|
||||
this.type = type;
|
||||
this.model = initialModel || type.getInitialModel();
|
||||
this.properties = type.getProperties();
|
||||
function CreateWizard(domainObject, parent, policyService) {
|
||||
this.type = domainObject.getCapability('type');
|
||||
this.model = domainObject.getModel();
|
||||
this.domainObject = domainObject;
|
||||
this.properties = this.type.getProperties();
|
||||
this.parent = parent;
|
||||
this.policyService = policyService;
|
||||
}
|
||||
@ -46,11 +49,14 @@ define(
|
||||
* Get the form model for this wizard; this is a description
|
||||
* that will be rendered to an HTML form. See the
|
||||
* platform/forms bundle
|
||||
*
|
||||
* @param {boolean} includeLocation if true, a 'location' section
|
||||
* will be included that will allow the user to select the location
|
||||
* of the newly created object, otherwise the .location property of
|
||||
* the model will be used.
|
||||
* @return {FormModel} formModel the form model to
|
||||
* show in the create dialog
|
||||
*/
|
||||
CreateWizard.prototype.getFormStructure = function () {
|
||||
CreateWizard.prototype.getFormStructure = function (includeLocation) {
|
||||
var sections = [],
|
||||
type = this.type,
|
||||
policyService = this.policyService;
|
||||
@ -84,12 +90,16 @@ define(
|
||||
});
|
||||
|
||||
// Ensure there is always a "save in" section
|
||||
sections.push({ name: 'Location', rows: [{
|
||||
name: "Save In",
|
||||
control: "locator",
|
||||
validate: validateLocation,
|
||||
key: "createParent"
|
||||
}]});
|
||||
if (includeLocation) {
|
||||
sections.push({
|
||||
name: 'Location', rows: [{
|
||||
name: "Save In",
|
||||
control: "locator",
|
||||
validate: validateLocation,
|
||||
key: "createParent"
|
||||
}]
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
sections: sections,
|
||||
@ -97,6 +107,23 @@ define(
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Given some form input values and a domain object, populate the
|
||||
* domain object used to create this wizard from the given form values.
|
||||
* @param formValue
|
||||
* @returns {DomainObject}
|
||||
*/
|
||||
CreateWizard.prototype.populateObjectFromInput = function(formValue) {
|
||||
var parent = this.getLocation(formValue),
|
||||
formModel = this.createModel(formValue);
|
||||
|
||||
formModel.location = parent.getId();
|
||||
this.domainObject.useCapability("mutation", function(){
|
||||
return formModel;
|
||||
});
|
||||
return this.domainObject;
|
||||
};
|
||||
|
||||
/**
|
||||
* Get the initial value for the form being described.
|
||||
* This will include the values for all properties described
|
||||
@ -120,6 +147,7 @@ define(
|
||||
/**
|
||||
* Based on a populated form, get the domain object which
|
||||
* should be used as a parent for the newly-created object.
|
||||
* @private
|
||||
* @return {DomainObject}
|
||||
*/
|
||||
CreateWizard.prototype.getLocation = function (formValue) {
|
||||
@ -129,6 +157,7 @@ define(
|
||||
/**
|
||||
* Create the domain object model for a newly-created object,
|
||||
* based on user input read from a formModel.
|
||||
* @private
|
||||
* @return {object} the domain object model
|
||||
*/
|
||||
CreateWizard.prototype.createModel = function (formValue) {
|
||||
|
137
platform/commonUI/browse/test/creation/AddActionProviderSpec.js
Normal file
137
platform/commonUI/browse/test/creation/AddActionProviderSpec.js
Normal file
@ -0,0 +1,137 @@
|
||||
/*****************************************************************************
|
||||
* 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,Promise,describe,it,expect,beforeEach,waitsFor,jasmine,xit,xdescribe*/
|
||||
|
||||
/**
|
||||
* MCTRepresentationSpec. Created by ahenry on 01/21/14.
|
||||
*/
|
||||
define(
|
||||
["../../src/creation/AddActionProvider"],
|
||||
function (AddActionProvider) {
|
||||
"use strict";
|
||||
|
||||
describe("The add action provider", function () {
|
||||
var mockTypeService,
|
||||
mockDialogService,
|
||||
mockPolicyService,
|
||||
mockCreationPolicy,
|
||||
mockCompositionPolicy,
|
||||
mockPolicyMap = {},
|
||||
mockTypes,
|
||||
mockDomainObject,
|
||||
mockQ,
|
||||
provider;
|
||||
|
||||
function createMockType(name) {
|
||||
var mockType = jasmine.createSpyObj(
|
||||
"type" + name,
|
||||
[
|
||||
"getKey",
|
||||
"getGlyph",
|
||||
"getName",
|
||||
"getDescription",
|
||||
"getProperties",
|
||||
"getInitialModel",
|
||||
"hasFeature"
|
||||
]
|
||||
);
|
||||
mockType.hasFeature.andReturn(true);
|
||||
mockType.getName.andReturn(name);
|
||||
return mockType;
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockTypeService = jasmine.createSpyObj(
|
||||
"typeService",
|
||||
[ "listTypes" ]
|
||||
);
|
||||
mockDialogService = jasmine.createSpyObj(
|
||||
"dialogService",
|
||||
[ "getUserInput" ]
|
||||
);
|
||||
mockPolicyService = jasmine.createSpyObj(
|
||||
"policyService",
|
||||
[ "allow" ]
|
||||
);
|
||||
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
[ "getCapability" ]
|
||||
);
|
||||
|
||||
//Mocking getCapability because AddActionProvider uses the
|
||||
// type capability of the destination object.
|
||||
mockDomainObject.getCapability.andReturn({});
|
||||
|
||||
mockTypes = [ "A", "B", "C" ].map(createMockType);
|
||||
|
||||
mockTypes.forEach(function(type){
|
||||
mockPolicyMap[type.getName()] = true;
|
||||
});
|
||||
|
||||
mockCreationPolicy = function(type){
|
||||
return mockPolicyMap[type.getName()];
|
||||
};
|
||||
|
||||
mockCompositionPolicy = function(){
|
||||
return true;
|
||||
};
|
||||
|
||||
mockPolicyService.allow.andReturn(true);
|
||||
|
||||
mockTypeService.listTypes.andReturn(mockTypes);
|
||||
|
||||
provider = new AddActionProvider(
|
||||
mockQ,
|
||||
mockTypeService,
|
||||
mockDialogService,
|
||||
mockPolicyService
|
||||
);
|
||||
});
|
||||
|
||||
it("checks for creatability", function () {
|
||||
provider.getActions({
|
||||
key: "add",
|
||||
domainObject: mockDomainObject
|
||||
});
|
||||
// Make sure it was creation which was used to check
|
||||
expect(mockPolicyService.allow)
|
||||
.toHaveBeenCalledWith("creation", mockTypes[0]);
|
||||
});
|
||||
|
||||
it("checks for composability of type", function () {
|
||||
provider.getActions({
|
||||
key: "add",
|
||||
domainObject: mockDomainObject
|
||||
});
|
||||
|
||||
expect(mockPolicyService.allow).toHaveBeenCalledWith(
|
||||
"composition",
|
||||
jasmine.any(Object),
|
||||
jasmine.any(Object)
|
||||
);
|
||||
|
||||
expect(mockDomainObject.getCapability).toHaveBeenCalledWith('type');
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -32,11 +32,12 @@ define(
|
||||
describe("The create action provider", function () {
|
||||
var mockTypeService,
|
||||
mockDialogService,
|
||||
mockCreationService,
|
||||
mockNavigationService,
|
||||
mockPolicyService,
|
||||
mockCreationPolicy,
|
||||
mockPolicyMap = {},
|
||||
mockTypes,
|
||||
mockQ,
|
||||
provider;
|
||||
|
||||
function createMockType(name) {
|
||||
@ -66,9 +67,9 @@ define(
|
||||
"dialogService",
|
||||
[ "getUserInput" ]
|
||||
);
|
||||
mockCreationService = jasmine.createSpyObj(
|
||||
"creationService",
|
||||
[ "createObject" ]
|
||||
mockNavigationService = jasmine.createSpyObj(
|
||||
"navigationService",
|
||||
[ "setNavigation" ]
|
||||
);
|
||||
mockPolicyService = jasmine.createSpyObj(
|
||||
"policyService",
|
||||
@ -92,15 +93,14 @@ define(
|
||||
mockTypeService.listTypes.andReturn(mockTypes);
|
||||
|
||||
provider = new CreateActionProvider(
|
||||
mockQ,
|
||||
mockTypeService,
|
||||
mockDialogService,
|
||||
mockCreationService,
|
||||
mockNavigationService,
|
||||
mockPolicyService
|
||||
);
|
||||
});
|
||||
|
||||
//TODO: Disabled for NEM Beta
|
||||
xit("exposes one create action per type", function () {
|
||||
it("exposes one create action per type", function () {
|
||||
expect(provider.getActions({
|
||||
key: "create",
|
||||
domainObject: {}
|
||||
@ -114,8 +114,7 @@ define(
|
||||
}).length).toEqual(0);
|
||||
});
|
||||
|
||||
//TODO: Disabled for NEM Beta
|
||||
xit("does not expose non-creatable types", function () {
|
||||
it("does not expose non-creatable types", function () {
|
||||
// One of the types won't have the creation feature...
|
||||
mockPolicyMap[mockTypes[0].getName()] = false;
|
||||
// ...so it should have been filtered out.
|
||||
|
@ -35,6 +35,7 @@ define(
|
||||
mockProperties,
|
||||
mockPolicyService,
|
||||
testModel,
|
||||
mockDomainObject,
|
||||
wizard;
|
||||
|
||||
function createMockProperty(name) {
|
||||
@ -81,8 +82,18 @@ define(
|
||||
mockType.getInitialModel.andReturn(testModel);
|
||||
mockType.getProperties.andReturn(mockProperties);
|
||||
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
['getCapability', 'useCapability', 'getModel']
|
||||
);
|
||||
|
||||
//Mocking the getCapability('type') call
|
||||
mockDomainObject.getCapability.andReturn(mockType);
|
||||
mockDomainObject.useCapability.andReturn();
|
||||
mockDomainObject.getModel.andReturn(testModel);
|
||||
|
||||
wizard = new CreateWizard(
|
||||
mockType,
|
||||
mockDomainObject,
|
||||
mockParent,
|
||||
mockPolicyService
|
||||
);
|
||||
@ -130,6 +141,18 @@ define(
|
||||
});
|
||||
});
|
||||
|
||||
it("populates the model on the associated object", function () {
|
||||
var formValue = {
|
||||
"A": "ValueA",
|
||||
"B": "ValueB",
|
||||
"C": "ValueC"
|
||||
},
|
||||
compareModel = wizard.createModel(formValue);
|
||||
wizard.populateObjectFromInput(formValue);
|
||||
expect(mockDomainObject.useCapability).toHaveBeenCalledWith('mutation', jasmine.any(Function));
|
||||
expect(mockDomainObject.useCapability.mostRecentCall.args[1]()).toEqual(compareModel);
|
||||
});
|
||||
|
||||
it("validates selection types using policy", function () {
|
||||
var mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
@ -139,7 +162,8 @@ define(
|
||||
'otherType',
|
||||
['getKey']
|
||||
),
|
||||
structure = wizard.getFormStructure(),
|
||||
//Create a form structure with location
|
||||
structure = wizard.getFormStructure(true),
|
||||
sections = structure.sections,
|
||||
rows = structure.sections[sections.length - 1].rows,
|
||||
locationRow = rows[rows.length - 1];
|
||||
@ -156,6 +180,12 @@ define(
|
||||
);
|
||||
});
|
||||
|
||||
it("creates a form model without a location if not requested", function () {
|
||||
expect(wizard.getFormStructure(false).sections.some(function(section){
|
||||
return section.name === 'Location';
|
||||
})).toEqual(false);
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
|
@ -79,65 +79,23 @@ define(
|
||||
|
||||
function doWizardSave(parent) {
|
||||
var context = domainObject.getCapability("context"),
|
||||
wizard = new CreateWizard(domainObject.useCapability('type'), parent, self.policyService, domainObject.getModel());
|
||||
|
||||
function mergeObjects(fromObject, toObject){
|
||||
Object.keys(fromObject).forEach(function(key) {
|
||||
toObject[key] = fromObject[key];
|
||||
});
|
||||
}
|
||||
|
||||
// Create and persist the new object, based on user
|
||||
// input.
|
||||
function buildObjectFromInput(formValue) {
|
||||
var parent = wizard.getLocation(formValue),
|
||||
formModel = wizard.createModel(formValue);
|
||||
|
||||
formModel.location = parent.getId();
|
||||
//Replace domain object model with model collected
|
||||
// from user form.
|
||||
domainObject.useCapability("mutation", function(){
|
||||
//Replace object model with the model from the form
|
||||
return formModel;
|
||||
});
|
||||
return domainObject;
|
||||
}
|
||||
|
||||
function getAllComposees(domainObject){
|
||||
return domainObject.useCapability('composition');
|
||||
}
|
||||
|
||||
function addComposeesToObject(object){
|
||||
return function(composees){
|
||||
return self.$q.all(composees.map(function (composee) {
|
||||
return object.getCapability('composition').add(composee);
|
||||
})).then(resolveWith(object));
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Add the composees of the 'virtual' object to the
|
||||
* persisted object
|
||||
* @param object
|
||||
* @returns {*}
|
||||
*/
|
||||
function composeNewObject(object){
|
||||
if (self.$q.when(object.hasCapability('composition') && domainObject.hasCapability('composition'))) {
|
||||
return getAllComposees(domainObject)
|
||||
.then(addComposeesToObject(object));
|
||||
}
|
||||
}
|
||||
wizard = new CreateWizard(domainObject, parent, self.policyService);
|
||||
|
||||
return self.dialogService
|
||||
.getUserInput(wizard.getFormStructure(), wizard.getInitialFormValue())
|
||||
.then(buildObjectFromInput);
|
||||
.getUserInput(wizard.getFormStructure(true), wizard.getInitialFormValue())
|
||||
.then(function(formValue){
|
||||
return wizard.populateObjectFromInput(formValue, domainObject);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function persistObject(object){
|
||||
return ((object.hasCapability('editor') && object.getCapability('editor').save(true)) ||
|
||||
object.getCapability('persistence').persist())
|
||||
.then(resolveWith(object));
|
||||
|
||||
//Persist first to mark dirty
|
||||
return object.getCapability('persistence').persist().then(function(){
|
||||
//then save permanently
|
||||
return object.getCapability('editor').save();
|
||||
});
|
||||
}
|
||||
|
||||
function fetchObject(objectId){
|
||||
@ -152,7 +110,9 @@ define(
|
||||
|
||||
function locateObjectInParent(parent){
|
||||
parent.getCapability('composition').add(domainObject.getId());
|
||||
return parent;
|
||||
return parent.getCapability('persistence').persist().then(function() {
|
||||
return parent;
|
||||
});
|
||||
}
|
||||
|
||||
function doNothing() {
|
||||
@ -174,7 +134,6 @@ define(
|
||||
.then(getParent)//Parent may have changed based
|
||||
// on user selection
|
||||
.then(locateObjectInParent)
|
||||
.then(persistObject)
|
||||
.then(function(){
|
||||
return fetchObject(domainObject.getId());
|
||||
})
|
||||
|
@ -0,0 +1,60 @@
|
||||
/*****************************************************************************
|
||||
* 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*/
|
||||
|
||||
|
||||
define(
|
||||
['./EditableLookupCapability'],
|
||||
function (EditableLookupCapability) {
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* Wrapper for the "instantiation" capability;
|
||||
* ensures that any domain objects instantiated in Edit mode
|
||||
* are also wrapped as EditableDomainObjects.
|
||||
*
|
||||
* Meant specifically for use by EditableDomainObject and the
|
||||
* associated cache; the constructor signature is particular
|
||||
* to a pattern used there and may contain unused arguments.
|
||||
* @constructor
|
||||
* @memberof platform/commonUI/edit
|
||||
* @implements {CompositionCapability}
|
||||
*/
|
||||
return function EditableInstantiationCapability(
|
||||
contextCapability,
|
||||
editableObject,
|
||||
domainObject,
|
||||
cache
|
||||
) {
|
||||
// This is a "lookup" style capability (it looks up other
|
||||
// domain objects), but we do not want to return the same
|
||||
// specific value every time (composition may change)
|
||||
return new EditableLookupCapability(
|
||||
contextCapability,
|
||||
editableObject,
|
||||
domainObject,
|
||||
cache,
|
||||
false // Not idempotent
|
||||
);
|
||||
};
|
||||
}
|
||||
);
|
@ -45,7 +45,8 @@ define(
|
||||
cache,
|
||||
idempotent
|
||||
) {
|
||||
var capability = Object.create(contextCapability);
|
||||
var capability = Object.create(contextCapability),
|
||||
method;
|
||||
|
||||
// Check for domain object interface. If something has these
|
||||
// three methods, we assume it's a domain object.
|
||||
@ -114,7 +115,9 @@ define(
|
||||
}
|
||||
|
||||
// Wrap all methods; return only editable domain objects.
|
||||
Object.keys(contextCapability).forEach(wrapMethod);
|
||||
for (method in contextCapability) {
|
||||
wrapMethod(method);
|
||||
}
|
||||
|
||||
return capability;
|
||||
};
|
||||
|
@ -81,7 +81,8 @@ define(
|
||||
var domainObject = this.domainObject,
|
||||
editableObject = this.editableObject,
|
||||
self = this,
|
||||
cache = this.cache;
|
||||
cache = this.cache,
|
||||
returnPromise;
|
||||
|
||||
// Update the underlying, "real" domain object's model
|
||||
// with changes made to the copy used for editing.
|
||||
@ -99,14 +100,18 @@ define(
|
||||
editableObject.getCapability("status").set("editing", false);
|
||||
|
||||
if (nonrecursive) {
|
||||
return resolvePromise(doMutate())
|
||||
returnPromise = resolvePromise(doMutate())
|
||||
.then(doPersist)
|
||||
.then(function(){
|
||||
self.cancel();
|
||||
});
|
||||
} else {
|
||||
return resolvePromise(cache.saveAll());
|
||||
returnPromise = resolvePromise(cache.saveAll());
|
||||
}
|
||||
//Return the original (non-editable) object
|
||||
return returnPromise.then(function() {
|
||||
return domainObject.getOriginalObject ? domainObject.getOriginalObject() : domainObject;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -36,6 +36,7 @@ define(
|
||||
'../capabilities/EditableContextCapability',
|
||||
'../capabilities/EditableCompositionCapability',
|
||||
'../capabilities/EditableRelationshipCapability',
|
||||
'../capabilities/EditableInstantiationCapability',
|
||||
'../capabilities/EditorCapability',
|
||||
'../capabilities/EditableActionCapability',
|
||||
'./EditableDomainObjectCache'
|
||||
@ -45,6 +46,7 @@ define(
|
||||
EditableContextCapability,
|
||||
EditableCompositionCapability,
|
||||
EditableRelationshipCapability,
|
||||
EditableInstantiationCapability,
|
||||
EditorCapability,
|
||||
EditableActionCapability,
|
||||
EditableDomainObjectCache
|
||||
@ -56,6 +58,7 @@ define(
|
||||
context: EditableContextCapability,
|
||||
composition: EditableCompositionCapability,
|
||||
relationship: EditableRelationshipCapability,
|
||||
instantiation: EditableInstantiationCapability,
|
||||
editor: EditorCapability
|
||||
};
|
||||
|
||||
|
@ -118,6 +118,29 @@ define(
|
||||
expect(mockContext.getDomainObject.calls.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("wraps inherited methods", function () {
|
||||
var CapabilityClass = function(){
|
||||
};
|
||||
CapabilityClass.prototype.inheritedMethod=function () {
|
||||
return "an inherited method";
|
||||
};
|
||||
|
||||
mockContext = new CapabilityClass();
|
||||
|
||||
capability = new EditableLookupCapability(
|
||||
mockContext,
|
||||
mockEditableObject,
|
||||
mockDomainObject,
|
||||
factory,
|
||||
false
|
||||
);
|
||||
expect(capability.inheritedMethod()).toEqual("an inherited method");
|
||||
expect(capability.hasOwnProperty('inheritedMethod')).toBe(true);
|
||||
// The presence of an own property indicates that the method
|
||||
// has been wrapped on the object itself and this is a valid
|
||||
// test that the inherited method has been wrapped.
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -39,7 +39,7 @@ define(
|
||||
function populateActionMap(domainObject) {
|
||||
var actionCapability = domainObject.getCapability('action'),
|
||||
actions = actionCapability ?
|
||||
actionCapability.getActions('create') : [];
|
||||
actionCapability.getActions('add') : [];
|
||||
actions.forEach(function (action) {
|
||||
actionMap[action.getMetadata().type] = action;
|
||||
});
|
||||
|
@ -74,7 +74,7 @@ define(
|
||||
expect(mockDomainObject.getCapability)
|
||||
.toHaveBeenCalledWith('action');
|
||||
expect(mockActionCapability.getActions)
|
||||
.toHaveBeenCalledWith('create');
|
||||
.toHaveBeenCalledWith('add');
|
||||
});
|
||||
|
||||
it("invokes the action on the selection, if any", function () {
|
||||
|
Loading…
Reference in New Issue
Block a user