Merge branch 'api-todo-update' into api-type-forms

This commit is contained in:
Victor Woeltjen 2016-08-11 15:31:11 -07:00
commit d4948f771b
14 changed files with 280 additions and 128 deletions

22
API.md
View File

@ -73,6 +73,22 @@ Status: First Draft
The time conductor is an API that facilitates time synchronization across multiple components. Components that would like to be "time aware" may attach listeners to the time conductor API to allow them to remain synchronized with other components. For more information ont he time conductor API, please look at the API draft here: https://github.com/nasa/openmct/blob/66220b89ca568075f107505ba414de9457dc0427/platform/features/conductor-redux/src/README.md
### `MCT.selection`
Status: First Draft
Tracks the application's selection state (which elements of a view has a user selected?)
One or more JavaScript objects may be selected at any given time. User code is responsible for any necessary type-checking.
The following methods are exposed from this object:
* `select(value)`: Add `value` to the current selection.
* `deselect(value)`: Remove `value` from the current selection.
* `selected()`: Get array of all selected objects.
* `clear()`: Deselect all selected objects.
MCT.selection is an EventEmitter; a `change` event is emitted whenever the selection changes.
### `MCT.systems`
Status: Not Implemented, Needs to be ported from old system.
@ -90,3 +106,9 @@ Install a plugin in MCT. Must be called before calling `run`. Plugins are func
For an example of writing a plugin, check out [plugin-example.html](plugin-example.html)
### `MCT.setAssetPath(path)`
Sets the path (absolute or relative) at which the Open MCT static files are being hosted. The default value is '.'.
Note that this API is transitional and will be removed in a future version.

View File

