Resovled merge conflicts

This commit is contained in:
Henry 2016-05-12 15:58:17 -07:00
parent 116c6e57ed
commit e5ef7c0c22
6 changed files with 381 additions and 86 deletions

View File

@ -40,6 +40,10 @@ define([
"./src/policies/EditContextualActionPolicy",
"./src/representers/EditRepresenter",
"./src/representers/EditToolbarRepresenter",
"./src/capabilities/EditorCapability",
"./src/capabilities/TransactionDecorator",
"./src/services/TransactionService",
"./src/services/DirtyModelCache",
"text!./res/templates/library.html",
"text!./res/templates/edit-object.html",
"text!./res/templates/edit-action-buttons.html",
@ -66,6 +70,10 @@ define([
EditContextualActionPolicy,
EditRepresenter,
EditToolbarRepresenter,
EditorCapability,
TransactionDecorator,
TransactionService,
DirtyModelCache,
libraryTemplate,
editObjectTemplate,
editActionButtonsTemplate,
@ -261,6 +269,35 @@ define([
"template": topbarEditTemplate
}
],
"components": [
{
"type": "decorator",
"provides": "capabilityService",
"implementation": TransactionDecorator,
"depends": [
"$q",
"transactionService",
"dirtyModelCache"
]
},
{
"type": "provider",
"provides": "transactionService",
"implementation": TransactionService,
"depends": [
"$q",
"dirtyModelCache"
]
},
{
"type": "provider",
"provides": "dirtyModelCache",
"implementation": DirtyModelCache,
"depends": [
"topic"
]
}
],
"representers": [
{
"implementation": EditRepresenter,
@ -282,7 +319,19 @@ define([
"key": "nonEditContextBlacklist",
"value": ["copy", "follow", "properties", "move", "link", "remove", "locate"]
}
]
],
"capabilities": [
{
"key": "editor",
"name": "Editor Capability",
"description": "Provides transactional editing capabilities",
"implementation": EditorCapability,
"depends": [
"transactionService",
"dirtyModelCache"
]
}
],
}
});
});

View File

