mirror of
https://github.com/nasa/openmct.git
synced 2024-12-24 07:16:39 +00:00
Merge remote-tracking branch 'origin/api-tutorials' into api-view
Conflicts: src/MCT.js src/api/api.js
This commit is contained in:
commit
b2e7db71cc
@ -19,6 +19,7 @@
|
||||
"comma-separated-values": "^3.6.4",
|
||||
"FileSaver.js": "^0.0.2",
|
||||
"zepto": "^1.1.6",
|
||||
"eventemitter3": "^1.2.0"
|
||||
"eventemitter3": "^1.2.0",
|
||||
"lodash": "3.10.1"
|
||||
}
|
||||
}
|
||||
|
@ -31,12 +31,14 @@
|
||||
<script type="text/javascript">
|
||||
require(['main'], function (mct) {
|
||||
require([
|
||||
'./tutorials/grootprovider/groots',
|
||||
'./tutorials/todo/todo',
|
||||
'./tutorials/todo/bundle',
|
||||
'./example/imagery/bundle',
|
||||
'./example/eventGenerator/bundle',
|
||||
'./example/generator/bundle'
|
||||
], function (todoPlugin) {
|
||||
'./example/generator/bundle',
|
||||
], function (grootify, todoPlugin) {
|
||||
grootify(mct);
|
||||
todoPlugin(mct);
|
||||
mct.start();
|
||||
})
|
||||
|
3
main.js
3
main.js
@ -35,7 +35,8 @@ requirejs.config({
|
||||
"screenfull": "bower_components/screenfull/dist/screenfull.min",
|
||||
"text": "bower_components/text/text",
|
||||
"uuid": "bower_components/node-uuid/uuid",
|
||||
"zepto": "bower_components/zepto/zepto.min"
|
||||
"zepto": "bower_components/zepto/zepto.min",
|
||||
"lodash": "bower_components/lodash/lodash"
|
||||
},
|
||||
"shim": {
|
||||
"angular": {
|
||||
|
@ -2,7 +2,8 @@ define([
|
||||
'EventEmitter',
|
||||
'legacyRegistry',
|
||||
'uuid',
|
||||
'./api/api'
|
||||
'./api/api',
|
||||
'./api/objects/bundle'
|
||||
], function (
|
||||
EventEmitter,
|
||||
legacyRegistry,
|
||||
|
@ -1,12 +1,15 @@
|
||||
define([
|
||||
'./Type',
|
||||
'./View'
|
||||
'./View',
|
||||
'./objects/ObjectAPI'
|
||||
], function (
|
||||
Type,
|
||||
View
|
||||
View,
|
||||
ObjectAPI
|
||||
) {
|
||||
return {
|
||||
Type: Type,
|
||||
View: View
|
||||
View: View,
|
||||
Objects: ObjectAPI
|
||||
};
|
||||
});
|
||||
|
70
src/api/objects/LegacyObjectAPIInterceptor.js
Normal file
70
src/api/objects/LegacyObjectAPIInterceptor.js
Normal file
@ -0,0 +1,70 @@
|
||||
define([
|
||||
'./object-utils',
|
||||
'./ObjectAPI'
|
||||
], function (
|
||||
utils,
|
||||
ObjectAPI
|
||||
) {
|
||||
function ObjectServiceProvider(objectService, instantiate) {
|
||||
this.objectService = objectService;
|
||||
this.instantiate = instantiate;
|
||||
}
|
||||
|
||||
ObjectServiceProvider.prototype.save = function (object) {
|
||||
var key = object.key,
|
||||
keyString = utils.makeKeyString(key),
|
||||
newObject = this.instantiate(utils.toOldFormat(object), keyString);
|
||||
|
||||
return object.getCapability('persistence')
|
||||
.persist()
|
||||
.then(function () {
|
||||
return utils.toNewFormat(object, key);
|
||||
});
|
||||
};
|
||||
|
||||
ObjectServiceProvider.prototype.delete = function (object) {
|
||||
// TODO!
|
||||
};
|
||||
|
||||
ObjectServiceProvider.prototype.get = function (key) {
|
||||
var keyString = utils.makeKeyString(key);
|
||||
return this.objectService.getObjects([keyString])
|
||||
.then(function (results) {
|
||||
var model = JSON.parse(JSON.stringify(results[keyString].getModel()));
|
||||
return utils.toNewFormat(model, key);
|
||||
});
|
||||
};
|
||||
|
||||
// Injects new object API as a decorator so that it hijacks all requests.
|
||||
// Object providers implemented on new API should just work, old API should just work, many things may break.
|
||||
function LegacyObjectAPIInterceptor(ROOTS, instantiate, objectService) {
|
||||
this.getObjects = function (keys) {
|
||||
var results = {},
|
||||
promises = keys.map(function (keyString) {
|
||||
var key = utils.parseKeyString(keyString);
|
||||
return ObjectAPI.get(key)
|
||||
.then(function (object) {
|
||||
object = utils.toOldFormat(object)
|
||||
results[keyString] = instantiate(object, keyString);
|
||||
});
|
||||
});
|
||||
|
||||
return Promise.all(promises)
|
||||
.then(function () {
|
||||
return results;
|
||||
});
|
||||
};
|
||||
|
||||
ObjectAPI._supersecretSetFallbackProvider(
|
||||
new ObjectServiceProvider(objectService, instantiate)
|
||||
);
|
||||
|
||||
ROOTS.forEach(function (r) {
|
||||
ObjectAPI.addRoot(utils.parseKeyString(r.id));
|
||||
});
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
return LegacyObjectAPIInterceptor;
|
||||
});
|
92
src/api/objects/ObjectAPI.js
Normal file
92
src/api/objects/ObjectAPI.js
Normal file
@ -0,0 +1,92 @@
|
||||
define([
|
||||
'lodash',
|
||||
'./object-utils'
|
||||
], function (
|
||||
_,
|
||||
utils
|
||||
) {
|
||||
|
||||
/**
|
||||
Object API. Intercepts the existing object API while also exposing
|
||||
A new Object API.
|
||||
|
||||
MCT.objects.get('mine')
|
||||
.then(function (root) {
|
||||
console.log(root);
|
||||
MCT.objects.getComposition(root)
|
||||
.then(function (composition) {
|
||||
console.log(composition)
|
||||
})
|
||||
});
|
||||
*/
|
||||
|
||||
var Objects = {},
|
||||
ROOT_REGISTRY = [],
|
||||
PROVIDER_REGISTRY = {},
|
||||
FALLBACK_PROVIDER;
|
||||
|
||||
Objects._supersecretSetFallbackProvider = function (p) {
|
||||
FALLBACK_PROVIDER = p;
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Root provider is hardcoded in; can't be skipped.
|
||||
var RootProvider = {
|
||||
'get': function () {
|
||||
return Promise.resolve({
|
||||
name: 'The root object',
|
||||
type: 'root',
|
||||
composition: ROOT_REGISTRY
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Retrieve the provider for a given key.
|
||||
function getProvider(key) {
|
||||
if (key.identifier === 'ROOT') {
|
||||
return RootProvider;
|
||||
}
|
||||
return PROVIDER_REGISTRY[key.namespace] || FALLBACK_PROVIDER;
|
||||
};
|
||||
|
||||
Objects.addProvider = function (namespace, provider) {
|
||||
PROVIDER_REGISTRY[namespace] = provider;
|
||||
};
|
||||
|
||||
[
|
||||
'save',
|
||||
'delete',
|
||||
'get'
|
||||
].forEach(function (method) {
|
||||
Objects[method] = function () {
|
||||
var key = arguments[0],
|
||||
provider = getProvider(key);
|
||||
|
||||
if (!provider) {
|
||||
throw new Error('No Provider Matched');
|
||||
}
|
||||
|
||||
if (!provider[method]) {
|
||||
throw new Error('Provider does not support [' + method + '].');
|
||||
}
|
||||
|
||||
return provider[method].apply(provider, arguments);
|
||||
};
|
||||
});
|
||||
|
||||
Objects.addRoot = function (key) {
|
||||
ROOT_REGISTRY.unshift(key);
|
||||
};
|
||||
|
||||
Objects.removeRoot = function (key) {
|
||||
ROOT_REGISTRY = ROOT_REGISTRY.filter(function (k) {
|
||||
return (
|
||||
k.identifier !== key.identifier ||
|
||||
k.namespace !== key.namespace
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
return Objects;
|
||||
});
|
100
src/api/objects/README.md
Normal file
100
src/api/objects/README.md
Normal file
@ -0,0 +1,100 @@
|
||||
# Object API - Overview
|
||||
|
||||
The object API provides methods for fetching domain objects.
|
||||
|
||||
# Keys
|
||||
Keys are a composite identifier that is used to create and persist objects. Ex:
|
||||
```javascript
|
||||
{
|
||||
namespace: 'elastic',
|
||||
identifier: 'myIdentifier'
|
||||
}
|
||||
```
|
||||
|
||||
In old MCT days, we called this an "id", and we encoded it in a single string.
|
||||
The above key would encode into the identifier, `elastic:myIdentifier`.
|
||||
|
||||
When interacting with the API you will be dealing with key objects.
|
||||
|
||||
# Configuring the Object API
|
||||
|
||||
The following methods should be used before calling run. They allow you to
|
||||
configure the persistence space of MCT.
|
||||
|
||||
* `MCT.objects.addRoot(key)` -- add a "ROOT" to Open MCT by specifying it's
|
||||
key.
|
||||
* `MCT.objects.removeRoot(key)` -- Remove a "ROOT" from Open MCT by key.
|
||||
* `MCT.objects.addProvider(namespace, provider)` -- register an object provider
|
||||
for a specific namespace. See below for documentation on the provider
|
||||
interface.
|
||||
|
||||
# Using the object API
|
||||
|
||||
The object API provides methods for getting, saving, and deleting objects.
|
||||
|
||||
* MCT.objects.get(key) -> returns promise for an object
|
||||
* MCT.objects.save(object) -> returns promise that is resolved when object
|
||||
has been saved
|
||||
* MCT.objects.delete(object) -> returns promise that is resolved when object has
|
||||
been deleted
|
||||
|
||||
## Configuration Example: Adding a groot
|
||||
|
||||
The following example adds a new root object for groot and populates it with
|
||||
some pieces of groot.
|
||||
|
||||
```javascript
|
||||
|
||||
var ROOT_KEY = {
|
||||
namespace: 'groot',
|
||||
identifier: 'groot'
|
||||
};
|
||||
|
||||
var GROOT_ROOT = {
|
||||
name: 'I am groot',
|
||||
type: 'folder',
|
||||
composition: [
|
||||
{
|
||||
namespace: 'groot',
|
||||
identifier: 'arms'
|
||||
},
|
||||
{
|
||||
namespace: 'groot',
|
||||
identifier: 'legs'
|
||||
},
|
||||
{
|
||||
namespace: 'groot',
|
||||
identifier: 'torso'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var GrootProvider = {
|
||||
get: function (key) {
|
||||
if (key.identifier === 'groot') {
|
||||
return Promise.resolve(GROOT_ROOT);
|
||||
}
|
||||
return Promise.resolve({
|
||||
name: 'Groot\'s ' + key.identifier
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
mct.Objects.addRoot(ROOT_KEY);
|
||||
|
||||
mct.Objects.addProvider('groot', GrootProvider);
|
||||
|
||||
```
|
||||
|
||||
### Making a custom provider:
|
||||
|
||||
All methods on the provider interface are optional, so you do not need
|
||||
to modify them.
|
||||
|
||||
* `provider.get(key)` -> promise for a domain object.
|
||||
* `provider.save(domainObject)` -> returns promise that is fulfilled when object
|
||||
has been saved.
|
||||
* `provider.delete(domainObject)` -> returns promise that is fulfilled when
|
||||
object has been deleted.
|
||||
|
||||
|
49
src/api/objects/bundle.js
Normal file
49
src/api/objects/bundle.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
define([
|
||||
'./LegacyObjectAPIInterceptor',
|
||||
'legacyRegistry'
|
||||
], function (
|
||||
LegacyObjectAPIInterceptor,
|
||||
legacyRegistry
|
||||
) {
|
||||
legacyRegistry.register('src/api/objects', {
|
||||
name: 'Object API',
|
||||
description: 'The public Objects API',
|
||||
extensions: {
|
||||
components: [
|
||||
{
|
||||
provides: "objectService",
|
||||
type: "decorator",
|
||||
priority: "mandatory",
|
||||
implementation: LegacyObjectAPIInterceptor,
|
||||
depends: [
|
||||
"roots[]",
|
||||
"instantiate"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
});
|
67
src/api/objects/object-utils.js
Normal file
67
src/api/objects/object-utils.js
Normal file
@ -0,0 +1,67 @@
|
||||
define([
|
||||
|
||||
], function (
|
||||
|
||||
) {
|
||||
|
||||
// take a key string and turn it into a key object
|
||||
// 'scratch:root' ==> {namespace: 'scratch', identifier: 'root'}
|
||||
var parseKeyString = function (key) {
|
||||
if (typeof key === 'object') {
|
||||
return key;
|
||||
}
|
||||
var namespace = '',
|
||||
identifier = key;
|
||||
for (var i = 0, escaped = false, len=key.length; i < len; i++) {
|
||||
if (key[i] === ":" && !escaped) {
|
||||
namespace = key.slice(0, i);
|
||||
identifier = key.slice(i + 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {
|
||||
namespace: namespace,
|
||||
identifier: identifier
|
||||
};
|
||||
};
|
||||
|
||||
// take a key and turn it into a key string
|
||||
// {namespace: 'scratch', identifier: 'root'} ==> 'scratch:root'
|
||||
var makeKeyString = function (key) {
|
||||
if (typeof key === 'string') {
|
||||
return key;
|
||||
}
|
||||
if (!key.namespace) {
|
||||
return key.identifier;
|
||||
}
|
||||
return [
|
||||
key.namespace.replace(':', '\\:'),
|
||||
key.identifier.replace(':', '\\:')
|
||||
].join(':');
|
||||
};
|
||||
|
||||
// Converts composition to use key strings instead of keys
|
||||
var toOldFormat = function (model) {
|
||||
delete model.key;
|
||||
if (model.composition) {
|
||||
model.composition = model.composition.map(makeKeyString);
|
||||
}
|
||||
return model;
|
||||
};
|
||||
|
||||
// converts composition to use keys instead of key strings
|
||||
var toNewFormat = function (model, key) {
|
||||
model.key = key;
|
||||
if (model.composition) {
|
||||
model.composition = model.composition.map(parseKeyString);
|
||||
}
|
||||
return model;
|
||||
};
|
||||
|
||||
return {
|
||||
toOldFormat: toOldFormat,
|
||||
toNewFormat: toNewFormat,
|
||||
makeKeyString: makeKeyString,
|
||||
parseKeyString: parseKeyString
|
||||
};
|
||||
});
|
44
tutorials/grootprovider/groots.js
Normal file
44
tutorials/grootprovider/groots.js
Normal file
@ -0,0 +1,44 @@
|
||||
define(function () {
|
||||
return function grootPlugin(mct) {
|
||||
var ROOT_KEY = {
|
||||
namespace: 'groot',
|
||||
identifier: 'groot'
|
||||
};
|
||||
|
||||
var GROOT_ROOT = {
|
||||
name: 'I am groot',
|
||||
type: 'folder',
|
||||
composition: [
|
||||
{
|
||||
namespace: 'groot',
|
||||
identifier: 'arms'
|
||||
},
|
||||
{
|
||||
namespace: 'groot',
|
||||
identifier: 'legs'
|
||||
},
|
||||
{
|
||||
namespace: 'groot',
|
||||
identifier: 'torso'
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
var GrootProvider = {
|
||||
get: function (key) {
|
||||
if (key.identifier === 'groot') {
|
||||
return Promise.resolve(GROOT_ROOT);
|
||||
}
|
||||
return Promise.resolve({
|
||||
name: 'Groot\'s ' + key.identifier
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
mct.Objects.addRoot(ROOT_KEY);
|
||||
|
||||
mct.Objects.addProvider('groot', GrootProvider);
|
||||
|
||||
return mct;
|
||||
};
|
||||
});
|
Loading…
Reference in New Issue
Block a user