mirror of
https://github.com/nasa/openmct.git
synced 2024-12-21 06:03:08 +00:00
* Implement transactions in Object API and retire legacy transactions #4089 * Added `objectAPI.refresh` Co-authored-by: Andrew Henry <akhenry@gmail.com>
This commit is contained in:
parent
5eaf222f88
commit
d0c5731287
@ -34,9 +34,6 @@ define([
|
|||||||
"./src/policies/EditPersistableObjectsPolicy",
|
"./src/policies/EditPersistableObjectsPolicy",
|
||||||
"./src/representers/EditRepresenter",
|
"./src/representers/EditRepresenter",
|
||||||
"./src/capabilities/EditorCapability",
|
"./src/capabilities/EditorCapability",
|
||||||
"./src/capabilities/TransactionCapabilityDecorator",
|
|
||||||
"./src/services/TransactionManager",
|
|
||||||
"./src/services/TransactionService",
|
|
||||||
"./src/creation/CreateMenuController",
|
"./src/creation/CreateMenuController",
|
||||||
"./src/creation/LocatorController",
|
"./src/creation/LocatorController",
|
||||||
"./src/creation/CreationPolicy",
|
"./src/creation/CreationPolicy",
|
||||||
@ -63,9 +60,6 @@ define([
|
|||||||
EditPersistableObjectsPolicy,
|
EditPersistableObjectsPolicy,
|
||||||
EditRepresenter,
|
EditRepresenter,
|
||||||
EditorCapability,
|
EditorCapability,
|
||||||
TransactionCapabilityDecorator,
|
|
||||||
TransactionManager,
|
|
||||||
TransactionService,
|
|
||||||
CreateMenuController,
|
CreateMenuController,
|
||||||
LocatorController,
|
LocatorController,
|
||||||
CreationPolicy,
|
CreationPolicy,
|
||||||
@ -263,26 +257,6 @@ define([
|
|||||||
}
|
}
|
||||||
],
|
],
|
||||||
"components": [
|
"components": [
|
||||||
{
|
|
||||||
"type": "decorator",
|
|
||||||
"provides": "capabilityService",
|
|
||||||
"implementation": TransactionCapabilityDecorator,
|
|
||||||
"depends": [
|
|
||||||
"$q",
|
|
||||||
"transactionManager"
|
|
||||||
],
|
|
||||||
"priority": "fallback"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"type": "provider",
|
|
||||||
"provides": "transactionService",
|
|
||||||
"implementation": TransactionService,
|
|
||||||
"depends": [
|
|
||||||
"$q",
|
|
||||||
"$log",
|
|
||||||
"cacheService"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"key": "CreateActionProvider",
|
"key": "CreateActionProvider",
|
||||||
"provides": "actionService",
|
"provides": "actionService",
|
||||||
@ -320,7 +294,6 @@ define([
|
|||||||
"description": "Provides transactional editing capabilities",
|
"description": "Provides transactional editing capabilities",
|
||||||
"implementation": EditorCapability,
|
"implementation": EditorCapability,
|
||||||
"depends": [
|
"depends": [
|
||||||
"transactionService",
|
|
||||||
"openmct"
|
"openmct"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -331,15 +304,6 @@ define([
|
|||||||
"template": locatorTemplate
|
"template": locatorTemplate
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"services": [
|
|
||||||
{
|
|
||||||
"key": "transactionManager",
|
|
||||||
"implementation": TransactionManager,
|
|
||||||
"depends": [
|
|
||||||
"transactionService"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"runs": [
|
"runs": [
|
||||||
{
|
{
|
||||||
depends: [
|
depends: [
|
||||||
|
@ -155,8 +155,8 @@ function (
|
|||||||
}
|
}
|
||||||
|
|
||||||
function undirtyOriginals(object) {
|
function undirtyOriginals(object) {
|
||||||
return Promise.all(toUndirty.map(undirty))
|
return object.getCapability("persistence").persist()
|
||||||
.then(() => {
|
.then(function () {
|
||||||
return object;
|
return object;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -30,32 +30,17 @@ define(
|
|||||||
* Once initiated, any persist operations will be queued pending a
|
* Once initiated, any persist operations will be queued pending a
|
||||||
* subsequent call to [.save()](@link #save) or [.finish()](@link
|
* subsequent call to [.save()](@link #save) or [.finish()](@link
|
||||||
* #finish).
|
* #finish).
|
||||||
* @param transactionService
|
|
||||||
* @param domainObject
|
* @param domainObject
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
function EditorCapability(
|
function EditorCapability(
|
||||||
transactionService,
|
|
||||||
openmct,
|
openmct,
|
||||||
domainObject
|
domainObject
|
||||||
) {
|
) {
|
||||||
this.transactionService = transactionService;
|
|
||||||
this.openmct = openmct;
|
this.openmct = openmct;
|
||||||
this.domainObject = domainObject;
|
this.domainObject = domainObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Initiate an editing session. This will start a transaction during
|
|
||||||
* which any persist operations will be deferred until either save()
|
|
||||||
* or finish() are called.
|
|
||||||
*/
|
|
||||||
EditorCapability.prototype.edit = function () {
|
|
||||||
if (!this.openmct.editor.isEditing()) {
|
|
||||||
this.openmct.editor.edit();
|
|
||||||
this.domainObject.getCapability('status').set('editing', true);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Determines whether this object, or any of its ancestors are
|
* Determines whether this object, or any of its ancestors are
|
||||||
* currently being edited.
|
* currently being edited.
|
||||||
@ -74,34 +59,6 @@ define(
|
|||||||
return this.openmct.editor.isEditing();
|
return this.openmct.editor.isEditing();
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* Save any unsaved changes from this editing session. This will
|
|
||||||
* end the current transaction and continue with a new one.
|
|
||||||
* @returns {*}
|
|
||||||
*/
|
|
||||||
EditorCapability.prototype.save = function () {
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
|
|
||||||
EditorCapability.prototype.invoke = EditorCapability.prototype.edit;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Finish the current editing session. This will discard any pending
|
|
||||||
* persist operations
|
|
||||||
* @returns {*}
|
|
||||||
*/
|
|
||||||
EditorCapability.prototype.finish = function () {
|
|
||||||
return Promise.resolve();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {boolean} true if there have been any domain model
|
|
||||||
* modifications since the last persist, false otherwise.
|
|
||||||
*/
|
|
||||||
EditorCapability.prototype.dirty = function () {
|
|
||||||
return this.transactionService.size() > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
return EditorCapability;
|
return EditorCapability;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
@ -1,75 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(
|
|
||||||
['./TransactionalPersistenceCapability'],
|
|
||||||
function (TransactionalPersistenceCapability) {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps the [PersistenceCapability]{@link PersistenceCapability} with
|
|
||||||
* transactional capabilities.
|
|
||||||
* @param $q
|
|
||||||
* @param transactionService
|
|
||||||
* @param capabilityService
|
|
||||||
* @see TransactionalPersistenceCapability
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function TransactionCapabilityDecorator(
|
|
||||||
$q,
|
|
||||||
transactionService,
|
|
||||||
capabilityService
|
|
||||||
) {
|
|
||||||
this.capabilityService = capabilityService;
|
|
||||||
this.transactionService = transactionService;
|
|
||||||
this.$q = $q;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decorate PersistenceCapability to queue persistence calls when a
|
|
||||||
* transaction is in progress.
|
|
||||||
*/
|
|
||||||
TransactionCapabilityDecorator.prototype.getCapabilities = function () {
|
|
||||||
var self = this,
|
|
||||||
capabilities = this.capabilityService.getCapabilities
|
|
||||||
.apply(this.capabilityService, arguments),
|
|
||||||
persistenceCapability = capabilities.persistence;
|
|
||||||
|
|
||||||
capabilities.persistence = function (domainObject) {
|
|
||||||
var original =
|
|
||||||
(typeof persistenceCapability === 'function')
|
|
||||||
? persistenceCapability(domainObject)
|
|
||||||
: persistenceCapability;
|
|
||||||
|
|
||||||
return new TransactionalPersistenceCapability(
|
|
||||||
self.$q,
|
|
||||||
self.transactionService,
|
|
||||||
original,
|
|
||||||
domainObject
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
return capabilities;
|
|
||||||
};
|
|
||||||
|
|
||||||
return TransactionCapabilityDecorator;
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,91 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(
|
|
||||||
[],
|
|
||||||
function () {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wraps persistence capability to enable transactions. Transactions
|
|
||||||
* will cause persist calls not to be invoked immediately, but
|
|
||||||
* rather queued until [EditorCapability.save()]{@link EditorCapability#save}
|
|
||||||
* or [EditorCapability.cancel()]{@link EditorCapability#cancel} are
|
|
||||||
* called.
|
|
||||||
* @memberof platform/commonUI/edit/capabilities
|
|
||||||
* @param $q
|
|
||||||
* @param transactionManager
|
|
||||||
* @param persistenceCapability
|
|
||||||
* @param domainObject
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function TransactionalPersistenceCapability(
|
|
||||||
$q,
|
|
||||||
transactionManager,
|
|
||||||
persistenceCapability,
|
|
||||||
domainObject
|
|
||||||
) {
|
|
||||||
this.transactionManager = transactionManager;
|
|
||||||
this.persistenceCapability = persistenceCapability;
|
|
||||||
this.domainObject = domainObject;
|
|
||||||
this.$q = $q;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The wrapped persist function. If a transaction is active, persist
|
|
||||||
* will be queued until the transaction is committed or cancelled.
|
|
||||||
* @returns {*}
|
|
||||||
*/
|
|
||||||
TransactionalPersistenceCapability.prototype.persist = function () {
|
|
||||||
var wrappedPersistence = this.persistenceCapability;
|
|
||||||
|
|
||||||
if (this.transactionManager.isActive()) {
|
|
||||||
this.transactionManager.addToTransaction(
|
|
||||||
this.domainObject.getId(),
|
|
||||||
wrappedPersistence.persist.bind(wrappedPersistence),
|
|
||||||
wrappedPersistence.refresh.bind(wrappedPersistence)
|
|
||||||
);
|
|
||||||
|
|
||||||
//Need to return a promise from this function
|
|
||||||
return this.$q.when(true);
|
|
||||||
} else {
|
|
||||||
return this.persistenceCapability.persist();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
TransactionalPersistenceCapability.prototype.refresh = function () {
|
|
||||||
this.transactionManager
|
|
||||||
.clearTransactionsFor(this.domainObject.getId());
|
|
||||||
|
|
||||||
return this.persistenceCapability.refresh();
|
|
||||||
};
|
|
||||||
|
|
||||||
TransactionalPersistenceCapability.prototype.getSpace = function () {
|
|
||||||
return this.persistenceCapability.getSpace();
|
|
||||||
};
|
|
||||||
|
|
||||||
TransactionalPersistenceCapability.prototype.persisted = function () {
|
|
||||||
return this.persistenceCapability.persisted();
|
|
||||||
};
|
|
||||||
|
|
||||||
return TransactionalPersistenceCapability;
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,49 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
define(['./Transaction'], function (Transaction) {
|
|
||||||
/**
|
|
||||||
* A nested transaction is a transaction which takes place in the context
|
|
||||||
* of a larger parent transaction. It becomes part of the parent
|
|
||||||
* transaction when (and only when) committed.
|
|
||||||
* @param parent
|
|
||||||
* @constructor
|
|
||||||
* @extends {platform/commonUI/edit/services.Transaction}
|
|
||||||
* @memberof platform/commonUI/edit/services
|
|
||||||
*/
|
|
||||||
function NestedTransaction(parent) {
|
|
||||||
this.parent = parent;
|
|
||||||
Transaction.call(this, parent.$log);
|
|
||||||
}
|
|
||||||
|
|
||||||
NestedTransaction.prototype = Object.create(Transaction.prototype);
|
|
||||||
|
|
||||||
NestedTransaction.prototype.commit = function () {
|
|
||||||
this.parent.add(
|
|
||||||
Transaction.prototype.commit.bind(this),
|
|
||||||
Transaction.prototype.cancel.bind(this)
|
|
||||||
);
|
|
||||||
|
|
||||||
return Promise.resolve(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
return NestedTransaction;
|
|
||||||
});
|
|
@ -1,99 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
define([], function () {
|
|
||||||
/**
|
|
||||||
* A Transaction represents a set of changes that are intended to
|
|
||||||
* be kept or discarded as a unit.
|
|
||||||
* @param $log Angular's `$log` service, for logging messages
|
|
||||||
* @constructor
|
|
||||||
* @memberof platform/commonUI/edit/services
|
|
||||||
*/
|
|
||||||
function Transaction($log) {
|
|
||||||
this.$log = $log;
|
|
||||||
this.callbacks = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add a change to the current transaction, as expressed by functions
|
|
||||||
* to either keep or discard the change.
|
|
||||||
* @param {Function} commit called when the transaction is committed
|
|
||||||
* @param {Function} cancel called when the transaction is cancelled
|
|
||||||
* @returns {Function) a function which may be called to remove this
|
|
||||||
* pair of callbacks from the transaction
|
|
||||||
*/
|
|
||||||
Transaction.prototype.add = function (commit, cancel) {
|
|
||||||
var callback = {
|
|
||||||
commit: commit,
|
|
||||||
cancel: cancel
|
|
||||||
};
|
|
||||||
this.callbacks.push(callback);
|
|
||||||
|
|
||||||
return function () {
|
|
||||||
this.callbacks = this.callbacks.filter(function (c) {
|
|
||||||
return c !== callback;
|
|
||||||
});
|
|
||||||
}.bind(this);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the number of changes in the current transaction.
|
|
||||||
* @returns {number} the size of the current transaction
|
|
||||||
*/
|
|
||||||
Transaction.prototype.size = function () {
|
|
||||||
return this.callbacks.length;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Keep all changes associated with this transaction.
|
|
||||||
* @method {platform/commonUI/edit/services.Transaction#commit}
|
|
||||||
* @returns {Promise} a promise which will resolve when all callbacks
|
|
||||||
* have been handled.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Discard all changes associated with this transaction.
|
|
||||||
* @method {platform/commonUI/edit/services.Transaction#cancel}
|
|
||||||
* @returns {Promise} a promise which will resolve when all callbacks
|
|
||||||
* have been handled.
|
|
||||||
*/
|
|
||||||
|
|
||||||
['commit', 'cancel'].forEach(function (method) {
|
|
||||||
Transaction.prototype[method] = function () {
|
|
||||||
var promises = [];
|
|
||||||
var callback;
|
|
||||||
|
|
||||||
while (this.callbacks.length > 0) {
|
|
||||||
callback = this.callbacks.shift();
|
|
||||||
try {
|
|
||||||
promises.push(callback[method]());
|
|
||||||
} catch (e) {
|
|
||||||
this.$log
|
|
||||||
.error("Error trying to " + method + " transaction.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Promise.all(promises);
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
return Transaction;
|
|
||||||
});
|
|
@ -1,119 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define([], function () {
|
|
||||||
/**
|
|
||||||
* Manages transactions to support the TransactionalPersistenceCapability.
|
|
||||||
* This assumes that all commit/cancel callbacks for a given domain
|
|
||||||
* object are equivalent, and only need to be added once to any active
|
|
||||||
* transaction. Violating this assumption may cause unexpected behavior.
|
|
||||||
* @constructor
|
|
||||||
* @memberof platform/commonUI/edit
|
|
||||||
*/
|
|
||||||
function TransactionManager(transactionService) {
|
|
||||||
this.transactionService = transactionService;
|
|
||||||
this.clearTransactionFns = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if a transaction is currently active.
|
|
||||||
* @returns {boolean} true if there is a transaction active
|
|
||||||
*/
|
|
||||||
TransactionManager.prototype.isActive = function () {
|
|
||||||
return this.transactionService.isActive();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check if callbacks associated with this domain object have already
|
|
||||||
* been added to the active transaction.
|
|
||||||
* @private
|
|
||||||
* @param {string} id the identifier of the domain object to check
|
|
||||||
* @returns {boolean} true if callbacks have been added
|
|
||||||
*/
|
|
||||||
TransactionManager.prototype.isScheduled = function (id) {
|
|
||||||
return Boolean(this.clearTransactionFns[id]);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add callbacks associated with this domain object to the active
|
|
||||||
* transaction. Both callbacks are expected to return promises that
|
|
||||||
* resolve when their associated behavior is complete.
|
|
||||||
*
|
|
||||||
* If callbacks associated with this domain object have already been
|
|
||||||
* added to the active transaction, this call will be ignored.
|
|
||||||
*
|
|
||||||
* @param {string} id the identifier of the associated domain object
|
|
||||||
* @param {Function} onCommit behavior to invoke when committing transaction
|
|
||||||
* @param {Function} onCancel behavior to invoke when cancelling transaction
|
|
||||||
*/
|
|
||||||
TransactionManager.prototype.addToTransaction = function (
|
|
||||||
id,
|
|
||||||
onCommit,
|
|
||||||
onCancel
|
|
||||||
) {
|
|
||||||
var release = this.releaseClearFn.bind(this, id);
|
|
||||||
|
|
||||||
function chain(promiseFn, nextFn) {
|
|
||||||
return function () {
|
|
||||||
return promiseFn().then(nextFn);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear any existing persistence calls for object with given ID. This ensures only the most recent persistence
|
|
||||||
* call is executed. This should prevent stale objects being persisted and overwriting fresh ones.
|
|
||||||
*/
|
|
||||||
if (this.isScheduled(id)) {
|
|
||||||
this.clearTransactionsFor(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
this.clearTransactionFns[id] =
|
|
||||||
this.transactionService.addToTransaction(
|
|
||||||
chain(onCommit, release),
|
|
||||||
chain(onCancel, release)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remove any callbacks associated with this domain object from the
|
|
||||||
* active transaction.
|
|
||||||
* @param {string} id the identifier for the domain object
|
|
||||||
*/
|
|
||||||
TransactionManager.prototype.clearTransactionsFor = function (id) {
|
|
||||||
if (this.isScheduled(id)) {
|
|
||||||
this.clearTransactionFns[id]();
|
|
||||||
this.releaseClearFn(id);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Release the cached "remove from transaction" function that has been
|
|
||||||
* stored in association with this domain object.
|
|
||||||
* @param {string} id the identifier for the domain object
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
TransactionManager.prototype.releaseClearFn = function (id) {
|
|
||||||
delete this.clearTransactionFns[id];
|
|
||||||
};
|
|
||||||
|
|
||||||
return TransactionManager;
|
|
||||||
});
|
|
@ -1,138 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
define(
|
|
||||||
['./Transaction', './NestedTransaction'],
|
|
||||||
function (Transaction, NestedTransaction) {
|
|
||||||
/**
|
|
||||||
* Implements an application-wide transaction state. Once a
|
|
||||||
* transaction is started, calls to
|
|
||||||
* [PersistenceCapability.persist()]{@link PersistenceCapability#persist}
|
|
||||||
* will be deferred until a subsequent call to
|
|
||||||
* [TransactionService.commit]{@link TransactionService#commit} is made.
|
|
||||||
*
|
|
||||||
* @memberof platform/commonUI/edit/services
|
|
||||||
* @param $q
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
function TransactionService($q, $log, cacheService) {
|
|
||||||
this.$q = $q;
|
|
||||||
this.$log = $log;
|
|
||||||
this.cacheService = cacheService;
|
|
||||||
this.transactions = [];
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Starts a transaction. While a transaction is active all calls to
|
|
||||||
* [PersistenceCapability.persist](@link PersistenceCapability#persist)
|
|
||||||
* will be queued until [commit]{@link #commit} or [cancel]{@link
|
|
||||||
* #cancel} are called
|
|
||||||
*/
|
|
||||||
TransactionService.prototype.startTransaction = function () {
|
|
||||||
var transaction = this.isActive()
|
|
||||||
? new NestedTransaction(this.transactions[0])
|
|
||||||
: new Transaction(this.$log);
|
|
||||||
|
|
||||||
this.transactions.push(transaction);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @returns {boolean} If true, indicates that a transaction is in progress
|
|
||||||
*/
|
|
||||||
TransactionService.prototype.isActive = function () {
|
|
||||||
return this.transactions.length > 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds provided functions to a queue to be called on
|
|
||||||
* [.commit()]{@link #commit} or
|
|
||||||
* [.cancel()]{@link #commit}
|
|
||||||
* @param onCommit A function to call on commit
|
|
||||||
* @param onCancel A function to call on cancel
|
|
||||||
*/
|
|
||||||
TransactionService.prototype.addToTransaction = function (onCommit, onCancel) {
|
|
||||||
if (this.isActive()) {
|
|
||||||
return this.activeTransaction().add(onCommit, onCancel);
|
|
||||||
} else {
|
|
||||||
//Log error because this is a programming error if it occurs.
|
|
||||||
this.$log.error("No transaction in progress");
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the transaction at the top of the stack.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
TransactionService.prototype.activeTransaction = function () {
|
|
||||||
return this.transactions[this.transactions.length - 1];
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* All persist calls deferred since the beginning of the transaction
|
|
||||||
* will be committed. If this is the last transaction, clears the
|
|
||||||
* cache.
|
|
||||||
*
|
|
||||||
* @returns {Promise} resolved when all persist operations have
|
|
||||||
* completed. Will reject if any commit operations fail
|
|
||||||
*/
|
|
||||||
TransactionService.prototype.commit = function () {
|
|
||||||
var transaction = this.transactions.pop();
|
|
||||||
if (!transaction) {
|
|
||||||
return Promise.reject();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!this.isActive()) {
|
|
||||||
return transaction.commit()
|
|
||||||
.then(function (r) {
|
|
||||||
this.cacheService.flush();
|
|
||||||
|
|
||||||
return r;
|
|
||||||
}.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
return transaction.commit();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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 transaction = this.transactions.pop();
|
|
||||||
|
|
||||||
return transaction ? transaction.cancel() : Promise.reject();
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the size (the number of commit/cancel callbacks) of
|
|
||||||
* the active transaction.
|
|
||||||
* @returns {number} size of the active transaction
|
|
||||||
*/
|
|
||||||
TransactionService.prototype.size = function () {
|
|
||||||
return this.isActive() ? this.activeTransaction().size() : 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
return TransactionService;
|
|
||||||
});
|
|
@ -1,192 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(
|
|
||||||
["../../src/capabilities/EditorCapability"],
|
|
||||||
function (EditorCapability) {
|
|
||||||
|
|
||||||
xdescribe("The editor capability", function () {
|
|
||||||
var mockDomainObject,
|
|
||||||
capabilities,
|
|
||||||
mockParentObject,
|
|
||||||
mockTransactionService,
|
|
||||||
mockStatusCapability,
|
|
||||||
mockParentStatus,
|
|
||||||
mockContextCapability,
|
|
||||||
capability;
|
|
||||||
|
|
||||||
function fastPromise(val) {
|
|
||||||
return {
|
|
||||||
then: function (callback) {
|
|
||||||
return callback(val);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
|
||||||
"domainObject",
|
|
||||||
["getId", "getModel", "hasCapability", "getCapability", "useCapability"]
|
|
||||||
);
|
|
||||||
mockParentObject = jasmine.createSpyObj(
|
|
||||||
"domainObject",
|
|
||||||
["getId", "getModel", "hasCapability", "getCapability", "useCapability"]
|
|
||||||
);
|
|
||||||
mockTransactionService = jasmine.createSpyObj(
|
|
||||||
"transactionService",
|
|
||||||
[
|
|
||||||
"startTransaction",
|
|
||||||
"size",
|
|
||||||
"commit",
|
|
||||||
"cancel"
|
|
||||||
]
|
|
||||||
);
|
|
||||||
mockTransactionService.commit.and.returnValue(fastPromise());
|
|
||||||
mockTransactionService.cancel.and.returnValue(fastPromise());
|
|
||||||
mockTransactionService.isActive = jasmine.createSpy('isActive');
|
|
||||||
|
|
||||||
mockStatusCapability = jasmine.createSpyObj(
|
|
||||||
"statusCapability",
|
|
||||||
["get", "set"]
|
|
||||||
);
|
|
||||||
mockParentStatus = jasmine.createSpyObj(
|
|
||||||
"statusCapability",
|
|
||||||
["get", "set"]
|
|
||||||
);
|
|
||||||
mockContextCapability = jasmine.createSpyObj(
|
|
||||||
"contextCapability",
|
|
||||||
["getParent"]
|
|
||||||
);
|
|
||||||
mockContextCapability.getParent.and.returnValue(mockParentObject);
|
|
||||||
|
|
||||||
capabilities = {
|
|
||||||
context: mockContextCapability,
|
|
||||||
status: mockStatusCapability
|
|
||||||
};
|
|
||||||
|
|
||||||
mockDomainObject.hasCapability.and.callFake(function (name) {
|
|
||||||
return capabilities[name] !== undefined;
|
|
||||||
});
|
|
||||||
|
|
||||||
mockDomainObject.getCapability.and.callFake(function (name) {
|
|
||||||
return capabilities[name];
|
|
||||||
});
|
|
||||||
|
|
||||||
mockParentObject.getCapability.and.returnValue(mockParentStatus);
|
|
||||||
mockParentObject.hasCapability.and.returnValue(false);
|
|
||||||
|
|
||||||
capability = new EditorCapability(
|
|
||||||
mockTransactionService,
|
|
||||||
mockDomainObject
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("starts a transaction when edit is invoked", function () {
|
|
||||||
capability.edit();
|
|
||||||
expect(mockTransactionService.startTransaction).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("sets editing status on object", function () {
|
|
||||||
capability.edit();
|
|
||||||
expect(mockStatusCapability.set).toHaveBeenCalledWith("editing", true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("uses editing status to determine editing context root", function () {
|
|
||||||
capability.edit();
|
|
||||||
mockStatusCapability.get.and.returnValue(false);
|
|
||||||
expect(capability.isEditContextRoot()).toBe(false);
|
|
||||||
mockStatusCapability.get.and.returnValue(true);
|
|
||||||
expect(capability.isEditContextRoot()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("inEditingContext returns true if parent object is being"
|
|
||||||
+ " edited", function () {
|
|
||||||
mockStatusCapability.get.and.returnValue(false);
|
|
||||||
mockParentStatus.get.and.returnValue(false);
|
|
||||||
expect(capability.inEditContext()).toBe(false);
|
|
||||||
mockParentStatus.get.and.returnValue(true);
|
|
||||||
expect(capability.inEditContext()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("save", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
capability.edit();
|
|
||||||
capability.save();
|
|
||||||
});
|
|
||||||
it("commits the transaction", function () {
|
|
||||||
expect(mockTransactionService.commit).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("begins a new transaction", function () {
|
|
||||||
expect(mockTransactionService.startTransaction).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("finish", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
mockTransactionService.isActive.and.returnValue(true);
|
|
||||||
capability.edit();
|
|
||||||
capability.finish();
|
|
||||||
});
|
|
||||||
it("cancels the transaction", function () {
|
|
||||||
expect(mockTransactionService.cancel).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
it("resets the edit state", function () {
|
|
||||||
expect(mockStatusCapability.set).toHaveBeenCalledWith('editing', false);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("finish", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
mockTransactionService.isActive.and.returnValue(false);
|
|
||||||
capability.edit();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not cancel transaction when transaction is not active", function () {
|
|
||||||
capability.finish();
|
|
||||||
expect(mockTransactionService.cancel).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns a promise", function () {
|
|
||||||
expect(capability.finish() instanceof Promise).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("dirty", function () {
|
|
||||||
var model = {};
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockDomainObject.getModel.and.returnValue(model);
|
|
||||||
capability.edit();
|
|
||||||
capability.finish();
|
|
||||||
});
|
|
||||||
it("returns true if the object has been modified since it"
|
|
||||||
+ " was last persisted", function () {
|
|
||||||
mockTransactionService.size.and.returnValue(0);
|
|
||||||
expect(capability.dirty()).toBe(false);
|
|
||||||
mockTransactionService.size.and.returnValue(1);
|
|
||||||
expect(capability.dirty()).toBe(true);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,111 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(
|
|
||||||
[
|
|
||||||
"../../src/capabilities/TransactionalPersistenceCapability"
|
|
||||||
],
|
|
||||||
function (TransactionalPersistenceCapability) {
|
|
||||||
|
|
||||||
function fastPromise(val) {
|
|
||||||
return {
|
|
||||||
then: function (callback) {
|
|
||||||
return callback(val);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
describe("The transactional persistence decorator", function () {
|
|
||||||
var mockQ,
|
|
||||||
mockTransactionManager,
|
|
||||||
mockPersistence,
|
|
||||||
mockDomainObject,
|
|
||||||
testId,
|
|
||||||
capability;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
testId = "test-id";
|
|
||||||
|
|
||||||
mockQ = jasmine.createSpyObj("$q", ["when"]);
|
|
||||||
mockQ.when.and.callFake(function (val) {
|
|
||||||
return fastPromise(val);
|
|
||||||
});
|
|
||||||
mockTransactionManager = jasmine.createSpyObj(
|
|
||||||
"transactionService",
|
|
||||||
["isActive", "addToTransaction", "clearTransactionsFor"]
|
|
||||||
);
|
|
||||||
mockPersistence = jasmine.createSpyObj(
|
|
||||||
"persistenceCapability",
|
|
||||||
["persist", "refresh", "getSpace"]
|
|
||||||
);
|
|
||||||
mockPersistence.persist.and.returnValue(fastPromise());
|
|
||||||
mockPersistence.refresh.and.returnValue(fastPromise());
|
|
||||||
|
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
|
||||||
"domainObject",
|
|
||||||
["getModel", "getId"]
|
|
||||||
);
|
|
||||||
mockDomainObject.getModel.and.returnValue({persisted: 1});
|
|
||||||
mockDomainObject.getId.and.returnValue(testId);
|
|
||||||
|
|
||||||
capability = new TransactionalPersistenceCapability(
|
|
||||||
mockQ,
|
|
||||||
mockTransactionManager,
|
|
||||||
mockPersistence,
|
|
||||||
mockDomainObject
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("if no transaction is active, passes through to persistence"
|
|
||||||
+ " provider", function () {
|
|
||||||
mockTransactionManager.isActive.and.returnValue(false);
|
|
||||||
capability.persist();
|
|
||||||
expect(mockPersistence.persist).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("if transaction is active, persist and cancel calls are"
|
|
||||||
+ " queued", function () {
|
|
||||||
mockTransactionManager.isActive.and.returnValue(true);
|
|
||||||
capability.persist();
|
|
||||||
expect(mockTransactionManager.addToTransaction).toHaveBeenCalled();
|
|
||||||
mockTransactionManager.addToTransaction.calls.mostRecent().args[1]();
|
|
||||||
expect(mockPersistence.persist).toHaveBeenCalled();
|
|
||||||
mockTransactionManager.addToTransaction.calls.mostRecent().args[2]();
|
|
||||||
expect(mockPersistence.refresh).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("wraps getSpace", function () {
|
|
||||||
mockPersistence.getSpace.and.returnValue('foo');
|
|
||||||
expect(capability.getSpace()).toEqual('foo');
|
|
||||||
});
|
|
||||||
|
|
||||||
it("clears transactions and delegates refresh calls", function () {
|
|
||||||
capability.refresh();
|
|
||||||
expect(mockTransactionManager.clearTransactionsFor)
|
|
||||||
.toHaveBeenCalledWith(testId);
|
|
||||||
expect(mockPersistence.refresh)
|
|
||||||
.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,75 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(["../../src/services/NestedTransaction"], function (NestedTransaction) {
|
|
||||||
var TRANSACTION_METHODS = ['add', 'commit', 'cancel', 'size'];
|
|
||||||
|
|
||||||
describe("A NestedTransaction", function () {
|
|
||||||
var mockTransaction,
|
|
||||||
nestedTransaction;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockTransaction =
|
|
||||||
jasmine.createSpyObj('transaction', TRANSACTION_METHODS);
|
|
||||||
nestedTransaction = new NestedTransaction(mockTransaction);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("exposes a Transaction's interface", function () {
|
|
||||||
TRANSACTION_METHODS.forEach(function (method) {
|
|
||||||
expect(nestedTransaction[method])
|
|
||||||
.toEqual(jasmine.any(Function));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when callbacks are added", function () {
|
|
||||||
var mockCommit,
|
|
||||||
mockCancel;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockCommit = jasmine.createSpy('commit');
|
|
||||||
mockCancel = jasmine.createSpy('cancel');
|
|
||||||
nestedTransaction.add(mockCommit, mockCancel);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not interact with its parent transaction", function () {
|
|
||||||
TRANSACTION_METHODS.forEach(function (method) {
|
|
||||||
expect(mockTransaction[method])
|
|
||||||
.not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("and the transaction is committed", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
nestedTransaction.commit();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("adds to its parent transaction", function () {
|
|
||||||
expect(mockTransaction.add).toHaveBeenCalledWith(
|
|
||||||
jasmine.any(Function),
|
|
||||||
jasmine.any(Function)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
@ -1,141 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(
|
|
||||||
["../../src/services/TransactionManager"],
|
|
||||||
function (TransactionManager) {
|
|
||||||
describe("TransactionManager", function () {
|
|
||||||
var mockTransactionService,
|
|
||||||
testId,
|
|
||||||
mockOnCommit,
|
|
||||||
mockOnCancel,
|
|
||||||
mockRemoves,
|
|
||||||
mockPromise,
|
|
||||||
manager;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockRemoves = [];
|
|
||||||
mockTransactionService = jasmine.createSpyObj(
|
|
||||||
"transactionService",
|
|
||||||
["addToTransaction", "isActive"]
|
|
||||||
);
|
|
||||||
mockOnCommit = jasmine.createSpy('commit');
|
|
||||||
mockOnCancel = jasmine.createSpy('cancel');
|
|
||||||
testId = 'test-id';
|
|
||||||
mockPromise = jasmine.createSpyObj('promise', ['then']);
|
|
||||||
|
|
||||||
mockOnCommit.and.returnValue(mockPromise);
|
|
||||||
mockOnCancel.and.returnValue(mockPromise);
|
|
||||||
|
|
||||||
mockTransactionService.addToTransaction.and.callFake(function () {
|
|
||||||
var mockRemove =
|
|
||||||
jasmine.createSpy('remove-' + mockRemoves.length);
|
|
||||||
mockRemoves.push(mockRemove);
|
|
||||||
|
|
||||||
return mockRemove;
|
|
||||||
});
|
|
||||||
|
|
||||||
manager = new TransactionManager(mockTransactionService);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("delegates isActive calls", function () {
|
|
||||||
[false, true].forEach(function (state) {
|
|
||||||
mockTransactionService.isActive.and.returnValue(state);
|
|
||||||
expect(manager.isActive()).toBe(state);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when addToTransaction is called", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
manager.addToTransaction(
|
|
||||||
testId,
|
|
||||||
mockOnCommit,
|
|
||||||
mockOnCancel
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("adds callbacks to the active transaction", function () {
|
|
||||||
expect(mockTransactionService.addToTransaction)
|
|
||||||
.toHaveBeenCalledWith(
|
|
||||||
jasmine.any(Function),
|
|
||||||
jasmine.any(Function)
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("invokes passed-in callbacks from its own callbacks", function () {
|
|
||||||
expect(mockOnCommit).not.toHaveBeenCalled();
|
|
||||||
mockTransactionService.addToTransaction
|
|
||||||
.calls.mostRecent().args[0]();
|
|
||||||
expect(mockOnCommit).toHaveBeenCalled();
|
|
||||||
|
|
||||||
expect(mockOnCancel).not.toHaveBeenCalled();
|
|
||||||
mockTransactionService.addToTransaction
|
|
||||||
.calls.mostRecent().args[1]();
|
|
||||||
expect(mockOnCancel).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("Adds callbacks to transaction", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
spyOn(manager, 'clearTransactionsFor');
|
|
||||||
manager.clearTransactionsFor.and.callThrough();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("and clears pending calls if same object", function () {
|
|
||||||
manager.addToTransaction(
|
|
||||||
testId,
|
|
||||||
jasmine.createSpy(),
|
|
||||||
jasmine.createSpy()
|
|
||||||
);
|
|
||||||
expect(manager.clearTransactionsFor).toHaveBeenCalledWith(testId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("and does not clear pending calls if different object", function () {
|
|
||||||
manager.addToTransaction(
|
|
||||||
'other-id',
|
|
||||||
jasmine.createSpy(),
|
|
||||||
jasmine.createSpy()
|
|
||||||
);
|
|
||||||
expect(manager.clearTransactionsFor).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(function () {
|
|
||||||
expect(mockTransactionService.addToTransaction.calls.count()).toEqual(2);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not remove callbacks from the transaction", function () {
|
|
||||||
expect(mockRemoves[0]).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("and clearTransactionsFor is subsequently called", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
manager.clearTransactionsFor(testId);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("removes callbacks from the transaction", function () {
|
|
||||||
expect(mockRemoves[0]).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,139 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(
|
|
||||||
["../../src/services/TransactionService"],
|
|
||||||
function (TransactionService) {
|
|
||||||
|
|
||||||
describe("The Transaction Service", function () {
|
|
||||||
var mockQ,
|
|
||||||
mockLog,
|
|
||||||
mockCacheService,
|
|
||||||
transactionService;
|
|
||||||
|
|
||||||
function fastPromise(val) {
|
|
||||||
return {
|
|
||||||
then: function (callback) {
|
|
||||||
return fastPromise(callback(val));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockQ = jasmine.createSpyObj("$q", ["all"]);
|
|
||||||
mockCacheService = jasmine.createSpyObj("cacheService", ["flush"]);
|
|
||||||
mockQ.all.and.returnValue(fastPromise());
|
|
||||||
mockLog = jasmine.createSpyObj("$log", ["error"]);
|
|
||||||
transactionService = new TransactionService(mockQ, mockLog, mockCacheService);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("isActive returns true if a transaction is in progress", function () {
|
|
||||||
expect(transactionService.isActive()).toBe(false);
|
|
||||||
transactionService.startTransaction();
|
|
||||||
expect(transactionService.isActive()).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("addToTransaction queues onCommit and onCancel functions", function () {
|
|
||||||
var onCommit = jasmine.createSpy('onCommit'),
|
|
||||||
onCancel = jasmine.createSpy('onCancel');
|
|
||||||
|
|
||||||
transactionService.startTransaction();
|
|
||||||
transactionService.addToTransaction(onCommit, onCancel);
|
|
||||||
expect(transactionService.size()).toBe(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("size function returns size of commit and cancel queues", function () {
|
|
||||||
var onCommit = jasmine.createSpy('onCommit'),
|
|
||||||
onCancel = jasmine.createSpy('onCancel');
|
|
||||||
|
|
||||||
transactionService.startTransaction();
|
|
||||||
transactionService.addToTransaction(onCommit, onCancel);
|
|
||||||
transactionService.addToTransaction(onCommit, onCancel);
|
|
||||||
transactionService.addToTransaction(onCommit, onCancel);
|
|
||||||
expect(transactionService.size()).toBe(3);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("commit", function () {
|
|
||||||
var onCommits;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
onCommits = [0, 1, 2].map(function (val) {
|
|
||||||
return jasmine.createSpy("onCommit" + val);
|
|
||||||
});
|
|
||||||
|
|
||||||
transactionService.startTransaction();
|
|
||||||
onCommits.forEach(transactionService.addToTransaction.bind(transactionService));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("commit calls all queued commit functions", function () {
|
|
||||||
expect(transactionService.size()).toBe(3);
|
|
||||||
|
|
||||||
return transactionService.commit().then(() => {
|
|
||||||
onCommits.forEach(function (spy) {
|
|
||||||
expect(spy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("commit resets active state and clears queues", function () {
|
|
||||||
return transactionService.commit().then(() => {
|
|
||||||
expect(transactionService.isActive()).toBe(false);
|
|
||||||
expect(transactionService.size()).toBe(0);
|
|
||||||
expect(transactionService.size()).toBe(0);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("cancel", function () {
|
|
||||||
var onCancels;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
onCancels = [0, 1, 2].map(function (val) {
|
|
||||||
return jasmine.createSpy("onCancel" + val);
|
|
||||||
});
|
|
||||||
|
|
||||||
transactionService.startTransaction();
|
|
||||||
onCancels.forEach(function (onCancel) {
|
|
||||||
transactionService.addToTransaction(undefined, onCancel);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("cancel calls all queued cancel functions", function () {
|
|
||||||
expect(transactionService.size()).toBe(3);
|
|
||||||
transactionService.cancel();
|
|
||||||
onCancels.forEach(function (spy) {
|
|
||||||
expect(spy).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it("cancel resets active state and clears queues", function () {
|
|
||||||
transactionService.cancel();
|
|
||||||
expect(transactionService.isActive()).toBe(false);
|
|
||||||
expect(transactionService.size()).toBe(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,109 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(
|
|
||||||
["../../src/services/Transaction"],
|
|
||||||
function (Transaction) {
|
|
||||||
|
|
||||||
describe("A Transaction", function () {
|
|
||||||
var mockLog,
|
|
||||||
transaction;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockLog = jasmine.createSpyObj(
|
|
||||||
'$log',
|
|
||||||
['warn', 'info', 'error', 'debug']
|
|
||||||
);
|
|
||||||
transaction = new Transaction(mockLog);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("initially has a size of zero", function () {
|
|
||||||
expect(transaction.size()).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("when callbacks are added", function () {
|
|
||||||
var mockCommit,
|
|
||||||
mockCancel,
|
|
||||||
remove;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockCommit = jasmine.createSpy('commit');
|
|
||||||
mockCancel = jasmine.createSpy('cancel');
|
|
||||||
remove = transaction.add(mockCommit, mockCancel);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("reports a new size", function () {
|
|
||||||
expect(transaction.size()).toEqual(1);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns a function to remove those callbacks", function () {
|
|
||||||
expect(remove).toEqual(jasmine.any(Function));
|
|
||||||
remove();
|
|
||||||
expect(transaction.size()).toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("and the transaction is committed", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
transaction.commit();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("triggers the commit callback", function () {
|
|
||||||
expect(mockCommit).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not trigger the cancel callback", function () {
|
|
||||||
expect(mockCancel).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("and the transaction is cancelled", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
transaction.cancel();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("triggers the cancel callback", function () {
|
|
||||||
expect(mockCancel).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not trigger the commit callback", function () {
|
|
||||||
expect(mockCommit).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
describe("and an exception is encountered during commit", function () {
|
|
||||||
beforeEach(function () {
|
|
||||||
mockCommit.and.callFake(function () {
|
|
||||||
throw new Error("test error");
|
|
||||||
});
|
|
||||||
transaction.commit();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("logs an error", function () {
|
|
||||||
expect(mockLog.error).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
@ -45,7 +45,6 @@ define([
|
|||||||
"./src/capabilities/MutationCapability",
|
"./src/capabilities/MutationCapability",
|
||||||
"./src/capabilities/DelegationCapability",
|
"./src/capabilities/DelegationCapability",
|
||||||
"./src/capabilities/InstantiationCapability",
|
"./src/capabilities/InstantiationCapability",
|
||||||
"./src/runs/TransactingMutationListener",
|
|
||||||
"./src/services/Now",
|
"./src/services/Now",
|
||||||
"./src/services/Throttle",
|
"./src/services/Throttle",
|
||||||
"./src/services/Topic",
|
"./src/services/Topic",
|
||||||
@ -75,7 +74,6 @@ define([
|
|||||||
MutationCapability,
|
MutationCapability,
|
||||||
DelegationCapability,
|
DelegationCapability,
|
||||||
InstantiationCapability,
|
InstantiationCapability,
|
||||||
TransactingMutationListener,
|
|
||||||
Now,
|
Now,
|
||||||
Throttle,
|
Throttle,
|
||||||
Topic,
|
Topic,
|
||||||
@ -363,12 +361,6 @@ define([
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"runs": [
|
|
||||||
{
|
|
||||||
"implementation": TransactingMutationListener,
|
|
||||||
"depends": ["topic", "transactionService", "cacheService"]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"constants": [
|
"constants": [
|
||||||
{
|
{
|
||||||
"key": "PERSISTENCE_SPACE",
|
"key": "PERSISTENCE_SPACE",
|
||||||
|
@ -1,55 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define([], function () {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listens for mutation on domain objects and triggers persistence when
|
|
||||||
* it occurs.
|
|
||||||
* @param {Topic} topic the `topic` service; used to listen for mutation
|
|
||||||
* @memberof platform/core
|
|
||||||
*/
|
|
||||||
function TransactingMutationListener(
|
|
||||||
topic,
|
|
||||||
transactionService,
|
|
||||||
cacheService
|
|
||||||
) {
|
|
||||||
|
|
||||||
function hasChanged(domainObject) {
|
|
||||||
var model = domainObject.getModel();
|
|
||||||
|
|
||||||
return model.persisted === undefined || model.modified > model.persisted;
|
|
||||||
}
|
|
||||||
|
|
||||||
var mutationTopic = topic('mutation');
|
|
||||||
mutationTopic.listen(function (domainObject) {
|
|
||||||
var persistence = domainObject.getCapability('persistence');
|
|
||||||
cacheService.put(domainObject.getId(), domainObject.getModel());
|
|
||||||
|
|
||||||
if (hasChanged(domainObject)) {
|
|
||||||
persistence.persist();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
return TransactingMutationListener;
|
|
||||||
});
|
|
@ -1,112 +0,0 @@
|
|||||||
/*****************************************************************************
|
|
||||||
* Open MCT, Copyright (c) 2014-2021, United States Government
|
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
|
||||||
* Administration. All rights reserved.
|
|
||||||
*
|
|
||||||
* Open MCT 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 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.
|
|
||||||
*****************************************************************************/
|
|
||||||
|
|
||||||
define(
|
|
||||||
["../../src/runs/TransactingMutationListener"],
|
|
||||||
function (TransactingMutationListener) {
|
|
||||||
|
|
||||||
describe("TransactingMutationListener", function () {
|
|
||||||
var mockTopic,
|
|
||||||
mockMutationTopic,
|
|
||||||
mockCacheService,
|
|
||||||
mockTransactionService,
|
|
||||||
mockDomainObject,
|
|
||||||
mockModel,
|
|
||||||
mockPersistence;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
mockTopic = jasmine.createSpy('topic');
|
|
||||||
mockMutationTopic =
|
|
||||||
jasmine.createSpyObj('mutation', ['listen']);
|
|
||||||
mockCacheService =
|
|
||||||
jasmine.createSpyObj('cacheService', [
|
|
||||||
'put'
|
|
||||||
]);
|
|
||||||
mockTransactionService =
|
|
||||||
jasmine.createSpyObj('transactionService', [
|
|
||||||
'isActive',
|
|
||||||
'startTransaction',
|
|
||||||
'commit'
|
|
||||||
]);
|
|
||||||
mockDomainObject = jasmine.createSpyObj(
|
|
||||||
'domainObject',
|
|
||||||
['getId', 'getCapability', 'getModel']
|
|
||||||
);
|
|
||||||
mockPersistence = jasmine.createSpyObj(
|
|
||||||
'persistence',
|
|
||||||
['persist', 'refresh', 'persisted']
|
|
||||||
);
|
|
||||||
|
|
||||||
mockTopic.and.callFake(function (t) {
|
|
||||||
expect(t).toBe('mutation');
|
|
||||||
|
|
||||||
return mockMutationTopic;
|
|
||||||
});
|
|
||||||
|
|
||||||
mockDomainObject.getId.and.returnValue('mockId');
|
|
||||||
mockDomainObject.getCapability.and.callFake(function (c) {
|
|
||||||
expect(c).toBe('persistence');
|
|
||||||
|
|
||||||
return mockPersistence;
|
|
||||||
});
|
|
||||||
mockModel = {};
|
|
||||||
mockDomainObject.getModel.and.returnValue(mockModel);
|
|
||||||
|
|
||||||
mockPersistence.persisted.and.returnValue(true);
|
|
||||||
|
|
||||||
return new TransactingMutationListener(
|
|
||||||
mockTopic,
|
|
||||||
mockTransactionService,
|
|
||||||
mockCacheService
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("listens for mutation", function () {
|
|
||||||
expect(mockMutationTopic.listen)
|
|
||||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("calls persist if the model has changed", function () {
|
|
||||||
mockModel.persisted = Date.now();
|
|
||||||
|
|
||||||
//Mark the model dirty by setting the mutated date later than the last persisted date.
|
|
||||||
mockModel.modified = mockModel.persisted + 1;
|
|
||||||
|
|
||||||
mockMutationTopic.listen.calls.mostRecent()
|
|
||||||
.args[0](mockDomainObject);
|
|
||||||
|
|
||||||
expect(mockPersistence.persist).toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("does not call persist if the model has not changed", function () {
|
|
||||||
mockModel.persisted = Date.now();
|
|
||||||
|
|
||||||
mockModel.modified = mockModel.persisted;
|
|
||||||
|
|
||||||
mockMutationTopic.listen.calls.mostRecent()
|
|
||||||
.args[0](mockDomainObject);
|
|
||||||
|
|
||||||
expect(mockPersistence.persist).not.toHaveBeenCalled();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
@ -34,7 +34,6 @@ export default class Editor extends EventEmitter {
|
|||||||
* Initiate an editing session. This will start a transaction during
|
* Initiate an editing session. This will start a transaction during
|
||||||
* which any persist operations will be deferred until either save()
|
* which any persist operations will be deferred until either save()
|
||||||
* or finish() are called.
|
* or finish() are called.
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
edit() {
|
edit() {
|
||||||
if (this.editing === true) {
|
if (this.editing === true) {
|
||||||
@ -42,8 +41,8 @@ export default class Editor extends EventEmitter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.editing = true;
|
this.editing = true;
|
||||||
this.getTransactionService().startTransaction();
|
|
||||||
this.emit('isEditing', true);
|
this.emit('isEditing', true);
|
||||||
|
this.openmct.objects.startTransaction();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,41 +55,36 @@ export default class Editor extends EventEmitter {
|
|||||||
/**
|
/**
|
||||||
* Save any unsaved changes from this editing session. This will
|
* Save any unsaved changes from this editing session. This will
|
||||||
* end the current transaction.
|
* end the current transaction.
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
save() {
|
save() {
|
||||||
return this.getTransactionService().commit().then((result) => {
|
const transaction = this.openmct.objects.getActiveTransaction();
|
||||||
|
|
||||||
|
return transaction.commit()
|
||||||
|
.then(() => {
|
||||||
this.editing = false;
|
this.editing = false;
|
||||||
this.emit('isEditing', false);
|
this.emit('isEditing', false);
|
||||||
|
}).catch(error => {
|
||||||
return result;
|
|
||||||
}).catch((error) => {
|
|
||||||
throw error;
|
throw error;
|
||||||
|
}).finally(() => {
|
||||||
|
this.openmct.objects.endTransaction();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* End the currently active transaction and discard unsaved changes.
|
* End the currently active transaction and discard unsaved changes.
|
||||||
*
|
|
||||||
* @private
|
|
||||||
*/
|
*/
|
||||||
cancel() {
|
cancel() {
|
||||||
let cancelPromise = this.getTransactionService().cancel();
|
|
||||||
this.editing = false;
|
this.editing = false;
|
||||||
this.emit('isEditing', false);
|
this.emit('isEditing', false);
|
||||||
|
|
||||||
return cancelPromise;
|
return new Promise((resolve, reject) => {
|
||||||
}
|
const transaction = this.openmct.objects.getActiveTransaction();
|
||||||
|
transaction.cancel()
|
||||||
/**
|
.then(resolve)
|
||||||
* @private
|
.catch(reject)
|
||||||
*/
|
.finally(() => {
|
||||||
getTransactionService() {
|
this.openmct.objects.endTransaction();
|
||||||
if (!this.transactionService) {
|
});
|
||||||
this.transactionService = this.openmct.$injector.get('transactionService');
|
});
|
||||||
}
|
|
||||||
|
|
||||||
return this.transactionService;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -129,9 +129,7 @@ class MutableDomainObject {
|
|||||||
|
|
||||||
mutable.$observe('$_synchronize_model', (updatedObject) => {
|
mutable.$observe('$_synchronize_model', (updatedObject) => {
|
||||||
let clone = JSON.parse(JSON.stringify(updatedObject));
|
let clone = JSON.parse(JSON.stringify(updatedObject));
|
||||||
let deleted = _.difference(Object.keys(mutable), Object.keys(updatedObject));
|
utils.refresh(mutable, clone);
|
||||||
deleted.forEach((propertyName) => delete mutable[propertyName]);
|
|
||||||
Object.assign(mutable, clone);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return mutable;
|
return mutable;
|
||||||
|
@ -26,6 +26,7 @@ import RootRegistry from './RootRegistry';
|
|||||||
import RootObjectProvider from './RootObjectProvider';
|
import RootObjectProvider from './RootObjectProvider';
|
||||||
import EventEmitter from 'EventEmitter';
|
import EventEmitter from 'EventEmitter';
|
||||||
import InterceptorRegistry from './InterceptorRegistry';
|
import InterceptorRegistry from './InterceptorRegistry';
|
||||||
|
import Transaction from './Transaction';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Utilities for loading, saving, and manipulating domain objects.
|
* Utilities for loading, saving, and manipulating domain objects.
|
||||||
@ -34,12 +35,14 @@ import InterceptorRegistry from './InterceptorRegistry';
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
function ObjectAPI(typeRegistry, openmct) {
|
function ObjectAPI(typeRegistry, openmct) {
|
||||||
|
this.openmct = openmct;
|
||||||
|
|
||||||
this.typeRegistry = typeRegistry;
|
this.typeRegistry = typeRegistry;
|
||||||
this.eventEmitter = new EventEmitter();
|
this.eventEmitter = new EventEmitter();
|
||||||
this.providers = {};
|
this.providers = {};
|
||||||
this.rootRegistry = new RootRegistry();
|
this.rootRegistry = new RootRegistry();
|
||||||
this.injectIdentifierService = function () {
|
this.injectIdentifierService = function () {
|
||||||
this.identifierService = openmct.$injector.get("identifierService");
|
this.identifierService = this.openmct.$injector.get("identifierService");
|
||||||
};
|
};
|
||||||
|
|
||||||
this.rootProvider = new RootObjectProvider(this.rootRegistry);
|
this.rootProvider = new RootObjectProvider(this.rootRegistry);
|
||||||
@ -86,6 +89,14 @@ ObjectAPI.prototype.getProvider = function (identifier) {
|
|||||||
return this.providers[namespace] || this.fallbackProvider;
|
return this.providers[namespace] || this.fallbackProvider;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get an active transaction instance
|
||||||
|
* @returns {Transaction} a transaction object
|
||||||
|
*/
|
||||||
|
ObjectAPI.prototype.getActiveTransaction = function () {
|
||||||
|
return this.transaction;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the root-level object.
|
* Get the root-level object.
|
||||||
* @returns {Promise.<DomainObject>} a promise for the root object
|
* @returns {Promise.<DomainObject>} a promise for the root object
|
||||||
@ -323,6 +334,24 @@ ObjectAPI.prototype.save = function (domainObject) {
|
|||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* After entering into edit mode, creates a new instance of Transaction to keep track of changes in Objects
|
||||||
|
*/
|
||||||
|
ObjectAPI.prototype.startTransaction = function () {
|
||||||
|
if (this.isTransactionActive()) {
|
||||||
|
throw new Error("Unable to start new Transaction: Previous Transaction is active");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.transaction = new Transaction(this);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear instance of Transaction
|
||||||
|
*/
|
||||||
|
ObjectAPI.prototype.endTransaction = function () {
|
||||||
|
this.transaction = null;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a root-level object.
|
* Add a root-level object.
|
||||||
* @param {module:openmct.ObjectAPI~Identifier|function} an array of
|
* @param {module:openmct.ObjectAPI~Identifier|function} an array of
|
||||||
@ -412,6 +441,12 @@ ObjectAPI.prototype.mutate = function (domainObject, path, value) {
|
|||||||
//Destroy temporary mutable object
|
//Destroy temporary mutable object
|
||||||
this.destroyMutable(mutableDomainObject);
|
this.destroyMutable(mutableDomainObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (this.isTransactionActive()) {
|
||||||
|
this.transaction.add(domainObject);
|
||||||
|
} else {
|
||||||
|
this.save(domainObject);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -448,6 +483,23 @@ ObjectAPI.prototype._toMutable = function (object) {
|
|||||||
return mutableObject;
|
return mutableObject;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates a domain object based on its latest persisted state. Note that this will mutate the provided object.
|
||||||
|
* @param {module:openmct.DomainObject} domainObject an object to refresh from its persistence store
|
||||||
|
* @returns {Promise} the provided object, updated to reflect the latest persisted state of the object.
|
||||||
|
*/
|
||||||
|
ObjectAPI.prototype.refresh = async function (domainObject) {
|
||||||
|
const refreshedObject = await this.get(domainObject.identifier);
|
||||||
|
|
||||||
|
if (domainObject.isMutable) {
|
||||||
|
domainObject.$refresh(refreshedObject);
|
||||||
|
} else {
|
||||||
|
utils.refresh(domainObject, refreshedObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
return domainObject;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param module:openmct.ObjectAPI~Identifier identifier An object identifier
|
* @param module:openmct.ObjectAPI~Identifier identifier An object identifier
|
||||||
* @returns {boolean} true if the object can be mutated, otherwise returns false
|
* @returns {boolean} true if the object can be mutated, otherwise returns false
|
||||||
@ -524,6 +576,10 @@ ObjectAPI.prototype.isObjectPathToALink = function (domainObject, objectPath) {
|
|||||||
&& domainObject.location !== this.makeKeyString(objectPath[1].identifier);
|
&& domainObject.location !== this.makeKeyString(objectPath[1].identifier);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
ObjectAPI.prototype.isTransactionActive = function () {
|
||||||
|
return Boolean(this.transaction && this.openmct.editor.isEditing());
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Uniquely identifies a domain object.
|
* Uniquely identifies a domain object.
|
||||||
*
|
*
|
||||||
|
@ -26,6 +26,10 @@ describe("The Object API", () => {
|
|||||||
|
|
||||||
openmct.$injector.get.and.returnValue(mockIdentifierService);
|
openmct.$injector.get.and.returnValue(mockIdentifierService);
|
||||||
objectAPI = new ObjectAPI(typeRegistry, openmct);
|
objectAPI = new ObjectAPI(typeRegistry, openmct);
|
||||||
|
|
||||||
|
openmct.editor = {};
|
||||||
|
openmct.editor.isEditing = () => false;
|
||||||
|
|
||||||
mockDomainObject = {
|
mockDomainObject = {
|
||||||
identifier: {
|
identifier: {
|
||||||
namespace: TEST_NAMESPACE,
|
namespace: TEST_NAMESPACE,
|
||||||
@ -223,6 +227,28 @@ describe("The Object API", () => {
|
|||||||
expect(testObject.name).toBe(MUTATED_NAME);
|
expect(testObject.name).toBe(MUTATED_NAME);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('Provides a way of refreshing an object from the persistence store', () => {
|
||||||
|
const modifiedTestObject = JSON.parse(JSON.stringify(testObject));
|
||||||
|
const OTHER_ATTRIBUTE_VALUE = 'Modified value';
|
||||||
|
const NEW_ATTRIBUTE_VALUE = 'A new attribute';
|
||||||
|
modifiedTestObject.otherAttribute = OTHER_ATTRIBUTE_VALUE;
|
||||||
|
modifiedTestObject.newAttribute = NEW_ATTRIBUTE_VALUE;
|
||||||
|
delete modifiedTestObject.objectAttribute;
|
||||||
|
|
||||||
|
spyOn(objectAPI, 'get');
|
||||||
|
objectAPI.get.and.returnValue(Promise.resolve(modifiedTestObject));
|
||||||
|
|
||||||
|
expect(objectAPI.get).not.toHaveBeenCalled();
|
||||||
|
|
||||||
|
return objectAPI.refresh(testObject).then(() => {
|
||||||
|
expect(objectAPI.get).toHaveBeenCalledWith(testObject.identifier);
|
||||||
|
|
||||||
|
expect(testObject.otherAttribute).toEqual(OTHER_ATTRIBUTE_VALUE);
|
||||||
|
expect(testObject.newAttribute).toEqual(NEW_ATTRIBUTE_VALUE);
|
||||||
|
expect(testObject.objectAttribute).not.toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe ('uses a MutableDomainObject', () => {
|
describe ('uses a MutableDomainObject', () => {
|
||||||
it('and retains properties of original object ', function () {
|
it('and retains properties of original object ', function () {
|
||||||
expect(hasOwnProperty(mutable, 'identifier')).toBe(true);
|
expect(hasOwnProperty(mutable, 'identifier')).toBe(true);
|
||||||
|
@ -20,35 +20,52 @@
|
|||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
define(
|
export default class Transaction {
|
||||||
[
|
constructor(objectAPI) {
|
||||||
"../../src/capabilities/TransactionalPersistenceCapability",
|
this.dirtyObjects = new Set();
|
||||||
"../../src/capabilities/TransactionCapabilityDecorator"
|
this.objectAPI = objectAPI;
|
||||||
],
|
}
|
||||||
function (TransactionalPersistenceCapability, TransactionCapabilityDecorator) {
|
|
||||||
|
|
||||||
describe("The transaction capability decorator", function () {
|
add(object) {
|
||||||
var mockQ,
|
this.dirtyObjects.add(object);
|
||||||
mockTransactionService,
|
}
|
||||||
mockCapabilityService,
|
|
||||||
provider;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
cancel() {
|
||||||
mockQ = {};
|
return this._clear();
|
||||||
mockTransactionService = {};
|
}
|
||||||
mockCapabilityService = jasmine.createSpyObj("capabilityService", ["getCapabilities"]);
|
|
||||||
mockCapabilityService.getCapabilities.and.returnValue({
|
commit() {
|
||||||
persistence: function () {}
|
const promiseArray = [];
|
||||||
|
const save = this.objectAPI.save.bind(this.objectAPI);
|
||||||
|
this.dirtyObjects.forEach(object => {
|
||||||
|
promiseArray.push(this.createDirtyObjectPromise(object, save));
|
||||||
});
|
});
|
||||||
|
|
||||||
provider = new TransactionCapabilityDecorator(mockQ, mockTransactionService, mockCapabilityService);
|
return Promise.all(promiseArray);
|
||||||
|
}
|
||||||
|
|
||||||
|
createDirtyObjectPromise(object, action) {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
action(object)
|
||||||
|
.then(resolve)
|
||||||
|
.catch(reject)
|
||||||
|
.finally(() => {
|
||||||
|
this.dirtyObjects.delete(object);
|
||||||
});
|
});
|
||||||
it("decorates the persistence capability", function () {
|
|
||||||
var capabilities = provider.getCapabilities();
|
|
||||||
expect(capabilities.persistence({}) instanceof TransactionalPersistenceCapability).toBe(true);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
start() {
|
||||||
|
this.dirtyObjects = new Set();
|
||||||
|
}
|
||||||
|
|
||||||
|
_clear() {
|
||||||
|
const promiseArray = [];
|
||||||
|
const refresh = this.objectAPI.refresh.bind(this.objectAPI);
|
||||||
|
this.dirtyObjects.forEach(object => {
|
||||||
|
promiseArray.push(this.createDirtyObjectPromise(object, refresh));
|
||||||
|
});
|
||||||
|
|
||||||
|
return Promise.all(promiseArray);
|
||||||
|
}
|
||||||
|
}
|
@ -165,12 +165,19 @@ define([
|
|||||||
return identifierEquals(a.identifier, b.identifier);
|
return identifierEquals(a.identifier, b.identifier);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function refresh(oldObject, newObject) {
|
||||||
|
let deleted = _.difference(Object.keys(oldObject), Object.keys(newObject));
|
||||||
|
deleted.forEach((propertyName) => delete oldObject[propertyName]);
|
||||||
|
Object.assign(oldObject, newObject);
|
||||||
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
toOldFormat: toOldFormat,
|
toOldFormat: toOldFormat,
|
||||||
toNewFormat: toNewFormat,
|
toNewFormat: toNewFormat,
|
||||||
makeKeyString: makeKeyString,
|
makeKeyString: makeKeyString,
|
||||||
parseKeyString: parseKeyString,
|
parseKeyString: parseKeyString,
|
||||||
equals: objectEquals,
|
equals: objectEquals,
|
||||||
identifierEquals: identifierEquals
|
identifierEquals: identifierEquals,
|
||||||
|
refresh: refresh
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
@ -148,10 +148,14 @@ describe("Notebook plugin:", () => {
|
|||||||
'observe'
|
'observe'
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
openmct.editor = {};
|
||||||
|
openmct.editor.isEditing = () => false;
|
||||||
|
|
||||||
const applicableViews = openmct.objectViews.get(notebookViewObject, [notebookViewObject]);
|
const applicableViews = openmct.objectViews.get(notebookViewObject, [notebookViewObject]);
|
||||||
notebookViewProvider = applicableViews.find(viewProvider => viewProvider.key === 'notebook-vue');
|
notebookViewProvider = applicableViews.find(viewProvider => viewProvider.key === 'notebook-vue');
|
||||||
|
|
||||||
testObjectProvider.get.and.returnValue(Promise.resolve(notebookViewObject));
|
testObjectProvider.get.and.returnValue(Promise.resolve(notebookViewObject));
|
||||||
|
testObjectProvider.create.and.returnValue(Promise.resolve(notebookViewObject));
|
||||||
openmct.objects.addProvider('test-namespace', testObjectProvider);
|
openmct.objects.addProvider('test-namespace', testObjectProvider);
|
||||||
testObjectProvider.observe.and.returnValue(() => {});
|
testObjectProvider.observe.and.returnValue(() => {});
|
||||||
|
|
||||||
|
@ -110,8 +110,7 @@ export default class Snapshot {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return () => {
|
return () => {
|
||||||
const path = window.location.href.split('#');
|
window.location.href = window.location.origin + url;
|
||||||
window.location.href = path[0] + url;
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,7 @@ const notebookDomainObject = {
|
|||||||
namespace: ''
|
namespace: ''
|
||||||
},
|
},
|
||||||
type: 'notebook',
|
type: 'notebook',
|
||||||
|
name: 'Test Notebook',
|
||||||
configuration: {
|
configuration: {
|
||||||
defaultSort: 'oldest',
|
defaultSort: 'oldest',
|
||||||
entries: notebookEntries,
|
entries: notebookEntries,
|
||||||
@ -118,6 +119,12 @@ describe('Notebook Entries:', () => {
|
|||||||
'create',
|
'create',
|
||||||
'update'
|
'update'
|
||||||
]));
|
]));
|
||||||
|
openmct.editor = {
|
||||||
|
isEditing: () => false
|
||||||
|
};
|
||||||
|
openmct.objects.isPersistable = () => true;
|
||||||
|
openmct.objects.save = () => Promise.resolve(true);
|
||||||
|
|
||||||
window.localStorage.setItem('notebook-storage', null);
|
window.localStorage.setItem('notebook-storage', null);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user