@ -24,12 +24,10 @@ define(
[],
function () {
/**
* Implements "save" and "cancel" as capabilities of
* the object. In editing mode, user is seeing/using
* a copy of the object (an EditableDomainObject)
* which is disconnected from persistence; the Save
* a copy of the object which is disconnected from persistence; the Save
* and Cancel actions can use this capability to
* propagate changes from edit mode to the underlying
* actual persistable object.
@ -41,99 +39,37 @@ define(
* @memberof platform/commonUI/edit
*/
function EditorCapability(
persistenceCapability,
editableObject,
domainObject,
cache
transactionService,
dirtyModelCache,
domainObject
) {
this.editableObject = editableObject;
this.transactionService = transactionService;
this.dirtyModelCache = dirtyModelCache;
this.domainObject = domainObject;
this.cache = cache;
}
// Simulate Promise.resolve (or $q.when); the former
// causes a delayed reaction from Angular (since it
// does not trigger a digest) and the latter is not
// readily accessible, since we're a few classes
// removed from the layer which gets dependency
// injection.
function resolvePromise(value) {
return (value && value.then) ? value : {
then: function (callback) {
return resolvePromise(callback(value));
}
};
}
EditorCapability.prototype.edit = function () {
this.transactionService.startTransaction();
this.getCapability('status').set('editing', true);
};
/**
* Save any changes that have been made to this domain object
* (as well as to others that might have been retrieved and
* modified during the editing session)
* @param {boolean} nonrecursive if true, save only this
* object (and not other objects with associated changes)
* @returns {Promise} a promise that will be fulfilled after
* persistence has completed.
* @memberof platform/commonUI/edit.EditorCapability#
*/
EditorCapability.prototype.save = function (nonrecursive) {
var domainObject = this.domainObject,
editableObject = this.editableObject,
self = this,
cache = this.cache,
returnPromise;
EditorCapability.prototype.save = function () {
return this.transactionService.commit();
};
// Update the underlying, "real" domain object's model
// with changes made to the copy used for editing.
function doMutate() {
return domainObject.useCapability('mutation', function () {
return editableObject.getModel();
});
}
// Persist the underlying domain object
function doPersist() {
return domainObject.getCapability('persistence').persist();
}
editableObject.getCapability("status").set("editing", false);
if (nonrecursive) {
returnPromise = resolvePromise(doMutate())
.then(doPersist)
.then(function(){
self.cancel();
});
} else {
returnPromise = resolvePromise(cache.saveAll());
}
//Return the original (non-editable) object
return returnPromise.then(function() {
return domainObject.getOriginalObject ? domainObject.getOriginalObject() : domainObject;
EditorCapability.prototype.cancel = function () {
var domainObject = this.domainObject;
return this.transactionService.cancel().then(function(){
domainObject.getCapability("status").set("editing", false);
});
};
/**
* Cancel editing; Discard any changes that have been made to
* this domain object (as well as to others that might have
* been retrieved and modified during the editing session)
* @returns {Promise} a promise that will be fulfilled after
* cancellation has completed.
* @memberof platform/commonUI/edit.EditorCapability#
*/
EditorCapability.prototype.cancel = function () {
this.editableObject.getCapability("status").set("editing", false);
this.cache.markClean();
return resolvePromise(undefined);
EditorCapability.prototype.dirty = function () {
return this.dirtyModelCache.isDirty(this.domainObject);
};
/**
* Check if there are any unsaved changes.
* @returns {boolean} true if there are unsaved changes
* @memberof platform/commonUI/edit.EditorCapability#
*/
EditorCapability.prototype.dirty = function () {
return this.cache.dirty();
};
//TODO: add 'appliesTo'. EditorCapability should not be available
// for objects that should not be edited
return EditorCapability;
}

View File

@ -0,0 +1,82 @@
/*****************************************************************************
* 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(
['./TransactionalPersistenceCapability'],
function (TransactionalPersistenceCapability) {
'use strict';
/**
* Implements "save" and "cancel" as capabilities of
* the object. In editing mode, user is seeing/using
* a copy of the object (an EditableDomainObject)
* which is disconnected from persistence; the Save
* and Cancel actions can use this capability to
* propagate changes from edit mode to the underlying
* actual persistable object.
*
* 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
*/
function TransactionDecorator(
$q,
transactionService,
dirtyModelCache,
capabilityService
) {
this.capabilityService = capabilityService;
this.transactionService = transactionService;
this.dirtyModelCache = dirtyModelCache;
this.$q = $q;
}
/**
* Decorate PersistenceCapability to ignore persistence calls when a
* transaction is in progress.
*/
TransactionDecorator.prototype.getCapabilities = function (model) {
var capabilities = this.capabilityService.getCapabilities(model),
persistenceCapability = capabilities.persistence;
capabilities.persistence = function (domainObject) {
var original =
(typeof persistenceCapability === 'function') ?
persistenceCapability(domainObject) :
persistenceCapability;
return new TransactionalPersistenceCapability(
self.$q,
self.transactionService,
self.dirtyModelCache,
original,
domainObject
);
};
return capabilities;
};
return TransactionDecorator;
}
);

View 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*/
define(
[],
function () {
'use strict';
function TransactionalPersistenceCapability(
$q,
transactionService,
dirtyModelCache,
persistenceCapability,
domainObject
) {
this.transactionService = transactionService;
this.dirtyModelCache = dirtyModelCache;
this.persistenceCapability = Object.create(persistenceCapability);
this.domainObject = domainObject;
this.$q = $q;
}
TransactionalPersistenceCapability.prototype.persist = function () {
var domainObject = this.domainObject,
dirtyModelCache = this.dirtyModelCache;
if (this.transactionService.isActive()) {
dirtyModelCache.markDirty(domainObject);
//Using $q here because need to return something
// from which 'catch' can be chained
return this.$q.when(true);
} else {
return this.persistenceCapability.persist().then(function (result) {
dirtyModelCache.markClean(domainObject);
return result;
});
}
};
TransactionalPersistenceCapability.prototype.refresh = function () {
var dirtyModelCache = this.dirtyModelCache;
return this.persistenceCapability.refresh().then(function (result) {
dirtyModelCache.markClean(domainObject);
return result;
});
};
TransactionalPersistenceCapability.prototype.getSpace = function () {
return this.persistenceCapability.getSpace();
};
return TransactionalPersistenceCapability;
}
);

View File

@ -0,0 +1,47 @@
/*****************************************************************************
* 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(
[],
function() {
function DirtyModelCache(topic) {
this.cache = {};
}
DirtyModelCache.prototype.get = function () {
return this.cache;
};
DirtyModelCache.prototype.isDirty = function (domainObject) {
return !!this.get(domainObject.getId());
};
DirtyModelCache.prototype.markDirty = function (domainObject) {
this.cache[domainObject.getId()] = domainObject;
};
DirtyModelCache.prototype.markClean = function (domainObject) {
delete this.cache[domainObject.getId()];
};
return DirtyModelCache;
});

View File

@ -0,0 +1,108 @@
/*****************************************************************************
* 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(
[],
function() {
/**
* Implements an application-wide transaction state. Once a
* transaction is started, calls to PersistenceCapability.persist()
* will be deferred until a subsequent call to
* TransactionService.commit() is made.
*
* @param $q
* @constructor
*/
function TransactionService($q, dirtyModelCache) {
this.$q = $q;
this.transaction = false;
this.cache = dirtyModelCache;
}
TransactionService.prototype.startTransaction = function () {
if (this.transaction) {
throw "Transaction in progress";
}
this.transaction = true;
};
TransactionService.prototype.isActive = function () {
return this.transaction;
};
/**
* All persist calls deferred since the beginning of the transaction
* will be committed. Any failures will be reported via a promise
* rejection.
* @returns {*}
*/
TransactionService.prototype.commit = function () {
var self = this;
cache = this.cache.get();
function keyToObject(key) {
return cache[key];
}
function objectToPromise(object) {
return object.getCapability('persistence').persist();
}
return this.$q.all(
Object.keys(this.cache)
.map(keyToObject)
.map(objectToPromise))
.then(function () {
self.transaction = false;
});
};
/**
* Cancel the current transaction, replacing any dirty objects from
* persistence. Not a true rollback, as it cannot be used to undo any
* persist calls that were successful in the event one of a batch of
* persists failing.
*
* @returns {*}
*/
TransactionService.prototype.cancel = function () {
var self = this,
cache = this.cache.get();
function keyToObject(key) {
return cache[key];
}
function objectToPromise(object) {
return object.getCapability('persistence').refresh();
}
return this.$q.all(Object.keys(cache)
.map(keyToObject)
.map(objectToPromise))
.then(function () {
self.transaction = false;
});
};
return TransactionService;
});