mirror of
https://github.com/nasa/openmct.git
synced 2024-12-23 23:12:23 +00:00
Merge branch 'open-master' into open1223
Conflicts: platform/features/plot/res/templates/plot.html
This commit is contained in:
commit
3b62add011
3
.gitignore
vendored
3
.gitignore
vendored
@ -17,3 +17,6 @@ target
|
||||
# Closed source libraries
|
||||
closed-lib
|
||||
|
||||
# Node dependencies
|
||||
node_modules
|
||||
|
||||
|
62
app.js
Normal file
62
app.js
Normal file
@ -0,0 +1,62 @@
|
||||
/*global require,process,console*/
|
||||
|
||||
/**
|
||||
* Usage:
|
||||
*
|
||||
* npm install minimist express
|
||||
* node app.js [options]
|
||||
*/
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var BUNDLE_FILE = 'bundles.json',
|
||||
options = require('minimist')(process.argv.slice(2)),
|
||||
express = require('express'),
|
||||
app = express(),
|
||||
fs = require('fs'),
|
||||
bundles = JSON.parse(fs.readFileSync(BUNDLE_FILE, 'utf8'));
|
||||
|
||||
// Defaults
|
||||
options.port = options.port || options.p || 8080;
|
||||
['include', 'exclude', 'i', 'x'].forEach(function (opt) {
|
||||
options[opt] = options[opt] || [];
|
||||
// Make sure includes/excludes always end up as arrays
|
||||
options[opt] = Array.isArray(options[opt]) ?
|
||||
options[opt] : [options[opt]];
|
||||
});
|
||||
options.include = options.include.concat(options.i);
|
||||
options.exclude = options.exclude.concat(options.x);
|
||||
|
||||
// Show command line options
|
||||
if (options.help || options.h) {
|
||||
console.log("\nUsage: node app.js [options]\n");
|
||||
console.log("Options:");
|
||||
console.log(" --help, -h Show this message.");
|
||||
console.log(" --port, -p <number> Specify port.");
|
||||
console.log(" --include, -i <bundle> Include the specified bundle.");
|
||||
console.log(" --exclude, -x <bundle> Exclude the specified bundle.");
|
||||
console.log("");
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Handle command line inclusions/exclusions
|
||||
bundles = bundles.concat(options.include);
|
||||
bundles = bundles.filter(function (bundle) {
|
||||
return options.exclude.indexOf(bundle) === -1;
|
||||
});
|
||||
bundles = bundles.filter(function (bundle, index) { // Uniquify
|
||||
return bundles.indexOf(bundle) === index;
|
||||
});
|
||||
|
||||
// Override bundles.json for HTTP requests
|
||||
app.use('/' + BUNDLE_FILE, function (req, res) {
|
||||
res.send(JSON.stringify(bundles));
|
||||
});
|
||||
|
||||
// Expose everything else as static files
|
||||
app.use(express['static']('.'));
|
||||
|
||||
// Finally, open the HTTP server
|
||||
app.listen(options.port);
|
||||
}());
|
@ -7,6 +7,7 @@
|
||||
"platform/commonUI/edit",
|
||||
"platform/commonUI/dialog",
|
||||
"platform/commonUI/general",
|
||||
"platform/commonUI/inspect",
|
||||
"platform/containment",
|
||||
"platform/telemetry",
|
||||
"platform/features/layout",
|
||||
@ -15,8 +16,8 @@
|
||||
"platform/features/scrolling",
|
||||
"platform/forms",
|
||||
"platform/persistence/queue",
|
||||
"platform/persistence/elastic",
|
||||
"platform/policy",
|
||||
|
||||
"example/persistence",
|
||||
"example/generator"
|
||||
]
|
||||
|
@ -57,7 +57,8 @@
|
||||
{
|
||||
"key": "grid-item",
|
||||
"templateUrl": "templates/items/grid-item.html",
|
||||
"uses": [ "type", "action" ]
|
||||
"uses": [ "type", "action" ],
|
||||
"gestures": [ "info", "menu" ]
|
||||
},
|
||||
{
|
||||
"key": "object-header",
|
||||
@ -121,6 +122,12 @@
|
||||
"depends": [ "typeService", "dialogService", "creationService", "policyService" ]
|
||||
}
|
||||
],
|
||||
"runs": [
|
||||
{
|
||||
"implementation": "windowing/WindowTitler.js",
|
||||
"depends": [ "navigationService", "$rootScope", "$document" ]
|
||||
}
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"name": "screenfull.js",
|
||||
|
@ -21,14 +21,12 @@
|
||||
-->
|
||||
<span>
|
||||
<div class="object-browse-bar bar abs">
|
||||
|
||||
<div class="items-select left abs">
|
||||
<mct-representation key="'object-header'" mct-object="domainObject">
|
||||
</mct-representation>
|
||||
</div>
|
||||
|
||||
<div class="view-controls sort-controls btn-bar right abs">
|
||||
|
||||
<div class="btn-bar right abs">
|
||||
<mct-representation key="'action-group'"
|
||||
mct-object="domainObject"
|
||||
parameters="{ category: 'view-control' }">
|
||||
@ -39,7 +37,6 @@
|
||||
ng-model="representation">
|
||||
</mct-representation>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class='object-holder abs vscroll'>
|
||||
|
@ -20,9 +20,11 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class='object-header'>
|
||||
<span class='type-icon icon ui-symbol'>{{type.getGlyph()}}</span>
|
||||
<span ng-if="parameters.mode" class='action'>{{parameters.mode}}</span>
|
||||
<span class='type'>{{type.getName()}}</span>
|
||||
<span class='title'>{{model.name}}</span>
|
||||
<a id='actions-menu' class='ui-symbol invoke-menu' onclick="alert('Not yet functional. This will display a dropdown menu of options for this object.');">v</a>
|
||||
<span class="label s-label">
|
||||
<span class='type-icon icon ui-symbol'>{{type.getGlyph()}}</span>
|
||||
<span ng-if="parameters.mode" class='action'>{{parameters.mode}}</span>
|
||||
<span class='type-name'>{{type.getName()}}</span>
|
||||
<span class='title-label'>{{model.name}}</span>
|
||||
<!--a id='actions-menu' class='ui-symbol context-available' onclick="alert('Not yet functional. This will display a dropdown menu of options for this object.');">v</a-->
|
||||
</span>
|
||||
</div>
|
@ -21,7 +21,7 @@
|
||||
-->
|
||||
<div class="menu-element wrapper" ng-controller="ClickAwayController as createController">
|
||||
<div class="btn btn-menu create-btn major" ng-click="createController.toggle()">
|
||||
<span class='ui-symbol major' href=''>+</span> Create<!--span class='ui-symbol invoke-menu'>v</span-->
|
||||
<span class='ui-symbol' href=''>+</span> Create
|
||||
</div>
|
||||
<div class="menu dropdown super-menu" ng-show="createController.isActive()">
|
||||
<mct-representation mct-object="domainObject" key="'create-menu'">
|
||||
|
@ -46,6 +46,7 @@ define(
|
||||
function setNavigation(domainObject) {
|
||||
$scope.navigatedObject = domainObject;
|
||||
$scope.treeModel.selectedObject = domainObject;
|
||||
navigationService.setNavigation(domainObject);
|
||||
}
|
||||
|
||||
// Load the root object, put it in the scope.
|
||||
|
@ -45,8 +45,9 @@ define(
|
||||
properties = type.getProperties();
|
||||
|
||||
function validateLocation(locatingObject) {
|
||||
var locatingType = locatingObject.getCapability('type');
|
||||
return policyService.allow(
|
||||
var locatingType = locatingObject &&
|
||||
locatingObject.getCapability('type');
|
||||
return locatingType && policyService.allow(
|
||||
"composition",
|
||||
locatingType,
|
||||
type
|
||||
|
@ -77,7 +77,19 @@ define(
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return parentPersistence.persist();
|
||||
return parentPersistence.persist().then(function () {
|
||||
// Locate and return new Object in context of parent.
|
||||
return parent
|
||||
.useCapability('composition')
|
||||
.then(function (children) {
|
||||
var i;
|
||||
for (i = 0; i < children.length; i += 1) {
|
||||
if (children[i].getId() === id) {
|
||||
return children[i];
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -45,10 +45,12 @@ define(
|
||||
|
||||
// Setter for navigation; invokes callbacks
|
||||
function setNavigation(value) {
|
||||
navigated = value;
|
||||
callbacks.forEach(function (callback) {
|
||||
callback(value);
|
||||
});
|
||||
if (navigated !== value) {
|
||||
navigated = value;
|
||||
callbacks.forEach(function (callback) {
|
||||
callback(value);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Adds a callback
|
||||
|
52
platform/commonUI/browse/src/windowing/WindowTitler.js
Normal file
52
platform/commonUI/browse/src/windowing/WindowTitler.js
Normal file
@ -0,0 +1,52 @@
|
||||
/*****************************************************************************
|
||||
* 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";
|
||||
|
||||
/**
|
||||
* Updates the title of the current window to reflect the name
|
||||
* of the currently navigated-to domain object.
|
||||
* @constructor
|
||||
*/
|
||||
function WindowTitler(navigationService, $rootScope, $document) {
|
||||
// Look up name of the navigated domain object...
|
||||
function getNavigatedObjectName() {
|
||||
var navigatedObject = navigationService.getNavigation();
|
||||
return navigatedObject && navigatedObject.getModel().name;
|
||||
}
|
||||
|
||||
// Set the window title...
|
||||
function setTitle(name) {
|
||||
$document[0].title = name;
|
||||
}
|
||||
|
||||
// Watch the former, and invoke the latter
|
||||
$rootScope.$watch(getNavigatedObjectName, setTitle);
|
||||
}
|
||||
|
||||
return WindowTitler;
|
||||
}
|
||||
);
|
@ -34,8 +34,10 @@ define(
|
||||
mockQ,
|
||||
mockLog,
|
||||
mockParentObject,
|
||||
mockNewObject,
|
||||
mockMutationCapability,
|
||||
mockPersistenceCapability,
|
||||
mockCompositionCapability,
|
||||
mockCapabilities,
|
||||
creationService;
|
||||
|
||||
@ -69,6 +71,10 @@ define(
|
||||
"parentObject",
|
||||
[ "getId", "getCapability", "useCapability" ]
|
||||
);
|
||||
mockNewObject = jasmine.createSpyObj(
|
||||
"newObject",
|
||||
[ "getId" ]
|
||||
);
|
||||
mockMutationCapability = jasmine.createSpyObj(
|
||||
"mutation",
|
||||
[ "invoke" ]
|
||||
@ -77,9 +83,14 @@ define(
|
||||
"persistence",
|
||||
[ "persist", "getSpace" ]
|
||||
);
|
||||
mockCompositionCapability = jasmine.createSpyObj(
|
||||
"composition",
|
||||
["invoke"]
|
||||
);
|
||||
mockCapabilities = {
|
||||
mutation: mockMutationCapability,
|
||||
persistence: mockPersistenceCapability
|
||||
persistence: mockPersistenceCapability,
|
||||
composition: mockCompositionCapability
|
||||
};
|
||||
|
||||
mockPersistenceService.createObject.andReturn(
|
||||
@ -93,8 +104,15 @@ define(
|
||||
return mockCapabilities[key].invoke(value);
|
||||
});
|
||||
|
||||
mockPersistenceCapability.persist.andReturn(
|
||||
mockPromise(true)
|
||||
);
|
||||
|
||||
mockMutationCapability.invoke.andReturn(mockPromise(true));
|
||||
mockPersistenceCapability.getSpace.andReturn("testSpace");
|
||||
mockCompositionCapability.invoke.andReturn(
|
||||
mockPromise([mockNewObject])
|
||||
);
|
||||
|
||||
creationService = new CreationService(
|
||||
mockPersistenceService,
|
||||
|
@ -62,6 +62,16 @@ define(
|
||||
expect(callback).toHaveBeenCalledWith(testObject);
|
||||
});
|
||||
|
||||
it("does not notify listeners when no changes occur", function () {
|
||||
var testObject = { someKey: 42 },
|
||||
callback = jasmine.createSpy("callback");
|
||||
|
||||
navigationService.addListener(callback);
|
||||
navigationService.setNavigation(testObject);
|
||||
navigationService.setNavigation(testObject);
|
||||
expect(callback.calls.length).toEqual(1);
|
||||
});
|
||||
|
||||
it("stops notifying listeners after removal", function () {
|
||||
var testObject = { someKey: 42 },
|
||||
callback = jasmine.createSpy("callback");
|
||||
|
@ -8,5 +8,6 @@
|
||||
"creation/LocatorController",
|
||||
"navigation/NavigateAction",
|
||||
"navigation/NavigationService",
|
||||
"windowing/FullscreenAction"
|
||||
"windowing/FullscreenAction",
|
||||
"windowing/WindowTitler"
|
||||
]
|
80
platform/commonUI/browse/test/windowing/WindowTitlerSpec.js
Normal file
80
platform/commonUI/browse/test/windowing/WindowTitlerSpec.js
Normal file
@ -0,0 +1,80 @@
|
||||
/*****************************************************************************
|
||||
* 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*/
|
||||
|
||||
/**
|
||||
* WindowTitlerSpec. Created by vwoeltje on 11/6/14.
|
||||
*/
|
||||
define(
|
||||
["../../src/windowing/WindowTitler"],
|
||||
function (WindowTitler) {
|
||||
"use strict";
|
||||
|
||||
describe("The window titler", function () {
|
||||
var mockNavigationService,
|
||||
mockRootScope,
|
||||
mockDocument,
|
||||
mockDomainObject,
|
||||
titler;
|
||||
|
||||
beforeEach(function () {
|
||||
mockNavigationService = jasmine.createSpyObj(
|
||||
'navigationService',
|
||||
[ 'getNavigation' ]
|
||||
);
|
||||
mockRootScope = jasmine.createSpyObj(
|
||||
'$rootScope',
|
||||
[ '$watch' ]
|
||||
);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
['getModel']
|
||||
);
|
||||
mockDocument = [{}];
|
||||
|
||||
mockDomainObject.getModel.andReturn({ name: 'Test name' });
|
||||
mockNavigationService.getNavigation.andReturn(mockDomainObject);
|
||||
|
||||
titler = new WindowTitler(
|
||||
mockNavigationService,
|
||||
mockRootScope,
|
||||
mockDocument
|
||||
);
|
||||
});
|
||||
|
||||
it("listens for changes to the name of the navigated object", function () {
|
||||
expect(mockRootScope.$watch).toHaveBeenCalledWith(
|
||||
jasmine.any(Function),
|
||||
jasmine.any(Function)
|
||||
);
|
||||
expect(mockRootScope.$watch.mostRecentCall.args[0]())
|
||||
.toEqual('Test name');
|
||||
});
|
||||
|
||||
it("sets the title to the name of the navigated object", function () {
|
||||
mockRootScope.$watch.mostRecentCall.args[1]("Some name");
|
||||
expect(mockDocument[0].title).toEqual("Some name");
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -25,7 +25,7 @@
|
||||
<a href=""
|
||||
ng-click="ngModel.cancel()"
|
||||
ng-if="ngModel.cancel"
|
||||
class="btn normal outline ui-symbol close">
|
||||
class="btn normal ui-symbol close">
|
||||
x
|
||||
</a>
|
||||
<div class="abs contents" ng-transclude>
|
||||
|
@ -33,8 +33,6 @@
|
||||
<mct-representation key="'edit-action-buttons'"
|
||||
mct-object="domainObject"
|
||||
class='conclude-editing'>
|
||||
<!--a class='btn major' href=''>Save<span id='save-actions-menu' class='ui-symbol invoke-menu'>v</span></a>
|
||||
<a class='btn subtle' href=''>Cancel</a-->
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
@ -181,7 +181,7 @@
|
||||
"key": "label",
|
||||
"templateUrl": "templates/label.html",
|
||||
"uses": [ "type" ],
|
||||
"gestures": [ "drag", "menu" ]
|
||||
"gestures": [ "drag", "menu", "info" ]
|
||||
},
|
||||
{
|
||||
"key": "node",
|
||||
|
@ -61,6 +61,15 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
||||
$c: $baseColor;
|
||||
color: $c;
|
||||
&:hover {
|
||||
color: lighten($c, $ltGamma);
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -186,9 +195,9 @@
|
||||
color: #666666; }
|
||||
/* line 116, ../sass/forms/_elems.scss */
|
||||
.form .form-row .selector-list {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
@ -225,9 +234,9 @@ label.form-control.checkbox input {
|
||||
vertical-align: top; }
|
||||
/* line 159, ../sass/forms/_elems.scss */
|
||||
.l-result div.s-hint {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
background: rgba(255, 153, 0, 0.8);
|
||||
display: block;
|
||||
color: #ffd699;
|
||||
@ -258,9 +267,9 @@ label.form-control.checkbox input {
|
||||
.edit-main textarea {
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
@ -302,13 +311,12 @@ label.form-control.checkbox input {
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/* line 22, ../sass/forms/_text-input.scss */
|
||||
input[type="text"],
|
||||
input[type="date"] {
|
||||
input[type="text"] {
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
@ -322,32 +330,10 @@ input[type="date"] {
|
||||
outline: none;
|
||||
padding: 0 3px; }
|
||||
/* line 33, ../sass/forms/_mixins.scss */
|
||||
input[type="text"].error,
|
||||
input[type="date"].error {
|
||||
input[type="text"].error {
|
||||
background: rgba(255, 0, 0, 0.5); }
|
||||
/* line 61, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
|
||||
input[type="text"]:-moz-placeholder,
|
||||
input[type="date"]:-moz-placeholder {
|
||||
color: gray;
|
||||
font-style: italic; }
|
||||
/* line 64, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
|
||||
input[type="text"]::-moz-placeholder,
|
||||
input[type="date"]::-moz-placeholder {
|
||||
color: gray;
|
||||
font-style: italic; }
|
||||
/* line 67, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
|
||||
input[type="text"]:-ms-input-placeholder,
|
||||
input[type="date"]:-ms-input-placeholder {
|
||||
color: gray;
|
||||
font-style: italic; }
|
||||
/* line 56, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/css3/_user-interface.scss */
|
||||
input[type="text"]::-webkit-input-placeholder,
|
||||
input[type="date"]::-webkit-input-placeholder {
|
||||
color: gray;
|
||||
font-style: italic; }
|
||||
/* line 34, ../sass/forms/_text-input.scss */
|
||||
input[type="text"].numeric,
|
||||
input[type="date"].numeric {
|
||||
/* line 29, ../sass/forms/_text-input.scss */
|
||||
input[type="text"].numeric {
|
||||
text-align: right; }
|
||||
|
||||
/*****************************************************************************
|
||||
@ -373,23 +359,23 @@ input[type="date"] {
|
||||
*****************************************************************************/
|
||||
/* line 22, ../sass/forms/_selects.scss */
|
||||
.form-control.select {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzRkNGQ0ZCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzQwNDA0MCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzUyNTI1MiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzQ1NDU0NSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #4d4d4d), color-stop(100%, #404040));
|
||||
background-image: -moz-linear-gradient(#4d4d4d, #404040);
|
||||
background-image: -webkit-linear-gradient(#4d4d4d, #404040);
|
||||
background-image: linear-gradient(#4d4d4d, #404040);
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #525252), color-stop(100%, #454545));
|
||||
background-image: -moz-linear-gradient(#525252, #454545);
|
||||
background-image: -webkit-linear-gradient(#525252, #454545);
|
||||
background-image: linear-gradient(#525252, #454545);
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
border: none;
|
||||
border-top: 1px solid #666666;
|
||||
border-top: 1px solid #575757;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
@ -397,14 +383,21 @@ input[type="date"] {
|
||||
margin: 0 0 2px 2px;
|
||||
overflow: hidden;
|
||||
position: relative; }
|
||||
/* line 148, ../sass/_mixins.scss */
|
||||
/* line 152, ../sass/_mixins.scss */
|
||||
.form-control.select:not(.disabled):hover {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzY2NjY2NiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzRkNGQ0ZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU3NTc1NyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #666666), color-stop(100%, #4d4d4d));
|
||||
background-image: -moz-linear-gradient(#666666, #4d4d4d);
|
||||
background-image: -webkit-linear-gradient(#666666, #4d4d4d);
|
||||
background-image: linear-gradient(#666666, #4d4d4d); }
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #636363), color-stop(100%, #575757));
|
||||
background-image: -moz-linear-gradient(#636363, #575757);
|
||||
background-image: -webkit-linear-gradient(#636363, #575757);
|
||||
background-image: linear-gradient(#636363, #575757);
|
||||
color: #bdbdbd; }
|
||||
/* line 155, ../sass/_mixins.scss */
|
||||
.form-control.select:not(.disabled):hover.btn-menu .invoke-menu {
|
||||
color: #878787; }
|
||||
/* line 160, ../sass/_mixins.scss */
|
||||
.form-control.select.btn-menu .invoke-menu {
|
||||
color: #757575; }
|
||||
/* line 29, ../sass/forms/_selects.scss */
|
||||
.form-control.select select {
|
||||
-moz-appearance: none;
|
||||
@ -461,9 +454,9 @@ input[type="date"] {
|
||||
.channel-selector .treeview {
|
||||
-moz-appearance: none;
|
||||
-webkit-appearance: none;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
|
@ -61,6 +61,15 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
||||
$c: $baseColor;
|
||||
color: $c;
|
||||
&:hover {
|
||||
color: lighten($c, $ltGamma);
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -92,23 +101,23 @@
|
||||
top: 0; }
|
||||
/* line 29, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzU5NTk1OSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzRkNGQ0ZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzVlNWU1ZSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzUyNTI1MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #595959), color-stop(100%, #4d4d4d));
|
||||
background-image: -moz-linear-gradient(#595959, #4d4d4d);
|
||||
background-image: -webkit-linear-gradient(#595959, #4d4d4d);
|
||||
background-image: linear-gradient(#595959, #4d4d4d);
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #5e5e5e), color-stop(100%, #525252));
|
||||
background-image: -moz-linear-gradient(#5e5e5e, #525252);
|
||||
background-image: -webkit-linear-gradient(#5e5e5e, #525252);
|
||||
background-image: linear-gradient(#5e5e5e, #525252);
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
border: none;
|
||||
border-top: 1px solid #737373;
|
||||
border-top: 1px solid #636363;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
@ -119,14 +128,21 @@
|
||||
margin-bottom: 3px;
|
||||
margin-right: 3px;
|
||||
position: relative; }
|
||||
/* line 148, ../sass/_mixins.scss */
|
||||
/* line 152, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item:not(.disabled):hover {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzczNzM3MyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzU5NTk1OSIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzcwNzA3MCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzYzNjM2MyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #737373), color-stop(100%, #595959));
|
||||
background-image: -moz-linear-gradient(#737373, #595959);
|
||||
background-image: -webkit-linear-gradient(#737373, #595959);
|
||||
background-image: linear-gradient(#737373, #595959); }
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #707070), color-stop(100%, #636363));
|
||||
background-image: -moz-linear-gradient(#707070, #636363);
|
||||
background-image: -webkit-linear-gradient(#707070, #636363);
|
||||
background-image: linear-gradient(#707070, #636363);
|
||||
color: #bdbdbd; }
|
||||
/* line 155, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item:not(.disabled):hover.btn-menu .invoke-menu {
|
||||
color: #949494; }
|
||||
/* line 160, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.btn-menu .invoke-menu {
|
||||
color: #828282; }
|
||||
/* line 42, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item:hover .item-main .item-type {
|
||||
color: #0099cc !important; }
|
||||
@ -184,40 +200,41 @@
|
||||
font-size: 0.8em; }
|
||||
/* line 104, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwYmZmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwYWNlNiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzBhYzJmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwYjRmMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #00bfff), color-stop(100%, #00ace6));
|
||||
background-image: -moz-linear-gradient(#00bfff, #00ace6);
|
||||
background-image: -webkit-linear-gradient(#00bfff, #00ace6);
|
||||
background-image: linear-gradient(#00bfff, #00ace6);
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #0ac2ff), color-stop(100%, #00b4f0));
|
||||
background-image: -moz-linear-gradient(#0ac2ff, #00b4f0);
|
||||
background-image: -webkit-linear-gradient(#0ac2ff, #00b4f0);
|
||||
background-image: linear-gradient(#0ac2ff, #00b4f0);
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
box-shadow: rgba(0, 0, 0, 0.3) 0 1px 3px;
|
||||
-moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
-webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
|
||||
border: none;
|
||||
border-top: 1px solid #33ccff;
|
||||
border-top: 1px solid #14c4ff;
|
||||
color: #999;
|
||||
display: inline-block;
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzMzY2NmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwOTljYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #33ccff), color-stop(100%, #0099cc));
|
||||
background-image: -moz-linear-gradient(#33ccff, #0099cc);
|
||||
background-image: -webkit-linear-gradient(#33ccff, #0099cc);
|
||||
background-image: linear-gradient(#33ccff, #0099cc);
|
||||
color: #80dfff; }
|
||||
/* line 156, ../sass/_mixins.scss */
|
||||
/* line 152, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.selected:not(.disabled):hover {
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzY2ZDlmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwYmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzJlY2JmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzE0YzRmZiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
|
||||
background-size: 100%;
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #66d9ff), color-stop(100%, #00bfff));
|
||||
background-image: -moz-linear-gradient(#66d9ff, #00bfff);
|
||||
background-image: -webkit-linear-gradient(#66d9ff, #00bfff);
|
||||
background-image: linear-gradient(#66d9ff, #00bfff); }
|
||||
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #2ecbff), color-stop(100%, #14c4ff));
|
||||
background-image: -moz-linear-gradient(#2ecbff, #14c4ff);
|
||||
background-image: -webkit-linear-gradient(#2ecbff, #14c4ff);
|
||||
background-image: linear-gradient(#2ecbff, #14c4ff);
|
||||
color: #bdbdbd; }
|
||||
/* line 155, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.selected:not(.disabled):hover.btn-menu .invoke-menu {
|
||||
color: #75ddff; }
|
||||
/* line 160, ../sass/_mixins.scss */
|
||||
.items-holder .item.grid-item.selected.btn-menu .invoke-menu {
|
||||
color: #52d4ff; }
|
||||
/* line 109, ../sass/items/_item.scss */
|
||||
.items-holder .item.grid-item.selected .item-type, .items-holder .item.grid-item.selected .top-bar .icon:not(.alert) {
|
||||
color: #80dfff; }
|
||||
|
@ -1,350 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/* line 31, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot {
|
||||
color: #999;
|
||||
font-size: 0.7rem;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
/****************************** Limits and Out-of-Bounds data */ }
|
||||
/* line 38, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-axis-area {
|
||||
position: absolute; }
|
||||
/* line 41, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-axis-area.gl-plot-x {
|
||||
top: auto;
|
||||
right: 0;
|
||||
bottom: 5px;
|
||||
left: 60px;
|
||||
height: 32px;
|
||||
width: auto;
|
||||
overflow: hidden; }
|
||||
/* line 50, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-axis-area.gl-plot-y {
|
||||
top: 29px;
|
||||
right: auto;
|
||||
bottom: 37px;
|
||||
left: 0;
|
||||
width: 60px; }
|
||||
/* line 59, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-coords {
|
||||
-moz-box-sizing: border-box;
|
||||
-webkit-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background: black;
|
||||
color: #e6e6e6;
|
||||
padding: 2px 5px;
|
||||
position: absolute;
|
||||
top: 39px;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: 70px;
|
||||
z-index: 10; }
|
||||
/* line 71, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-coords:empty {
|
||||
display: none; }
|
||||
/* line 76, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-display-area {
|
||||
position: absolute;
|
||||
top: 29px;
|
||||
right: 0;
|
||||
bottom: 37px;
|
||||
left: 60px;
|
||||
cursor: crosshair;
|
||||
border: 1px solid #4d4d4d; }
|
||||
/* line 86, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-label,
|
||||
.gl-plot .l-plot-label {
|
||||
color: #cccccc;
|
||||
position: absolute;
|
||||
text-align: center; }
|
||||
/* line 94, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-label.gl-plot-x-label, .gl-plot .gl-plot-label.l-plot-x-label,
|
||||
.gl-plot .l-plot-label.gl-plot-x-label,
|
||||
.gl-plot .l-plot-label.l-plot-x-label {
|
||||
top: auto;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
height: auto; }
|
||||
/* line 103, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-label.gl-plot-y-label, .gl-plot .gl-plot-label.l-plot-y-label,
|
||||
.gl-plot .l-plot-label.gl-plot-y-label,
|
||||
.gl-plot .l-plot-label.l-plot-y-label {
|
||||
-moz-transform-origin: 50% 0;
|
||||
-ms-transform-origin: 50% 0;
|
||||
-webkit-transform-origin: 50% 0;
|
||||
transform-origin: 50% 0;
|
||||
-moz-transform: translateX(-50%) rotate(-90deg);
|
||||
-ms-transform: translateX(-50%) rotate(-90deg);
|
||||
-webkit-transform: translateX(-50%) rotate(-90deg);
|
||||
transform: translateX(-50%) rotate(-90deg);
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
white-space: nowrap; }
|
||||
/* line 117, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-y-options {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: auto5px;
|
||||
margin-top: -16px;
|
||||
height: auto;
|
||||
min-height: 32px;
|
||||
width: 32px; }
|
||||
/* line 131, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-hash {
|
||||
position: absolute;
|
||||
border: 0 rgba(255, 255, 255, 0.3) dashed; }
|
||||
/* line 134, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-hash.hash-v {
|
||||
border-right-width: 1px;
|
||||
height: 100%; }
|
||||
/* line 138, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-hash.hash-h {
|
||||
border-bottom-width: 1px;
|
||||
width: 100%; }
|
||||
/* line 144, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .gl-plot-legend {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
height: 24px;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto; }
|
||||
/* line 157, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-limit-bar,
|
||||
.gl-plot .l-oob-data {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
width: auto; }
|
||||
/* line 165, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-limit-bar {
|
||||
height: auto;
|
||||
z-index: 0; }
|
||||
/* line 173, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-limit-bar.s-limit-yellow {
|
||||
background: rgba(157, 117, 0, 0.2); }
|
||||
/* line 174, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-limit-bar.s-limit-red {
|
||||
background: rgba(170, 0, 0, 0.2); }
|
||||
/* line 177, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-oob-data {
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
right: 0px;
|
||||
bottom: 0px;
|
||||
left: 0px;
|
||||
width: auto;
|
||||
height: auto;
|
||||
pointer-events: none;
|
||||
height: 10px;
|
||||
z-index: 1; }
|
||||
/* line 185, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-oob-data.l-oob-data-up {
|
||||
top: 0;
|
||||
bottom: auto;
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjEuMCIgeDI9IjAuNSIgeTI9IjAuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzc3NDhkNiIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM3NzQ4ZDYiIHN0b3Atb3BhY2l0eT0iMC41Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
|
||||
background-size: 100%;
|
||||
background-image: -moz-linear-gradient(90deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%);
|
||||
background-image: -webkit-linear-gradient(90deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%);
|
||||
background-image: linear-gradient(0deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%); }
|
||||
/* line 190, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot .l-oob-data.l-oob-data-dwn {
|
||||
bottom: 0;
|
||||
top: auto;
|
||||
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzc3NDhkNiIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiM3NzQ4ZDYiIHN0b3Atb3BhY2l0eT0iMC41Ii8+PC9saW5lYXJHcmFkaWVudD48L2RlZnM+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEwMCUiIGhlaWdodD0iMTAwJSIgZmlsbD0idXJsKCNncmFkKSIgLz48L3N2Zz4g');
|
||||
background-size: 100%;
|
||||
background-image: -moz-linear-gradient(270deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%);
|
||||
background-image: -webkit-linear-gradient(270deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%);
|
||||
background-image: linear-gradient(180deg, rgba(119, 72, 214, 0), rgba(119, 72, 214, 0.5) 100%); }
|
||||
|
||||
/* line 200, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-legend .plot-legend-item,
|
||||
.gl-plot-legend .legend-item,
|
||||
.legend .plot-legend-item,
|
||||
.legend .legend-item {
|
||||
display: inline-block;
|
||||
margin-right: 10px; }
|
||||
/* line 204, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-legend .plot-legend-item span,
|
||||
.gl-plot-legend .legend-item span,
|
||||
.legend .plot-legend-item span,
|
||||
.legend .legend-item span {
|
||||
vertical-align: middle; }
|
||||
/* line 207, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-legend .plot-legend-item .plot-color-swatch,
|
||||
.gl-plot-legend .plot-legend-item .color-swatch,
|
||||
.gl-plot-legend .legend-item .plot-color-swatch,
|
||||
.gl-plot-legend .legend-item .color-swatch,
|
||||
.legend .plot-legend-item .plot-color-swatch,
|
||||
.legend .plot-legend-item .color-swatch,
|
||||
.legend .legend-item .plot-color-swatch,
|
||||
.legend .legend-item .color-swatch {
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
display: inline-block;
|
||||
height: 8px;
|
||||
width: 8px; }
|
||||
|
||||
/* line 220, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-legend .plot-legend-item {
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
color: #fff;
|
||||
line-height: 1.5em;
|
||||
padding: 0px 5px; }
|
||||
/* line 226, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-legend .plot-legend-item .plot-color-swatch {
|
||||
border: 1px solid #333;
|
||||
height: 9px;
|
||||
width: 9px; }
|
||||
|
||||
/* line 234, ../sass/plots/_plots-main.scss */
|
||||
.tick {
|
||||
position: absolute;
|
||||
border: 0 rgba(255, 255, 255, 0.3) solid; }
|
||||
/* line 237, ../sass/plots/_plots-main.scss */
|
||||
.tick.tick-x {
|
||||
border-right-width: 1px;
|
||||
height: 100%; }
|
||||
|
||||
/* line 243, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-tick,
|
||||
.tick-label {
|
||||
font-size: 0.7rem;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis; }
|
||||
/* line 251, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-tick.gl-plot-x-tick-label, .gl-plot-tick.tick-label-x,
|
||||
.tick-label.gl-plot-x-tick-label,
|
||||
.tick-label.tick-label-x {
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
height: auto;
|
||||
width: 20%;
|
||||
margin-left: -10%;
|
||||
text-align: center; }
|
||||
/* line 261, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-tick.gl-plot-y-tick-label, .gl-plot-tick.tick-label-y,
|
||||
.tick-label.gl-plot-y-tick-label,
|
||||
.tick-label.tick-label-y {
|
||||
top: auto;
|
||||
height: 1em;
|
||||
width: auto;
|
||||
margin-bottom: -0.5em;
|
||||
text-align: right; }
|
||||
|
||||
/* line 273, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-tick.gl-plot-x-tick-label {
|
||||
top: 5px; }
|
||||
/* line 276, ../sass/plots/_plots-main.scss */
|
||||
.gl-plot-tick.gl-plot-y-tick-label {
|
||||
right: 5px;
|
||||
left: 5px; }
|
||||
|
||||
/* line 283, ../sass/plots/_plots-main.scss */
|
||||
.tick-label.tick-label-x {
|
||||
top: 0; }
|
||||
/* line 286, ../sass/plots/_plots-main.scss */
|
||||
.tick-label.tick-label-y {
|
||||
right: 0;
|
||||
left: 0; }
|
File diff suppressed because it is too large
Load Diff
@ -61,6 +61,15 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*
|
||||
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
||||
$c: $baseColor;
|
||||
color: $c;
|
||||
&:hover {
|
||||
color: lighten($c, $ltGamma);
|
||||
}
|
||||
}
|
||||
*/
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
@ -86,7 +95,7 @@
|
||||
ul.tree {
|
||||
margin: 0;
|
||||
padding: 0; }
|
||||
/* line 208, ../sass/_mixins.scss */
|
||||
/* line 264, ../sass/_mixins.scss */
|
||||
ul.tree li {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
@ -97,17 +106,17 @@ ul.tree {
|
||||
position: relative; }
|
||||
/* line 27, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item {
|
||||
-moz-border-radius: 3px;
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
-moz-border-radius: 2px;
|
||||
-webkit-border-radius: 2px;
|
||||
border-radius: 2px;
|
||||
-moz-transition: background-color 0.25s;
|
||||
-o-transition: background-color 0.25s;
|
||||
-webkit-transition: background-color 0.25s;
|
||||
transition: background-color 0.25s;
|
||||
display: block;
|
||||
font-size: 0.80rem;
|
||||
height: 1.5rem;
|
||||
line-height: 1.5rem;
|
||||
height: 1.4rem;
|
||||
line-height: 1.4rem;
|
||||
margin-bottom: 3px;
|
||||
position: relative; }
|
||||
/* line 38, ../sass/tree/_tree.scss */
|
||||
@ -168,7 +177,7 @@ ul.tree {
|
||||
width: auto;
|
||||
height: auto;
|
||||
display: block;
|
||||
left: 25px;
|
||||
left: 20px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap; }
|
||||
@ -207,17 +216,16 @@ ul.tree {
|
||||
/* line 125, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item:not(.loading) {
|
||||
cursor: pointer; }
|
||||
/* line 130, ../sass/tree/_tree.scss */
|
||||
/* line 129, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .context-trigger {
|
||||
display: none;
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
right: 3px; }
|
||||
/* line 136, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .context-trigger .btn-invoke-menu {
|
||||
/* line 135, ../sass/tree/_tree.scss */
|
||||
ul.tree li span.tree-item .context-trigger .invoke-menu {
|
||||
font-size: 0.75em;
|
||||
height: 0.9rem;
|
||||
line-height: 0.9rem; }
|
||||
/* line 145, ../sass/tree/_tree.scss */
|
||||
/* line 144, ../sass/tree/_tree.scss */
|
||||
ul.tree ul.tree {
|
||||
margin-left: 15px; }
|
||||
|
Binary file not shown.
@ -2,7 +2,7 @@
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||
<svg>
|
||||
<metadata>
|
||||
Created by FontForge 20090622 at Mon May 4 20:21:42 2015
|
||||
Created by FontForge 20090622 at Tue Jun 9 23:00:40 2015
|
||||
By deploy user
|
||||
Copyright 2015 Adobe Systems Incorporated. All rights reserved.
|
||||
</metadata>
|
||||
@ -62,8 +62,10 @@ q52 -180 95 -231q42 53 88 212z" />
|
||||
d="M193 787v-193h-193v193h193zM193 491v-195h-193v195h193zM193 193v-193h-193v193h193zM671 732v-82h-388v82h388zM671 435v-81h-388v81h388zM671 138v-82h-388v82h388z" />
|
||||
<glyph glyph-name="eight" unicode="8" horiz-adv-x="636"
|
||||
d="M625 735v-318h-625v318h625zM625 315v-315h-625v315h625z" />
|
||||
<glyph glyph-name="nine" unicode="9" horiz-adv-x="636"
|
||||
d="M267 735v-319h-267v319h267zM267 315v-315h-267v315h267zM630 735v-319h-267v319h267zM630 315v-315h-267v315h267z" />
|
||||
<glyph glyph-name="nine" unicode="9"
|
||||
d="M328 469q0 -20 -13.5 -33.5t-33.5 -13.5h-234q-20 0 -33.5 13.5t-13.5 33.5v234q0 19 14 33t33 14h234q20 0 33.5 -13.5t13.5 -33.5v-234zM750 469q0 -20 -13.5 -33.5t-33.5 -13.5h-234q-20 0 -33.5 13.5t-13.5 33.5v234q0 20 13.5 33.5t33.5 13.5h234q19 0 33 -14
|
||||
t14 -33v-234zM328 47q0 -20 -13.5 -33.5t-33.5 -13.5h-234q-19 0 -33 14t-14 33v234q0 20 13.5 33.5t33.5 13.5h234q20 0 33.5 -13.5t13.5 -33.5v-234zM750 47q0 -19 -14 -33t-33 -14h-234q-20 0 -33.5 13.5t-13.5 33.5v234q0 20 13.5 33.5t33.5 13.5h234q20 0 33.5 -13.5
|
||||
t13.5 -33.5v-234z" />
|
||||
<glyph glyph-name="colon" unicode=":" horiz-adv-x="625"
|
||||
d="M625 -19l-397 397l397 397v-794zM173 756v-735h-173v735h173z" />
|
||||
<glyph glyph-name="semicolon" unicode=";" horiz-adv-x="624"
|
||||
@ -163,8 +165,8 @@ d="M123 367l-123 123v147l123 -123l220 221v-147zM123 0l-123 123v147l123 -123l220
|
||||
d="M123 93l-123 123v147l123 -123l220 220v-147zM485 262v71h313v-71h-313z" />
|
||||
<glyph glyph-name="l" unicode="l" horiz-adv-x="617"
|
||||
d="M551 386h66v-386h-617v386h63v106q0 100 72 171.5t173 71.5q99 0 171 -71.5t72 -171.5v-106zM173 492v-106h267v106q0 56 -38.5 94.5t-93.5 38.5q-56 0 -95.5 -39t-39.5 -94z" />
|
||||
<glyph glyph-name="m" unicode="m" horiz-adv-x="804"
|
||||
d="M804 729v-156h-804v156h804zM804 445v-160h-804v160h804zM804 158v-158h-804v158h804z" />
|
||||
<glyph glyph-name="m" unicode="m" horiz-adv-x="751"
|
||||
d="M751 563h-751v188h751v-188zM751 282h-751v187h751v-187zM751 0h-751v188h751v-188z" />
|
||||
<glyph glyph-name="n" unicode="n" horiz-adv-x="738"
|
||||
d="M690 697q48 -50 48 -88q0 -18 -10 -26l-243 -243l-3 -3l-4 -2l-227 -78l77 228l2 4l3 3l242 243q22 19 57 3q29 -14 58 -41zM461 371l1 2l-3 50l-34 2h-9v10v28l-51 6l-2 -1l-32 -97l33 -33zM249 512l-134 -389l304 104v-215q-136 -8 -246.5 29t-172.5 93v561
|
||||
q48 -42 125 -75.5t172 -43.5l-24 -25l-17 -17z" />
|
||||
@ -232,6 +234,22 @@ d="M748 750l-375 -750l-374 750h749z" />
|
||||
d="M-1 0l375 750l374 -750h-749z" />
|
||||
<glyph glyph-name="icircumflex" unicode="î" horiz-adv-x="748"
|
||||
d="M748 750l-375 -375l-374 375h749zM748 375l-375 -374l-374 374h749z" />
|
||||
<glyph glyph-name="idieresis" unicode="ï"
|
||||
d="M0 749l750 -375l-750 -374v749z" />
|
||||
<glyph glyph-name="ntilde" unicode="ñ"
|
||||
d="M283 751v-751h-188v751h188zM658 751v-751h-188v751h188z" />
|
||||
<glyph glyph-name="ograve" unicode="ò" horiz-adv-x="751"
|
||||
d="M469 563h-102q-74 0 -126.5 -52.5t-52.5 -126.5v-102h-94q-38 0 -66 27.5t-28 65.5v282q0 38 28 66t66 28h281q39 0 66.5 -28t27.5 -66v-94zM657 469q38 0 66 -27.5t28 -66.5v-281q0 -38 -28 -66t-66 -28h-282q-38 0 -65.5 28t-27.5 66v281q0 39 27.5 66.5t65.5 27.5h282
|
||||
z" />
|
||||
<glyph glyph-name="oacute" unicode="ó" horiz-adv-x="751"
|
||||
d="M216 375l187 -187h-309q-38 0 -66 27.5t-28 66.5v375q0 38 28 66t66 28h375q39 0 66.5 -28t27.5 -66v-309l-188 187zM751 422v-422h-422v94h234l-281 281l93 94l282 -281v234h94z" />
|
||||
<glyph glyph-name="ocircumflex" unicode="ô" horiz-adv-x="751"
|
||||
d="M610 751q58 0 99.5 -41.5t41.5 -99.5v-469q0 -59 -41.5 -100t-99.5 -41h-469q-59 0 -100 41t-41 100v469q0 58 41 99.5t100 41.5h469zM610 282v328h-328l93 -94l-234 -375l375 234z" />
|
||||
<glyph glyph-name="otilde" unicode="õ" horiz-adv-x="657"
|
||||
d="M329 657q136 0 232 -96t96 -232t-96 -232.5t-232 -96.5q-137 0 -233 96t-96 233q0 136 96.5 232t232.5 96zM329 329v246q-101 0 -175 -72zM422 704q0 -20 -13.5 -33.5t-33.5 -13.5h-46h-47q-20 0 -33.5 13.5t-13.5 33.5t13.5 33.5t33.5 13.5h93q20 0 33.5 -13.5
|
||||
t13.5 -33.5z" />
|
||||
<glyph glyph-name="odieresis" unicode="ö"
|
||||
d="M328 562v-375h-328v375h328zM750 562v-375h-328v375h328z" />
|
||||
<glyph glyph-name="fraction" unicode="⁄" horiz-adv-x="761"
|
||||
d="M380 751q158 0 269.5 -111.5t111.5 -268.5q0 -133 -82.5 -236.5t-209.5 -134.5l-4 491l-176 -490q-126 31 -207.5 134.5t-81.5 235.5q0 157 111.5 268.5t268.5 111.5zM168 488l55 20l-34 94l-56 -20zM410 530v100h-59v-100h59zM593 488l34 94l-55 20l-34 -94z" />
|
||||
<glyph glyph-name="H.002" horiz-adv-x="803"
|
||||
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 24 KiB |
Binary file not shown.
Binary file not shown.
@ -19,13 +19,17 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
// Features
|
||||
$enableImageryThumbs: false; // Set to true if historical imagery thumbnails are supported
|
||||
|
||||
// Margins, spacing, radii
|
||||
$bodyMargin: 10px;
|
||||
$interiorMargin: 5px;
|
||||
$interiorMarginLg: $interiorMargin * 2;
|
||||
$interiorMarginSm: 3px;
|
||||
$basicCr: 3px;
|
||||
$controlCr: $basicCr;
|
||||
$basicCr: 2px;
|
||||
$controlCr: 2px;
|
||||
$smallCr: 2px;
|
||||
$badgeW: 35px;
|
||||
|
||||
@ -34,9 +38,12 @@ $colorBodyBg: #333;
|
||||
$colorBodyFg: #999;
|
||||
$colorFooterBg: #000;
|
||||
$colorKey: #0099cc;
|
||||
$colorKeySelectedBg: #005177;
|
||||
$colorKeyFg: #fff;
|
||||
$colorAlt1: #ffc700;
|
||||
$colorAlert: #ff3c00;
|
||||
$colorPausedBg: #c56f01;
|
||||
$colorPausedFg: #fff;
|
||||
$colorCheck: $colorKey;
|
||||
$colorCreateBtn: $colorKey;
|
||||
$colorInteriorBorder: lighten($colorBodyBg, 10%);
|
||||
@ -50,7 +57,18 @@ $colorLimitYellow: #9d7500;
|
||||
$colorLimitRed: #aa0000;
|
||||
$colorTelemFresh: #fff;
|
||||
$colorTelemStale: #888;
|
||||
$styleTelemStale: italic;
|
||||
$colorInfoBubbleFg: #666;
|
||||
$colorInfoBubbleBg: #ddd;
|
||||
$colorThumbsBubbleFg: lighten($colorBodyFg, 10%);
|
||||
$colorThumbsBubbleBg: lighten($colorBodyBg, 10%);
|
||||
$colorLimitYellow: #9d7500;
|
||||
$colorLimitRed: #aa0000;
|
||||
$colorTelemFresh: #fff;
|
||||
$colorTelemStale: #888;
|
||||
$styleTelemState: italic;
|
||||
$colorInfoBubbleFg: #666;
|
||||
$colorInfoBubbleBg: #ddd;
|
||||
|
||||
// Ratios
|
||||
$ltGamma: 20%;
|
||||
@ -108,7 +126,7 @@ $controlDisabledOpacity: 0.3;
|
||||
$formLabelW: 20%;
|
||||
$formInputH: 22px;
|
||||
$formRowCtrlsH: 14px;
|
||||
$menuLineH: 1.5rem;
|
||||
$menuLineH: 1.4rem;
|
||||
$scrollbarTrackSize: 10px;
|
||||
$scrollbarTrackColorBg: rgba(#000, 0.4);
|
||||
$btnStdH: 25px;
|
||||
@ -124,3 +142,19 @@ $tickLblH: 15px;
|
||||
$tickLblW: 50px;
|
||||
$tickH: $ticksH - $tickLblVMargin - $tickLblH;
|
||||
$tickW: 1px;
|
||||
|
||||
// Imagery
|
||||
$imageMainControlBarH: 20px;
|
||||
$imageThumbsD: 120px;
|
||||
$imageThumbsWrapperH: $imageThumbsD * 1.4;
|
||||
$imageThumbPad: 1px;
|
||||
|
||||
// Bubbles
|
||||
$bubbleArwSize: 10px;
|
||||
$bubblePad: $interiorMargin;
|
||||
$bubbleMinW: 100px;
|
||||
$bubbleMaxW: 300px;
|
||||
|
||||
|
||||
// Timing
|
||||
$controlFadeMs: 100ms;
|
@ -44,7 +44,7 @@ a.disabled {
|
||||
}
|
||||
|
||||
@include keyframes(pulse) {
|
||||
0% { opacity: 0.2; }
|
||||
0% { opacity: 0.5; }
|
||||
100% { opacity: 1; }
|
||||
}
|
||||
|
||||
@ -57,5 +57,5 @@ a.disabled {
|
||||
}
|
||||
|
||||
.pulse {
|
||||
@include pulse(1000ms);
|
||||
@include pulse(750ms);
|
||||
}
|
@ -69,6 +69,10 @@ span {
|
||||
*/
|
||||
}
|
||||
|
||||
mct-container {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.abs {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@ -117,6 +121,13 @@ span {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.paused {
|
||||
&:not(.s-btn) {
|
||||
border-color: $colorPausedBg !important;
|
||||
color: $colorPausedBg !important;
|
||||
}
|
||||
}
|
||||
|
||||
.sep {
|
||||
color: rgba(#fff, 0.2);
|
||||
}
|
@ -36,7 +36,7 @@
|
||||
// Don't pad in from top and bottom
|
||||
//top: 0; bottom: 0;
|
||||
.object-browse-bar {
|
||||
.t-btn.key-window {
|
||||
.btn.key-window {
|
||||
// Hide the Open in New Window button
|
||||
display: none;
|
||||
}
|
||||
|
@ -42,12 +42,6 @@
|
||||
&.major {
|
||||
font-size: 1.65em;
|
||||
}
|
||||
&:hover {
|
||||
// color: lighten($c, $ltGamma);
|
||||
.invoke-menu {
|
||||
// color: lighten($colorBodyBg, $ltGamma * 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -56,36 +50,35 @@
|
||||
}
|
||||
|
||||
.invoke-menu {
|
||||
@include invokeMenu($colorKey);
|
||||
//@include invokeMenu(); // $colorKey
|
||||
text-shadow: none;
|
||||
display: inline-block;
|
||||
font-size: 1rem;
|
||||
font-size: 0.8rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.btn-menu .invoke-menu,
|
||||
.icon.major .invoke-menu {
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
|
||||
.icon-buttons-main .invoke-menu {
|
||||
@include invokeMenu(lighten($colorBodyBg, $ltGamma));
|
||||
}
|
||||
|
||||
.menu-element .invoke-menu {
|
||||
|
||||
margin-left: $interiorMarginSm;
|
||||
}
|
||||
|
||||
/*
|
||||
.object-header .type-icon {
|
||||
color: $colorKey;
|
||||
margin-right: $interiorMargin;
|
||||
margin-right: $interiorMarginSm;
|
||||
}
|
||||
*/
|
||||
|
||||
.menu .type-icon,
|
||||
.tree-item .type-icon,
|
||||
.icon-btn .menu.dropdown .icon,
|
||||
.super-menu.menu.dropdown .icon {
|
||||
font-size: $menuLineH * 0.93;
|
||||
.super-menu.menu .type-icon {
|
||||
font-size: $menuLineH * 0.8; //.93
|
||||
line-height: $menuLineH * 1.13;
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
|
||||
.super-menu.menu.dropdown .icon {
|
||||
font-size: $menuLineH * 0.95
|
||||
}
|
||||
|
||||
|
@ -46,6 +46,9 @@
|
||||
@import "controls/lists";
|
||||
@import "controls/menus";
|
||||
@import "controls/time-controller";
|
||||
@import "edit/editor";
|
||||
@import "features/imagery";
|
||||
@import "features/time-display";
|
||||
@import "forms/mixins";
|
||||
@import "forms/elems";
|
||||
@import "forms/validation";
|
||||
|
@ -26,6 +26,16 @@
|
||||
width: auto; height: auto;
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice($props, $t) {
|
||||
@if $t == 0 {
|
||||
@include transition-property(none);
|
||||
} @else {
|
||||
@include transition-property($props);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice-fade($t: 0.5s) {
|
||||
@if $t == 0 {
|
||||
@include transition-property(none);
|
||||
@ -42,6 +52,12 @@
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
|
||||
@mixin trans-prop-nice-resize-w($t: 0.5s) {
|
||||
@include transition-property(width, left, right);
|
||||
@include transition-duration($t);
|
||||
@include transition-timing-function(ease-in-out);
|
||||
}
|
||||
|
||||
@mixin triangle-right($size, $color) {
|
||||
$size: $size/2;
|
||||
$ratio: 1;
|
||||
@ -62,6 +78,31 @@
|
||||
border-right: $size/$ratio solid transparent;
|
||||
}
|
||||
|
||||
@mixin triangle($dir: "left", $size: 5px, $ratio: 1, $color: red) {
|
||||
//$size: $size*2;
|
||||
width: 0;
|
||||
height: 0;
|
||||
$slopedB: $size/$ratio solid transparent;
|
||||
$straightB: $size solid $color;
|
||||
@if $dir == "up" {
|
||||
border-left: $slopedB;
|
||||
border-right: $slopedB;
|
||||
border-bottom: $straightB;
|
||||
} @else if $dir == "right" {
|
||||
border-top: $slopedB;
|
||||
border-bottom: $slopedB;
|
||||
border-left: $straightB;
|
||||
} @else if $dir == "down" {
|
||||
border-left: $slopedB;
|
||||
border-right: $slopedB;
|
||||
border-top: $straightB;
|
||||
} @else {
|
||||
border-top: $slopedB;
|
||||
border-bottom: $slopedB;
|
||||
border-right: $straightB;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin bgDiagonalStripes($c: yellow, $a: 0.1, $d: 40px) {
|
||||
@include background-image(linear-gradient(-45deg,
|
||||
rgba($c, $a) 25%, transparent 25%,
|
||||
@ -90,20 +131,35 @@
|
||||
}
|
||||
|
||||
@mixin containerSubtle($bg: $colorBodyBg, $fg: $colorBodyFg, $hover: false) {
|
||||
@include background-image(linear-gradient(lighten($bg, 10%), lighten($bg, 5%)));
|
||||
$ltnRatio: 7%;
|
||||
$gradRatio: 5%;
|
||||
$hovRatio: 7%;
|
||||
$bgBase: lighten($bg, $ltnRatio);
|
||||
$fgBase: lighten($fg, $ltnRatio);
|
||||
$gradC1: lighten($bgBase, $gradRatio);
|
||||
$gradC2: $bgBase;
|
||||
$cInvokeBase: lighten($gradC1, $ltnRatio*2);
|
||||
|
||||
@include background-image(linear-gradient($gradC1, $gradC2));
|
||||
@include border-radius($controlCr);
|
||||
@include box-sizing(border-box);
|
||||
// @include box-shadow(rgba(black, 0.3) 0 1px 2px);
|
||||
@include boxShdwSubtle();
|
||||
border: none;
|
||||
border-top: 1px solid lighten($bg, 20%);
|
||||
border-top: 1px solid lighten($gradC1, 2%);
|
||||
color: $fg;
|
||||
display: inline-block;
|
||||
@if $hover == true {
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 15%)));
|
||||
&:not(.disabled):hover {
|
||||
@include background-image(linear-gradient(lighten($gradC1, $hovRatio), lighten($gradC2, $hovRatio)));
|
||||
color: lighten($fgBase, $hovRatio);
|
||||
&.btn-menu .invoke-menu {
|
||||
color: lighten($cInvokeBase, $hovRatio);
|
||||
}
|
||||
}
|
||||
}
|
||||
&.btn-menu .invoke-menu {
|
||||
color: $cInvokeBase;
|
||||
}
|
||||
}
|
||||
|
||||
@mixin sliderTrack($bg: $scrollbarTrackColorBg) {
|
||||
@ -144,18 +200,16 @@
|
||||
}
|
||||
|
||||
@mixin btnSubtle($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
@include containerSubtle($bg, $fg);
|
||||
&:not(.disabled):hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 10%)));
|
||||
}
|
||||
@include containerSubtle($bg, $fg, true);
|
||||
}
|
||||
|
||||
@mixin btnNoticeable($bg: $colorBodyBg, $fg: $colorBodyFg) {
|
||||
@include containerSubtle($bg, $fg);
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), $bg));
|
||||
&:not(.disabled):hover {
|
||||
// No longer should be used; use btnSubtle instead
|
||||
//@include containerSubtle($bg, $fg, true);
|
||||
//@include background-image(linear-gradient(lighten($bg, 20%), $bg));
|
||||
/* &:not(.disabled):hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 30%), lighten($bg, 10%)));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@mixin boxIncised($sVal: 0.6) {
|
||||
@ -166,8 +220,8 @@
|
||||
border: 1px solid $c;
|
||||
}
|
||||
|
||||
@mixin boxShdwSubtle($sVal: 0.3) {
|
||||
@include box-shadow(rgba(black, $sVal) 0 1px 3px);
|
||||
@mixin boxShdwSubtle($sVal: 0.2) {
|
||||
@include box-shadow(rgba(black, $sVal) 0 1px 2px);
|
||||
}
|
||||
|
||||
@mixin boxShdwLarge($sVal: 0.7) {
|
||||
@ -194,13 +248,15 @@
|
||||
}
|
||||
|
||||
|
||||
@mixin invokeMenu($baseColor) {
|
||||
/*
|
||||
@mixin invokeMenu($baseColor: $colorBodyFg) {
|
||||
$c: $baseColor;
|
||||
color: $c;
|
||||
&:hover {
|
||||
color: lighten($c, $ltGamma);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
@mixin menuUlReset() {
|
||||
margin: 0;
|
||||
|
@ -19,37 +19,97 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
$pad: $interiorMargin * 2;
|
||||
$baseRatio: 1.5;
|
||||
$pad: $interiorMargin * $baseRatio;
|
||||
|
||||
/*********************************** TYPE STYLES */
|
||||
.t-btn {
|
||||
cursor: pointer;
|
||||
/******* LAYOUT AND SIZING */
|
||||
.btn,
|
||||
.l-btn {
|
||||
line-height: 1.25em;
|
||||
padding: 0 $pad;
|
||||
text-decoration: none;
|
||||
&.lg,
|
||||
&.create-btn {
|
||||
$h: $ueTopBarH - $interiorMargin;
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
padding: 0 $pad * 3;
|
||||
}
|
||||
&.create-btn {
|
||||
.menu {
|
||||
margin-left: $pad * -1;
|
||||
}
|
||||
>.ui-symbol {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
&.sm {
|
||||
padding: 0 $pad / $baseRatio;
|
||||
}
|
||||
&.vsm {
|
||||
padding: 0 ($pad / $baseRatio) / 2;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************** STYLE STYLES */
|
||||
.btn,
|
||||
.s-btn {
|
||||
$base: lighten($colorBodyBg, 20%);
|
||||
$base: lighten($colorBodyBg, 20%); // Moved to s-btn
|
||||
@include border-radius($controlCr);
|
||||
@include box-sizing(border-box);
|
||||
@include text-shadow(rgba(black, 0.3) 0 1px 1px);
|
||||
cursor: pointer;
|
||||
line-height: 1.2em;
|
||||
padding: 0 $pad;
|
||||
text-decoration: none;
|
||||
&.major {
|
||||
$bg: $colorKey;
|
||||
@include btnSubtle($bg);
|
||||
$fg: lighten($bg, 50%);
|
||||
color: $fg;
|
||||
&:hover {
|
||||
@include btnSubtle(lighten($bg, 5%), $fg);
|
||||
//color: $fg;
|
||||
}
|
||||
.invoke-menu {
|
||||
color: $fg;
|
||||
}
|
||||
}
|
||||
&.subtle {
|
||||
@include btnSubtle($base, lighten($base, 40%));
|
||||
}
|
||||
&.very-subtle,
|
||||
&.s-very-subtle {
|
||||
@include containerSubtle($colorBodyBg, $colorBodyFg, true);
|
||||
&.paused {
|
||||
@include containerSubtle($colorPausedBg, $colorPausedFg, true);
|
||||
.icon:before {
|
||||
content:"\0000EF";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.icon-btn,
|
||||
.s-icon-btn {
|
||||
@extend .s-btn;
|
||||
font-size: 1.2em;
|
||||
font-size: 1em;
|
||||
.icon {
|
||||
color: $colorKey;
|
||||
}
|
||||
&.paused {
|
||||
.icon {
|
||||
color: $colorPausedFg;
|
||||
}
|
||||
}
|
||||
|
||||
&:not(.disabled):hover .icon {
|
||||
color: lighten($colorKey, $ltGamma);
|
||||
&:not(.disabled) {
|
||||
&:not(.paused) {
|
||||
&:hover {
|
||||
.icon {
|
||||
color: lighten($colorKey, $ltGamma);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.labeled {
|
||||
@ -61,12 +121,30 @@ $pad: $interiorMargin * 2;
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
&.pause-play {
|
||||
&.paused {
|
||||
@include pulse(500ms);
|
||||
}
|
||||
.icon:before {
|
||||
content:"\0000F1";
|
||||
}
|
||||
}
|
||||
|
||||
&.show-thumbs {
|
||||
.icon:before {
|
||||
content:"\000039";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*********************************** LAYOUT STYLES */
|
||||
span.btn,
|
||||
span.btn span,
|
||||
span.l-btn,
|
||||
span.l-btn span,
|
||||
a.btn,
|
||||
a.btn span,
|
||||
a.l-btn,
|
||||
a.l-btn span {
|
||||
display: inline-block;
|
||||
|
@ -19,7 +19,8 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
.control {
|
||||
/*.control {
|
||||
// UNUSED?
|
||||
&.view-control {
|
||||
.icon {
|
||||
display: inline-block;
|
||||
@ -45,10 +46,10 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
.accordion {
|
||||
$accordionHeadH: 18px;
|
||||
$accordionHeadH: 18px;
|
||||
margin-top: $interiorMargin;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
@ -56,16 +57,20 @@
|
||||
.accordion-head {
|
||||
$op: 0.2;
|
||||
@include border-radius($basicCr * 0.75);
|
||||
@include box-sizing("border-box");
|
||||
@include box-sizing("border-box");
|
||||
background: rgba($colorBodyFg, $op);
|
||||
cursor: pointer;
|
||||
font-size: 0.75em;
|
||||
line-height: $accordionHeadH;
|
||||
line-height: $accordionHeadH;
|
||||
margin-bottom: $interiorMargin;
|
||||
padding: 0 $interiorMargin;
|
||||
position: absolute;
|
||||
top: 0; right: 0; bottom: auto; left: 0;
|
||||
width: auto; height: $accordionHeadH;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
width: auto;
|
||||
height: $accordionHeadH;
|
||||
text-transform: uppercase;
|
||||
&:hover {
|
||||
background: rgba($colorBodyFg, $op * 2);
|
||||
@ -84,79 +89,14 @@
|
||||
content: "v";
|
||||
}
|
||||
}
|
||||
.accordion-contents {
|
||||
position: absolute;
|
||||
top: $accordionHeadH + $interiorMargin; right: 0; bottom: 0; left: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
$base: lighten($colorBodyBg, 20%); // Moved to s-btn
|
||||
$p: 10px; // Moved to s-btn
|
||||
@include border-radius($controlCr); // Moved to s-btn
|
||||
@include box-sizing(border-box); // Moved to s-btn
|
||||
@include text-shadow(rgba(black, 0.3) 0 1px 1px); // Moved to s-btn
|
||||
// display: inline-block;
|
||||
// margin-right: 10px;
|
||||
padding: 0 ($interiorMargin * 2); // Moved to s-btn
|
||||
text-decoration: none; // Moved to s-btn
|
||||
&.create-btn {
|
||||
$h: $ueTopBarH - $interiorMargin; //$btnStdH * 1.5;;
|
||||
$p: $p * 2.25;
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
//font-size: 1.1em;
|
||||
padding: 0 $p;
|
||||
.menu {
|
||||
margin-left: $p * -1;
|
||||
}
|
||||
.ui-symbol.major {
|
||||
font-size: 1.1em;
|
||||
}
|
||||
}
|
||||
&.major {
|
||||
$bg: $colorKey;
|
||||
@include btnNoticeable($bg);
|
||||
$fg: lighten($bg, 50%);
|
||||
color: $fg;
|
||||
&:hover {
|
||||
@include btnNoticeable(lighten($bg, 5%));
|
||||
color: $fg;
|
||||
}
|
||||
.invoke-menu {
|
||||
color: $fg;
|
||||
}
|
||||
}
|
||||
&.normal {
|
||||
padding: $p * 0.5 $p * 0.7;
|
||||
}
|
||||
&.outline {
|
||||
&:hover {
|
||||
background: rgba(#fff, 0.1);
|
||||
}
|
||||
}
|
||||
&.subtle {
|
||||
@include btnSubtle($base, lighten($base, 40%));
|
||||
}
|
||||
|
||||
&.very-subtle {
|
||||
@include btnSubtle($colorBodyBg, lighten($colorBodyBg, 50%));
|
||||
}
|
||||
&.lg {
|
||||
@include border-radius($controlCr * 1.5);
|
||||
font-size: 1.2em;
|
||||
padding: 7px 25px;
|
||||
}
|
||||
&.icon-btn {
|
||||
.icon {
|
||||
color: $colorKey;
|
||||
}
|
||||
|
||||
&:not(.disabled):hover .icon {
|
||||
color: lighten($colorKey, $ltGamma);
|
||||
}
|
||||
.accordion-contents {
|
||||
position: absolute;
|
||||
top: $accordionHeadH + $interiorMargin;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
}
|
||||
|
||||
@ -166,12 +106,12 @@
|
||||
.btn-set,
|
||||
.t-btn {
|
||||
display: inline-block;
|
||||
// margin-left: $interiorMargin;
|
||||
// margin-left: $interiorMargin;
|
||||
}
|
||||
.btn,
|
||||
.t-btn {
|
||||
&:first-child {
|
||||
// margin-left: 0;
|
||||
// margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -199,6 +139,20 @@
|
||||
}
|
||||
}
|
||||
|
||||
.l-local-controls {
|
||||
// Control shown when hovering over an object, like plots and imagery
|
||||
// Default position is upper right
|
||||
$p: $interiorMargin;
|
||||
position: absolute;
|
||||
top: $p;
|
||||
right: $p;
|
||||
z-index: 5;
|
||||
}
|
||||
|
||||
.s-local-controls {
|
||||
font-size: 0.7rem;
|
||||
}
|
||||
|
||||
.btn-set {
|
||||
// Buttons that have a very tight conceptual grouping - no internal space between them.
|
||||
display: inline-block;
|
||||
@ -230,8 +184,8 @@
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
.icon:not(.invoke-menu) {
|
||||
// position: relative;
|
||||
// top: -0.04em;
|
||||
// position: relative;
|
||||
// top: -0.04em;
|
||||
font-size: 150%;
|
||||
vertical-align: middle;
|
||||
}
|
||||
@ -318,37 +272,43 @@ label.checkbox.custom {
|
||||
|
||||
.btn-menu {
|
||||
$h: 20px;
|
||||
$p: $interiorMargin * 2;
|
||||
$p: $interiorMarginSm * 2;
|
||||
$c: $colorBodyFg;
|
||||
@include btnSubtle($colorBodyBg);
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
&.dropdown {
|
||||
// padding-left: $p;
|
||||
padding-left: $p;
|
||||
padding-right: $p;
|
||||
}
|
||||
/* height: $h;
|
||||
line-height: $h;
|
||||
&.dropdown {
|
||||
padding-left: $p;
|
||||
padding-right: $p;
|
||||
}*/
|
||||
|
||||
&:not(.disabled):hover {
|
||||
color: lighten($c, 20%);
|
||||
}
|
||||
|
||||
&.btn-invoke-menu {
|
||||
$c: $colorKey;
|
||||
color: $c;
|
||||
padding: 0 5px;
|
||||
&:hover {
|
||||
color: lighten($c, 10%);
|
||||
}
|
||||
/* &.context-available {
|
||||
// An element like the invoke-menu triangle;
|
||||
// Indicates that this element has a dropdown menu available;
|
||||
// Currently unused
|
||||
$c: $colorKey;
|
||||
color: $c;
|
||||
padding: 0 5px;
|
||||
&:hover {
|
||||
color: lighten($c, 10%);
|
||||
}
|
||||
}*/
|
||||
|
||||
span.l-click-area {
|
||||
// In markup, this element should not enclose anything.
|
||||
@extend .abs;
|
||||
}
|
||||
|
||||
span.l-click-area {
|
||||
// In markup, this element should not enclose anything.
|
||||
@extend .abs;
|
||||
}
|
||||
|
||||
.type-icon {
|
||||
margin-right: $interiorMargin;
|
||||
//margin-right: $interiorMargin;
|
||||
}
|
||||
|
||||
.name {
|
||||
margin-left: $interiorMargin;
|
||||
}
|
||||
.menu {
|
||||
// margin-left: (-1 * $p);
|
||||
@ -388,17 +348,23 @@ label.checkbox.custom {
|
||||
}
|
||||
}
|
||||
|
||||
.view-switcher {
|
||||
@include trans-prop-nice-fade($controlFadeMs);
|
||||
}
|
||||
|
||||
/******************************************************** OBJECT-HEADER */
|
||||
.object-header {
|
||||
display: inline-block;
|
||||
font-size: 1em;
|
||||
.title {
|
||||
color: lighten($colorBodyFg, 40%);
|
||||
}
|
||||
.type-icon {
|
||||
font-size: 1.5em;
|
||||
margin-right: $interiorMargin;
|
||||
vertical-align: middle;
|
||||
.label {
|
||||
.title-label {
|
||||
color: lighten($colorBodyFg, 40%);
|
||||
}
|
||||
.type-icon {
|
||||
font-size: 1.5em;
|
||||
margin-right: $interiorMargin;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -412,86 +378,53 @@ label.checkbox.custom {
|
||||
}
|
||||
}
|
||||
|
||||
/******************************************************** VIEW-CONTROLS */
|
||||
|
||||
.view-controls .view-type {
|
||||
$d: 20px;
|
||||
$p: 5px;
|
||||
@include border-radius($controlCr);
|
||||
box-sizing: border-box;
|
||||
display: inline-block;
|
||||
margin-left: $interiorMargin;
|
||||
height: $d;
|
||||
line-height: $d;
|
||||
padding-left: $p;
|
||||
padding-right: $p;
|
||||
&.cur {
|
||||
background: lighten($colorBodyBg, $ltGamma);
|
||||
}
|
||||
}
|
||||
|
||||
.edit-mode .top-bar .control-set.edit-view-controls {
|
||||
// Used in templates/edit-view-controls.html
|
||||
margin-right: $interiorMargin * 10;
|
||||
}
|
||||
|
||||
/******************************************************** SLIDERS */
|
||||
.wrapper-slider {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.slider {
|
||||
//$knobH: 70%; //14px;
|
||||
$knobH: 100%; //14px;
|
||||
$knobW: 12px;
|
||||
$slotH: 80%;
|
||||
$rangeO: 0.3;
|
||||
$slotH: 50%;
|
||||
.slot {
|
||||
// @include border-radius($basicCr * .75);
|
||||
@include sliderTrack();
|
||||
height: auto;
|
||||
height: $slotH;
|
||||
width: auto;
|
||||
position: absolute;
|
||||
//top: ($knobH - $slotH) / 2;
|
||||
top: (100% - $slotH)/2;
|
||||
top: ($knobH - $slotH) / 2;
|
||||
right: 0;
|
||||
bottom: (100% - $slotH)/2;
|
||||
bottom: auto;
|
||||
left: 0;
|
||||
z-index: 0;
|
||||
.range {
|
||||
background: rgba($colorKey, $rangeO);
|
||||
cursor: ew-resize;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: auto;
|
||||
bottom: 0;
|
||||
left: auto;
|
||||
height: auto;
|
||||
width: auto;
|
||||
z-index: 1;
|
||||
&:hover {
|
||||
background: rgba($colorKey, $rangeO + 0.2);
|
||||
}
|
||||
}
|
||||
}
|
||||
.knob {
|
||||
@include btnSubtle();
|
||||
@include controlGrippy(rgba(black, 0.3), vertical, 1px, solid);
|
||||
@include border-radius(2px);
|
||||
cursor: ew-resize;
|
||||
position: absolute;
|
||||
height: auto;
|
||||
height: $knobH;
|
||||
width: $knobW;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
auto: 0;
|
||||
bottom: auto;
|
||||
left: auto;
|
||||
z-index: 2;
|
||||
&.knob-l { margin-left: $knobW / -2; }
|
||||
&.knob-r { margin-right: $knobW / -2; }
|
||||
&:before {
|
||||
top: 1px;
|
||||
bottom: 3px;
|
||||
//left: ($knobW / 2) - 1;
|
||||
//margin-left: -1px;
|
||||
left: 45%;
|
||||
left: ($knobW / 2) - 1;
|
||||
}
|
||||
|
||||
}
|
||||
.range {
|
||||
background: rgba($colorKey, 0.6);
|
||||
cursor: ew-resize;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: auto;
|
||||
bottom: 0;
|
||||
left: auto;
|
||||
height: auto;
|
||||
width: auto;
|
||||
&:hover {
|
||||
background: rgba($colorKey, 0.7);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -499,23 +432,23 @@ label.checkbox.custom {
|
||||
/******************************************************** BROWSER ELEMENTS */
|
||||
|
||||
::-webkit-scrollbar {
|
||||
@include sliderTrack();
|
||||
height: $scrollbarTrackSize;
|
||||
width: $scrollbarTrackSize;
|
||||
@include sliderTrack();
|
||||
height: $scrollbarTrackSize;
|
||||
width: $scrollbarTrackSize;
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-thumb {
|
||||
$bg: lighten($colorBodyBg, 10%);
|
||||
@include background-image(linear-gradient(lighten($bg, 10%), lighten($bg, 5%) 20px));
|
||||
@include border-radius(1px);
|
||||
@include box-sizing(border-box);
|
||||
@include boxShdwSubtle();
|
||||
border-top: 1px solid lighten($bg, 20%);
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 15%) 20px));
|
||||
}
|
||||
$bg: lighten($colorBodyBg, 10%);
|
||||
@include background-image(linear-gradient(lighten($bg, 10%), lighten($bg, 5%) 20px));
|
||||
@include border-radius(1px);
|
||||
@include box-sizing(border-box);
|
||||
@include boxShdwSubtle();
|
||||
border-top: 1px solid lighten($bg, 20%);
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($bg, 20%), lighten($bg, 15%) 20px));
|
||||
}
|
||||
}
|
||||
|
||||
::-webkit-scrollbar-corner {
|
||||
background: rgba(#000, 0.4);
|
||||
background: rgba(#000, 0.4);
|
||||
}
|
@ -41,7 +41,7 @@
|
||||
@include box-sizing(border-box);
|
||||
border-top: 1px solid lighten($bg, 20%);
|
||||
line-height: $menuLineH;
|
||||
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 3) + $treeTypeIconW;
|
||||
padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW;
|
||||
white-space: nowrap;
|
||||
&:first-child {
|
||||
border: none;
|
||||
@ -168,7 +168,7 @@
|
||||
position: absolute;
|
||||
height: 200px;
|
||||
width: 170px;
|
||||
z-index: 59;
|
||||
z-index: 70;
|
||||
.context-menu-wrapper {
|
||||
position: absolute;
|
||||
height: 100%;
|
||||
|
@ -19,3 +19,86 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
.edit-main {
|
||||
$handleD: 15px;
|
||||
$cr: 5px;
|
||||
.edit-corner,
|
||||
.edit-handle {
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.edit-corner {
|
||||
width: $handleD;
|
||||
height: $handleD;
|
||||
&.edit-resize-nw {
|
||||
@include border-bottom-right-radius($cr);
|
||||
cursor: nw-resize;
|
||||
top: 0; left: 0;
|
||||
}
|
||||
&.edit-resize-se {
|
||||
@include border-top-left-radius($cr);
|
||||
cursor: se-resize;
|
||||
bottom: 0; right: 0;
|
||||
}
|
||||
&.edit-resize-sw {
|
||||
@include border-top-right-radius($cr);
|
||||
cursor: sw-resize;
|
||||
bottom: 0; left: 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.edit-handle {
|
||||
top: $handleD; right: $handleD; bottom: $handleD; left: $handleD;
|
||||
&.edit-move {
|
||||
$m: 0; //$handleD;
|
||||
cursor: move;
|
||||
left: $m;
|
||||
right: $m;
|
||||
top: $m;
|
||||
bottom: $m;
|
||||
z-index: 1;
|
||||
|
||||
}
|
||||
&.edit-resize-n {
|
||||
top: 0px; bottom: auto;
|
||||
height: $handleD;
|
||||
cursor: n-resize;
|
||||
}
|
||||
&.edit-resize-e {
|
||||
right: 0px; left: auto;
|
||||
width: $handleD;
|
||||
cursor: e-resize;
|
||||
}
|
||||
&.edit-resize-s {
|
||||
bottom: 0px; top: auto;
|
||||
height: $handleD;
|
||||
cursor: s-resize;
|
||||
}
|
||||
&.edit-resize-w {
|
||||
left: 0px; right: auto;
|
||||
width: $handleD;
|
||||
cursor: w-resize;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.frame.child-frame.panel {
|
||||
&:hover {
|
||||
@include boxShdwLarge();
|
||||
border-color: $colorKey;
|
||||
z-index: 2;
|
||||
.view-switcher {
|
||||
opacity: 1;
|
||||
}
|
||||
.edit-corner {
|
||||
background-color: rgba($colorKey, 0.8);
|
||||
&:hover {
|
||||
background-color: rgba($colorKey, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
171
platform/commonUI/general/res/sass/features/_imagery.scss
Normal file
171
platform/commonUI/general/res/sass/features/_imagery.scss
Normal file
@ -0,0 +1,171 @@
|
||||
.l-image-main-wrapper,
|
||||
.l-image-main,
|
||||
.l-image-main-controlbar,
|
||||
.l-image-main-controlbar .left,
|
||||
.l-image-main-controlbar .right,
|
||||
.l-image-thumbs-wrapper {
|
||||
@include absPosDefault(0, false);
|
||||
}
|
||||
|
||||
/*************************************** MAIN LAYOUT */
|
||||
.l-image-main-wrapper {
|
||||
//@include test();
|
||||
@if $enableImageryThumbs == true {
|
||||
bottom: $interiorMargin*2 + $imageThumbsWrapperH;
|
||||
}
|
||||
min-height: 100px;
|
||||
min-width: 150px;
|
||||
.l-image-main {
|
||||
background-color: rgba(#fff, 0.1);
|
||||
bottom: $imageMainControlBarH + $interiorMargin;
|
||||
}
|
||||
.l-image-main-controlbar {
|
||||
top: auto;
|
||||
height: $imageMainControlBarH;
|
||||
}
|
||||
}
|
||||
|
||||
.l-image-thumbs-wrapper {
|
||||
//@include test(red);
|
||||
top: auto;
|
||||
height: $imageThumbsWrapperH;
|
||||
}
|
||||
|
||||
.l-date,
|
||||
.l-time,
|
||||
.l-timezone {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/*************************************** MAIN IMAGE */
|
||||
|
||||
.l-image-main,
|
||||
.l-image-thumb-item .l-thumb {
|
||||
background-size: contain;
|
||||
background-position: center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.l-image-main {
|
||||
cursor: crosshair;
|
||||
}
|
||||
|
||||
.l-image-main-controlbar {
|
||||
//@include test();
|
||||
font-size: 0.8em;
|
||||
line-height: $imageMainControlBarH;
|
||||
.left, .right {
|
||||
direction: rtl;
|
||||
overflow: hidden;
|
||||
}
|
||||
.left {
|
||||
//@include test(red);
|
||||
text-align: left;
|
||||
width: 75% !important;
|
||||
}
|
||||
.right {
|
||||
//@include test(green);
|
||||
min-width: 40px;
|
||||
width: 25% !important;
|
||||
z-index: 2;
|
||||
}
|
||||
.l-date,
|
||||
.l-time {
|
||||
color: #fff;
|
||||
}
|
||||
.l-mag {
|
||||
direction: ltr;
|
||||
display: inline-block;
|
||||
//white-space: nowrap;
|
||||
&:before {
|
||||
content: "\000049";
|
||||
}
|
||||
}
|
||||
.s-mag {
|
||||
color: darken($colorBodyFg, 20%);
|
||||
}
|
||||
.l-btn.show-thumbs {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.s-image-main {
|
||||
border: 1px solid transparent;
|
||||
&.paused {
|
||||
border-color: $colorPausedBg;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************** THUMBS */
|
||||
|
||||
.l-image-thumbs-wrapper {
|
||||
//@include test(green);
|
||||
direction: rtl;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
padding-bottom: $interiorMargin;
|
||||
white-space: nowrap;
|
||||
z-index: 70;
|
||||
}
|
||||
|
||||
.l-image-thumb-item {
|
||||
@include single-transition(background-color, 0.25s);
|
||||
@include box-sizing(border-box);
|
||||
padding: 1px;
|
||||
position: relative;
|
||||
.l-thumb,
|
||||
.l-date,
|
||||
.l-time {
|
||||
display: inline-block;
|
||||
}
|
||||
.l-date,
|
||||
.l-time {
|
||||
padding: 2px 3px;
|
||||
}
|
||||
cursor: pointer;
|
||||
direction: ltr;
|
||||
display: inline-block;
|
||||
font-size: 0.8em;
|
||||
margin-left: $interiorMarginSm;
|
||||
text-align: left;
|
||||
width: $imageThumbsD + $imageThumbPad*2;
|
||||
white-space: normal;
|
||||
&:hover {
|
||||
background: rgba(#fff, 0.2);
|
||||
.l-date,
|
||||
.l-time {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
&.selected {
|
||||
background: $colorKeySelectedBg;
|
||||
.l-date,
|
||||
.l-time {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.l-thumb {
|
||||
background-color: rgba(#fff, 0.1);
|
||||
height: $imageThumbsD;
|
||||
width: $imageThumbsD;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
/*************************************** WHEN IN FRAME */
|
||||
.frame .t-imagery {
|
||||
.l-image-main-wrapper {
|
||||
bottom: 0;
|
||||
.l-image-main-controlbar {
|
||||
font-size: 0.7em;
|
||||
}
|
||||
@if $enableImageryThumbs == true {
|
||||
.l-btn.show-thumbs {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.l-image-thumbs-wrapper {
|
||||
display: none;
|
||||
}
|
||||
}
|
@ -0,0 +1,44 @@
|
||||
.l-time-display {
|
||||
$transTime: 200ms;
|
||||
// Layout
|
||||
&:hover {
|
||||
.l-btn.control {
|
||||
//display: inline-block;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.l-elem-wrapper {
|
||||
position: relative;
|
||||
}
|
||||
.l-elem {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
&.l-timer {
|
||||
.l-elem.l-value {
|
||||
@include trans-prop-nice(left, $transTime);
|
||||
position: absolute;
|
||||
left: 0;
|
||||
z-index: 1;
|
||||
}
|
||||
&:hover .l-elem.l-value {
|
||||
left: 20px;
|
||||
}
|
||||
}
|
||||
|
||||
// Look-and-feel
|
||||
.l-elem {
|
||||
.value.active,
|
||||
&.value.active {
|
||||
color: $colorKeyFg;
|
||||
}
|
||||
}
|
||||
.l-btn.control {
|
||||
@include trans-prop-nice-fade($transTime);
|
||||
//display: none;
|
||||
opacity: 0;
|
||||
font-size: 0.9em;
|
||||
line-height: 1em;
|
||||
}
|
||||
|
||||
}
|
@ -19,18 +19,13 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
input[type="text"],
|
||||
input[type="date"] {
|
||||
input[type="text"] {
|
||||
@include nice-input();
|
||||
@include input-placeholder {
|
||||
color: darken($colorBodyFg, 10%);
|
||||
font-style: italic;
|
||||
}
|
||||
&.filter {
|
||||
&.ng-dirty {
|
||||
// background: red;
|
||||
}
|
||||
}
|
||||
&.filter {
|
||||
&.ng-dirty {
|
||||
// background: red;
|
||||
}
|
||||
}
|
||||
&.numeric {
|
||||
text-align: right;
|
||||
}
|
||||
|
@ -21,17 +21,15 @@
|
||||
*****************************************************************************/
|
||||
//************************************************* LAYOUT
|
||||
|
||||
$infoBubbleFg: #666;
|
||||
$infoBubbleBg: #ddd;
|
||||
|
||||
.l-infobubble-wrapper {
|
||||
$arwSize: 5px;
|
||||
@include box-shadow(rgba(black, 0.4) 0 1px 5px);
|
||||
position: absolute;
|
||||
z-index: 70;
|
||||
position: relative;
|
||||
z-index: 50;
|
||||
.l-infobubble {
|
||||
display: inline-block;
|
||||
max-width: 250px;
|
||||
min-width: $bubbleMinW;
|
||||
max-width: $bubbleMaxW;
|
||||
padding: 5px 10px;
|
||||
&:before {
|
||||
content:"";
|
||||
@ -71,34 +69,30 @@ $infoBubbleBg: #ddd;
|
||||
}
|
||||
|
||||
&.arw-left {
|
||||
margin-left: $arwSize*2;
|
||||
margin-left: $bubbleArwSize*2;
|
||||
.l-infobubble::before {
|
||||
right: 100%;
|
||||
border-top: $arwSize solid transparent;
|
||||
border-bottom: $arwSize solid transparent;
|
||||
border-right: ($arwSize * 1.5) solid $infoBubbleBg;
|
||||
@include triangle('left', $bubbleArwSize, 1.5, $colorInfoBubbleBg);
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-right {
|
||||
margin-right: $arwSize*2;
|
||||
margin-right: $bubbleArwSize*2;
|
||||
.l-infobubble::before {
|
||||
left: 100%;
|
||||
border-top: $arwSize solid transparent;
|
||||
border-bottom: $arwSize solid transparent;
|
||||
border-left: ($arwSize * 1.5) solid $infoBubbleBg;
|
||||
@include triangle('right', $bubbleArwSize, 1.5, $colorInfoBubbleBg);
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-top {
|
||||
.l-infobubble::before {
|
||||
top: $arwSize * 2;
|
||||
top: $bubbleArwSize * 2;
|
||||
}
|
||||
}
|
||||
|
||||
&.arw-btm {
|
||||
.l-infobubble::before {
|
||||
bottom: $arwSize * 2;
|
||||
bottom: $bubbleArwSize * 2;
|
||||
}
|
||||
}
|
||||
|
||||
@ -110,18 +104,32 @@ $infoBubbleBg: #ddd;
|
||||
margin-left: -1 * $arwSize;
|
||||
border-left: $arwSize solid transparent;
|
||||
border-right: $arwSize solid transparent;
|
||||
border-top: ($arwSize * 1.5) solid $infoBubbleBg;
|
||||
border-top: ($arwSize * 1.5) solid $colorInfoBubbleBg;
|
||||
}
|
||||
}
|
||||
.arw {
|
||||
z-index: 2;
|
||||
}
|
||||
&.arw-up .arw.arw-down,
|
||||
&.arw-down .arw.arw-up { display: none; }
|
||||
}
|
||||
|
||||
//************************************************* LOOK AND FEEL
|
||||
|
||||
.l-thumbsbubble-wrapper {
|
||||
.arw-up {
|
||||
@include triangle('up', $bubbleArwSize, 1.5, $colorThumbsBubbleBg);
|
||||
}
|
||||
.arw-down {
|
||||
@include triangle('down', $bubbleArwSize, 1.5, $colorThumbsBubbleBg);
|
||||
}
|
||||
}
|
||||
.s-infobubble {
|
||||
$emFg: darken($infoBubbleFg, 20%);
|
||||
$emFg: darken($colorInfoBubbleFg, 20%);
|
||||
@include border-radius($basicCr);
|
||||
background: $infoBubbleBg;
|
||||
color: $infoBubbleFg;
|
||||
@include box-shadow(rgba(black, 0.4) 0 1px 5px);
|
||||
background: $colorInfoBubbleBg;
|
||||
color: $colorInfoBubbleFg;
|
||||
font-size: 0.8rem;
|
||||
.title {
|
||||
color: $emFg;
|
||||
@ -129,7 +137,7 @@ $infoBubbleBg: #ddd;
|
||||
}
|
||||
tr {
|
||||
td {
|
||||
border-top: 1px solid darken($infoBubbleBg, 10%);
|
||||
border-top: 1px solid darken($colorInfoBubbleBg, 10%);
|
||||
font-size: 0.9em;
|
||||
}
|
||||
&:first-child td {
|
||||
@ -139,5 +147,9 @@ $infoBubbleBg: #ddd;
|
||||
.value {
|
||||
color: $emFg;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.s-thumbsbubble {
|
||||
background: $colorThumbsBubbleBg;
|
||||
color: $colorThumbsBubbleFg;
|
||||
}
|
@ -104,7 +104,7 @@
|
||||
&.selected {
|
||||
$cfg: lighten($colorItemSelected, 35%);
|
||||
$cfgh: lighten($cfg, 30%);
|
||||
@include btnNoticeable($colorItemSelected);
|
||||
@include btnSubtle($colorItemSelected);
|
||||
color: $cfg;
|
||||
.item-type, .top-bar .icon:not(.alert) { color: $cfg }
|
||||
.item-main .item-open { color: $cfg }
|
||||
|
@ -75,8 +75,8 @@ ul.tree {
|
||||
.title-label {
|
||||
@include absPosDefault();
|
||||
display: block;
|
||||
left: $runningItemW + ($interiorMargin * 2);
|
||||
// right: $treeContextTriggerW + $interiorMargin; //Disabling as context trigger not being used
|
||||
left: $runningItemW + ($interiorMargin);
|
||||
//right: $treeContextTriggerW + $interiorMargin;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
// height: $menuLineH;
|
||||
@ -99,7 +99,7 @@ ul.tree {
|
||||
|
||||
&.selected {
|
||||
$c: #fff;
|
||||
background: #005177;
|
||||
background: $colorKeySelectedBg;
|
||||
color: $c;
|
||||
.view-control {
|
||||
color: $colorItemTreeIcon;
|
||||
@ -124,16 +124,15 @@ ul.tree {
|
||||
|
||||
&:not(.loading) {
|
||||
cursor: pointer;
|
||||
// @include tree-item-hover();
|
||||
}
|
||||
|
||||
.context-trigger {
|
||||
$h: 0.9rem;
|
||||
display: none;
|
||||
//display: none;
|
||||
top: -1px;
|
||||
position: absolute;
|
||||
right: $interiorMarginSm;
|
||||
.btn-invoke-menu {
|
||||
.invoke-menu {
|
||||
font-size: 0.75em;
|
||||
height: $h;
|
||||
line-height: $h;
|
||||
|
@ -27,6 +27,7 @@
|
||||
border: 1px solid $bc;
|
||||
&:hover {
|
||||
border-color: lighten($bc, 10%);
|
||||
z-index: 2;
|
||||
}
|
||||
.contents {
|
||||
// overflow: hidden;
|
||||
@ -46,12 +47,25 @@
|
||||
bottom: $myM;
|
||||
left: $myM;
|
||||
}
|
||||
}
|
||||
|
||||
.edit-main .frame.child-frame.panel {
|
||||
&:hover {
|
||||
border-color: $colorKey;
|
||||
@include boxShdwLarge();
|
||||
&.frame-template {
|
||||
// Hide the view switcher by default when it's in an element that's in a frame context
|
||||
// Frame template is used because we need to target the lowest nested frame
|
||||
// This has the effect of hiding the view switcher in nested frames in edit mode, which is desirable currently (as it's non-functional)
|
||||
.view-switcher {
|
||||
//display: none;
|
||||
opacity: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
&:hover .view-switcher {
|
||||
// Show the view switcher on frame hover
|
||||
//display: inline-block !important;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.view-switcher {
|
||||
// Hide the name when the view switcher is in a frame context
|
||||
.name {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -70,23 +70,19 @@
|
||||
&.abs {
|
||||
text-wrap: none;
|
||||
white-space: nowrap;
|
||||
&.left,
|
||||
.left {
|
||||
width: 45%;
|
||||
right: auto;
|
||||
}
|
||||
&.right,
|
||||
.right {
|
||||
width: 45%;
|
||||
left: auto;
|
||||
right: 0;
|
||||
text-align: right;
|
||||
.icon.major {
|
||||
margin-left: $interiorMargin * 3;
|
||||
}
|
||||
// .icon.major {
|
||||
// margin-left: $interiorMargin;
|
||||
// }
|
||||
}
|
||||
&.left,
|
||||
.left {
|
||||
width: 45% !important;
|
||||
right: auto !important;
|
||||
}
|
||||
&.right,
|
||||
.right {
|
||||
width: 45% !important;
|
||||
left: auto !important;
|
||||
text-align: right;
|
||||
.icon.major {
|
||||
margin-left: $interiorMargin * 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<a class="t-btn l-btn s-btn s-icon-btn s-very-subtle key-{{parameters.action.getMetadata().key}}"
|
||||
<a class="btn s-btn s-icon-btn s-very-subtle key-{{parameters.action.getMetadata().key}}"
|
||||
ng-class="{ labeled: parameters.labeled }"
|
||||
title="{{parameters.action.getMetadata().description}}"
|
||||
ng-click="parameters.action.perform()">
|
||||
|
@ -21,25 +21,29 @@
|
||||
-->
|
||||
<span ng-controller="ViewSwitcherController">
|
||||
|
||||
<div class="menu-element btn icon-btn very-subtle btn-menu dropdown click-invoke"
|
||||
ng-if="view.length > 1"
|
||||
ng-controller="ClickAwayController as toggle">
|
||||
<div
|
||||
class="view-switcher menu-element btn btn-menu dropdown click-invoke"
|
||||
ng-if="view.length > 1"
|
||||
ng-controller="ClickAwayController as toggle"
|
||||
>
|
||||
|
||||
<span class="l-click-area" ng-click="toggle.toggle()"></span>
|
||||
<span
|
||||
class="l-click-area"
|
||||
ng-click="toggle.toggle()"
|
||||
title="{{ngModel.selected.name}}"
|
||||
></span>
|
||||
|
||||
<span class="ui-symbol icon type-icon">{{ngModel.selected.glyph}}</span>
|
||||
<span>{{ngModel.selected.name}}</span>
|
||||
<span class='ui-symbol icon invoke-menu'>v</span>
|
||||
<span class="name">{{ngModel.selected.name}}</span>
|
||||
<span class='ui-symbol invoke-menu'>v</span>
|
||||
|
||||
|
||||
<div class="menu dropdown" ng-show="toggle.isActive()">
|
||||
<ul>
|
||||
<li ng-repeat="option in view">
|
||||
<a href="" ng-click="ngModel.selected = option; toggle.setState(false)">
|
||||
<span class="ui-symbol type-icon icon">
|
||||
{{option.glyph}}
|
||||
</span>
|
||||
{{option.name}}
|
||||
<a ng-click="ngModel.selected = option; toggle.setState(false)">
|
||||
<span class="ui-symbol type-icon icon">{{option.glyph}}</span>
|
||||
{{option.name}}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
@ -1,20 +1,50 @@
|
||||
{
|
||||
"extensions": {
|
||||
"types": [
|
||||
"templates": [
|
||||
{
|
||||
"key": "infobubble",
|
||||
"name": "Info Bubble",
|
||||
"glyph": "\u00EA",
|
||||
"description": "Static markup for info bubbles",
|
||||
"features": [ "creation" ]
|
||||
"key": "info-table",
|
||||
"templateUrl": "info-table.html"
|
||||
},
|
||||
{
|
||||
"key": "info-bubble",
|
||||
"templateUrl": "info-bubble.html"
|
||||
}
|
||||
],
|
||||
"views": [
|
||||
"containers": [
|
||||
{
|
||||
"templateUrl": "infobubble.html",
|
||||
"name": "Info Bubble",
|
||||
"type": "infobubble",
|
||||
"key": "infobubble"
|
||||
"key": "bubble",
|
||||
"templateUrl": "bubble.html",
|
||||
"attributes": [ "bubbleTitle", "bubbleLayout" ],
|
||||
"alias": "bubble"
|
||||
}
|
||||
],
|
||||
"gestures": [
|
||||
{
|
||||
"key": "info",
|
||||
"implementation": "gestures/InfoGesture.js",
|
||||
"depends": [
|
||||
"$timeout",
|
||||
"infoService",
|
||||
"INFO_HOVER_DELAY"
|
||||
]
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
{
|
||||
"key": "infoService",
|
||||
"implementation": "services/InfoService.js",
|
||||
"depends": [
|
||||
"$compile",
|
||||
"$document",
|
||||
"$window",
|
||||
"$rootScope"
|
||||
]
|
||||
}
|
||||
],
|
||||
"constants": [
|
||||
{
|
||||
"key": "INFO_HOVER_DELAY",
|
||||
"value": 500
|
||||
}
|
||||
]
|
||||
}
|
||||
|
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>
|
7
platform/commonUI/inspect/res/info-bubble.html
Normal file
7
platform/commonUI/inspect/res/info-bubble.html
Normal file
@ -0,0 +1,7 @@
|
||||
<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,17 @@
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
@import "compass";
|
||||
@import "compass/css3";
|
||||
@import "compass/css3/border-radius";
|
||||
@import "compass/css3/opacity";
|
||||
@import "compass/utilities";
|
||||
|
||||
@import "constants";
|
||||
@import "mixins";
|
||||
@import "plots/plots-main";
|
||||
/*global define*/
|
||||
define({
|
||||
BUBBLE_TEMPLATE: "<mct-container key=\"bubble\" " +
|
||||
"bubble-title=\"{{bubbleTitle}}\" " +
|
||||
"bubble-layout=\"{{bubbleLayout}}\">" +
|
||||
"<mct-include key=\"bubbleTemplate\" ng-model=\"bubbleModel\">" +
|
||||
"</mct-include>" +
|
||||
"</mct-container>",
|
||||
// Pixel offset for bubble, to align arrow position
|
||||
BUBBLE_OFFSET: [ 0, -26 ],
|
||||
// Max width and margins allowed for bubbles; defined in /platform/commonUI/general/res/sass/_constants.scss
|
||||
BUBBLE_MARGIN_LR: 10,
|
||||
BUBBLE_MAX_WIDTH: 300
|
||||
});
|
121
platform/commonUI/inspect/src/gestures/InfoGesture.js
Normal file
121
platform/commonUI/inspect/src/gestures/InfoGesture.js
Normal file
@ -0,0 +1,121 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* The `info` gesture displays domain object metadata in a
|
||||
* bubble on hover.
|
||||
*
|
||||
* @constructor
|
||||
* @param $timeout Angular's `$timeout`
|
||||
* @param {InfoService} infoService a service which shows info bubbles
|
||||
* @param {number} DELAY delay, in milliseconds, before bubble appears
|
||||
* @param element jqLite-wrapped DOM element
|
||||
* @param {DomainObject} domainObject the domain object for which to
|
||||
* show information
|
||||
*/
|
||||
function InfoGesture($timeout, infoService, DELAY, element, domainObject) {
|
||||
var dismissBubble,
|
||||
pendingBubble,
|
||||
mousePosition,
|
||||
scopeOff;
|
||||
|
||||
function trackPosition(event) {
|
||||
// Record mouse position, so bubble can be shown at latest
|
||||
// mouse position (not just where the mouse entered)
|
||||
mousePosition = [ event.clientX, event.clientY ];
|
||||
}
|
||||
|
||||
function hideBubble() {
|
||||
// If a bubble is showing, dismiss it
|
||||
if (dismissBubble) {
|
||||
dismissBubble();
|
||||
element.off('mouseleave', hideBubble);
|
||||
dismissBubble = undefined;
|
||||
}
|
||||
// If a bubble will be shown on a timeout, cancel that
|
||||
if (pendingBubble) {
|
||||
$timeout.cancel(pendingBubble);
|
||||
element.off('mousemove', trackPosition);
|
||||
element.off('mouseleave', hideBubble);
|
||||
pendingBubble = undefined;
|
||||
}
|
||||
// Also clear mouse position so we don't have a ton of tiny
|
||||
// arrays allocated while user mouses over things
|
||||
mousePosition = undefined;
|
||||
}
|
||||
|
||||
function showBubble(event) {
|
||||
trackPosition(event);
|
||||
|
||||
// Also need to track position during hover
|
||||
element.on('mousemove', trackPosition);
|
||||
|
||||
// Show the bubble, after a suitable delay (if mouse has
|
||||
// left before this time is up, this will be canceled.)
|
||||
pendingBubble = $timeout(function () {
|
||||
dismissBubble = infoService.display(
|
||||
"info-table",
|
||||
domainObject.getModel().name,
|
||||
domainObject.useCapability('metadata'),
|
||||
mousePosition
|
||||
);
|
||||
element.off('mousemove', trackPosition);
|
||||
pendingBubble = undefined;
|
||||
}, DELAY);
|
||||
|
||||
element.on('mouseleave', hideBubble);
|
||||
}
|
||||
|
||||
// Show bubble (on a timeout) on mouse over
|
||||
element.on('mouseenter', showBubble);
|
||||
|
||||
// Also make sure we dismiss bubble if representation is destroyed
|
||||
// before the mouse actually leaves it
|
||||
scopeOff = element.scope().$on('$destroy', hideBubble);
|
||||
|
||||
return {
|
||||
/**
|
||||
* Detach any event handlers associated with this gesture.
|
||||
* @memberof InfoGesture
|
||||
* @method
|
||||
*/
|
||||
destroy: function () {
|
||||
// Dismiss any active bubble...
|
||||
hideBubble();
|
||||
// ...and detach listeners
|
||||
element.off('mouseenter', showBubble);
|
||||
scopeOff();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return InfoGesture;
|
||||
|
||||
}
|
||||
|
||||
);
|
95
platform/commonUI/inspect/src/services/InfoService.js
Normal file
95
platform/commonUI/inspect/src/services/InfoService.js
Normal file
@ -0,0 +1,95 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
['../InfoConstants'],
|
||||
function (InfoConstants) {
|
||||
"use strict";
|
||||
|
||||
var BUBBLE_TEMPLATE = InfoConstants.BUBBLE_TEMPLATE,
|
||||
OFFSET = InfoConstants.BUBBLE_OFFSET;
|
||||
|
||||
/**
|
||||
* Displays informative content ("info bubbles") for the user.
|
||||
* @constructor
|
||||
*/
|
||||
function InfoService($compile, $document, $window, $rootScope) {
|
||||
|
||||
function display(templateKey, title, content, position) {
|
||||
var body = $document.find('body'),
|
||||
scope = $rootScope.$new(),
|
||||
winDim = [$window.innerWidth, $window.innerHeight],
|
||||
bubbleSpaceLR = InfoConstants.BUBBLE_MARGIN_LR + InfoConstants.BUBBLE_MAX_WIDTH,
|
||||
goLeft = position[0] > (winDim[0] - bubbleSpaceLR),
|
||||
goUp = position[1] > (winDim[1] / 2),
|
||||
bubble;
|
||||
|
||||
// Pass model & container parameters into the scope
|
||||
scope.bubbleModel = content;
|
||||
scope.bubbleTemplate = templateKey;
|
||||
scope.bubbleLayout = (goUp ? 'arw-btm' : 'arw-top') + ' ' +
|
||||
(goLeft ? 'arw-right' : 'arw-left');
|
||||
scope.bubbleTitle = title;
|
||||
|
||||
// Create the context menu
|
||||
bubble = $compile(BUBBLE_TEMPLATE)(scope);
|
||||
|
||||
// Position the bubble
|
||||
bubble.css('position', 'absolute');
|
||||
if (goLeft) {
|
||||
bubble.css('right', (winDim[0] - position[0] + OFFSET[0]) + 'px');
|
||||
} else {
|
||||
bubble.css('left', position[0] + OFFSET[0] + 'px');
|
||||
}
|
||||
if (goUp) {
|
||||
bubble.css('bottom', (winDim[1] - position[1] + OFFSET[1]) + 'px');
|
||||
} else {
|
||||
bubble.css('top', position[1] + OFFSET[1] + 'px');
|
||||
}
|
||||
|
||||
// Add the menu to the body
|
||||
body.append(bubble);
|
||||
|
||||
// Return a function to dismiss the bubble
|
||||
return function () { bubble.remove(); };
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Display an info bubble at the specified location.
|
||||
* @param {string} templateKey template to place in bubble
|
||||
* @param {string} title title for the bubble
|
||||
* @param {*} content content to pass to the template, via
|
||||
* `ng-model`
|
||||
* @param {number[]} x,y position of the info bubble, in
|
||||
* pixel coordinates.
|
||||
* @returns {Function} a function that may be invoked to
|
||||
* dismiss the info bubble
|
||||
*/
|
||||
display: display
|
||||
};
|
||||
}
|
||||
|
||||
return InfoService;
|
||||
}
|
||||
);
|
157
platform/commonUI/inspect/test/gestures/InfoGestureSpec.js
Normal file
157
platform/commonUI/inspect/test/gestures/InfoGestureSpec.js
Normal file
@ -0,0 +1,157 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
['../../src/gestures/InfoGesture'],
|
||||
function (InfoGesture) {
|
||||
"use strict";
|
||||
|
||||
describe("The info gesture", function () {
|
||||
var mockTimeout,
|
||||
mockInfoService,
|
||||
testDelay = 12321,
|
||||
mockElement,
|
||||
mockDomainObject,
|
||||
mockScope,
|
||||
mockOff,
|
||||
testMetadata,
|
||||
mockPromise,
|
||||
mockHide,
|
||||
gesture;
|
||||
|
||||
function fireEvent(evt, value) {
|
||||
mockElement.on.calls.forEach(function (call) {
|
||||
if (call.args[0] === evt) {
|
||||
call.args[1](value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
mockTimeout = jasmine.createSpy('$timeout');
|
||||
mockTimeout.cancel = jasmine.createSpy('cancel');
|
||||
mockInfoService = jasmine.createSpyObj(
|
||||
'infoService',
|
||||
[ 'display' ]
|
||||
);
|
||||
mockElement = jasmine.createSpyObj(
|
||||
'element',
|
||||
[ 'on', 'off', 'scope', 'css' ]
|
||||
);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getId', 'getCapability', 'useCapability', 'getModel' ]
|
||||
);
|
||||
mockScope = jasmine.createSpyObj('$scope', [ '$on' ]);
|
||||
mockOff = jasmine.createSpy('$off');
|
||||
testMetadata = [ { name: "Test name", value: "Test value" } ];
|
||||
mockPromise = jasmine.createSpyObj('promise', ['then']);
|
||||
mockHide = jasmine.createSpy('hide');
|
||||
|
||||
mockDomainObject.getModel.andReturn({ name: "Test Object" });
|
||||
mockDomainObject.useCapability.andCallFake(function (c) {
|
||||
return (c === 'metadata') ? testMetadata : undefined;
|
||||
});
|
||||
mockElement.scope.andReturn(mockScope);
|
||||
mockScope.$on.andReturn(mockOff);
|
||||
mockTimeout.andReturn(mockPromise);
|
||||
mockInfoService.display.andReturn(mockHide);
|
||||
|
||||
gesture = new InfoGesture(
|
||||
mockTimeout,
|
||||
mockInfoService,
|
||||
testDelay,
|
||||
mockElement,
|
||||
mockDomainObject
|
||||
);
|
||||
});
|
||||
|
||||
it("listens for mouseenter on the representation", function () {
|
||||
expect(mockElement.on)
|
||||
.toHaveBeenCalledWith('mouseenter', jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("displays an info bubble on a delay after mouseenter", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
expect(mockTimeout)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function), testDelay);
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockInfoService.display).toHaveBeenCalledWith(
|
||||
jasmine.any(String),
|
||||
"Test Object",
|
||||
testMetadata,
|
||||
[ 1977, 42 ]
|
||||
);
|
||||
});
|
||||
|
||||
it("does not display info bubble if mouse leaves too soon", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
fireEvent("mouseleave", { clientX: 1977, clientY: 42 });
|
||||
expect(mockTimeout.cancel).toHaveBeenCalledWith(mockPromise);
|
||||
expect(mockInfoService.display).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("hides a shown bubble when mouse leaves", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockHide).not.toHaveBeenCalled(); // verify precondition
|
||||
fireEvent("mouseleave", {});
|
||||
expect(mockHide).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("tracks mouse position", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
fireEvent("mousemove", { clientX: 1999, clientY: 11 });
|
||||
fireEvent("mousemove", { clientX: 1984, clientY: 11 });
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
// Should have displayed at the latest observed mouse position
|
||||
expect(mockInfoService.display).toHaveBeenCalledWith(
|
||||
jasmine.any(String),
|
||||
"Test Object",
|
||||
testMetadata,
|
||||
[ 1984, 11 ]
|
||||
);
|
||||
});
|
||||
|
||||
it("hides shown bubbles when destroyed", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
mockTimeout.mostRecentCall.args[0]();
|
||||
expect(mockHide).not.toHaveBeenCalled(); // verify precondition
|
||||
gesture.destroy();
|
||||
expect(mockHide).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("detaches listeners when destroyed", function () {
|
||||
fireEvent("mouseenter", { clientX: 1977, clientY: 42 });
|
||||
gesture.destroy();
|
||||
mockElement.on.calls.forEach(function (call) {
|
||||
expect(mockElement.off).toHaveBeenCalledWith(
|
||||
call.args[0],
|
||||
call.args[1]
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
131
platform/commonUI/inspect/test/services/InfoServiceSpec.js
Normal file
131
platform/commonUI/inspect/test/services/InfoServiceSpec.js
Normal file
@ -0,0 +1,131 @@
|
||||
/*****************************************************************************
|
||||
* Open MCT Web, Copyright (c) 2014-2015, United States Government
|
||||
* as represented by the Administrator of the National Aeronautics and Space
|
||||
* Administration. All rights reserved.
|
||||
*
|
||||
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* http://www.apache.org/licenses/LICENSE-2.0.
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
* License for the specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*
|
||||
* Open MCT Web includes source code licensed under additional open source
|
||||
* licenses. See the Open Source Licenses file (LICENSES.md) included with
|
||||
* this source code distribution or the Licensing information page available
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
['../../src/services/InfoService', '../../src/InfoConstants'],
|
||||
function (InfoService, InfoConstants) {
|
||||
"use strict";
|
||||
|
||||
describe("The info service", function () {
|
||||
var mockCompile,
|
||||
mockDocument,
|
||||
testWindow,
|
||||
mockRootScope,
|
||||
mockCompiledTemplate,
|
||||
testScope,
|
||||
mockBody,
|
||||
mockElement,
|
||||
service;
|
||||
|
||||
beforeEach(function () {
|
||||
mockCompile = jasmine.createSpy('$compile');
|
||||
mockDocument = jasmine.createSpyObj('$document', ['find']);
|
||||
testWindow = { innerWidth: 1000, innerHeight: 100 };
|
||||
mockRootScope = jasmine.createSpyObj('$rootScope', ['$new']);
|
||||
mockCompiledTemplate = jasmine.createSpy('template');
|
||||
testScope = {};
|
||||
mockBody = jasmine.createSpyObj('body', ['append']);
|
||||
mockElement = jasmine.createSpyObj('element', ['css', 'remove']);
|
||||
|
||||
mockDocument.find.andCallFake(function (tag) {
|
||||
return tag === 'body' ? mockBody : undefined;
|
||||
});
|
||||
mockCompile.andReturn(mockCompiledTemplate);
|
||||
mockCompiledTemplate.andReturn(mockElement);
|
||||
mockRootScope.$new.andReturn(testScope);
|
||||
|
||||
service = new InfoService(
|
||||
mockCompile,
|
||||
mockDocument,
|
||||
testWindow,
|
||||
mockRootScope
|
||||
);
|
||||
});
|
||||
|
||||
it("creates elements and appends them to the body to display", function () {
|
||||
service.display('', '', {}, [0, 0]);
|
||||
expect(mockBody.append).toHaveBeenCalledWith(mockElement);
|
||||
});
|
||||
|
||||
it("provides a function to remove displayed info bubbles", function () {
|
||||
var fn = service.display('', '', {}, [0, 0]);
|
||||
expect(mockElement.remove).not.toHaveBeenCalled();
|
||||
fn();
|
||||
expect(mockElement.remove).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
describe("depending on mouse position", function () {
|
||||
// Positioning should vary based on quadrant in window,
|
||||
// which is 1000 x 100 in this test case.
|
||||
it("displays from the top-left in the top-left quadrant", function () {
|
||||
service.display('', '', {}, [250, 25]);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'left',
|
||||
(250 + InfoConstants.BUBBLE_OFFSET[0]) + 'px'
|
||||
);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'top',
|
||||
(25 + InfoConstants.BUBBLE_OFFSET[1]) + 'px'
|
||||
);
|
||||
});
|
||||
|
||||
it("displays from the top-right in the top-right quadrant", function () {
|
||||
service.display('', '', {}, [700, 25]);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'right',
|
||||
(300 + InfoConstants.BUBBLE_OFFSET[0]) + 'px'
|
||||
);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'top',
|
||||
(25 + InfoConstants.BUBBLE_OFFSET[1]) + 'px'
|
||||
);
|
||||
});
|
||||
|
||||
it("displays from the bottom-left in the bottom-left quadrant", function () {
|
||||
service.display('', '', {}, [250, 70]);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'left',
|
||||
(250 + InfoConstants.BUBBLE_OFFSET[0]) + 'px'
|
||||
);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'bottom',
|
||||
(30 + InfoConstants.BUBBLE_OFFSET[1]) + 'px'
|
||||
);
|
||||
});
|
||||
|
||||
it("displays from the bottom-right in the bottom-right quadrant", function () {
|
||||
service.display('', '', {}, [800, 60]);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'right',
|
||||
(200 + InfoConstants.BUBBLE_OFFSET[0]) + 'px'
|
||||
);
|
||||
expect(mockElement.css).toHaveBeenCalledWith(
|
||||
'bottom',
|
||||
(40 + InfoConstants.BUBBLE_OFFSET[1]) + 'px'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
4
platform/commonUI/inspect/test/suite.json
Normal file
4
platform/commonUI/inspect/test/suite.json
Normal file
@ -0,0 +1,4 @@
|
||||
[
|
||||
"gestures/InfoGesture",
|
||||
"services/InfoService"
|
||||
]
|
@ -12,6 +12,11 @@
|
||||
"implementation": "CompositionMutabilityPolicy.js",
|
||||
"message": "Objects of this type cannot be modified."
|
||||
},
|
||||
{
|
||||
"category": "composition",
|
||||
"implementation": "CompositionModelPolicy.js",
|
||||
"message": "Objects of this type cannot contain other objects."
|
||||
},
|
||||
{
|
||||
"category": "action",
|
||||
"implementation": "ComposeActionPolicy.js",
|
||||
|
28
platform/containment/src/CompositionModelPolicy.js
Normal file
28
platform/containment/src/CompositionModelPolicy.js
Normal file
@ -0,0 +1,28 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
[],
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* Policy allowing composition only for domain object types which
|
||||
* have a composition property.
|
||||
*/
|
||||
function CompositionModelPolicy() {
|
||||
return {
|
||||
/**
|
||||
* Is the type identified by the candidate allowed to
|
||||
* contain the type described by the context?
|
||||
*/
|
||||
allow: function (candidate, context) {
|
||||
return Array.isArray(
|
||||
(candidate.getInitialModel() || {}).composition
|
||||
);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
return CompositionModelPolicy;
|
||||
}
|
||||
);
|
26
platform/containment/test/CompositionModelPolicySpec.js
Normal file
26
platform/containment/test/CompositionModelPolicySpec.js
Normal file
@ -0,0 +1,26 @@
|
||||
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/CompositionModelPolicy"],
|
||||
function (CompositionModelPolicy) {
|
||||
"use strict";
|
||||
|
||||
describe("The composition model policy", function () {
|
||||
var mockType,
|
||||
policy;
|
||||
|
||||
beforeEach(function () {
|
||||
mockType = jasmine.createSpyObj('type', ['getInitialModel']);
|
||||
policy = new CompositionModelPolicy();
|
||||
});
|
||||
|
||||
it("only allows composition for types which will have a composition property", function () {
|
||||
mockType.getInitialModel.andReturn({});
|
||||
expect(policy.allow(mockType)).toBeFalsy();
|
||||
mockType.getInitialModel.andReturn({ composition: [] });
|
||||
expect(policy.allow(mockType)).toBeTruthy();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
);
|
@ -35,7 +35,7 @@ define(
|
||||
policy = new CompositionMutabilityPolicy();
|
||||
});
|
||||
|
||||
it("only allows composition for types which will have a composition capability", function () {
|
||||
it("only allows composition for types which can be created/modified", function () {
|
||||
expect(policy.allow(mockType)).toBeFalsy();
|
||||
mockType.hasFeature.andReturn(true);
|
||||
expect(policy.allow(mockType)).toBeTruthy();
|
||||
|
@ -1,6 +1,7 @@
|
||||
[
|
||||
"CapabilityTable",
|
||||
"ComposeActionPolicy",
|
||||
"CompositionModelPolicy",
|
||||
"CompositionMutabilityPolicy",
|
||||
"CompositionPolicy",
|
||||
"ContainmentTable"
|
||||
|
@ -165,6 +165,10 @@
|
||||
"implementation": "capabilities/PersistenceCapability.js",
|
||||
"depends": [ "persistenceService", "PERSISTENCE_SPACE" ]
|
||||
},
|
||||
{
|
||||
"key": "metadata",
|
||||
"implementation": "capabilities/MetadataCapability.js"
|
||||
},
|
||||
{
|
||||
"key": "mutation",
|
||||
"implementation": "capabilities/MutationCapability.js",
|
||||
|
92
platform/core/src/capabilities/MetadataCapability.js
Normal file
92
platform/core/src/capabilities/MetadataCapability.js
Normal file
@ -0,0 +1,92 @@
|
||||
/*global define*/
|
||||
|
||||
define(
|
||||
['moment'],
|
||||
function (moment) {
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* A piece of information about a domain object.
|
||||
* @typedef {Object} MetadataProperty
|
||||
* @property {string} name the human-readable name of this property
|
||||
* @property {string} value the human-readable value of this property,
|
||||
* for this specific domain object
|
||||
*/
|
||||
|
||||
var TIME_FORMAT = "YYYY-MM-DD HH:mm:ss";
|
||||
|
||||
/**
|
||||
* Implements the `metadata` capability of a domain object, providing
|
||||
* properties of that object for display.
|
||||
*
|
||||
* Usage: `domainObject.useCapability("metadata")`
|
||||
*
|
||||
* ...which will return an array of objects containing `name` and
|
||||
* `value` properties describing that domain object (suitable for
|
||||
* display.)
|
||||
*
|
||||
* @constructor
|
||||
*/
|
||||
function MetadataCapability(domainObject) {
|
||||
var model = domainObject.getModel();
|
||||
|
||||
function hasDisplayableValue(metadataProperty) {
|
||||
var t = typeof metadataProperty.value;
|
||||
return (t === 'string' || t === 'number');
|
||||
}
|
||||
|
||||
function formatTimestamp(timestamp) {
|
||||
return typeof timestamp === 'number' ?
|
||||
(moment.utc(timestamp).format(TIME_FORMAT) + " UTC") :
|
||||
undefined;
|
||||
}
|
||||
|
||||
function getProperties() {
|
||||
var type = domainObject.getCapability('type');
|
||||
|
||||
function lookupProperty(typeProperty) {
|
||||
return {
|
||||
name: typeProperty.getDefinition().name,
|
||||
value: typeProperty.getValue(model)
|
||||
};
|
||||
}
|
||||
|
||||
return (type ? type.getProperties() : []).map(lookupProperty);
|
||||
}
|
||||
|
||||
function getCommonMetadata() {
|
||||
var type = domainObject.getCapability('type');
|
||||
// Note that invalid values will be filtered out later
|
||||
return [
|
||||
{
|
||||
name: "Updated",
|
||||
value: formatTimestamp(model.modified)
|
||||
},
|
||||
{
|
||||
name: "Type",
|
||||
value: type && type.getName()
|
||||
},
|
||||
{
|
||||
name: "ID",
|
||||
value: domainObject.getId()
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
function getMetadata() {
|
||||
return getProperties().concat(getCommonMetadata())
|
||||
.filter(hasDisplayableValue);
|
||||
}
|
||||
|
||||
return {
|
||||
/**
|
||||
* Get metadata about this object.
|
||||
* @returns {MetadataProperty[]} metadata about this object
|
||||
*/
|
||||
invoke: getMetadata
|
||||
};
|
||||
}
|
||||
|
||||
return MetadataCapability;
|
||||
}
|
||||
);
|
@ -77,7 +77,8 @@ define(
|
||||
// Get the object's model and clone it, so the
|
||||
// mutator function has a temporary copy to work with.
|
||||
var model = domainObject.getModel(),
|
||||
clone = JSON.parse(JSON.stringify(model));
|
||||
clone = JSON.parse(JSON.stringify(model)),
|
||||
useTimestamp = arguments.length > 1;
|
||||
|
||||
// Function to handle copying values to the actual
|
||||
function handleMutation(mutationResult) {
|
||||
@ -94,8 +95,7 @@ define(
|
||||
if (model !== result) {
|
||||
copyValues(model, result);
|
||||
}
|
||||
model.modified = (typeof timestamp === 'number') ?
|
||||
timestamp : now();
|
||||
model.modified = useTimestamp ? timestamp : now();
|
||||
}
|
||||
|
||||
// Report the result of the mutation
|
||||
|
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");
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
@ -9,6 +9,7 @@
|
||||
"capabilities/ContextualDomainObject",
|
||||
"capabilities/CoreCapabilityProvider",
|
||||
"capabilities/DelegationCapability",
|
||||
"capabilities/MetadataCapability",
|
||||
"capabilities/MutationCapability",
|
||||
"capabilities/PersistenceCapability",
|
||||
"capabilities/RelationshipCapability",
|
||||
|
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"
|
||||
]
|
@ -34,50 +34,62 @@
|
||||
|
||||
<!-- Drag handles -->
|
||||
<span ng-show="domainObject.hasCapability('editor')">
|
||||
<span style="position: absolute; left: 12px; right: 12px; top: 12px; bottom: 12px; cursor: move;"
|
||||
|
||||
<span
|
||||
class="edit-handle edit-move"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [1,1], [0,0])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()">
|
||||
</span>
|
||||
|
||||
<span style="position: absolute; left: 0px; width: 12px; top: 12px; bottom: 12px; cursor: w-resize;"
|
||||
<!--
|
||||
<span
|
||||
class="edit-handle edit-resize-w"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [1,0], [-1,0])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()">
|
||||
</span>
|
||||
<span style="position: absolute; right: 0px; width: 12px; top: 12px; bottom: 12px; cursor: e-resize;"
|
||||
<span
|
||||
class="edit-handle edit-resize-e"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [0,0], [1,0])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()">
|
||||
</span>
|
||||
|
||||
<span style="position: absolute; left: 12px; right: 12px; top: 0px; height: 12px; cursor: n-resize;"
|
||||
<span
|
||||
class="edit-handle edit-resize-n"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [0,1], [0,-1])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()">
|
||||
</span>
|
||||
<span style="position: absolute; left: 12px; right: 12px; bottom: 0px; height: 12px; cursor: s-resize;"
|
||||
<span
|
||||
class="edit-handle edit-resize-s"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [0,0], [0,1])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()">
|
||||
</span>
|
||||
-->
|
||||
|
||||
<span style="position: absolute; left: 0px; width: 12px; top: 0px; height: 12px; cursor: nw-resize;"
|
||||
<span
|
||||
class="edit-corner edit-resize-nw"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [1,1], [-1,-1])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()">
|
||||
</span>
|
||||
<span style="position: absolute; right: 0px; width: 12px; top: 0px; height: 12px; cursor: ne-resize;"
|
||||
<!--span
|
||||
class="edit-corner edit-resize-nw"
|
||||
style="position: absolute; right: 0px; width: 12px; top: 0px; height: 12px; cursor: ne-resize;"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [0,1], [1,-1])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()">
|
||||
</span>
|
||||
<span style="position: absolute; left: 0px; width: 12px; bottom: 0px; height: 12px; cursor: sw-resize;"
|
||||
</span-->
|
||||
<span
|
||||
class="edit-corner edit-resize-sw"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [1,0], [-1,1])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()">
|
||||
</span>
|
||||
<span style="position: absolute; right: 0px; width: 12px; bottom: 0px; height: 12px; cursor: se-resize;"
|
||||
<span
|
||||
class="edit-corner edit-resize-se"
|
||||
mct-drag-down="controller.startDrag(childObject.getId(), [0,0], [1,1])"
|
||||
mct-drag="controller.continueDrag(delta)"
|
||||
mct-drag-up="controller.endDrag()">
|
||||
|
@ -8,6 +8,7 @@
|
||||
"glyph": "6",
|
||||
"templateUrl": "templates/plot.html",
|
||||
"needs": [ "telemetry" ],
|
||||
"priority": "preferred",
|
||||
"delegation": true
|
||||
}
|
||||
],
|
||||
|
@ -22,16 +22,16 @@
|
||||
<span ng-controller="PlotController as plot"
|
||||
ng-mouseleave="representation.showControls = false">
|
||||
|
||||
<div class="gl-plot"
|
||||
<div class="gl-plot"
|
||||
ng-style="{ height: 100 / plot.getSubPlots().length + '%'}"
|
||||
ng-repeat="subplot in plot.getSubPlots()">
|
||||
<div class="gl-plot-legend">
|
||||
<!-- ng-class is temporarily hard-coded in next element -->
|
||||
<!-- ng-class is temporarily hard-coded in next element -->
|
||||
<span
|
||||
class='plot-legend-item'
|
||||
class='plot-legend-item'
|
||||
ng-repeat="telemetryObject in subplot.getTelemetryObjects()"
|
||||
ng-class="plot.getLegendClass(telemetryObject)"
|
||||
>
|
||||
>
|
||||
<span class='plot-color-swatch'
|
||||
ng-style="{ 'background-color': plot.getColor($index) }">
|
||||
</span>
|
||||
@ -40,9 +40,9 @@
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="gl-plot-coords"
|
||||
ng-if="subplot.isHovering() && subplot.getHoverCoordinates()"
|
||||
>
|
||||
class="gl-plot-coords"
|
||||
ng-if="subplot.isHovering() && subplot.getHoverCoordinates()"
|
||||
>
|
||||
{{subplot.getHoverCoordinates()}}
|
||||
</div>
|
||||
|
||||
@ -75,8 +75,8 @@
|
||||
ng-mouseenter="subplot.isHovering(true); representation.showControls = true;"
|
||||
ng-mouseleave="subplot.isHovering(false)">
|
||||
|
||||
<!-- Out-of-bounds data indicators -->
|
||||
<!-- ng-show is temporarily hard-coded in next element -->
|
||||
<!-- Out-of-bounds data indicators -->
|
||||
<!-- ng-show is temporarily hard-coded in next element -->
|
||||
<div ng-show="1" class="l-oob-data l-oob-data-up"></div>
|
||||
<div ng-show="1" class="l-oob-data l-oob-data-dwn"></div>
|
||||
|
||||
@ -98,7 +98,7 @@
|
||||
</mct-chart>
|
||||
|
||||
<!-- TODO: Move into correct position; make part of group; infer from set of actions -->
|
||||
<div class="gl-plot-local-controls"
|
||||
<div class="l-local-controls gl-plot-local-controls"
|
||||
ng-if="$first"
|
||||
ng-show="representation.showControls"
|
||||
style="position: absolute; top: 8px; right: 8px;">
|
||||
@ -119,7 +119,7 @@
|
||||
<span class="ui-symbol icon">I</span>
|
||||
</a>
|
||||
|
||||
<div class="menu-element btn icon-btn very-subtle btn-menu dropdown click-invoke"
|
||||
<div class="menu-element btn s-very-subtle btn-menu dropdown menus-to-left"
|
||||
ng-if="plot.getModeOptions().length > 1"
|
||||
ng-controller="ClickAwayController as toggle">
|
||||
|
||||
@ -127,7 +127,7 @@
|
||||
|
||||
<span class="ui-symbol icon type-icon">{{plot.getMode().glyph}}</span>
|
||||
<span>{{plot.getMode().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()">
|
||||
<ul>
|
||||
|
@ -30,7 +30,7 @@
|
||||
<span class="title-label" ng-if="structure.text">
|
||||
{{structure.text}}
|
||||
</span>
|
||||
<span class='ui-symbol icon invoke-menu' ng-if="!structure.text">v</span>
|
||||
<span class='ui-symbol invoke-menu' ng-if="!structure.text">v</span>
|
||||
|
||||
|
||||
<div
|
||||
|
@ -38,7 +38,7 @@
|
||||
placeholder="YYYY-DDD"
|
||||
ng-pattern="/\d\d\d\d-\d\d\d/"
|
||||
ng-model='datetime.date'
|
||||
ng-required='true'/>
|
||||
ng-required='ngRequired || partiallyComplete'/>
|
||||
</span>
|
||||
<span class='field control time sm'>
|
||||
<input type='text'
|
||||
@ -49,7 +49,7 @@
|
||||
integer
|
||||
ng-pattern='/\d+/'
|
||||
ng-model="datetime.hour"
|
||||
ng-required='true'/>
|
||||
ng-required='ngRequired || partiallyComplete'/>
|
||||
</span>
|
||||
<span class='field control time sm'>
|
||||
<input type='text'
|
||||
@ -60,7 +60,7 @@
|
||||
integer
|
||||
ng-pattern='/\d+/'
|
||||
ng-model="datetime.min"
|
||||
ng-required='true'/>
|
||||
ng-required='ngRequired || partiallyComplete'/>
|
||||
</span>
|
||||
<span class='field control time sm'>
|
||||
<input type='text'
|
||||
@ -71,7 +71,7 @@
|
||||
integer
|
||||
ng-pattern='/\d+/'
|
||||
ng-model="datetime.sec"
|
||||
ng-required='true'/>
|
||||
ng-required='ngRequired || partiallyComplete'/>
|
||||
</span>
|
||||
<span class='field control timezone'>
|
||||
UTC
|
||||
|
@ -28,7 +28,7 @@
|
||||
<span class="title-label" ng-if="structure.text">
|
||||
{{structure.text}}
|
||||
</span>
|
||||
<span class='ui-symbol icon invoke-menu'
|
||||
<span class='ui-symbol invoke-menu'
|
||||
ng-if="!structure.text">
|
||||
v
|
||||
</span>
|
||||
|
@ -52,15 +52,51 @@ define(
|
||||
if (fullDateTime.isValid()) {
|
||||
$scope.ngModel[$scope.field] = fullDateTime.valueOf();
|
||||
}
|
||||
|
||||
// If anything is complete, say so in scope; there are
|
||||
// ng-required usages that will update off of this (to
|
||||
// allow datetime to be optional while still permitting
|
||||
// incomplete input)
|
||||
$scope.partiallyComplete =
|
||||
Object.keys($scope.datetime).some(function (key) {
|
||||
return $scope.datetime[key];
|
||||
});
|
||||
|
||||
// Treat empty input as an undefined value
|
||||
if (!$scope.partiallyComplete) {
|
||||
$scope.ngModel[$scope.field] = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function updateDateTime(value) {
|
||||
var m;
|
||||
if (value !== undefined) {
|
||||
m = moment.utc(value);
|
||||
$scope.datetime = {
|
||||
date: m.format(DATE_FORMAT),
|
||||
hour: m.format("H"),
|
||||
min: m.format("m"),
|
||||
sec: m.format("s")
|
||||
};
|
||||
} else {
|
||||
$scope.datetime = {};
|
||||
}
|
||||
}
|
||||
|
||||
// ...and update form values when actual field in model changes
|
||||
$scope.$watch("ngModel[field]", updateDateTime);
|
||||
|
||||
// Update value whenever any field changes.
|
||||
$scope.$watch("datetime.date", update);
|
||||
$scope.$watch("datetime.hour", update);
|
||||
$scope.$watch("datetime.min", update);
|
||||
$scope.$watch("datetime.sec", update);
|
||||
|
||||
$scope.datetime = {};
|
||||
// Initialize forms values
|
||||
updateDateTime(
|
||||
($scope.ngModel && $scope.field) ?
|
||||
$scope.ngModel[$scope.field] : undefined
|
||||
);
|
||||
}
|
||||
|
||||
return DateTimeController;
|
||||
|
@ -57,6 +57,49 @@ define(
|
||||
expect(mockScope.ngModel.test).toEqual(1417215313000);
|
||||
});
|
||||
|
||||
it("reports when form input is partially complete", function () {
|
||||
// This is needed to flag the control's state as invalid
|
||||
// when it is partially complete without having it treated
|
||||
// as required.
|
||||
mockScope.ngModel = {};
|
||||
mockScope.field = "test";
|
||||
mockScope.datetime.date = "2014-332";
|
||||
mockScope.datetime.hour = 22;
|
||||
mockScope.datetime.min = 55;
|
||||
// mockScope.datetime.sec = 13;
|
||||
|
||||
mockScope.$watch.mostRecentCall.args[1]();
|
||||
|
||||
expect(mockScope.partiallyComplete).toBeTruthy();
|
||||
});
|
||||
|
||||
it("reports 'undefined' for empty input", function () {
|
||||
mockScope.ngModel = { test: 12345 };
|
||||
mockScope.field = "test";
|
||||
mockScope.$watch.mostRecentCall.args[1]();
|
||||
// Clear all inputs
|
||||
mockScope.datetime = {};
|
||||
mockScope.$watch.mostRecentCall.args[1]();
|
||||
|
||||
// Should have cleared out the time stamp
|
||||
expect(mockScope.ngModel.test).toBeUndefined();
|
||||
});
|
||||
|
||||
it("initializes form fields with values from ng-model", function () {
|
||||
mockScope.ngModel = { test: 1417215313000 };
|
||||
mockScope.field = "test";
|
||||
mockScope.$watch.calls.forEach(function (call) {
|
||||
if (call.args[0] === 'ngModel[field]') {
|
||||
call.args[1](mockScope.ngModel.test);
|
||||
}
|
||||
});
|
||||
expect(mockScope.datetime).toEqual({
|
||||
date: "2014-332",
|
||||
hour: "22",
|
||||
min: "55",
|
||||
sec: "13"
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
@ -17,15 +17,18 @@
|
||||
},
|
||||
{
|
||||
"key": "ELASTIC_ROOT",
|
||||
"value": "/elastic"
|
||||
"value": "/elastic",
|
||||
"priority": "fallback"
|
||||
},
|
||||
{
|
||||
"key": "ELASTIC_PATH",
|
||||
"value": "mct/domain_object"
|
||||
"value": "mct/domain_object",
|
||||
"priority": "fallback"
|
||||
},
|
||||
{
|
||||
"key": "ELASTIC_INDICATOR_INTERVAL",
|
||||
"value": 15000
|
||||
"value": 15000,
|
||||
"priority": "fallback"
|
||||
}
|
||||
],
|
||||
"indicators": [
|
||||
|
@ -92,17 +92,24 @@ define(
|
||||
|
||||
function drop(e) {
|
||||
var event = (e || {}).originalEvent || e,
|
||||
id = event.dataTransfer.getData(GestureConstants.MCT_DRAG_TYPE);
|
||||
id = event.dataTransfer.getData(GestureConstants.MCT_DRAG_TYPE),
|
||||
domainObjectType = domainObject.getModel().type;
|
||||
|
||||
// Handle the drop; add the dropped identifier to the
|
||||
// destination domain object's composition, and persist
|
||||
// the change.
|
||||
if (id) {
|
||||
$q.when(action && action.perform()).then(function (result) {
|
||||
broadcastDrop(id, event);
|
||||
});
|
||||
// If currently in edit mode allow drag and drop gestures to the
|
||||
// domain object. An exception to this is folders which have drop
|
||||
// gestures in browse mode.
|
||||
if (domainObjectType === 'folder' || domainObject.hasCapability('editor')) {
|
||||
|
||||
// Handle the drop; add the dropped identifier to the
|
||||
// destination domain object's composition, and persist
|
||||
// the change.
|
||||
if (id) {
|
||||
$q.when(action && action.perform()).then(function (result) {
|
||||
broadcastDrop(id, event);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Alert user if drag and drop is not allowed
|
||||
}
|
||||
|
||||
// We can only handle drops if we have access to actions...
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user