mirror of
https://github.com/nasa/openmct.git
synced 2025-06-11 03:41:37 +00:00
Rewrite local storage (#4583)
* Reimplementation of Local Storage provider * Added tests * Remove identifierService mocks from all test specs * Do not persist identifiers in couch * Constant rename * Fix broken test * Clean up mock window functions * Updated copyright notice * Fixed bug in in-memory search indexer
This commit is contained in:
parent
fd0e89ca05
commit
2d64813a4f
@ -1,9 +0,0 @@
|
|||||||
# Local Storage Plugin
|
|
||||||
Provides persistence of user-created objects in browser Local Storage. Objects persisted in this way will only be
|
|
||||||
available from the browser and machine on which they were persisted. For shared persistence, consider the
|
|
||||||
[Elasticsearch](../elastic/) and [CouchDB](../couch/) persistence plugins.
|
|
||||||
|
|
||||||
## Installation
|
|
||||||
```js
|
|
||||||
openmct.install(openmct.plugins.LocalStorage());
|
|
||||||
```
|
|
@ -1,61 +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/LocalStoragePersistenceProvider",
|
|
||||||
"./src/LocalStorageIndicator"
|
|
||||||
], function (
|
|
||||||
LocalStoragePersistenceProvider,
|
|
||||||
LocalStorageIndicator
|
|
||||||
) {
|
|
||||||
|
|
||||||
return {
|
|
||||||
name: "platform/persistence/local",
|
|
||||||
definition: {
|
|
||||||
"extensions": {
|
|
||||||
"components": [
|
|
||||||
{
|
|
||||||
"provides": "persistenceService",
|
|
||||||
"type": "provider",
|
|
||||||
"implementation": LocalStoragePersistenceProvider,
|
|
||||||
"depends": [
|
|
||||||
"$window",
|
|
||||||
"$q",
|
|
||||||
"PERSISTENCE_SPACE"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"constants": [
|
|
||||||
{
|
|
||||||
"key": "PERSISTENCE_SPACE",
|
|
||||||
"value": "mct"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"indicators": [
|
|
||||||
{
|
|
||||||
"implementation": LocalStorageIndicator
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
});
|
|
@ -1,61 +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 () {
|
|
||||||
|
|
||||||
var LOCAL_STORAGE_WARNING = [
|
|
||||||
"Using browser local storage for persistence.",
|
|
||||||
"Anything you create or change will only be saved",
|
|
||||||
"in this browser on this machine."
|
|
||||||
].join(' ');
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicator for local storage persistence. Provides a minimum
|
|
||||||
* level of feedback indicating that local storage is in use.
|
|
||||||
* @constructor
|
|
||||||
* @memberof platform/persistence/local
|
|
||||||
* @implements {Indicator}
|
|
||||||
*/
|
|
||||||
function LocalStorageIndicator() {
|
|
||||||
}
|
|
||||||
|
|
||||||
LocalStorageIndicator.prototype.getCssClass = function () {
|
|
||||||
return "c-indicator--clickable icon-suitcase s-status-caution";
|
|
||||||
};
|
|
||||||
|
|
||||||
LocalStorageIndicator.prototype.getGlyphClass = function () {
|
|
||||||
return 'caution';
|
|
||||||
};
|
|
||||||
|
|
||||||
LocalStorageIndicator.prototype.getText = function () {
|
|
||||||
return "Off-line storage";
|
|
||||||
};
|
|
||||||
|
|
||||||
LocalStorageIndicator.prototype.getDescription = function () {
|
|
||||||
return LOCAL_STORAGE_WARNING;
|
|
||||||
};
|
|
||||||
|
|
||||||
return LocalStorageIndicator;
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,97 +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 () {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The LocalStoragePersistenceProvider reads and writes JSON documents
|
|
||||||
* (more specifically, domain object models) to/from the browser's
|
|
||||||
* local storage.
|
|
||||||
* @memberof platform/persistence/local
|
|
||||||
* @constructor
|
|
||||||
* @implements {PersistenceService}
|
|
||||||
* @param q Angular's $q, for promises
|
|
||||||
* @param $interval Angular's $interval service
|
|
||||||
* @param {string} space the name of the persistence space being served
|
|
||||||
*/
|
|
||||||
function LocalStoragePersistenceProvider($window, $q, space) {
|
|
||||||
this.$q = $q;
|
|
||||||
this.space = space;
|
|
||||||
this.spaces = space ? [space] : [];
|
|
||||||
this.localStorage = $window.localStorage;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set a value in local storage.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
LocalStoragePersistenceProvider.prototype.setValue = function (key, value) {
|
|
||||||
this.localStorage[key] = JSON.stringify(value);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get a value from local storage.
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
LocalStoragePersistenceProvider.prototype.getValue = function (key) {
|
|
||||||
return this.localStorage[key]
|
|
||||||
? JSON.parse(this.localStorage[key]) : {};
|
|
||||||
};
|
|
||||||
|
|
||||||
LocalStoragePersistenceProvider.prototype.listSpaces = function () {
|
|
||||||
return this.$q.when(this.spaces);
|
|
||||||
};
|
|
||||||
|
|
||||||
LocalStoragePersistenceProvider.prototype.listObjects = function (space) {
|
|
||||||
return this.$q.when(Object.keys(this.getValue(space)));
|
|
||||||
};
|
|
||||||
|
|
||||||
LocalStoragePersistenceProvider.prototype.createObject = function (space, key, value) {
|
|
||||||
var spaceObj = this.getValue(space);
|
|
||||||
spaceObj[key] = value;
|
|
||||||
this.setValue(space, spaceObj);
|
|
||||||
|
|
||||||
return this.$q.when(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
LocalStoragePersistenceProvider.prototype.readObject = function (space, key) {
|
|
||||||
var spaceObj = this.getValue(space);
|
|
||||||
|
|
||||||
return this.$q.when(spaceObj[key]);
|
|
||||||
};
|
|
||||||
|
|
||||||
LocalStoragePersistenceProvider.prototype.deleteObject = function (space, key) {
|
|
||||||
var spaceObj = this.getValue(space);
|
|
||||||
delete spaceObj[key];
|
|
||||||
this.setValue(space, spaceObj);
|
|
||||||
|
|
||||||
return this.$q.when(true);
|
|
||||||
};
|
|
||||||
|
|
||||||
LocalStoragePersistenceProvider.prototype.updateObject =
|
|
||||||
LocalStoragePersistenceProvider.prototype.createObject;
|
|
||||||
|
|
||||||
return LocalStoragePersistenceProvider;
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,58 +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/LocalStorageIndicator"],
|
|
||||||
function (LocalStorageIndicator) {
|
|
||||||
|
|
||||||
xdescribe("The local storage status indicator", function () {
|
|
||||||
var indicator;
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
indicator = new LocalStorageIndicator();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("provides text to display in status area", function () {
|
|
||||||
// Don't particularly care what is there so long
|
|
||||||
// as interface is appropriately implemented.
|
|
||||||
expect(indicator.getText()).toEqual(jasmine.any(String));
|
|
||||||
});
|
|
||||||
|
|
||||||
it("has a database icon", function () {
|
|
||||||
expect(indicator.getCssClass()).toEqual("icon-suitcase s-status-caution");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("has a 'caution' class to draw attention", function () {
|
|
||||||
expect(indicator.getGlyphClass()).toEqual("caution");
|
|
||||||
});
|
|
||||||
|
|
||||||
it("provides a description for a tooltip", function () {
|
|
||||||
// Just want some non-empty string here. Providing a
|
|
||||||
// message here is important but don't want to test wording.
|
|
||||||
var description = indicator.getDescription();
|
|
||||||
expect(description).toEqual(jasmine.any(String));
|
|
||||||
expect(description.length).not.toEqual(0);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
@ -1,113 +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/LocalStoragePersistenceProvider"],
|
|
||||||
function (LocalStoragePersistenceProvider) {
|
|
||||||
|
|
||||||
describe("The local storage persistence provider", function () {
|
|
||||||
var mockQ,
|
|
||||||
testSpace = "testSpace",
|
|
||||||
mockCallback,
|
|
||||||
testLocalStorage,
|
|
||||||
provider;
|
|
||||||
|
|
||||||
function mockPromise(value) {
|
|
||||||
return (value || {}).then ? value : {
|
|
||||||
then: function (callback) {
|
|
||||||
return mockPromise(callback(value));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
beforeEach(function () {
|
|
||||||
testLocalStorage = {};
|
|
||||||
|
|
||||||
mockQ = jasmine.createSpyObj("$q", ["when", "reject"]);
|
|
||||||
mockCallback = jasmine.createSpy('callback');
|
|
||||||
|
|
||||||
mockQ.when.and.callFake(mockPromise);
|
|
||||||
|
|
||||||
provider = new LocalStoragePersistenceProvider(
|
|
||||||
{ localStorage: testLocalStorage },
|
|
||||||
mockQ,
|
|
||||||
testSpace
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("reports available spaces", function () {
|
|
||||||
provider.listSpaces().then(mockCallback);
|
|
||||||
expect(mockCallback).toHaveBeenCalledWith([testSpace]);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("lists all available documents", function () {
|
|
||||||
provider.listObjects(testSpace).then(mockCallback);
|
|
||||||
expect(mockCallback.calls.mostRecent().args[0]).toEqual([]);
|
|
||||||
provider.createObject(testSpace, 'abc', { a: 42 });
|
|
||||||
provider.listObjects(testSpace).then(mockCallback);
|
|
||||||
expect(mockCallback.calls.mostRecent().args[0]).toEqual(['abc']);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("allows object creation", function () {
|
|
||||||
var model = { someKey: "some value" };
|
|
||||||
provider.createObject(testSpace, "abc", model)
|
|
||||||
.then(mockCallback);
|
|
||||||
expect(JSON.parse(testLocalStorage[testSpace]).abc)
|
|
||||||
.toEqual(model);
|
|
||||||
expect(mockCallback.calls.mostRecent().args[0]).toBeTruthy();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("allows object models to be read back", function () {
|
|
||||||
var model = { someKey: "some other value" };
|
|
||||||
testLocalStorage[testSpace] = JSON.stringify({ abc: model });
|
|
||||||
provider.readObject(testSpace, "abc").then(mockCallback);
|
|
||||||
expect(mockCallback).toHaveBeenCalledWith(model);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("allows object update", function () {
|
|
||||||
var model = { someKey: "some new value" };
|
|
||||||
testLocalStorage[testSpace] = JSON.stringify({
|
|
||||||
abc: { somethingElse: 42 }
|
|
||||||
});
|
|
||||||
provider.updateObject(testSpace, "abc", model)
|
|
||||||
.then(mockCallback);
|
|
||||||
expect(JSON.parse(testLocalStorage[testSpace]).abc)
|
|
||||||
.toEqual(model);
|
|
||||||
});
|
|
||||||
|
|
||||||
it("allows object deletion", function () {
|
|
||||||
testLocalStorage[testSpace] = JSON.stringify({
|
|
||||||
abc: { somethingElse: 42 }
|
|
||||||
});
|
|
||||||
provider.deleteObject(testSpace, "abc").then(mockCallback);
|
|
||||||
expect(testLocalStorage[testSpace].abc)
|
|
||||||
.toBeUndefined();
|
|
||||||
});
|
|
||||||
|
|
||||||
it("returns undefined when objects are not found", function () {
|
|
||||||
provider.readObject("testSpace", "abc").then(mockCallback);
|
|
||||||
expect(mockCallback).toHaveBeenCalledWith(undefined);
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
);
|
|
@ -29,22 +29,10 @@ describe('The ActionCollection', () => {
|
|||||||
let mockApplicableActions;
|
let mockApplicableActions;
|
||||||
let mockObjectPath;
|
let mockObjectPath;
|
||||||
let mockView;
|
let mockView;
|
||||||
let mockIdentifierService;
|
|
||||||
|
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
openmct = createOpenMct();
|
openmct = createOpenMct();
|
||||||
openmct.$injector = jasmine.createSpyObj('$injector', ['get']);
|
|
||||||
mockIdentifierService = jasmine.createSpyObj(
|
|
||||||
'identifierService',
|
|
||||||
['parse']
|
|
||||||
);
|
|
||||||
mockIdentifierService.parse.and.returnValue({
|
|
||||||
getSpace: () => {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
openmct.$injector.get.and.returnValue(mockIdentifierService);
|
|
||||||
mockObjectPath = [
|
mockObjectPath = [
|
||||||
{
|
{
|
||||||
name: 'mock folder',
|
name: 'mock folder',
|
||||||
|
@ -187,7 +187,7 @@ class InMemorySearchProvider {
|
|||||||
*/
|
*/
|
||||||
scheduleForIndexing(identifier) {
|
scheduleForIndexing(identifier) {
|
||||||
const keyString = this.openmct.objects.makeKeyString(identifier);
|
const keyString = this.openmct.objects.makeKeyString(identifier);
|
||||||
const objectProvider = this.openmct.objects.getProvider(identifier.key);
|
const objectProvider = this.openmct.objects.getProvider(identifier);
|
||||||
|
|
||||||
if (objectProvider === undefined || objectProvider.search === undefined) {
|
if (objectProvider === undefined || objectProvider.search === undefined) {
|
||||||
if (!this.indexedIds[keyString] && !this.pendingIndex[keyString]) {
|
if (!this.indexedIds[keyString] && !this.pendingIndex[keyString]) {
|
||||||
|
@ -43,9 +43,6 @@ function ObjectAPI(typeRegistry, openmct) {
|
|||||||
this.providers = {};
|
this.providers = {};
|
||||||
this.rootRegistry = new RootRegistry();
|
this.rootRegistry = new RootRegistry();
|
||||||
this.inMemorySearchProvider = new InMemorySearchProvider(openmct);
|
this.inMemorySearchProvider = new InMemorySearchProvider(openmct);
|
||||||
this.injectIdentifierService = function () {
|
|
||||||
this.identifierService = this.openmct.$injector.get("identifierService");
|
|
||||||
};
|
|
||||||
|
|
||||||
this.rootProvider = new RootObjectProvider(this.rootRegistry);
|
this.rootProvider = new RootObjectProvider(this.rootRegistry);
|
||||||
this.cache = {};
|
this.cache = {};
|
||||||
@ -66,33 +63,17 @@ ObjectAPI.prototype.supersecretSetFallbackProvider = function (p) {
|
|||||||
this.fallbackProvider = p;
|
this.fallbackProvider = p;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
|
||||||
* @private
|
|
||||||
*/
|
|
||||||
ObjectAPI.prototype.getIdentifierService = function () {
|
|
||||||
// Lazily acquire identifier service
|
|
||||||
if (!this.identifierService) {
|
|
||||||
this.injectIdentifierService();
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.identifierService;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the provider for a given identifier.
|
* Retrieve the provider for a given identifier.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
ObjectAPI.prototype.getProvider = function (identifier) {
|
ObjectAPI.prototype.getProvider = function (identifier) {
|
||||||
//handles the '' vs 'mct' namespace issue
|
|
||||||
const keyString = utils.makeKeyString(identifier);
|
|
||||||
const identifierService = this.getIdentifierService();
|
|
||||||
const namespace = identifierService.parse(keyString).getSpace();
|
|
||||||
|
|
||||||
if (identifier.key === 'ROOT') {
|
if (identifier.key === 'ROOT') {
|
||||||
return this.rootProvider;
|
return this.rootProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this.providers[namespace] || this.fallbackProvider;
|
return this.providers[identifier.namespace] || this.fallbackProvider;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -5,7 +5,6 @@ describe("The Object API", () => {
|
|||||||
let objectAPI;
|
let objectAPI;
|
||||||
let typeRegistry;
|
let typeRegistry;
|
||||||
let openmct = {};
|
let openmct = {};
|
||||||
let mockIdentifierService;
|
|
||||||
let mockDomainObject;
|
let mockDomainObject;
|
||||||
const TEST_NAMESPACE = "test-namespace";
|
const TEST_NAMESPACE = "test-namespace";
|
||||||
const FIFTEEN_MINUTES = 15 * 60 * 1000;
|
const FIFTEEN_MINUTES = 15 * 60 * 1000;
|
||||||
@ -15,18 +14,6 @@ describe("The Object API", () => {
|
|||||||
'get'
|
'get'
|
||||||
]);
|
]);
|
||||||
openmct = createOpenMct();
|
openmct = createOpenMct();
|
||||||
openmct.$injector = jasmine.createSpyObj('$injector', ['get']);
|
|
||||||
mockIdentifierService = jasmine.createSpyObj(
|
|
||||||
'identifierService',
|
|
||||||
['parse']
|
|
||||||
);
|
|
||||||
mockIdentifierService.parse.and.returnValue({
|
|
||||||
getSpace: () => {
|
|
||||||
return TEST_NAMESPACE;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
openmct.$injector.get.and.returnValue(mockIdentifierService);
|
|
||||||
objectAPI = openmct.objects;
|
objectAPI = openmct.objects;
|
||||||
|
|
||||||
openmct.editor = {};
|
openmct.editor = {};
|
||||||
|
@ -9,7 +9,7 @@ describe("Transaction Class", () => {
|
|||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
objectAPI = {
|
objectAPI = {
|
||||||
makeKeyString: (identifier) => utils.makeKeyString(identifier),
|
makeKeyString: (identifier) => utils.makeKeyString(identifier),
|
||||||
save: (object) => Promise.resolve(object),
|
save: () => Promise.resolve(true),
|
||||||
mutate: (object, prop, value) => {
|
mutate: (object, prop, value) => {
|
||||||
object[prop] = value;
|
object[prop] = value;
|
||||||
|
|
||||||
@ -61,6 +61,7 @@ describe("Transaction Class", () => {
|
|||||||
|
|
||||||
expect(transaction.dirtyObjects.size).toEqual(3);
|
expect(transaction.dirtyObjects.size).toEqual(3);
|
||||||
spyOn(objectAPI, 'save').and.callThrough();
|
spyOn(objectAPI, 'save').and.callThrough();
|
||||||
|
|
||||||
transaction.commit()
|
transaction.commit()
|
||||||
.then(success => {
|
.then(success => {
|
||||||
expect(transaction.dirtyObjects.size).toEqual(0);
|
expect(transaction.dirtyObjects.size).toEqual(0);
|
||||||
|
@ -74,7 +74,6 @@ define([
|
|||||||
'../platform/identity/bundle',
|
'../platform/identity/bundle',
|
||||||
'../platform/persistence/aggregator/bundle',
|
'../platform/persistence/aggregator/bundle',
|
||||||
'../platform/persistence/elastic/bundle',
|
'../platform/persistence/elastic/bundle',
|
||||||
'../platform/persistence/local/bundle',
|
|
||||||
'../platform/persistence/queue/bundle',
|
'../platform/persistence/queue/bundle',
|
||||||
'../platform/policy/bundle',
|
'../platform/policy/bundle',
|
||||||
'../platform/representation/bundle',
|
'../platform/representation/bundle',
|
||||||
|
@ -810,21 +810,6 @@ describe('the plugin', function () {
|
|||||||
openmct.telemetry.getMetadata.and.returnValue(testTelemetryObject.telemetry);
|
openmct.telemetry.getMetadata.and.returnValue(testTelemetryObject.telemetry);
|
||||||
openmct.telemetry.request.and.returnValue(Promise.resolve([]));
|
openmct.telemetry.request.and.returnValue(Promise.resolve([]));
|
||||||
|
|
||||||
// mockTransactionService.commit = async () => {};
|
|
||||||
const mockIdentifierService = jasmine.createSpyObj(
|
|
||||||
'identifierService',
|
|
||||||
['parse']
|
|
||||||
);
|
|
||||||
mockIdentifierService.parse.and.returnValue({
|
|
||||||
getSpace: () => {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
openmct.$injector = jasmine.createSpyObj('$injector', ['get']);
|
|
||||||
openmct.$injector.get.withArgs('identifierService').and.returnValue(mockIdentifierService);
|
|
||||||
// .withArgs('transactionService').and.returnValue(mockTransactionService);
|
|
||||||
|
|
||||||
const styleRuleManger = new StyleRuleManager(stylesObject, openmct, null, true);
|
const styleRuleManger = new StyleRuleManager(stylesObject, openmct, null, true);
|
||||||
spyOn(styleRuleManger, 'subscribeToConditionSet');
|
spyOn(styleRuleManger, 'subscribeToConditionSet');
|
||||||
openmct.editor.edit();
|
openmct.editor.edit();
|
||||||
|
100
src/plugins/localStorage/LocalStorageObjectProvider.js
Normal file
100
src/plugins/localStorage/LocalStorageObjectProvider.js
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
export default class LocalStorageObjectProvider {
|
||||||
|
constructor(spaceKey = 'mct') {
|
||||||
|
this.localStorage = window.localStorage;
|
||||||
|
this.spaceKey = spaceKey;
|
||||||
|
this.initializeSpace(spaceKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
get(identifier) {
|
||||||
|
if (this.getSpaceAsObject()[identifier.key] !== undefined) {
|
||||||
|
const persistedModel = this.getSpaceAsObject()[identifier.key];
|
||||||
|
const domainObject = {
|
||||||
|
identifier,
|
||||||
|
...persistedModel
|
||||||
|
};
|
||||||
|
|
||||||
|
return Promise.resolve(domainObject);
|
||||||
|
} else {
|
||||||
|
return Promise.resolve(undefined);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
create(object) {
|
||||||
|
return this.persistObject(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
update(object) {
|
||||||
|
return this.persistObject(object);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
persistObject(domainObject) {
|
||||||
|
let space = this.getSpaceAsObject();
|
||||||
|
space[domainObject.identifier.key] = domainObject;
|
||||||
|
|
||||||
|
this.persistSpace(space);
|
||||||
|
|
||||||
|
return Promise.resolve(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
persistSpace(space) {
|
||||||
|
this.localStorage[this.spaceKey] = JSON.stringify(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getSpace() {
|
||||||
|
return this.localStorage[this.spaceKey];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getSpaceAsObject() {
|
||||||
|
return JSON.parse(this.getSpace());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
initializeSpace() {
|
||||||
|
if (this.isEmpty()) {
|
||||||
|
this.localStorage[this.spaceKey] = JSON.stringify({});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
isEmpty() {
|
||||||
|
return this.getSpace() === undefined;
|
||||||
|
}
|
||||||
|
}
|
29
src/plugins/localStorage/plugin.js
Normal file
29
src/plugins/localStorage/plugin.js
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*****************************************************************************
|
||||||
|
* Open MCT, Copyright (c) 2014-2022, 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
import LocalStorageObjectProvider from './LocalStorageObjectProvider';
|
||||||
|
|
||||||
|
export default function (namespace = '', storageSpace = 'mct') {
|
||||||
|
return function (openmct) {
|
||||||
|
openmct.objects.addProvider(namespace, new LocalStorageObjectProvider(storageSpace));
|
||||||
|
};
|
||||||
|
}
|
96
src/plugins/localStorage/pluginSpec.js
Normal file
96
src/plugins/localStorage/pluginSpec.js
Normal file
@ -0,0 +1,96 @@
|
|||||||
|
/* eslint-disable no-invalid-this */
|
||||||
|
/*****************************************************************************
|
||||||
|
* 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.
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
import {
|
||||||
|
createOpenMct,
|
||||||
|
resetApplicationState
|
||||||
|
} from 'utils/testing';
|
||||||
|
|
||||||
|
describe("The local storage plugin", () => {
|
||||||
|
let space;
|
||||||
|
let openmct;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
space = `test-${Date.now()}`;
|
||||||
|
openmct = createOpenMct();
|
||||||
|
|
||||||
|
openmct.install(openmct.plugins.LocalStorage('', space));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
it('initializes localstorage if not already initialized', () => {
|
||||||
|
const ls = getLocalStorage();
|
||||||
|
expect(ls[space]).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully persists an object to localstorage', async () => {
|
||||||
|
const domainObject = {
|
||||||
|
identifier: {
|
||||||
|
namespace: '',
|
||||||
|
key: 'test-key'
|
||||||
|
},
|
||||||
|
name: 'A test object'
|
||||||
|
};
|
||||||
|
let spaceAsObject = getSpaceAsObject();
|
||||||
|
expect(spaceAsObject['test-key']).not.toBeDefined();
|
||||||
|
|
||||||
|
await openmct.objects.save(domainObject);
|
||||||
|
|
||||||
|
spaceAsObject = getSpaceAsObject();
|
||||||
|
expect(spaceAsObject['test-key']).toBeDefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('successfully retrieves an object from localstorage', async () => {
|
||||||
|
const domainObject = {
|
||||||
|
identifier: {
|
||||||
|
namespace: '',
|
||||||
|
key: 'test-key'
|
||||||
|
},
|
||||||
|
name: 'A test object',
|
||||||
|
anotherProperty: Date.now()
|
||||||
|
};
|
||||||
|
await openmct.objects.save(domainObject);
|
||||||
|
|
||||||
|
let testObject = await openmct.objects.get(domainObject.identifier);
|
||||||
|
|
||||||
|
expect(testObject.name).toEqual(domainObject.name);
|
||||||
|
expect(testObject.anotherProperty).toEqual(domainObject.anotherProperty);
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
resetApplicationState(openmct);
|
||||||
|
resetLocalStorage();
|
||||||
|
});
|
||||||
|
|
||||||
|
function resetLocalStorage() {
|
||||||
|
delete window.localStorage[space];
|
||||||
|
}
|
||||||
|
|
||||||
|
function getLocalStorage() {
|
||||||
|
return window.localStorage;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getSpaceAsObject() {
|
||||||
|
return JSON.parse(getLocalStorage()[space]);
|
||||||
|
}
|
||||||
|
});
|
@ -95,23 +95,10 @@ const selectedPage = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let openmct;
|
let openmct;
|
||||||
let mockIdentifierService;
|
|
||||||
|
|
||||||
describe('Notebook Entries:', () => {
|
describe('Notebook Entries:', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
openmct = createOpenMct();
|
openmct = createOpenMct();
|
||||||
openmct.$injector = jasmine.createSpyObj('$injector', ['get']);
|
|
||||||
mockIdentifierService = jasmine.createSpyObj(
|
|
||||||
'identifierService',
|
|
||||||
['parse']
|
|
||||||
);
|
|
||||||
mockIdentifierService.parse.and.returnValue({
|
|
||||||
getSpace: () => {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
openmct.$injector.get.and.returnValue(mockIdentifierService);
|
|
||||||
openmct.types.addType('notebook', {
|
openmct.types.addType('notebook', {
|
||||||
creatable: true
|
creatable: true
|
||||||
});
|
});
|
||||||
|
@ -64,23 +64,11 @@ const notebookStorage = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let openmct;
|
let openmct;
|
||||||
let mockIdentifierService;
|
|
||||||
|
|
||||||
describe('Notebook Storage:', () => {
|
describe('Notebook Storage:', () => {
|
||||||
beforeEach(() => {
|
beforeEach(() => {
|
||||||
openmct = createOpenMct();
|
openmct = createOpenMct();
|
||||||
openmct.$injector = jasmine.createSpyObj('$injector', ['get']);
|
|
||||||
mockIdentifierService = jasmine.createSpyObj(
|
|
||||||
'identifierService',
|
|
||||||
['parse']
|
|
||||||
);
|
|
||||||
mockIdentifierService.parse.and.returnValue({
|
|
||||||
getSpace: () => {
|
|
||||||
return '';
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
openmct.$injector.get.and.returnValue(mockIdentifierService);
|
|
||||||
window.localStorage.setItem('notebook-storage', null);
|
window.localStorage.setItem('notebook-storage', null);
|
||||||
openmct.objects.addProvider('', jasmine.createSpyObj('mockNotebookProvider', [
|
openmct.objects.addProvider('', jasmine.createSpyObj('mockNotebookProvider', [
|
||||||
'create',
|
'create',
|
||||||
|
@ -84,17 +84,17 @@ class CouchObjectProvider {
|
|||||||
this.changesFeedSharedWorkerConnectionId = event.data.connectionId;
|
this.changesFeedSharedWorkerConnectionId = event.data.connectionId;
|
||||||
} else {
|
} else {
|
||||||
let objectChanges = event.data.objectChanges;
|
let objectChanges = event.data.objectChanges;
|
||||||
objectChanges.identifier = {
|
const objectIdentifier = {
|
||||||
namespace: this.namespace,
|
namespace: this.namespace,
|
||||||
key: objectChanges.id
|
key: objectChanges.id
|
||||||
};
|
};
|
||||||
let keyString = this.openmct.objects.makeKeyString(objectChanges.identifier);
|
let keyString = this.openmct.objects.makeKeyString(objectIdentifier);
|
||||||
//TODO: Optimize this so that we don't 'get' the object if it's current revision (from this.objectQueue) is the same as the one we already have.
|
//TODO: Optimize this so that we don't 'get' the object if it's current revision (from this.objectQueue) is the same as the one we already have.
|
||||||
let observersForObject = this.observers[keyString];
|
let observersForObject = this.observers[keyString];
|
||||||
|
|
||||||
if (observersForObject) {
|
if (observersForObject) {
|
||||||
observersForObject.forEach(async (observer) => {
|
observersForObject.forEach(async (observer) => {
|
||||||
const updatedObject = await this.get(objectChanges.identifier);
|
const updatedObject = await this.get(objectIdentifier);
|
||||||
if (this.isSynchronizedObject(updatedObject)) {
|
if (this.isSynchronizedObject(updatedObject)) {
|
||||||
observer(updatedObject);
|
observer(updatedObject);
|
||||||
}
|
}
|
||||||
@ -179,11 +179,8 @@ class CouchObjectProvider {
|
|||||||
getModel(response) {
|
getModel(response) {
|
||||||
if (response && response.model) {
|
if (response && response.model) {
|
||||||
let key = response[ID];
|
let key = response[ID];
|
||||||
let object = response.model;
|
let object = this.fromPersistedModel(response.model, key);
|
||||||
object.identifier = {
|
|
||||||
namespace: this.namespace,
|
|
||||||
key: key
|
|
||||||
};
|
|
||||||
if (!this.objectQueue[key]) {
|
if (!this.objectQueue[key]) {
|
||||||
this.objectQueue[key] = new CouchObjectQueue(undefined, response[REV]);
|
this.objectQueue[key] = new CouchObjectQueue(undefined, response[REV]);
|
||||||
}
|
}
|
||||||
@ -445,17 +442,17 @@ class CouchObjectProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onEventMessage(event) {
|
onEventMessage(event) {
|
||||||
const object = JSON.parse(event.data);
|
const eventData = JSON.parse(event.data);
|
||||||
object.identifier = {
|
const identifier = {
|
||||||
namespace: this.namespace,
|
namespace: this.namespace,
|
||||||
key: object.id
|
key: eventData.id
|
||||||
};
|
};
|
||||||
let keyString = this.openmct.objects.makeKeyString(object.identifier);
|
const keyString = this.openmct.objects.makeKeyString(identifier);
|
||||||
let observersForObject = this.observers[keyString];
|
let observersForObject = this.observers[keyString];
|
||||||
|
|
||||||
if (observersForObject) {
|
if (observersForObject) {
|
||||||
observersForObject.forEach(async (observer) => {
|
observersForObject.forEach(async (observer) => {
|
||||||
const updatedObject = await this.get(object.identifier);
|
const updatedObject = await this.get(identifier);
|
||||||
if (this.isSynchronizedObject(updatedObject)) {
|
if (this.isSynchronizedObject(updatedObject)) {
|
||||||
observer(updatedObject);
|
observer(updatedObject);
|
||||||
}
|
}
|
||||||
@ -520,7 +517,9 @@ class CouchObjectProvider {
|
|||||||
create(model) {
|
create(model) {
|
||||||
let intermediateResponse = this.getIntermediateResponse();
|
let intermediateResponse = this.getIntermediateResponse();
|
||||||
const key = model.identifier.key;
|
const key = model.identifier.key;
|
||||||
|
model = this.toPersistableModel(model);
|
||||||
this.enqueueObject(key, model, intermediateResponse);
|
this.enqueueObject(key, model, intermediateResponse);
|
||||||
|
|
||||||
if (!this.objectQueue[key].pending) {
|
if (!this.objectQueue[key].pending) {
|
||||||
this.objectQueue[key].pending = true;
|
this.objectQueue[key].pending = true;
|
||||||
const queued = this.objectQueue[key].dequeue();
|
const queued = this.objectQueue[key].dequeue();
|
||||||
@ -557,11 +556,31 @@ class CouchObjectProvider {
|
|||||||
update(model) {
|
update(model) {
|
||||||
let intermediateResponse = this.getIntermediateResponse();
|
let intermediateResponse = this.getIntermediateResponse();
|
||||||
const key = model.identifier.key;
|
const key = model.identifier.key;
|
||||||
|
model = this.toPersistableModel(model);
|
||||||
|
|
||||||
this.enqueueObject(key, model, intermediateResponse);
|
this.enqueueObject(key, model, intermediateResponse);
|
||||||
this.updateQueued(key);
|
this.updateQueued(key);
|
||||||
|
|
||||||
return intermediateResponse.promise;
|
return intermediateResponse.promise;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
toPersistableModel(model) {
|
||||||
|
//First make a copy so we are not mutating the provided model.
|
||||||
|
const persistableModel = JSON.parse(JSON.stringify(model));
|
||||||
|
//Delete the identifier. Couch manages namespaces dynamically.
|
||||||
|
delete persistableModel.identifier;
|
||||||
|
|
||||||
|
return persistableModel;
|
||||||
|
}
|
||||||
|
|
||||||
|
fromPersistedModel(model, key) {
|
||||||
|
model.identifier = {
|
||||||
|
namespace: this.namespace,
|
||||||
|
key
|
||||||
|
};
|
||||||
|
|
||||||
|
return model;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CouchObjectProvider.HTTP_CONFLICT = 409;
|
CouchObjectProvider.HTTP_CONFLICT = 409;
|
||||||
|
@ -22,11 +22,15 @@
|
|||||||
|
|
||||||
import CouchObjectProvider from './CouchObjectProvider';
|
import CouchObjectProvider from './CouchObjectProvider';
|
||||||
const NAMESPACE = '';
|
const NAMESPACE = '';
|
||||||
const PERSISTENCE_SPACE = 'mct';
|
const LEGACY_SPACE = 'mct';
|
||||||
|
|
||||||
export default function CouchPlugin(options) {
|
export default function CouchPlugin(options) {
|
||||||
return function install(openmct) {
|
return function install(openmct) {
|
||||||
install.couchProvider = new CouchObjectProvider(openmct, options, NAMESPACE);
|
install.couchProvider = new CouchObjectProvider(openmct, options, NAMESPACE);
|
||||||
openmct.objects.addProvider(PERSISTENCE_SPACE, install.couchProvider);
|
|
||||||
|
// Unfortunately, for historical reasons, Couch DB produces objects with a mix of namepaces (alternately "mct", and "")
|
||||||
|
// Installing the same provider under both namespaces means that it can respond to object gets for both namespaces.
|
||||||
|
openmct.objects.addProvider(LEGACY_SPACE, install.couchProvider);
|
||||||
|
openmct.objects.addProvider(NAMESPACE, install.couchProvider);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -129,8 +129,9 @@ describe('the plugin', () => {
|
|||||||
|
|
||||||
it('works without Shared Workers', async () => {
|
it('works without Shared Workers', async () => {
|
||||||
let sharedWorkerCallback;
|
let sharedWorkerCallback;
|
||||||
const restoreSharedWorker = window.SharedWorker;
|
const cachedSharedWorker = window.SharedWorker;
|
||||||
window.SharedWorker = undefined;
|
window.SharedWorker = undefined;
|
||||||
|
|
||||||
const mockEventSource = {
|
const mockEventSource = {
|
||||||
addEventListener: (topic, addedListener) => {
|
addEventListener: (topic, addedListener) => {
|
||||||
sharedWorkerCallback = addedListener;
|
sharedWorkerCallback = addedListener;
|
||||||
@ -139,6 +140,8 @@ describe('the plugin', () => {
|
|||||||
sharedWorkerCallback = null;
|
sharedWorkerCallback = null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
const cachedEventSource = window.EventSource;
|
||||||
|
|
||||||
window.EventSource = function (url) {
|
window.EventSource = function (url) {
|
||||||
return mockEventSource;
|
return mockEventSource;
|
||||||
};
|
};
|
||||||
@ -163,17 +166,21 @@ describe('the plugin', () => {
|
|||||||
expect(result).toBeTrue();
|
expect(result).toBeTrue();
|
||||||
expect(provider.create).toHaveBeenCalled();
|
expect(provider.create).toHaveBeenCalled();
|
||||||
expect(provider.startSharedWorker).not.toHaveBeenCalled();
|
expect(provider.startSharedWorker).not.toHaveBeenCalled();
|
||||||
|
|
||||||
//Set modified timestamp it detects a change and persists the updated model.
|
//Set modified timestamp it detects a change and persists the updated model.
|
||||||
mockDomainObject.modified = mockDomainObject.persisted + 1;
|
mockDomainObject.modified = mockDomainObject.persisted + 1;
|
||||||
const updatedResult = await openmct.objects.save(mockDomainObject);
|
const updatedResult = await openmct.objects.save(mockDomainObject);
|
||||||
openmct.objects.observe(mockDomainObject, '*', (updatedObject) => {
|
openmct.objects.observe(mockDomainObject, '*', (updatedObject) => {
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(updatedResult).toBeTrue();
|
expect(updatedResult).toBeTrue();
|
||||||
expect(provider.update).toHaveBeenCalled();
|
expect(provider.update).toHaveBeenCalled();
|
||||||
expect(provider.fetchChanges).toHaveBeenCalled();
|
expect(provider.fetchChanges).toHaveBeenCalled();
|
||||||
sharedWorkerCallback(fakeUpdateEvent);
|
sharedWorkerCallback(fakeUpdateEvent);
|
||||||
expect(provider.onEventMessage).toHaveBeenCalled();
|
expect(provider.onEventMessage).toHaveBeenCalled();
|
||||||
window.SharedWorker = restoreSharedWorker;
|
|
||||||
|
window.SharedWorker = cachedSharedWorker;
|
||||||
|
window.EventSource = cachedEventSource;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
describe('batches requests', () => {
|
describe('batches requests', () => {
|
||||||
|
@ -73,7 +73,8 @@ define([
|
|||||||
'./hyperlink/plugin',
|
'./hyperlink/plugin',
|
||||||
'./clock/plugin',
|
'./clock/plugin',
|
||||||
'./DeviceClassifier/plugin',
|
'./DeviceClassifier/plugin',
|
||||||
'./timer/plugin'
|
'./timer/plugin',
|
||||||
|
'./localStorage/plugin'
|
||||||
], function (
|
], function (
|
||||||
_,
|
_,
|
||||||
UTCTimeSystem,
|
UTCTimeSystem,
|
||||||
@ -127,10 +128,10 @@ define([
|
|||||||
Hyperlink,
|
Hyperlink,
|
||||||
Clock,
|
Clock,
|
||||||
DeviceClassifier,
|
DeviceClassifier,
|
||||||
Timer
|
Timer,
|
||||||
|
LocalStorage
|
||||||
) {
|
) {
|
||||||
const bundleMap = {
|
const bundleMap = {
|
||||||
LocalStorage: 'platform/persistence/local',
|
|
||||||
Elasticsearch: 'platform/persistence/elastic'
|
Elasticsearch: 'platform/persistence/elastic'
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -235,6 +236,7 @@ define([
|
|||||||
plugins.Clock = Clock.default;
|
plugins.Clock = Clock.default;
|
||||||
plugins.Timer = Timer.default;
|
plugins.Timer = Timer.default;
|
||||||
plugins.DeviceClassifier = DeviceClassifier.default;
|
plugins.DeviceClassifier = DeviceClassifier.default;
|
||||||
|
plugins.LocalStorage = LocalStorage.default;
|
||||||
|
|
||||||
return plugins;
|
return plugins;
|
||||||
});
|
});
|
||||||
|
Loading…
x
Reference in New Issue
Block a user