Merge remote-tracking branch 'origin/open667' into open-master

This commit is contained in:
bwyu 2015-01-16 13:50:53 -08:00
commit 7c0cf22b27
25 changed files with 331 additions and 53 deletions

@ -2,6 +2,7 @@
"platform/framework",
"platform/core",
"platform/representation",
"platform/commonUI/about",
"platform/commonUI/browse",
"platform/commonUI/edit",
"platform/commonUI/dialog",

@ -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.

@ -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"
}
]
}
}

@ -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>

@ -0,0 +1,4 @@
<span ng-controller="LogoController as logo">
<mct-include ng-click="logo.showAboutDialog()" key="'app-logo'">
</mct-include>
</span>

@ -0,0 +1 @@
<span><div class='app-logo abs'>Open MCT Web</div></span>

@ -0,0 +1 @@
Placeholder for open source licenses.

@ -0,0 +1,4 @@
<mct-container key="overlay">
<mct-include key="'about-dialog'">
</mct-include>
</mct-container>

@ -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;
}
);

@ -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;
}
);

@ -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");
});
});
}
);

@ -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");
});
});
}
);

@ -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"
}
]

@ -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) {