@ -36,7 +36,7 @@ define([
legacyRegistry
) {
"use strict";
legacyRegistry.register("example/notifications", {
legacyRegistry.register("example/msl-adapter", {
"name" : "Mars Science Laboratory Data Adapter",
"extensions" : {
"types": [

View File

@ -21,36 +21,24 @@
*****************************************************************************/
/*global require,__dirname*/
var gulp = require('gulp'),
requirejsOptimize = require('gulp-requirejs-optimize'),
sourcemaps = require('gulp-sourcemaps'),
rename = require('gulp-rename'),
sass = require('gulp-sass'),
bourbon = require('node-bourbon'),
jshint = require('gulp-jshint'),
jscs = require('gulp-jscs'),
replace = require('gulp-replace-task'),
karma = require('karma'),
path = require('path'),
fs = require('fs'),
git = require('git-rev-sync'),
moment = require('moment'),
merge = require('merge-stream'),
project = require('./package.json'),
_ = require('lodash'),
paths = {
main: 'main.js',
dist: 'dist',
assets: 'dist/assets',
scss: ['./platform/**/*.scss', './example/**/*.scss'],
assets: [
'./{example,platform}/**/*.{css,css.map,png,svg,ico,woff,eot,ttf}'
],
scripts: [ 'main.js', 'platform/**/*.js', 'src/**/*.js' ],
specs: [ 'platform/**/*Spec.js', 'src/**/*Spec.js' ],
static: [
'index.html',
'platform/**/*',
'example/**/*',
'bower_components/**/*'
]
},
options = {
requirejsOptimize: {
@ -68,7 +56,6 @@ var gulp = require('gulp'),
singleRun: true
},
sass: {
includePaths: bourbon.includePaths,
sourceComments: true
},
replace: {
@ -82,6 +69,8 @@ var gulp = require('gulp'),
};
gulp.task('scripts', function () {
var requirejsOptimize = require('gulp-requirejs-optimize');
var replace = require('gulp-replace-task');
return gulp.src(paths.main)
.pipe(sourcemaps.init())
.pipe(requirejsOptimize(options.requirejsOptimize))
@ -91,10 +80,16 @@ gulp.task('scripts', function () {
});
gulp.task('test', function (done) {
var karma = require('karma');
new karma.Server(options.karma, done).start();
});
gulp.task('stylesheets', function () {
var sass = require('gulp-sass');
var rename = require('gulp-rename');
var bourbon = require('node-bourbon');
options.sass.includePaths = bourbon.includePaths;
return gulp.src(paths.scss, {base: '.'})
.pipe(sourcemaps.init())
.pipe(sass(options.sass).on('error', sass.logError))
@ -108,6 +103,9 @@ gulp.task('stylesheets', function () {
});
gulp.task('lint', function () {
var jshint = require('gulp-jshint');
var merge = require('merge-stream');
var nonspecs = paths.specs.map(function (glob) {
return "!" + glob;
}),
@ -122,6 +120,8 @@ gulp.task('lint', function () {
});
gulp.task('checkstyle', function () {
var jscs = require('gulp-jscs');
return gulp.src(paths.scripts)
.pipe(jscs())
.pipe(jscs.reporter())
@ -129,18 +129,20 @@ gulp.task('checkstyle', function () {
});
gulp.task('fixstyle', function () {
var jscs = require('gulp-jscs');
return gulp.src(paths.scripts, { base: '.' })
.pipe(jscs({ fix: true }))
.pipe(gulp.dest('.'));
});
gulp.task('static', ['stylesheets'], function () {
return gulp.src(paths.static, { base: '.' })
gulp.task('assets', ['stylesheets'], function () {
return gulp.src(paths.assets)
.pipe(gulp.dest(paths.dist));
});
gulp.task('watch', function () {
gulp.watch(paths.scss, ['stylesheets']);
return gulp.watch(paths.scss, ['stylesheets', 'assets']);
});
gulp.task('serve', function () {
@ -148,9 +150,9 @@ gulp.task('serve', function () {
var app = require('./app.js');
});
gulp.task('develop', ['serve', 'stylesheets', 'watch']);
gulp.task('develop', ['serve', 'install', 'watch']);
gulp.task('install', [ 'static', 'scripts' ]);
gulp.task('install', [ 'assets', 'scripts' ]);
gulp.task('verify', [ 'lint', 'test', 'checkstyle' ]);

47
main.js
View File

@ -65,49 +65,12 @@ requirejs.config({
define([
'./platform/framework/src/Main',
'legacyRegistry',
'./src/MCT',
'./src/adapter/bundle',
'./platform/framework/bundle',
'./platform/core/bundle',
'./platform/representation/bundle',
'./platform/commonUI/about/bundle',
'./platform/commonUI/browse/bundle',
'./platform/commonUI/edit/bundle',
'./platform/commonUI/dialog/bundle',
'./platform/commonUI/formats/bundle',
'./platform/commonUI/general/bundle',
'./platform/commonUI/inspect/bundle',
'./platform/commonUI/mobile/bundle',
'./platform/commonUI/themes/espresso/bundle',
'./platform/commonUI/notification/bundle',
'./platform/containment/bundle',
'./platform/execution/bundle',
'./platform/exporters/bundle',
'./platform/telemetry/bundle',
'./platform/features/clock/bundle',
'./platform/features/imagery/bundle',
'./platform/features/layout/bundle',
'./platform/features/pages/bundle',
'./platform/features/plot/bundle',
'./platform/features/timeline/bundle',
'./platform/features/table/bundle',
'./platform/forms/bundle',
'./platform/identity/bundle',
'./platform/persistence/aggregator/bundle',
'./platform/persistence/local/bundle',
'./platform/persistence/queue/bundle',
'./platform/policy/bundle',
'./platform/entanglement/bundle',
'./platform/search/bundle',
'./platform/status/bundle',
'./platform/commonUI/regions/bundle'
], function (Main, legacyRegistry, MCT) {
'./src/defaultRegistry',
'./src/MCT'
], function (Main, defaultRegistry, MCT) {
var mct = new MCT();
mct.legacyRegistry = legacyRegistry;
mct.legacyRegistry = defaultRegistry;
mct.run = function (domElement) {
if (!domElement) { domElement = document.body; }
var appDiv = document.createElement('div');
@ -117,7 +80,7 @@ define([
mct.start();
};
mct.on('start', function () {
return new Main().run(legacyRegistry);
return new Main().run(defaultRegistry);
});
return mct;

View File

@ -39,6 +39,7 @@ define([
"text!./res/templates/items/items.html",
"text!./res/templates/browse/object-properties.html",
"text!./res/templates/browse/inspector-region.html",
"text!./res/templates/view-object.html",
'legacyRegistry'
], function (
BrowseController,
@ -59,6 +60,7 @@ define([
itemsTemplate,
objectPropertiesTemplate,
inspectorRegionTemplate,
viewObjectTemplate,
legacyRegistry
) {
@ -129,7 +131,7 @@ define([
"representations": [
{
"key": "view-object",
"templateUrl": "templates/view-object.html"
"template": viewObjectTemplate
},
{
"key": "browse-object",

View File

@ -148,7 +148,8 @@ define([
"depends": [
"stylesheets[]",
"$document",
"THEME"
"THEME",
"ASSETS_PATH"
]
},
{
@ -406,6 +407,11 @@ define([
"key": "THEME",
"value": "unspecified",
"priority": "fallback"
},
{
"key": "ASSETS_PATH",
"value": ".",
"priority": "fallback"
}
],
"containers": [

View File

@ -38,7 +38,7 @@ define(
* @param $document Angular's jqLite-wrapped document element
* @param {string} activeTheme the theme in use
*/
function StyleSheetLoader(stylesheets, $document, activeTheme) {
function StyleSheetLoader(stylesheets, $document, activeTheme, assetPath) {
var head = $document.find('head'),
document = $document[0];
@ -47,6 +47,7 @@ define(
// Create a link element, and construct full path
var link = document.createElement('link'),
path = [
assetPath,
stylesheet.bundle.path,
stylesheet.bundle.resources,
stylesheet.stylesheetUrl

View File

@ -42,11 +42,19 @@ define(
function addWorker(worker) {
var key = worker.key;
if (!workerUrls[key]) {
workerUrls[key] = [
worker.bundle.path,
worker.bundle.sources,
worker.scriptUrl
].join("/");
if (worker.scriptUrl) {
workerUrls[key] = [
worker.bundle.path,
worker.bundle.sources,
worker.scriptUrl
].join("/");
} else if (worker.scriptText) {
var blob = new Blob(
[worker.scriptText],
{type: 'application/javascript'}
);
workerUrls[key] = URL.createObjectURL(blob);
}
sharedWorkers[key] = worker.shared;
}
}

View File

@ -27,6 +27,9 @@ define([
"./src/controllers/TableOptionsController",
'../../commonUI/regions/src/Region',
'../../commonUI/browse/src/InspectorRegion',
"text!./res/templates/table-options-edit.html",
"text!./res/templates/rt-table.html",
"text!./res/templates/historical-table.html",
"legacyRegistry"
], function (
MCTTable,
@ -35,6 +38,9 @@ define([
TableOptionsController,
Region,
InspectorRegion,
tableOptionsEditTemplate,
rtTableTemplate,
historicalTableTemplate,
legacyRegistry
) {
/**
@ -128,7 +134,7 @@ define([
"name": "Historical Table",
"key": "table",
"glyph": "\ue604",
"templateUrl": "templates/historical-table.html",
"template": historicalTableTemplate,
"needs": [
"telemetry"
],
@ -139,7 +145,7 @@ define([
"name": "Real-time Table",
"key": "rt-table",
"glyph": "\ue620",
"templateUrl": "templates/rt-table.html",
"template": rtTableTemplate,
"needs": [
"telemetry"
],
@ -157,7 +163,7 @@ define([
"representations": [
{
"key": "table-options-edit",
"templateUrl": "templates/table-options-edit.html"
"template": tableOptionsEditTemplate
}
],
"stylesheets": [

View File

@ -28,6 +28,7 @@ define([
"text!./res/templates/search-item.html",
"text!./res/templates/search.html",
"text!./res/templates/search-menu.html",
"text!./src/services/GenericSearchWorker.js",
'legacyRegistry'
], function (
SearchController,
@ -37,6 +38,7 @@ define([
searchItemTemplate,
searchTemplate,
searchMenuTemplate,
searchWorkerText,
legacyRegistry
) {
@ -114,7 +116,7 @@ define([
"workers": [
{
"key": "genericSearchWorker",
"scriptUrl": "services/GenericSearchWorker.js"
"scriptText": searchWorkerText
}
]
}

View File

@ -24,10 +24,27 @@ define(function () {
function BundleRegistry() {
this.bundles = {};
this.knownBundles = {};
}
BundleRegistry.prototype.register = function (path, definition) {
this.bundles[path] = definition;
if (this.knownBundles.hasOwnProperty(path)) {
throw new Error('Cannot register bundle with duplicate path', path);
}
this.knownBundles[path] = definition;
};
BundleRegistry.prototype.enable = function (path) {
if (!this.knownBundles[path]) {
throw new Error('Unknown bundle ' + path);
}
this.bundles[path] = this.knownBundles[path];
};
BundleRegistry.prototype.disable = function (path) {
if (!this.bundles[path]) {
throw new Error('Tried to disable inactive bundle ' + path);
}
};
BundleRegistry.prototype.contains = function (path) {
@ -42,8 +59,14 @@ define(function () {
return Object.keys(this.bundles);
};
BundleRegistry.prototype.remove = function (path) {
BundleRegistry.prototype.remove = BundleRegistry.prototype.disable;
BundleRegistry.prototype.delete = function (path) {
if (!this.knownBundles[path]) {
throw new Error('Cannot remove Unknown Bundle ' + path);
}
delete this.bundles[path];
delete this.knownBundles[path];
};
return BundleRegistry;

View File

@ -6,7 +6,6 @@ define([
'text!./adapter/templates/edit-object-replacement.html',
'./ui/Dialog',
'./Selection',
'./api/objects/bundle',
'./api/objects/object-utils'
], function (
EventEmitter,
@ -16,7 +15,6 @@ define([
editObjectTemplate,
Dialog,
Selection,
objectAPIBundle,
objectUtils
) {
function MCT() {
@ -49,6 +47,16 @@ define([
this.legacyBundle.extensions[category].push(extension);
};
/**
* Set path to where assets are hosted. This should be the path to main.js.
*/
MCT.prototype.setAssetPath = function (path) {
this.legacyExtension('constants', {
key: "ASSETS_PATH",
value: path
});
};
/**
* Register a new type of view.
*
@ -125,6 +133,7 @@ define([
});
legacyRegistry.register('adapter', this.legacyBundle);
legacyRegistry.enable('adapter');
this.emit('start');
};

113
src/defaultRegistry.js Normal file
View File

@ -0,0 +1,113 @@
define([
'legacyRegistry',
'../src/adapter/bundle',
'../src/api/objects/bundle',
'../example/builtins/bundle',
'../example/composite/bundle',
'../example/eventGenerator/bundle',
'../example/export/bundle',
'../example/extensions/bundle',
'../example/forms/bundle',
'../example/generator/bundle',
'../example/identity/bundle',
'../example/imagery/bundle',
'../example/mobile/bundle',
'../example/msl/bundle',
'../example/notifications/bundle',
'../example/persistence/bundle',
'../example/plotOptions/bundle',
'../example/policy/bundle',
'../example/profiling/bundle',
'../example/scratchpad/bundle',
'../example/taxonomy/bundle',
'../example/worker/bundle',
'../platform/commonUI/about/bundle',
'../platform/commonUI/browse/bundle',
'../platform/commonUI/dialog/bundle',
'../platform/commonUI/edit/bundle',
'../platform/commonUI/formats/bundle',
'../platform/commonUI/general/bundle',
'../platform/commonUI/inspect/bundle',
'../platform/commonUI/mobile/bundle',
'../platform/commonUI/notification/bundle',
'../platform/commonUI/regions/bundle',
'../platform/commonUI/themes/espresso/bundle',
'../platform/commonUI/themes/snow/bundle',
'../platform/containment/bundle',
'../platform/core/bundle',
'../platform/entanglement/bundle',
'../platform/execution/bundle',
'../platform/exporters/bundle',
'../platform/features/clock/bundle',
'../platform/features/conductor/bundle',
'../platform/features/imagery/bundle',
'../platform/features/layout/bundle',
'../platform/features/pages/bundle',
'../platform/features/plot/bundle',
'../platform/features/static-markup/bundle',
'../platform/features/table/bundle',
'../platform/features/timeline/bundle',
'../platform/forms/bundle',
'../platform/framework/bundle',
'../platform/framework/src/load/Bundle',
'../platform/identity/bundle',
'../platform/persistence/aggregator/bundle',
'../platform/persistence/couch/bundle',
'../platform/persistence/elastic/bundle',
'../platform/persistence/local/bundle',
'../platform/persistence/queue/bundle',
'../platform/policy/bundle',
'../platform/representation/bundle',
'../platform/search/bundle',
'../platform/status/bundle',
'../platform/telemetry/bundle',
], function (legacyRegistry) {
var DEFAULTS = [
'src/adapter',
'src/api/objects',
'platform/framework',
'platform/core',
'platform/representation',
'platform/commonUI/about',
'platform/commonUI/browse',
'platform/commonUI/edit',
'platform/commonUI/dialog',
'platform/commonUI/formats',
'platform/commonUI/general',
'platform/commonUI/inspect',
'platform/commonUI/mobile',
'platform/commonUI/themes/espresso',
'platform/commonUI/notification',
'platform/containment',
'platform/execution',
'platform/exporters',
'platform/telemetry',
'platform/features/clock',
'platform/features/imagery',
'platform/features/layout',
'platform/features/pages',
'platform/features/plot',
'platform/features/timeline',
'platform/features/table',
'platform/forms',
'platform/identity',
'platform/persistence/aggregator',
'platform/persistence/local',
'platform/persistence/queue',
'platform/policy',
'platform/entanglement',
'platform/search',
'platform/status',
'platform/commonUI/regions'
];
DEFAULTS.forEach(function (bundlePath) {
legacyRegistry.enable(bundlePath);
});
return legacyRegistry;
});

View File

@ -48,22 +48,20 @@ define([
var self = this;
this.destroy();
mct.Objects.get(utils.parseKeyString(self.domainObject.getId())).then(function (object) {
self.$els = $(todoTemplate);
self.$buttons = {
all: self.$els.find('.example-todo-button-all'),
incomplete: self.$els.find('.example-todo-button-incomplete'),
complete: self.$els.find('.example-todo-button-complete')
};
self.$els = $(todoTemplate);
self.$buttons = {
all: self.$els.find('.example-todo-button-all'),
incomplete: self.$els.find('.example-todo-button-incomplete'),
complete: self.$els.find('.example-todo-button-complete')
};
$(container).empty().append(self.$els);
$(container).empty().append(self.$els);
self.initialize();
self.objectChanged(object);
self.initialize();
self.objectChanged(this.domainObject);
mct.selection.on('change', self.render);
});
mct.selection.on('change', self.render);
};
TodoView.prototype.destroy = function () {
@ -148,47 +146,44 @@ define([
var self = this;
this.destroy();
mct.Objects.get(utils.parseKeyString(this.domainObject.getId())).then(function (wrappedObject){
self.mutableObject = mct.Objects.getMutable(this.domainObject);
self.mutableObject = mct.Objects.getMutable(wrappedObject);
var $els = $(toolbarTemplate);
var $add = $els.find('a.example-add');
var $remove = $els.find('a.example-remove');
var $els = $(toolbarTemplate);
var $add = $els.find('a.example-add');
var $remove = $els.find('a.example-remove');
$(container).append($els);
$(container).append($els);
$add.on('click', function () {
var $dialog = $(dialogTemplate),
view = {
show: function (container) {
$(container).append($dialog);
},
destroy: function () {}
};
$add.on('click', function () {
var $dialog = $(dialogTemplate),
view = {
show: function (container) {
$(container).append($dialog);
},
destroy: function () {}
};
mct.dialog(view, "Add a Task").then(function () {
var description = $dialog.find('input').val();
var tasks = self.mutableObject.get('tasks');
tasks.push({ description: description });
self.mutableObject.set('tasks', tasks);
});
mct.dialog(view, "Add a Task").then(function () {
var description = $dialog.find('input').val();
var tasks = self.mutableObject.get('tasks');
tasks.push({ description: description });
self.mutableObject.set('tasks', tasks);
});
$remove.on('click', function () {
var index = mct.selection.selected()[0].index;
if (index !== undefined) {
var tasks = self.mutableObject.get('tasks').filter(function (t, i) {
return i !== index;
});
self.mutableObject.set("tasks", tasks);
self.mutableObject.set("selected", undefined);
mct.selection.clear();
}
});
self.$remove = $remove;
self.handleSelectionChange();
mct.selection.on('change', self.handleSelectionChange);
});
$remove.on('click', function () {
var index = mct.selection.selected()[0].index;
if (index !== undefined) {
var tasks = self.mutableObject.get('tasks').filter(function (t, i) {
return i !== index;
});
self.mutableObject.set("tasks", tasks);
self.mutableObject.set("selected", undefined);
mct.selection.clear();
}
});
self.$remove = $remove;
self.handleSelectionChange();
mct.selection.on('change', self.handleSelectionChange);
};
TodoToolbarView.prototype.handleSelectionChange = function () {