mirror of
https://github.com/nasa/openmct.git
synced 2024-12-24 15:26:39 +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 source libraries
|
||||||
closed-lib
|
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/edit",
|
||||||
"platform/commonUI/dialog",
|
"platform/commonUI/dialog",
|
||||||
"platform/commonUI/general",
|
"platform/commonUI/general",
|
||||||
|
"platform/commonUI/inspect",
|
||||||
"platform/containment",
|
"platform/containment",
|
||||||
|
"platform/execution",
|
||||||
"platform/telemetry",
|
"platform/telemetry",
|
||||||
"platform/features/layout",
|
"platform/features/layout",
|
||||||
"platform/features/pages",
|
"platform/features/pages",
|
||||||
@ -15,8 +17,8 @@
|
|||||||
"platform/features/scrolling",
|
"platform/features/scrolling",
|
||||||
"platform/forms",
|
"platform/forms",
|
||||||
"platform/persistence/queue",
|
"platform/persistence/queue",
|
||||||
"platform/persistence/elastic",
|
|
||||||
"platform/policy",
|
"platform/policy",
|
||||||
|
|
||||||
|
"example/persistence",
|
||||||
"example/generator"
|
"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": {
|
"extensions": {
|
||||||
"routes": [
|
"routes": [
|
||||||
{
|
{
|
||||||
"when": "/browse",
|
"when": "/browse/:ids*",
|
||||||
"templateUrl": "templates/browse.html"
|
"templateUrl": "templates/browse.html",
|
||||||
|
"reloadOnSearch": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"when": "",
|
"when": "",
|
||||||
"templateUrl": "templates/browse.html"
|
"templateUrl": "templates/browse.html",
|
||||||
|
"reloadOnSearch": false
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"controllers": [
|
"controllers": [
|
||||||
{
|
{
|
||||||
"key": "BrowseController",
|
"key": "BrowseController",
|
||||||
"implementation": "BrowseController.js",
|
"implementation": "BrowseController.js",
|
||||||
"depends": [ "$scope", "objectService", "navigationService" ]
|
"depends": [ "$scope", "$route", "$location", "objectService", "navigationService" ]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "BrowseObjectController",
|
||||||
|
"implementation": "BrowseObjectController.js",
|
||||||
|
"depends": [ "$scope", "$location", "$route" ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "CreateMenuController",
|
"key": "CreateMenuController",
|
||||||
@ -57,7 +64,8 @@
|
|||||||
{
|
{
|
||||||
"key": "grid-item",
|
"key": "grid-item",
|
||||||
"templateUrl": "templates/items/grid-item.html",
|
"templateUrl": "templates/items/grid-item.html",
|
||||||
"uses": [ "type", "action" ]
|
"uses": [ "type", "action" ],
|
||||||
|
"gestures": [ "info", "menu" ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "object-header",
|
"key": "object-header",
|
||||||
|
@ -19,16 +19,14 @@
|
|||||||
this source code distribution or the Licensing information page available
|
this source code distribution or the Licensing information page available
|
||||||
at runtime from the About dialog for additional information.
|
at runtime from the About dialog for additional information.
|
||||||
-->
|
-->
|
||||||
<span>
|
<span ng-controller="BrowseObjectController">
|
||||||
<div class="object-browse-bar bar abs">
|
<div class="object-browse-bar bar abs">
|
||||||
|
|
||||||
<div class="items-select left abs">
|
<div class="items-select left abs">
|
||||||
<mct-representation key="'object-header'" mct-object="domainObject">
|
<mct-representation key="'object-header'" mct-object="domainObject">
|
||||||
</mct-representation>
|
</mct-representation>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="view-controls sort-controls btn-bar right abs">
|
<div class="btn-bar right abs">
|
||||||
|
|
||||||
<mct-representation key="'action-group'"
|
<mct-representation key="'action-group'"
|
||||||
mct-object="domainObject"
|
mct-object="domainObject"
|
||||||
parameters="{ category: 'view-control' }">
|
parameters="{ category: 'view-control' }">
|
||||||
@ -39,7 +37,6 @@
|
|||||||
ng-model="representation">
|
ng-model="representation">
|
||||||
</mct-representation>
|
</mct-representation>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class='object-holder abs vscroll'>
|
<div class='object-holder abs vscroll'>
|
||||||
|
@ -20,9 +20,11 @@
|
|||||||
at runtime from the About dialog for additional information.
|
at runtime from the About dialog for additional information.
|
||||||
-->
|
-->
|
||||||
<div class='object-header'>
|
<div class='object-header'>
|
||||||
|
<span class="label s-label">
|
||||||
<span class='type-icon icon ui-symbol'>{{type.getGlyph()}}</span>
|
<span class='type-icon icon ui-symbol'>{{type.getGlyph()}}</span>
|
||||||
<span ng-if="parameters.mode" class='action'>{{parameters.mode}}</span>
|
<span ng-if="parameters.mode" class='action'>{{parameters.mode}}</span>
|
||||||
<span class='type'>{{type.getName()}}</span>
|
<span class='type-name'>{{type.getName()}}</span>
|
||||||
<span class='title'>{{model.name}}</span>
|
<span class='title-label'>{{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>
|
<!--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>
|
</div>
|
@ -21,7 +21,7 @@
|
|||||||
-->
|
-->
|
||||||
<div class="menu-element wrapper" ng-controller="ClickAwayController as createController">
|
<div class="menu-element wrapper" ng-controller="ClickAwayController as createController">
|
||||||
<div class="btn btn-menu create-btn major" ng-click="createController.toggle()">
|
<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>
|
||||||
<div class="menu dropdown super-menu" ng-show="createController.isActive()">
|
<div class="menu dropdown super-menu" ng-show="createController.isActive()">
|
||||||
<mct-representation mct-object="domainObject" key="'create-menu'">
|
<mct-representation mct-object="domainObject" key="'create-menu'">
|
||||||
|
@ -29,7 +29,8 @@ define(
|
|||||||
function () {
|
function () {
|
||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
var ROOT_OBJECT = "ROOT";
|
var ROOT_ID = "ROOT",
|
||||||
|
DEFAULT_PATH = "mine";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The BrowseController is used to populate the initial scope in Browse
|
* The BrowseController is used to populate the initial scope in Browse
|
||||||
@ -40,35 +41,98 @@ define(
|
|||||||
*
|
*
|
||||||
* @constructor
|
* @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
|
// Callback for updating the in-scope reference to the object
|
||||||
// that is currently navigated-to.
|
// that is currently navigated-to.
|
||||||
function setNavigation(domainObject) {
|
function setNavigation(domainObject) {
|
||||||
$scope.navigatedObject = domainObject;
|
$scope.navigatedObject = domainObject;
|
||||||
$scope.treeModel.selectedObject = domainObject;
|
$scope.treeModel.selectedObject = domainObject;
|
||||||
navigationService.setNavigation(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.
|
// Load the root object, put it in the scope.
|
||||||
// Also, load its immediate children, and (possibly)
|
// Also, load its immediate children, and (possibly)
|
||||||
// navigate to one of them, so that navigation state has
|
// navigate to one of them, so that navigation state has
|
||||||
// a useful initial value.
|
// a useful initial value.
|
||||||
objectService.getObjects([ROOT_OBJECT]).then(function (objects) {
|
objectService.getObjects([path[0]]).then(function (objects) {
|
||||||
var composition = objects[ROOT_OBJECT].useCapability("composition");
|
$scope.domainObject = objects[path[0]];
|
||||||
$scope.domainObject = objects[ROOT_OBJECT];
|
doNavigate($scope.domainObject, 1);
|
||||||
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();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Provide a model for the tree to modify
|
// 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();
|
properties = type.getProperties();
|
||||||
|
|
||||||
function validateLocation(locatingObject) {
|
function validateLocation(locatingObject) {
|
||||||
var locatingType = locatingObject.getCapability('type');
|
var locatingType = locatingObject &&
|
||||||
return policyService.allow(
|
locatingObject.getCapability('type');
|
||||||
|
return locatingType && policyService.allow(
|
||||||
"composition",
|
"composition",
|
||||||
locatingType,
|
locatingType,
|
||||||
type
|
type
|
||||||
|
@ -77,7 +77,19 @@ define(
|
|||||||
return undefined;
|
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 () {
|
describe("The browse controller", function () {
|
||||||
var mockScope,
|
var mockScope,
|
||||||
|
mockRoute,
|
||||||
|
mockLocation,
|
||||||
mockObjectService,
|
mockObjectService,
|
||||||
mockNavigationService,
|
mockNavigationService,
|
||||||
mockRootObject,
|
mockRootObject,
|
||||||
mockDomainObject,
|
mockDomainObject,
|
||||||
|
mockNextObject,
|
||||||
controller;
|
controller;
|
||||||
|
|
||||||
function mockPromise(value) {
|
function mockPromise(value) {
|
||||||
@ -50,6 +53,11 @@ define(
|
|||||||
"$scope",
|
"$scope",
|
||||||
[ "$on", "$watch" ]
|
[ "$on", "$watch" ]
|
||||||
);
|
);
|
||||||
|
mockRoute = { current: { params: {} } };
|
||||||
|
mockLocation = jasmine.createSpyObj(
|
||||||
|
"$location",
|
||||||
|
[ "path" ]
|
||||||
|
);
|
||||||
mockObjectService = jasmine.createSpyObj(
|
mockObjectService = jasmine.createSpyObj(
|
||||||
"objectService",
|
"objectService",
|
||||||
[ "getObjects" ]
|
[ "getObjects" ]
|
||||||
@ -71,25 +79,38 @@ define(
|
|||||||
"domainObject",
|
"domainObject",
|
||||||
[ "getId", "getCapability", "getModel", "useCapability" ]
|
[ "getId", "getCapability", "getModel", "useCapability" ]
|
||||||
);
|
);
|
||||||
|
mockNextObject = jasmine.createSpyObj(
|
||||||
|
"nextObject",
|
||||||
|
[ "getId", "getCapability", "getModel", "useCapability" ]
|
||||||
|
);
|
||||||
|
|
||||||
mockObjectService.getObjects.andReturn(mockPromise({
|
mockObjectService.getObjects.andReturn(mockPromise({
|
||||||
ROOT: mockRootObject
|
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(
|
controller = new BrowseController(
|
||||||
mockScope,
|
mockScope,
|
||||||
|
mockRoute,
|
||||||
|
mockLocation,
|
||||||
mockObjectService,
|
mockObjectService,
|
||||||
mockNavigationService
|
mockNavigationService
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
it("uses composition to set the navigated object, if there is none", function () {
|
it("uses composition to set the navigated object, if there is none", function () {
|
||||||
mockRootObject.useCapability.andReturn(mockPromise([
|
|
||||||
mockDomainObject
|
|
||||||
]));
|
|
||||||
controller = new BrowseController(
|
controller = new BrowseController(
|
||||||
mockScope,
|
mockScope,
|
||||||
|
mockRoute,
|
||||||
|
mockLocation,
|
||||||
mockObjectService,
|
mockObjectService,
|
||||||
mockNavigationService
|
mockNavigationService
|
||||||
);
|
);
|
||||||
@ -98,12 +119,11 @@ define(
|
|||||||
});
|
});
|
||||||
|
|
||||||
it("does not try to override navigation", function () {
|
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);
|
mockNavigationService.getNavigation.andReturn(mockDomainObject);
|
||||||
controller = new BrowseController(
|
controller = new BrowseController(
|
||||||
mockScope,
|
mockScope,
|
||||||
|
mockRoute,
|
||||||
|
mockLocation,
|
||||||
mockObjectService,
|
mockObjectService,
|
||||||
mockNavigationService
|
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,
|
mockQ,
|
||||||
mockLog,
|
mockLog,
|
||||||
mockParentObject,
|
mockParentObject,
|
||||||
|
mockNewObject,
|
||||||
mockMutationCapability,
|
mockMutationCapability,
|
||||||
mockPersistenceCapability,
|
mockPersistenceCapability,
|
||||||
|
mockCompositionCapability,
|
||||||
mockCapabilities,
|
mockCapabilities,
|
||||||
creationService;
|
creationService;
|
||||||
|
|
||||||
@ -69,6 +71,10 @@ define(
|
|||||||
"parentObject",
|
"parentObject",
|
||||||
[ "getId", "getCapability", "useCapability" ]
|
[ "getId", "getCapability", "useCapability" ]
|
||||||
);
|
);
|
||||||
|
mockNewObject = jasmine.createSpyObj(
|
||||||
|
"newObject",
|
||||||
|
[ "getId" ]
|
||||||
|
);
|
||||||
mockMutationCapability = jasmine.createSpyObj(
|
mockMutationCapability = jasmine.createSpyObj(
|
||||||
"mutation",
|
"mutation",
|
||||||
[ "invoke" ]
|
[ "invoke" ]
|
||||||
@ -77,9 +83,14 @@ define(
|
|||||||
"persistence",
|
"persistence",
|
||||||
[ "persist", "getSpace" ]
|
[ "persist", "getSpace" ]
|
||||||
);
|
);
|
||||||
|
mockCompositionCapability = jasmine.createSpyObj(
|
||||||
|
"composition",
|
||||||
|
["invoke"]
|
||||||
|
);
|
||||||
mockCapabilities = {
|
mockCapabilities = {
|
||||||
mutation: mockMutationCapability,
|
mutation: mockMutationCapability,
|
||||||
persistence: mockPersistenceCapability
|
persistence: mockPersistenceCapability,
|
||||||
|
composition: mockCompositionCapability
|
||||||
};
|
};
|
||||||
|
|
||||||
mockPersistenceService.createObject.andReturn(
|
mockPersistenceService.createObject.andReturn(
|
||||||
@ -93,8 +104,15 @@ define(
|
|||||||
return mockCapabilities[key].invoke(value);
|
return mockCapabilities[key].invoke(value);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
mockPersistenceCapability.persist.andReturn(
|
||||||
|
mockPromise(true)
|
||||||
|
);
|
||||||
|
|
||||||
mockMutationCapability.invoke.andReturn(mockPromise(true));
|
mockMutationCapability.invoke.andReturn(mockPromise(true));
|
||||||
mockPersistenceCapability.getSpace.andReturn("testSpace");
|
mockPersistenceCapability.getSpace.andReturn("testSpace");
|
||||||
|
mockCompositionCapability.invoke.andReturn(
|
||||||
|
mockPromise([mockNewObject])
|
||||||
|
);
|
||||||
|
|
||||||
creationService = new CreationService(
|
creationService = new CreationService(
|
||||||
mockPersistenceService,
|
mockPersistenceService,
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
[
|
[
|
||||||
"BrowseController",
|
"BrowseController",
|
||||||
|
"BrowseObjectController",
|
||||||
"creation/CreateAction",
|
"creation/CreateAction",
|
||||||
"creation/CreateActionProvider",
|
"creation/CreateActionProvider",
|
||||||
"creation/CreateMenuController",
|
"creation/CreateMenuController",
|
||||||
|
@ -25,7 +25,7 @@
|
|||||||
<a href=""
|
<a href=""
|
||||||
ng-click="ngModel.cancel()"
|
ng-click="ngModel.cancel()"
|
||||||
ng-if="ngModel.cancel"
|
ng-if="ngModel.cancel"
|
||||||
class="btn normal outline ui-symbol close">
|
class="btn normal ui-symbol close">
|
||||||
x
|
x
|
||||||
</a>
|
</a>
|
||||||
<div class="abs contents" ng-transclude>
|
<div class="abs contents" ng-transclude>
|
||||||
|
@ -33,8 +33,6 @@
|
|||||||
<mct-representation key="'edit-action-buttons'"
|
<mct-representation key="'edit-action-buttons'"
|
||||||
mct-object="domainObject"
|
mct-object="domainObject"
|
||||||
class='conclude-editing'>
|
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>
|
</mct-representation>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
@ -181,7 +181,7 @@
|
|||||||
"key": "label",
|
"key": "label",
|
||||||
"templateUrl": "templates/label.html",
|
"templateUrl": "templates/label.html",
|
||||||
"uses": [ "type" ],
|
"uses": [ "type" ],
|
||||||
"gestures": [ "drag", "menu" ]
|
"gestures": [ "drag", "menu", "info" ]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "node",
|
"key": "node",
|
||||||
|
@ -61,6 +61,15 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* 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
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
@ -186,9 +195,9 @@
|
|||||||
color: #666666; }
|
color: #666666; }
|
||||||
/* line 116, ../sass/forms/_elems.scss */
|
/* line 116, ../sass/forms/_elems.scss */
|
||||||
.form .form-row .selector-list {
|
.form .form-row .selector-list {
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 2px;
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 2px;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -225,9 +234,9 @@ label.form-control.checkbox input {
|
|||||||
vertical-align: top; }
|
vertical-align: top; }
|
||||||
/* line 159, ../sass/forms/_elems.scss */
|
/* line 159, ../sass/forms/_elems.scss */
|
||||||
.l-result div.s-hint {
|
.l-result div.s-hint {
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 2px;
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 2px;
|
||||||
background: rgba(255, 153, 0, 0.8);
|
background: rgba(255, 153, 0, 0.8);
|
||||||
display: block;
|
display: block;
|
||||||
color: #ffd699;
|
color: #ffd699;
|
||||||
@ -258,9 +267,9 @@ label.form-control.checkbox input {
|
|||||||
.edit-main textarea {
|
.edit-main textarea {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 2px;
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 2px;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
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.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/* line 22, ../sass/forms/_text-input.scss */
|
/* line 22, ../sass/forms/_text-input.scss */
|
||||||
input[type="text"],
|
input[type="text"] {
|
||||||
input[type="date"] {
|
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 2px;
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 2px;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -322,32 +330,10 @@ input[type="date"] {
|
|||||||
outline: none;
|
outline: none;
|
||||||
padding: 0 3px; }
|
padding: 0 3px; }
|
||||||
/* line 33, ../sass/forms/_mixins.scss */
|
/* line 33, ../sass/forms/_mixins.scss */
|
||||||
input[type="text"].error,
|
input[type="text"].error {
|
||||||
input[type="date"].error {
|
|
||||||
background: rgba(255, 0, 0, 0.5); }
|
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 */
|
/* line 29, ../sass/forms/_text-input.scss */
|
||||||
input[type="text"]:-moz-placeholder,
|
input[type="text"].numeric {
|
||||||
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 {
|
|
||||||
text-align: right; }
|
text-align: right; }
|
||||||
|
|
||||||
/*****************************************************************************
|
/*****************************************************************************
|
||||||
@ -373,23 +359,23 @@ input[type="date"] {
|
|||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
/* line 22, ../sass/forms/_selects.scss */
|
/* line 22, ../sass/forms/_selects.scss */
|
||||||
.form-control.select {
|
.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-size: 100%;
|
||||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4d4d4d), color-stop(100%, #404040));
|
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #525252), color-stop(100%, #454545));
|
||||||
background-image: -moz-linear-gradient(#4d4d4d, #404040);
|
background-image: -moz-linear-gradient(#525252, #454545);
|
||||||
background-image: -webkit-linear-gradient(#4d4d4d, #404040);
|
background-image: -webkit-linear-gradient(#525252, #454545);
|
||||||
background-image: linear-gradient(#4d4d4d, #404040);
|
background-image: linear-gradient(#525252, #454545);
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 2px;
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 2px;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-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.3) 0 1px 3px;
|
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||||
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 1px solid #666666;
|
border-top: 1px solid #575757;
|
||||||
color: #999;
|
color: #999;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
@ -397,14 +383,21 @@ input[type="date"] {
|
|||||||
margin: 0 0 2px 2px;
|
margin: 0 0 2px 2px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
position: relative; }
|
position: relative; }
|
||||||
/* line 148, ../sass/_mixins.scss */
|
/* line 152, ../sass/_mixins.scss */
|
||||||
.form-control.select:not(.disabled):hover {
|
.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-size: 100%;
|
||||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #666666), color-stop(100%, #4d4d4d));
|
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #636363), color-stop(100%, #575757));
|
||||||
background-image: -moz-linear-gradient(#666666, #4d4d4d);
|
background-image: -moz-linear-gradient(#636363, #575757);
|
||||||
background-image: -webkit-linear-gradient(#666666, #4d4d4d);
|
background-image: -webkit-linear-gradient(#636363, #575757);
|
||||||
background-image: linear-gradient(#666666, #4d4d4d); }
|
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 */
|
/* line 29, ../sass/forms/_selects.scss */
|
||||||
.form-control.select select {
|
.form-control.select select {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
@ -461,9 +454,9 @@ input[type="date"] {
|
|||||||
.channel-selector .treeview {
|
.channel-selector .treeview {
|
||||||
-moz-appearance: none;
|
-moz-appearance: none;
|
||||||
-webkit-appearance: none;
|
-webkit-appearance: none;
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 2px;
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 2px;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
@ -61,6 +61,15 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* 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
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
@ -92,23 +101,23 @@
|
|||||||
top: 0; }
|
top: 0; }
|
||||||
/* line 29, ../sass/items/_item.scss */
|
/* line 29, ../sass/items/_item.scss */
|
||||||
.items-holder .item.grid-item {
|
.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-size: 100%;
|
||||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #595959), color-stop(100%, #4d4d4d));
|
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #5e5e5e), color-stop(100%, #525252));
|
||||||
background-image: -moz-linear-gradient(#595959, #4d4d4d);
|
background-image: -moz-linear-gradient(#5e5e5e, #525252);
|
||||||
background-image: -webkit-linear-gradient(#595959, #4d4d4d);
|
background-image: -webkit-linear-gradient(#5e5e5e, #525252);
|
||||||
background-image: linear-gradient(#595959, #4d4d4d);
|
background-image: linear-gradient(#5e5e5e, #525252);
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 2px;
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 2px;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-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.3) 0 1px 3px;
|
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||||
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 1px solid #737373;
|
border-top: 1px solid #636363;
|
||||||
color: #999;
|
color: #999;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
@ -119,14 +128,21 @@
|
|||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
margin-right: 3px;
|
margin-right: 3px;
|
||||||
position: relative; }
|
position: relative; }
|
||||||
/* line 148, ../sass/_mixins.scss */
|
/* line 152, ../sass/_mixins.scss */
|
||||||
.items-holder .item.grid-item:not(.disabled):hover {
|
.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-size: 100%;
|
||||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #737373), color-stop(100%, #595959));
|
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #707070), color-stop(100%, #636363));
|
||||||
background-image: -moz-linear-gradient(#737373, #595959);
|
background-image: -moz-linear-gradient(#707070, #636363);
|
||||||
background-image: -webkit-linear-gradient(#737373, #595959);
|
background-image: -webkit-linear-gradient(#707070, #636363);
|
||||||
background-image: linear-gradient(#737373, #595959); }
|
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 */
|
/* line 42, ../sass/items/_item.scss */
|
||||||
.items-holder .item.grid-item:hover .item-main .item-type {
|
.items-holder .item.grid-item:hover .item-main .item-type {
|
||||||
color: #0099cc !important; }
|
color: #0099cc !important; }
|
||||||
@ -184,40 +200,41 @@
|
|||||||
font-size: 0.8em; }
|
font-size: 0.8em; }
|
||||||
/* line 104, ../sass/items/_item.scss */
|
/* line 104, ../sass/items/_item.scss */
|
||||||
.items-holder .item.grid-item.selected {
|
.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-size: 100%;
|
||||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #00bfff), color-stop(100%, #00ace6));
|
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #0ac2ff), color-stop(100%, #00b4f0));
|
||||||
background-image: -moz-linear-gradient(#00bfff, #00ace6);
|
background-image: -moz-linear-gradient(#0ac2ff, #00b4f0);
|
||||||
background-image: -webkit-linear-gradient(#00bfff, #00ace6);
|
background-image: -webkit-linear-gradient(#0ac2ff, #00b4f0);
|
||||||
background-image: linear-gradient(#00bfff, #00ace6);
|
background-image: linear-gradient(#0ac2ff, #00b4f0);
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 2px;
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 2px;
|
||||||
-moz-box-sizing: border-box;
|
-moz-box-sizing: border-box;
|
||||||
-webkit-box-sizing: border-box;
|
-webkit-box-sizing: border-box;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
-moz-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.3) 0 1px 3px;
|
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||||
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 1px solid #33ccff;
|
border-top: 1px solid #14c4ff;
|
||||||
color: #999;
|
color: #999;
|
||||||
display: inline-block;
|
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; }
|
color: #80dfff; }
|
||||||
/* line 156, ../sass/_mixins.scss */
|
/* line 152, ../sass/_mixins.scss */
|
||||||
.items-holder .item.grid-item.selected:not(.disabled):hover {
|
.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-size: 100%;
|
||||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #66d9ff), color-stop(100%, #00bfff));
|
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #2ecbff), color-stop(100%, #14c4ff));
|
||||||
background-image: -moz-linear-gradient(#66d9ff, #00bfff);
|
background-image: -moz-linear-gradient(#2ecbff, #14c4ff);
|
||||||
background-image: -webkit-linear-gradient(#66d9ff, #00bfff);
|
background-image: -webkit-linear-gradient(#2ecbff, #14c4ff);
|
||||||
background-image: linear-gradient(#66d9ff, #00bfff); }
|
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 */
|
/* 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) {
|
.items-holder .item.grid-item.selected .item-type, .items-holder .item.grid-item.selected .top-bar .icon:not(.alert) {
|
||||||
color: #80dfff; }
|
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
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* 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
|
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||||
* as represented by the Administrator of the National Aeronautics and Space
|
* as represented by the Administrator of the National Aeronautics and Space
|
||||||
@ -86,7 +95,7 @@
|
|||||||
ul.tree {
|
ul.tree {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0; }
|
padding: 0; }
|
||||||
/* line 208, ../sass/_mixins.scss */
|
/* line 264, ../sass/_mixins.scss */
|
||||||
ul.tree li {
|
ul.tree li {
|
||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -97,17 +106,17 @@ ul.tree {
|
|||||||
position: relative; }
|
position: relative; }
|
||||||
/* line 27, ../sass/tree/_tree.scss */
|
/* line 27, ../sass/tree/_tree.scss */
|
||||||
ul.tree li span.tree-item {
|
ul.tree li span.tree-item {
|
||||||
-moz-border-radius: 3px;
|
-moz-border-radius: 2px;
|
||||||
-webkit-border-radius: 3px;
|
-webkit-border-radius: 2px;
|
||||||
border-radius: 3px;
|
border-radius: 2px;
|
||||||
-moz-transition: background-color 0.25s;
|
-moz-transition: background-color 0.25s;
|
||||||
-o-transition: background-color 0.25s;
|
-o-transition: background-color 0.25s;
|
||||||
-webkit-transition: background-color 0.25s;
|
-webkit-transition: background-color 0.25s;
|
||||||
transition: background-color 0.25s;
|
transition: background-color 0.25s;
|
||||||
display: block;
|
display: block;
|
||||||
font-size: 0.80rem;
|
font-size: 0.80rem;
|
||||||
height: 1.5rem;
|
height: 1.4rem;
|
||||||
line-height: 1.5rem;
|
line-height: 1.4rem;
|
||||||
margin-bottom: 3px;
|
margin-bottom: 3px;
|
||||||
position: relative; }
|
position: relative; }
|
||||||
/* line 38, ../sass/tree/_tree.scss */
|
/* line 38, ../sass/tree/_tree.scss */
|
||||||
@ -168,7 +177,7 @@ ul.tree {
|
|||||||
width: auto;
|
width: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
display: block;
|
display: block;
|
||||||
left: 25px;
|
left: 20px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
white-space: nowrap; }
|
white-space: nowrap; }
|
||||||
@ -207,17 +216,16 @@ ul.tree {
|
|||||||
/* line 125, ../sass/tree/_tree.scss */
|
/* line 125, ../sass/tree/_tree.scss */
|
||||||
ul.tree li span.tree-item:not(.loading) {
|
ul.tree li span.tree-item:not(.loading) {
|
||||||
cursor: pointer; }
|
cursor: pointer; }
|
||||||
/* line 130, ../sass/tree/_tree.scss */
|
/* line 129, ../sass/tree/_tree.scss */
|
||||||
ul.tree li span.tree-item .context-trigger {
|
ul.tree li span.tree-item .context-trigger {
|
||||||
display: none;
|
|
||||||
top: -1px;
|
top: -1px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 3px; }
|
right: 3px; }
|
||||||
/* line 136, ../sass/tree/_tree.scss */
|
/* line 135, ../sass/tree/_tree.scss */
|
||||||
ul.tree li span.tree-item .context-trigger .btn-invoke-menu {
|
ul.tree li span.tree-item .context-trigger .invoke-menu {
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
height: 0.9rem;
|
height: 0.9rem;
|
||||||
line-height: 0.9rem; }
|
line-height: 0.9rem; }
|
||||||
/* line 145, ../sass/tree/_tree.scss */
|
/* line 144, ../sass/tree/_tree.scss */
|
||||||
ul.tree ul.tree {
|
ul.tree ul.tree {
|
||||||
margin-left: 15px; }
|
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" >
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||||
<svg>
|
<svg>
|
||||||
<metadata>
|
<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
|
By deploy user
|
||||||
Copyright 2015 Adobe Systems Incorporated. All rights reserved.
|
Copyright 2015 Adobe Systems Incorporated. All rights reserved.
|
||||||
</metadata>
|
</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" />
|
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"
|
<glyph glyph-name="eight" unicode="8" horiz-adv-x="636"
|
||||||
d="M625 735v-318h-625v318h625zM625 315v-315h-625v315h625z" />
|
d="M625 735v-318h-625v318h625zM625 315v-315h-625v315h625z" />
|
||||||
<glyph glyph-name="nine" unicode="9" horiz-adv-x="636"
|
<glyph glyph-name="nine" unicode="9"
|
||||||
d="M267 735v-319h-267v319h267zM267 315v-315h-267v315h267zM630 735v-319h-267v319h267zM630 315v-315h-267v315h267z" />
|
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"
|
<glyph glyph-name="colon" unicode=":" horiz-adv-x="625"
|
||||||
d="M625 -19l-397 397l397 397v-794zM173 756v-735h-173v735h173z" />
|
d="M625 -19l-397 397l397 397v-794zM173 756v-735h-173v735h173z" />
|
||||||
<glyph glyph-name="semicolon" unicode=";" horiz-adv-x="624"
|
<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" />
|
d="M123 93l-123 123v147l123 -123l220 220v-147zM485 262v71h313v-71h-313z" />
|
||||||
<glyph glyph-name="l" unicode="l" horiz-adv-x="617"
|
<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" />
|
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"
|
<glyph glyph-name="m" unicode="m" horiz-adv-x="751"
|
||||||
d="M804 729v-156h-804v156h804zM804 445v-160h-804v160h804zM804 158v-158h-804v158h804z" />
|
d="M751 563h-751v188h751v-188zM751 282h-751v187h751v-187zM751 0h-751v188h751v-188z" />
|
||||||
<glyph glyph-name="n" unicode="n" horiz-adv-x="738"
|
<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
|
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" />
|
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" />
|
d="M-1 0l375 750l374 -750h-749z" />
|
||||||
<glyph glyph-name="icircumflex" unicode="î" horiz-adv-x="748"
|
<glyph glyph-name="icircumflex" unicode="î" horiz-adv-x="748"
|
||||||
d="M748 750l-375 -375l-374 375h749zM748 375l-375 -374l-374 374h749z" />
|
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"
|
<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" />
|
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"
|
<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
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// Features
|
||||||
|
$enableImageryThumbs: false; // Set to true if historical imagery thumbnails are supported
|
||||||
|
|
||||||
// Margins, spacing, radii
|
// Margins, spacing, radii
|
||||||
$bodyMargin: 10px;
|
$bodyMargin: 10px;
|
||||||
$interiorMargin: 5px;
|
$interiorMargin: 5px;
|
||||||
$interiorMarginLg: $interiorMargin * 2;
|
$interiorMarginLg: $interiorMargin * 2;
|
||||||
$interiorMarginSm: 3px;
|
$interiorMarginSm: 3px;
|
||||||
$basicCr: 3px;
|
$basicCr: 2px;
|
||||||
$controlCr: $basicCr;
|
$controlCr: 2px;
|
||||||
$smallCr: 2px;
|
$smallCr: 2px;
|
||||||
$badgeW: 35px;
|
$badgeW: 35px;
|
||||||
|
|
||||||
@ -34,9 +38,12 @@ $colorBodyBg: #333;
|
|||||||
$colorBodyFg: #999;
|
$colorBodyFg: #999;
|
||||||
$colorFooterBg: #000;
|
$colorFooterBg: #000;
|
||||||
$colorKey: #0099cc;
|
$colorKey: #0099cc;
|
||||||
|
$colorKeySelectedBg: #005177;
|
||||||
$colorKeyFg: #fff;
|
$colorKeyFg: #fff;
|
||||||
$colorAlt1: #ffc700;
|
$colorAlt1: #ffc700;
|
||||||
$colorAlert: #ff3c00;
|
$colorAlert: #ff3c00;
|
||||||
|
$colorPausedBg: #c56f01;
|
||||||
|
$colorPausedFg: #fff;
|
||||||
$colorCheck: $colorKey;
|
$colorCheck: $colorKey;
|
||||||
$colorCreateBtn: $colorKey;
|
$colorCreateBtn: $colorKey;
|
||||||
$colorInteriorBorder: lighten($colorBodyBg, 10%);
|
$colorInteriorBorder: lighten($colorBodyBg, 10%);
|
||||||
@ -50,7 +57,18 @@ $colorLimitYellow: #9d7500;
|
|||||||
$colorLimitRed: #aa0000;
|
$colorLimitRed: #aa0000;
|
||||||
$colorTelemFresh: #fff;
|
$colorTelemFresh: #fff;
|
||||||
$colorTelemStale: #888;
|
$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;
|
$styleTelemState: italic;
|
||||||
|
$colorInfoBubbleFg: #666;
|
||||||
|
$colorInfoBubbleBg: #ddd;
|
||||||
|
|
||||||
// Ratios
|
// Ratios
|
||||||
$ltGamma: 20%;
|
$ltGamma: 20%;
|
||||||
@ -108,7 +126,7 @@ $controlDisabledOpacity: 0.3;
|
|||||||
$formLabelW: 20%;
|
$formLabelW: 20%;
|
||||||
$formInputH: 22px;
|
$formInputH: 22px;
|
||||||
$formRowCtrlsH: 14px;
|
$formRowCtrlsH: 14px;
|
||||||
$menuLineH: 1.5rem;
|
$menuLineH: 1.4rem;
|
||||||
$scrollbarTrackSize: 10px;
|
$scrollbarTrackSize: 10px;
|
||||||
$scrollbarTrackColorBg: rgba(#000, 0.4);
|
$scrollbarTrackColorBg: rgba(#000, 0.4);
|
||||||
$btnStdH: 25px;
|
$btnStdH: 25px;
|
||||||
@ -124,3 +142,19 @@ $tickLblH: 15px;
|
|||||||
$tickLblW: 50px;
|
$tickLblW: 50px;
|
||||||
$tickH: $ticksH - $tickLblVMargin - $tickLblH;
|
$tickH: $ticksH - $tickLblVMargin - $tickLblH;
|
||||||
$tickW: 1px;
|
$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) {
|
@include keyframes(pulse) {
|
||||||
0% { opacity: 0.2; }
|
0% { opacity: 0.5; }
|
||||||
100% { opacity: 1; }
|
100% { opacity: 1; }
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -57,5 +57,5 @@ a.disabled {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.pulse {
|
.pulse {
|
||||||
@include pulse(1000ms);
|
@include pulse(750ms);
|
||||||
}
|
}
|
@ -69,6 +69,10 @@ span {
|
|||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mct-container {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
.abs {
|
.abs {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -117,6 +121,13 @@ span {
|
|||||||
display: none !important;
|
display: none !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.paused {
|
||||||
|
&:not(.s-btn) {
|
||||||
|
border-color: $colorPausedBg !important;
|
||||||
|
color: $colorPausedBg !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.sep {
|
.sep {
|
||||||
color: rgba(#fff, 0.2);
|
color: rgba(#fff, 0.2);
|
||||||
}
|
}
|
@ -36,7 +36,7 @@
|
|||||||
// Don't pad in from top and bottom
|
// Don't pad in from top and bottom
|
||||||
//top: 0; bottom: 0;
|
//top: 0; bottom: 0;
|
||||||
.object-browse-bar {
|
.object-browse-bar {
|
||||||
.t-btn.key-window {
|
.btn.key-window {
|
||||||
// Hide the Open in New Window button
|
// Hide the Open in New Window button
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
@ -42,12 +42,6 @@
|
|||||||
&.major {
|
&.major {
|
||||||
font-size: 1.65em;
|
font-size: 1.65em;
|
||||||
}
|
}
|
||||||
&:hover {
|
|
||||||
// color: lighten($c, $ltGamma);
|
|
||||||
.invoke-menu {
|
|
||||||
// color: lighten($colorBodyBg, $ltGamma * 2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -56,36 +50,35 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.invoke-menu {
|
.invoke-menu {
|
||||||
@include invokeMenu($colorKey);
|
//@include invokeMenu(); // $colorKey
|
||||||
|
text-shadow: none;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 1rem;
|
font-size: 0.8rem;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-menu .invoke-menu,
|
.btn-menu .invoke-menu,
|
||||||
.icon.major .invoke-menu {
|
.icon.major .invoke-menu {
|
||||||
margin-left: $interiorMargin;
|
margin-left: $interiorMarginSm;
|
||||||
}
|
|
||||||
|
|
||||||
.icon-buttons-main .invoke-menu {
|
|
||||||
@include invokeMenu(lighten($colorBodyBg, $ltGamma));
|
|
||||||
}
|
|
||||||
|
|
||||||
.menu-element .invoke-menu {
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
.object-header .type-icon {
|
.object-header .type-icon {
|
||||||
color: $colorKey;
|
color: $colorKey;
|
||||||
margin-right: $interiorMargin;
|
margin-right: $interiorMarginSm;
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
.menu .type-icon,
|
.menu .type-icon,
|
||||||
.tree-item .type-icon,
|
.tree-item .type-icon,
|
||||||
.icon-btn .menu.dropdown .icon,
|
.super-menu.menu .type-icon {
|
||||||
.super-menu.menu.dropdown .icon {
|
font-size: $menuLineH * 0.8; //.93
|
||||||
font-size: $menuLineH * 0.93;
|
|
||||||
line-height: $menuLineH * 1.13;
|
line-height: $menuLineH * 1.13;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.super-menu.menu.dropdown .icon {
|
||||||
|
font-size: $menuLineH * 0.95
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,9 @@
|
|||||||
@import "controls/lists";
|
@import "controls/lists";
|
||||||
@import "controls/menus";
|
@import "controls/menus";
|
||||||
@import "controls/time-controller";
|
@import "controls/time-controller";
|
||||||
|
@import "edit/editor";
|
||||||
|
@import "features/imagery";
|
||||||
|
@import "features/time-display";
|
||||||
@import "forms/mixins";
|
@import "forms/mixins";
|
||||||
@import "forms/elems";
|
@import "forms/elems";
|
||||||
@import "forms/validation";
|
@import "forms/validation";
|
||||||
|
@ -26,6 +26,16 @@
|
|||||||
width: auto; height: auto;
|
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) {
|
@mixin trans-prop-nice-fade($t: 0.5s) {
|
||||||
@if $t == 0 {
|
@if $t == 0 {
|
||||||
@include transition-property(none);
|
@include transition-property(none);
|
||||||
@ -42,6 +52,12 @@
|
|||||||
@include transition-timing-function(ease-in-out);
|
@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) {
|
@mixin triangle-right($size, $color) {
|
||||||
$size: $size/2;
|
$size: $size/2;
|
||||||
$ratio: 1;
|
$ratio: 1;
|
||||||
@ -62,6 +78,31 @@
|
|||||||
border-right: $size/$ratio solid transparent;
|
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) {
|
@mixin bgDiagonalStripes($c: yellow, $a: 0.1, $d: 40px) {
|
||||||
@include background-image(linear-gradient(-45deg,
|
@include background-image(linear-gradient(-45deg,
|
||||||
rgba($c, $a) 25%, transparent 25%,
|
rgba($c, $a) 25%, transparent 25%,
|
||||||
@ -90,20 +131,35 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@mixin containerSubtle($bg: $colorBodyBg, $fg: $colorBodyFg, $hover: false) {
|
@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 border-radius($controlCr);
|
||||||
@include box-sizing(border-box);
|
@include box-sizing(border-box);
|
||||||
// @include box-shadow(rgba(black, 0.3) 0 1px 2px);
|
|
||||||
@include boxShdwSubtle();
|
@include boxShdwSubtle();
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 1px solid lighten($bg, 20%);
|
border-top: 1px solid lighten($gradC1, 2%);
|
||||||
color: $fg;
|
color: $fg;
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@if $hover == true {
|
@if $hover == true {
|
||||||
&:hover {
|
&:not(.disabled):hover {
|
||||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 15%)));
|
@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) {
|
@mixin sliderTrack($bg: $scrollbarTrackColorBg) {
|
||||||
@ -144,18 +200,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
@mixin btnSubtle($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
@mixin btnSubtle($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||||
@include containerSubtle($bg, $fg);
|
@include containerSubtle($bg, $fg, true);
|
||||||
&:not(.disabled):hover {
|
|
||||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 10%)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin btnNoticeable($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
@mixin btnNoticeable($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||||
@include containerSubtle($bg, $fg);
|
// No longer should be used; use btnSubtle instead
|
||||||
@include background-image(linear-gradient(lighten($bg, 20%), $bg));
|
//@include containerSubtle($bg, $fg, true);
|
||||||
&:not(.disabled):hover {
|
//@include background-image(linear-gradient(lighten($bg, 20%), $bg));
|
||||||
|
/* &:not(.disabled):hover {
|
||||||
@include background-image(linear-gradient(lighten($bg, 30%), lighten($bg, 10%)));
|
@include background-image(linear-gradient(lighten($bg, 30%), lighten($bg, 10%)));
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin boxIncised($sVal: 0.6) {
|
@mixin boxIncised($sVal: 0.6) {
|
||||||
@ -166,8 +220,8 @@
|
|||||||
border: 1px solid $c;
|
border: 1px solid $c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin boxShdwSubtle($sVal: 0.3) {
|
@mixin boxShdwSubtle($sVal: 0.2) {
|
||||||
@include box-shadow(rgba(black, $sVal) 0 1px 3px);
|
@include box-shadow(rgba(black, $sVal) 0 1px 2px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin boxShdwLarge($sVal: 0.7) {
|
@mixin boxShdwLarge($sVal: 0.7) {
|
||||||
@ -194,13 +248,15 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@mixin invokeMenu($baseColor) {
|
/*
|
||||||
|
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
||||||
$c: $baseColor;
|
$c: $baseColor;
|
||||||
color: $c;
|
color: $c;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: lighten($c, $ltGamma);
|
color: lighten($c, $ltGamma);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
@mixin menuUlReset() {
|
@mixin menuUlReset() {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
@ -19,38 +19,98 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
$pad: $interiorMargin * 2;
|
$baseRatio: 1.5;
|
||||||
|
$pad: $interiorMargin * $baseRatio;
|
||||||
|
|
||||||
/*********************************** TYPE STYLES */
|
/******* LAYOUT AND SIZING */
|
||||||
.t-btn {
|
.btn,
|
||||||
cursor: pointer;
|
.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 */
|
/*********************************** STYLE STYLES */
|
||||||
|
.btn,
|
||||||
.s-btn {
|
.s-btn {
|
||||||
$base: lighten($colorBodyBg, 20%);
|
$base: lighten($colorBodyBg, 20%); // Moved to s-btn
|
||||||
@include border-radius($controlCr);
|
@include border-radius($controlCr);
|
||||||
@include box-sizing(border-box);
|
@include box-sizing(border-box);
|
||||||
@include text-shadow(rgba(black, 0.3) 0 1px 1px);
|
@include text-shadow(rgba(black, 0.3) 0 1px 1px);
|
||||||
|
cursor: pointer;
|
||||||
line-height: 1.2em;
|
line-height: 1.2em;
|
||||||
padding: 0 $pad;
|
|
||||||
text-decoration: none;
|
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 {
|
&.s-very-subtle {
|
||||||
@include containerSubtle($colorBodyBg, $colorBodyFg, true);
|
@include containerSubtle($colorBodyBg, $colorBodyFg, true);
|
||||||
|
&.paused {
|
||||||
|
@include containerSubtle($colorPausedBg, $colorPausedFg, true);
|
||||||
|
.icon:before {
|
||||||
|
content:"\0000EF";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.icon-btn,
|
||||||
.s-icon-btn {
|
.s-icon-btn {
|
||||||
@extend .s-btn;
|
@extend .s-btn;
|
||||||
font-size: 1.2em;
|
font-size: 1em;
|
||||||
.icon {
|
.icon {
|
||||||
color: $colorKey;
|
color: $colorKey;
|
||||||
}
|
}
|
||||||
|
&.paused {
|
||||||
|
.icon {
|
||||||
|
color: $colorPausedFg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&:not(.disabled):hover .icon {
|
&:not(.disabled) {
|
||||||
|
&:not(.paused) {
|
||||||
|
&:hover {
|
||||||
|
.icon {
|
||||||
color: lighten($colorKey, $ltGamma);
|
color: lighten($colorKey, $ltGamma);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
&.labeled {
|
&.labeled {
|
||||||
padding: 0 $pad/2;
|
padding: 0 $pad/2;
|
||||||
@ -61,12 +121,30 @@ $pad: $interiorMargin * 2;
|
|||||||
margin-left: $interiorMargin;
|
margin-left: $interiorMargin;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&.pause-play {
|
||||||
|
&.paused {
|
||||||
|
@include pulse(500ms);
|
||||||
|
}
|
||||||
|
.icon:before {
|
||||||
|
content:"\0000F1";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.show-thumbs {
|
||||||
|
.icon:before {
|
||||||
|
content:"\000039";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*********************************** LAYOUT STYLES */
|
/*********************************** LAYOUT STYLES */
|
||||||
|
span.btn,
|
||||||
|
span.btn span,
|
||||||
span.l-btn,
|
span.l-btn,
|
||||||
span.l-btn span,
|
span.l-btn span,
|
||||||
|
a.btn,
|
||||||
|
a.btn span,
|
||||||
a.l-btn,
|
a.l-btn,
|
||||||
a.l-btn span {
|
a.l-btn span {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
|
@ -19,7 +19,8 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
.control {
|
/*.control {
|
||||||
|
// UNUSED?
|
||||||
&.view-control {
|
&.view-control {
|
||||||
.icon {
|
.icon {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -45,7 +46,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
.accordion {
|
.accordion {
|
||||||
$accordionHeadH: 18px;
|
$accordionHeadH: 18px;
|
||||||
@ -64,8 +65,12 @@
|
|||||||
margin-bottom: $interiorMargin;
|
margin-bottom: $interiorMargin;
|
||||||
padding: 0 $interiorMargin;
|
padding: 0 $interiorMargin;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0; right: 0; bottom: auto; left: 0;
|
top: 0;
|
||||||
width: auto; height: $accordionHeadH;
|
right: 0;
|
||||||
|
bottom: auto;
|
||||||
|
left: 0;
|
||||||
|
width: auto;
|
||||||
|
height: $accordionHeadH;
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba($colorBodyFg, $op * 2);
|
background: rgba($colorBodyFg, $op * 2);
|
||||||
@ -86,92 +91,27 @@
|
|||||||
}
|
}
|
||||||
.accordion-contents {
|
.accordion-contents {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: $accordionHeadH + $interiorMargin; right: 0; bottom: 0; left: 0;
|
top: $accordionHeadH + $interiorMargin;
|
||||||
|
right: 0;
|
||||||
|
bottom: 0;
|
||||||
|
left: 0;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
overflow-x: hidden;
|
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.btn-bar {
|
.btn-bar {
|
||||||
// position: relative;
|
// position: relative;
|
||||||
.btn,
|
.btn,
|
||||||
.btn-set,
|
.btn-set,
|
||||||
.t-btn {
|
.t-btn {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
// margin-left: $interiorMargin;
|
// margin-left: $interiorMargin;
|
||||||
}
|
}
|
||||||
.btn,
|
.btn,
|
||||||
.t-btn {
|
.t-btn {
|
||||||
&:first-child {
|
&: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 {
|
.btn-set {
|
||||||
// Buttons that have a very tight conceptual grouping - no internal space between them.
|
// Buttons that have a very tight conceptual grouping - no internal space between them.
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
@ -230,8 +184,8 @@
|
|||||||
height: $h;
|
height: $h;
|
||||||
line-height: $h;
|
line-height: $h;
|
||||||
.icon:not(.invoke-menu) {
|
.icon:not(.invoke-menu) {
|
||||||
// position: relative;
|
// position: relative;
|
||||||
// top: -0.04em;
|
// top: -0.04em;
|
||||||
font-size: 150%;
|
font-size: 150%;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
@ -318,29 +272,31 @@ label.checkbox.custom {
|
|||||||
|
|
||||||
.btn-menu {
|
.btn-menu {
|
||||||
$h: 20px;
|
$h: 20px;
|
||||||
$p: $interiorMargin * 2;
|
$p: $interiorMarginSm * 2;
|
||||||
$c: $colorBodyFg;
|
$c: $colorBodyFg;
|
||||||
@include btnSubtle($colorBodyBg);
|
@include btnSubtle($colorBodyBg);
|
||||||
height: $h;
|
/* height: $h;
|
||||||
line-height: $h;
|
line-height: $h;
|
||||||
&.dropdown {
|
&.dropdown {
|
||||||
// padding-left: $p;
|
|
||||||
padding-left: $p;
|
padding-left: $p;
|
||||||
padding-right: $p;
|
padding-right: $p;
|
||||||
}
|
}*/
|
||||||
|
|
||||||
&:not(.disabled):hover {
|
&:not(.disabled):hover {
|
||||||
color: lighten($c, 20%);
|
color: lighten($c, 20%);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.btn-invoke-menu {
|
/* &.context-available {
|
||||||
|
// An element like the invoke-menu triangle;
|
||||||
|
// Indicates that this element has a dropdown menu available;
|
||||||
|
// Currently unused
|
||||||
$c: $colorKey;
|
$c: $colorKey;
|
||||||
color: $c;
|
color: $c;
|
||||||
padding: 0 5px;
|
padding: 0 5px;
|
||||||
&:hover {
|
&:hover {
|
||||||
color: lighten($c, 10%);
|
color: lighten($c, 10%);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
span.l-click-area {
|
span.l-click-area {
|
||||||
// In markup, this element should not enclose anything.
|
// In markup, this element should not enclose anything.
|
||||||
@ -348,7 +304,11 @@ label.checkbox.custom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.type-icon {
|
.type-icon {
|
||||||
margin-right: $interiorMargin;
|
//margin-right: $interiorMargin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.name {
|
||||||
|
margin-left: $interiorMargin;
|
||||||
}
|
}
|
||||||
.menu {
|
.menu {
|
||||||
// margin-left: (-1 * $p);
|
// margin-left: (-1 * $p);
|
||||||
@ -388,11 +348,16 @@ label.checkbox.custom {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.view-switcher {
|
||||||
|
@include trans-prop-nice-fade($controlFadeMs);
|
||||||
|
}
|
||||||
|
|
||||||
/******************************************************** OBJECT-HEADER */
|
/******************************************************** OBJECT-HEADER */
|
||||||
.object-header {
|
.object-header {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
font-size: 1em;
|
font-size: 1em;
|
||||||
.title {
|
.label {
|
||||||
|
.title-label {
|
||||||
color: lighten($colorBodyFg, 40%);
|
color: lighten($colorBodyFg, 40%);
|
||||||
}
|
}
|
||||||
.type-icon {
|
.type-icon {
|
||||||
@ -400,6 +365,7 @@ label.checkbox.custom {
|
|||||||
margin-right: $interiorMargin;
|
margin-right: $interiorMargin;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.top-bar,
|
.top-bar,
|
||||||
@ -412,52 +378,43 @@ 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 */
|
/******************************************************** SLIDERS */
|
||||||
.wrapper-slider {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.slider {
|
.slider {
|
||||||
//$knobH: 70%; //14px;
|
$knobH: 100%; //14px;
|
||||||
$knobW: 12px;
|
$knobW: 12px;
|
||||||
$slotH: 80%;
|
$slotH: 50%;
|
||||||
$rangeO: 0.3;
|
|
||||||
.slot {
|
.slot {
|
||||||
// @include border-radius($basicCr * .75);
|
// @include border-radius($basicCr * .75);
|
||||||
@include sliderTrack();
|
@include sliderTrack();
|
||||||
height: auto;
|
height: $slotH;
|
||||||
width: auto;
|
width: auto;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
//top: ($knobH - $slotH) / 2;
|
top: ($knobH - $slotH) / 2;
|
||||||
top: (100% - $slotH)/2;
|
|
||||||
right: 0;
|
right: 0;
|
||||||
bottom: (100% - $slotH)/2;
|
bottom: auto;
|
||||||
left: 0;
|
left: 0;
|
||||||
z-index: 0;
|
}
|
||||||
|
.knob {
|
||||||
|
@include btnSubtle();
|
||||||
|
@include controlGrippy(rgba(black, 0.3), vertical, 1px, solid);
|
||||||
|
cursor: ew-resize;
|
||||||
|
position: absolute;
|
||||||
|
height: $knobH;
|
||||||
|
width: $knobW;
|
||||||
|
top: 0;
|
||||||
|
auto: 0;
|
||||||
|
bottom: auto;
|
||||||
|
left: auto;
|
||||||
|
&:before {
|
||||||
|
top: 1px;
|
||||||
|
bottom: 3px;
|
||||||
|
left: ($knobW / 2) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
.range {
|
.range {
|
||||||
background: rgba($colorKey, $rangeO);
|
background: rgba($colorKey, 0.6);
|
||||||
cursor: ew-resize;
|
cursor: ew-resize;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 0;
|
top: 0;
|
||||||
@ -466,32 +423,8 @@ label.checkbox.custom {
|
|||||||
left: auto;
|
left: auto;
|
||||||
height: auto;
|
height: auto;
|
||||||
width: auto;
|
width: auto;
|
||||||
z-index: 1;
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: rgba($colorKey, $rangeO + 0.2);
|
background: rgba($colorKey, 0.7);
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.knob {
|
|
||||||
@include btnSubtle();
|
|
||||||
@include controlGrippy(rgba(black, 0.3), vertical, 1px, solid);
|
|
||||||
@include border-radius(2px);
|
|
||||||
cursor: ew-resize;
|
|
||||||
position: absolute;
|
|
||||||
height: auto;
|
|
||||||
width: $knobW;
|
|
||||||
top: 0;
|
|
||||||
bottom: 0;
|
|
||||||
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%;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@
|
|||||||
@include box-sizing(border-box);
|
@include box-sizing(border-box);
|
||||||
border-top: 1px solid lighten($bg, 20%);
|
border-top: 1px solid lighten($bg, 20%);
|
||||||
line-height: $menuLineH;
|
line-height: $menuLineH;
|
||||||
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 3) + $treeTypeIconW;
|
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
&:first-child {
|
&:first-child {
|
||||||
border: none;
|
border: none;
|
||||||
@ -168,7 +168,7 @@
|
|||||||
position: absolute;
|
position: absolute;
|
||||||
height: 200px;
|
height: 200px;
|
||||||
width: 170px;
|
width: 170px;
|
||||||
z-index: 59;
|
z-index: 70;
|
||||||
.context-menu-wrapper {
|
.context-menu-wrapper {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
@ -19,3 +19,86 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* 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,16 +19,11 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
input[type="text"],
|
input[type="text"] {
|
||||||
input[type="date"] {
|
|
||||||
@include nice-input();
|
@include nice-input();
|
||||||
@include input-placeholder {
|
|
||||||
color: darken($colorBodyFg, 10%);
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
&.filter {
|
&.filter {
|
||||||
&.ng-dirty {
|
&.ng-dirty {
|
||||||
// background: red;
|
// background: red;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
&.numeric {
|
&.numeric {
|
||||||
|
@ -19,19 +19,24 @@
|
|||||||
* this source code distribution or the Licensing information page available
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
//************************************************* LAYOUT
|
|
||||||
|
|
||||||
$infoBubbleFg: #666;
|
//************************************************* GENERAL
|
||||||
$infoBubbleBg: #ddd;
|
.bubble-container {
|
||||||
|
pointer-events: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//************************************************* LAYOUT
|
||||||
|
|
||||||
.l-infobubble-wrapper {
|
.l-infobubble-wrapper {
|
||||||
$arwSize: 5px;
|
$arwSize: 5px;
|
||||||
@include box-shadow(rgba(black, 0.4) 0 1px 5px);
|
@include box-shadow(rgba(black, 0.4) 0 1px 5px);
|
||||||
position: absolute;
|
position: relative;
|
||||||
z-index: 70;
|
z-index: 50;
|
||||||
.l-infobubble {
|
.l-infobubble {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
max-width: 250px;
|
min-width: $bubbleMinW;
|
||||||
|
max-width: $bubbleMaxW;
|
||||||
padding: 5px 10px;
|
padding: 5px 10px;
|
||||||
&:before {
|
&:before {
|
||||||
content:"";
|
content:"";
|
||||||
@ -71,34 +76,30 @@ $infoBubbleBg: #ddd;
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.arw-left {
|
&.arw-left {
|
||||||
margin-left: $arwSize*2;
|
margin-left: $bubbleArwSize*2;
|
||||||
.l-infobubble::before {
|
.l-infobubble::before {
|
||||||
right: 100%;
|
right: 100%;
|
||||||
border-top: $arwSize solid transparent;
|
@include triangle('left', $bubbleArwSize, 1.5, $colorInfoBubbleBg);
|
||||||
border-bottom: $arwSize solid transparent;
|
|
||||||
border-right: ($arwSize * 1.5) solid $infoBubbleBg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.arw-right {
|
&.arw-right {
|
||||||
margin-right: $arwSize*2;
|
margin-right: $bubbleArwSize*2;
|
||||||
.l-infobubble::before {
|
.l-infobubble::before {
|
||||||
left: 100%;
|
left: 100%;
|
||||||
border-top: $arwSize solid transparent;
|
@include triangle('right', $bubbleArwSize, 1.5, $colorInfoBubbleBg);
|
||||||
border-bottom: $arwSize solid transparent;
|
|
||||||
border-left: ($arwSize * 1.5) solid $infoBubbleBg;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.arw-top {
|
&.arw-top {
|
||||||
.l-infobubble::before {
|
.l-infobubble::before {
|
||||||
top: $arwSize * 2;
|
top: $bubbleArwSize * 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.arw-btm {
|
&.arw-btm {
|
||||||
.l-infobubble::before {
|
.l-infobubble::before {
|
||||||
bottom: $arwSize * 2;
|
bottom: $bubbleArwSize * 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,18 +111,32 @@ $infoBubbleBg: #ddd;
|
|||||||
margin-left: -1 * $arwSize;
|
margin-left: -1 * $arwSize;
|
||||||
border-left: $arwSize solid transparent;
|
border-left: $arwSize solid transparent;
|
||||||
border-right: $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
|
//************************************************* 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 {
|
.s-infobubble {
|
||||||
$emFg: darken($infoBubbleFg, 20%);
|
$emFg: darken($colorInfoBubbleFg, 20%);
|
||||||
@include border-radius($basicCr);
|
@include border-radius($basicCr);
|
||||||
background: $infoBubbleBg;
|
@include box-shadow(rgba(black, 0.4) 0 1px 5px);
|
||||||
color: $infoBubbleFg;
|
background: $colorInfoBubbleBg;
|
||||||
|
color: $colorInfoBubbleFg;
|
||||||
font-size: 0.8rem;
|
font-size: 0.8rem;
|
||||||
.title {
|
.title {
|
||||||
color: $emFg;
|
color: $emFg;
|
||||||
@ -129,7 +144,7 @@ $infoBubbleBg: #ddd;
|
|||||||
}
|
}
|
||||||
tr {
|
tr {
|
||||||
td {
|
td {
|
||||||
border-top: 1px solid darken($infoBubbleBg, 10%);
|
border-top: 1px solid darken($colorInfoBubbleBg, 10%);
|
||||||
font-size: 0.9em;
|
font-size: 0.9em;
|
||||||
}
|
}
|
||||||
&:first-child td {
|
&:first-child td {
|
||||||
@ -139,5 +154,9 @@ $infoBubbleBg: #ddd;
|
|||||||
.value {
|
.value {
|
||||||
color: $emFg;
|
color: $emFg;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.s-thumbsbubble {
|
||||||
|
background: $colorThumbsBubbleBg;
|
||||||
|
color: $colorThumbsBubbleFg;
|
||||||
}
|
}
|
@ -104,7 +104,7 @@
|
|||||||
&.selected {
|
&.selected {
|
||||||
$cfg: lighten($colorItemSelected, 35%);
|
$cfg: lighten($colorItemSelected, 35%);
|
||||||
$cfgh: lighten($cfg, 30%);
|
$cfgh: lighten($cfg, 30%);
|
||||||
@include btnNoticeable($colorItemSelected);
|
@include btnSubtle($colorItemSelected);
|
||||||
color: $cfg;
|
color: $cfg;
|
||||||
.item-type, .top-bar .icon:not(.alert) { color: $cfg }
|
.item-type, .top-bar .icon:not(.alert) { color: $cfg }
|
||||||
.item-main .item-open { color: $cfg }
|
.item-main .item-open { color: $cfg }
|
||||||
|
@ -75,8 +75,8 @@ ul.tree {
|
|||||||
.title-label {
|
.title-label {
|
||||||
@include absPosDefault();
|
@include absPosDefault();
|
||||||
display: block;
|
display: block;
|
||||||
left: $runningItemW + ($interiorMargin * 2);
|
left: $runningItemW + ($interiorMargin);
|
||||||
// right: $treeContextTriggerW + $interiorMargin; //Disabling as context trigger not being used
|
//right: $treeContextTriggerW + $interiorMargin;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-overflow: ellipsis;
|
text-overflow: ellipsis;
|
||||||
// height: $menuLineH;
|
// height: $menuLineH;
|
||||||
@ -99,7 +99,7 @@ ul.tree {
|
|||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
$c: #fff;
|
$c: #fff;
|
||||||
background: #005177;
|
background: $colorKeySelectedBg;
|
||||||
color: $c;
|
color: $c;
|
||||||
.view-control {
|
.view-control {
|
||||||
color: $colorItemTreeIcon;
|
color: $colorItemTreeIcon;
|
||||||
@ -124,16 +124,15 @@ ul.tree {
|
|||||||
|
|
||||||
&:not(.loading) {
|
&:not(.loading) {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
// @include tree-item-hover();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.context-trigger {
|
.context-trigger {
|
||||||
$h: 0.9rem;
|
$h: 0.9rem;
|
||||||
display: none;
|
//display: none;
|
||||||
top: -1px;
|
top: -1px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: $interiorMarginSm;
|
right: $interiorMarginSm;
|
||||||
.btn-invoke-menu {
|
.invoke-menu {
|
||||||
font-size: 0.75em;
|
font-size: 0.75em;
|
||||||
height: $h;
|
height: $h;
|
||||||
line-height: $h;
|
line-height: $h;
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
border: 1px solid $bc;
|
border: 1px solid $bc;
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: lighten($bc, 10%);
|
border-color: lighten($bc, 10%);
|
||||||
|
z-index: 2;
|
||||||
}
|
}
|
||||||
.contents {
|
.contents {
|
||||||
// overflow: hidden;
|
// overflow: hidden;
|
||||||
@ -46,12 +47,25 @@
|
|||||||
bottom: $myM;
|
bottom: $myM;
|
||||||
left: $myM;
|
left: $myM;
|
||||||
}
|
}
|
||||||
}
|
&.frame-template {
|
||||||
|
// Hide the view switcher by default when it's in an element that's in a frame context
|
||||||
.edit-main .frame.child-frame.panel {
|
// Frame template is used because we need to target the lowest nested frame
|
||||||
&:hover {
|
// This has the effect of hiding the view switcher in nested frames in edit mode, which is desirable currently (as it's non-functional)
|
||||||
border-color: $colorKey;
|
.view-switcher {
|
||||||
@include boxShdwLarge();
|
//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,24 +70,20 @@
|
|||||||
&.abs {
|
&.abs {
|
||||||
text-wrap: none;
|
text-wrap: none;
|
||||||
white-space: nowrap;
|
white-space: nowrap;
|
||||||
|
}
|
||||||
&.left,
|
&.left,
|
||||||
.left {
|
.left {
|
||||||
width: 45%;
|
width: 45% !important;
|
||||||
right: auto;
|
right: auto !important;
|
||||||
}
|
}
|
||||||
&.right,
|
&.right,
|
||||||
.right {
|
.right {
|
||||||
width: 45%;
|
width: 45% !important;
|
||||||
left: auto;
|
left: auto !important;
|
||||||
right: 0;
|
|
||||||
text-align: right;
|
text-align: right;
|
||||||
.icon.major {
|
.icon.major {
|
||||||
margin-left: $interiorMargin * 3;
|
margin-left: $interiorMargin * 3;
|
||||||
}
|
}
|
||||||
// .icon.major {
|
|
||||||
// margin-left: $interiorMargin;
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,7 @@
|
|||||||
this source code distribution or the Licensing information page available
|
this source code distribution or the Licensing information page available
|
||||||
at runtime from the About dialog for additional information.
|
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 }"
|
ng-class="{ labeled: parameters.labeled }"
|
||||||
title="{{parameters.action.getMetadata().description}}"
|
title="{{parameters.action.getMetadata().description}}"
|
||||||
ng-click="parameters.action.perform()">
|
ng-click="parameters.action.perform()">
|
||||||
|
@ -21,24 +21,28 @@
|
|||||||
-->
|
-->
|
||||||
<span ng-controller="ViewSwitcherController">
|
<span ng-controller="ViewSwitcherController">
|
||||||
|
|
||||||
<div class="menu-element btn icon-btn very-subtle btn-menu dropdown click-invoke"
|
<div
|
||||||
|
class="view-switcher menu-element btn btn-menu dropdown click-invoke"
|
||||||
ng-if="view.length > 1"
|
ng-if="view.length > 1"
|
||||||
ng-controller="ClickAwayController as toggle">
|
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 class="ui-symbol icon type-icon">{{ngModel.selected.glyph}}</span>
|
||||||
<span>{{ngModel.selected.name}}</span>
|
<span class="name">{{ngModel.selected.name}}</span>
|
||||||
<span class='ui-symbol icon invoke-menu'>v</span>
|
<span class='ui-symbol invoke-menu'>v</span>
|
||||||
|
|
||||||
|
|
||||||
<div class="menu dropdown" ng-show="toggle.isActive()">
|
<div class="menu dropdown" ng-show="toggle.isActive()">
|
||||||
<ul>
|
<ul>
|
||||||
<li ng-repeat="option in view">
|
<li ng-repeat="option in view">
|
||||||
<a href="" ng-click="ngModel.selected = option; toggle.setState(false)">
|
<a ng-click="ngModel.selected = option; toggle.setState(false)">
|
||||||
<span class="ui-symbol type-icon icon">
|
<span class="ui-symbol type-icon icon">{{option.glyph}}</span>
|
||||||
{{option.glyph}}
|
|
||||||
</span>
|
|
||||||
{{option.name}}
|
{{option.name}}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@ -53,13 +53,15 @@ define(
|
|||||||
|
|
||||||
// Get list of views, read from capability
|
// Get list of views, read from capability
|
||||||
function updateOptions(views) {
|
function updateOptions(views) {
|
||||||
|
if (Array.isArray(views)) {
|
||||||
$timeout(function () {
|
$timeout(function () {
|
||||||
$scope.ngModel.selected = findMatchingOption(
|
$scope.ngModel.selected = findMatchingOption(
|
||||||
views || [],
|
views,
|
||||||
($scope.ngModel || {}).selected
|
($scope.ngModel || {}).selected
|
||||||
);
|
);
|
||||||
}, 0);
|
}, 0);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Update view options when the in-scope results of using the
|
// Update view options when the in-scope results of using the
|
||||||
// view capability change.
|
// view capability change.
|
||||||
|
@ -1,20 +1,50 @@
|
|||||||
{
|
{
|
||||||
"extensions": {
|
"extensions": {
|
||||||
"types": [
|
"templates": [
|
||||||
{
|
{
|
||||||
"key": "infobubble",
|
"key": "info-table",
|
||||||
"name": "Info Bubble",
|
"templateUrl": "info-table.html"
|
||||||
"glyph": "\u00EA",
|
},
|
||||||
"description": "Static markup for info bubbles",
|
{
|
||||||
"features": [ "creation" ]
|
"key": "info-bubble",
|
||||||
|
"templateUrl": "info-bubble.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"views": [
|
"containers": [
|
||||||
{
|
{
|
||||||
"templateUrl": "infobubble.html",
|
"key": "bubble",
|
||||||
"name": "Info Bubble",
|
"templateUrl": "bubble.html",
|
||||||
"type": "infobubble",
|
"attributes": [ "bubbleTitle", "bubbleLayout" ],
|
||||||
"key": "infobubble"
|
"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
|
* this source code distribution or the Licensing information page available
|
||||||
* at runtime from the About dialog for additional information.
|
* at runtime from the About dialog for additional information.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
@import "compass";
|
/*global define*/
|
||||||
@import "compass/css3";
|
define({
|
||||||
@import "compass/css3/border-radius";
|
BUBBLE_TEMPLATE: "<mct-container key=\"bubble\" " +
|
||||||
@import "compass/css3/opacity";
|
"bubble-title=\"{{bubbleTitle}}\" " +
|
||||||
@import "compass/utilities";
|
"bubble-layout=\"{{bubbleLayout}}\" " +
|
||||||
|
"class=\"bubble-container\">" +
|
||||||
@import "constants";
|
"<mct-include key=\"bubbleTemplate\" ng-model=\"bubbleModel\">" +
|
||||||
@import "mixins";
|
"</mct-include>" +
|
||||||
@import "plots/plots-main";
|
"</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",
|
"implementation": "CompositionMutabilityPolicy.js",
|
||||||
"message": "Objects of this type cannot be modified."
|
"message": "Objects of this type cannot be modified."
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"category": "composition",
|
||||||
|
"implementation": "CompositionModelPolicy.js",
|
||||||
|
"message": "Objects of this type cannot contain other objects."
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"category": "action",
|
"category": "action",
|
||||||
"implementation": "ComposeActionPolicy.js",
|
"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();
|
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();
|
expect(policy.allow(mockType)).toBeFalsy();
|
||||||
mockType.hasFeature.andReturn(true);
|
mockType.hasFeature.andReturn(true);
|
||||||
expect(policy.allow(mockType)).toBeTruthy();
|
expect(policy.allow(mockType)).toBeTruthy();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
[
|
[
|
||||||
"CapabilityTable",
|
"CapabilityTable",
|
||||||
"ComposeActionPolicy",
|
"ComposeActionPolicy",
|
||||||
|
"CompositionModelPolicy",
|
||||||
"CompositionMutabilityPolicy",
|
"CompositionMutabilityPolicy",
|
||||||
"CompositionPolicy",
|
"CompositionPolicy",
|
||||||
"ContainmentTable"
|
"ContainmentTable"
|
||||||
|
@ -176,6 +176,10 @@
|
|||||||
"implementation": "capabilities/PersistenceCapability.js",
|
"implementation": "capabilities/PersistenceCapability.js",
|
||||||
"depends": [ "persistenceService", "PERSISTENCE_SPACE" ]
|
"depends": [ "persistenceService", "PERSISTENCE_SPACE" ]
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"key": "metadata",
|
||||||
|
"implementation": "capabilities/MetadataCapability.js"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"key": "mutation",
|
"key": "mutation",
|
||||||
"implementation": "capabilities/MutationCapability.js",
|
"implementation": "capabilities/MutationCapability.js",
|
||||||
@ -191,6 +195,11 @@
|
|||||||
{
|
{
|
||||||
"key": "now",
|
"key": "now",
|
||||||
"implementation": "services/Now.js"
|
"implementation": "services/Now.js"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"key": "throttle",
|
||||||
|
"implementation": "services/Throttle.js",
|
||||||
|
"depends": [ "$timeout" ]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"roots": [
|
"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
|
// Get the object's model and clone it, so the
|
||||||
// mutator function has a temporary copy to work with.
|
// mutator function has a temporary copy to work with.
|
||||||
var model = domainObject.getModel(),
|
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 to handle copying values to the actual
|
||||||
function handleMutation(mutationResult) {
|
function handleMutation(mutationResult) {
|
||||||
@ -94,8 +95,7 @@ define(
|
|||||||
if (model !== result) {
|
if (model !== result) {
|
||||||
copyValues(model, result);
|
copyValues(model, result);
|
||||||
}
|
}
|
||||||
model.modified = (typeof timestamp === 'number') ?
|
model.modified = useTimestamp ? timestamp : now();
|
||||||
timestamp : now();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Report the result of the mutation
|
// 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/ContextualDomainObject",
|
||||||
"capabilities/CoreCapabilityProvider",
|
"capabilities/CoreCapabilityProvider",
|
||||||
"capabilities/DelegationCapability",
|
"capabilities/DelegationCapability",
|
||||||
|
"capabilities/MetadataCapability",
|
||||||
"capabilities/MutationCapability",
|
"capabilities/MutationCapability",
|
||||||
"capabilities/PersistenceCapability",
|
"capabilities/PersistenceCapability",
|
||||||
"capabilities/RelationshipCapability",
|
"capabilities/RelationshipCapability",
|
||||||
@ -23,6 +24,7 @@
|
|||||||
"objects/DomainObjectProvider",
|
"objects/DomainObjectProvider",
|
||||||
|
|
||||||
"services/Now",
|
"services/Now",
|
||||||
|
"services/Throttle",
|
||||||
|
|
||||||
"types/MergeModels",
|
"types/MergeModels",
|
||||||
"types/TypeCapability",
|
"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