mirror of
https://github.com/nasa/openmct.git
synced 2024-12-19 21:27:52 +00:00
Merge branch 'open-master' into open1241
Merge latest from master branch into topic branch for WTD-1241.
This commit is contained in:
commit
14fbd64ae4
3
.gitignore
vendored
3
.gitignore
vendored
@ -17,3 +17,6 @@ target
|
||||
# Closed source libraries
|
||||
closed-lib
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
|
62
app.js
Normal file
62
app.js
Normal file
@ -0,0 +1,62 @@
|
||||
/*global require,process,console*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* npm install minimist express
|
||||
* node app.js [options]
|
||||
*/
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var BUNDLE_FILE = 'bundles.json',
|
||||
options = require('minimist')(process.argv.slice(2)),
|
||||
express = require('express'),
|
||||
app = express(),
|
||||
fs = require('fs'),
|
||||
bundles = JSON.parse(fs.readFileSync(BUNDLE_FILE, 'utf8'));
|
||||
|
||||
// Defaults
|
||||
options.port = options.port || options.p || 8080;
|
||||
['include', 'exclude', 'i', 'x'].forEach(function (opt) {
|
||||
options[opt] = options[opt] || [];
|
||||
// Make sure includes/excludes always end up as arrays
|
||||
options[opt] = Array.isArray(options[opt]) ?
|
||||
options[opt] : [options[opt]];
|
||||
});
|
||||
options.include = options.include.concat(options.i);
|
||||
options.exclude = options.exclude.concat(options.x);
|
||||
|
||||
// Show command line options
|
||||
if (options.help || options.h) {
|
||||
console.log("\nUsage: node app.js [options]\n");
|
||||
console.log("Options:");
|
||||
console.log(" --help, -h Show this message.");
|
||||
console.log(" --port, -p <number> Specify port.");
|
||||
console.log(" --include, -i <bundle> Include the specified bundle.");
|
||||
console.log(" --exclude, -x <bundle> Exclude the specified bundle.");
|
||||
console.log("");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Handle command line inclusions/exclusions
|
||||
bundles = bundles.concat(options.include);
|
||||
bundles = bundles.filter(function (bundle) {
|
||||
return options.exclude.indexOf(bundle) === -1;
|
||||
});
|
||||
bundles = bundles.filter(function (bundle, index) { // Uniquify
|
||||
return bundles.indexOf(bundle) === index;
|
||||
});
|
||||
|
||||
// Override bundles.json for HTTP requests
|
||||
app.use('/' + BUNDLE_FILE, function (req, res) {
|
||||
res.send(JSON.stringify(bundles));
|
||||
});
|
||||
|
||||
// Expose everything else as static files
|
||||
app.use(express['static']('.'));
|
||||
|
||||
// Finally, open the HTTP server
|
||||
app.listen(options.port);
|
||||
}());
|
@ -7,7 +7,9 @@
|
||||
"platform/commonUI/edit",
|
||||
"platform/commonUI/dialog",
|
||||
"platform/commonUI/general",
|
||||
"platform/commonUI/inspect",
|
||||
"platform/containment",
|
||||
"platform/execution",
|
||||
"platform/telemetry",
|
||||
"platform/features/layout",
|
||||
"platform/features/pages",
|
||||
@ -15,8 +17,8 @@
|
||||
"platform/features/scrolling",
|
||||
"platform/forms",
|
||||
"platform/persistence/queue",
|
||||
"platform/persistence/elastic",
|
||||
"platform/policy",
|
||||
|
||||
"example/persistence",
|
||||
"example/generator"
|
||||
]
|
||||
|
1
example/worker/README.md
Normal file
1
example/worker/README.md
Normal file
@ -0,0 +1 @@
|
||||
Example of running a Web Worker using the `workerService`.
|
16
example/worker/bundle.json
Normal file
16
example/worker/bundle.json
Normal file
@ -0,0 +1,16 @@
|
||||
{
|
||||
"extensions": {
|
||||
"indicators": [
|
||||
{
|
||||
"implementation": "FibonacciIndicator.js",
|
||||
"depends": [ "workerService", "$rootScope" ]
|
||||
}
|
||||
],
|
||||
"workers": [
|
||||
{
|
||||
"key": "example.fibonacci",
|
||||
"scriptUrl": "FibonacciWorker.js"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
70
example/worker/src/FibonacciIndicator.js
Normal file
70
example/worker/src/FibonacciIndicator.js
Normal file
@ -0,0 +1,70 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Displays Fibonacci numbers in the status area.
|
||||
* @constructor
|
||||
*/
|
||||
function FibonacciIndicator(workerService, $rootScope) {
|
||||
var latest,
|
||||
counter = 0,
|
||||
worker = workerService.run('example.fibonacci');
|
||||
|
||||
function requestNext() {
|
||||
worker.postMessage([counter]);
|
||||
counter += 1;
|
||||
}
|
||||
|
||||
function handleResponse(event) {
|
||||
latest = event.data;
|
||||
$rootScope.$apply();
|
||||
requestNext();
|
||||
}
|
||||
|
||||
worker.onmessage = handleResponse;
|
||||
requestNext();
|
||||
|
||||
return {
|
||||
getGlyph: function () {
|
||||
return "?";
|
||||
},
|
||||
getText: function () {
|
||||
return latest;
|
||||
},
|
||||
getGlyphClass: function () {
|
||||
return "";
|
||||
},
|
||||
getDescription: function () {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return FibonacciIndicator;
|
||||
}
|
||||
);
|
15
example/worker/src/FibonacciWorker.js
Normal file
15
example/worker/src/FibonacciWorker.js
Normal file
@ -0,0 +1,15 @@
|
||||
/*global self*/
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
// Calculate fibonacci numbers inefficiently.
|
||||
// We can do this because we're on a background thread, and
|
||||
// won't halt the UI.
|
||||
function fib(n) {
|
||||
return n < 2 ? n : (fib(n - 1) + fib(n - 2));
|
||||
}
|
||||
|
||||
self.onmessage = function (event) {
|
||||
self.postMessage(fib(event.data));
|
||||
};
|
||||
}());
|
@ -2,19 +2,26 @@
|
||||
"extensions": {
|
||||
"routes": [
|
||||
{
|
||||
"when": "/browse",
|
||||
"templateUrl": "templates/browse.html"
|
||||
"when": "/browse/:ids*",
|
||||
"templateUrl": "templates/browse.html",
|
||||
"reloadOnSearch": false
|
||||
},
|
||||
{
|
||||
"when": "",
|
||||
"templateUrl": "templates/browse.html"
|
||||
"templateUrl": "templates/browse.html",
|
||||
"reloadOnSearch": false
|
||||
}
|
||||
],
|
||||
"controllers": [
|
||||
{
|
||||
"key": "BrowseController",
|
||||
"implementation": "BrowseController.js",
|
||||
"depends": [ "$scope", "objectService", "navigationService" ]
|
||||
"depends": [ "$scope", "$route", "$location", "objectService", "navigationService" ]
|
||||
},
|
||||
{
|
||||
"key": "BrowseObjectController",
|
||||
"implementation": "BrowseObjectController.js",
|
||||
"depends": [ "$scope", "$location", "$route" ]
|
||||
},
|
||||
{
|
||||
"key": "CreateMenuController",
|
||||
@ -57,7 +64,8 @@
|
||||
{
|
||||
"key": "grid-item",
|
||||
"templateUrl": "templates/items/grid-item.html",
|
||||
"uses": [ "type", "action" ]
|
||||
"uses": [ "type", "action" ],
|
||||
"gestures": [ "info", "menu" ]
|
||||
},
|
||||
{
|
||||
"key": "object-header",
|
||||
|
@ -19,16 +19,14 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<span>
|
||||
<span ng-controller="BrowseObjectController">
|
||||
<div class="object-browse-bar bar abs">
|
||||
|
||||
<div class="items-select left abs">
|
||||
<mct-representation key="'object-header'" mct-object="domainObject">
|
||||
</mct-representation>
|
||||
</div>
|
||||
|
||||
<div class="view-controls sort-controls btn-bar right abs">
|
||||
|
||||
<div class="btn-bar right abs">
|
||||
<mct-representation key="'action-group'"
|
||||
mct-object="domainObject"
|
||||
parameters="{ category: 'view-control' }">
|
||||
@ -39,7 +37,6 @@
|
||||
ng-model="representation">
|
||||
</mct-representation>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class='object-holder abs vscroll'>
|
||||
|
@ -20,9 +20,11 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class='object-header'>
|
||||
<span class='type-icon icon ui-symbol'>{{type.getGlyph()}}</span>
|
||||
<span ng-if="parameters.mode" class='action'>{{parameters.mode}}</span>
|
||||
<span class='type'>{{type.getName()}}</span>
|
||||
<span class='title'>{{model.name}}</span>
|
||||
<a id='actions-menu' class='ui-symbol invoke-menu' onclick="alert('Not yet functional. This will display a dropdown menu of options for this object.');">v</a>
|
||||
<span class="label s-label">
|
||||
<span class='type-icon icon ui-symbol'>{{type.getGlyph()}}</span>
|
||||
<span ng-if="parameters.mode" class='action'>{{parameters.mode}}</span>
|
||||
<span class='type-name'>{{type.getName()}}</span>
|
||||
<span class='title-label'>{{model.name}}</span>
|
||||
<!--a id='actions-menu' class='ui-symbol context-available' onclick="alert('Not yet functional. This will display a dropdown menu of options for this object.');">v</a-->
|
||||
</span>
|
||||
</div>
|
@ -21,7 +21,7 @@
|
||||
-->
|
||||
<div class="menu-element wrapper" ng-controller="ClickAwayController as createController">
|
||||
<div class="btn btn-menu create-btn major" ng-click="createController.toggle()">
|
||||
<span class='ui-symbol major' href=''>+</span> Create<!--span class='ui-symbol invoke-menu'>v</span-->
|
||||
<span class='ui-symbol' href=''>+</span> Create
|
||||
</div>
|
||||
<div class="menu dropdown super-menu" ng-show="createController.isActive()">
|
||||
<mct-representation mct-object="domainObject" key="'create-menu'">
|
||||
|
@ -29,7 +29,8 @@ define(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
var ROOT_OBJECT = "ROOT";
|
||||
var ROOT_ID = "ROOT",
|
||||
DEFAULT_PATH = "mine";
|
||||
|
||||
/**
|
||||
* The BrowseController is used to populate the initial scope in Browse
|
||||
@ -40,35 +41,98 @@ define(
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function BrowseController($scope, objectService, navigationService) {
|
||||
function BrowseController($scope, $route, $location, objectService, navigationService) {
|
||||
var path = [ROOT_ID].concat(
|
||||
($route.current.params.ids || DEFAULT_PATH).split("/")
|
||||
);
|
||||
|
||||
function updateRoute(domainObject) {
|
||||
var context = domainObject &&
|
||||
domainObject.getCapability('context'),
|
||||
objectPath = context ? context.getPath() : [],
|
||||
ids = objectPath.map(function (domainObject) {
|
||||
return domainObject.getId();
|
||||
}),
|
||||
priorRoute = $route.current,
|
||||
// Act as if params HADN'T changed to avoid page reload
|
||||
unlisten;
|
||||
|
||||
unlisten = $scope.$on('$locationChangeSuccess', function () {
|
||||
$route.current = priorRoute;
|
||||
unlisten();
|
||||
});
|
||||
|
||||
$location.path("/browse/" + ids.slice(1).join("/"));
|
||||
}
|
||||
|
||||
// Callback for updating the in-scope reference to the object
|
||||
// that is currently navigated-to.
|
||||
function setNavigation(domainObject) {
|
||||
$scope.navigatedObject = domainObject;
|
||||
$scope.treeModel.selectedObject = domainObject;
|
||||
navigationService.setNavigation(domainObject);
|
||||
updateRoute(domainObject);
|
||||
}
|
||||
|
||||
function navigateTo(domainObject) {
|
||||
// Check if an object has been navigated-to already...
|
||||
// If not, or if an ID path has been explicitly set in the URL,
|
||||
// navigate to the URL-specified object.
|
||||
if (!navigationService.getNavigation() || $route.current.params.ids) {
|
||||
// If not, pick a default as the last
|
||||
// root-level component (usually "mine")
|
||||
navigationService.setNavigation(domainObject);
|
||||
$scope.navigatedObject = domainObject;
|
||||
} else {
|
||||
// Otherwise, just expose the currently navigated object.
|
||||
$scope.navigatedObject = navigationService.getNavigation();
|
||||
updateRoute($scope.navigatedObject);
|
||||
}
|
||||
}
|
||||
|
||||
function findObject(domainObjects, id) {
|
||||
var i;
|
||||
for (i = 0; i < domainObjects.length; i += 1) {
|
||||
if (domainObjects[i].getId() === id) {
|
||||
return domainObjects[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Navigate to the domain object identified by path[index],
|
||||
// which we expect to find in the composition of the passed
|
||||
// domain object.
|
||||
function doNavigate(domainObject, index) {
|
||||
var composition = domainObject.useCapability("composition");
|
||||
if (composition) {
|
||||
composition.then(function (c) {
|
||||
var nextObject = findObject(c, path[index]);
|
||||
if (nextObject) {
|
||||
if (index + 1 >= path.length) {
|
||||
navigateTo(nextObject);
|
||||
} else {
|
||||
doNavigate(nextObject, index + 1);
|
||||
}
|
||||
} else {
|
||||
// Couldn't find the next element of the path
|
||||
// so navigate to the last path object we did find
|
||||
navigateTo(domainObject);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
// Similar to above case; this object has no composition,
|
||||
// so navigate to it instead of subsequent path elements.
|
||||
navigateTo(domainObject);
|
||||
}
|
||||
}
|
||||
|
||||
// Load the root object, put it in the scope.
|
||||
// Also, load its immediate children, and (possibly)
|
||||
// navigate to one of them, so that navigation state has
|
||||
// a useful initial value.
|
||||
objectService.getObjects([ROOT_OBJECT]).then(function (objects) {
|
||||
var composition = objects[ROOT_OBJECT].useCapability("composition");
|
||||
$scope.domainObject = objects[ROOT_OBJECT];
|
||||
if (composition) {
|
||||
composition.then(function (c) {
|
||||
// Check if an object has been navigated-to already...
|
||||
if (!navigationService.getNavigation()) {
|
||||
// If not, pick a default as the last
|
||||
// root-level component (usually "mine")
|
||||
navigationService.setNavigation(c[c.length - 1]);
|
||||
} else {
|
||||
// Otherwise, just expose it in the scope
|
||||
$scope.navigatedObject = navigationService.getNavigation();
|
||||
}
|
||||
});
|
||||
}
|
||||
objectService.getObjects([path[0]]).then(function (objects) {
|
||||
$scope.domainObject = objects[path[0]];
|
||||
doNavigate($scope.domainObject, 1);
|
||||
});
|
||||
|
||||
// Provide a model for the tree to modify
|
||||
|
69
platform/commonUI/browse/src/BrowseObjectController.js
Normal file
69
platform/commonUI/browse/src/BrowseObjectController.js
Normal file
@ -0,0 +1,69 @@
|
||||
/*****************************************************************************
|
||||
* 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,Promise*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Controller for the `browse-object` representation of a domain
|
||||
* object (the right-hand side of Browse mode.)
|
||||
* @constructor
|
||||
*/
|
||||
function BrowseObjectController($scope, $location, $route) {
|
||||
function setViewForDomainObject(domainObject) {
|
||||
var locationViewKey = $location.search().view;
|
||||
|
||||
function selectViewIfMatching(view) {
|
||||
if (view.key === locationViewKey) {
|
||||
$scope.representation = $scope.representation || {};
|
||||
$scope.representation.selected = view;
|
||||
}
|
||||
}
|
||||
|
||||
if (locationViewKey) {
|
||||
((domainObject && domainObject.useCapability('view')) || [])
|
||||
.forEach(selectViewIfMatching);
|
||||
}
|
||||
}
|
||||
|
||||
function updateQueryParam(viewKey) {
|
||||
var unlisten, priorRoute = $route.current;
|
||||
|
||||
if (viewKey) {
|
||||
$location.search('view', viewKey);
|
||||
unlisten = $scope.$on('$locationChangeSuccess', function () {
|
||||
$route.current = priorRoute;
|
||||
unlisten();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$scope.$watch('domainObject', setViewForDomainObject);
|
||||
$scope.$watch('representation.selected.key', updateQueryParam);
|
||||
}
|
||||
|
||||
return BrowseObjectController;
|
||||
}
|
||||
);
|
@ -45,8 +45,9 @@ define(
|
||||
properties = type.getProperties();
|
||||
|
||||
function validateLocation(locatingObject) {
|
||||
var locatingType = locatingObject.getCapability('type');
|
||||
return policyService.allow(
|
||||
var locatingType = locatingObject &&
|
||||
locatingObject.getCapability('type');
|
||||
return locatingType && policyService.allow(
|
||||
"composition",
|
||||
locatingType,
|
||||
type
|
||||
|
@ -77,7 +77,19 @@ define(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return parentPersistence.persist();
|
||||
return parentPersistence.persist().then(function () {
|
||||
// Locate and return new Object in context of parent.
|
||||
return parent
|
||||
.useCapability('composition')
|
||||
.then(function (children) {
|
||||
var i;
|
||||
for (i = 0; i < children.length; i += 1) {
|
||||
if (children[i].getId() === id) {
|
||||
return children[i];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -31,10 +31,13 @@ define(
|
||||
|
||||
describe("The browse controller", function () {
|
||||
var mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService,
|
||||
mockRootObject,
|
||||
mockDomainObject,
|
||||
mockNextObject,
|
||||
controller;
|
||||
|
||||
function mockPromise(value) {
|
||||
@ -50,6 +53,11 @@ define(
|
||||
"$scope",
|
||||
[ "$on", "$watch" ]
|
||||
);
|
||||
mockRoute = { current: { params: {} } };
|
||||
mockLocation = jasmine.createSpyObj(
|
||||
"$location",
|
||||
[ "path" ]
|
||||
);
|
||||
mockObjectService = jasmine.createSpyObj(
|
||||
"objectService",
|
||||
[ "getObjects" ]
|
||||
@ -71,25 +79,38 @@ define(
|
||||
"domainObject",
|
||||
[ "getId", "getCapability", "getModel", "useCapability" ]
|
||||
);
|
||||
mockNextObject = jasmine.createSpyObj(
|
||||
"nextObject",
|
||||
[ "getId", "getCapability", "getModel", "useCapability" ]
|
||||
);
|
||||
|
||||
mockObjectService.getObjects.andReturn(mockPromise({
|
||||
ROOT: mockRootObject
|
||||
}));
|
||||
|
||||
mockRootObject.useCapability.andReturn(mockPromise([
|
||||
mockDomainObject
|
||||
]));
|
||||
mockDomainObject.useCapability.andReturn(mockPromise([
|
||||
mockNextObject
|
||||
]));
|
||||
mockNextObject.useCapability.andReturn(undefined);
|
||||
mockNextObject.getId.andReturn("next");
|
||||
mockDomainObject.getId.andReturn("mine");
|
||||
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
});
|
||||
|
||||
it("uses composition to set the navigated object, if there is none", function () {
|
||||
mockRootObject.useCapability.andReturn(mockPromise([
|
||||
mockDomainObject
|
||||
]));
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
@ -98,12 +119,11 @@ define(
|
||||
});
|
||||
|
||||
it("does not try to override navigation", function () {
|
||||
// This behavior is needed if object navigation has been
|
||||
// determined by query string parameters
|
||||
mockRootObject.useCapability.andReturn(mockPromise([null]));
|
||||
mockNavigationService.getNavigation.andReturn(mockDomainObject);
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
@ -130,6 +150,76 @@ define(
|
||||
);
|
||||
});
|
||||
|
||||
it("uses route parameters to choose initially-navigated object", function () {
|
||||
mockRoute.current.params.ids = "mine/next";
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
expect(mockScope.navigatedObject).toBe(mockNextObject);
|
||||
expect(mockNavigationService.setNavigation)
|
||||
.toHaveBeenCalledWith(mockNextObject);
|
||||
});
|
||||
|
||||
it("handles invalid IDs by going as far as possible", function () {
|
||||
// Idea here is that if we get a bad path of IDs,
|
||||
// browse controller should traverse down it until
|
||||
// it hits an invalid ID.
|
||||
mockRoute.current.params.ids = "mine/junk";
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
expect(mockScope.navigatedObject).toBe(mockDomainObject);
|
||||
expect(mockNavigationService.setNavigation)
|
||||
.toHaveBeenCalledWith(mockDomainObject);
|
||||
});
|
||||
|
||||
it("handles compositionless objects by going as far as possible", function () {
|
||||
// Idea here is that if we get a path which passes
|
||||
// through an object without a composition, browse controller
|
||||
// should stop at it since remaining IDs cannot be loaded.
|
||||
mockRoute.current.params.ids = "mine/next/junk";
|
||||
controller = new BrowseController(
|
||||
mockScope,
|
||||
mockRoute,
|
||||
mockLocation,
|
||||
mockObjectService,
|
||||
mockNavigationService
|
||||
);
|
||||
expect(mockScope.navigatedObject).toBe(mockNextObject);
|
||||
expect(mockNavigationService.setNavigation)
|
||||
.toHaveBeenCalledWith(mockNextObject);
|
||||
});
|
||||
|
||||
it("updates the displayed route to reflect current navigation", function () {
|
||||
var mockContext = jasmine.createSpyObj('context', ['getPath']),
|
||||
mockUnlisten = jasmine.createSpy('unlisten');
|
||||
|
||||
mockContext.getPath.andReturn(
|
||||
[mockRootObject, mockDomainObject, mockNextObject]
|
||||
);
|
||||
mockNextObject.getCapability.andCallFake(function (c) {
|
||||
return c === 'context' && mockContext;
|
||||
});
|
||||
mockScope.$on.andReturn(mockUnlisten);
|
||||
// Provide a navigation change
|
||||
mockNavigationService.addListener.mostRecentCall.args[0](
|
||||
mockNextObject
|
||||
);
|
||||
expect(mockLocation.path).toHaveBeenCalledWith("/browse/mine/next");
|
||||
|
||||
// Exercise the Angular workaround
|
||||
mockScope.$on.mostRecentCall.args[1]();
|
||||
expect(mockUnlisten).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
99
platform/commonUI/browse/test/BrowseObjectControllerSpec.js
Normal file
99
platform/commonUI/browse/test/BrowseObjectControllerSpec.js
Normal file
@ -0,0 +1,99 @@
|
||||
/*****************************************************************************
|
||||
* 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,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
|
||||
define(
|
||||
["../src/BrowseObjectController"],
|
||||
function (BrowseObjectController) {
|
||||
"use strict";
|
||||
|
||||
describe("The browse object controller", function () {
|
||||
var mockScope,
|
||||
mockLocation,
|
||||
mockRoute,
|
||||
mockUnlisten,
|
||||
controller;
|
||||
|
||||
// Utility function; look for a $watch on scope and fire it
|
||||
function fireWatch(expr, value) {
|
||||
mockScope.$watch.calls.forEach(function (call) {
|
||||
if (call.args[0] === expr) {
|
||||
call.args[1](value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
"$scope",
|
||||
[ "$on", "$watch" ]
|
||||
);
|
||||
mockRoute = { current: { params: {} } };
|
||||
mockLocation = jasmine.createSpyObj(
|
||||
"$location",
|
||||
[ "path", "search" ]
|
||||
);
|
||||
mockUnlisten = jasmine.createSpy("unlisten");
|
||||
|
||||
mockScope.$on.andReturn(mockUnlisten);
|
||||
|
||||
controller = new BrowseObjectController(
|
||||
mockScope,
|
||||
mockLocation,
|
||||
mockRoute
|
||||
);
|
||||
});
|
||||
|
||||
it("updates query parameters when selected view changes", function () {
|
||||
fireWatch("representation.selected.key", "xyz");
|
||||
expect(mockLocation.search).toHaveBeenCalledWith('view', "xyz");
|
||||
|
||||
// Exercise the Angular workaround
|
||||
mockScope.$on.mostRecentCall.args[1]();
|
||||
expect(mockUnlisten).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("sets the active view from query parameters", function () {
|
||||
var mockDomainObject = jasmine.createSpyObj(
|
||||
"domainObject",
|
||||
['getId', 'getModel', 'getCapability', 'useCapability']
|
||||
),
|
||||
testViews = [
|
||||
{ key: 'abc' },
|
||||
{ key: 'def', someKey: 'some value' },
|
||||
{ key: 'xyz' }
|
||||
];
|
||||
|
||||
mockDomainObject.useCapability.andCallFake(function (c) {
|
||||
return (c === 'view') && testViews;
|
||||
});
|
||||
mockLocation.search.andReturn({ view: 'def' });
|
||||
|
||||
fireWatch('domainObject', mockDomainObject);
|
||||
expect(mockScope.representation.selected)
|
||||
.toEqual(testViews[1]);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -34,8 +34,10 @@ define(
|
||||
mockQ,
|
||||
mockLog,
|
||||
mockParentObject,
|
||||
mockNewObject,
|
||||
mockMutationCapability,
|
||||
mockPersistenceCapability,
|
||||
mockCompositionCapability,
|
||||
mockCapabilities,
|
||||
creationService;
|
||||
|
||||
@ -69,6 +71,10 @@ define(
|
||||
"parentObject",
|
||||
[ "getId", "getCapability", "useCapability" ]
|
||||
);
|
||||
mockNewObject = jasmine.createSpyObj(
|
||||
"newObject",
|
||||
[ "getId" ]
|
||||
);
|
||||
mockMutationCapability = jasmine.createSpyObj(
|
||||
"mutation",
|
||||
[ "invoke" ]
|
||||
@ -77,9 +83,14 @@ define(
|
||||
"persistence",
|
||||
[ "persist", "getSpace" ]
|
||||
);
|
||||
mockCompositionCapability = jasmine.createSpyObj(
|
||||
"composition",
|
||||
["invoke"]
|
||||
);
|
||||
mockCapabilities = {
|
||||
mutation: mockMutationCapability,
|
||||
persistence: mockPersistenceCapability
|
||||
persistence: mockPersistenceCapability,
|
||||
composition: mockCompositionCapability
|
||||
};
|
||||
|
||||
mockPersistenceService.createObject.andReturn(
|
||||
@ -93,8 +104,15 @@ define(
|
||||
return mockCapabilities[key].invoke(value);
|
||||
});
|
||||
|
||||
mockPersistenceCapability.persist.andReturn(
|
||||
mockPromise(true)
|
||||
);
|
||||
|
||||
mockMutationCapability.invoke.andReturn(mockPromise(true));
|
||||
mockPersistenceCapability.getSpace.andReturn("testSpace");
|
||||
mockCompositionCapability.invoke.andReturn(
|
||||
mockPromise([mockNewObject])
|
||||
);
|
||||
|
||||
creationService = new CreationService(
|
||||
mockPersistenceService,
|
||||
|
@ -1,5 +1,6 @@
|
||||
[
|
||||
"BrowseController",
|
||||
"BrowseObjectController",
|
||||
"creation/CreateAction",
|
||||
"creation/CreateActionProvider",
|
||||
"creation/CreateMenuController",
|
||||
|
@ -25,7 +25,7 @@
|
||||
<a href=""
|
||||
ng-click="ngModel.cancel()"
|
||||
ng-if="ngModel.cancel"
|
||||
class="btn normal outline ui-symbol close">
|
||||
class="btn normal ui-symbol close">
|
||||
x
|
||||
</a>
|
||||
<div class="abs contents" ng-transclude>
|
||||
|
@ -33,8 +33,6 @@
|
||||
<mct-representation key="'edit-action-buttons'"
|
||||
mct-object="domainObject"
|
||||
class='conclude-editing'>
|
||||
<!--a class='btn major' href=''>Save<span id='save-actions-menu' class='ui-symbol invoke-menu'>v</span></a>
|
||||
<a class='btn subtle' href=''>Cancel</a-->
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
@ -181,7 +181,7 @@
|
||||
"key": "label",
|
||||
"templateUrl": "templates/label.html",
|
||||
"uses": [ "type" ],
|
||||
"gestures": [ "drag", "menu" ]
|
||||
"gestures": [ "drag", "menu", "info" ]
|
||||
},
|
||||
{
|
||||
"key": "node",
|
||||
|
@ -61,6 +61,15 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
||||
$c: $baseColor;
|
||||
color: $c;
|
||||
&:hover {
|
||||
color: lighten($c, $ltGamma);
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -186,9 +195,9 @@
|
||||
color: #666666; }
|
||||
/* line 116, ../sass/forms/_elems.scss */
|
||||
.form .form-row .selector-list {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
@ -225,9 +234,9 @@ label.form-control.checkbox input {
|
||||
vertical-align: top; }
|
||||
/* line 159, ../sass/forms/_elems.scss */
|
||||
.l-result div.s-hint {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
background: rgba(255, 153, 0, 0.8);
|
||||
display: block;
|
||||
color: #ffd699;
|
||||
@ -258,9 +267,9 @@ label.form-control.checkbox input {
|
||||
.edit-main textarea {
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
@ -302,13 +311,12 @@ label.form-control.checkbox input {
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/* line 22, ../sass/forms/_text-input.scss */
|
||||
input[type="text"],
|
||||
input[type="date"] {
|
||||
input[type="text"] {
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
@ -322,32 +330,10 @@ input[type="date"] {
|
||||
outline: none;
|
||||
padding: 0 3px; }
|
||||
/* line 33, ../sass/forms/_mixins.scss */
|
||||
input[type="text"].error,
|
||||
input[type="date"].error {
|
||||
input[type="text"].error {
|
||||
background: rgba(255, 0, 0, 0.5); }
|
||||
/* line 61, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
|
||||
input[type="text"]:-moz-placeholder,
|
||||
input[type="date"]:-moz-placeholder {
|
||||
color: gray;
|
||||
font-style: italic; }
|
||||
/* line 64, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
|
||||
input[type="text"]::-moz-placeholder,
|
||||
input[type="date"]::-moz-placeholder {
|
||||
color: gray;
|
||||
font-style: italic; }
|
||||
/* line 67, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
|
||||
input[type="text"]:-ms-input-placeholder,
|
||||
input[type="date"]:-ms-input-placeholder {
|
||||
color: gray;
|
||||
font-style: italic; }
|
||||
/* line 56, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
|
||||
input[type="text"]::-webkit-input-placeholder,
|
||||
input[type="date"]::-webkit-input-placeholder {
|
||||
color: gray;
|
||||
font-style: italic; }
|
||||
/* line 34, ../sass/forms/_text-input.scss */
|
||||
input[type="text"].numeric,
|
||||
input[type="date"].numeric {
|
||||
/* line 29, ../sass/forms/_text-input.scss */
|
||||
input[type="text"].numeric {
|
||||
text-align: right; }
|
||||
|
||||
/*****************************************************************************
|
||||
@ -373,23 +359,23 @@ input[type="date"] {
|
||||
*****************************************************************************/
|
||||
/* line 22, ../sass/forms/_selects.scss */
|
||||
.form-control.select {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzRkNGQ0ZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzQwNDA0MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzUyNTI1MiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzQ1NDU0NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4d4d4d), color-stop(100%, #404040));
|
||||
background-image: -moz-linear-gradient(#4d4d4d, #404040);
|
||||
background-image: -webkit-linear-gradient(#4d4d4d, #404040);
|
||||
background-image: linear-gradient(#4d4d4d, #404040);
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #525252), color-stop(100%, #454545));
|
||||
background-image: -moz-linear-gradient(#525252, #454545);
|
||||
background-image: -webkit-linear-gradient(#525252, #454545);
|
||||
background-image: linear-gradient(#525252, #454545);
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
border: none;
|
||||
border-top: 1px solid #666666;
|
||||
border-top: 1px solid #575757;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
@ -397,14 +383,21 @@ input[type="date"] {
|
||||
margin: 0 0 2px 2px;
|
||||
overflow: hidden;
|
||||
position: relative; }
|
||||
/* line 148, ../sass/_mixins.scss */
|
||||
/* line 152, ../sass/_mixins.scss */
|
||||
.form-control.select:not(.disabled):hover {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzY2NjY2NiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzRkNGQ0ZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU3NTc1NyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #666666), color-stop(100%, #4d4d4d));
|
||||
background-image: -moz-linear-gradient(#666666, #4d4d4d);
|
||||
background-image: -webkit-linear-gradient(#666666, #4d4d4d);
|
||||
background-image: linear-gradient(#666666, #4d4d4d); }
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #636363), color-stop(100%, #575757));
|
||||
background-image: -moz-linear-gradient(#636363, #575757);
|
||||
background-image: -webkit-linear-gradient(#636363, #575757);
|
||||
background-image: linear-gradient(#636363, #575757);
|
||||
color: #bdbdbd; }
|
||||
/* line 155, ../sass/_mixins.scss */
|
||||
.form-control.select:not(.disabled):hover.btn-menu .invoke-menu {
|
||||
color: #878787; }
|
||||
/* line 160, ../sass/_mixins.scss */
|
||||
.form-control.select.btn-menu .invoke-menu {
|
||||
color: #757575; }
|
||||
/* line 29, ../sass/forms/_selects.scss */
|
||||
.form-control.select select {
|
||||
-moz-appearance: none;
|
||||
@ -461,9 +454,9 @@ input[type="date"] {
|
||||
.channel-selector .treeview {
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
@ -61,6 +61,15 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
||||
$c: $baseColor;
|
||||
color: $c;
|
||||
&:hover {
|
||||
color: lighten($c, $ltGamma);
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -92,23 +101,23 @@
|
||||
top: 0; }
|
||||
/* line 29, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzU5NTk1OSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzRkNGQ0ZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzVlNWU1ZSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzUyNTI1MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #595959), color-stop(100%, #4d4d4d));
|
||||
background-image: -moz-linear-gradient(#595959, #4d4d4d);
|
||||
background-image: -webkit-linear-gradient(#595959, #4d4d4d);
|
||||
background-image: linear-gradient(#595959, #4d4d4d);
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #5e5e5e), color-stop(100%, #525252));
|
||||
background-image: -moz-linear-gradient(#5e5e5e, #525252);
|
||||
background-image: -webkit-linear-gradient(#5e5e5e, #525252);
|
||||
background-image: linear-gradient(#5e5e5e, #525252);
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
border: none;
|
||||
border-top: 1px solid #737373;
|
||||
border-top: 1px solid #636363;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
@ -119,14 +128,21 @@
|
||||
margin-bottom: 3px;
|
||||
margin-right: 3px;
|
||||
position: relative; }
|
||||
/* line 148, ../sass/_mixins.scss */
|
||||
/* line 152, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item:not(.disabled):hover {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzczNzM3MyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU5NTk1OSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzcwNzA3MCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #737373), color-stop(100%, #595959));
|
||||
background-image: -moz-linear-gradient(#737373, #595959);
|
||||
background-image: -webkit-linear-gradient(#737373, #595959);
|
||||
background-image: linear-gradient(#737373, #595959); }
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #707070), color-stop(100%, #636363));
|
||||
background-image: -moz-linear-gradient(#707070, #636363);
|
||||
background-image: -webkit-linear-gradient(#707070, #636363);
|
||||
background-image: linear-gradient(#707070, #636363);
|
||||
color: #bdbdbd; }
|
||||
/* line 155, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item:not(.disabled):hover.btn-menu .invoke-menu {
|
||||
color: #949494; }
|
||||
/* line 160, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.btn-menu .invoke-menu {
|
||||
color: #828282; }
|
||||
/* line 42, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item:hover .item-main .item-type {
|
||||
color: #0099cc !important; }
|
||||
@ -184,40 +200,41 @@
|
||||
font-size: 0.8em; }
|
||||
/* line 104, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwYmZmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwYWNlNiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzBhYzJmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwYjRmMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #00bfff), color-stop(100%, #00ace6));
|
||||
background-image: -moz-linear-gradient(#00bfff, #00ace6);
|
||||
background-image: -webkit-linear-gradient(#00bfff, #00ace6);
|
||||
background-image: linear-gradient(#00bfff, #00ace6);
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #0ac2ff), color-stop(100%, #00b4f0));
|
||||
background-image: -moz-linear-gradient(#0ac2ff, #00b4f0);
|
||||
background-image: -webkit-linear-gradient(#0ac2ff, #00b4f0);
|
||||
background-image: linear-gradient(#0ac2ff, #00b4f0);
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
border: none;
|
||||
border-top: 1px solid #33ccff;
|
||||
border-top: 1px solid #14c4ff;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzMzY2NmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwOTljYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #33ccff), color-stop(100%, #0099cc));
|
||||
background-image: -moz-linear-gradient(#33ccff, #0099cc);
|
||||
background-image: -webkit-linear-gradient(#33ccff, #0099cc);
|
||||
background-image: linear-gradient(#33ccff, #0099cc);
|
||||
color: #80dfff; }
|
||||
/* line 156, ../sass/_mixins.scss */
|
||||
/* line 152, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.selected:not(.disabled):hover {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzY2ZDlmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwYmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzJlY2JmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzE0YzRmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #66d9ff), color-stop(100%, #00bfff));
|
||||
background-image: -moz-linear-gradient(#66d9ff, #00bfff);
|
||||
background-image: -webkit-linear-gradient(#66d9ff, #00bfff);
|
||||
background-image: linear-gradient(#66d9ff, #00bfff); }
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #2ecbff), color-stop(100%, #14c4ff));
|
||||
background-image: -moz-linear-gradient(#2ecbff, #14c4ff);
|
||||
background-image: -webkit-linear-gradient(#2ecbff, #14c4ff);
|
||||
background-image: linear-gradient(#2ecbff, #14c4ff);
|
||||
color: #bdbdbd; }
|
||||
/* line 155, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.selected:not(.disabled):hover.btn-menu .invoke-menu {
|
||||
color: #75ddff; }
|
||||
/* line 160, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.selected.btn-menu .invoke-menu {
|
||||
color: #52d4ff; }
|
||||
/* line 109, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected .item-type, .items-holder .item.grid-item.selected .top-bar .icon:not(.alert) {
|
||||
color: #80dfff; }
|
||||
|
@ -1,350 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
/* line 31, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot {
|
||||
color: #999;
|
||||
font-size: 0.7rem;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/****************************** Limits and Out-of-Bounds data */ }
|
||||
/* line 38, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-axis-area {
|
||||
position: absolute; }
|
||||
/* line 41, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-axis-area.gl-plot-x {
|
||||
top: auto;
|
||||
right: 0;
|
||||
bottom: 5px;
|
||||
left: 60px;
|
||||
height: 32px;
|
||||
width: auto;
|
||||
overflow: hidden; }
|
||||
/* line 50, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-axis-area.gl-plot-y {
|
||||
top: 29px;
|
||||
right: auto;
|
||||
bottom: 37px;
|
||||
left: 0;
|
||||
width: 60px; }
|
||||
/* line 59, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-coords {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background: black;
|
||||
color: #e6e6e6;
|
||||
padding: 2px 5px;
|
||||
position: absolute;
|
||||
top: 39px;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: 70px;
|
||||
z-index: 10; }
|
||||
/* line 71, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-coords:empty {
|
||||
display: none; }
|
||||
/* line 76, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-display-area {
|
||||
position: absolute;
|
||||
top: 29px;
|
||||
right: 0;
|
||||
bottom: 37px;
|
||||
left: 60px;
|
||||
cursor: crosshair;
|
||||
border: 1px solid #4d4d4d; }
|
||||
/* line 86, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-label,
|
||||
.gl-plot .l-plot-label {
|
||||
color: #cccccc;
|
||||
position: absolute;
|
||||
text-align: center; }
|
||||
/* line 94, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-label.gl-plot-x-label, .gl-plot .gl-plot-label.l-plot-x-label,
|
||||
.gl-plot .l-plot-label.gl-plot-x-label,
|
||||
.gl-plot .l-plot-label.l-plot-x-label {
|
||||
top: auto;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: auto; }
|
||||
/* line 103, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-label.gl-plot-y-label, .gl-plot .gl-plot-label.l-plot-y-label,
|
||||
.gl-plot .l-plot-label.gl-plot-y-label,
|
||||
.gl-plot .l-plot-label.l-plot-y-label {
|
||||
-moz-transform-origin: 50% 0;
|
||||
-ms-transform-origin: 50% 0;
|
||||
-webkit-transform-origin: 50% 0;
|
||||
transform-origin: 50% 0;
|
||||
-moz-transform: translateX(-50%) rotate(-90deg);
|
||||
-ms-transform: translateX(-50%) rotate(-90deg);
|
||||
-webkit-transform: translateX(-50%) rotate(-90deg);
|
||||
transform: translateX(-50%) rotate(-90deg);
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
white-space: nowrap; }
|
||||
/* line 117, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-y-options {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: auto5px;
|
||||
margin-top: -16px;
|
||||
height: auto;
|
||||
min-height: 32px;
|
||||
width: 32px; }
|
||||
/* line 131, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-hash {
|
||||
position: absolute;
|
||||
border: 0 rgba(255, 255, 255, 0.3) dashed; }
|
||||
/* line 134, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-hash.hash-v {
|
||||
border-right-width: 1px;
|
||||
height: 100%; }
|
||||
/* line 138, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-hash.hash-h {
|
||||
border-bottom-width: 1px;
|
||||
width: 100%; }
|
||||
/* line 144, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-legend {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
height: 24px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto; }
|
||||
/* line 157, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-limit-bar,
|
||||
.gl-plot .l-oob-data {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: auto; }
|
||||
/* line 165, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-limit-bar {
|
||||
height: auto;
|
||||
z-index: 0; }
|
||||
/* line 173, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-limit-bar.s-limit-yellow {
|
||||
background: rgba(157, 117, 0, 0.2); }
|
||||
/* line 174, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-limit-bar.s-limit-red {
|
||||
background: rgba(170, 0, 0, 0.2); }
|
||||
/* line 177, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-oob-data {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
pointer-events: none;
|
||||
height: 10px;
|
||||
z-index: 1; }
|
||||
/* line 185, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-oob-data.l-oob-data-up {
|
||||
top: 0;
|
||||
bottom: auto;
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzc3NDhkNiIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM3NzQ4ZDYiIHN0b3Atb3BhY2l0eT0iMC41Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
|
||||
background-size: 100%;
|
||||
background-image: -moz-linear-gradient(90deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%);
|
||||
background-image: -webkit-linear-gradient(90deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%);
|
||||
background-image: linear-gradient(0deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%); }
|
||||
/* line 190, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-oob-data.l-oob-data-dwn {
|
||||
bottom: 0;
|
||||
top: auto;
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzc3NDhkNiIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM3NzQ4ZDYiIHN0b3Atb3BhY2l0eT0iMC41Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
|
||||
background-size: 100%;
|
||||
background-image: -moz-linear-gradient(270deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%);
|
||||
background-image: -webkit-linear-gradient(270deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%);
|
||||
background-image: linear-gradient(180deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%); }
|
||||
|
||||
/* line 200, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-legend .plot-legend-item,
|
||||
.gl-plot-legend .legend-item,
|
||||
.legend .plot-legend-item,
|
||||
.legend .legend-item {
|
||||
display: inline-block;
|
||||
margin-right: 10px; }
|
||||
/* line 204, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-legend .plot-legend-item span,
|
||||
.gl-plot-legend .legend-item span,
|
||||
.legend .plot-legend-item span,
|
||||
.legend .legend-item span {
|
||||
vertical-align: middle; }
|
||||
/* line 207, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-legend .plot-legend-item .plot-color-swatch,
|
||||
.gl-plot-legend .plot-legend-item .color-swatch,
|
||||
.gl-plot-legend .legend-item .plot-color-swatch,
|
||||
.gl-plot-legend .legend-item .color-swatch,
|
||||
.legend .plot-legend-item .plot-color-swatch,
|
||||
.legend .plot-legend-item .color-swatch,
|
||||
.legend .legend-item .plot-color-swatch,
|
||||
.legend .legend-item .color-swatch {
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
height: 8px;
|
||||
width: 8px; }
|
||||
|
||||
/* line 220, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-legend .plot-legend-item {
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
color: #fff;
|
||||
line-height: 1.5em;
|
||||
padding: 0px 5px; }
|
||||
/* line 226, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-legend .plot-legend-item .plot-color-swatch {
|
||||
border: 1px solid #333;
|
||||
height: 9px;
|
||||
width: 9px; }
|
||||
|
||||
/* line 234, ../sass/plots/_plots-main.scss */
|
||||
.tick {
|
||||
position: absolute;
|
||||
border: 0 rgba(255, 255, 255, 0.3) solid; }
|
||||
/* line 237, ../sass/plots/_plots-main.scss */
|
||||
.tick.tick-x {
|
||||
border-right-width: 1px;
|
||||
height: 100%; }
|
||||
|
||||
/* line 243, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-tick,
|
||||
.tick-label {
|
||||
font-size: 0.7rem;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis; }
|
||||
/* line 251, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-tick.gl-plot-x-tick-label, .gl-plot-tick.tick-label-x,
|
||||
.tick-label.gl-plot-x-tick-label,
|
||||
.tick-label.tick-label-x {
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
height: auto;
|
||||
width: 20%;
|
||||
margin-left: -10%;
|
||||
text-align: center; }
|
||||
/* line 261, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-tick.gl-plot-y-tick-label, .gl-plot-tick.tick-label-y,
|
||||
.tick-label.gl-plot-y-tick-label,
|
||||
.tick-label.tick-label-y {
|
||||
top: auto;
|
||||
height: 1em;
|
||||
width: auto;
|
||||
margin-bottom: -0.5em;
|
||||
text-align: right; }
|
||||
|
||||
/* line 273, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-tick.gl-plot-x-tick-label {
|
||||
top: 5px; }
|
||||
/* line 276, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-tick.gl-plot-y-tick-label {
|
||||
right: 5px;
|
||||
left: 5px; }
|
||||
|
||||
/* line 283, ../sass/plots/_plots-main.scss */
|
||||
.tick-label.tick-label-x {
|
||||
top: 0; }
|
||||
/* line 286, ../sass/plots/_plots-main.scss */
|
||||
.tick-label.tick-label-y {
|
||||
right: 0;
|
||||
left: 0; }
|
File diff suppressed because it is too large
Load Diff
@ -61,6 +61,15 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
||||
$c: $baseColor;
|
||||
color: $c;
|
||||
&:hover {
|
||||
color: lighten($c, $ltGamma);
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -86,7 +95,7 @@
|
||||
ul.tree {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
/* line 208, ../sass/_mixins.scss */
|
||||
/* line 264, ../sass/_mixins.scss */
|
||||
ul.tree li {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
@ -97,17 +106,17 @@ ul.tree {
|
||||
position: relative; }
|
||||
/* line 27, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-transition: background-color 0.25s;
|
||||
-o-transition: background-color 0.25s;
|
||||
-webkit-transition: background-color 0.25s;
|
||||
transition: background-color 0.25s;
|
||||
display: block;
|
||||
font-size: 0.80rem;
|
||||
height: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
height: 1.4rem;
|
||||
line-height: 1.4rem;
|
||||
margin-bottom: 3px;
|
||||
position: relative; }
|
||||
/* line 38, ../sass/tree/_tree.scss */
|
||||
@ -168,7 +177,7 @@ ul.tree {
|
||||
width: auto;
|
||||
height: auto;
|
||||
display: block;
|
||||
left: 25px;
|
||||
left: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
@ -207,17 +216,16 @@ ul.tree {
|
||||
/* line 125, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item:not(.loading) {
|
||||
cursor: pointer; }
|
||||
/* line 130, ../sass/tree/_tree.scss */
|
||||
/* line 129, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .context-trigger {
|
||||
display: none;
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
right: 3px; }
|
||||
/* line 136, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .context-trigger .btn-invoke-menu {
|
||||
/* line 135, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .context-trigger .invoke-menu {
|
||||
font-size: 0.75em;
|
||||
height: 0.9rem;
|
||||
line-height: 0.9rem; }
|
||||
/* line 145, ../sass/tree/_tree.scss */
|
||||
/* line 144, ../sass/tree/_tree.scss */
|
||||
ul.tree ul.tree {
|
||||
margin-left: 15px; }
|
||||
|
Binary file not shown.
@ -2,7 +2,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg>
|
||||
<metadata>
|
||||
Created by FontForge 20090622 at Mon May 4 20:21:42 2015
|
||||
Created by FontForge 20090622 at Tue Jun 9 23:00:40 2015
|
||||
By deploy user
|
||||
Copyright 2015 Adobe Systems Incorporated. All rights reserved.
|
||||
</metadata>
|
||||
@ -62,8 +62,10 @@ q52 -180 95 -231q42 53 88 212z" />
|
||||
d="M193 787v-193h-193v193h193zM193 491v-195h-193v195h193zM193 193v-193h-193v193h193zM671 732v-82h-388v82h388zM671 435v-81h-388v81h388zM671 138v-82h-388v82h388z" />
|
||||
<glyph glyph-name="eight" unicode="8" horiz-adv-x="636"
|
||||
d="M625 735v-318h-625v318h625zM625 315v-315h-625v315h625z" />
|
||||
<glyph glyph-name="nine" unicode="9" horiz-adv-x="636"
|
||||
d="M267 735v-319h-267v319h267zM267 315v-315h-267v315h267zM630 735v-319h-267v319h267zM630 315v-315h-267v315h267z" />
|
||||
<glyph glyph-name="nine" unicode="9"
|
||||
d="M328 469q0 -20 -13.5 -33.5t-33.5 -13.5h-234q-20 0 -33.5 13.5t-13.5 33.5v234q0 19 14 33t33 14h234q20 0 33.5 -13.5t13.5 -33.5v-234zM750 469q0 -20 -13.5 -33.5t-33.5 -13.5h-234q-20 0 -33.5 13.5t-13.5 33.5v234q0 20 13.5 33.5t33.5 13.5h234q19 0 33 -14
|
||||
t14 -33v-234zM328 47q0 -20 -13.5 -33.5t-33.5 -13.5h-234q-19 0 -33 14t-14 33v234q0 20 13.5 33.5t33.5 13.5h234q20 0 33.5 -13.5t13.5 -33.5v-234zM750 47q0 -19 -14 -33t-33 -14h-234q-20 0 -33.5 13.5t-13.5 33.5v234q0 20 13.5 33.5t33.5 13.5h234q20 0 33.5 -13.5
|
||||
t13.5 -33.5v-234z" />
|
||||
<glyph glyph-name="colon" unicode=":" horiz-adv-x="625"
|
||||
d="M625 -19l-397 397l397 397v-794zM173 756v-735h-173v735h173z" />
|
||||
<glyph glyph-name="semicolon" unicode=";" horiz-adv-x="624"
|
||||
@ -163,8 +165,8 @@ d="M123 367l-123 123v147l123 -123l220 221v-147zM123 0l-123 123v147l123 -123l220
|
||||
d="M123 93l-123 123v147l123 -123l220 220v-147zM485 262v71h313v-71h-313z" />
|
||||
<glyph glyph-name="l" unicode="l" horiz-adv-x="617"
|
||||
d="M551 386h66v-386h-617v386h63v106q0 100 72 171.5t173 71.5q99 0 171 -71.5t72 -171.5v-106zM173 492v-106h267v106q0 56 -38.5 94.5t-93.5 38.5q-56 0 -95.5 -39t-39.5 -94z" />
|
||||
<glyph glyph-name="m" unicode="m" horiz-adv-x="804"
|
||||
d="M804 729v-156h-804v156h804zM804 445v-160h-804v160h804zM804 158v-158h-804v158h804z" />
|
||||
<glyph glyph-name="m" unicode="m" horiz-adv-x="751"
|
||||
d="M751 563h-751v188h751v-188zM751 282h-751v187h751v-187zM751 0h-751v188h751v-188z" />
|
||||
<glyph glyph-name="n" unicode="n" horiz-adv-x="738"
|
||||
d="M690 697q48 -50 48 -88q0 -18 -10 -26l-243 -243l-3 -3l-4 -2l-227 -78l77 228l2 4l3 3l242 243q22 19 57 3q29 -14 58 -41zM461 371l1 2l-3 50l-34 2h-9v10v28l-51 6l-2 -1l-32 -97l33 -33zM249 512l-134 -389l304 104v-215q-136 -8 -246.5 29t-172.5 93v561
|
||||
q48 -42 125 -75.5t172 -43.5l-24 -25l-17 -17z" />
|
||||
@ -232,6 +234,22 @@ d="M748 750l-375 -750l-374 750h749z" />
|
||||
d="M-1 0l375 750l374 -750h-749z" />
|
||||
<glyph glyph-name="icircumflex" unicode="î" horiz-adv-x="748"
|
||||
d="M748 750l-375 -375l-374 375h749zM748 375l-375 -374l-374 374h749z" />
|
||||
<glyph glyph-name="idieresis" unicode="ï"
|
||||
d="M0 749l750 -375l-750 -374v749z" />
|
||||
<glyph glyph-name="ntilde" unicode="ñ"
|
||||
d="M283 751v-751h-188v751h188zM658 751v-751h-188v751h188z" />
|
||||
<glyph glyph-name="ograve" unicode="ò" horiz-adv-x="751"
|
||||
d="M469 563h-102q-74 0 -126.5 -52.5t-52.5 -126.5v-102h-94q-38 0 -66 27.5t-28 65.5v282q0 38 28 66t66 28h281q39 0 66.5 -28t27.5 -66v-94zM657 469q38 0 66 -27.5t28 -66.5v-281q0 -38 -28 -66t-66 -28h-282q-38 0 -65.5 28t-27.5 66v281q0 39 27.5 66.5t65.5 27.5h282
|
||||
z" />
|
||||
<glyph glyph-name="oacute" unicode="ó" horiz-adv-x="751"
|
||||
d="M216 375l187 -187h-309q-38 0 -66 27.5t-28 66.5v375q0 38 28 66t66 28h375q39 0 66.5 -28t27.5 -66v-309l-188 187zM751 422v-422h-422v94h234l-281 281l93 94l282 -281v234h94z" />
|
||||
<glyph glyph-name="ocircumflex" unicode="ô" horiz-adv-x="751"
|
||||
d="M610 751q58 0 99.5 -41.5t41.5 -99.5v-469q0 -59 -41.5 -100t-99.5 -41h-469q-59 0 -100 41t-41 100v469q0 58 41 99.5t100 41.5h469zM610 282v328h-328l93 -94l-234 -375l375 234z" />
|
||||
<glyph glyph-name="otilde" unicode="õ" horiz-adv-x="657"
|
||||
d="M329 657q136 0 232 -96t96 -232t-96 -232.5t-232 -96.5q-137 0 -233 96t-96 233q0 136 96.5 232t232.5 96zM329 329v246q-101 0 -175 -72zM422 704q0 -20 -13.5 -33.5t-33.5 -13.5h-46h-47q-20 0 -33.5 13.5t-13.5 33.5t13.5 33.5t33.5 13.5h93q20 0 33.5 -13.5
|
||||
t13.5 -33.5z" />
|
||||
<glyph glyph-name="odieresis" unicode="ö"
|
||||
d="M328 562v-375h-328v375h328zM750 562v-375h-328v375h328z" />
|
||||
<glyph glyph-name="fraction" unicode="⁄" horiz-adv-x="761"
|
||||
d="M380 751q158 0 269.5 -111.5t111.5 -268.5q0 -133 -82.5 -236.5t-209.5 -134.5l-4 491l-176 -490q-126 31 -207.5 134.5t-81.5 235.5q0 157 111.5 268.5t268.5 111.5zM168 488l55 20l-34 94l-56 -20zM410 530v100h-59v-100h59zM593 488l34 94l-55 20l-34 -94z" />
|
||||
<glyph glyph-name="H.002" horiz-adv-x="803"
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 24 KiB |
Binary file not shown.
Binary file not shown.
@ -19,13 +19,17 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
// Features
|
||||
$enableImageryThumbs: false; // Set to true if historical imagery thumbnails are supported
|
||||
|
||||
// Margins, spacing, radii
|
||||
$bodyMargin: 10px;
|
||||
$interiorMargin: 5px;
|
||||
$interiorMarginLg: $interiorMargin * 2;
|
||||
$interiorMarginSm: 3px;
|
||||
$basicCr: 3px;
|
||||
$controlCr: $basicCr;
|
||||
$basicCr: 2px;
|
||||
$controlCr: 2px;
|
||||
$smallCr: 2px;
|
||||
$badgeW: 35px;
|
||||
|
||||
@ -34,9 +38,12 @@ $colorBodyBg: #333;
|
||||
$colorBodyFg: #999;
|
||||
$colorFooterBg: #000;
|
||||
$colorKey: #0099cc;
|
||||
$colorKeySelectedBg: #005177;
|
||||
$colorKeyFg: #fff;
|
||||
$colorAlt1: #ffc700;
|
||||
$colorAlert: #ff3c00;
|
||||
$colorPausedBg: #c56f01;
|
||||
$colorPausedFg: #fff;
|
||||
$colorCheck: $colorKey;
|
||||
$colorCreateBtn: $colorKey;
|
||||
$colorInteriorBorder: lighten($colorBodyBg, 10%);
|
||||
@ -50,7 +57,18 @@ $colorLimitYellow: #9d7500;
|
||||
$colorLimitRed: #aa0000;
|
||||
$colorTelemFresh: #fff;
|
||||
$colorTelemStale: #888;
|
||||
$styleTelemStale: italic;
|
||||
$colorInfoBubbleFg: #666;
|
||||
$colorInfoBubbleBg: #ddd;
|
||||
$colorThumbsBubbleFg: lighten($colorBodyFg, 10%);
|
||||
$colorThumbsBubbleBg: lighten($colorBodyBg, 10%);
|
||||
$colorLimitYellow: #9d7500;
|
||||
$colorLimitRed: #aa0000;
|
||||
$colorTelemFresh: #fff;
|
||||
$colorTelemStale: #888;
|
||||
$styleTelemState: italic;
|
||||
$colorInfoBubbleFg: #666;
|
||||
$colorInfoBubbleBg: #ddd;
|
||||
|
||||
// Ratios
|
||||
$ltGamma: 20%;
|
||||
@ -108,7 +126,7 @@ $controlDisabledOpacity: 0.3;
|
||||
$formLabelW: 20%;
|
||||
$formInputH: 22px;
|
||||
$formRowCtrlsH: 14px;
|
||||
$menuLineH: 1.5rem;
|
||||
$menuLineH: 1.4rem;
|
||||
$scrollbarTrackSize: 10px;
|
||||
$scrollbarTrackColorBg: rgba(#000, 0.4);
|
||||
$btnStdH: 25px;
|
||||
@ -124,3 +142,19 @@ $tickLblH: 15px;
|
||||
$tickLblW: 50px;
|
||||
$tickH: $ticksH - $tickLblVMargin - $tickLblH;
|
||||
$tickW: 1px;
|
||||
|
||||
// Imagery
|
||||
$imageMainControlBarH: 20px;
|
||||
$imageThumbsD: 120px;
|
||||
$imageThumbsWrapperH: $imageThumbsD * 1.4;
|
||||
$imageThumbPad: 1px;
|
||||
|
||||
// Bubbles
|
||||
$bubbleArwSize: 10px;
|
||||
$bubblePad: $interiorMargin;
|
||||
$bubbleMinW: 100px;
|
||||
$bubbleMaxW: 300px;
|
||||
|
||||
|
||||
// Timing
|
||||
$controlFadeMs: 100ms;
|
@ -44,7 +44,7 @@ a.disabled {
|
||||
}
|
||||
|
||||
@include keyframes(pulse) {
|
||||
0% { opacity: 0.2; }
|
||||
0% { opacity: 0.5; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@ -57,5 +57,5 @@ a.disabled {
|
||||
}
|
||||
|
||||
.pulse {
|
||||
@include pulse(1000ms);
|
||||
@include pulse(750ms);
|
||||
}
|
@ -69,6 +69,10 @@ span {
|
||||
*/
|
||||
}
|
||||
|
||||
mct-container {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.abs {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@ -117,6 +121,13 @@ span {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.paused {
|
||||
&:not(.s-btn) {
|
||||
border-color: $colorPausedBg !important;
|
||||
color: $colorPausedBg !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sep {
|
||||
color: rgba(#fff, 0.2);
|
||||
}
|
@ -36,7 +36,7 @@
|
||||
// Don't pad in from top and bottom
|
||||
//top: 0; bottom: 0;
|
||||
.object-browse-bar {
|
||||
.t-btn.key-window {
|
||||
.btn.key-window {
|
||||
// Hide the Open in New Window button
|
||||
display: none;
|
||||
}
|
||||
|
@ -42,12 +42,6 @@
|
||||
&.major {
|
||||
font-size: 1.65em;
|
||||
}
|
||||
&:hover {
|
||||
// color: lighten($c, $ltGamma);
|
||||
.invoke-menu {
|
||||
// color: lighten($colorBodyBg, $ltGamma * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,36 +50,35 @@
|
||||
}
|
||||
|
||||
.invoke-menu {
|
||||
@include invokeMenu($colorKey);
|
||||
//@include invokeMenu(); // $colorKey
|
||||
text-shadow: none;
|
||||
display: inline-block;
|
||||
font-size: 1rem;
|
||||
font-size: 0.8rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.btn-menu .invoke-menu,
|
||||
.icon.major .invoke-menu {
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
|
||||
.icon-buttons-main .invoke-menu {
|
||||
@include invokeMenu(lighten($colorBodyBg, $ltGamma));
|
||||
}
|
||||
|
||||
.menu-element .invoke-menu {
|
||||
|
||||
margin-left: $interiorMarginSm;
|
||||
}
|
||||
|
||||
/*
|
||||
.object-header .type-icon {
|
||||
color: $colorKey;
|
||||
margin-right: $interiorMargin;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
*/
|
||||
|
||||
.menu .type-icon,
|
||||
.tree-item .type-icon,
|
||||
.icon-btn .menu.dropdown .icon,
|
||||
.super-menu.menu.dropdown .icon {
|
||||
font-size: $menuLineH * 0.93;
|
||||
.super-menu.menu .type-icon {
|
||||
font-size: $menuLineH * 0.8; //.93
|
||||
line-height: $menuLineH * 1.13;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
||||
.super-menu.menu.dropdown .icon {
|
||||
font-size: $menuLineH * 0.95
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,9 @@
|
||||
@import "controls/lists";
|
||||
@import "controls/menus";
|
||||
@import "controls/time-controller";
|
||||
@import "edit/editor";
|
||||
@import "features/imagery";
|
||||
@import "features/time-display";
|
||||
@import "forms/mixins";
|
||||
@import "forms/elems";
|
||||
@import "forms/validation";
|
||||
|
@ -26,6 +26,16 @@
|
||||
width: auto; height: auto;
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice($props, $t) {
|
||||
@if $t == 0 {
|
||||
@include transition-property(none);
|
||||
} @else {
|
||||
@include transition-property($props);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice-fade($t: 0.5s) {
|
||||
@if $t == 0 {
|
||||
@include transition-property(none);
|
||||
@ -42,6 +52,12 @@
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice-resize-w($t: 0.5s) {
|
||||
@include transition-property(width, left, right);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
|
||||
@mixin triangle-right($size, $color) {
|
||||
$size: $size/2;
|
||||
$ratio: 1;
|
||||
@ -62,6 +78,31 @@
|
||||
border-right: $size/$ratio solid transparent;
|
||||
}
|
||||
|
||||
@mixin triangle($dir: "left", $size: 5px, $ratio: 1, $color: red) {
|
||||
//$size: $size*2;
|
||||
width: 0;
|
||||
height: 0;
|
||||
$slopedB: $size/$ratio solid transparent;
|
||||
$straightB: $size solid $color;
|
||||
@if $dir == "up" {
|
||||
border-left: $slopedB;
|
||||
border-right: $slopedB;
|
||||
border-bottom: $straightB;
|
||||
} @else if $dir == "right" {
|
||||
border-top: $slopedB;
|
||||
border-bottom: $slopedB;
|
||||
border-left: $straightB;
|
||||
} @else if $dir == "down" {
|
||||
border-left: $slopedB;
|
||||
border-right: $slopedB;
|
||||
border-top: $straightB;
|
||||
} @else {
|
||||
border-top: $slopedB;
|
||||
border-bottom: $slopedB;
|
||||
border-right: $straightB;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin bgDiagonalStripes($c: yellow, $a: 0.1, $d: 40px) {
|
||||
@include background-image(linear-gradient(-45deg,
|
||||
rgba($c, $a) 25%, transparent 25%,
|
||||
@ -90,20 +131,35 @@
|
||||
}
|
||||
|
||||
@mixin containerSubtle($bg: $colorBodyBg, $fg: $colorBodyFg, $hover: false) {
|
||||
@include background-image(linear-gradient(lighten($bg, 10%), lighten($bg, 5%)));
|
||||
$ltnRatio: 7%;
|
||||
$gradRatio: 5%;
|
||||
$hovRatio: 7%;
|
||||
$bgBase: lighten($bg, $ltnRatio);
|
||||
$fgBase: lighten($fg, $ltnRatio);
|
||||
$gradC1: lighten($bgBase, $gradRatio);
|
||||
$gradC2: $bgBase;
|
||||
$cInvokeBase: lighten($gradC1, $ltnRatio*2);
|
||||
|
||||
@include background-image(linear-gradient($gradC1, $gradC2));
|
||||
@include border-radius($controlCr);
|
||||
@include box-sizing(border-box);
|
||||
// @include box-shadow(rgba(black, 0.3) 0 1px 2px);
|
||||
@include boxShdwSubtle();
|
||||
border: none;
|
||||
border-top: 1px solid lighten($bg, 20%);
|
||||
border-top: 1px solid lighten($gradC1, 2%);
|
||||
color: $fg;
|
||||
display: inline-block;
|
||||
@if $hover == true {
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 15%)));
|
||||
&:not(.disabled):hover {
|
||||
@include background-image(linear-gradient(lighten($gradC1, $hovRatio), lighten($gradC2, $hovRatio)));
|
||||
color: lighten($fgBase, $hovRatio);
|
||||
&.btn-menu .invoke-menu {
|
||||
color: lighten($cInvokeBase, $hovRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.btn-menu .invoke-menu {
|
||||
color: $cInvokeBase;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin sliderTrack($bg: $scrollbarTrackColorBg) {
|
||||
@ -144,18 +200,16 @@
|
||||
}
|
||||
|
||||
@mixin btnSubtle($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
@include containerSubtle($bg, $fg);
|
||||
&:not(.disabled):hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 10%)));
|
||||
}
|
||||
@include containerSubtle($bg, $fg, true);
|
||||
}
|
||||
|
||||
@mixin btnNoticeable($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
@include containerSubtle($bg, $fg);
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), $bg));
|
||||
&:not(.disabled):hover {
|
||||
// No longer should be used; use btnSubtle instead
|
||||
//@include containerSubtle($bg, $fg, true);
|
||||
//@include background-image(linear-gradient(lighten($bg, 20%), $bg));
|
||||
/* &:not(.disabled):hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 30%), lighten($bg, 10%)));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@mixin boxIncised($sVal: 0.6) {
|
||||
@ -166,8 +220,8 @@
|
||||
border: 1px solid $c;
|
||||
}
|
||||
|
||||
@mixin boxShdwSubtle($sVal: 0.3) {
|
||||
@include box-shadow(rgba(black, $sVal) 0 1px 3px);
|
||||
@mixin boxShdwSubtle($sVal: 0.2) {
|
||||
@include box-shadow(rgba(black, $sVal) 0 1px 2px);
|
||||
}
|
||||
|
||||
@mixin boxShdwLarge($sVal: 0.7) {
|
||||
@ -194,13 +248,15 @@
|
||||
}
|
||||
|
||||
|
||||
@mixin invokeMenu($baseColor) {
|
||||
/*
|
||||
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
||||
$c: $baseColor;
|
||||
color: $c;
|
||||
&:hover {
|
||||
color: lighten($c, $ltGamma);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@mixin menuUlReset() {
|
||||
margin: 0;
|
||||
|
@ -19,37 +19,97 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
$pad: $interiorMargin * 2;
|
||||
$baseRatio: 1.5;
|
||||
$pad: $interiorMargin * $baseRatio;
|
||||
|
||||
/*********************************** TYPE STYLES */
|
||||
.t-btn {
|
||||
cursor: pointer;
|
||||
/******* LAYOUT AND SIZING */
|
||||
.btn,
|
||||
.l-btn {
|
||||
line-height: 1.25em;
|
||||
padding: 0 $pad;
|
||||
text-decoration: none;
|
||||
&.lg,
|
||||
&.create-btn {
|
||||
$h: $ueTopBarH - $interiorMargin;
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
padding: 0 $pad * 3;
|
||||
}
|
||||
&.create-btn {
|
||||
.menu {
|
||||
margin-left: $pad * -1;
|
||||
}
|
||||
>.ui-symbol {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
&.sm {
|
||||
padding: 0 $pad / $baseRatio;
|
||||
}
|
||||
&.vsm {
|
||||
padding: 0 ($pad / $baseRatio) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************** STYLE STYLES */
|
||||
.btn,
|
||||
.s-btn {
|
||||
$base: lighten($colorBodyBg, 20%);
|
||||
$base: lighten($colorBodyBg, 20%); // Moved to s-btn
|
||||
@include border-radius($controlCr);
|
||||
@include box-sizing(border-box);
|
||||
@include text-shadow(rgba(black, 0.3) 0 1px 1px);
|
||||
cursor: pointer;
|
||||
line-height: 1.2em;
|
||||
padding: 0 $pad;
|
||||
text-decoration: none;
|
||||
&.major {
|
||||
$bg: $colorKey;
|
||||
@include btnSubtle($bg);
|
||||
$fg: lighten($bg, 50%);
|
||||
color: $fg;
|
||||
&:hover {
|
||||
@include btnSubtle(lighten($bg, 5%), $fg);
|
||||
//color: $fg;
|
||||
}
|
||||
.invoke-menu {
|
||||
color: $fg;
|
||||
}
|
||||
}
|
||||
&.subtle {
|
||||
@include btnSubtle($base, lighten($base, 40%));
|
||||
}
|
||||
&.very-subtle,
|
||||
&.s-very-subtle {
|
||||
@include containerSubtle($colorBodyBg, $colorBodyFg, true);
|
||||
&.paused {
|
||||
@include containerSubtle($colorPausedBg, $colorPausedFg, true);
|
||||
.icon:before {
|
||||
content:"\0000EF";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-btn,
|
||||
.s-icon-btn {
|
||||
@extend .s-btn;
|
||||
font-size: 1.2em;
|
||||
font-size: 1em;
|
||||
.icon {
|
||||
color: $colorKey;
|
||||
}
|
||||
&.paused {
|
||||
.icon {
|
||||
color: $colorPausedFg;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.disabled):hover .icon {
|
||||
color: lighten($colorKey, $ltGamma);
|
||||
&:not(.disabled) {
|
||||
&:not(.paused) {
|
||||
&:hover {
|
||||
.icon {
|
||||
color: lighten($colorKey, $ltGamma);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.labeled {
|
||||
@ -61,12 +121,30 @@ $pad: $interiorMargin * 2;
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
&.pause-play {
|
||||
&.paused {
|
||||
@include pulse(500ms);
|
||||
}
|
||||
.icon:before {
|
||||
content:"\0000F1";
|
||||
}
|
||||
}
|
||||
|
||||
&.show-thumbs {
|
||||
.icon:before {
|
||||
content:"\000039";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************** LAYOUT STYLES */
|
||||
span.btn,
|
||||
span.btn span,
|
||||
span.l-btn,
|
||||
span.l-btn span,
|
||||
a.btn,
|
||||
a.btn span,
|
||||
a.l-btn,
|
||||
a.l-btn span {
|
||||
display: inline-block;
|
||||
|
@ -19,7 +19,8 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.control {
|
||||
/*.control {
|
||||
// UNUSED?
|
||||
&.view-control {
|
||||
.icon {
|
||||
display: inline-block;
|
||||
@ -45,10 +46,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
.accordion {
|
||||
$accordionHeadH: 18px;
|
||||
$accordionHeadH: 18px;
|
||||
margin-top: $interiorMargin;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
@ -56,16 +57,20 @@
|
||||
.accordion-head {
|
||||
$op: 0.2;
|
||||
@include border-radius($basicCr * 0.75);
|
||||
@include box-sizing("border-box");
|
||||
@include box-sizing("border-box");
|
||||
background: rgba($colorBodyFg, $op);
|
||||
cursor: pointer;
|
||||
font-size: 0.75em;
|
||||
line-height: $accordionHeadH;
|
||||
line-height: $accordionHeadH;
|
||||
margin-bottom: $interiorMargin;
|
||||
padding: 0 $interiorMargin;
|
||||
position: absolute;
|
||||
top: 0; right: 0; bottom: auto; left: 0;
|
||||
width: auto; height: $accordionHeadH;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
width: auto;
|
||||
height: $accordionHeadH;
|
||||
text-transform: uppercase;
|
||||
&:hover {
|
||||
background: rgba($colorBodyFg, $op * 2);
|
||||
@ -84,79 +89,14 @@
|
||||
content: "v";
|
||||
}
|
||||
}
|
||||
.accordion-contents {
|
||||
position: absolute;
|
||||
top: $accordionHeadH + $interiorMargin; right: 0; bottom: 0; left: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
$base: lighten($colorBodyBg, 20%); // Moved to s-btn
|
||||
$p: 10px; // Moved to s-btn
|
||||
@include border-radius($controlCr); // Moved to s-btn
|
||||
@include box-sizing(border-box); // Moved to s-btn
|
||||
@include text-shadow(rgba(black, 0.3) 0 1px 1px); // Moved to s-btn
|
||||
// display: inline-block;
|
||||
// margin-right: 10px;
|
||||
padding: 0 ($interiorMargin * 2); // Moved to s-btn
|
||||
text-decoration: none; // Moved to s-btn
|
||||
&.create-btn {
|
||||
$h: $ueTopBarH - $interiorMargin; //$btnStdH * 1.5;;
|
||||
$p: $p * 2.25;
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
//font-size: 1.1em;
|
||||
padding: 0 $p;
|
||||
.menu {
|
||||
margin-left: $p * -1;
|
||||
}
|
||||
.ui-symbol.major {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
&.major {
|
||||
$bg: $colorKey;
|
||||
@include btnNoticeable($bg);
|
||||
$fg: lighten($bg, 50%);
|
||||
color: $fg;
|
||||
&:hover {
|
||||
@include btnNoticeable(lighten($bg, 5%));
|
||||
color: $fg;
|
||||
}
|
||||
.invoke-menu {
|
||||
color: $fg;
|
||||
}
|
||||
}
|
||||
&.normal {
|
||||
padding: $p * 0.5 $p * 0.7;
|
||||
}
|
||||
&.outline {
|
||||
&:hover {
|
||||
background: rgba(#fff, 0.1);
|
||||
}
|
||||
}
|
||||
&.subtle {
|
||||
@include btnSubtle($base, lighten($base, 40%));
|
||||
}
|
||||
|
||||
&.very-subtle {
|
||||
@include btnSubtle($colorBodyBg, lighten($colorBodyBg, 50%));
|
||||
}
|
||||
&.lg {
|
||||
@include border-radius($controlCr * 1.5);
|
||||
font-size: 1.2em;
|
||||
padding: 7px 25px;
|
||||
}
|
||||
&.icon-btn {
|
||||
.icon {
|
||||
color: $colorKey;
|
||||
}
|
||||
|
||||
&:not(.disabled):hover .icon {
|
||||
color: lighten($colorKey, $ltGamma);
|
||||
}
|
||||
.accordion-contents {
|
||||
position: absolute;
|
||||
top: $accordionHeadH + $interiorMargin;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,12 +106,12 @@
|
||||
.btn-set,
|
||||
.t-btn {
|
||||
display: inline-block;
|
||||
// margin-left: $interiorMargin;
|
||||
// margin-left: $interiorMargin;
|
||||
}
|
||||
.btn,
|
||||
.t-btn {
|
||||
&:first-child {
|
||||
// margin-left: 0;
|
||||
// margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -199,6 +139,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
.l-local-controls {
|
||||
// Control shown when hovering over an object, like plots and imagery
|
||||
// Default position is upper right
|
||||
$p: $interiorMargin;
|
||||
position: absolute;
|
||||
top: $p;
|
||||
right: $p;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.s-local-controls {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.btn-set {
|
||||
// Buttons that have a very tight conceptual grouping - no internal space between them.
|
||||
display: inline-block;
|
||||
@ -230,8 +184,8 @@
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
.icon:not(.invoke-menu) {
|
||||
// position: relative;
|
||||
// top: -0.04em;
|
||||
// position: relative;
|
||||
// top: -0.04em;
|
||||
font-size: 150%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@ -318,37 +272,43 @@ label.checkbox.custom {
|
||||
|
||||
.btn-menu {
|
||||
$h: 20px;
|
||||
$p: $interiorMargin * 2;
|
||||
$p: $interiorMarginSm * 2;
|
||||
$c: $colorBodyFg;
|
||||
@include btnSubtle($colorBodyBg);
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
&.dropdown {
|
||||
// padding-left: $p;
|
||||
padding-left: $p;
|
||||
padding-right: $p;
|
||||
}
|
||||
/* height: $h;
|
||||
line-height: $h;
|
||||
&.dropdown {
|
||||
padding-left: $p;
|
||||
padding-right: $p;
|
||||
}*/
|
||||
|
||||
&:not(.disabled):hover {
|
||||
color: lighten($c, 20%);
|
||||
}
|
||||
|
||||
&.btn-invoke-menu {
|
||||
$c: $colorKey;
|
||||
color: $c;
|
||||
padding: 0 5px;
|
||||
&:hover {
|
||||
color: lighten($c, 10%);
|
||||
}
|
||||
/* &.context-available {
|
||||
// An element like the invoke-menu triangle;
|
||||
// Indicates that this element has a dropdown menu available;
|
||||
// Currently unused
|
||||
$c: $colorKey;
|
||||
color: $c;
|
||||
padding: 0 5px;
|
||||
&:hover {
|
||||
color: lighten($c, 10%);
|
||||
}
|
||||
}*/
|
||||
|
||||
span.l-click-area {
|
||||
// In markup, this element should not enclose anything.
|
||||
@extend .abs;
|
||||
}
|
||||
|
||||
span.l-click-area {
|
||||
// In markup, this element should not enclose anything.
|
||||
@extend .abs;
|
||||
}
|
||||
|
||||
.type-icon {
|
||||
margin-right: $interiorMargin;
|
||||
//margin-right: $interiorMargin;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
.menu {
|
||||
// margin-left: (-1 * $p);
|
||||
@ -388,17 +348,23 @@ label.checkbox.custom {
|
||||
}
|
||||
}
|
||||
|
||||
.view-switcher {
|
||||
@include trans-prop-nice-fade($controlFadeMs);
|
||||
}
|
||||
|
||||
/******************************************************** OBJECT-HEADER */
|
||||
.object-header {
|
||||
display: inline-block;
|
||||
font-size: 1em;
|
||||
.title {
|
||||
color: lighten($colorBodyFg, 40%);
|
||||
}
|
||||
.type-icon {
|
||||
font-size: 1.5em;
|
||||
margin-right: $interiorMargin;
|
||||
vertical-align: middle;
|
||||
.label {
|
||||
.title-label {
|
||||
color: lighten($colorBodyFg, 40%);
|
||||
}
|
||||
.type-icon {
|
||||
font-size: 1.5em;
|
||||
margin-right: $interiorMargin;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -412,86 +378,53 @@ label.checkbox.custom {
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************** VIEW-CONTROLS */
|
||||
|
||||
.view-controls .view-type {
|
||||
$d: 20px;
|
||||
$p: 5px;
|
||||
@include border-radius($controlCr);
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
margin-left: $interiorMargin;
|
||||
height: $d;
|
||||
line-height: $d;
|
||||
padding-left: $p;
|
||||
padding-right: $p;
|
||||
&.cur {
|
||||
background: lighten($colorBodyBg, $ltGamma);
|
||||
}
|
||||
}
|
||||
|
||||
.edit-mode .top-bar .control-set.edit-view-controls {
|
||||
// Used in templates/edit-view-controls.html
|
||||
margin-right: $interiorMargin * 10;
|
||||
}
|
||||
|
||||
/******************************************************** SLIDERS */
|
||||
.wrapper-slider {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.slider {
|
||||
//$knobH: 70%; //14px;
|
||||
$knobH: 100%; //14px;
|
||||
$knobW: 12px;
|
||||
$slotH: 80%;
|
||||
$rangeO: 0.3;
|
||||
$slotH: 50%;
|
||||
.slot {
|
||||
// @include border-radius($basicCr * .75);
|
||||
@include sliderTrack();
|
||||
height: auto;
|
||||
height: $slotH;
|
||||
width: auto;
|
||||
position: absolute;
|
||||
//top: ($knobH - $slotH) / 2;
|
||||
top: (100% - $slotH)/2;
|
||||
top: ($knobH - $slotH) / 2;
|
||||
right: 0;
|
||||
bottom: (100% - $slotH)/2;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
.range {
|
||||
background: rgba($colorKey, $rangeO);
|
||||
cursor: ew-resize;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: auto;
|
||||
bottom: 0;
|
||||
left: auto;
|
||||
height: auto;
|
||||
width: auto;
|
||||
z-index: 1;
|
||||
&:hover {
|
||||
background: rgba($colorKey, $rangeO + 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
.knob {
|
||||
@include btnSubtle();
|
||||
@include controlGrippy(rgba(black, 0.3), vertical, 1px, solid);
|
||||
@include border-radius(2px);
|
||||
cursor: ew-resize;
|
||||
position: absolute;
|
||||
height: auto;
|
||||
height: $knobH;
|
||||
width: $knobW;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
auto: 0;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
z-index: 2;
|
||||
&.knob-l { margin-left: $knobW / -2; }
|
||||
&.knob-r { margin-right: $knobW / -2; }
|
||||
&:before {
|
||||
top: 1px;
|
||||
bottom: 3px;
|
||||
//left: ($knobW / 2) - 1;
|
||||
//margin-left: -1px;
|
||||
left: 45%;
|
||||
left: ($knobW / 2) - 1;
|
||||
}
|
||||
|
||||
}
|
||||
.range {
|
||||
background: rgba($colorKey, 0.6);
|
||||
cursor: ew-resize;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: auto;
|
||||
bottom: 0;
|
||||
left: auto;
|
||||
height: auto;
|
||||
width: auto;
|
||||
&:hover {
|
||||
background: rgba($colorKey, 0.7);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -499,23 +432,23 @@ label.checkbox.custom {
|
||||
/******************************************************** BROWSER ELEMENTS */
|
||||
|
||||
::-webkit-scrollbar {
|
||||
@include sliderTrack();
|
||||
height: $scrollbarTrackSize;
|
||||
width: $scrollbarTrackSize;
|
||||
@include sliderTrack();
|
||||
height: $scrollbarTrackSize;
|
||||
width: $scrollbarTrackSize;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
$bg: lighten($colorBodyBg, 10%);
|
||||
@include background-image(linear-gradient(lighten($bg, 10%), lighten($bg, 5%) 20px));
|
||||
@include border-radius(1px);
|
||||
@include box-sizing(border-box);
|
||||
@include boxShdwSubtle();
|
||||
border-top: 1px solid lighten($bg, 20%);
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 15%) 20px));
|
||||
}
|
||||
$bg: lighten($colorBodyBg, 10%);
|
||||
@include background-image(linear-gradient(lighten($bg, 10%), lighten($bg, 5%) 20px));
|
||||
@include border-radius(1px);
|
||||
@include box-sizing(border-box);
|
||||
@include boxShdwSubtle();
|
||||
border-top: 1px solid lighten($bg, 20%);
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 15%) 20px));
|
||||
}
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background: rgba(#000, 0.4);
|
||||
background: rgba(#000, 0.4);
|
||||
}
|
@ -41,7 +41,7 @@
|
||||
@include box-sizing(border-box);
|
||||
border-top: 1px solid lighten($bg, 20%);
|
||||
line-height: $menuLineH;
|
||||
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 3) + $treeTypeIconW;
|
||||
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW;
|
||||
white-space: nowrap;
|
||||
&:first-child {
|
||||
border: none;
|
||||
@ -168,7 +168,7 @@
|
||||
position: absolute;
|
||||
height: 200px;
|
||||
width: 170px;
|
||||
z-index: 59;
|
||||
z-index: 70;
|
||||
.context-menu-wrapper {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
|
@ -19,3 +19,86 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
.edit-main {
|
||||
$handleD: 15px;
|
||||
$cr: 5px;
|
||||
.edit-corner,
|
||||
.edit-handle {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.edit-corner {
|
||||
width: $handleD;
|
||||
height: $handleD;
|
||||
&.edit-resize-nw {
|
||||
@include border-bottom-right-radius($cr);
|
||||
cursor: nw-resize;
|
||||
top: 0; left: 0;
|
||||
}
|
||||
&.edit-resize-se {
|
||||
@include border-top-left-radius($cr);
|
||||
cursor: se-resize;
|
||||
bottom: 0; right: 0;
|
||||
}
|
||||
&.edit-resize-sw {
|
||||
@include border-top-right-radius($cr);
|
||||
cursor: sw-resize;
|
||||
bottom: 0; left: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.edit-handle {
|
||||
top: $handleD; right: $handleD; bottom: $handleD; left: $handleD;
|
||||
&.edit-move {
|
||||
$m: 0; //$handleD;
|
||||
cursor: move;
|
||||
left: $m;
|
||||
right: $m;
|
||||
top: $m;
|
||||
bottom: $m;
|
||||
z-index: 1;
|
||||
|
||||
}
|
||||
&.edit-resize-n {
|
||||
top: 0px; bottom: auto;
|
||||
height: $handleD;
|
||||
cursor: n-resize;
|
||||
}
|
||||
&.edit-resize-e {
|
||||
right: 0px; left: auto;
|
||||
width: $handleD;
|
||||
cursor: e-resize;
|
||||
}
|
||||
&.edit-resize-s {
|
||||
bottom: 0px; top: auto;
|
||||
height: $handleD;
|
||||
cursor: s-resize;
|
||||
}
|
||||
&.edit-resize-w {
|
||||
left: 0px; right: auto;
|
||||
width: $handleD;
|
||||
cursor: w-resize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.frame.child-frame.panel {
|
||||
&:hover {
|
||||
@include boxShdwLarge();
|
||||
border-color: $colorKey;
|
||||
z-index: 2;
|
||||
.view-switcher {
|
||||
opacity: 1;
|
||||
}
|
||||
.edit-corner {
|
||||
background-color: rgba($colorKey, 0.8);
|
||||
&:hover {
|
||||
background-color: rgba($colorKey, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
171
platform/commonUI/general/res/sass/features/_imagery.scss
Normal file
171
platform/commonUI/general/res/sass/features/_imagery.scss
Normal file
@ -0,0 +1,171 @@
|
||||
.l-image-main-wrapper,
|
||||
.l-image-main,
|
||||
.l-image-main-controlbar,
|
||||
.l-image-main-controlbar .left,
|
||||
.l-image-main-controlbar .right,
|
||||
.l-image-thumbs-wrapper {
|
||||
@include absPosDefault(0, false);
|
||||
}
|
||||
|
||||
/*************************************** MAIN LAYOUT */
|
||||
.l-image-main-wrapper {
|
||||
//@include test();
|
||||
@if $enableImageryThumbs == true {
|
||||
bottom: $interiorMargin*2 + $imageThumbsWrapperH;
|
||||
}
|
||||
min-height: 100px;
|
||||
min-width: 150px;
|
||||
.l-image-main {
|
||||
background-color: rgba(#fff, 0.1);
|
||||
bottom: $imageMainControlBarH + $interiorMargin;
|
||||
}
|
||||
.l-image-main-controlbar {
|
||||
top: auto;
|
||||
height: $imageMainControlBarH;
|
||||
}
|
||||
}
|
||||
|
||||
.l-image-thumbs-wrapper {
|
||||
//@include test(red);
|
||||
top: auto;
|
||||
height: $imageThumbsWrapperH;
|
||||
}
|
||||
|
||||
.l-date,
|
||||
.l-time,
|
||||
.l-timezone {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/*************************************** MAIN IMAGE */
|
||||
|
||||
.l-image-main,
|
||||
.l-image-thumb-item .l-thumb {
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.l-image-main {
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.l-image-main-controlbar {
|
||||
//@include test();
|
||||
font-size: 0.8em;
|
||||
line-height: $imageMainControlBarH;
|
||||
.left, .right {
|
||||
direction: rtl;
|
||||
overflow: hidden;
|
||||
}
|
||||
.left {
|
||||
//@include test(red);
|
||||
text-align: left;
|
||||
width: 75% !important;
|
||||
}
|
||||
.right {
|
||||
//@include test(green);
|
||||
min-width: 40px;
|
||||
width: 25% !important;
|
||||
z-index: 2;
|
||||
}
|
||||
.l-date,
|
||||
.l-time {
|
||||
color: #fff;
|
||||
}
|
||||
.l-mag {
|
||||
direction: ltr;
|
||||
display: inline-block;
|
||||
//white-space: nowrap;
|
||||
&:before {
|
||||
content: "\000049";
|
||||
}
|
||||
}
|
||||
.s-mag {
|
||||
color: darken($colorBodyFg, 20%);
|
||||
}
|
||||
.l-btn.show-thumbs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.s-image-main {
|
||||
border: 1px solid transparent;
|
||||
&.paused {
|
||||
border-color: $colorPausedBg;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************** THUMBS */
|
||||
|
||||
.l-image-thumbs-wrapper {
|
||||
//@include test(green);
|
||||
direction: rtl;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
padding-bottom: $interiorMargin;
|
||||
white-space: nowrap;
|
||||
z-index: 70;
|
||||
}
|
||||
|
||||
.l-image-thumb-item {
|
||||
@include single-transition(background-color, 0.25s);
|
||||
@include box-sizing(border-box);
|
||||
padding: 1px;
|
||||
position: relative;
|
||||
.l-thumb,
|
||||
.l-date,
|
||||
.l-time {
|
||||
display: inline-block;
|
||||
}
|
||||
.l-date,
|
||||
.l-time {
|
||||
padding: 2px 3px;
|
||||
}
|
||||
cursor: pointer;
|
||||
direction: ltr;
|
||||
display: inline-block;
|
||||
font-size: 0.8em;
|
||||
margin-left: $interiorMarginSm;
|
||||
text-align: left;
|
||||
width: $imageThumbsD + $imageThumbPad*2;
|
||||
white-space: normal;
|
||||
&:hover {
|
||||
background: rgba(#fff, 0.2);
|
||||
.l-date,
|
||||
.l-time {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
background: $colorKeySelectedBg;
|
||||
.l-date,
|
||||
.l-time {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.l-thumb {
|
||||
background-color: rgba(#fff, 0.1);
|
||||
height: $imageThumbsD;
|
||||
width: $imageThumbsD;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************** WHEN IN FRAME */
|
||||
.frame .t-imagery {
|
||||
.l-image-main-wrapper {
|
||||
bottom: 0;
|
||||
.l-image-main-controlbar {
|
||||
font-size: 0.7em;
|
||||
}
|
||||
@if $enableImageryThumbs == true {
|
||||
.l-btn.show-thumbs {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.l-image-thumbs-wrapper {
|
||||
display: none;
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
.l-time-display {
|
||||
$transTime: 200ms;
|
||||
// Layout
|
||||
&:hover {
|
||||
.l-btn.control {
|
||||
//display: inline-block;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.l-elem-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
.l-elem {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&.l-timer {
|
||||
.l-elem.l-value {
|
||||
@include trans-prop-nice(left, $transTime);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
&:hover .l-elem.l-value {
|
||||
left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
// Look-and-feel
|
||||
.l-elem {
|
||||
.value.active,
|
||||
&.value.active {
|
||||
color: $colorKeyFg;
|
||||
}
|
||||
}
|
||||
.l-btn.control {
|
||||
@include trans-prop-nice-fade($transTime);
|
||||
//display: none;
|
||||
opacity: 0;
|
||||
font-size: 0.9em;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
}
|
@ -19,18 +19,13 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
input[type="text"],
|
||||
input[type="date"] {
|
||||
input[type="text"] {
|
||||
@include nice-input();
|
||||
@include input-placeholder {
|
||||
color: darken($colorBodyFg, 10%);
|
||||
font-style: italic;
|
||||
}
|
||||
&.filter {
|
||||
&.ng-dirty {
|
||||
// background: red;
|
||||
}
|
||||
}
|
||||
&.filter {
|
||||
&.ng-dirty {
|
||||
// background: red;
|
||||
}
|
||||
}
|
||||
&.numeric {
|
||||
text-align: right;
|
||||
}
|
||||
|
@ -19,19 +19,24 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
//************************************************* LAYOUT
|
||||
|
||||
$infoBubbleFg: #666;
|
||||
$infoBubbleBg: #ddd;
|
||||
//************************************************* GENERAL
|
||||
.bubble-container {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
|
||||
//************************************************* LAYOUT
|
||||
|
||||
.l-infobubble-wrapper {
|
||||
$arwSize: 5px;
|
||||
@include box-shadow(rgba(black, 0.4) 0 1px 5px);
|
||||
position: absolute;
|
||||
z-index: 70;
|
||||
position: relative;
|
||||
z-index: 50;
|
||||
.l-infobubble {
|
||||
display: inline-block;
|
||||
max-width: 250px;
|
||||
min-width: $bubbleMinW;
|
||||
max-width: $bubbleMaxW;
|
||||
padding: 5px 10px;
|
||||
&:before {
|
||||
content:"";
|
||||
@ -71,34 +76,30 @@ $infoBubbleBg: #ddd;
|
||||
}
|
||||
|
||||
&.arw-left {
|
||||
margin-left: $arwSize*2;
|
||||
margin-left: $bubbleArwSize*2;
|
||||
.l-infobubble::before {
|
||||
right: 100%;
|
||||
border-top: $arwSize solid transparent;
|
||||
border-bottom: $arwSize solid transparent;
|
||||
border-right: ($arwSize * 1.5) solid $infoBubbleBg;
|
||||
@include triangle('left', $bubbleArwSize, 1.5, $colorInfoBubbleBg);
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-right {
|
||||
margin-right: $arwSize*2;
|
||||
margin-right: $bubbleArwSize*2;
|
||||
.l-infobubble::before {
|
||||
left: 100%;
|
||||
border-top: $arwSize solid transparent;
|
||||
border-bottom: $arwSize solid transparent;
|
||||
border-left: ($arwSize * 1.5) solid $infoBubbleBg;
|
||||
@include triangle('right', $bubbleArwSize, 1.5, $colorInfoBubbleBg);
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-top {
|
||||
.l-infobubble::before {
|
||||
top: $arwSize * 2;
|
||||
top: $bubbleArwSize * 2;
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-btm {
|
||||
.l-infobubble::before {
|
||||
bottom: $arwSize * 2;
|
||||
bottom: $bubbleArwSize * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,18 +111,32 @@ $infoBubbleBg: #ddd;
|
||||
margin-left: -1 * $arwSize;
|
||||
border-left: $arwSize solid transparent;
|
||||
border-right: $arwSize solid transparent;
|
||||
border-top: ($arwSize * 1.5) solid $infoBubbleBg;
|
||||
border-top: ($arwSize * 1.5) solid $colorInfoBubbleBg;
|
||||
}
|
||||
}
|
||||
.arw {
|
||||
z-index: 2;
|
||||
}
|
||||
&.arw-up .arw.arw-down,
|
||||
&.arw-down .arw.arw-up { display: none; }
|
||||
}
|
||||
|
||||
//************************************************* LOOK AND FEEL
|
||||
|
||||
.l-thumbsbubble-wrapper {
|
||||
.arw-up {
|
||||
@include triangle('up', $bubbleArwSize, 1.5, $colorThumbsBubbleBg);
|
||||
}
|
||||
.arw-down {
|
||||
@include triangle('down', $bubbleArwSize, 1.5, $colorThumbsBubbleBg);
|
||||
}
|
||||
}
|
||||
.s-infobubble {
|
||||
$emFg: darken($infoBubbleFg, 20%);
|
||||
$emFg: darken($colorInfoBubbleFg, 20%);
|
||||
@include border-radius($basicCr);
|
||||
background: $infoBubbleBg;
|
||||
color: $infoBubbleFg;
|
||||
@include box-shadow(rgba(black, 0.4) 0 1px 5px);
|
||||
background: $colorInfoBubbleBg;
|
||||
color: $colorInfoBubbleFg;
|
||||
font-size: 0.8rem;
|
||||
.title {
|
||||
color: $emFg;
|
||||
@ -129,7 +144,7 @@ $infoBubbleBg: #ddd;
|
||||
}
|
||||
tr {
|
||||
td {
|
||||
border-top: 1px solid darken($infoBubbleBg, 10%);
|
||||
border-top: 1px solid darken($colorInfoBubbleBg, 10%);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
&:first-child td {
|
||||
@ -139,5 +154,9 @@ $infoBubbleBg: #ddd;
|
||||
.value {
|
||||
color: $emFg;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.s-thumbsbubble {
|
||||
background: $colorThumbsBubbleBg;
|
||||
color: $colorThumbsBubbleFg;
|
||||
}
|
@ -104,7 +104,7 @@
|
||||
&.selected {
|
||||
$cfg: lighten($colorItemSelected, 35%);
|
||||
$cfgh: lighten($cfg, 30%);
|
||||
@include btnNoticeable($colorItemSelected);
|
||||
@include btnSubtle($colorItemSelected);
|
||||
color: $cfg;
|
||||
.item-type, .top-bar .icon:not(.alert) { color: $cfg }
|
||||
.item-main .item-open { color: $cfg }
|
||||
|
@ -75,8 +75,8 @@ ul.tree {
|
||||
.title-label {
|
||||
@include absPosDefault();
|
||||
display: block;
|
||||
left: $runningItemW + ($interiorMargin * 2);
|
||||
// right: $treeContextTriggerW + $interiorMargin; //Disabling as context trigger not being used
|
||||
left: $runningItemW + ($interiorMargin);
|
||||
//right: $treeContextTriggerW + $interiorMargin;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
// height: $menuLineH;
|
||||
@ -99,7 +99,7 @@ ul.tree {
|
||||
|
||||
&.selected {
|
||||
$c: #fff;
|
||||
background: #005177;
|
||||
background: $colorKeySelectedBg;
|
||||
color: $c;
|
||||
.view-control {
|
||||
color: $colorItemTreeIcon;
|
||||
@ -124,16 +124,15 @@ ul.tree {
|
||||
|
||||
&:not(.loading) {
|
||||
cursor: pointer;
|
||||
// @include tree-item-hover();
|
||||
}
|
||||
|
||||
.context-trigger {
|
||||
$h: 0.9rem;
|
||||
display: none;
|
||||
//display: none;
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
right: $interiorMarginSm;
|
||||
.btn-invoke-menu {
|
||||
.invoke-menu {
|
||||
font-size: 0.75em;
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
|
@ -27,6 +27,7 @@
|
||||
border: 1px solid $bc;
|
||||
&:hover {
|
||||
border-color: lighten($bc, 10%);
|
||||
z-index: 2;
|
||||
}
|
||||
.contents {
|
||||
// overflow: hidden;
|
||||
@ -46,12 +47,25 @@
|
||||
bottom: $myM;
|
||||
left: $myM;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-main .frame.child-frame.panel {
|
||||
&:hover {
|
||||
border-color: $colorKey;
|
||||
@include boxShdwLarge();
|
||||
&.frame-template {
|
||||
// Hide the view switcher by default when it's in an element that's in a frame context
|
||||
// Frame template is used because we need to target the lowest nested frame
|
||||
// This has the effect of hiding the view switcher in nested frames in edit mode, which is desirable currently (as it's non-functional)
|
||||
.view-switcher {
|
||||
//display: none;
|
||||
opacity: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
&:hover .view-switcher {
|
||||
// Show the view switcher on frame hover
|
||||
//display: inline-block !important;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.view-switcher {
|
||||
// Hide the name when the view switcher is in a frame context
|
||||
.name {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -70,23 +70,19 @@
|
||||
&.abs {
|
||||
text-wrap: none;
|
||||
white-space: nowrap;
|
||||
&.left,
|
||||
.left {
|
||||
width: 45%;
|
||||
right: auto;
|
||||
}
|
||||
&.right,
|
||||
.right {
|
||||
width: 45%;
|
||||
left: auto;
|
||||
right: 0;
|
||||
text-align: right;
|
||||
.icon.major {
|
||||
margin-left: $interiorMargin * 3;
|
||||
}
|
||||
// .icon.major {
|
||||
// margin-left: $interiorMargin;
|
||||
// }
|
||||
}
|
||||
&.left,
|
||||
.left {
|
||||
width: 45% !important;
|
||||
right: auto !important;
|
||||
}
|
||||
&.right,
|
||||
.right {
|
||||
width: 45% !important;
|
||||
left: auto !important;
|
||||
text-align: right;
|
||||
.icon.major {
|
||||
margin-left: $interiorMargin * 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<a class="t-btn l-btn s-btn s-icon-btn s-very-subtle key-{{parameters.action.getMetadata().key}}"
|
||||
<a class="btn s-btn s-icon-btn s-very-subtle key-{{parameters.action.getMetadata().key}}"
|
||||
ng-class="{ labeled: parameters.labeled }"
|
||||
title="{{parameters.action.getMetadata().description}}"
|
||||
ng-click="parameters.action.perform()">
|
||||
|
@ -21,25 +21,29 @@
|
||||
-->
|
||||
<span ng-controller="ViewSwitcherController">
|
||||
|
||||
<div class="menu-element btn icon-btn very-subtle btn-menu dropdown click-invoke"
|
||||
ng-if="view.length > 1"
|
||||
ng-controller="ClickAwayController as toggle">
|
||||
<div
|
||||
class="view-switcher menu-element btn btn-menu dropdown click-invoke"
|
||||
ng-if="view.length > 1"
|
||||
ng-controller="ClickAwayController as toggle"
|
||||
>
|
||||
|
||||
<span class="l-click-area" ng-click="toggle.toggle()"></span>
|
||||
<span
|
||||
class="l-click-area"
|
||||
ng-click="toggle.toggle()"
|
||||
title="{{ngModel.selected.name}}"
|
||||
></span>
|
||||
|
||||
<span class="ui-symbol icon type-icon">{{ngModel.selected.glyph}}</span>
|
||||
<span>{{ngModel.selected.name}}</span>
|
||||
<span class='ui-symbol icon invoke-menu'>v</span>
|
||||
<span class="name">{{ngModel.selected.name}}</span>
|
||||
<span class='ui-symbol invoke-menu'>v</span>
|
||||
|
||||
|
||||
<div class="menu dropdown" ng-show="toggle.isActive()">
|
||||
<ul>
|
||||
<li ng-repeat="option in view">
|
||||
<a href="" ng-click="ngModel.selected = option; toggle.setState(false)">
|
||||
<span class="ui-symbol type-icon icon">
|
||||
{{option.glyph}}
|
||||
</span>
|
||||
{{option.name}}
|
||||
<a ng-click="ngModel.selected = option; toggle.setState(false)">
|
||||
<span class="ui-symbol type-icon icon">{{option.glyph}}</span>
|
||||
{{option.name}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -53,12 +53,14 @@ define(
|
||||
|
||||
// Get list of views, read from capability
|
||||
function updateOptions(views) {
|
||||
$timeout(function () {
|
||||
$scope.ngModel.selected = findMatchingOption(
|
||||
views || [],
|
||||
($scope.ngModel || {}).selected
|
||||
);
|
||||
}, 0);
|
||||
if (Array.isArray(views)) {
|
||||
$timeout(function () {
|
||||
$scope.ngModel.selected = findMatchingOption(
|
||||
views,
|
||||
($scope.ngModel || {}).selected
|
||||
);
|
||||
}, 0);
|
||||
}
|
||||
}
|
||||
|
||||
// Update view options when the in-scope results of using the
|
||||
|
@ -1,20 +1,50 @@
|
||||
{
|
||||
"extensions": {
|
||||
"types": [
|
||||
"templates": [
|
||||
{
|
||||
"key": "infobubble",
|
||||
"name": "Info Bubble",
|
||||
"glyph": "\u00EA",
|
||||
"description": "Static markup for info bubbles",
|
||||
"features": [ "creation" ]
|
||||
"key": "info-table",
|
||||
"templateUrl": "info-table.html"
|
||||
},
|
||||
{
|
||||
"key": "info-bubble",
|
||||
"templateUrl": "info-bubble.html"
|
||||
}
|
||||
],
|
||||
"views": [
|
||||
"containers": [
|
||||
{
|
||||
"templateUrl": "infobubble.html",
|
||||
"name": "Info Bubble",
|
||||
"type": "infobubble",
|
||||
"key": "infobubble"
|
||||
"key": "bubble",
|
||||
"templateUrl": "bubble.html",
|
||||
"attributes": [ "bubbleTitle", "bubbleLayout" ],
|
||||
"alias": "bubble"
|
||||
}
|
||||
],
|
||||
"gestures": [
|
||||
{
|
||||
"key": "info",
|
||||
"implementation": "gestures/InfoGesture.js",
|
||||
"depends": [
|
||||
"$timeout",
|
||||
"infoService",
|
||||
"INFO_HOVER_DELAY"
|
||||
]
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
{
|
||||
"key": "infoService",
|
||||
"implementation": "services/InfoService.js",
|
||||
"depends": [
|
||||
"$compile",
|
||||
"$document",
|
||||
"$window",
|
||||
"$rootScope"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constants": [
|
||||
{
|
||||
"key": "INFO_HOVER_DELAY",
|
||||
"value": 2000
|
||||
}
|
||||
]
|
||||
}
|
||||
|
9
platform/commonUI/inspect/res/bubble.html
Normal file
9
platform/commonUI/inspect/res/bubble.html
Normal file
@ -0,0 +1,9 @@
|
||||
<div class="t-infobubble s-infobubble l-infobubble-wrapper {{bubble.bubbleLayout}}">
|
||||
<div class="l-infobubble">
|
||||
<div ng-show="bubble.bubbleTitle.length > 0"
|
||||
class="title">
|
||||
{{bubble.bubbleTitle}}
|
||||
</div>
|
||||
<span ng-transclude></span>
|
||||
</div>
|
||||
</div>
|
9
platform/commonUI/inspect/res/info-bubble.html
Normal file
9
platform/commonUI/inspect/res/info-bubble.html
Normal file
@ -0,0 +1,9 @@
|
||||
<mct-container
|
||||
key="bubble"
|
||||
bubble-title="{{parameters.title}}"
|
||||
bubble-layout="{{parameters.layout}}"
|
||||
>
|
||||
<mct-include key="info-table"
|
||||
ng-model="ngModel">
|
||||
</mct-include>
|
||||
</mct-container>
|
8
platform/commonUI/inspect/res/info-table.html
Normal file
8
platform/commonUI/inspect/res/info-table.html
Normal file
@ -0,0 +1,8 @@
|
||||
<table>
|
||||
<tr ng-repeat="property in ngModel">
|
||||
<td class="label">{{property.name}}</td>
|
||||
<td title="{{property.value}}" class="value align-{{property.align}}">
|
||||
{{property.value}}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
@ -19,12 +19,18 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
@import "compass";
|
||||
@import "compass/css3";
|
||||
@import "compass/css3/border-radius";
|
||||
@import "compass/css3/opacity";
|
||||
@import "compass/utilities";
|
||||
|
||||
@import "constants";
|
||||
@import "mixins";
|
||||
@import "plots/plots-main";
|
||||
/*global define*/
|
||||
define({
|
||||
BUBBLE_TEMPLATE: "<mct-container key=\"bubble\" " +
|
||||
"bubble-title=\"{{bubbleTitle}}\" " +
|
||||
"bubble-layout=\"{{bubbleLayout}}\" " +
|
||||
"class=\"bubble-container\">" +
|
||||
"<mct-include key=\"bubbleTemplate\" ng-model=\"bubbleModel\">" +
|
||||
"</mct-include>" +
|
||||
"</mct-container>",
|
||||
// Pixel offset for bubble, to align arrow position
|
||||
BUBBLE_OFFSET: [ 0, -26 ],
|
||||
// Max width and margins allowed for bubbles; defined in /platform/commonUI/general/res/sass/_constants.scss
|
||||
BUBBLE_MARGIN_LR: 10,
|
||||
BUBBLE_MAX_WIDTH: 300
|
||||
});
|
121
platform/commonUI/inspect/src/gestures/InfoGesture.js
Normal file
121
platform/commonUI/inspect/src/gestures/InfoGesture.js
Normal file
@ -0,0 +1,121 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The `info` gesture displays domain object metadata in a
|
||||
* bubble on hover.
|
||||
*
|
||||
* @constructor
|
||||
* @param $timeout Angular's `$timeout`
|
||||
* @param {InfoService} infoService a service which shows info bubbles
|
||||
* @param {number} DELAY delay, in milliseconds, before bubble appears
|
||||
* @param element jqLite-wrapped DOM element
|
||||
* @param {DomainObject} domainObject the domain object for which to
|
||||
* show information
|
||||
*/
|
||||
function InfoGesture($timeout, infoService, DELAY, element, domainObject) {
|
||||
var dismissBubble,
|
||||
pendingBubble,
|
||||
mousePosition,
|
||||
scopeOff;
|
||||
|
||||
function trackPosition(event) {
|
||||
// Record mouse position, so bubble can be shown at latest
|
||||
// mouse position (not just where the mouse entered)
|
||||
mousePosition = [ event.clientX, event.clientY ];
|
||||
}
|
||||
|
||||
function hideBubble() {
|
||||
// If a bubble is showing, dismiss it
|
||||
if (dismissBubble) {
|
||||
dismissBubble();
|
||||
element.off('mouseleave', hideBubble);
|
||||
dismissBubble = undefined;
|
||||
}
|
||||
// If a bubble will be shown on a timeout, cancel that
|
||||
if (pendingBubble) {
|
||||
$timeout.cancel(pendingBubble);
|
||||
element.off('mousemove', trackPosition);
|
||||
element.off('mouseleave', hideBubble);
|
||||
pendingBubble = undefined;
|
||||
}
|
||||
// Also clear mouse position so we don't have a ton of tiny
|
||||
// arrays allocated while user mouses over things
|
||||
mousePosition = undefined;
|
||||
}
|
||||
|
||||
function showBubble(event) {
|
||||
trackPosition(event);
|
||||
|
||||
// Also need to track position during hover
|
||||
element.on('mousemove', trackPosition);
|
||||
|
||||
// Show the bubble, after a suitable delay (if mouse has
|
||||
// left before this time is up, this will be canceled.)
|
||||
pendingBubble = $timeout(function () {
|
||||
dismissBubble = infoService.display(
|
||||
"info-table",
|
||||
domainObject.getModel().name,
|
||||
domainObject.useCapability('metadata'),
|
||||
mousePosition
|
||||
);
|
||||
element.off('mousemove', trackPosition);
|
||||
pendingBubble = undefined;
|
||||
}, DELAY);
|
||||
|
||||
element.on('mouseleave', hideBubble);
|
||||
}
|
||||
|
||||
// Show bubble (on a timeout) on mouse over
|
||||
element.on('mouseenter', showBubble);
|
||||
|
||||
// Also make sure we dismiss bubble if representation is destroyed
|
||||
// before the mouse actually leaves it
|
||||
scopeOff = element.scope().$on('$destroy', hideBubble);
|
||||
|
||||
return {
|
||||
/**
|
||||
* Detach any event handlers associated with this gesture.
|
||||
* @memberof InfoGesture
|
||||
* @method
|
||||
*/
|
||||
destroy: function () {
|
||||
// Dismiss any active bubble...
|
||||
hideBubble();
|
||||
// ...and detach listeners
|
||||
element.off('mouseenter', showBubble);
|
||||
scopeOff();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return InfoGesture;
|
||||
|
||||
}
|
||||
|
||||
);
|
95
platform/commonUI/inspect/src/services/InfoService.js
Normal file
95
platform/commonUI/inspect/src/services/InfoService.js
Normal file
@ -0,0 +1,95 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
['../InfoConstants'],
|
||||
function (InfoConstants) {
|
||||
"use strict";
|
||||
|
||||
var BUBBLE_TEMPLATE = InfoConstants.BUBBLE_TEMPLATE,
|
||||
OFFSET = InfoConstants.BUBBLE_OFFSET;
|
||||
|
||||
/**
|
||||
* Displays informative content ("info bubbles") for the user.
|
||||
* @constructor
|
||||
*/
|
||||
function InfoService($compile, $document, $window, $rootScope) {
|
||||
|
||||
function display(templateKey, title, content, position) {
|
||||
var body = $document.find('body'),
|
||||
scope = $rootScope.$new(),
|
||||
winDim = [$window.innerWidth, $window.innerHeight],
|
||||
bubbleSpaceLR = InfoConstants.BUBBLE_MARGIN_LR + InfoConstants.BUBBLE_MAX_WIDTH,
|
||||
goLeft = position[0] > (winDim[0] - bubbleSpaceLR),
|
||||
goUp = position[1] > (winDim[1] / 2),
|
||||
bubble;
|
||||
|
||||
// Pass model & container parameters into the scope
|
||||
scope.bubbleModel = content;
|
||||
scope.bubbleTemplate = templateKey;
|
||||
scope.bubbleLayout = (goUp ? 'arw-btm' : 'arw-top') + ' ' +
|
||||
(goLeft ? 'arw-right' : 'arw-left');
|
||||
scope.bubbleTitle = title;
|
||||
|
||||
// Create the context menu
|
||||
bubble = $compile(BUBBLE_TEMPLATE)(scope);
|
||||
|
||||
// Position the bubble
|
||||
bubble.css('position', 'absolute');
|
||||
if (goLeft) {
|
||||
bubble.css('right', (winDim[0] - position[0] + OFFSET[0]) + 'px');
|
||||
} else {
|
||||
bubble.css('left', position[0] + OFFSET[0] + 'px');
|
||||
}
|
||||
if (goUp) {
|
||||
bubble.css('bottom', (winDim[1] - position[1] + OFFSET[1]) + 'px');
|
||||
} else {
|
||||
bubble.css('top', position[1] + OFFSET[1] + 'px');
|
||||
}
|
||||
|
||||
// Add the menu to the body
|
||||
body.append(bubble);
|
||||
|
||||
// Return a function to dismiss the bubble
|
||||
return function () { bubble.remove(); };
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Display an info bubble at the specified location.
|
||||
* @param {string} templateKey template to place in bubble
|
||||
* @param {string} title title for the bubble
|
||||
* @param {*} content content to pass to the template, via
|
||||
* `ng-model`
|
||||
* @param {number[]} x,y position of the info bubble, in
|
||||
* pixel coordinates.
|
||||
* @returns {Function} a function that may be invoked to
|
||||
* dismiss the info bubble
|
||||
*/
|
||||
display: display
|
||||
};
|
||||
}
|
||||
|
||||
return InfoService;
|
||||
}
|
||||
);
|
157
platform/commonUI/inspect/test/gestures/InfoGestureSpec.js
Normal file
157
platform/commonUI/inspect/test/gestures/InfoGestureSpec.js
Normal file
@ -0,0 +1,157 @@
|
||||
/*****************************************************************************
|
||||
* 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,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
['../../src/gestures/InfoGesture'],
|
||||
function (InfoGesture) {
|
||||
"use strict";
|
||||
|
||||
describe("The info gesture", function () {
|
||||
var mockTimeout,
|
||||
mockInfoService,
|
||||
testDelay = 12321,
|
||||
mockElement,
|
||||
mockDomainObject,
|
||||
mockScope,
|
||||
mockOff,
|
||||
testMetadata,
|
||||
mockPromise,
|
||||
mockHide,
|
||||
gesture;
|
||||
|
||||
function fireEvent(evt, value) {
|
||||
mockElement.on.calls.forEach(function (call) {
|
||||
if (call.args[0] === evt) {
|
||||
call.args[1](value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockTimeout = jasmine.createSpy('$timeout');
|
||||
mockTimeout.cancel = jasmine.createSpy('cancel');
|
||||
mockInfoService = jasmine.createSpyObj(
|
||||
'infoService',
|
||||
[ 'display' ]
|
||||
);
|
||||
mockElement = jasmine.createSpyObj(
|
||||
'element',
|
||||
[ 'on', 'off', 'scope', 'css' ]
|
||||
);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getId', 'getCapability', 'useCapability', 'getModel' ]
|
||||
);
|
||||
mockScope = jasmine.createSpyObj('$scope', [ '$on' ]);
|
||||
mockOff = jasmine.createSpy('$off');
|
||||
testMetadata = [ { name: "Test name", value: "Test value" } ];
|
||||
mockPromise = jasmine.createSpyObj('promise', ['then']);
|
||||
mockHide = jasmine.createSpy('hide');
|
||||
|
||||
mockDomainObject.getModel.andReturn({ name: "Test Object" });
|
||||
mockDomainObject.useCapability.andCallFake(function (c) {
|
||||
return (c === 'metadata') ? testMetadata : undefined;
|
||||
});
|
||||
mockElement.scope.andReturn(mockScope);
|
||||
mockScope.$on.andReturn(mockOff);
|
||||
mockTimeout.andReturn(mockPromise);
|
||||
mockInfoService.display.andReturn(mockHide);
|
||||
|
||||
gesture = new InfoGesture(
|
||||
mockTimeout,
|
||||
mockInfoService,
|
||||
testDelay,
|
||||
mockElement,
|
||||
mockDomainObject
|
||||
);
|
||||
});
|
||||
|
||||
it("listens for mouseenter on the representation", function () {
|
||||
expect(mockElement.on)
|
||||
.toHaveBeenCalledWith('mouseenter', jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("displays an info bubble on a delay after mouseenter", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
expect(mockTimeout)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function), testDelay);
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockInfoService.display).toHaveBeenCalledWith(
|
||||
jasmine.any(String),
|
||||
"Test Object",
|
||||
testMetadata,
|
||||
[ 1977, 42 ]
|
||||
);
|
||||
});
|
||||
|
||||
it("does not display info bubble if mouse leaves too soon", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
fireEvent("mouseleave", { clientX: 1977, clientY: 42 });
|
||||
expect(mockTimeout.cancel).toHaveBeenCalledWith(mockPromise);
|
||||
expect(mockInfoService.display).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("hides a shown bubble when mouse leaves", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockHide).not.toHaveBeenCalled(); // verify precondition
|
||||
fireEvent("mouseleave", {});
|
||||
expect(mockHide).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("tracks mouse position", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
fireEvent("mousemove", { clientX: 1999, clientY: 11 });
|
||||
fireEvent("mousemove", { clientX: 1984, clientY: 11 });
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
// Should have displayed at the latest observed mouse position
|
||||
expect(mockInfoService.display).toHaveBeenCalledWith(
|
||||
jasmine.any(String),
|
||||
"Test Object",
|
||||
testMetadata,
|
||||
[ 1984, 11 ]
|
||||
);
|
||||
});
|
||||
|
||||
it("hides shown bubbles when destroyed", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockHide).not.toHaveBeenCalled(); // verify precondition
|
||||
gesture.destroy();
|
||||
expect(mockHide).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("detaches listeners when destroyed", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
gesture.destroy();
|
||||
mockElement.on.calls.forEach(function (call) {
|
||||
expect(mockElement.off).toHaveBeenCalledWith(
|
||||
call.args[0],
|
||||
call.args[1]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
131
platform/commonUI/inspect/test/services/InfoServiceSpec.js
Normal file
131
platform/commonUI/inspect/test/services/InfoServiceSpec.js
Normal file
@ -0,0 +1,131 @@
|
||||
/*****************************************************************************
|
||||
* 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,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
['../../src/services/InfoService', '../../src/InfoConstants'],
|
||||
function (InfoService, InfoConstants) {
|
||||
"use strict";
|
||||
|
||||
describe("The info service", function () {
|
||||
var mockCompile,
|
||||
mockDocument,
|
||||
testWindow,
|
||||
mockRootScope,
|
||||
mockCompiledTemplate,
|
||||
testScope,
|
||||
mockBody,
|
||||
mockElement,
|
||||
service;
|
||||
|
||||
beforeEach(function () {
|
||||
mockCompile = jasmine.createSpy('$compile');
|
||||
mockDocument = jasmine.createSpyObj('$document', ['find']);
|
||||
testWindow = { innerWidth: 1000, innerHeight: 100 };
|
||||
mockRootScope = jasmine.createSpyObj('$rootScope', ['$new']);
|
||||
mockCompiledTemplate = jasmine.createSpy('template');
|
||||
testScope = {};
|
||||
mockBody = jasmine.createSpyObj('body', ['append']);
|
||||
mockElement = jasmine.createSpyObj('element', ['css', 'remove']);
|
||||
|
||||
mockDocument.find.andCallFake(function (tag) {
|
||||
return tag === 'body' ? mockBody : undefined;
|
||||
});
|
||||
mockCompile.andReturn(mockCompiledTemplate);
|
||||
mockCompiledTemplate.andReturn(mockElement);
|
||||
mockRootScope.$new.andReturn(testScope);
|
||||
|
||||
service = new InfoService(
|
||||
mockCompile,
|
||||
mockDocument,
|
||||
testWindow,
|
||||
mockRootScope
|
||||
);
|
||||
});
|
||||
|
||||
it("creates elements and appends them to the body to display", function () {
|
||||
service.display('', '', {}, [0, 0]);
|
||||
expect(mockBody.append).toHaveBeenCalledWith(mockElement);
|
||||
});
|
||||
|
||||
it("provides a function to remove displayed info bubbles", function () {
|
||||
var fn = service.display('', '', {}, [0, 0]);
|
||||
expect(mockElement.remove).not.toHaveBeenCalled();
|
||||
fn();
|
||||
expect(mockElement.remove).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("depending on mouse position", function () {
|
||||
// Positioning should vary based on quadrant in window,
|
||||
// which is 1000 x 100 in this test case.
|
||||
it("displays from the top-left in the top-left quadrant", function () {
|
||||
service.display('', '', {}, [250, 25]);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'left',
|
||||
(250 + InfoConstants.BUBBLE_OFFSET[0]) + 'px'
|
||||
);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'top',
|
||||
(25 + InfoConstants.BUBBLE_OFFSET[1]) + 'px'
|
||||
);
|
||||
});
|
||||
|
||||
it("displays from the top-right in the top-right quadrant", function () {
|
||||
service.display('', '', {}, [700, 25]);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'right',
|
||||
(300 + InfoConstants.BUBBLE_OFFSET[0]) + 'px'
|
||||
);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'top',
|
||||
(25 + InfoConstants.BUBBLE_OFFSET[1]) + 'px'
|
||||
);
|
||||
});
|
||||
|
||||
it("displays from the bottom-left in the bottom-left quadrant", function () {
|
||||
service.display('', '', {}, [250, 70]);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'left',
|
||||
(250 + InfoConstants.BUBBLE_OFFSET[0]) + 'px'
|
||||
);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'bottom',
|
||||
(30 + InfoConstants.BUBBLE_OFFSET[1]) + 'px'
|
||||
);
|
||||
});
|
||||
|
||||
it("displays from the bottom-right in the bottom-right quadrant", function () {
|
||||
service.display('', '', {}, [800, 60]);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'right',
|
||||
(200 + InfoConstants.BUBBLE_OFFSET[0]) + 'px'
|
||||
);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'bottom',
|
||||
(40 + InfoConstants.BUBBLE_OFFSET[1]) + 'px'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
4
platform/commonUI/inspect/test/suite.json
Normal file
4
platform/commonUI/inspect/test/suite.json
Normal file
@ -0,0 +1,4 @@
|
||||
[
|
||||
"gestures/InfoGesture",
|
||||
"services/InfoService"
|
||||
]
|
@ -12,6 +12,11 @@
|
||||
"implementation": "CompositionMutabilityPolicy.js",
|
||||
"message": "Objects of this type cannot be modified."
|
||||
},
|
||||
{
|
||||
"category": "composition",
|
||||
"implementation": "CompositionModelPolicy.js",
|
||||
"message": "Objects of this type cannot contain other objects."
|
||||
},
|
||||
{
|
||||
"category": "action",
|
||||
"implementation": "ComposeActionPolicy.js",
|
||||
|
28
platform/containment/src/CompositionModelPolicy.js
Normal file
28
platform/containment/src/CompositionModelPolicy.js
Normal file
@ -0,0 +1,28 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Policy allowing composition only for domain object types which
|
||||
* have a composition property.
|
||||
*/
|
||||
function CompositionModelPolicy() {
|
||||
return {
|
||||
/**
|
||||
* Is the type identified by the candidate allowed to
|
||||
* contain the type described by the context?
|
||||
*/
|
||||
allow: function (candidate, context) {
|
||||
return Array.isArray(
|
||||
(candidate.getInitialModel() || {}).composition
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return CompositionModelPolicy;
|
||||
}
|
||||
);
|
26
platform/containment/test/CompositionModelPolicySpec.js
Normal file
26
platform/containment/test/CompositionModelPolicySpec.js
Normal file
@ -0,0 +1,26 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/CompositionModelPolicy"],
|
||||
function (CompositionModelPolicy) {
|
||||
"use strict";
|
||||
|
||||
describe("The composition model policy", function () {
|
||||
var mockType,
|
||||
policy;
|
||||
|
||||
beforeEach(function () {
|
||||
mockType = jasmine.createSpyObj('type', ['getInitialModel']);
|
||||
policy = new CompositionModelPolicy();
|
||||
});
|
||||
|
||||
it("only allows composition for types which will have a composition property", function () {
|
||||
mockType.getInitialModel.andReturn({});
|
||||
expect(policy.allow(mockType)).toBeFalsy();
|
||||
mockType.getInitialModel.andReturn({ composition: [] });
|
||||
expect(policy.allow(mockType)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
);
|
@ -35,7 +35,7 @@ define(
|
||||
policy = new CompositionMutabilityPolicy();
|
||||
});
|
||||
|
||||
it("only allows composition for types which will have a composition capability", function () {
|
||||
it("only allows composition for types which can be created/modified", function () {
|
||||
expect(policy.allow(mockType)).toBeFalsy();
|
||||
mockType.hasFeature.andReturn(true);
|
||||
expect(policy.allow(mockType)).toBeTruthy();
|
||||
|
@ -1,6 +1,7 @@
|
||||
[
|
||||
"CapabilityTable",
|
||||
"ComposeActionPolicy",
|
||||
"CompositionModelPolicy",
|
||||
"CompositionMutabilityPolicy",
|
||||
"CompositionPolicy",
|
||||
"ContainmentTable"
|
||||
|
@ -176,6 +176,10 @@
|
||||
"implementation": "capabilities/PersistenceCapability.js",
|
||||
"depends": [ "persistenceService", "PERSISTENCE_SPACE" ]
|
||||
},
|
||||
{
|
||||
"key": "metadata",
|
||||
"implementation": "capabilities/MetadataCapability.js"
|
||||
},
|
||||
{
|
||||
"key": "mutation",
|
||||
"implementation": "capabilities/MutationCapability.js",
|
||||
@ -191,6 +195,11 @@
|
||||
{
|
||||
"key": "now",
|
||||
"implementation": "services/Now.js"
|
||||
},
|
||||
{
|
||||
"key": "throttle",
|
||||
"implementation": "services/Throttle.js",
|
||||
"depends": [ "$timeout" ]
|
||||
}
|
||||
],
|
||||
"roots": [
|
||||
|
92
platform/core/src/capabilities/MetadataCapability.js
Normal file
92
platform/core/src/capabilities/MetadataCapability.js
Normal file
@ -0,0 +1,92 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
['moment'],
|
||||
function (moment) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* A piece of information about a domain object.
|
||||
* @typedef {Object} MetadataProperty
|
||||
* @property {string} name the human-readable name of this property
|
||||
* @property {string} value the human-readable value of this property,
|
||||
* for this specific domain object
|
||||
*/
|
||||
|
||||
var TIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
|
||||
|
||||
/**
|
||||
* Implements the `metadata` capability of a domain object, providing
|
||||
* properties of that object for display.
|
||||
*
|
||||
* Usage: `domainObject.useCapability("metadata")`
|
||||
*
|
||||
* ...which will return an array of objects containing `name` and
|
||||
* `value` properties describing that domain object (suitable for
|
||||
* display.)
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function MetadataCapability(domainObject) {
|
||||
var model = domainObject.getModel();
|
||||
|
||||
function hasDisplayableValue(metadataProperty) {
|
||||
var t = typeof metadataProperty.value;
|
||||
return (t === 'string' || t === 'number');
|
||||
}
|
||||
|
||||
function formatTimestamp(timestamp) {
|
||||
return typeof timestamp === 'number' ?
|
||||
(moment.utc(timestamp).format(TIME_FORMAT) + " UTC") :
|
||||
undefined;
|
||||
}
|
||||
|
||||
function getProperties() {
|
||||
var type = domainObject.getCapability('type');
|
||||
|
||||
function lookupProperty(typeProperty) {
|
||||
return {
|
||||
name: typeProperty.getDefinition().name,
|
||||
value: typeProperty.getValue(model)
|
||||
};
|
||||
}
|
||||
|
||||
return (type ? type.getProperties() : []).map(lookupProperty);
|
||||
}
|
||||
|
||||
function getCommonMetadata() {
|
||||
var type = domainObject.getCapability('type');
|
||||
// Note that invalid values will be filtered out later
|
||||
return [
|
||||
{
|
||||
name: "Updated",
|
||||
value: formatTimestamp(model.modified)
|
||||
},
|
||||
{
|
||||
name: "Type",
|
||||
value: type && type.getName()
|
||||
},
|
||||
{
|
||||
name: "ID",
|
||||
value: domainObject.getId()
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
function getMetadata() {
|
||||
return getProperties().concat(getCommonMetadata())
|
||||
.filter(hasDisplayableValue);
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Get metadata about this object.
|
||||
* @returns {MetadataProperty[]} metadata about this object
|
||||
*/
|
||||
invoke: getMetadata
|
||||
};
|
||||
}
|
||||
|
||||
return MetadataCapability;
|
||||
}
|
||||
);
|
@ -77,7 +77,8 @@ define(
|
||||
// Get the object's model and clone it, so the
|
||||
// mutator function has a temporary copy to work with.
|
||||
var model = domainObject.getModel(),
|
||||
clone = JSON.parse(JSON.stringify(model));
|
||||
clone = JSON.parse(JSON.stringify(model)),
|
||||
useTimestamp = arguments.length > 1;
|
||||
|
||||
// Function to handle copying values to the actual
|
||||
function handleMutation(mutationResult) {
|
||||
@ -94,8 +95,7 @@ define(
|
||||
if (model !== result) {
|
||||
copyValues(model, result);
|
||||
}
|
||||
model.modified = (typeof timestamp === 'number') ?
|
||||
timestamp : now();
|
||||
model.modified = useTimestamp ? timestamp : now();
|
||||
}
|
||||
|
||||
// Report the result of the mutation
|
||||
|
63
platform/core/src/services/Throttle.js
Normal file
63
platform/core/src/services/Throttle.js
Normal file
@ -0,0 +1,63 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Throttler for function executions, registered as the `throttle`
|
||||
* service.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* throttle(fn, delay, [apply])
|
||||
*
|
||||
* Returns a function that, when invoked, will invoke `fn` after
|
||||
* `delay` milliseconds, only if no other invocations are pending.
|
||||
* The optional argument `apply` determines whether.
|
||||
*
|
||||
* The returned function will itself return a `Promise` which will
|
||||
* resolve to the returned value of `fn` whenever that is invoked.
|
||||
*
|
||||
* @returns {Function}
|
||||
*/
|
||||
function Throttle($timeout) {
|
||||
/**
|
||||
* Throttle this function.
|
||||
* @param {Function} fn the function to throttle
|
||||
* @param {number} [delay] the delay, in milliseconds, before
|
||||
* executing this function; defaults to 0.
|
||||
* @param {boolean} apply true if a `$apply` call should be
|
||||
* invoked after this function executes; defaults to
|
||||
* `false`.
|
||||
*/
|
||||
return function (fn, delay, apply) {
|
||||
var activeTimeout;
|
||||
|
||||
// Clear active timeout, so that next invocation starts
|
||||
// a new one.
|
||||
function clearActiveTimeout() {
|
||||
activeTimeout = undefined;
|
||||
}
|
||||
|
||||
// Defaults
|
||||
delay = delay || 0;
|
||||
apply = apply || false;
|
||||
|
||||
return function () {
|
||||
// Start a timeout if needed
|
||||
if (!activeTimeout) {
|
||||
activeTimeout = $timeout(fn, delay, apply);
|
||||
activeTimeout.then(clearActiveTimeout);
|
||||
}
|
||||
// Return whichever timeout is active (to get
|
||||
// a promise for the results of fn)
|
||||
return activeTimeout;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
return Throttle;
|
||||
}
|
||||
);
|
101
platform/core/test/capabilities/MetadataCapabilitySpec.js
Normal file
101
platform/core/test/capabilities/MetadataCapabilitySpec.js
Normal file
@ -0,0 +1,101 @@
|
||||
/*****************************************************************************
|
||||
* 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,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
['../../src/capabilities/MetadataCapability'],
|
||||
function (MetadataCapability) {
|
||||
"use strict";
|
||||
|
||||
describe("The metadata capability", function () {
|
||||
var mockDomainObject,
|
||||
mockType,
|
||||
mockProperties,
|
||||
testModel,
|
||||
metadata;
|
||||
|
||||
function getCapability(key) {
|
||||
return key === 'type' ? mockType : undefined;
|
||||
}
|
||||
|
||||
function findValue(properties, name) {
|
||||
var i;
|
||||
for (i = 0; i < properties.length; i += 1) {
|
||||
if (properties[i].name === name) {
|
||||
return properties[i].value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
['getId', 'getCapability', 'useCapability', 'getModel']
|
||||
);
|
||||
mockType = jasmine.createSpyObj(
|
||||
'type',
|
||||
['getProperties', 'getName']
|
||||
);
|
||||
mockProperties = ['a', 'b', 'c'].map(function (k) {
|
||||
var mockProperty = jasmine.createSpyObj(
|
||||
'property-' + k,
|
||||
['getValue', 'getDefinition']
|
||||
);
|
||||
mockProperty.getValue.andReturn("Value " + k);
|
||||
mockProperty.getDefinition.andReturn({ name: "Property " + k});
|
||||
return mockProperty;
|
||||
});
|
||||
testModel = { name: "" };
|
||||
|
||||
mockDomainObject.getId.andReturn("Test id");
|
||||
mockDomainObject.getModel.andReturn(testModel);
|
||||
mockDomainObject.getCapability.andCallFake(getCapability);
|
||||
mockDomainObject.useCapability.andCallFake(getCapability);
|
||||
mockType.getProperties.andReturn(mockProperties);
|
||||
mockType.getName.andReturn("Test type");
|
||||
|
||||
metadata = new MetadataCapability(mockDomainObject);
|
||||
});
|
||||
|
||||
it("reads properties from the domain object model", function () {
|
||||
metadata.invoke();
|
||||
mockProperties.forEach(function (mockProperty) {
|
||||
expect(mockProperty.getValue).toHaveBeenCalledWith(testModel);
|
||||
});
|
||||
});
|
||||
|
||||
it("reports type-specific properties", function () {
|
||||
var properties = metadata.invoke();
|
||||
expect(findValue(properties, 'Property a')).toEqual("Value a");
|
||||
expect(findValue(properties, 'Property b')).toEqual("Value b");
|
||||
expect(findValue(properties, 'Property c')).toEqual("Value c");
|
||||
});
|
||||
|
||||
it("reports generic properties", function () {
|
||||
var properties = metadata.invoke();
|
||||
expect(findValue(properties, 'ID')).toEqual("Test id");
|
||||
expect(findValue(properties, 'Type')).toEqual("Test type");
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
49
platform/core/test/services/ThrottleSpec.js
Normal file
49
platform/core/test/services/ThrottleSpec.js
Normal file
@ -0,0 +1,49 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../../src/services/Throttle"],
|
||||
function (Throttle) {
|
||||
"use strict";
|
||||
|
||||
describe("The 'throttle' service", function () {
|
||||
var throttle,
|
||||
mockTimeout,
|
||||
mockFn,
|
||||
mockPromise;
|
||||
|
||||
beforeEach(function () {
|
||||
mockTimeout = jasmine.createSpy("$timeout");
|
||||
mockPromise = jasmine.createSpyObj("promise", ["then"]);
|
||||
mockFn = jasmine.createSpy("fn");
|
||||
mockTimeout.andReturn(mockPromise);
|
||||
throttle = new Throttle(mockTimeout);
|
||||
});
|
||||
|
||||
it("provides functions which run on a timeout", function () {
|
||||
var throttled = throttle(mockFn);
|
||||
// Verify precondition: Not called at throttle-time
|
||||
expect(mockTimeout).not.toHaveBeenCalled();
|
||||
expect(throttled()).toEqual(mockPromise);
|
||||
expect(mockTimeout).toHaveBeenCalledWith(mockFn, 0, false);
|
||||
});
|
||||
|
||||
it("schedules only one timeout at a time", function () {
|
||||
var throttled = throttle(mockFn);
|
||||
throttled();
|
||||
throttled();
|
||||
throttled();
|
||||
expect(mockTimeout.calls.length).toEqual(1);
|
||||
});
|
||||
|
||||
it("schedules additional invocations after resolution", function () {
|
||||
var throttled = throttle(mockFn);
|
||||
throttled();
|
||||
mockPromise.then.mostRecentCall.args[0](); // Resolve timeout
|
||||
throttled();
|
||||
mockPromise.then.mostRecentCall.args[0]();
|
||||
throttled();
|
||||
expect(mockTimeout.calls.length).toEqual(3);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -9,6 +9,7 @@
|
||||
"capabilities/ContextualDomainObject",
|
||||
"capabilities/CoreCapabilityProvider",
|
||||
"capabilities/DelegationCapability",
|
||||
"capabilities/MetadataCapability",
|
||||
"capabilities/MutationCapability",
|
||||
"capabilities/PersistenceCapability",
|
||||
"capabilities/RelationshipCapability",
|
||||
@ -23,6 +24,7 @@
|
||||
"objects/DomainObjectProvider",
|
||||
|
||||
"services/Now",
|
||||
"services/Throttle",
|
||||
|
||||
"types/MergeModels",
|
||||
"types/TypeCapability",
|
||||
|
24
platform/entanglement/README.md
Normal file
24
platform/entanglement/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# Entanglement
|
||||
|
||||
Entanglement is the process of moving, copying, and linking domain objects
|
||||
in such a way that their relationships are impossible to discern.
|
||||
|
||||
This bundle provides move, copy, and link functionality. Acheiving a state of
|
||||
entanglement is left up to the end user.
|
||||
|
||||
|
||||
## Services implement logic
|
||||
|
||||
Each method (move, copy, link) is implemented as a service, and each service
|
||||
provides two functions: `validate` and `perform`.
|
||||
|
||||
`validate(object, parentCandidate)` returns true if the `object` can be
|
||||
move/copy/linked into the `parentCandidate`'s composition.
|
||||
|
||||
`perform(object, parentObject)` move/copy/links the `object` into the
|
||||
`parentObject`'s composition.
|
||||
|
||||
## Actions implement user interactions
|
||||
|
||||
Actions are used to expose move/copy/link to the user. They prompt for input
|
||||
where necessary, and complete the actions.
|
75
platform/entanglement/bundle.json
Normal file
75
platform/entanglement/bundle.json
Normal file
@ -0,0 +1,75 @@
|
||||
{
|
||||
"name": "Entanglement",
|
||||
"description": "Tools to assist you in entangling the world of WARP.",
|
||||
"configuration": {},
|
||||
"extensions": {
|
||||
"actions": [
|
||||
{
|
||||
"key": "move",
|
||||
"name": "Move",
|
||||
"description": "Move object to another location.",
|
||||
"glyph": "f",
|
||||
"category": "contextual",
|
||||
"implementation": "actions/MoveAction.js",
|
||||
"depends": ["locationService", "moveService"]
|
||||
},
|
||||
{
|
||||
"key": "copy",
|
||||
"name": "Duplicate",
|
||||
"description": "Duplicate object to another location.",
|
||||
"glyph": "+",
|
||||
"category": "contextual",
|
||||
"implementation": "actions/CopyAction.js",
|
||||
"depends": ["locationService", "copyService"]
|
||||
},
|
||||
{
|
||||
"key": "link",
|
||||
"name": "Create Link",
|
||||
"description": "Create Link to object in another location.",
|
||||
"glyph": "\u00E8",
|
||||
"category": "contextual",
|
||||
"implementation": "actions/LinkAction.js",
|
||||
"depends": ["locationService", "linkService"]
|
||||
}
|
||||
],
|
||||
"components": [
|
||||
],
|
||||
"controllers": [
|
||||
],
|
||||
"capabilities": [
|
||||
],
|
||||
"services": [
|
||||
{
|
||||
"key": "moveService",
|
||||
"name": "Move Service",
|
||||
"description": "Provides a service for moving objects",
|
||||
"implementation": "services/MoveService.js",
|
||||
"depends": ["policyService", "linkService"]
|
||||
},
|
||||
{
|
||||
"key": "linkService",
|
||||
"name": "Link Service",
|
||||
"description": "Provides a service for linking objects",
|
||||
"implementation": "services/LinkService.js",
|
||||
"depends": ["policyService"]
|
||||
},
|
||||
{
|
||||
"key": "copyService",
|
||||
"name": "Copy Service",
|
||||
"description": "Provides a service for copying objects",
|
||||
"implementation": "services/CopyService.js",
|
||||
"depends": ["$q", "creationService", "policyService"]
|
||||
},
|
||||
{
|
||||
"key": "locationService",
|
||||
"name": "Location Service",
|
||||
"description": "Provides a service for prompting a user for locations.",
|
||||
"implementation": "services/LocationService.js",
|
||||
"depends": ["dialogService"]
|
||||
}
|
||||
|
||||
],
|
||||
"licenses": [
|
||||
]
|
||||
}
|
||||
}
|
92
platform/entanglement/src/actions/CopyAction.js
Normal file
92
platform/entanglement/src/actions/CopyAction.js
Normal file
@ -0,0 +1,92 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
|
||||
/**
|
||||
* The CopyAction is available from context menus and allows a user to
|
||||
* deep copy an object to another location of their choosing.
|
||||
*
|
||||
* @implements Action
|
||||
*/
|
||||
function CopyAction(locationService, copyService, context) {
|
||||
|
||||
var object,
|
||||
newParent,
|
||||
currentParent;
|
||||
|
||||
if (context.selectedObject) {
|
||||
newParent = context.domainObject;
|
||||
object = context.selectedObject;
|
||||
} else {
|
||||
object = context.domainObject;
|
||||
}
|
||||
|
||||
currentParent = object
|
||||
.getCapability('context')
|
||||
.getParent();
|
||||
|
||||
return {
|
||||
perform: function () {
|
||||
|
||||
if (newParent) {
|
||||
return copyService
|
||||
.perform(object, newParent);
|
||||
}
|
||||
|
||||
var dialogTitle,
|
||||
label,
|
||||
validateLocation;
|
||||
|
||||
dialogTitle = [
|
||||
"Duplicate ",
|
||||
object.getModel().name,
|
||||
" to a location"
|
||||
].join("");
|
||||
|
||||
label = "Duplicate To";
|
||||
|
||||
validateLocation = function (newParent) {
|
||||
return copyService
|
||||
.validate(object, newParent);
|
||||
};
|
||||
|
||||
return locationService.getLocationFromUser(
|
||||
dialogTitle,
|
||||
label,
|
||||
validateLocation,
|
||||
currentParent
|
||||
).then(function (newParent) {
|
||||
return copyService
|
||||
.perform(object, newParent);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return CopyAction;
|
||||
}
|
||||
);
|
89
platform/entanglement/src/actions/LinkAction.js
Normal file
89
platform/entanglement/src/actions/LinkAction.js
Normal file
@ -0,0 +1,89 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The LinkAction is available from context menus and allows a user to
|
||||
* link an object to another location of their choosing.
|
||||
*
|
||||
* @implements Action
|
||||
*/
|
||||
function LinkAction(locationService, linkService, context) {
|
||||
|
||||
var object,
|
||||
newParent,
|
||||
currentParent;
|
||||
|
||||
if (context.selectedObject) {
|
||||
newParent = context.domainObject;
|
||||
object = context.selectedObject;
|
||||
} else {
|
||||
object = context.domainObject;
|
||||
}
|
||||
|
||||
currentParent = object
|
||||
.getCapability('context')
|
||||
.getParent();
|
||||
|
||||
return {
|
||||
perform: function () {
|
||||
if (newParent) {
|
||||
return linkService
|
||||
.perform(object, newParent);
|
||||
}
|
||||
var dialogTitle,
|
||||
label,
|
||||
validateLocation;
|
||||
|
||||
dialogTitle = [
|
||||
"Link ",
|
||||
object.getModel().name,
|
||||
" to a new location"
|
||||
].join("");
|
||||
|
||||
label = "Link To";
|
||||
|
||||
validateLocation = function (newParent) {
|
||||
return linkService
|
||||
.validate(object, newParent);
|
||||
};
|
||||
|
||||
return locationService.getLocationFromUser(
|
||||
dialogTitle,
|
||||
label,
|
||||
validateLocation,
|
||||
currentParent
|
||||
).then(function (newParent) {
|
||||
return linkService
|
||||
.perform(object, newParent);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return LinkAction;
|
||||
}
|
||||
);
|
90
platform/entanglement/src/actions/MoveAction.js
Normal file
90
platform/entanglement/src/actions/MoveAction.js
Normal file
@ -0,0 +1,90 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The MoveAction is available from context menus and allows a user to
|
||||
* move an object to another location of their choosing.
|
||||
*
|
||||
* @implements Action
|
||||
*/
|
||||
function MoveAction(locationService, moveService, context) {
|
||||
|
||||
var object,
|
||||
newParent,
|
||||
currentParent;
|
||||
|
||||
if (context.selectedObject) {
|
||||
newParent = context.domainObject;
|
||||
object = context.selectedObject;
|
||||
} else {
|
||||
object = context.domainObject;
|
||||
}
|
||||
|
||||
currentParent = object
|
||||
.getCapability('context')
|
||||
.getParent();
|
||||
|
||||
return {
|
||||
perform: function () {
|
||||
if (newParent) {
|
||||
return moveService
|
||||
.perform(object, newParent);
|
||||
}
|
||||
|
||||
var dialogTitle,
|
||||
label,
|
||||
validateLocation;
|
||||
|
||||
dialogTitle = [
|
||||
"Move ",
|
||||
object.getModel().name,
|
||||
" to a new location"
|
||||
].join("");
|
||||
|
||||
label = "Move To";
|
||||
|
||||
validateLocation = function (newParent) {
|
||||
return moveService
|
||||
.validate(object, newParent);
|
||||
};
|
||||
|
||||
return locationService.getLocationFromUser(
|
||||
dialogTitle,
|
||||
label,
|
||||
validateLocation,
|
||||
currentParent
|
||||
).then(function (newParent) {
|
||||
return moveService
|
||||
.perform(object, newParent);
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return MoveAction;
|
||||
}
|
||||
);
|
106
platform/entanglement/src/services/CopyService.js
Normal file
106
platform/entanglement/src/services/CopyService.js
Normal file
@ -0,0 +1,106 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* CopyService provides an interface for deep copying objects from one
|
||||
* location to another. It also provides a method for determining if
|
||||
* an object can be copied to a specific location.
|
||||
*/
|
||||
function CopyService($q, creationService, policyService) {
|
||||
|
||||
/**
|
||||
* duplicateObject duplicates a `domainObject` into the composition
|
||||
* of `parent`, and then duplicates the composition of
|
||||
* `domainObject` into the new object.
|
||||
*
|
||||
* This function is a recursive deep copy.
|
||||
*
|
||||
* @param {DomainObject} domainObject - the domain object to
|
||||
* duplicate.
|
||||
* @param {DomainObject} parent - the parent domain object to
|
||||
* create the duplicate in.
|
||||
* @returns {Promise} A promise that is fulfilled when the
|
||||
* duplicate operation has completed.
|
||||
*/
|
||||
function duplicateObject(domainObject, parent) {
|
||||
var model = JSON.parse(JSON.stringify(domainObject.getModel()));
|
||||
if (domainObject.hasCapability('composition')) {
|
||||
model.composition = [];
|
||||
}
|
||||
|
||||
return creationService
|
||||
.createObject(model, parent)
|
||||
.then(function (newObject) {
|
||||
if (!domainObject.hasCapability('composition')) {
|
||||
return;
|
||||
}
|
||||
|
||||
return domainObject
|
||||
.useCapability('composition')
|
||||
.then(function (composees) {
|
||||
// Duplicate composition serially to prevent
|
||||
// write conflicts.
|
||||
return composees.reduce(function (promise, composee) {
|
||||
return promise.then(function () {
|
||||
return duplicateObject(composee, newObject);
|
||||
});
|
||||
}, $q.when(undefined));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Returns true if `object` can be copied into
|
||||
* `parentCandidate`'s composition.
|
||||
*/
|
||||
validate: function (object, parentCandidate) {
|
||||
if (!parentCandidate || !parentCandidate.getId) {
|
||||
return false;
|
||||
}
|
||||
if (parentCandidate.getId() === object.getId()) {
|
||||
return false;
|
||||
}
|
||||
return policyService.allow(
|
||||
"composition",
|
||||
parentCandidate.getCapability('type'),
|
||||
object.getCapability('type')
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Wrapper, @see {@link duplicateObject} for implementation.
|
||||
*/
|
||||
perform: function (object, parentObject) {
|
||||
return duplicateObject(object, parentObject);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return CopyService;
|
||||
}
|
||||
);
|
76
platform/entanglement/src/services/LinkService.js
Normal file
76
platform/entanglement/src/services/LinkService.js
Normal file
@ -0,0 +1,76 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* LinkService provides an interface for linking objects to additional
|
||||
* locations. It also provides a method for determining if an object
|
||||
* can be copied to a specific location.
|
||||
*/
|
||||
function LinkService(policyService) {
|
||||
return {
|
||||
/**
|
||||
* Returns `true` if `object` can be linked into
|
||||
* `parentCandidate`'s composition.
|
||||
*/
|
||||
validate: function (object, parentCandidate) {
|
||||
if (!parentCandidate || !parentCandidate.getId) {
|
||||
return false;
|
||||
}
|
||||
if (parentCandidate.getId() === object.getId()) {
|
||||
return false;
|
||||
}
|
||||
if (parentCandidate.getModel().composition.indexOf(object.getId()) !== -1) {
|
||||
return false;
|
||||
}
|
||||
return policyService.allow(
|
||||
"composition",
|
||||
parentCandidate.getCapability('type'),
|
||||
object.getCapability('type')
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Link `object` into `parentObject`'s composition.
|
||||
*
|
||||
* @returns {Promise} A promise that is fulfilled when the
|
||||
* linking operation has completed.
|
||||
*/
|
||||
perform: function (object, parentObject) {
|
||||
return parentObject.useCapability('mutation', function (model) {
|
||||
if (model.composition.indexOf(object.getId()) === -1) {
|
||||
model.composition.push(object.getId());
|
||||
}
|
||||
}).then(function () {
|
||||
return parentObject.getCapability('persistence').persist();
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return LinkService;
|
||||
}
|
||||
);
|
83
platform/entanglement/src/services/LocationService.js
Normal file
83
platform/entanglement/src/services/LocationService.js
Normal file
@ -0,0 +1,83 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The LocationService allows for easily prompting the user for a
|
||||
* location in the root tree.
|
||||
*/
|
||||
function LocationService(dialogService) {
|
||||
return {
|
||||
/** Prompt the user to select a location. Returns a promise
|
||||
* that is resolved with a domainObject representing the
|
||||
* location selected by the user.
|
||||
*
|
||||
* @param {string} title - title of location dialog
|
||||
* @param {string} label - label for location input field
|
||||
* @param {function} validate - function that validates
|
||||
* selections.
|
||||
* @param {domainObject} initialLocation - tree location to
|
||||
* display at start
|
||||
* @returns {Promise} promise for a domain object.
|
||||
*/
|
||||
getLocationFromUser: function (title, label, validate, initialLocation) {
|
||||
var formStructure,
|
||||
formState;
|
||||
|
||||
formStructure = {
|
||||
sections: [
|
||||
{
|
||||
name: 'Location',
|
||||
rows: [
|
||||
{
|
||||
name: label,
|
||||
control: "locator",
|
||||
validate: validate,
|
||||
key: 'location'
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
name: title
|
||||
};
|
||||
|
||||
formState = {
|
||||
location: initialLocation
|
||||
};
|
||||
|
||||
return dialogService
|
||||
.getUserInput(formStructure, formState)
|
||||
.then(function (formState) {
|
||||
return formState.location;
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return LocationService;
|
||||
}
|
||||
);
|
83
platform/entanglement/src/services/MoveService.js
Normal file
83
platform/entanglement/src/services/MoveService.js
Normal file
@ -0,0 +1,83 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* MoveService provides an interface for moving objects from one
|
||||
* location to another. It also provides a method for determining if
|
||||
* an object can be copied to a specific location.
|
||||
*/
|
||||
function MoveService(policyService, linkService) {
|
||||
return {
|
||||
/**
|
||||
* Returns `true` if `object` can be moved into
|
||||
* `parentCandidate`'s composition.
|
||||
*/
|
||||
validate: function (object, parentCandidate) {
|
||||
var currentParent = object
|
||||
.getCapability('context')
|
||||
.getParent();
|
||||
|
||||
if (!parentCandidate || !parentCandidate.getId) {
|
||||
return false;
|
||||
}
|
||||
if (parentCandidate.getId() === currentParent.getId()) {
|
||||
return false;
|
||||
}
|
||||
if (parentCandidate.getId() === object.getId()) {
|
||||
return false;
|
||||
}
|
||||
if (parentCandidate.getModel().composition.indexOf(object.getId()) !== -1) {
|
||||
return false;
|
||||
}
|
||||
return policyService.allow(
|
||||
"composition",
|
||||
parentCandidate.getCapability('type'),
|
||||
object.getCapability('type')
|
||||
);
|
||||
},
|
||||
/**
|
||||
* Move `object` into `parentObject`'s composition.
|
||||
*
|
||||
* @returns {Promise} A promise that is fulfilled when the
|
||||
* move operation has completed.
|
||||
*/
|
||||
perform: function (object, parentObject) {
|
||||
return linkService
|
||||
.perform(object, parentObject)
|
||||
.then(function () {
|
||||
return object
|
||||
.getCapability('action')
|
||||
.perform('remove');
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return MoveService;
|
||||
}
|
||||
);
|
158
platform/entanglement/test/DomainObjectFactory.js
Normal file
158
platform/entanglement/test/DomainObjectFactory.js
Normal file
@ -0,0 +1,158 @@
|
||||
/*****************************************************************************
|
||||
* 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, jasmine, */
|
||||
|
||||
define(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @typedef DomainObjectConfig
|
||||
* @type {object}
|
||||
* @property {string} [name] a name for the underlying jasmine spy
|
||||
* object mockDomainObject. Used as
|
||||
* @property {string} [id] initial id value for the domainOBject.
|
||||
* @property {object} [model] initial values for the object's model.
|
||||
* @property {object} [capabilities] an object containing
|
||||
* capability definitions.
|
||||
*/
|
||||
|
||||
var configObjectProps = ['model', 'capabilities'];
|
||||
|
||||
/**
|
||||
* Internal function for ensuring an object is an instance of a
|
||||
* DomainObjectConfig.
|
||||
*/
|
||||
function ensureValidConfigObject(config) {
|
||||
if (!config || !config.hasOwnProperty) {
|
||||
config = {};
|
||||
}
|
||||
if (!config.name) {
|
||||
config.name = 'domainObject';
|
||||
}
|
||||
configObjectProps.forEach(function (prop) {
|
||||
if (!config[prop] || !config[prop].hasOwnProperty) {
|
||||
config[prop] = {};
|
||||
}
|
||||
});
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines a factory function which takes a `config` object and returns
|
||||
* a mock domainObject. The config object is an easy way to provide
|
||||
* initial properties for the domainObject-- they can be changed at any
|
||||
* time by directly modifying the domainObject's properties.
|
||||
*
|
||||
* @param {Object} [config] initial configuration for a domain object.
|
||||
* @returns {Object} mockDomainObject
|
||||
*/
|
||||
function domainObjectFactory(config) {
|
||||
config = ensureValidConfigObject(config);
|
||||
|
||||
var domainObject = jasmine.createSpyObj(config.name, [
|
||||
'getId',
|
||||
'getModel',
|
||||
'getCapability',
|
||||
'hasCapability',
|
||||
'useCapability'
|
||||
]);
|
||||
|
||||
domainObject.model = JSON.parse(JSON.stringify(config.model));
|
||||
domainObject.capabilities = config.capabilities;
|
||||
domainObject.id = config.id;
|
||||
|
||||
/**
|
||||
* getId: Returns `domainObject.id`.
|
||||
*
|
||||
* @returns {string} id
|
||||
*/
|
||||
domainObject.getId.andCallFake(function () {
|
||||
return domainObject.id;
|
||||
});
|
||||
|
||||
/**
|
||||
* getModel: Returns `domainObject.model`.
|
||||
*
|
||||
* @returns {object} model
|
||||
*/
|
||||
domainObject.getModel.andCallFake(function () {
|
||||
return domainObject.model;
|
||||
});
|
||||
|
||||
/**
|
||||
* getCapability: returns a `capability` object defined in
|
||||
* domainObject.capabilities. Returns undefined if capability
|
||||
* does not exist.
|
||||
*
|
||||
* @param {string} capability name of the capability to return.
|
||||
* @returns {*} capability object
|
||||
*/
|
||||
domainObject.getCapability.andCallFake(function (capability) {
|
||||
if (config.capabilities.hasOwnProperty(capability)) {
|
||||
return config.capabilities[capability];
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
* hasCapability: return true if domainObject.capabilities has a
|
||||
* property named `capability`, otherwise returns false.
|
||||
*
|
||||
* @param {string} capability name of the capability to test for
|
||||
* existence of.
|
||||
* @returns {boolean}
|
||||
*/
|
||||
domainObject.hasCapability.andCallFake(function (capability) {
|
||||
return config.capabilities.hasOwnProperty(capability);
|
||||
});
|
||||
|
||||
/**
|
||||
* useCapability: find a capability in domainObject.capabilities
|
||||
* and call that capabilities' invoke method. If the capability
|
||||
* does not have an invoke method, will throw an error.
|
||||
*
|
||||
* @param {string} capability name of a capability to invoke.
|
||||
* @param {...*} params to pass to the capability's `invoke` method.
|
||||
* @returns {*} result whatever was returned by `invoke`.
|
||||
*/
|
||||
domainObject.useCapability.andCallFake(function (capability) {
|
||||
if (config.capabilities.hasOwnProperty(capability)) {
|
||||
if (!config.capabilities[capability].invoke) {
|
||||
throw new Error(
|
||||
capability + ' missing invoke function.'
|
||||
);
|
||||
}
|
||||
var passThroughArgs = [].slice.call(arguments, 1);
|
||||
return config
|
||||
.capabilities[capability]
|
||||
.invoke
|
||||
.apply(null, passThroughArgs);
|
||||
}
|
||||
});
|
||||
|
||||
return domainObject;
|
||||
}
|
||||
|
||||
return domainObjectFactory;
|
||||
}
|
||||
);
|
174
platform/entanglement/test/actions/CopyActionSpec.js
Normal file
174
platform/entanglement/test/actions/CopyActionSpec.js
Normal file
@ -0,0 +1,174 @@
|
||||
/*****************************************************************************
|
||||
* 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,describe,beforeEach,it,jasmine,expect */
|
||||
|
||||
define(
|
||||
[
|
||||
'../../src/actions/CopyAction',
|
||||
'../services/MockCopyService',
|
||||
'../DomainObjectFactory'
|
||||
],
|
||||
function (CopyAction, MockCopyService, domainObjectFactory) {
|
||||
"use strict";
|
||||
|
||||
describe("Copy Action", function () {
|
||||
|
||||
var copyAction,
|
||||
locationService,
|
||||
locationServicePromise,
|
||||
copyService,
|
||||
context,
|
||||
selectedObject,
|
||||
selectedObjectContextCapability,
|
||||
currentParent,
|
||||
newParent;
|
||||
|
||||
beforeEach(function () {
|
||||
selectedObjectContextCapability = jasmine.createSpyObj(
|
||||
'selectedObjectContextCapability',
|
||||
[
|
||||
'getParent'
|
||||
]
|
||||
);
|
||||
|
||||
selectedObject = domainObjectFactory({
|
||||
name: 'selectedObject',
|
||||
model: {
|
||||
name: 'selectedObject'
|
||||
},
|
||||
capabilities: {
|
||||
context: selectedObjectContextCapability
|
||||
}
|
||||
});
|
||||
|
||||
currentParent = domainObjectFactory({
|
||||
name: 'currentParent'
|
||||
});
|
||||
|
||||
selectedObjectContextCapability
|
||||
.getParent
|
||||
.andReturn(currentParent);
|
||||
|
||||
newParent = domainObjectFactory({
|
||||
name: 'newParent'
|
||||
});
|
||||
|
||||
locationService = jasmine.createSpyObj(
|
||||
'locationService',
|
||||
[
|
||||
'getLocationFromUser'
|
||||
]
|
||||
);
|
||||
|
||||
locationServicePromise = jasmine.createSpyObj(
|
||||
'locationServicePromise',
|
||||
[
|
||||
'then'
|
||||
]
|
||||
);
|
||||
|
||||
locationService
|
||||
.getLocationFromUser
|
||||
.andReturn(locationServicePromise);
|
||||
|
||||
copyService = new MockCopyService();
|
||||
});
|
||||
|
||||
|
||||
describe("with context from context-action", function () {
|
||||
beforeEach(function () {
|
||||
context = {
|
||||
domainObject: selectedObject
|
||||
};
|
||||
|
||||
copyAction = new CopyAction(
|
||||
locationService,
|
||||
copyService,
|
||||
context
|
||||
);
|
||||
});
|
||||
|
||||
it("initializes happily", function () {
|
||||
expect(copyAction).toBeDefined();
|
||||
});
|
||||
|
||||
describe("when performed it", function () {
|
||||
beforeEach(function () {
|
||||
copyAction.perform();
|
||||
});
|
||||
|
||||
it("prompts for location", function () {
|
||||
expect(locationService.getLocationFromUser)
|
||||
.toHaveBeenCalledWith(
|
||||
"Duplicate selectedObject to a location",
|
||||
"Duplicate To",
|
||||
jasmine.any(Function),
|
||||
currentParent
|
||||
);
|
||||
});
|
||||
|
||||
it("waits for location from user", function () {
|
||||
expect(locationServicePromise.then)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("copys object to selected location", function () {
|
||||
locationServicePromise
|
||||
.then
|
||||
.mostRecentCall
|
||||
.args[0](newParent);
|
||||
|
||||
expect(copyService.perform)
|
||||
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with context from drag-drop", function () {
|
||||
beforeEach(function () {
|
||||
context = {
|
||||
selectedObject: selectedObject,
|
||||
domainObject: newParent
|
||||
};
|
||||
|
||||
copyAction = new CopyAction(
|
||||
locationService,
|
||||
copyService,
|
||||
context
|
||||
);
|
||||
});
|
||||
|
||||
it("initializes happily", function () {
|
||||
expect(copyAction).toBeDefined();
|
||||
});
|
||||
|
||||
|
||||
it("performs copy immediately", function () {
|
||||
copyAction.perform();
|
||||
expect(copyService.perform)
|
||||
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
174
platform/entanglement/test/actions/LinkActionSpec.js
Normal file
174
platform/entanglement/test/actions/LinkActionSpec.js
Normal file
@ -0,0 +1,174 @@
|
||||
/*****************************************************************************
|
||||
* 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,describe,beforeEach,it,jasmine,expect */
|
||||
|
||||
define(
|
||||
[
|
||||
'../../src/actions/LinkAction',
|
||||
'../services/MockLinkService',
|
||||
'../DomainObjectFactory'
|
||||
],
|
||||
function (LinkAction, MockLinkService, domainObjectFactory) {
|
||||
"use strict";
|
||||
|
||||
describe("Link Action", function () {
|
||||
|
||||
var linkAction,
|
||||
locationService,
|
||||
locationServicePromise,
|
||||
linkService,
|
||||
context,
|
||||
selectedObject,
|
||||
selectedObjectContextCapability,
|
||||
currentParent,
|
||||
newParent;
|
||||
|
||||
beforeEach(function () {
|
||||
selectedObjectContextCapability = jasmine.createSpyObj(
|
||||
'selectedObjectContextCapability',
|
||||
[
|
||||
'getParent'
|
||||
]
|
||||
);
|
||||
|
||||
selectedObject = domainObjectFactory({
|
||||
name: 'selectedObject',
|
||||
model: {
|
||||
name: 'selectedObject'
|
||||
},
|
||||
capabilities: {
|
||||
context: selectedObjectContextCapability
|
||||
}
|
||||
});
|
||||
|
||||
currentParent = domainObjectFactory({
|
||||
name: 'currentParent'
|
||||
});
|
||||
|
||||
selectedObjectContextCapability
|
||||
.getParent
|
||||
.andReturn(currentParent);
|
||||
|
||||
newParent = domainObjectFactory({
|
||||
name: 'newParent'
|
||||
});
|
||||
|
||||
locationService = jasmine.createSpyObj(
|
||||
'locationService',
|
||||
[
|
||||
'getLocationFromUser'
|
||||
]
|
||||
);
|
||||
|
||||
locationServicePromise = jasmine.createSpyObj(
|
||||
'locationServicePromise',
|
||||
[
|
||||
'then'
|
||||
]
|
||||
);
|
||||
|
||||
locationService
|
||||
.getLocationFromUser
|
||||
.andReturn(locationServicePromise);
|
||||
|
||||
linkService = new MockLinkService();
|
||||
});
|
||||
|
||||
|
||||
describe("with context from context-action", function () {
|
||||
beforeEach(function () {
|
||||
context = {
|
||||
domainObject: selectedObject
|
||||
};
|
||||
|
||||
linkAction = new LinkAction(
|
||||
locationService,
|
||||
linkService,
|
||||
context
|
||||
);
|
||||
});
|
||||
|
||||
it("initializes happily", function () {
|
||||
expect(linkAction).toBeDefined();
|
||||
});
|
||||
|
||||
describe("when performed it", function () {
|
||||
beforeEach(function () {
|
||||
linkAction.perform();
|
||||
});
|
||||
|
||||
it("prompts for location", function () {
|
||||
expect(locationService.getLocationFromUser)
|
||||
.toHaveBeenCalledWith(
|
||||
"Link selectedObject to a new location",
|
||||
"Link To",
|
||||
jasmine.any(Function),
|
||||
currentParent
|
||||
);
|
||||
});
|
||||
|
||||
it("waits for location from user", function () {
|
||||
expect(locationServicePromise.then)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("links object to selected location", function () {
|
||||
locationServicePromise
|
||||
.then
|
||||
.mostRecentCall
|
||||
.args[0](newParent);
|
||||
|
||||
expect(linkService.perform)
|
||||
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with context from drag-drop", function () {
|
||||
beforeEach(function () {
|
||||
context = {
|
||||
selectedObject: selectedObject,
|
||||
domainObject: newParent
|
||||
};
|
||||
|
||||
linkAction = new LinkAction(
|
||||
locationService,
|
||||
linkService,
|
||||
context
|
||||
);
|
||||
});
|
||||
|
||||
it("initializes happily", function () {
|
||||
expect(linkAction).toBeDefined();
|
||||
});
|
||||
|
||||
|
||||
it("performs link immediately", function () {
|
||||
linkAction.perform();
|
||||
expect(linkService.perform)
|
||||
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
174
platform/entanglement/test/actions/MoveActionSpec.js
Normal file
174
platform/entanglement/test/actions/MoveActionSpec.js
Normal file
@ -0,0 +1,174 @@
|
||||
/*****************************************************************************
|
||||
* 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,describe,beforeEach,it,jasmine,expect */
|
||||
|
||||
define(
|
||||
[
|
||||
'../../src/actions/MoveAction',
|
||||
'../services/MockMoveService',
|
||||
'../DomainObjectFactory'
|
||||
],
|
||||
function (MoveAction, MockMoveService, domainObjectFactory) {
|
||||
"use strict";
|
||||
|
||||
describe("Move Action", function () {
|
||||
|
||||
var moveAction,
|
||||
locationService,
|
||||
locationServicePromise,
|
||||
moveService,
|
||||
context,
|
||||
selectedObject,
|
||||
selectedObjectContextCapability,
|
||||
currentParent,
|
||||
newParent;
|
||||
|
||||
beforeEach(function () {
|
||||
selectedObjectContextCapability = jasmine.createSpyObj(
|
||||
'selectedObjectContextCapability',
|
||||
[
|
||||
'getParent'
|
||||
]
|
||||
);
|
||||
|
||||
selectedObject = domainObjectFactory({
|
||||
name: 'selectedObject',
|
||||
model: {
|
||||
name: 'selectedObject'
|
||||
},
|
||||
capabilities: {
|
||||
context: selectedObjectContextCapability
|
||||
}
|
||||
});
|
||||
|
||||
currentParent = domainObjectFactory({
|
||||
name: 'currentParent'
|
||||
});
|
||||
|
||||
selectedObjectContextCapability
|
||||
.getParent
|
||||
.andReturn(currentParent);
|
||||
|
||||
newParent = domainObjectFactory({
|
||||
name: 'newParent'
|
||||
});
|
||||
|
||||
locationService = jasmine.createSpyObj(
|
||||
'locationService',
|
||||
[
|
||||
'getLocationFromUser'
|
||||
]
|
||||
);
|
||||
|
||||
locationServicePromise = jasmine.createSpyObj(
|
||||
'locationServicePromise',
|
||||
[
|
||||
'then'
|
||||
]
|
||||
);
|
||||
|
||||
locationService
|
||||
.getLocationFromUser
|
||||
.andReturn(locationServicePromise);
|
||||
|
||||
moveService = new MockMoveService();
|
||||
});
|
||||
|
||||
|
||||
describe("with context from context-action", function () {
|
||||
beforeEach(function () {
|
||||
context = {
|
||||
domainObject: selectedObject
|
||||
};
|
||||
|
||||
moveAction = new MoveAction(
|
||||
locationService,
|
||||
moveService,
|
||||
context
|
||||
);
|
||||
});
|
||||
|
||||
it("initializes happily", function () {
|
||||
expect(moveAction).toBeDefined();
|
||||
});
|
||||
|
||||
describe("when performed it", function () {
|
||||
beforeEach(function () {
|
||||
moveAction.perform();
|
||||
});
|
||||
|
||||
it("prompts for location", function () {
|
||||
expect(locationService.getLocationFromUser)
|
||||
.toHaveBeenCalledWith(
|
||||
"Move selectedObject to a new location",
|
||||
"Move To",
|
||||
jasmine.any(Function),
|
||||
currentParent
|
||||
);
|
||||
});
|
||||
|
||||
it("waits for location from user", function () {
|
||||
expect(locationServicePromise.then)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("moves object to selected location", function () {
|
||||
locationServicePromise
|
||||
.then
|
||||
.mostRecentCall
|
||||
.args[0](newParent);
|
||||
|
||||
expect(moveService.perform)
|
||||
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("with context from drag-drop", function () {
|
||||
beforeEach(function () {
|
||||
context = {
|
||||
selectedObject: selectedObject,
|
||||
domainObject: newParent
|
||||
};
|
||||
|
||||
moveAction = new MoveAction(
|
||||
locationService,
|
||||
moveService,
|
||||
context
|
||||
);
|
||||
});
|
||||
|
||||
it("initializes happily", function () {
|
||||
expect(moveAction).toBeDefined();
|
||||
});
|
||||
|
||||
|
||||
it("performs move immediately", function () {
|
||||
moveAction.perform();
|
||||
expect(moveService.perform)
|
||||
.toHaveBeenCalledWith(selectedObject, newParent);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
272
platform/entanglement/test/services/CopyServiceSpec.js
Normal file
272
platform/entanglement/test/services/CopyServiceSpec.js
Normal file
@ -0,0 +1,272 @@
|
||||
/*****************************************************************************
|
||||
* 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,describe,beforeEach,it,jasmine,expect,spyOn */
|
||||
|
||||
define(
|
||||
[
|
||||
'../../src/services/CopyService',
|
||||
'../DomainObjectFactory'
|
||||
],
|
||||
function (CopyService, domainObjectFactory) {
|
||||
"use strict";
|
||||
|
||||
function synchronousPromise(value) {
|
||||
var promise = {
|
||||
then: function (callback) {
|
||||
return synchronousPromise(callback(value));
|
||||
}
|
||||
};
|
||||
spyOn(promise, 'then').andCallThrough();
|
||||
return promise;
|
||||
}
|
||||
|
||||
describe("CopyService", function () {
|
||||
describe("validate", function () {
|
||||
|
||||
var policyService,
|
||||
copyService,
|
||||
object,
|
||||
parentCandidate,
|
||||
validate;
|
||||
|
||||
beforeEach(function () {
|
||||
policyService = jasmine.createSpyObj(
|
||||
'policyService',
|
||||
['allow']
|
||||
);
|
||||
copyService = new CopyService(
|
||||
null,
|
||||
null,
|
||||
policyService
|
||||
);
|
||||
object = domainObjectFactory({
|
||||
name: 'object',
|
||||
capabilities: {
|
||||
type: { type: 'object' }
|
||||
}
|
||||
});
|
||||
parentCandidate = domainObjectFactory({
|
||||
name: 'parentCandidate',
|
||||
capabilities: {
|
||||
type: { type: 'parentCandidate' }
|
||||
}
|
||||
});
|
||||
validate = function () {
|
||||
return copyService.validate(object, parentCandidate);
|
||||
};
|
||||
});
|
||||
|
||||
it("does not allow invalid parentCandidate", function () {
|
||||
parentCandidate = undefined;
|
||||
expect(validate()).toBe(false);
|
||||
parentCandidate = {};
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
it("does not allow copying into source object", function () {
|
||||
object.id = parentCandidate.id = 'abc';
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
describe("defers to policyService", function () {
|
||||
beforeEach(function () {
|
||||
object.id = 'a';
|
||||
parentCandidate.id = 'b';
|
||||
});
|
||||
|
||||
it("calls policy service with correct args", function () {
|
||||
validate();
|
||||
expect(policyService.allow).toHaveBeenCalledWith(
|
||||
"composition",
|
||||
parentCandidate.capabilities.type,
|
||||
object.capabilities.type
|
||||
);
|
||||
});
|
||||
|
||||
it("and returns false", function () {
|
||||
policyService.allow.andReturn(false);
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
it("and returns true", function () {
|
||||
policyService.allow.andReturn(true);
|
||||
expect(validate()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("perform", function () {
|
||||
|
||||
var mockQ,
|
||||
creationService,
|
||||
createObjectPromise,
|
||||
copyService,
|
||||
object,
|
||||
newParent,
|
||||
copyResult,
|
||||
copyFinished;
|
||||
|
||||
describe("on domain object without composition", function () {
|
||||
beforeEach(function () {
|
||||
object = domainObjectFactory({
|
||||
name: 'object',
|
||||
id: 'abc',
|
||||
model: {
|
||||
name: 'some object'
|
||||
}
|
||||
});
|
||||
newParent = domainObjectFactory({
|
||||
name: 'newParent',
|
||||
id: '456',
|
||||
model: {
|
||||
composition: []
|
||||
}
|
||||
});
|
||||
creationService = jasmine.createSpyObj(
|
||||
'creationService',
|
||||
['createObject']
|
||||
);
|
||||
createObjectPromise = synchronousPromise(undefined);
|
||||
creationService.createObject.andReturn(createObjectPromise);
|
||||
copyService = new CopyService(null, creationService);
|
||||
copyResult = copyService.perform(object, newParent);
|
||||
copyFinished = jasmine.createSpy('copyFinished');
|
||||
copyResult.then(copyFinished);
|
||||
});
|
||||
|
||||
it("uses creation service", function () {
|
||||
expect(creationService.createObject)
|
||||
.toHaveBeenCalledWith(jasmine.any(Object), newParent);
|
||||
|
||||
expect(createObjectPromise.then)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("deep clones object model", function () {
|
||||
var newModel = creationService
|
||||
.createObject
|
||||
.mostRecentCall
|
||||
.args[0];
|
||||
|
||||
expect(newModel).toEqual(object.model);
|
||||
expect(newModel).not.toBe(object.model);
|
||||
});
|
||||
|
||||
it("returns a promise", function () {
|
||||
expect(copyResult).toBeDefined();
|
||||
expect(copyFinished).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
describe("on domainObject with composition", function () {
|
||||
var childObject,
|
||||
compositionCapability,
|
||||
compositionPromise;
|
||||
|
||||
beforeEach(function () {
|
||||
mockQ = jasmine.createSpyObj('mockQ', ['when']);
|
||||
mockQ.when.andCallFake(synchronousPromise);
|
||||
childObject = domainObjectFactory({
|
||||
name: 'childObject',
|
||||
id: 'def',
|
||||
model: {
|
||||
name: 'a child object'
|
||||
}
|
||||
});
|
||||
compositionCapability = jasmine.createSpyObj(
|
||||
'compositionCapability',
|
||||
['invoke']
|
||||
);
|
||||
compositionPromise = jasmine.createSpyObj(
|
||||
'compositionPromise',
|
||||
['then']
|
||||
);
|
||||
compositionCapability
|
||||
.invoke
|
||||
.andReturn(compositionPromise);
|
||||
object = domainObjectFactory({
|
||||
name: 'object',
|
||||
id: 'abc',
|
||||
model: {
|
||||
name: 'some object',
|
||||
composition: ['def']
|
||||
},
|
||||
capabilities: {
|
||||
composition: compositionCapability
|
||||
}
|
||||
});
|
||||
newParent = domainObjectFactory({
|
||||
name: 'newParent',
|
||||
id: '456',
|
||||
model: {
|
||||
composition: []
|
||||
}
|
||||
});
|
||||
creationService = jasmine.createSpyObj(
|
||||
'creationService',
|
||||
['createObject']
|
||||
);
|
||||
createObjectPromise = synchronousPromise(undefined);
|
||||
creationService.createObject.andReturn(createObjectPromise);
|
||||
copyService = new CopyService(mockQ, creationService);
|
||||
copyResult = copyService.perform(object, newParent);
|
||||
copyFinished = jasmine.createSpy('copyFinished');
|
||||
copyResult.then(copyFinished);
|
||||
});
|
||||
|
||||
it("uses creation service", function () {
|
||||
expect(creationService.createObject)
|
||||
.toHaveBeenCalledWith(jasmine.any(Object), newParent);
|
||||
|
||||
expect(createObjectPromise.then)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("clears model composition", function () {
|
||||
var newModel = creationService
|
||||
.createObject
|
||||
.mostRecentCall
|
||||
.args[0];
|
||||
|
||||
expect(newModel.composition.length).toBe(0);
|
||||
expect(newModel.name).toBe('some object');
|
||||
});
|
||||
|
||||
it("recursively clones it's children", function () {
|
||||
expect(creationService.createObject.calls.length).toBe(1);
|
||||
expect(compositionCapability.invoke).toHaveBeenCalled();
|
||||
compositionPromise.then.mostRecentCall.args[0]([childObject]);
|
||||
expect(creationService.createObject.calls.length).toBe(2);
|
||||
});
|
||||
|
||||
it("returns a promise", function () {
|
||||
expect(copyResult.then).toBeDefined();
|
||||
expect(copyFinished).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
183
platform/entanglement/test/services/LinkServiceSpec.js
Normal file
183
platform/entanglement/test/services/LinkServiceSpec.js
Normal file
@ -0,0 +1,183 @@
|
||||
/*****************************************************************************
|
||||
* 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,describe,beforeEach,it,jasmine,expect */
|
||||
|
||||
define(
|
||||
[
|
||||
'../../src/services/LinkService',
|
||||
'../DomainObjectFactory'
|
||||
],
|
||||
function (LinkService, domainObjectFactory) {
|
||||
"use strict";
|
||||
|
||||
describe("LinkService", function () {
|
||||
|
||||
var linkService,
|
||||
mockPolicyService;
|
||||
|
||||
beforeEach(function () {
|
||||
mockPolicyService = jasmine.createSpyObj(
|
||||
'policyService',
|
||||
['allow']
|
||||
);
|
||||
linkService = new LinkService(mockPolicyService);
|
||||
});
|
||||
|
||||
describe("validate", function () {
|
||||
|
||||
var object,
|
||||
parentCandidate,
|
||||
validate;
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
object = domainObjectFactory({
|
||||
name: 'object'
|
||||
});
|
||||
parentCandidate = domainObjectFactory({
|
||||
name: 'parentCandidate'
|
||||
});
|
||||
validate = function () {
|
||||
return linkService.validate(object, parentCandidate);
|
||||
};
|
||||
});
|
||||
|
||||
it("does not allow invalid parentCandidate", function () {
|
||||
parentCandidate = undefined;
|
||||
expect(validate()).toBe(false);
|
||||
parentCandidate = {};
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
it("does not allow parent to be object", function () {
|
||||
parentCandidate.id = object.id = 'abc';
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
it("does not allow parent that contains object", function () {
|
||||
object.id = 'abc';
|
||||
parentCandidate.id = 'xyz';
|
||||
parentCandidate.model.composition = ['abc'];
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
describe("defers to policyService", function () {
|
||||
beforeEach(function () {
|
||||
object.id = 'abc';
|
||||
object.capabilities.type = { type: 'object' };
|
||||
parentCandidate.id = 'xyz';
|
||||
parentCandidate.capabilities.type = {
|
||||
type: 'parentCandidate'
|
||||
};
|
||||
parentCandidate.model.composition = [];
|
||||
});
|
||||
|
||||
it("calls policy service with correct args", function () {
|
||||
validate();
|
||||
expect(mockPolicyService.allow).toHaveBeenCalledWith(
|
||||
"composition",
|
||||
parentCandidate.capabilities.type,
|
||||
object.capabilities.type
|
||||
);
|
||||
});
|
||||
|
||||
it("and returns false", function () {
|
||||
mockPolicyService.allow.andReturn(true);
|
||||
expect(validate()).toBe(true);
|
||||
expect(mockPolicyService.allow).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("and returns true", function () {
|
||||
mockPolicyService.allow.andReturn(false);
|
||||
expect(validate()).toBe(false);
|
||||
expect(mockPolicyService.allow).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("perform", function () {
|
||||
|
||||
var object,
|
||||
parentModel,
|
||||
parentObject,
|
||||
mutationPromise,
|
||||
persistenceCapability;
|
||||
|
||||
beforeEach(function () {
|
||||
mutationPromise = jasmine.createSpyObj(
|
||||
'promise',
|
||||
['then']
|
||||
);
|
||||
persistenceCapability = jasmine.createSpyObj(
|
||||
'persistenceCapability',
|
||||
['persist']
|
||||
);
|
||||
parentModel = {
|
||||
composition: []
|
||||
};
|
||||
parentObject = domainObjectFactory({
|
||||
name: 'parentObject',
|
||||
model: parentModel,
|
||||
capabilities: {
|
||||
mutation: {
|
||||
invoke: function (mutator) {
|
||||
mutator(parentModel);
|
||||
return mutationPromise;
|
||||
}
|
||||
},
|
||||
persistence: persistenceCapability
|
||||
}
|
||||
});
|
||||
|
||||
object = domainObjectFactory({
|
||||
name: 'object',
|
||||
id: 'xyz'
|
||||
});
|
||||
|
||||
parentObject.getCapability.andReturn(persistenceCapability);
|
||||
});
|
||||
|
||||
|
||||
it("modifies parent model composition", function () {
|
||||
expect(parentModel.composition.length).toBe(0);
|
||||
linkService.perform(object, parentObject);
|
||||
expect(parentObject.useCapability).toHaveBeenCalledWith(
|
||||
'mutation',
|
||||
jasmine.any(Function)
|
||||
);
|
||||
expect(parentModel.composition).toContain('xyz');
|
||||
});
|
||||
|
||||
it("persists parent", function () {
|
||||
linkService.perform(object, parentObject);
|
||||
expect(mutationPromise.then).toHaveBeenCalled();
|
||||
mutationPromise.then.calls[0].args[0]();
|
||||
expect(parentObject.getCapability)
|
||||
.toHaveBeenCalledWith('persistence');
|
||||
|
||||
expect(persistenceCapability.persist).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
151
platform/entanglement/test/services/LocationServiceSpec.js
Normal file
151
platform/entanglement/test/services/LocationServiceSpec.js
Normal file
@ -0,0 +1,151 @@
|
||||
/*****************************************************************************
|
||||
* 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,describe,beforeEach,it,jasmine,expect */
|
||||
|
||||
define(
|
||||
[
|
||||
'../../src/services/LocationService'
|
||||
],
|
||||
function (LocationService) {
|
||||
"use strict";
|
||||
|
||||
describe("LocationService", function () {
|
||||
var dialogService,
|
||||
locationService,
|
||||
dialogServicePromise,
|
||||
chainedPromise;
|
||||
|
||||
beforeEach(function () {
|
||||
dialogService = jasmine.createSpyObj(
|
||||
'dialogService',
|
||||
['getUserInput']
|
||||
);
|
||||
dialogServicePromise = jasmine.createSpyObj(
|
||||
'dialogServicePromise',
|
||||
['then']
|
||||
);
|
||||
chainedPromise = jasmine.createSpyObj(
|
||||
'chainedPromise',
|
||||
['then']
|
||||
);
|
||||
dialogServicePromise.then.andReturn(chainedPromise);
|
||||
dialogService.getUserInput.andReturn(dialogServicePromise);
|
||||
locationService = new LocationService(dialogService);
|
||||
});
|
||||
|
||||
describe("getLocationFromUser", function () {
|
||||
var title,
|
||||
label,
|
||||
validate,
|
||||
initialLocation,
|
||||
locationResult,
|
||||
formStructure,
|
||||
formState;
|
||||
|
||||
beforeEach(function () {
|
||||
title = "Get a location to do something";
|
||||
label = "a location";
|
||||
validate = function () { return true; };
|
||||
initialLocation = { key: "a key" };
|
||||
locationResult = locationService.getLocationFromUser(
|
||||
title,
|
||||
label,
|
||||
validate,
|
||||
initialLocation
|
||||
);
|
||||
formStructure = dialogService
|
||||
.getUserInput
|
||||
.mostRecentCall
|
||||
.args[0];
|
||||
formState = dialogService
|
||||
.getUserInput
|
||||
.mostRecentCall
|
||||
.args[1];
|
||||
});
|
||||
|
||||
it("calls through to dialogService", function () {
|
||||
expect(dialogService.getUserInput).toHaveBeenCalledWith(
|
||||
jasmine.any(Object),
|
||||
jasmine.any(Object)
|
||||
);
|
||||
expect(formStructure.name).toBe(title);
|
||||
});
|
||||
|
||||
it("returns a promise", function () {
|
||||
expect(locationResult.then).toBeDefined();
|
||||
});
|
||||
|
||||
describe("formStructure", function () {
|
||||
var locationSection,
|
||||
inputRow;
|
||||
|
||||
beforeEach(function () {
|
||||
locationSection = formStructure.sections[0];
|
||||
inputRow = locationSection.rows[0];
|
||||
});
|
||||
|
||||
it("has a location section", function () {
|
||||
expect(locationSection).toBeDefined();
|
||||
expect(locationSection.name).toBe('Location');
|
||||
});
|
||||
|
||||
it("has a input row", function () {
|
||||
expect(inputRow.control).toBe('locator');
|
||||
expect(inputRow.key).toBe('location');
|
||||
expect(inputRow.name).toBe(label);
|
||||
expect(inputRow.validate).toBe(validate);
|
||||
});
|
||||
});
|
||||
|
||||
describe("formState", function () {
|
||||
it("has an initial location", function () {
|
||||
expect(formState.location).toBe(initialLocation);
|
||||
});
|
||||
});
|
||||
|
||||
describe("resolution of dialog service promise", function () {
|
||||
var resolution,
|
||||
resolver,
|
||||
dialogResult,
|
||||
selectedLocation;
|
||||
|
||||
beforeEach(function () {
|
||||
resolver =
|
||||
dialogServicePromise.then.mostRecentCall.args[0];
|
||||
|
||||
selectedLocation = { key: "i'm a location key" };
|
||||
dialogResult = {
|
||||
location: selectedLocation
|
||||
};
|
||||
|
||||
resolution = resolver(dialogResult);
|
||||
});
|
||||
|
||||
it("returns selectedLocation", function () {
|
||||
expect(resolution).toBe(selectedLocation);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
99
platform/entanglement/test/services/MockCopyService.js
Normal file
99
platform/entanglement/test/services/MockCopyService.js
Normal file
@ -0,0 +1,99 @@
|
||||
/*****************************************************************************
|
||||
* 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,jasmine */
|
||||
|
||||
define(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* MockCopyService provides the same interface as the copyService,
|
||||
* returning promises where it would normally do so. At it's core,
|
||||
* it is a jasmine spy object, but it also tracks the promises it
|
||||
* returns and provides shortcut methods for resolving those promises
|
||||
* synchronously.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* ```javascript
|
||||
* var copyService = new MockCopyService();
|
||||
*
|
||||
* // validate is a standard jasmine spy.
|
||||
* copyService.validate.andReturn(true);
|
||||
* var isValid = copyService.validate(object, parentCandidate);
|
||||
* expect(isValid).toBe(true);
|
||||
*
|
||||
* // perform returns promises and tracks them.
|
||||
* var whenCopied = jasmine.createSpy('whenCopied');
|
||||
* copyService.perform(object, parentObject).then(whenCopied);
|
||||
* expect(whenCopied).not.toHaveBeenCalled();
|
||||
* copyService.perform.mostRecentCall.resolve('someArg');
|
||||
* expect(whenCopied).toHaveBeenCalledWith('someArg');
|
||||
* ```
|
||||
*/
|
||||
function MockCopyService() {
|
||||
// track most recent call of a function,
|
||||
// perform automatically returns
|
||||
var mockCopyService = jasmine.createSpyObj(
|
||||
'MockCopyService',
|
||||
[
|
||||
'validate',
|
||||
'perform'
|
||||
]
|
||||
);
|
||||
|
||||
mockCopyService.perform.andCallFake(function () {
|
||||
var performPromise,
|
||||
callExtensions,
|
||||
spy;
|
||||
|
||||
performPromise = jasmine.createSpyObj(
|
||||
'performPromise',
|
||||
['then']
|
||||
);
|
||||
|
||||
callExtensions = {
|
||||
promise: performPromise,
|
||||
resolve: function (resolveWith) {
|
||||
performPromise.then.calls.forEach(function (call) {
|
||||
call.args[0](resolveWith);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
spy = this.perform;
|
||||
|
||||
Object.keys(callExtensions).forEach(function (key) {
|
||||
spy.mostRecentCall[key] = callExtensions[key];
|
||||
spy.calls[spy.calls.length - 1][key] = callExtensions[key];
|
||||
});
|
||||
|
||||
return performPromise;
|
||||
});
|
||||
|
||||
return mockCopyService;
|
||||
}
|
||||
|
||||
return MockCopyService;
|
||||
}
|
||||
);
|
99
platform/entanglement/test/services/MockLinkService.js
Normal file
99
platform/entanglement/test/services/MockLinkService.js
Normal file
@ -0,0 +1,99 @@
|
||||
/*****************************************************************************
|
||||
* 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,jasmine */
|
||||
|
||||
define(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* MockLinkService provides the same interface as the linkService,
|
||||
* returning promises where it would normally do so. At it's core,
|
||||
* it is a jasmine spy object, but it also tracks the promises it
|
||||
* returns and provides shortcut methods for resolving those promises
|
||||
* synchronously.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* ```javascript
|
||||
* var linkService = new MockLinkService();
|
||||
*
|
||||
* // validate is a standard jasmine spy.
|
||||
* linkService.validate.andReturn(true);
|
||||
* var isValid = linkService.validate(object, parentObject);
|
||||
* expect(isValid).toBe(true);
|
||||
*
|
||||
* // perform returns promises and tracks them.
|
||||
* var whenLinked = jasmine.createSpy('whenLinked');
|
||||
* linkService.perform(object, parentObject).then(whenLinked);
|
||||
* expect(whenLinked).not.toHaveBeenCalled();
|
||||
* linkService.perform.mostRecentCall.resolve('someArg');
|
||||
* expect(whenLinked).toHaveBeenCalledWith('someArg');
|
||||
* ```
|
||||
*/
|
||||
function MockLinkService() {
|
||||
// track most recent call of a function,
|
||||
// perform automatically returns
|
||||
var mockLinkService = jasmine.createSpyObj(
|
||||
'MockLinkService',
|
||||
[
|
||||
'validate',
|
||||
'perform'
|
||||
]
|
||||
);
|
||||
|
||||
mockLinkService.perform.andCallFake(function () {
|
||||
var performPromise,
|
||||
callExtensions,
|
||||
spy;
|
||||
|
||||
performPromise = jasmine.createSpyObj(
|
||||
'performPromise',
|
||||
['then']
|
||||
);
|
||||
|
||||
callExtensions = {
|
||||
promise: performPromise,
|
||||
resolve: function (resolveWith) {
|
||||
performPromise.then.calls.forEach(function (call) {
|
||||
call.args[0](resolveWith);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
spy = this.perform;
|
||||
|
||||
Object.keys(callExtensions).forEach(function (key) {
|
||||
spy.mostRecentCall[key] = callExtensions[key];
|
||||
spy.calls[spy.calls.length - 1][key] = callExtensions[key];
|
||||
});
|
||||
|
||||
return performPromise;
|
||||
});
|
||||
|
||||
return mockLinkService;
|
||||
}
|
||||
|
||||
return MockLinkService;
|
||||
}
|
||||
);
|
99
platform/entanglement/test/services/MockMoveService.js
Normal file
99
platform/entanglement/test/services/MockMoveService.js
Normal file
@ -0,0 +1,99 @@
|
||||
/*****************************************************************************
|
||||
* 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,jasmine */
|
||||
|
||||
define(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* MockMoveService provides the same interface as the moveService,
|
||||
* returning promises where it would normally do so. At it's core,
|
||||
* it is a jasmine spy object, but it also tracks the promises it
|
||||
* returns and provides shortcut methods for resolving those promises
|
||||
* synchronously.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* ```javascript
|
||||
* var moveService = new MockMoveService();
|
||||
*
|
||||
* // validate is a standard jasmine spy.
|
||||
* moveService.validate.andReturn(true);
|
||||
* var isValid = moveService.validate(object, parentCandidate);
|
||||
* expect(isValid).toBe(true);
|
||||
*
|
||||
* // perform returns promises and tracks them.
|
||||
* var whenCopied = jasmine.createSpy('whenCopied');
|
||||
* moveService.perform(object, parentObject).then(whenCopied);
|
||||
* expect(whenCopied).not.toHaveBeenCalled();
|
||||
* moveService.perform.mostRecentCall.resolve('someArg');
|
||||
* expect(whenCopied).toHaveBeenCalledWith('someArg');
|
||||
* ```
|
||||
*/
|
||||
function MockMoveService() {
|
||||
// track most recent call of a function,
|
||||
// perform automatically returns
|
||||
var mockMoveService = jasmine.createSpyObj(
|
||||
'MockMoveService',
|
||||
[
|
||||
'validate',
|
||||
'perform'
|
||||
]
|
||||
);
|
||||
|
||||
mockMoveService.perform.andCallFake(function () {
|
||||
var performPromise,
|
||||
callExtensions,
|
||||
spy;
|
||||
|
||||
performPromise = jasmine.createSpyObj(
|
||||
'performPromise',
|
||||
['then']
|
||||
);
|
||||
|
||||
callExtensions = {
|
||||
promise: performPromise,
|
||||
resolve: function (resolveWith) {
|
||||
performPromise.then.calls.forEach(function (call) {
|
||||
call.args[0](resolveWith);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
spy = this.perform;
|
||||
|
||||
Object.keys(callExtensions).forEach(function (key) {
|
||||
spy.mostRecentCall[key] = callExtensions[key];
|
||||
spy.calls[spy.calls.length - 1][key] = callExtensions[key];
|
||||
});
|
||||
|
||||
return performPromise;
|
||||
});
|
||||
|
||||
return mockMoveService;
|
||||
}
|
||||
|
||||
return MockMoveService;
|
||||
}
|
||||
);
|
189
platform/entanglement/test/services/MoveServiceSpec.js
Normal file
189
platform/entanglement/test/services/MoveServiceSpec.js
Normal file
@ -0,0 +1,189 @@
|
||||
/*****************************************************************************
|
||||
* 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,describe,beforeEach,it,jasmine,expect */
|
||||
define(
|
||||
[
|
||||
'../../src/services/MoveService',
|
||||
'../services/MockLinkService',
|
||||
'../DomainObjectFactory'
|
||||
],
|
||||
function (MoveService, MockLinkService, domainObjectFactory) {
|
||||
"use strict";
|
||||
|
||||
describe("MoveService", function () {
|
||||
|
||||
var moveService,
|
||||
policyService,
|
||||
linkService;
|
||||
|
||||
beforeEach(function () {
|
||||
policyService = jasmine.createSpyObj(
|
||||
'policyService',
|
||||
['allow']
|
||||
);
|
||||
linkService = new MockLinkService();
|
||||
moveService = new MoveService(policyService, linkService);
|
||||
});
|
||||
|
||||
describe("validate", function () {
|
||||
var object,
|
||||
objectContextCapability,
|
||||
currentParent,
|
||||
parentCandidate,
|
||||
validate;
|
||||
|
||||
beforeEach(function () {
|
||||
|
||||
objectContextCapability = jasmine.createSpyObj(
|
||||
'objectContextCapability',
|
||||
[
|
||||
'getParent'
|
||||
]
|
||||
);
|
||||
|
||||
object = domainObjectFactory({
|
||||
name: 'object',
|
||||
id: 'a',
|
||||
capabilities: {
|
||||
context: objectContextCapability,
|
||||
type: { type: 'object' }
|
||||
}
|
||||
});
|
||||
|
||||
currentParent = domainObjectFactory({
|
||||
name: 'currentParent',
|
||||
id: 'b'
|
||||
});
|
||||
|
||||
objectContextCapability.getParent.andReturn(currentParent);
|
||||
|
||||
parentCandidate = domainObjectFactory({
|
||||
name: 'parentCandidate',
|
||||
model: { composition: [] },
|
||||
id: 'c',
|
||||
capabilities: {
|
||||
type: { type: 'parentCandidate' }
|
||||
}
|
||||
});
|
||||
|
||||
validate = function () {
|
||||
return moveService.validate(object, parentCandidate);
|
||||
};
|
||||
});
|
||||
|
||||
it("does not allow an invalid parent", function () {
|
||||
parentCandidate = undefined;
|
||||
expect(validate()).toBe(false);
|
||||
parentCandidate = {};
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
it("does not allow moving to current parent", function () {
|
||||
parentCandidate.id = currentParent.id = 'xyz';
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
it("does not allow moving to self", function () {
|
||||
object.id = parentCandidate.id = 'xyz';
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
it("does not allow moving to the same location", function () {
|
||||
object.id = 'abc';
|
||||
parentCandidate.model.composition = ['abc'];
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
describe("defers to policyService", function () {
|
||||
|
||||
it("calls policy service with correct args", function () {
|
||||
validate();
|
||||
expect(policyService.allow).toHaveBeenCalledWith(
|
||||
"composition",
|
||||
parentCandidate.capabilities.type,
|
||||
object.capabilities.type
|
||||
);
|
||||
});
|
||||
|
||||
it("and returns false", function () {
|
||||
policyService.allow.andReturn(false);
|
||||
expect(validate()).toBe(false);
|
||||
});
|
||||
|
||||
it("and returns true", function () {
|
||||
policyService.allow.andReturn(true);
|
||||
expect(validate()).toBe(true);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe("perform", function () {
|
||||
|
||||
var object,
|
||||
parentObject,
|
||||
actionCapability;
|
||||
|
||||
beforeEach(function () {
|
||||
actionCapability = jasmine.createSpyObj(
|
||||
'actionCapability',
|
||||
['perform']
|
||||
);
|
||||
|
||||
object = domainObjectFactory({
|
||||
name: 'object',
|
||||
capabilities: {
|
||||
action: actionCapability
|
||||
}
|
||||
});
|
||||
|
||||
parentObject = domainObjectFactory({
|
||||
name: 'parentObject'
|
||||
});
|
||||
|
||||
moveService.perform(object, parentObject);
|
||||
});
|
||||
|
||||
it("links object to parentObject", function () {
|
||||
expect(linkService.perform).toHaveBeenCalledWith(
|
||||
object,
|
||||
parentObject
|
||||
);
|
||||
});
|
||||
|
||||
it("waits for result of link", function () {
|
||||
expect(linkService.perform.mostRecentCall.promise.then)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("removes object when link is completed", function () {
|
||||
linkService.perform.mostRecentCall.resolve();
|
||||
expect(object.getCapability)
|
||||
.toHaveBeenCalledWith('action');
|
||||
expect(actionCapability.perform)
|
||||
.toHaveBeenCalledWith('remove');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
9
platform/entanglement/test/suite.json
Normal file
9
platform/entanglement/test/suite.json
Normal file
@ -0,0 +1,9 @@
|
||||
[
|
||||
"actions/CopyAction",
|
||||
"actions/LinkAction",
|
||||
"actions/MoveAction",
|
||||
"services/CopyService",
|
||||
"services/LinkService",
|
||||
"services/MoveService",
|
||||
"services/LocationService"
|
||||
]
|
1
platform/execution/README.md
Normal file
1
platform/execution/README.md
Normal file
@ -0,0 +1 @@
|
||||
Contains services which manage execution and flow control (e.g. for concurrency.)
|
11
platform/execution/bundle.json
Normal file
11
platform/execution/bundle.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"extensions": {
|
||||
"services": [
|
||||
{
|
||||
"key": "workerService",
|
||||
"implementation": "WorkerService.js",
|
||||
"depends": [ "$window", "workers[]" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
68
platform/execution/src/WorkerService.js
Normal file
68
platform/execution/src/WorkerService.js
Normal file
@ -0,0 +1,68 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Handles the execution of WebWorkers.
|
||||
* @constructor
|
||||
*/
|
||||
function WorkerService($window, workers) {
|
||||
var workerUrls = {},
|
||||
Worker = $window.Worker;
|
||||
|
||||
function addWorker(worker) {
|
||||
var key = worker.key;
|
||||
if (!workerUrls[key]) {
|
||||
workerUrls[key] = [
|
||||
worker.bundle.path,
|
||||
worker.bundle.sources,
|
||||
worker.scriptUrl
|
||||
].join("/");
|
||||
}
|
||||
}
|
||||
|
||||
(workers || []).forEach(addWorker);
|
||||
|
||||
return {
|
||||
/**
|
||||
* Start running a new web worker. This will run a worker
|
||||
* that has been registered under the `workers` category
|
||||
* of extension.
|
||||
*
|
||||
* @param {string} key symbolic identifier for the worker
|
||||
* @returns {Worker} the running Worker
|
||||
*/
|
||||
run: function (key) {
|
||||
var scriptUrl = workerUrls[key];
|
||||
return scriptUrl && Worker && new Worker(scriptUrl);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return WorkerService;
|
||||
}
|
||||
);
|
77
platform/execution/test/WorkerServiceSpec.js
Normal file
77
platform/execution/test/WorkerServiceSpec.js
Normal file
@ -0,0 +1,77 @@
|
||||
/*****************************************************************************
|
||||
* 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,describe,it,expect,beforeEach,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/WorkerService"],
|
||||
function (WorkerService) {
|
||||
"use strict";
|
||||
|
||||
describe("The worker service", function () {
|
||||
var mockWindow,
|
||||
testWorkers,
|
||||
mockWorker,
|
||||
service;
|
||||
|
||||
beforeEach(function () {
|
||||
mockWindow = jasmine.createSpyObj('$window', ['Worker']);
|
||||
testWorkers = [
|
||||
{
|
||||
key: 'abc',
|
||||
scriptUrl: 'c.js',
|
||||
bundle: { path: 'a', sources: 'b' }
|
||||
},
|
||||
{
|
||||
key: 'xyz',
|
||||
scriptUrl: 'z.js',
|
||||
bundle: { path: 'x', sources: 'y' }
|
||||
},
|
||||
{
|
||||
key: 'xyz',
|
||||
scriptUrl: 'bad.js',
|
||||
bundle: { path: 'bad', sources: 'bad' }
|
||||
}
|
||||
];
|
||||
mockWorker = {};
|
||||
|
||||
mockWindow.Worker.andReturn(mockWorker);
|
||||
|
||||
service = new WorkerService(mockWindow, testWorkers);
|
||||
});
|
||||
|
||||
it("instantiates workers at registered paths", function () {
|
||||
expect(service.run('abc')).toBe(mockWorker);
|
||||
expect(mockWindow.Worker).toHaveBeenCalledWith('a/b/c.js');
|
||||
});
|
||||
|
||||
it("prefers the first worker when multiple keys are found", function () {
|
||||
expect(service.run('xyz')).toBe(mockWorker);
|
||||
expect(mockWindow.Worker).toHaveBeenCalledWith('x/y/z.js');
|
||||
});
|
||||
|
||||
it("returns undefined for unknown workers", function () {
|
||||
expect(service.run('def')).toBeUndefined();
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user