mirror of
https://github.com/nasa/openmct.git
synced 2025-04-11 13:20:18 +00:00
Merge remote-tracking branch 'origin/open667' into open-master
This commit is contained in:
commit
7c0cf22b27
bundles.json
platform
commonUI
about
dialog
general/res/templates
core
framework
representation/src
@ -2,6 +2,7 @@
|
||||
"platform/framework",
|
||||
"platform/core",
|
||||
"platform/representation",
|
||||
"platform/commonUI/about",
|
||||
"platform/commonUI/browse",
|
||||
"platform/commonUI/edit",
|
||||
"platform/commonUI/dialog",
|
||||
|
26
platform/commonUI/about/README.md
Normal file
26
platform/commonUI/about/README.md
Normal file
@ -0,0 +1,26 @@
|
||||
The "about" bundle provides the default lower-right application logo,
|
||||
as well as the dialog it launches when clicked.
|
||||
|
||||
# Extensions
|
||||
|
||||
The About dialog contains several line items to display different
|
||||
version properties (e.g. when built, et cetera.) Plug-ins may wish
|
||||
to introduce additional line items here, in particular if the
|
||||
platform is used to build a separately-branded piece of software.
|
||||
|
||||
This bundle introduces the `versions` extension category to support this.
|
||||
An extension of this category is implementation-less (all information
|
||||
is contained within its declaration) and should include the following
|
||||
fields:
|
||||
|
||||
* `name`: The name to display for this version line-item; this may
|
||||
be the name of the software, or something else such as "Built".
|
||||
* `value`: The value to display corresponding to this line-item;
|
||||
this is typically a version number, revision identifier, or
|
||||
human-readable date.
|
||||
* `description`: Optional; a longer-form description of this line
|
||||
item, to display in a tooltip.
|
||||
|
||||
Ordering of these line items is handled by extension priority; see framework
|
||||
documentation (`platform/framework/README.md`) for information on how
|
||||
this ordering is handled.
|
43
platform/commonUI/about/bundle.json
Normal file
43
platform/commonUI/about/bundle.json
Normal file
@ -0,0 +1,43 @@
|
||||
{
|
||||
"name": "About Open MCT Web",
|
||||
"extensions": {
|
||||
"templates": [
|
||||
{
|
||||
"key": "app-logo",
|
||||
"priority": "optional",
|
||||
"templateUrl": "templates/app-logo.html"
|
||||
},
|
||||
{
|
||||
"key": "about-logo",
|
||||
"priority": "preferred",
|
||||
"templateUrl": "templates/about-logo.html"
|
||||
},
|
||||
{
|
||||
"key": "about-dialog",
|
||||
"templateUrl": "templates/about-dialog.html"
|
||||
},
|
||||
{
|
||||
"key": "overlay-about",
|
||||
"templateUrl": "templates/overlay-about.html"
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
{
|
||||
"key": "LogoController",
|
||||
"depends": [ "overlayService" ],
|
||||
"implementation": "LogoController.js"
|
||||
},
|
||||
{
|
||||
"key": "AboutController",
|
||||
"depends": [ "versions[]", "$window" ],
|
||||
"implementation": "AboutController.js"
|
||||
}
|
||||
],
|
||||
"routes": [
|
||||
{
|
||||
"when": "/licenses",
|
||||
"templateUrl": "templates/licenses.html"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
12
platform/commonUI/about/res/templates/about-dialog.html
Normal file
12
platform/commonUI/about/res/templates/about-dialog.html
Normal file
@ -0,0 +1,12 @@
|
||||
<div ng-controller = "AboutController as about">
|
||||
This is a placeholder for the about dialog.
|
||||
|
||||
<a ng-click="about.openLicenses()">Show licenses.</a>
|
||||
|
||||
<p ng-repeat = "version in about.versions()">
|
||||
<span title="{{version.description}}">
|
||||
<b>{{version.name}}</b>
|
||||
<i>{{version.value}}</i>
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
4
platform/commonUI/about/res/templates/about-logo.html
Normal file
4
platform/commonUI/about/res/templates/about-logo.html
Normal file
@ -0,0 +1,4 @@
|
||||
<span ng-controller="LogoController as logo">
|
||||
<mct-include ng-click="logo.showAboutDialog()" key="'app-logo'">
|
||||
</mct-include>
|
||||
</span>
|
1
platform/commonUI/about/res/templates/app-logo.html
Normal file
1
platform/commonUI/about/res/templates/app-logo.html
Normal file
@ -0,0 +1 @@
|
||||
<span><div class='app-logo abs'>Open MCT Web</div></span>
|
1
platform/commonUI/about/res/templates/licenses.html
Normal file
1
platform/commonUI/about/res/templates/licenses.html
Normal file
@ -0,0 +1 @@
|
||||
Placeholder for open source licenses.
|
4
platform/commonUI/about/res/templates/overlay-about.html
Normal file
4
platform/commonUI/about/res/templates/overlay-about.html
Normal file
@ -0,0 +1,4 @@
|
||||
<mct-container key="overlay">
|
||||
<mct-include key="'about-dialog'">
|
||||
</mct-include>
|
||||
</mct-container>
|
42
platform/commonUI/about/src/AboutController.js
Normal file
42
platform/commonUI/about/src/AboutController.js
Normal file
@ -0,0 +1,42 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The AboutController provides information to populate the
|
||||
* About dialog.
|
||||
* @constructor
|
||||
* @param {object[]} versions an array of version extensions;
|
||||
* injected from `versions[]`
|
||||
* @param $window Angular-injected window object
|
||||
*/
|
||||
function AboutController(versions, $window) {
|
||||
return {
|
||||
/**
|
||||
* Get version info. This is given as an array of
|
||||
* objects, where each object is intended to appear
|
||||
* as a line-item in the version information listing.
|
||||
* @memberof AboutController#
|
||||
* @returns {object[]} version information
|
||||
*/
|
||||
versions: function () {
|
||||
return versions;
|
||||
},
|
||||
/**
|
||||
* Open a new window (or tab, depending on browser
|
||||
* configuration) containing open source licenses.
|
||||
* @memberof AboutController#
|
||||
*/
|
||||
openLicenses: function () {
|
||||
// Open a new browser window at the licenses route
|
||||
$window.open("#/licenses");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return AboutController;
|
||||
}
|
||||
);
|
28
platform/commonUI/about/src/LogoController.js
Normal file
28
platform/commonUI/about/src/LogoController.js
Normal file
@ -0,0 +1,28 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The LogoController provides functionality to the application
|
||||
* logo in the bottom-right of the user interface.
|
||||
* @constructor
|
||||
* @param {OverlayService} overlayService the overlay service
|
||||
*/
|
||||
function LogoController(overlayService) {
|
||||
return {
|
||||
/**
|
||||
* Display the About dialog.
|
||||
* @memberof LogoController#
|
||||
*/
|
||||
showAboutDialog: function () {
|
||||
overlayService.createOverlay("overlay-about");
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return LogoController;
|
||||
}
|
||||
);
|
39
platform/commonUI/about/test/AboutControllerSpec.js
Normal file
39
platform/commonUI/about/test/AboutControllerSpec.js
Normal file
@ -0,0 +1,39 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
['../src/AboutController'],
|
||||
function (AboutController) {
|
||||
"use strict";
|
||||
|
||||
describe("The About controller", function () {
|
||||
var testVersions,
|
||||
mockWindow,
|
||||
controller;
|
||||
|
||||
beforeEach(function () {
|
||||
testVersions = [
|
||||
{ name: "Some name", value: "1.2.3" },
|
||||
{ name: "Some other name", value: "3.2.1" }
|
||||
];
|
||||
mockWindow = jasmine.createSpyObj("$window", ["open"]);
|
||||
controller = new AboutController(testVersions, mockWindow);
|
||||
});
|
||||
|
||||
it("exposes version information", function () {
|
||||
// This will be injected, so it should just give back
|
||||
// what it got in.
|
||||
expect(controller.versions()).toEqual(testVersions);
|
||||
});
|
||||
|
||||
it("opens license information in a window", function () {
|
||||
//Verify precondition
|
||||
expect(mockWindow.open).not.toHaveBeenCalled();
|
||||
controller.openLicenses();
|
||||
expect(mockWindow.open).toHaveBeenCalledWith("#/licenses");
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
);
|
32
platform/commonUI/about/test/LogoControllerSpec.js
Normal file
32
platform/commonUI/about/test/LogoControllerSpec.js
Normal file
@ -0,0 +1,32 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
['../src/LogoController'],
|
||||
function (LogoController) {
|
||||
"use strict";
|
||||
|
||||
describe("The About controller", function () {
|
||||
var mockOverlayService,
|
||||
controller;
|
||||
|
||||
beforeEach(function () {
|
||||
mockOverlayService = jasmine.createSpyObj(
|
||||
"overlayService",
|
||||
["createOverlay"]
|
||||
);
|
||||
controller = new LogoController(mockOverlayService);
|
||||
});
|
||||
|
||||
it("shows the about dialog", function () {
|
||||
//Verify precondition
|
||||
expect(mockOverlayService.createOverlay)
|
||||
.not.toHaveBeenCalled();
|
||||
controller.showAboutDialog();
|
||||
expect(mockOverlayService.createOverlay)
|
||||
.toHaveBeenCalledWith("overlay-about");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
);
|
4
platform/commonUI/about/test/suite.json
Normal file
4
platform/commonUI/about/test/suite.json
Normal file
@ -0,0 +1,4 @@
|
||||
[
|
||||
"AboutController",
|
||||
"LogoController"
|
||||
]
|
@ -15,6 +15,16 @@
|
||||
"templates": [
|
||||
{
|
||||
"key": "overlay-dialog",
|
||||
"templateUrl": "templates/overlay-dialog.html"
|
||||
},
|
||||
{
|
||||
"key": "form-dialog",
|
||||
"templateUrl": "templates/dialog.html"
|
||||
}
|
||||
],
|
||||
"containers": [
|
||||
{
|
||||
"key": "overlay",
|
||||
"templateUrl": "templates/overlay.html"
|
||||
}
|
||||
]
|
||||
|
25
platform/commonUI/dialog/res/templates/dialog.html
Normal file
25
platform/commonUI/dialog/res/templates/dialog.html
Normal file
@ -0,0 +1,25 @@
|
||||
<div class="abs top-bar">
|
||||
<div class="title">{{ngModel.title}}</div>
|
||||
<div class="hint">
|
||||
All fields marked <span class="ui-symbol req">*</span> are required.
|
||||
</div>
|
||||
</div>
|
||||
<div class="abs form outline editor">
|
||||
<div class='abs contents'>
|
||||
<mct-form ng-model="ngModel.value"
|
||||
structure="ngModel.structure"
|
||||
name="createForm">
|
||||
</mct-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="abs bottom-bar">
|
||||
<a class='btn lg major'
|
||||
href=''
|
||||
ng-class="{ disabled: !createForm.$valid }"
|
||||
ng-click="ngModel.confirm()">
|
||||
OK
|
||||
</a>
|
||||
<a class='btn lg subtle' href='' ng-click="ngModel.cancel()">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
@ -0,0 +1,4 @@
|
||||
<mct-container key="overlay">
|
||||
<mct-include key="'form-dialog'" ng-model="ngModel">
|
||||
</mct-include>
|
||||
</mct-container>
|
@ -3,32 +3,12 @@
|
||||
<div class="abs holder">
|
||||
<a href=""
|
||||
ng-click="ngModel.cancel()"
|
||||
class="btn normal outline ui-symbol close">x</a>
|
||||
<div class="abs contents">
|
||||
<div class="abs top-bar">
|
||||
<div class="title">{{ngModel.title}}</div>
|
||||
<div class="hint">All fields marked <span class="ui-symbol req">*</span> are required.</div>
|
||||
</div>
|
||||
<div class="abs form outline editor">
|
||||
<div class='abs contents'>
|
||||
<!-- mct-include key="'form'" ng-model="" -->
|
||||
<mct-form ng-model="ngModel.value"
|
||||
structure="ngModel.structure"
|
||||
name="createForm">
|
||||
</mct-form>
|
||||
</div>
|
||||
</div>
|
||||
<div class="abs bottom-bar">
|
||||
<a class='btn lg major'
|
||||
href=''
|
||||
ng-class="{ disabled: !createForm.$valid }"
|
||||
ng-click="ngModel.confirm()">
|
||||
OK
|
||||
</a>
|
||||
<a class='btn lg subtle' href='' ng-click="ngModel.cancel()">
|
||||
Cancel
|
||||
</a>
|
||||
</div>
|
||||
ng-if="ngModel.cancel"
|
||||
class="btn normal outline ui-symbol close">
|
||||
x
|
||||
</a>
|
||||
<div class="abs contents" ng-transclude>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
@ -76,8 +76,8 @@ define(
|
||||
// Add the overlay using the OverlayService, which
|
||||
// will handle actual insertion into the DOM
|
||||
overlay = overlayService.createOverlay(
|
||||
overlayModel,
|
||||
"overlay-dialog"
|
||||
"overlay-dialog",
|
||||
overlayModel
|
||||
);
|
||||
|
||||
// Track that a dialog is already visible, to
|
||||
|
@ -25,11 +25,21 @@ define(
|
||||
* @constructor
|
||||
*/
|
||||
function OverlayService($document, $compile, $rootScope) {
|
||||
function createOverlay(overlayModel, key) {
|
||||
function createOverlay(key, overlayModel) {
|
||||
// Create a new scope for this overlay
|
||||
var scope = $rootScope.$new(),
|
||||
element;
|
||||
|
||||
// Stop showing the overlay; additionally, release the scope
|
||||
// that it uses.
|
||||
function dismiss() {
|
||||
scope.$destroy();
|
||||
element.remove();
|
||||
}
|
||||
|
||||
// If no model is supplied, just fill in a default "cancel"
|
||||
overlayModel = overlayModel || { cancel: dismiss };
|
||||
|
||||
// Populate the scope; will be passed directly to the template
|
||||
scope.overlay = overlayModel;
|
||||
scope.key = key;
|
||||
@ -38,12 +48,7 @@ define(
|
||||
element = $compile(TEMPLATE)(scope);
|
||||
$document.find('body').prepend(element);
|
||||
|
||||
// Stop showing the overlay; additionally, release the scope
|
||||
// that it uses.
|
||||
function dismiss() {
|
||||
scope.$destroy();
|
||||
element.remove();
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
dismiss: dismiss
|
||||
@ -57,11 +62,12 @@ define(
|
||||
* template (as pointed to by the `key` argument) is
|
||||
* responsible for having a useful z-order, and for
|
||||
* blocking user interactions if appropriate.
|
||||
*
|
||||
* @param {string} key the symbolic key which identifies
|
||||
* the template of the overlay to be shown
|
||||
* @param {object} overlayModel the model to pass to the
|
||||
* included overlay template (this will be passed
|
||||
* in via ng-model)
|
||||
* @param {string} key the symbolic key which identifies
|
||||
* the template of the overlay to be shown
|
||||
*/
|
||||
createOverlay: createOverlay
|
||||
};
|
||||
|
@ -56,7 +56,7 @@ define(
|
||||
|
||||
it("allows user input to be canceled", function () {
|
||||
dialogService.getUserInput({}, { someKey: "some value" });
|
||||
mockOverlayService.createOverlay.mostRecentCall.args[0].cancel();
|
||||
mockOverlayService.createOverlay.mostRecentCall.args[1].cancel();
|
||||
expect(mockDeferred.reject).toHaveBeenCalled();
|
||||
expect(mockDeferred.resolve).not.toHaveBeenCalled();
|
||||
});
|
||||
@ -64,7 +64,7 @@ define(
|
||||
it("passes back the result of user input when confirmed", function () {
|
||||
var value = { someKey: 42 };
|
||||
dialogService.getUserInput({}, value);
|
||||
mockOverlayService.createOverlay.mostRecentCall.args[0].confirm();
|
||||
mockOverlayService.createOverlay.mostRecentCall.args[1].confirm();
|
||||
expect(mockDeferred.reject).not.toHaveBeenCalled();
|
||||
expect(mockDeferred.resolve).toHaveBeenCalledWith(value);
|
||||
});
|
||||
@ -80,7 +80,7 @@ define(
|
||||
it("can show multiple dialogs if prior ones are dismissed", function () {
|
||||
dialogService.getUserInput({}, {});
|
||||
expect(mockLog.warn).not.toHaveBeenCalled();
|
||||
mockOverlayService.createOverlay.mostRecentCall.args[0].confirm();
|
||||
mockOverlayService.createOverlay.mostRecentCall.args[1].confirm();
|
||||
dialogService.getUserInput({}, {});
|
||||
expect(mockLog.warn).not.toHaveBeenCalled();
|
||||
expect(mockDeferred.reject).not.toHaveBeenCalled();
|
||||
|
@ -8,7 +8,7 @@ define(
|
||||
function (OverlayService) {
|
||||
"use strict";
|
||||
|
||||
describe("The dialog service", function () {
|
||||
describe("The overlay service", function () {
|
||||
var mockDocument,
|
||||
mockCompile,
|
||||
mockRootScope,
|
||||
@ -40,19 +40,19 @@ define(
|
||||
});
|
||||
|
||||
it("prepends an mct-include to create overlays", function () {
|
||||
overlayService.createOverlay({}, "test");
|
||||
overlayService.createOverlay("test", {});
|
||||
expect(mockCompile).toHaveBeenCalled();
|
||||
expect(mockCompile.mostRecentCall.args[0].indexOf("mct-include"))
|
||||
.not.toEqual(-1);
|
||||
});
|
||||
|
||||
it("adds the templated element to the body", function () {
|
||||
overlayService.createOverlay({}, "test");
|
||||
overlayService.createOverlay("test", {});
|
||||
expect(mockBody.prepend).toHaveBeenCalledWith(mockElement);
|
||||
});
|
||||
|
||||
it("places the provided model/key in its template's scope", function () {
|
||||
overlayService.createOverlay({ someKey: 42 }, "test");
|
||||
overlayService.createOverlay("test", { someKey: 42 });
|
||||
expect(mockScope.overlay).toEqual({ someKey: 42 });
|
||||
expect(mockScope.key).toEqual("test");
|
||||
|
||||
@ -61,7 +61,7 @@ define(
|
||||
});
|
||||
|
||||
it("removes the prepended element on request", function () {
|
||||
var overlay = overlayService.createOverlay({}, "test");
|
||||
var overlay = overlayService.createOverlay("test", {});
|
||||
|
||||
// Verify precondition
|
||||
expect(mockElement.remove).not.toHaveBeenCalled();
|
||||
|
@ -5,5 +5,5 @@
|
||||
key="indicator.template">
|
||||
</mct-include>
|
||||
</div>
|
||||
<!--mct-include key="'app-logo'"></mct-include-->
|
||||
<mct-include key="'about-logo'"></mct-include>
|
||||
</div>
|
@ -3,6 +3,19 @@
|
||||
"description": "Defines core concepts of Open MCT Web.",
|
||||
"sources": "src",
|
||||
"extensions": {
|
||||
"versions": [
|
||||
{
|
||||
"name": "Open MCT Web",
|
||||
"value": "0.3.0-dev",
|
||||
"priority": 1000
|
||||
},
|
||||
{
|
||||
"name": "Built",
|
||||
"value": "YYYY-MM-DDTHH:MM:ssZ",
|
||||
"description": "The date on which this version of the client was built.",
|
||||
"priority": 990
|
||||
}
|
||||
],
|
||||
"components": [
|
||||
{
|
||||
"provides": "objectService",
|
||||
|
@ -12,5 +12,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"extensions": {}
|
||||
"extensions": {
|
||||
}
|
||||
}
|
@ -37,12 +37,14 @@ define(
|
||||
|
||||
// Prepopulate templateMap for easy look up by key
|
||||
templates.forEach(function (template) {
|
||||
var path = [
|
||||
template.bundle.path,
|
||||
template.bundle.resources,
|
||||
template.templateUrl
|
||||
].join("/");
|
||||
templateMap[template.key] = path;
|
||||
var key = template.key,
|
||||
path = [
|
||||
template.bundle.path,
|
||||
template.bundle.resources,
|
||||
template.templateUrl
|
||||
].join("/");
|
||||
// First found should win (priority ordering)
|
||||
templateMap[key] = templateMap[key] || path;
|
||||
});
|
||||
|
||||
function controller($scope) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user