Compare commits
	
		
			180 Commits
		
	
	
		
			plot-telem
			...
			telemetry-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					b939eb2fbe | ||
| 
						 | 
					1afecdc82c | ||
| 
						 | 
					b9cda6985e | ||
| 
						 | 
					401b7e3f19 | ||
| 
						 | 
					c9e9845172 | ||
| 
						 | 
					abbba38eac | ||
| 
						 | 
					db856251da | ||
| 
						 | 
					e1566e448d | ||
| 
						 | 
					d9aae0700c | ||
| 
						 | 
					8703f363b8 | ||
| 
						 | 
					26210eaa50 | ||
| 
						 | 
					a4a1cb5e05 | ||
| 
						 | 
					9570f2f7a1 | ||
| 
						 | 
					eb4ded39b3 | ||
| 
						 | 
					5c29726cc0 | ||
| 
						 | 
					5c207c3fe0 | ||
| 
						 | 
					eba1dd1a4e | ||
| 
						 | 
					570edc0dec | ||
| 
						 | 
					ad6bcd4ef8 | ||
| 
						 | 
					aedbbbbf75 | ||
| 
						 | 
					3caaf00483 | ||
| 
						 | 
					971eda4d88 | ||
| 
						 | 
					090d216517 | ||
| 
						 | 
					7deb3cd025 | ||
| 
						 | 
					d42d7ae68d | ||
| 
						 | 
					06779e6cd9 | ||
| 
						 | 
					7f43c0bf1a | ||
| 
						 | 
					68e6e3c121 | ||
| 
						 | 
					7e7f39db2d | ||
| 
						 | 
					b6e0fca828 | ||
| 
						 | 
					ffc5896e5a | ||
| 
						 | 
					fd6ebd152f | ||
| 
						 | 
					7a5c1c0e1f | ||
| 
						 | 
					2f7e1e3f1a | ||
| 
						 | 
					d73746b51b | ||
| 
						 | 
					2df54af019 | ||
| 
						 | 
					586269f761 | ||
| 
						 | 
					e536ab34d7 | ||
| 
						 | 
					e15002dd72 | ||
| 
						 | 
					453cf3ad6a | ||
| 
						 | 
					5c46e48bde | ||
| 
						 | 
					bfa3bbcdc7 | ||
| 
						 | 
					2baf3f8bb0 | ||
| 
						 | 
					868ea9362f | ||
| 
						 | 
					10ac13ac5c | ||
| 
						 | 
					138cb199bb | ||
| 
						 | 
					374c363a78 | ||
| 
						 | 
					d69106ff2c | ||
| 
						 | 
					e9cb5cd639 | ||
| 
						 | 
					bc7d92ee0d | ||
| 
						 | 
					1658b17c56 | ||
| 
						 | 
					78f49784a0 | ||
| 
						 | 
					39cf0528ca | ||
| 
						 | 
					3d12f7312b | ||
| 
						 | 
					22481fdc31 | ||
| 
						 | 
					4a9d27dc79 | ||
| 
						 | 
					a5a9fefd40 | ||
| 
						 | 
					dae4074934 | ||
| 
						 | 
					a540a3573f | ||
| 
						 | 
					4e7fe9082c | ||
| 
						 | 
					568141bf81 | ||
| 
						 | 
					ac3ea43fe5 | ||
| 
						 | 
					e922e8d504 | ||
| 
						 | 
					650a877d2a | ||
| 
						 | 
					1202109c59 | ||
| 
						 | 
					429d7bbd57 | ||
| 
						 | 
					af749fe71b | ||
| 
						 | 
					cf64c512ce | ||
| 
						 | 
					14592d1c3e | ||
| 
						 | 
					8754c438cc | ||
| 
						 | 
					c5bd3da44a | ||
| 
						 | 
					ff3e49e926 | ||
| 
						 | 
					e244a3e431 | ||
| 
						 | 
					1419c75503 | ||
| 
						 | 
					c5d9fb6fd9 | ||
| 
						 | 
					ca8cad0a74 | ||
| 
						 | 
					4c276ab422 | ||
| 
						 | 
					bf321abae4 | ||
| 
						 | 
					7336968ef9 | ||
| 
						 | 
					d60956948b | ||
| 
						 | 
					23d5c2e1ee | ||
| 
						 | 
					2632b8891a | ||
| 
						 | 
					fff4cd9d51 | ||
| 
						 | 
					7f9fd5c705 | ||
| 
						 | 
					a3a55d3b48 | ||
| 
						 | 
					be0291cf70 | ||
| 
						 | 
					b3a6d7271d | ||
| 
						 | 
					ebeed2f236 | ||
| 
						 | 
					e66f818996 | ||
| 
						 | 
					337c26c019 | ||
| 
						 | 
					730f363f94 | ||
| 
						 | 
					ae30e6110b | ||
| 
						 | 
					6e4bf3e45b | ||
| 
						 | 
					5465ca92f9 | ||
| 
						 | 
					e55ea41b0a | ||
| 
						 | 
					8cfb3cc689 | ||
| 
						 | 
					2d728a1362 | ||
| 
						 | 
					99333988df | ||
| 
						 | 
					de783d4286 | ||
| 
						 | 
					1e1a2443d5 | ||
| 
						 | 
					d65e1e604e | ||
| 
						 | 
					f6c1488ccd | ||
| 
						 | 
					26be1ecf37 | ||
| 
						 | 
					38f0f072bb | ||
| 
						 | 
					e5e969665f | ||
| 
						 | 
					ffbb662c99 | ||
| 
						 | 
					bd7b23f896 | ||
| 
						 | 
					c238def902 | ||
| 
						 | 
					2d430ece7f | ||
| 
						 | 
					c92644a661 | ||
| 
						 | 
					41ce3c04f7 | ||
| 
						 | 
					fcf77f359f | ||
| 
						 | 
					40a2737915 | ||
| 
						 | 
					216489d67f | ||
| 
						 | 
					418a393b26 | ||
| 
						 | 
					1f3d744494 | ||
| 
						 | 
					ff3f2dccba | ||
| 
						 | 
					e69973bd29 | ||
| 
						 | 
					05b352cc36 | ||
| 
						 | 
					9735548999 | ||
| 
						 | 
					f9529b1362 | ||
| 
						 | 
					c598cec702 | ||
| 
						 | 
					e9ea1c4a0f | ||
| 
						 | 
					e9238ff282 | ||
| 
						 | 
					4cebd72cba | ||
| 
						 | 
					f8a44d6e71 | ||
| 
						 | 
					d0745b300b | ||
| 
						 | 
					2a4e0a3081 | ||
| 
						 | 
					1ff19f9574 | ||
| 
						 | 
					7ef84cb50d | ||
| 
						 | 
					cd05c70d64 | ||
| 
						 | 
					568473b82f | ||
| 
						 | 
					c61b074755 | ||
| 
						 | 
					8ed66ab4ab | ||
| 
						 | 
					b2502dd998 | ||
| 
						 | 
					856eedbf9d | ||
| 
						 | 
					0c0ca6e6af | ||
| 
						 | 
					498b797e49 | ||
| 
						 | 
					02c33388ba | ||
| 
						 | 
					8a8e3cc055 | ||
| 
						 | 
					36d60b16e9 | ||
| 
						 | 
					de3114568b | ||
| 
						 | 
					eb5835faeb | ||
| 
						 | 
					ff1ddb0b79 | ||
| 
						 | 
					15b127bb2e | ||
| 
						 | 
					e4ed881f6d | ||
| 
						 | 
					7b62cf130c | ||
| 
						 | 
					72fd2e531c | ||
| 
						 | 
					4a5392ef78 | ||
| 
						 | 
					0150a708ca | ||
| 
						 | 
					eacc181d5e | ||
| 
						 | 
					405bb55881 | ||
| 
						 | 
					4a35508459 | ||
| 
						 | 
					98a9d71a2e | ||
| 
						 | 
					a1596d0b06 | ||
| 
						 | 
					4b3be4c483 | ||
| 
						 | 
					0fa8472db1 | ||
| 
						 | 
					e1e2dca1d8 | ||
| 
						 | 
					755c013ec8 | ||
| 
						 | 
					eab702b763 | ||
| 
						 | 
					d15446ac91 | ||
| 
						 | 
					500733afb2 | ||
| 
						 | 
					2aa04b0a56 | ||
| 
						 | 
					c051f342af | ||
| 
						 | 
					8aeb365f5f | ||
| 
						 | 
					827a28313d | ||
| 
						 | 
					c83de8aad2 | ||
| 
						 | 
					b55f43b8df | ||
| 
						 | 
					8466723a90 | ||
| 
						 | 
					a103b4dbff | ||
| 
						 | 
					826ac3a947 | ||
| 
						 | 
					597327f138 | ||
| 
						 | 
					bef79402ca | ||
| 
						 | 
					e68e0c381f | ||
| 
						 | 
					c73f7259c2 | ||
| 
						 | 
					4c9235ba10 | ||
| 
						 | 
					55e2a77df8 | ||
| 
						 | 
					cfbff02e7f | ||
| 
						 | 
					54980fb296 | ||
| 
						 | 
					ba98d9315c | 
@@ -18,7 +18,7 @@
 | 
			
		||||
    "node-uuid": "^1.4.7",
 | 
			
		||||
    "comma-separated-values": "^3.6.4",
 | 
			
		||||
    "FileSaver.js": "^0.0.2",
 | 
			
		||||
    "zepto": "^1.1.6",
 | 
			
		||||
    "zepto": "1.2.0",
 | 
			
		||||
    "eventemitter3": "^1.2.0",
 | 
			
		||||
    "lodash": "3.10.1",
 | 
			
		||||
    "almond": "~0.3.2",
 | 
			
		||||
 
 | 
			
		||||
@@ -59,7 +59,7 @@ define([
 | 
			
		||||
            if (domainObject.telemetry && domainObject.telemetry.hasOwnProperty(prop)) {
 | 
			
		||||
                workerRequest[prop] = domainObject.telemetry[prop];
 | 
			
		||||
            }
 | 
			
		||||
            if (request.hasOwnProperty(prop)) {
 | 
			
		||||
            if (request && request.hasOwnProperty(prop)) {
 | 
			
		||||
                workerRequest[prop] = request[prop];
 | 
			
		||||
            }
 | 
			
		||||
            if (!workerRequest[prop]) {
 | 
			
		||||
 
 | 
			
		||||
@@ -127,7 +127,8 @@
 | 
			
		||||
{ 'meaning': 'Timer object', 'cssClass': 'icon-timer', 'cssContent': 'e1127', 'htmlEntity': '&#xe1127' },
 | 
			
		||||
{ 'meaning': 'Data Topic', 'cssClass': 'icon-topic', 'cssContent': 'e1128', 'htmlEntity': '&#xe1128' },
 | 
			
		||||
{ 'meaning': 'Fixed Position object', 'cssClass': 'icon-box-with-dashed-lines', 'cssContent': 'e1129', 'htmlEntity': '&#xe1129' },
 | 
			
		||||
{ 'meaning': 'Summary Widget', 'cssClass': 'icon-summary-widget', 'cssContent': 'e1130', 'htmlEntity': '&#xe1130' }
 | 
			
		||||
{ 'meaning': 'Summary Widget', 'cssClass': 'icon-summary-widget', 'cssContent': 'e1130', 'htmlEntity': '&#xe1130' },
 | 
			
		||||
{ 'meaning': 'Notebook object', 'cssClass': 'icon-notebook', 'cssContent': 'e1131', 'htmlEntity': '&#xe1131' }
 | 
			
		||||
];
 | 
			
		||||
"></div>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -121,7 +121,7 @@
 | 
			
		||||
        <h2>Palettes</h2>
 | 
			
		||||
        <div class="cols cols1-1">
 | 
			
		||||
            <div class="col">
 | 
			
		||||
                <p>Use a palette to provide color choices. Similar to context menus and dropdowns, palettes should be dismissed when a choice is made within them, or if the user clicks outside one.</p>
 | 
			
		||||
                <p>Use a palette to provide color choices. Similar to context menus and dropdowns, palettes should be dismissed when a choice is made within them, or if the user clicks outside one. Selected palette choices should utilize the <code>selected</code> CSS class to visualize indicate that state.</p>
 | 
			
		||||
                <p>Note that while this example uses static markup for illustrative purposes, don't do this - use a front-end framework with repeaters to build the color choices.</p>
 | 
			
		||||
            </div>
 | 
			
		||||
            <mct-example><div style="height: 220px" title="Ignore me, I'm just here to provide space for this example.">
 | 
			
		||||
@@ -129,9 +129,9 @@
 | 
			
		||||
<div class="s-button s-menu-button menu-element t-color-palette icon-paint-bucket" ng-controller="ClickAwayController as toggle">
 | 
			
		||||
    <span class="l-click-area" ng-click="toggle.toggle()"></span>
 | 
			
		||||
    <span class="color-swatch" style="background: rgb(255, 0, 0);"></span>
 | 
			
		||||
    <div class="menu l-color-palette" ng-show="toggle.isActive()">
 | 
			
		||||
    <div class="menu l-palette l-color-palette" ng-show="toggle.isActive()">
 | 
			
		||||
        <div class="l-palette-row l-option-row">
 | 
			
		||||
            <div class="l-palette-item s-palette-item " ng-click="ngModel[field] = 'transparent'"></div>
 | 
			
		||||
            <div class="l-palette-item s-palette-item no-selection"></div>
 | 
			
		||||
            <span class="l-palette-item-label">None</span>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="l-palette-row">
 | 
			
		||||
@@ -147,7 +147,7 @@
 | 
			
		||||
            <div class="l-palette-item s-palette-item" style="background: rgb(255, 255, 255);"></div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="l-palette-row">
 | 
			
		||||
            <div class="l-palette-item s-palette-item" style="background: rgb(136, 32, 32);"></div>
 | 
			
		||||
            <div class="l-palette-item s-palette-item selected" style="background: rgb(255, 0, 0);"></div>
 | 
			
		||||
            <div class="l-palette-item s-palette-item" style="background: rgb(224, 64, 64);"></div>
 | 
			
		||||
            <div class="l-palette-item s-palette-item" style="background: rgb(240, 160, 72);"></div>
 | 
			
		||||
            <div class="l-palette-item s-palette-item" style="background: rgb(255, 248, 96);"></div>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								gulpfile.js
									
									
									
									
									
								
							
							
						
						
									
										28
									
								
								gulpfile.js
									
									
									
									
									
								
							@@ -46,9 +46,22 @@ var gulp = require('gulp'),
 | 
			
		||||
            name: 'bower_components/almond/almond.js',
 | 
			
		||||
            include: paths.main.replace('.js', ''),
 | 
			
		||||
            wrap: {
 | 
			
		||||
                startFile: "src/start.frag",
 | 
			
		||||
                start: (function () {
 | 
			
		||||
                    var buildVariables = {
 | 
			
		||||
                        version: project.version,
 | 
			
		||||
                        timestamp: moment.utc(Date.now()).format(),
 | 
			
		||||
                        revision: fs.existsSync('.git') ? git.long() : 'Unknown',
 | 
			
		||||
                        branch: fs.existsSync('.git') ? git.branch() : 'Unknown'
 | 
			
		||||
                    };
 | 
			
		||||
                    return fs.readFileSync("src/start.frag", 'utf-8')
 | 
			
		||||
                        .replace(/@@(\w+)/g, function (match, key) {
 | 
			
		||||
                            return buildVariables[key];
 | 
			
		||||
                        });;
 | 
			
		||||
                }()),
 | 
			
		||||
                endFile: "src/end.frag"
 | 
			
		||||
            },
 | 
			
		||||
            optimize: 'uglify2',
 | 
			
		||||
            uglify2: { output: { comments: /@preserve/ } },
 | 
			
		||||
            mainConfigFile: paths.main,
 | 
			
		||||
            wrapShim: true
 | 
			
		||||
        },
 | 
			
		||||
@@ -58,14 +71,6 @@ var gulp = require('gulp'),
 | 
			
		||||
        },
 | 
			
		||||
        sass: {
 | 
			
		||||
            sourceComments: true
 | 
			
		||||
        },
 | 
			
		||||
        replace: {
 | 
			
		||||
            variables: {
 | 
			
		||||
                version: project.version,
 | 
			
		||||
                timestamp: moment.utc(Date.now()).format(),
 | 
			
		||||
                revision: fs.existsSync('.git') ? git.long() : 'Unknown',
 | 
			
		||||
                branch: fs.existsSync('.git') ? git.branch() : 'Unknown'
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -76,16 +81,11 @@ if (process.env.NODE_ENV === 'development') {
 | 
			
		||||
 | 
			
		||||
gulp.task('scripts', function () {
 | 
			
		||||
    var requirejsOptimize = require('gulp-requirejs-optimize');
 | 
			
		||||
    var replace = require('gulp-replace-task');
 | 
			
		||||
    var header = require('gulp-header');
 | 
			
		||||
    var comment = fs.readFileSync('src/about.frag');
 | 
			
		||||
 | 
			
		||||
    return gulp.src(paths.main)
 | 
			
		||||
        .pipe(sourcemaps.init())
 | 
			
		||||
        .pipe(requirejsOptimize(options.requirejsOptimize))
 | 
			
		||||
        .pipe(sourcemaps.write('.'))
 | 
			
		||||
        .pipe(replace(options.replace))
 | 
			
		||||
        .pipe(header(comment, options.replace.variables))
 | 
			
		||||
        .pipe(gulp.dest(paths.dist));
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,7 @@
 | 
			
		||||
    <meta charset="utf-8">
 | 
			
		||||
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
 | 
			
		||||
    <title></title>
 | 
			
		||||
    <script src="bower_components/requirejs/require.js">
 | 
			
		||||
    </script>
 | 
			
		||||
    <script src="bower_components/requirejs/require.js"> </script>
 | 
			
		||||
    <script>
 | 
			
		||||
        var THIRTY_MINUTES = 30 * 60 * 1000;
 | 
			
		||||
 | 
			
		||||
@@ -44,13 +43,14 @@
 | 
			
		||||
            openmct.install(openmct.plugins.ExampleImagery());
 | 
			
		||||
            openmct.install(openmct.plugins.UTCTimeSystem());
 | 
			
		||||
            openmct.install(openmct.plugins.ImportExport());
 | 
			
		||||
            openmct.install(openmct.plugins.TelemetryMean());
 | 
			
		||||
            openmct.install(openmct.plugins.Conductor({
 | 
			
		||||
                menuOptions: [
 | 
			
		||||
                    {
 | 
			
		||||
                        name: "Fixed",
 | 
			
		||||
                        timeSystem: 'utc',
 | 
			
		||||
                        bounds: {
 | 
			
		||||
                            start: Date.now() - 30 * 60 * 1000,
 | 
			
		||||
                            start: Date.now() - THIRTY_MINUTES,
 | 
			
		||||
                            end: Date.now()
 | 
			
		||||
                        }
 | 
			
		||||
                    },
 | 
			
		||||
@@ -65,6 +65,7 @@
 | 
			
		||||
                    }
 | 
			
		||||
                ]
 | 
			
		||||
            }));
 | 
			
		||||
            openmct.install(openmct.plugins.SummaryWidget());
 | 
			
		||||
            openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
 | 
			
		||||
            openmct.time.timeSystem('utc');
 | 
			
		||||
            openmct.start();
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										11
									
								
								openmct.js
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								openmct.js
									
									
									
									
									
								
							@@ -19,7 +19,7 @@
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
/*global requirejs*/
 | 
			
		||||
/*global requirejs,BUILD_CONSTANTS*/
 | 
			
		||||
 | 
			
		||||
requirejs.config({
 | 
			
		||||
    "paths": {
 | 
			
		||||
@@ -91,12 +91,17 @@ requirejs.config({
 | 
			
		||||
define([
 | 
			
		||||
    './platform/framework/src/Main',
 | 
			
		||||
    './src/defaultRegistry',
 | 
			
		||||
    './src/MCT'
 | 
			
		||||
], function (Main, defaultRegistry, MCT) {
 | 
			
		||||
    './src/MCT',
 | 
			
		||||
    './src/plugins/buildInfo/plugin'
 | 
			
		||||
], function (Main, defaultRegistry, MCT, buildInfo) {
 | 
			
		||||
    var openmct = new MCT();
 | 
			
		||||
 | 
			
		||||
    openmct.legacyRegistry = defaultRegistry;
 | 
			
		||||
 | 
			
		||||
    if (typeof BUILD_CONSTANTS !== 'undefined') {
 | 
			
		||||
        openmct.install(buildInfo(BUILD_CONSTANTS));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    openmct.on('start', function () {
 | 
			
		||||
        return new Main().run(defaultRegistry);
 | 
			
		||||
    });
 | 
			
		||||
 
 | 
			
		||||
@@ -22,12 +22,10 @@
 | 
			
		||||
    "git-rev-sync": "^1.4.0",
 | 
			
		||||
    "glob": ">= 3.0.0",
 | 
			
		||||
    "gulp": "^3.9.1",
 | 
			
		||||
    "gulp-header": "^1.8.8",
 | 
			
		||||
    "gulp-jscs": "^3.0.2",
 | 
			
		||||
    "gulp-jshint": "^2.0.0",
 | 
			
		||||
    "gulp-jshint-html-reporter": "^0.1.3",
 | 
			
		||||
    "gulp-rename": "^1.2.2",
 | 
			
		||||
    "gulp-replace-task": "^0.11.0",
 | 
			
		||||
    "gulp-requirejs-optimize": "^0.3.1",
 | 
			
		||||
    "gulp-sass": "^2.2.0",
 | 
			
		||||
    "gulp-sourcemaps": "^1.6.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,7 @@ define([
 | 
			
		||||
    "./src/InspectorPaneController",
 | 
			
		||||
    "./src/BrowseObjectController",
 | 
			
		||||
    "./src/MenuArrowController",
 | 
			
		||||
    "./src/ObjectHeaderController",
 | 
			
		||||
    "./src/navigation/NavigationService",
 | 
			
		||||
    "./src/navigation/NavigateAction",
 | 
			
		||||
    "./src/navigation/OrphanNavigationHandler",
 | 
			
		||||
@@ -36,6 +37,7 @@ define([
 | 
			
		||||
    "text!./res/templates/browse-object.html",
 | 
			
		||||
    "text!./res/templates/items/grid-item.html",
 | 
			
		||||
    "text!./res/templates/browse/object-header.html",
 | 
			
		||||
    "text!./res/templates/browse/object-header-frame.html",
 | 
			
		||||
    "text!./res/templates/menu-arrow.html",
 | 
			
		||||
    "text!./res/templates/back-arrow.html",
 | 
			
		||||
    "text!./res/templates/items/items.html",
 | 
			
		||||
@@ -48,6 +50,7 @@ define([
 | 
			
		||||
    InspectorPaneController,
 | 
			
		||||
    BrowseObjectController,
 | 
			
		||||
    MenuArrowController,
 | 
			
		||||
    ObjectHeaderController,
 | 
			
		||||
    NavigationService,
 | 
			
		||||
    NavigateAction,
 | 
			
		||||
    OrphanNavigationHandler,
 | 
			
		||||
@@ -58,6 +61,7 @@ define([
 | 
			
		||||
    browseObjectTemplate,
 | 
			
		||||
    gridItemTemplate,
 | 
			
		||||
    objectHeaderTemplate,
 | 
			
		||||
    objectHeaderFrameTemplate,
 | 
			
		||||
    menuArrowTemplate,
 | 
			
		||||
    backArrowTemplate,
 | 
			
		||||
    itemsTemplate,
 | 
			
		||||
@@ -140,6 +144,13 @@ define([
 | 
			
		||||
                        "$location",
 | 
			
		||||
                        "$attrs"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "ObjectHeaderController",
 | 
			
		||||
                    "implementation": ObjectHeaderController,
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                        "$scope"
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "representations": [
 | 
			
		||||
@@ -173,6 +184,13 @@ define([
 | 
			
		||||
                        "type"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "object-header-frame",
 | 
			
		||||
                    "template": objectHeaderFrameTemplate,
 | 
			
		||||
                    "uses": [
 | 
			
		||||
                        "type"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "menu-arrow",
 | 
			
		||||
                    "template": menuArrowTemplate,
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,31 @@
 | 
			
		||||
<!--
 | 
			
		||||
 Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 Administration. All rights reserved.
 | 
			
		||||
 | 
			
		||||
 Open MCT 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 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.
 | 
			
		||||
-->
 | 
			
		||||
<span class='type-icon flex-elem {{type.getCssClass()}}'></span>
 | 
			
		||||
<span class="l-elem-wrapper l-flex-row flex-elem grows" ng-controller="ObjectHeaderController as controller">
 | 
			
		||||
    <span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span>
 | 
			
		||||
    <span class='title-label flex-elem holder flex-can-shrink s-input-inline'>{{model.name}}</span>
 | 
			
		||||
    <span class='t-object-alert t-alert-unsynced flex-elem holder' title='This object is not currently displaying real-time data'></span>
 | 
			
		||||
    <mct-representation
 | 
			
		||||
        key="'menu-arrow'"
 | 
			
		||||
        mct-object='domainObject'
 | 
			
		||||
        class="flex-elem context-available-w"></mct-representation>
 | 
			
		||||
</span>
 | 
			
		||||
@@ -20,9 +20,13 @@
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<span class='type-icon flex-elem {{type.getCssClass()}}'></span>
 | 
			
		||||
<span class="l-elem-wrapper l-flex-row flex-elem grows">
 | 
			
		||||
<span class="l-elem-wrapper l-flex-row flex-elem grows" ng-controller="ObjectHeaderController as controller">
 | 
			
		||||
    <span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span>
 | 
			
		||||
    <span class='title-label flex-elem holder flex-can-shrink'>{{model.name}}</span>
 | 
			
		||||
    <span ng-attr-contenteditable="{{ controller.editable ? true : undefined }}"
 | 
			
		||||
		class='title-label flex-elem holder flex-can-shrink s-input-inline'
 | 
			
		||||
		ng-click="controller.edit()"
 | 
			
		||||
		ng-blur="controller.updateName($event)"
 | 
			
		||||
		ng-keypress="controller.updateName($event)">{{model.name}}</span>
 | 
			
		||||
    <span class='t-object-alert t-alert-unsynced flex-elem holder' title='This object is not currently displaying real-time data'></span>
 | 
			
		||||
    <mct-representation
 | 
			
		||||
        key="'menu-arrow'"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										78
									
								
								platform/commonUI/browse/src/ObjectHeaderController.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								platform/commonUI/browse/src/ObjectHeaderController.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,78 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Controller to provide the ability to inline edit an object name.
 | 
			
		||||
         *
 | 
			
		||||
         * @constructor
 | 
			
		||||
         * @memberof platform/commonUI/browse
 | 
			
		||||
         */
 | 
			
		||||
        function ObjectHeaderController($scope) {
 | 
			
		||||
            this.$scope = $scope;
 | 
			
		||||
            this.domainObject = $scope.domainObject;
 | 
			
		||||
            this.editable = this.allowEdit();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Updates the object name on blur and enter keypress events.
 | 
			
		||||
         *
 | 
			
		||||
         * @param event the mouse event
 | 
			
		||||
         */
 | 
			
		||||
        ObjectHeaderController.prototype.updateName = function (event) {
 | 
			
		||||
            if (event && (event.type === 'blur' || event.which === 13)) {
 | 
			
		||||
                var name = event.currentTarget.innerHTML;
 | 
			
		||||
 | 
			
		||||
                if (name.length === 0) {
 | 
			
		||||
                    name = "Unnamed " + this.domainObject.getCapability("type").typeDef.name;
 | 
			
		||||
                    event.currentTarget.innerHTML = name;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (name !== this.$scope.domainObject.model.name) {
 | 
			
		||||
                    this.domainObject.getCapability('mutation').mutate(function (model) {
 | 
			
		||||
                        model.name = name;
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                if (event.which === 13) {
 | 
			
		||||
                    event.currentTarget.blur();
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Checks if the domain object is editable.
 | 
			
		||||
         *
 | 
			
		||||
         * @private
 | 
			
		||||
         * @return true if object is editable
 | 
			
		||||
         */
 | 
			
		||||
        ObjectHeaderController.prototype.allowEdit = function () {
 | 
			
		||||
            var type = this.domainObject && this.domainObject.getCapability('type');
 | 
			
		||||
            return !!(type && type.hasFeature('creation'));
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return ObjectHeaderController;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										132
									
								
								platform/commonUI/browse/test/ObjectHeaderControllerSpec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										132
									
								
								platform/commonUI/browse/test/ObjectHeaderControllerSpec.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,132 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    ["../src/ObjectHeaderController"],
 | 
			
		||||
    function (ObjectHeaderController) {
 | 
			
		||||
 | 
			
		||||
        describe("The object header controller", function () {
 | 
			
		||||
            var mockScope,
 | 
			
		||||
                mockDomainObject,
 | 
			
		||||
                mockCapabilities,
 | 
			
		||||
                mockMutationCapability,
 | 
			
		||||
                mockTypeCapability,
 | 
			
		||||
                mockEvent,
 | 
			
		||||
                mockCurrentTarget,
 | 
			
		||||
                controller;
 | 
			
		||||
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                mockMutationCapability = jasmine.createSpyObj("mutation", ["mutate"]);
 | 
			
		||||
                mockTypeCapability = jasmine.createSpyObj("type", ["typeDef", "hasFeature"]);
 | 
			
		||||
                mockTypeCapability.typeDef = { name: ""};
 | 
			
		||||
                mockTypeCapability.hasFeature.andCallFake(function (feature) {
 | 
			
		||||
                    return feature === 'creation';
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                mockCapabilities = {
 | 
			
		||||
                    mutation: mockMutationCapability,
 | 
			
		||||
                    type: mockTypeCapability
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "model"]);
 | 
			
		||||
                mockDomainObject.model = {name: "Test name"};
 | 
			
		||||
                mockDomainObject.getCapability.andCallFake(function (key) {
 | 
			
		||||
                    return mockCapabilities[key];
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                mockScope = {
 | 
			
		||||
                    domainObject: mockDomainObject
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur", "innerHTML"]);
 | 
			
		||||
                mockCurrentTarget.blur.andReturn(mockCurrentTarget);
 | 
			
		||||
 | 
			
		||||
                mockEvent = {
 | 
			
		||||
                    which: {},
 | 
			
		||||
                    type: {},
 | 
			
		||||
                    currentTarget: mockCurrentTarget
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                controller = new ObjectHeaderController(mockScope);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("updates the model with new name on blur", function () {
 | 
			
		||||
                mockEvent.type = "blur";
 | 
			
		||||
                mockCurrentTarget.innerHTML = "New name";
 | 
			
		||||
                controller.updateName(mockEvent);
 | 
			
		||||
 | 
			
		||||
                expect(mockMutationCapability.mutate).toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("updates the model with a default for blank names", function () {
 | 
			
		||||
                mockEvent.type = "blur";
 | 
			
		||||
                mockCurrentTarget.innerHTML = "";
 | 
			
		||||
                controller.updateName(mockEvent);
 | 
			
		||||
 | 
			
		||||
                expect(mockCurrentTarget.innerHTML.length).not.toEqual(0);
 | 
			
		||||
                expect(mockMutationCapability.mutate).toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("does not update the model if the same name", function () {
 | 
			
		||||
                mockEvent.type = "blur";
 | 
			
		||||
                mockCurrentTarget.innerHTML = mockDomainObject.model.name;
 | 
			
		||||
                controller.updateName(mockEvent);
 | 
			
		||||
 | 
			
		||||
                expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("updates the model on enter keypress event only", function () {
 | 
			
		||||
                mockCurrentTarget.innerHTML = "New name";
 | 
			
		||||
                controller.updateName(mockEvent);
 | 
			
		||||
 | 
			
		||||
                expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
 | 
			
		||||
 | 
			
		||||
                mockEvent.which = 13;
 | 
			
		||||
                controller.updateName(mockEvent);
 | 
			
		||||
 | 
			
		||||
                expect(mockMutationCapability.mutate).toHaveBeenCalledWith(jasmine.any(Function));
 | 
			
		||||
 | 
			
		||||
                mockMutationCapability.mutate.mostRecentCall.args[0](mockDomainObject.model);
 | 
			
		||||
 | 
			
		||||
                expect(mockDomainObject.model.name).toBe("New name");
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("blurs the field on enter key press", function () {
 | 
			
		||||
                mockEvent.which = 13;
 | 
			
		||||
                controller.updateName(mockEvent);
 | 
			
		||||
 | 
			
		||||
                expect(mockEvent.currentTarget.blur).toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("allows editting name when object is creatable", function () {
 | 
			
		||||
                expect(controller.allowEdit()).toBe(true);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("disallows editting name when object is non-creatable", function () {
 | 
			
		||||
                mockTypeCapability.hasFeature.andReturn(false);
 | 
			
		||||
 | 
			
		||||
                expect(controller.allowEdit()).toBe(false);
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<div class="abs top-bar">
 | 
			
		||||
    <div class="title">{{ngModel.title}}</div>
 | 
			
		||||
    <div class="dialog-title">{{ngModel.title}}</div>
 | 
			
		||||
    <div class="hint">All fields marked <span class="req icon-asterisk"></span> are required.</div>
 | 
			
		||||
</div>
 | 
			
		||||
<div class='abs editor'>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,10 @@
 | 
			
		||||
<div class="l-message"
 | 
			
		||||
     ng-class="'message-severity-' + ngModel.severity">
 | 
			
		||||
    <div class="ui-symbol type-icon message-type"></div>
 | 
			
		||||
    <div class="message-contents">
 | 
			
		||||
    <div class="w-message-contents">
 | 
			
		||||
        <div class="top-bar">
 | 
			
		||||
            <div class="title">{{ngModel.title}}</div>
 | 
			
		||||
            <div class="hint" ng-hide="ngModel.hint === undefined">{{ngModel.hint}}</div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="hint" ng-hide="ngModel.hint === undefined">{{ngModel.hint}}</div>
 | 
			
		||||
        <div class="message-body">
 | 
			
		||||
            <div class="message-action">
 | 
			
		||||
                {{ngModel.actionText}}
 | 
			
		||||
@@ -25,8 +24,6 @@
 | 
			
		||||
               ng-click="ngModel.primaryOption.callback()">
 | 
			
		||||
                {{ngModel.primaryOption.label}}
 | 
			
		||||
            </a>
 | 
			
		||||
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,17 @@
 | 
			
		||||
<mct-container key="overlay" class="t-message-list">
 | 
			
		||||
    <div class="message-contents">
 | 
			
		||||
        <div class="abs top-bar">
 | 
			
		||||
            <div class="title">{{ngModel.dialog.title}}</div>
 | 
			
		||||
<mct-container key="overlay">
 | 
			
		||||
    <div class="t-message-list">
 | 
			
		||||
        <div class="top-bar">
 | 
			
		||||
            <div class="dialog-title">{{ngModel.dialog.title}}</div>
 | 
			
		||||
            <div class="hint">Displaying {{ngModel.dialog.messages.length}} message<span ng-show="ngModel.dialog.messages.length > 1 ||
 | 
			
		||||
                                                                                                  ngModel.dialog.messages.length == 0">s</span>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="abs message-body">
 | 
			
		||||
        <div class="w-messages">
 | 
			
		||||
            <mct-include
 | 
			
		||||
                    ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'"
 | 
			
		||||
                    key="'message'" ng-model="msg.model"></mct-include>
 | 
			
		||||
                ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'"
 | 
			
		||||
                key="'message'" ng-model="msg.model"></mct-include>
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="abs bottom-bar">
 | 
			
		||||
        <div class="bottom-bar">
 | 
			
		||||
            <a ng-repeat="dialogAction in ngModel.dialog.actions"
 | 
			
		||||
               class="s-button major"
 | 
			
		||||
               ng-click="dialogAction.action()">
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@
 | 
			
		||||
-->
 | 
			
		||||
<mct-container key="overlay">
 | 
			
		||||
    <div class="abs top-bar">
 | 
			
		||||
        <div class="title">{{ngModel.dialog.title}}</div>
 | 
			
		||||
        <div class="dialog-title">{{ngModel.dialog.title}}</div>
 | 
			
		||||
        <div class="hint">{{ngModel.dialog.hint}}</div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class='abs editor'>
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
    <div class="s-menu-button major create-button" ng-click="createController.toggle()">
 | 
			
		||||
		<span class="title-label">Create</span>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="menu super-menu" ng-show="createController.isActive()">
 | 
			
		||||
    <div class="menu super-menu l-create-menu" ng-show="createController.isActive()">
 | 
			
		||||
        <mct-representation mct-object="domainObject" key="'create-menu'">
 | 
			
		||||
        </mct-representation>
 | 
			
		||||
    </div>
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,8 @@
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<div class="contents" ng-controller="CreateMenuController">
 | 
			
		||||
    <div class="pane left menu-items">
 | 
			
		||||
<div class="w-menu" ng-controller="CreateMenuController">
 | 
			
		||||
    <div class="col menu-items">
 | 
			
		||||
        <ul>
 | 
			
		||||
            <li ng-repeat="createAction in createActions" ng-click="createAction.perform()">
 | 
			
		||||
                <a ng-mouseover="representation.activeMetadata = createAction.getMetadata()"
 | 
			
		||||
@@ -31,13 +31,15 @@
 | 
			
		||||
            </li>
 | 
			
		||||
        </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="pane right menu-item-description">
 | 
			
		||||
    <div class="col menu-item-description">
 | 
			
		||||
        <div class="desc-area icon {{ representation.activeMetadata.cssClass }}"></div>
 | 
			
		||||
        <div class="desc-area title">
 | 
			
		||||
            {{representation.activeMetadata.name}}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="desc-area description">
 | 
			
		||||
            {{representation.activeMetadata.description}}
 | 
			
		||||
        <div class="w-title-desc">
 | 
			
		||||
            <div class="desc-area title">
 | 
			
		||||
                {{representation.activeMetadata.name}}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="desc-area description">
 | 
			
		||||
                {{representation.activeMetadata.description}}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -80,6 +80,12 @@ define(
 | 
			
		||||
                return closeEditor();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            function resolveWith (object) {
 | 
			
		||||
                return function () {
 | 
			
		||||
                    return object;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            newModel.type = this.type.getKey();
 | 
			
		||||
            newModel.location = this.parent.getId();
 | 
			
		||||
            newObject = this.parent.useCapability('instantiation', newModel);
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
  "metadata": {
 | 
			
		||||
    "name": "openmct-symbols-16px",
 | 
			
		||||
    "lastOpened": 0,
 | 
			
		||||
    "created": 1505151140023
 | 
			
		||||
    "created": 1506973656040
 | 
			
		||||
  },
 | 
			
		||||
  "iconSets": [
 | 
			
		||||
    {
 | 
			
		||||
@@ -899,6 +899,14 @@
 | 
			
		||||
          "prevSize": 24,
 | 
			
		||||
          "code": 921904,
 | 
			
		||||
          "tempChar": ""
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "order": 139,
 | 
			
		||||
          "id": 117,
 | 
			
		||||
          "name": "icon-notebook",
 | 
			
		||||
          "prevSize": 24,
 | 
			
		||||
          "code": 921905,
 | 
			
		||||
          "tempChar": ""
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      "metadata": {
 | 
			
		||||
@@ -3524,6 +3532,29 @@
 | 
			
		||||
              {}
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
          "id": 117,
 | 
			
		||||
          "paths": [
 | 
			
		||||
            "M896 110.8c0-79.8-55.4-127.4-123-105.4l-773 250.6h896v-145.2z",
 | 
			
		||||
            "M896 320h-896v576c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v-448c0-70.4-57.6-128-128-128zM832 832h-384v-320h384v320z"
 | 
			
		||||
          ],
 | 
			
		||||
          "attrs": [
 | 
			
		||||
            {},
 | 
			
		||||
            {}
 | 
			
		||||
          ],
 | 
			
		||||
          "isMulticolor": false,
 | 
			
		||||
          "isMulticolor2": false,
 | 
			
		||||
          "grid": 16,
 | 
			
		||||
          "tags": [
 | 
			
		||||
            "icon-notebook"
 | 
			
		||||
          ],
 | 
			
		||||
          "colorPermutations": {
 | 
			
		||||
            "1161751207457516161751": [
 | 
			
		||||
              {},
 | 
			
		||||
              {}
 | 
			
		||||
            ]
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      ],
 | 
			
		||||
      "colorThemes": [
 | 
			
		||||
 
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							@@ -118,4 +118,5 @@
 | 
			
		||||
<glyph unicode="󡄨" glyph-name="icon-topic" d="M454.36 483.36l86.3 86.3c9.088 8.965 21.577 14.502 35.36 14.502s26.272-5.537 35.366-14.507l86.294-86.294c19.328-19.358 42.832-34.541 69.047-44.082l1.313 171.722-57.64 57.64c-34.407 34.33-81.9 55.558-134.35 55.558s-99.943-21.228-134.354-55.562l-86.296-86.297c-9.088-8.965-21.577-14.502-35.36-14.502s-26.272 5.537-35.366 14.507l-28.674 28.654v-172.14c19.045-7.022 41.040-11.084 63.984-11.084 52.463 0 99.966 21.239 134.379 55.587zM505.64 412.64l-86.3-86.3c-9.088-8.965-21.577-14.502-35.36-14.502s-26.272 5.537-35.366 14.507l-86.294 86.294c-2 2-4.2 4-6.36 6v-197.36c33.664-30.72 78.65-49.537 128.031-49.537 52.44 0 99.923 21.22 134.333 55.541l86.296 86.296c9.088 8.965 21.577 14.502 35.36 14.502s26.272-5.537 35.366-14.507l86.294-86.294c2-2 4.2-4 6.36-6v197.36c-33.664 30.72-78.65 49.537-128.031 49.537-52.44 0-99.923-21.22-134.333-55.541zM832 960h-128v-192h127.66l0.34-0.34v-639.32l-0.34-0.34h-127.66v-192h128c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM320 128h-127.66l-0.34 0.34v639.32l0.34 0.34h127.66v192h-128c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h128v192z" />
 | 
			
		||||
<glyph unicode="󡄩" glyph-name="icon-box-with-dashed-lines" d="M0 576h128v-256h-128v256zM128 831.78l0.22 0.22h191.78v128h-192c-70.606-0.215-127.785-57.394-128-127.979v-192.021h128v191.78zM128 64.22v191.78h-128v-192c0.215-70.606 57.394-127.785 127.979-128h192.021v128h-191.78zM384 960h256v-128h-256v128zM896 64.22l-0.22-0.22h-191.78v-128h192c70.606 0.215 127.785 57.394 128 127.979v192.021h-128v-191.78zM896 960h-192v-128h191.78l0.22-0.22v-191.78h128v192c-0.215 70.606-57.394 127.785-127.979 128zM896 576h128v-256h-128v256zM384 64h256v-128h-256v128zM256 704h512v-512h-512v512z" />
 | 
			
		||||
<glyph unicode="󡄰" glyph-name="icon-summary-widget" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM847.8 349.6l-82.6-143.2-189.6 131.6 19.2-230h-165.4l19.2 230-189.6-131.6-82.6 143.2 208.6 98.4-208.8 98.4 82.6 143.2 189.6-131.6-19.2 230h165.4l-19.2-230 189.6 131.6 82.6-143.2-208.6-98.4 208.8-98.4z" />
 | 
			
		||||
<glyph unicode="󡄱" glyph-name="icon-notebook" d="M896 849.2c0 79.8-55.4 127.4-123 105.4l-773-250.6h896v145.2zM896 640h-896v-576c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v448c0 70.4-57.6 128-128 128zM832 128h-384v320h384v-320z" />
 | 
			
		||||
</font></defs></svg>
 | 
			
		||||
| 
		 Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB  | 
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							@@ -137,6 +137,11 @@
 | 
			
		||||
        min-height: 0;
 | 
			
		||||
        &.holder:not(:last-child) { margin-bottom: $interiorMarginLg; }
 | 
			
		||||
    }
 | 
			
		||||
    &.l-flex-accordion .flex-accordion-holder {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        //overflow: hidden !important;
 | 
			
		||||
    }
 | 
			
		||||
    .flex-container { @include flex-direction(column); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -111,7 +111,9 @@ $bubbleMaxW: 300px;
 | 
			
		||||
$reqSymbolW: 15px;
 | 
			
		||||
$reqSymbolM: $interiorMargin * 2;
 | 
			
		||||
$reqSymbolFontSize: 0.75em;
 | 
			
		||||
$inputTextP: 3px 5px;
 | 
			
		||||
$inputTextPTopBtm: 3px;
 | 
			
		||||
$inputTextPLeftRight: 5px;
 | 
			
		||||
$inputTextP: $inputTextPTopBtm $inputTextPLeftRight;
 | 
			
		||||
/*************** Wait Spinner Defaults */
 | 
			
		||||
$waitSpinnerD: 32px;
 | 
			
		||||
$waitSpinnerTreeD: 20px;
 | 
			
		||||
 
 | 
			
		||||
@@ -180,6 +180,20 @@ a.disabled {
 | 
			
		||||
    @include ellipsize();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.no-selection {
 | 
			
		||||
    // aka selection = "None". Used in palettes and their menu buttons.
 | 
			
		||||
    $c: red; $s: 48%; $e: 52%;
 | 
			
		||||
    @include background-image(linear-gradient(-45deg,
 | 
			
		||||
        transparent $s - 5%,
 | 
			
		||||
        $c $s,
 | 
			
		||||
        $c $e,
 | 
			
		||||
        transparent $e + 5%
 | 
			
		||||
    ));
 | 
			
		||||
    background-repeat: no-repeat;
 | 
			
		||||
    background-size: contain;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.scrolling,
 | 
			
		||||
.scroll {
 | 
			
		||||
    overflow: auto;
 | 
			
		||||
 
 | 
			
		||||
@@ -146,6 +146,7 @@ $glyph-icon-timer: '\e1127';
 | 
			
		||||
$glyph-icon-topic: '\e1128';
 | 
			
		||||
$glyph-icon-box-with-dashed-lines: '\e1129';
 | 
			
		||||
$glyph-icon-summary-widget: '\e1130';
 | 
			
		||||
$glyph-icon-notebook: '\e1131';
 | 
			
		||||
 | 
			
		||||
/************************** 16 PX CLASSES */
 | 
			
		||||
 | 
			
		||||
@@ -260,6 +261,7 @@ $glyph-icon-summary-widget: '\e1130';
 | 
			
		||||
.icon-topic {  @include glyphBefore($glyph-icon-topic); }
 | 
			
		||||
.icon-box-with-dashed-lines {  @include glyphBefore($glyph-icon-box-with-dashed-lines); }
 | 
			
		||||
.icon-summary-widget {  @include glyphBefore($glyph-icon-summary-widget); }
 | 
			
		||||
.icon-notebook {  @include glyphBefore($glyph-icon-notebook); }
 | 
			
		||||
 | 
			
		||||
/************************** 12 PX CLASSES */
 | 
			
		||||
.icon-crosshair-12px {  @include glyphBefore($glyph-icon-crosshair,'symbolsfont-12px'); }
 | 
			
		||||
 
 | 
			
		||||
@@ -26,5 +26,6 @@
 | 
			
		||||
        display: block;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        border: none;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@
 | 
			
		||||
/********************************* CONTROLS */
 | 
			
		||||
@import "controls/breadcrumb";
 | 
			
		||||
@import "controls/buttons";
 | 
			
		||||
@import "controls/color-palette";
 | 
			
		||||
@import "controls/palette";
 | 
			
		||||
@import "controls/controls";
 | 
			
		||||
@import "controls/lists";
 | 
			
		||||
@import "controls/menus";
 | 
			
		||||
@@ -80,3 +80,4 @@
 | 
			
		||||
@import "autoflow";
 | 
			
		||||
@import "features/imagery";
 | 
			
		||||
@import "features/time-display";
 | 
			
		||||
@import "widgets";
 | 
			
		||||
 
 | 
			
		||||
@@ -316,23 +316,28 @@
 | 
			
		||||
    text-shadow: $shdwItemText;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin input-base($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
 | 
			
		||||
@mixin input-base() {
 | 
			
		||||
	@include appearance(none);
 | 
			
		||||
	border-radius: $controlCr;
 | 
			
		||||
	box-sizing: border-box;
 | 
			
		||||
	box-shadow: inset $shdw;
 | 
			
		||||
	background: $bg;
 | 
			
		||||
	border: none;
 | 
			
		||||
	color: $fg;
 | 
			
		||||
	outline: none;
 | 
			
		||||
    &:focus { outline: 0; }
 | 
			
		||||
	&.error {
 | 
			
		||||
		background-color: $colorFormFieldErrorBg;
 | 
			
		||||
        color: $colorFormFieldErrorFg;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg) {
 | 
			
		||||
	@include input-base($bg, $fg);
 | 
			
		||||
@mixin s-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
 | 
			
		||||
    @include input-base();
 | 
			
		||||
    background: $bg;
 | 
			
		||||
    box-shadow: inset $shdw;
 | 
			
		||||
    color: $fg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
 | 
			
		||||
    @include s-input($bg, $fg, $shdw);
 | 
			
		||||
    border: none;
 | 
			
		||||
    outline: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin contextArrow() {
 | 
			
		||||
@@ -344,7 +349,7 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin nice-textarea($bg: $colorBodyBg, $fg: $colorBodyFg) {
 | 
			
		||||
    @include input-base($bg, $fg);
 | 
			
		||||
    @include nice-input($bg, $fg);
 | 
			
		||||
    padding: $interiorMargin;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -50,7 +50,6 @@
 | 
			
		||||
        content:'';
 | 
			
		||||
        font-family: symbolsfont;
 | 
			
		||||
        font-size: 0.8em;
 | 
			
		||||
        display: inline;
 | 
			
		||||
        margin-right: $interiorMarginSm;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										301
									
								
								platform/commonUI/general/res/sass/_widgets.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										301
									
								
								platform/commonUI/general/res/sass/_widgets.scss
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,301 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/************************************************************* WIDGET OBJECT */
 | 
			
		||||
.l-summary-widget {
 | 
			
		||||
    // Widget layout classes here
 | 
			
		||||
    @include ellipsize();
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    text-align: center;
 | 
			
		||||
    .widget-label:before {
 | 
			
		||||
        // Widget icon
 | 
			
		||||
        font-size: 0.9em;
 | 
			
		||||
        margin-right: $interiorMarginSm;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-summary-widget {
 | 
			
		||||
    // Widget style classes here
 | 
			
		||||
    @include boxShdw($shdwBtns);
 | 
			
		||||
    border-radius: $basicCr;
 | 
			
		||||
    border-style: solid;
 | 
			
		||||
    border-width: 1px;
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    cursor: default;
 | 
			
		||||
    font-size: 0.8rem;
 | 
			
		||||
    padding: $interiorMarginLg $interiorMarginLg * 2;
 | 
			
		||||
    &[href] {
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.widget-edit-holder {
 | 
			
		||||
    // Hide edit area when in browse mode
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.widget-rule-header {
 | 
			
		||||
    @extend .l-flex-row;
 | 
			
		||||
    @include align-items(center);
 | 
			
		||||
    margin-bottom: $interiorMargin;
 | 
			
		||||
    > .flex-elem {
 | 
			
		||||
        &:not(:first-child) {
 | 
			
		||||
            margin-left: $interiorMargin;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.widget-rules-wrapper,
 | 
			
		||||
.widget-rule-content,
 | 
			
		||||
.w-widget-test-data-content {
 | 
			
		||||
    @include trans-prop-nice($props: (height, min-height, opacity), $dur: 250ms);
 | 
			
		||||
    min-height: 0;
 | 
			
		||||
    height: 0;
 | 
			
		||||
    opacity: 0;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.widget-rules-wrapper {
 | 
			
		||||
    flex: 1 1 auto !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.widget-rule-content.expanded {
 | 
			
		||||
    overflow: visible !important;
 | 
			
		||||
    min-height: 50px;
 | 
			
		||||
    height: auto;
 | 
			
		||||
    opacity: 1;
 | 
			
		||||
    pointer-events: inherit;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.w-widget-test-data-content {
 | 
			
		||||
    .l-enable {
 | 
			
		||||
        padding: $interiorMargin 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .w-widget-test-data-items {
 | 
			
		||||
        max-height: 20vh;
 | 
			
		||||
        overflow-y: scroll !important;
 | 
			
		||||
        padding-right: $interiorMargin;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.l-widget-thumb-wrapper,
 | 
			
		||||
.l-compact-form label {
 | 
			
		||||
    $ruleLabelW: 40%;
 | 
			
		||||
    $ruleLabelMaxW: 150px;
 | 
			
		||||
    @include display(flex);
 | 
			
		||||
    max-width: $ruleLabelMaxW;
 | 
			
		||||
    width: $ruleLabelW;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.t-message-widget-no-data {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/********************************************************** EDITING A WIDGET */
 | 
			
		||||
.s-status-editing > mct-view > .w-summary-widget {
 | 
			
		||||
    // Classes for editor layout while editing a widget
 | 
			
		||||
    // This selector is ugly and brittle, but needed to prevent interface from showing when widget is in a layout
 | 
			
		||||
    // being edited.
 | 
			
		||||
    @include absPosDefault();
 | 
			
		||||
    @extend .l-flex-col;
 | 
			
		||||
 | 
			
		||||
    > .l-summary-widget {
 | 
			
		||||
        // Main view of the summary widget
 | 
			
		||||
        // Give some airspace and center the widget in the area
 | 
			
		||||
        margin: 30px auto;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .widget-edit-holder {
 | 
			
		||||
        display: flex; // Overrides `display: none` during Browse mode
 | 
			
		||||
        .flex-accordion-holder {
 | 
			
		||||
            // Needed because otherwise accordion elements "creep" when contents expand and contract
 | 
			
		||||
            display: block !important;
 | 
			
		||||
        }
 | 
			
		||||
        &.expanded-widget-test-data {
 | 
			
		||||
            .w-widget-test-data-content {
 | 
			
		||||
                min-height: 50px;
 | 
			
		||||
                height: auto;
 | 
			
		||||
                opacity: 1;
 | 
			
		||||
                pointer-events: inherit;
 | 
			
		||||
            }
 | 
			
		||||
            &:not(.expanded-widget-rules) {
 | 
			
		||||
                // Test data is expanded and rules are collapsed
 | 
			
		||||
                // Make text data take up all the vertical space
 | 
			
		||||
                .flex-accordion-holder { display: flex; }
 | 
			
		||||
                .widget-test-data {
 | 
			
		||||
                    flex-grow: 999999;
 | 
			
		||||
                }
 | 
			
		||||
                .w-widget-test-data-items {
 | 
			
		||||
                    max-height: inherit;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        &.expanded-widget-rules {
 | 
			
		||||
            .widget-rules-wrapper {
 | 
			
		||||
                min-height: 50px;
 | 
			
		||||
                height: auto;
 | 
			
		||||
                opacity: 1;
 | 
			
		||||
                pointer-events: inherit;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.s-status-no-data {
 | 
			
		||||
        .widget-edit-holder {
 | 
			
		||||
            opacity: 0.3;
 | 
			
		||||
            pointer-events: none;
 | 
			
		||||
        }
 | 
			
		||||
        .t-message-widget-no-data {
 | 
			
		||||
            display: flex;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    .l-compact-form {
 | 
			
		||||
        // Overrides on .l-compact-form
 | 
			
		||||
        ul {
 | 
			
		||||
            &:last-child { margin: 0; }
 | 
			
		||||
            li {
 | 
			
		||||
                @include align-items(flex-start);
 | 
			
		||||
                @include flex-wrap(nowrap);
 | 
			
		||||
                line-height: 230%; // Provide enough space when controls wrap
 | 
			
		||||
                padding: 2px 0;
 | 
			
		||||
                &:not(.widget-rule-header) {
 | 
			
		||||
                    &:not(.connects-to-previous) {
 | 
			
		||||
                        border-top: 1px solid $colorFormLines;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                &.connects-to-previous {
 | 
			
		||||
                    padding: $interiorMargin 0;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                > label {
 | 
			
		||||
                    display: block; // Needed to align text to right
 | 
			
		||||
                    text-align: right;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &.s-widget-test-data-item {
 | 
			
		||||
            // Single line of ul li label span, etc.
 | 
			
		||||
            ul {
 | 
			
		||||
                li {
 | 
			
		||||
                    border: none !important;
 | 
			
		||||
                    > label {
 | 
			
		||||
                        display: inline-block;
 | 
			
		||||
                        width: auto;
 | 
			
		||||
                        text-align: left;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.widget-edit-holder {
 | 
			
		||||
    font-size: 0.8rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.widget-rules-wrapper {
 | 
			
		||||
    // Wrapper area that holds n rules
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    overflow-y: scroll;
 | 
			
		||||
    padding-right: $interiorMargin;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.l-widget-rule,
 | 
			
		||||
.l-widget-test-data-item {
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    margin-bottom: $interiorMarginSm;
 | 
			
		||||
    padding: $interiorMargin $interiorMarginLg;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.l-widget-thumb-wrapper {
 | 
			
		||||
    @extend .l-flex-row;
 | 
			
		||||
    @include align-items(center);
 | 
			
		||||
    > span { display: block; }
 | 
			
		||||
    .grippy-holder,
 | 
			
		||||
    .view-control {
 | 
			
		||||
        margin-right: $interiorMargin;
 | 
			
		||||
        width: 1em;
 | 
			
		||||
        height: 1em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .widget-thumb {
 | 
			
		||||
        @include flex(1 1 auto);
 | 
			
		||||
        width: 100%;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rule-title {
 | 
			
		||||
    @include flex(0 1 auto);
 | 
			
		||||
    color: pullForward($colorBodyFg, 50%);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.rule-description {
 | 
			
		||||
    @include flex(1 1 auto);
 | 
			
		||||
    @include ellipsize();
 | 
			
		||||
    color: pushBack($colorBodyFg, 20%);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-widget-rule,
 | 
			
		||||
.s-widget-test-data-item {
 | 
			
		||||
    background-color: rgba($colorBodyFg, 0.1);
 | 
			
		||||
    border-radius: $basicCr;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.widget-thumb {
 | 
			
		||||
    @include ellipsize();
 | 
			
		||||
    @extend .s-summary-widget;
 | 
			
		||||
    @extend .l-summary-widget;
 | 
			
		||||
    padding: $interiorMarginSm $interiorMargin;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Hide and show elements in the rule-header on hover
 | 
			
		||||
.l-widget-rule,
 | 
			
		||||
.l-widget-test-data-item {
 | 
			
		||||
    .grippy,
 | 
			
		||||
    .l-rule-action-buttons-wrapper,
 | 
			
		||||
    .l-condition-action-buttons-wrapper,
 | 
			
		||||
    .l-widget-test-data-item-action-buttons-wrapper {
 | 
			
		||||
        @include trans-prop-nice($props: opacity, $dur: 500ms);
 | 
			
		||||
        opacity: 0;
 | 
			
		||||
    }
 | 
			
		||||
    &:hover {
 | 
			
		||||
        .grippy,
 | 
			
		||||
        .l-rule-action-buttons-wrapper,
 | 
			
		||||
        .l-widget-test-data-item-action-buttons-wrapper {
 | 
			
		||||
            @include trans-prop-nice($props: opacity, $dur: 0);
 | 
			
		||||
            opacity: 1;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    .t-condition {
 | 
			
		||||
        &:hover {
 | 
			
		||||
            .l-condition-action-buttons-wrapper {
 | 
			
		||||
                @include trans-prop-nice($props: opacity, $dur: 0);
 | 
			
		||||
                opacity: 1;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -234,12 +234,16 @@ textarea {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************** INPUTS */
 | 
			
		||||
%input-base {
 | 
			
		||||
    @include input-base();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
input[type="text"],
 | 
			
		||||
input[type="search"],
 | 
			
		||||
input[type="number"] {
 | 
			
		||||
    @include nice-input();
 | 
			
		||||
    vertical-align: baseline;
 | 
			
		||||
    padding: $inputTextP;
 | 
			
		||||
    padding: $inputTextPTopBtm $inputTextPLeftRight;
 | 
			
		||||
    &.numeric {
 | 
			
		||||
        text-align: right;
 | 
			
		||||
    }
 | 
			
		||||
@@ -257,7 +261,7 @@ input[type="number"] {
 | 
			
		||||
input[type="text"].lg {  width: 100% !important; }
 | 
			
		||||
.l-input-med input[type="text"],
 | 
			
		||||
input[type="text"].med { width: 200px !important; }
 | 
			
		||||
input[type="text"].sm {  width: 50px !important; }
 | 
			
		||||
input[type="text"].sm, input[type="number"].sm {  width: 50px !important; }
 | 
			
		||||
.l-numeric input[type="text"],
 | 
			
		||||
input[type="text"].numeric { text-align: right; }
 | 
			
		||||
 | 
			
		||||
@@ -283,21 +287,44 @@ textarea.lg { position: relative; height: 300px; }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
*[contenteditable].s-input-inline,
 | 
			
		||||
input[type="text"].s-input-inline,
 | 
			
		||||
.s-input-inline input[type="text"] {
 | 
			
		||||
    // A text input or contenteditable element that indicates edit affordance on hover and looks like an input on focus
 | 
			
		||||
    @extend %input-base;
 | 
			
		||||
    @include trans-prop-nice((padding, box-shadow), 250ms);
 | 
			
		||||
    background: none;
 | 
			
		||||
    box-shadow: none;
 | 
			
		||||
    border: 1px solid transparent;
 | 
			
		||||
    min-width: 20px;
 | 
			
		||||
    padding-left: 0;
 | 
			
		||||
    padding-right: 0;
 | 
			
		||||
    &:hover,
 | 
			
		||||
    &:focus {
 | 
			
		||||
        padding-left: $inputTextPLeftRight;
 | 
			
		||||
        padding-right: $inputTextPLeftRight;
 | 
			
		||||
    }
 | 
			
		||||
    &:hover {
 | 
			
		||||
        border-color: rgba($colorBodyFg, 0.2);
 | 
			
		||||
    }
 | 
			
		||||
    &:focus {
 | 
			
		||||
        @include s-input();
 | 
			
		||||
        border-color: transparent;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************** SELECTS */
 | 
			
		||||
.select {
 | 
			
		||||
    @include btnSubtle($bg: $colorSelectBg);
 | 
			
		||||
    @extend .icon-arrow-down; // Context arrow
 | 
			
		||||
    @if $shdwBtns != none {
 | 
			
		||||
        margin: 0 0 2px 0; // Needed to avoid dropshadow from being clipped by parent containers
 | 
			
		||||
    }
 | 
			
		||||
    display: inline-block;
 | 
			
		||||
    padding: 0 $interiorMargin;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    line-height: $formInputH;
 | 
			
		||||
    select {
 | 
			
		||||
        @include appearance(none);
 | 
			
		||||
        box-sizing: border-box;
 | 
			
		||||
        &:focus { outline: 0; }
 | 
			
		||||
        background: none;
 | 
			
		||||
        color: $colorSelectFg;
 | 
			
		||||
        cursor: pointer;
 | 
			
		||||
@@ -309,11 +336,13 @@ textarea.lg { position: relative; height: 300px; }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    &:before {
 | 
			
		||||
        pointer-events: none;
 | 
			
		||||
        @include transform(translateY(-50%));
 | 
			
		||||
        color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent));
 | 
			
		||||
        display: block;
 | 
			
		||||
        pointer-events: none;
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        right: $interiorMargin; top: 0;
 | 
			
		||||
        right: $interiorMargin;
 | 
			
		||||
        top: 50%;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -365,8 +394,7 @@ textarea.lg { position: relative; height: 300px; }
 | 
			
		||||
    .l-elem-wrapper {
 | 
			
		||||
        mct-representation {
 | 
			
		||||
            // Holds the context-available item
 | 
			
		||||
            // Must have min-width to make flex work properly
 | 
			
		||||
            // in Safari
 | 
			
		||||
            // Must have min-width to make flex work properly in Safari
 | 
			
		||||
            min-width: 0.7em;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -532,7 +560,6 @@ textarea.lg { position: relative; height: 300px; }
 | 
			
		||||
    height: $h;
 | 
			
		||||
    margin-top: 1 + floor($h/2) * -1;
 | 
			
		||||
    @include btnSubtle(pullForward($colorBtnBg, 10%));
 | 
			
		||||
    //border-radius: 50% !important;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin sliderKnobRound() {
 | 
			
		||||
@@ -547,7 +574,6 @@ textarea.lg { position: relative; height: 300px; }
 | 
			
		||||
 | 
			
		||||
input[type="range"] {
 | 
			
		||||
    // HTML5 range inputs
 | 
			
		||||
 | 
			
		||||
    -webkit-appearance: none; /* Hides the slider so that custom slider can be made */
 | 
			
		||||
    background: transparent; /* Otherwise white in Chrome */
 | 
			
		||||
    &:focus {
 | 
			
		||||
@@ -705,6 +731,30 @@ textarea {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.view-switcher,
 | 
			
		||||
.t-btn-view-large {
 | 
			
		||||
    @include trans-prop-nice-fade($controlFadeMs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.view-control {
 | 
			
		||||
    @extend .icon-arrow-right;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    font-size: 0.75em;
 | 
			
		||||
    &:before {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        @include trans-prop-nice(transform, 100ms);
 | 
			
		||||
        @include transform-origin(center);
 | 
			
		||||
    }
 | 
			
		||||
    &.expanded:before {
 | 
			
		||||
        @include transform(rotate(90deg));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.grippy {
 | 
			
		||||
    @extend .icon-grippy;
 | 
			
		||||
    cursor: move;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************** BROWSER ELEMENTS */
 | 
			
		||||
body.desktop {
 | 
			
		||||
    ::-webkit-scrollbar {
 | 
			
		||||
@@ -722,11 +772,15 @@ body.desktop {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .overlay ::-webkit-scrollbar-thumb {
 | 
			
		||||
        $lr: 15%;
 | 
			
		||||
        background: $scrollbarThumbColorOverlay;
 | 
			
		||||
        &:hover { background: $scrollbarThumbColorOverlayHov; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .menu ::-webkit-scrollbar-thumb {
 | 
			
		||||
        background: $scrollbarThumbColorMenu;
 | 
			
		||||
        &:hover { background: $scrollbarThumbColorMenuHov; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ::-webkit-scrollbar-corner {
 | 
			
		||||
        background: $scrollbarTrackColorBg;
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -21,92 +21,91 @@
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
/******************************************************** MENU BUTTONS */
 | 
			
		||||
.s-menu-button {
 | 
			
		||||
	// Formerly .btn-menu
 | 
			
		||||
	@extend .s-button;
 | 
			
		||||
	span.l-click-area {
 | 
			
		||||
		// In markup, this element should not enclose anything.
 | 
			
		||||
		@extend .abs;
 | 
			
		||||
	}
 | 
			
		||||
    // Formerly .btn-menu
 | 
			
		||||
    @extend .s-button;
 | 
			
		||||
    span.l-click-area {
 | 
			
		||||
        // In markup, this element should not enclose anything.
 | 
			
		||||
        @extend .abs;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	.icon {
 | 
			
		||||
		font-size: 16px; //120%;
 | 
			
		||||
	}
 | 
			
		||||
    .icon {
 | 
			
		||||
        font-size: 16px;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	.title-label {
 | 
			
		||||
		margin-left: $interiorMarginSm;
 | 
			
		||||
	}
 | 
			
		||||
    .title-label {
 | 
			
		||||
        margin-left: $interiorMarginSm;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .icon-swatch,
 | 
			
		||||
    .color-swatch {
 | 
			
		||||
        // Used in color menu buttons in toolbar
 | 
			
		||||
        $d: 10px;
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
        border: 1px solid rgba($colorBtnFg, 0.2);
 | 
			
		||||
        height: $d; width: $d;
 | 
			
		||||
        line-height: $d;
 | 
			
		||||
        vertical-align: middle;
 | 
			
		||||
        margin-left: $interiorMarginSm;
 | 
			
		||||
        margin-top: -2px;
 | 
			
		||||
        &:not(.no-selection) {
 | 
			
		||||
            border-color: transparent;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	&:after {
 | 
			
		||||
		// Adds the downward facing 'context available / invoke menu' arrow element
 | 
			
		||||
		@include contextArrow();
 | 
			
		||||
		color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent));
 | 
			
		||||
	}
 | 
			
		||||
    &:after {
 | 
			
		||||
        // Adds the downward facing 'context available / invoke menu' arrow element
 | 
			
		||||
        @include contextArrow();
 | 
			
		||||
        color: rgba($colorInvokeMenu, percentToDecimal($contrastInvokeMenuPercent));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	&.create-button {
 | 
			
		||||
    &.create-button {
 | 
			
		||||
        @extend .icon-plus;
 | 
			
		||||
		.title-label {
 | 
			
		||||
			font-size: 1rem;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
        .title-label {
 | 
			
		||||
            font-size: 1rem;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	.menu {
 | 
			
		||||
		left: 0;
 | 
			
		||||
		text-align: left;
 | 
			
		||||
	}
 | 
			
		||||
    .menu {
 | 
			
		||||
        left: 0;
 | 
			
		||||
        text-align: left;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/******************************************************** MENUS THEMSELVES */
 | 
			
		||||
.menu-element {
 | 
			
		||||
	cursor: pointer;
 | 
			
		||||
	position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-menu {
 | 
			
		||||
	border-radius: $basicCr;
 | 
			
		||||
	@include containerSubtle($colorMenuBg, $colorMenuFg);
 | 
			
		||||
	@include boxShdw($shdwMenu);
 | 
			
		||||
	@include txtShdw($shdwMenuText);
 | 
			
		||||
	padding: $interiorMarginSm 0;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu {
 | 
			
		||||
    // TODO: reduce size of icons
 | 
			
		||||
	@extend .s-menu;
 | 
			
		||||
	display: block;
 | 
			
		||||
	position: absolute;
 | 
			
		||||
	z-index: 10;
 | 
			
		||||
	ul {
 | 
			
		||||
		@include menuUlReset();
 | 
			
		||||
		li {
 | 
			
		||||
			box-sizing: border-box;
 | 
			
		||||
			border-top: 1px solid pullForward($colorMenuBg, 10%);
 | 
			
		||||
    border-radius: $basicCr;
 | 
			
		||||
    @include containerSubtle($colorMenuBg, $colorMenuFg);
 | 
			
		||||
    @include boxShdw($shdwMenu);
 | 
			
		||||
    @include txtShdw($shdwMenuText);
 | 
			
		||||
    padding: $interiorMarginSm 0;
 | 
			
		||||
    display: block;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    z-index: 10;
 | 
			
		||||
    ul {
 | 
			
		||||
        @include menuUlReset();
 | 
			
		||||
        li {
 | 
			
		||||
            box-sizing: border-box;
 | 
			
		||||
            border-top: 1px solid pullForward($colorMenuBg, 10%);
 | 
			
		||||
            color: $colorMenuFg;
 | 
			
		||||
			//color: pullForward($colorMenuBg, 60%);
 | 
			
		||||
			line-height: $menuLineH;
 | 
			
		||||
			padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW;
 | 
			
		||||
			position: relative;
 | 
			
		||||
			white-space: nowrap;
 | 
			
		||||
			&:first-child {
 | 
			
		||||
				border: none;
 | 
			
		||||
			}
 | 
			
		||||
			&:hover {
 | 
			
		||||
				background: $colorMenuHovBg;
 | 
			
		||||
				color: $colorMenuHovFg;
 | 
			
		||||
            line-height: $menuLineH;
 | 
			
		||||
            padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW;
 | 
			
		||||
            position: relative;
 | 
			
		||||
            white-space: nowrap;
 | 
			
		||||
            &:first-child {
 | 
			
		||||
                border: none;
 | 
			
		||||
            }
 | 
			
		||||
            &:hover {
 | 
			
		||||
                background: $colorMenuHovBg;
 | 
			
		||||
                color: $colorMenuHovFg;
 | 
			
		||||
                &:before {
 | 
			
		||||
                    color: $colorMenuHovIc;
 | 
			
		||||
                }
 | 
			
		||||
			}
 | 
			
		||||
            }
 | 
			
		||||
            &:before {
 | 
			
		||||
                @extend .ui-symbol;
 | 
			
		||||
                @extend .type-icon;
 | 
			
		||||
@@ -114,8 +113,8 @@
 | 
			
		||||
                display: inline-block;
 | 
			
		||||
                left: $interiorMargin * 2;
 | 
			
		||||
            }
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menu,
 | 
			
		||||
@@ -123,94 +122,97 @@
 | 
			
		||||
.context-menu,
 | 
			
		||||
.super-menu,
 | 
			
		||||
.s-menu-button .menu {
 | 
			
		||||
	pointer-events: auto;
 | 
			
		||||
	ul li {
 | 
			
		||||
		a.menu-item-a {
 | 
			
		||||
    pointer-events: auto;
 | 
			
		||||
    ul li {
 | 
			
		||||
        a.menu-item-a {
 | 
			
		||||
            color: $colorMenuFg;
 | 
			
		||||
            display: block;
 | 
			
		||||
		}
 | 
			
		||||
        }
 | 
			
		||||
        &:before,
 | 
			
		||||
        a.menu-item-a:before {
 | 
			
		||||
            color: $colorMenuIc;
 | 
			
		||||
            left: $interiorMargin;
 | 
			
		||||
        }
 | 
			
		||||
	}
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.checkbox-menu {
 | 
			
		||||
	// Used in search dropdown in tree
 | 
			
		||||
	@extend .context-menu;
 | 
			
		||||
	ul li {
 | 
			
		||||
		padding-left: 50px;
 | 
			
		||||
		.checkbox {
 | 
			
		||||
			$d: 0.7rem;
 | 
			
		||||
			position: absolute;
 | 
			
		||||
			left: $interiorMargin;
 | 
			
		||||
			top: ($menuLineH - $d) / 1.5;
 | 
			
		||||
			em {
 | 
			
		||||
				height: $d;
 | 
			
		||||
				width: $d;
 | 
			
		||||
				&:before {
 | 
			
		||||
					font-size: 7px !important;
 | 
			
		||||
					height: $d;
 | 
			
		||||
					width: $d;
 | 
			
		||||
					line-height: $d;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		&:before {
 | 
			
		||||
    // Used in search dropdown in tree
 | 
			
		||||
    @extend .context-menu;
 | 
			
		||||
    ul li {
 | 
			
		||||
        padding-left: 50px;
 | 
			
		||||
        .checkbox {
 | 
			
		||||
            $d: 0.7rem;
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            left: $interiorMargin;
 | 
			
		||||
            top: ($menuLineH - $d) / 1.5;
 | 
			
		||||
            em {
 | 
			
		||||
                height: $d;
 | 
			
		||||
                width: $d;
 | 
			
		||||
                &:before {
 | 
			
		||||
                    font-size: 7px !important;
 | 
			
		||||
                    height: $d;
 | 
			
		||||
                    width: $d;
 | 
			
		||||
                    line-height: $d;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        &:before {
 | 
			
		||||
            // Type icon
 | 
			
		||||
			left: 25px;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
            left: 25px;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.super-menu,
 | 
			
		||||
.super-menu > mct-representation,
 | 
			
		||||
.super-menu > .contents {
 | 
			
		||||
    box-sizing: border-box;
 | 
			
		||||
    display: block;
 | 
			
		||||
    position: relative;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.super-menu {
 | 
			
		||||
	$w: 500px;
 | 
			
		||||
	$h: $w - 20;
 | 
			
		||||
	$plw: 50%;
 | 
			
		||||
	$prw: 50%;
 | 
			
		||||
	display: block;
 | 
			
		||||
	width: $w;
 | 
			
		||||
	height: $h;
 | 
			
		||||
	.contents {
 | 
			
		||||
		@include absPosDefault($interiorMargin);
 | 
			
		||||
	}
 | 
			
		||||
	.pane {
 | 
			
		||||
		box-sizing: border-box;
 | 
			
		||||
		&.menu-items {
 | 
			
		||||
			border-right: 1px solid pullForward($colorMenuBg, 10%);
 | 
			
		||||
			left: 0;
 | 
			
		||||
			padding-right: $interiorMargin;
 | 
			
		||||
			right: auto;
 | 
			
		||||
			width: $plw;
 | 
			
		||||
			overflow-x: hidden;
 | 
			
		||||
			overflow-y: auto;
 | 
			
		||||
			ul {
 | 
			
		||||
				li {
 | 
			
		||||
					border-radius: $controlCr;
 | 
			
		||||
					padding-left: 30px;
 | 
			
		||||
					border-top: none;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		&.menu-item-description {
 | 
			
		||||
			left: auto;
 | 
			
		||||
			right: 0;
 | 
			
		||||
			padding: $interiorMargin * 5;
 | 
			
		||||
			width: $prw;
 | 
			
		||||
    $plw: 50%;
 | 
			
		||||
    $prw: 100% - $plw;
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    .w-menu {
 | 
			
		||||
        align-items: stretch;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: row;
 | 
			
		||||
        margin: $interiorMarginLg;
 | 
			
		||||
    }
 | 
			
		||||
    .col {
 | 
			
		||||
        box-sizing: border-box;
 | 
			
		||||
        flex: 1 1 auto;
 | 
			
		||||
        overflow-x: hidden;
 | 
			
		||||
        &.menu-items {
 | 
			
		||||
            border-right: 1px solid pullForward($colorMenuBg, 10%);
 | 
			
		||||
            overflow-y: auto;
 | 
			
		||||
            padding-right: $interiorMargin;
 | 
			
		||||
            width: $plw;
 | 
			
		||||
            ul {
 | 
			
		||||
                li {
 | 
			
		||||
                    border-radius: $controlCr;
 | 
			
		||||
                    padding-left: 30px;
 | 
			
		||||
                    border-top: none;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        &.menu-item-description {
 | 
			
		||||
            $p: $interiorMargin * 3;
 | 
			
		||||
            overflow-y: hidden;
 | 
			
		||||
            padding: $p $p 0 $p;
 | 
			
		||||
            width: $prw;
 | 
			
		||||
 | 
			
		||||
            .desc-area {
 | 
			
		||||
                &.icon {
 | 
			
		||||
                    color: $colorCreateMenuLgIcon;
 | 
			
		||||
                    font-size: 8em;
 | 
			
		||||
                    margin-bottom: $interiorMargin * 3;
 | 
			
		||||
                    position: relative;
 | 
			
		||||
                    text-align: center;
 | 
			
		||||
                }
 | 
			
		||||
                &.title {
 | 
			
		||||
                    color: $colorCreateMenuText;
 | 
			
		||||
                    font-size: 1.2em;
 | 
			
		||||
                    margin-bottom: $interiorMargin * 2;
 | 
			
		||||
                }
 | 
			
		||||
                &.description {
 | 
			
		||||
                    color: pushBack($colorCreateMenuText, 20%);
 | 
			
		||||
@@ -218,67 +220,104 @@
 | 
			
		||||
                    line-height: 1.5em;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .w-title-desc {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        overflow: hidden; // Height set in specific menu instances
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Specific menu instances
 | 
			
		||||
    &.l-create-menu {
 | 
			
		||||
        width: 500px;
 | 
			
		||||
        .col {
 | 
			
		||||
            max-height: 70vh;
 | 
			
		||||
        }
 | 
			
		||||
        .w-title-desc {
 | 
			
		||||
            height: 190px;
 | 
			
		||||
        }
 | 
			
		||||
        .desc-area {
 | 
			
		||||
            &.icon {
 | 
			
		||||
                font-size: 8em;
 | 
			
		||||
                height: 135px;
 | 
			
		||||
                margin-bottom: $interiorMargin * 3;
 | 
			
		||||
            }
 | 
			
		||||
            &.title {
 | 
			
		||||
                font-size: 1.2em;
 | 
			
		||||
                margin-bottom: $interiorMargin * 2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.mini {
 | 
			
		||||
        width: 400px;
 | 
			
		||||
        height: 300px;
 | 
			
		||||
        .pane {
 | 
			
		||||
        .col {
 | 
			
		||||
            max-height: 50vh;
 | 
			
		||||
            &.menu-items {
 | 
			
		||||
                font-size: 0.8em;
 | 
			
		||||
            }
 | 
			
		||||
            &.menu-item-description {
 | 
			
		||||
                padding: $interiorMargin * 3;
 | 
			
		||||
                .desc-area {
 | 
			
		||||
                    &.icon {
 | 
			
		||||
                        font-size: 4em;
 | 
			
		||||
                    }
 | 
			
		||||
                    &.title {
 | 
			
		||||
                        font-size: 1em;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                $p: $interiorMargin * 2;
 | 
			
		||||
                padding: $p $p 0 $p;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        .w-title-desc {
 | 
			
		||||
            height: 180px;
 | 
			
		||||
        }
 | 
			
		||||
        .desc-area {
 | 
			
		||||
            &.icon {
 | 
			
		||||
                font-size: 4em;
 | 
			
		||||
                height: 70px;
 | 
			
		||||
                margin-bottom: $interiorMargin * 3;
 | 
			
		||||
            }
 | 
			
		||||
            &.title {
 | 
			
		||||
                font-size: 1em;
 | 
			
		||||
                margin-bottom: $interiorMargin * 2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.context-menu {
 | 
			
		||||
	font-size: 0.80rem;
 | 
			
		||||
    font-size: 0.80rem;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.context-menu-holder,
 | 
			
		||||
.menu-holder {
 | 
			
		||||
	position: absolute;
 | 
			
		||||
	z-index: 120;
 | 
			
		||||
	.context-menu-wrapper {
 | 
			
		||||
		position: absolute;
 | 
			
		||||
		height: 100%;
 | 
			
		||||
		width: 100%;
 | 
			
		||||
	}
 | 
			
		||||
	&.go-left .context-menu,
 | 
			
		||||
	&.go-left .menu {
 | 
			
		||||
		right: 0;
 | 
			
		||||
	}
 | 
			
		||||
	&.go-up .context-menu,
 | 
			
		||||
	&.go-up .menu {
 | 
			
		||||
		bottom: 0;
 | 
			
		||||
	}
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    z-index: 120;
 | 
			
		||||
    .context-menu-wrapper {
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
    }
 | 
			
		||||
    &.go-left .context-menu,
 | 
			
		||||
    &.go-left .menu {
 | 
			
		||||
        right: 0;
 | 
			
		||||
    }
 | 
			
		||||
    &.go-up .context-menu,
 | 
			
		||||
    &.go-up .menu {
 | 
			
		||||
        bottom: 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.context-menu-holder {
 | 
			
		||||
	pointer-events: none;
 | 
			
		||||
	height: 200px;
 | 
			
		||||
	width: 170px;
 | 
			
		||||
    pointer-events: none;
 | 
			
		||||
    height: 200px;
 | 
			
		||||
    width: 170px;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.btn-bar.right .menu,
 | 
			
		||||
.menus-to-left .menu {
 | 
			
		||||
    z-index: 79;
 | 
			
		||||
	left: auto;
 | 
			
		||||
	right: 0;
 | 
			
		||||
	width: auto;
 | 
			
		||||
    left: auto;
 | 
			
		||||
    right: 0;
 | 
			
		||||
    width: auto;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.menus-up .menu {
 | 
			
		||||
    bottom: $btnStdH; top: auto;
 | 
			
		||||
    bottom: $btnStdH;
 | 
			
		||||
    top: auto;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -19,7 +19,7 @@
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/******************************************************************* STATUS BLOCK ELEMS */
 | 
			
		||||
@mixin statusBannerColors($bg, $fg: $colorStatusFg) {
 | 
			
		||||
	$bgPb: 30%;
 | 
			
		||||
	$bgPbD: 10%;
 | 
			
		||||
@@ -120,7 +120,11 @@
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.status-indicator {
 | 
			
		||||
        background: none !important;
 | 
			
		||||
		margin-right: $interiorMarginSm;
 | 
			
		||||
        &[class*='s-status']:before {
 | 
			
		||||
            font-size: 1em;
 | 
			
		||||
        }
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	.count {
 | 
			
		||||
@@ -136,7 +140,7 @@
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/* Styles for messages and message banners */
 | 
			
		||||
/******************************************************************* MESSAGE BANNERS */
 | 
			
		||||
.message {
 | 
			
		||||
	&.block {
 | 
			
		||||
		border-radius: $basicCr;
 | 
			
		||||
@@ -192,7 +196,6 @@
 | 
			
		||||
		padding: 0 $interiorMargin;
 | 
			
		||||
	}
 | 
			
		||||
    .close {
 | 
			
		||||
		//@include test(red, 0.7);
 | 
			
		||||
		cursor: pointer;
 | 
			
		||||
        font-size: 7px;
 | 
			
		||||
		width: 8px;
 | 
			
		||||
@@ -236,132 +239,147 @@
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin messageBlock($iconW: 32px) {
 | 
			
		||||
    .type-icon.message-type {
 | 
			
		||||
/******************************************************************* MESSAGES */
 | 
			
		||||
 | 
			
		||||
/* Contexts:
 | 
			
		||||
    In .t-message-list
 | 
			
		||||
    In .overlay as a singleton
 | 
			
		||||
    Inline in the view area
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// Archetypal message
 | 
			
		||||
.l-message {
 | 
			
		||||
    $iconW: 32px;
 | 
			
		||||
    @include display(flex);
 | 
			
		||||
    @include flex-direction(row);
 | 
			
		||||
    @include align-items(stretch);
 | 
			
		||||
    padding: $interiorMarginLg;
 | 
			
		||||
 | 
			
		||||
    &:before {
 | 
			
		||||
        // Icon
 | 
			
		||||
        @include flex(0 1 auto);
 | 
			
		||||
        @include txtShdw($shdwStatusIc);
 | 
			
		||||
        @extend .icon-bell;
 | 
			
		||||
        color: $colorStatusDefault;
 | 
			
		||||
        font-size: $iconW;
 | 
			
		||||
        padding: 1px;
 | 
			
		||||
        width: $iconW + 2;
 | 
			
		||||
        margin-right: $interiorMarginLg;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .message-severity-info .type-icon.message-type {
 | 
			
		||||
    &.message-severity-info:before {
 | 
			
		||||
        @extend .icon-info;
 | 
			
		||||
        color: $colorInfo;
 | 
			
		||||
    }
 | 
			
		||||
    .message-severity-alert .type-icon.message-type {
 | 
			
		||||
        @extend .icon-bell;
 | 
			
		||||
 | 
			
		||||
    &.message-severity-alert:before {
 | 
			
		||||
        color: $colorWarningLo;
 | 
			
		||||
    }
 | 
			
		||||
    .message-severity-error .type-icon.message-type {
 | 
			
		||||
 | 
			
		||||
    &.message-severity-error:before {
 | 
			
		||||
        @extend .icon-alert-rect;
 | 
			
		||||
        color: $colorWarningHi;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
/* Paths:
 | 
			
		||||
    t-dialog | t-dialog-sm > t-message-single | t-message-list > overlay > holder > contents > l-message >
 | 
			
		||||
        message-type > (icon)
 | 
			
		||||
        message-contents >
 | 
			
		||||
        top-bar >
 | 
			
		||||
            title
 | 
			
		||||
            hint
 | 
			
		||||
        editor >
 | 
			
		||||
            (if displaying list of messages)
 | 
			
		||||
            ul > li > l-message >
 | 
			
		||||
                ... same as above
 | 
			
		||||
        bottom-bar
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
.l-message {
 | 
			
		||||
 | 
			
		||||
.w-message-contents {
 | 
			
		||||
    @include flex(1 1 auto);
 | 
			
		||||
    @include display(flex);
 | 
			
		||||
    @include flex-direction(row);
 | 
			
		||||
    @include align-items(stretch);
 | 
			
		||||
    .type-icon.message-type {
 | 
			
		||||
        @include flex(0 1 auto);
 | 
			
		||||
        position: relative;
 | 
			
		||||
    }
 | 
			
		||||
    .message-contents {
 | 
			
		||||
        @include flex(1 1 auto);
 | 
			
		||||
        margin-left: $overlayMargin;
 | 
			
		||||
        position: relative;
 | 
			
		||||
    @include flex-direction(column);
 | 
			
		||||
 | 
			
		||||
        .top-bar,
 | 
			
		||||
    > div,
 | 
			
		||||
    > span {
 | 
			
		||||
        //@include test(red);
 | 
			
		||||
        margin-bottom: $interiorMargin;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .message-body {
 | 
			
		||||
        @include flex(1 1 100%);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Singleton in an overlay dialog
 | 
			
		||||
.t-message-single .l-message,
 | 
			
		||||
.t-message-single.l-message {
 | 
			
		||||
        $iconW: 80px;
 | 
			
		||||
        @include absPosDefault();
 | 
			
		||||
        padding: 0;
 | 
			
		||||
        &:before {
 | 
			
		||||
            font-size: $iconW;
 | 
			
		||||
            width: $iconW + 2;
 | 
			
		||||
        }
 | 
			
		||||
        .title {
 | 
			
		||||
            font-size: 1.2em;
 | 
			
		||||
        }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Singleton inline in a view
 | 
			
		||||
.t-message-inline .l-message,
 | 
			
		||||
.t-message-inline.l-message {
 | 
			
		||||
    border-radius: $controlCr;
 | 
			
		||||
    &.message-severity-info { background-color: rgba($colorInfo, 0.3); }
 | 
			
		||||
    &.message-severity-alert { background-color: rgba($colorWarningLo, 0.3); }
 | 
			
		||||
    &.message-severity-error { background-color: rgba($colorWarningHi, 0.3); }
 | 
			
		||||
 | 
			
		||||
    .w-message-contents.l-message-body-only {
 | 
			
		||||
        .message-body {
 | 
			
		||||
            margin-bottom: $interiorMarginLg * 2;
 | 
			
		||||
            margin-top: $interiorMargin;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// In a list
 | 
			
		||||
.t-message-list {
 | 
			
		||||
    @include absPosDefault();
 | 
			
		||||
    @include display(flex);
 | 
			
		||||
    @include flex-direction(column);
 | 
			
		||||
 | 
			
		||||
// Message as singleton
 | 
			
		||||
.t-message-single {
 | 
			
		||||
    @include messageBlock(80px);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body.desktop .t-message-single {
 | 
			
		||||
    .l-message,
 | 
			
		||||
    .bottom-bar {
 | 
			
		||||
        @include absPosDefault();
 | 
			
		||||
    > div,
 | 
			
		||||
    > span {
 | 
			
		||||
        margin-bottom: $interiorMargin;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .bottom-bar {
 | 
			
		||||
        top: auto;
 | 
			
		||||
        height: $ovrFooterH;
 | 
			
		||||
    .w-messages {
 | 
			
		||||
        @include flex(1 1 100%);
 | 
			
		||||
        overflow-y: auto;
 | 
			
		||||
        padding-right: $interiorMargin;
 | 
			
		||||
    }
 | 
			
		||||
    // Each message
 | 
			
		||||
    .l-message {
 | 
			
		||||
        border-radius: $controlCr;
 | 
			
		||||
        background: rgba($colorOvrFg, 0.1);
 | 
			
		||||
        margin-bottom: $interiorMargin;
 | 
			
		||||
        .hint,
 | 
			
		||||
        .bottom-bar {
 | 
			
		||||
            text-align: left;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@include phonePortrait {
 | 
			
		||||
    .t-message-single {
 | 
			
		||||
        .l-message {
 | 
			
		||||
            @include flex-direction(column);
 | 
			
		||||
            .message-contents { margin-left: 0; }
 | 
			
		||||
        }
 | 
			
		||||
        .type-icon.message-type {
 | 
			
		||||
    .t-message-single .l-message,
 | 
			
		||||
    .t-message-single.l-message {
 | 
			
		||||
        @include flex-direction(column);
 | 
			
		||||
        &:before {
 | 
			
		||||
            margin-right: 0;
 | 
			
		||||
            margin-bottom: $interiorMarginLg;
 | 
			
		||||
            width: 100%;
 | 
			
		||||
            text-align: center;
 | 
			
		||||
            width: 100%;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .bottom-bar {
 | 
			
		||||
            text-align: center !important;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Messages in list
 | 
			
		||||
.t-message-list {
 | 
			
		||||
    @include messageBlock(32px);
 | 
			
		||||
 | 
			
		||||
    .message-contents {
 | 
			
		||||
        .l-message {
 | 
			
		||||
            border-radius: $controlCr;
 | 
			
		||||
            background: rgba($colorOvrFg, 0.1);
 | 
			
		||||
            margin-bottom: $interiorMargin;
 | 
			
		||||
            padding: $interiorMarginLg;
 | 
			
		||||
 | 
			
		||||
            .message-contents,
 | 
			
		||||
            .bottom-bar {
 | 
			
		||||
                position: relative;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .message-contents {
 | 
			
		||||
                font-size: 0.9em;
 | 
			
		||||
                margin-left: $interiorMarginLg;
 | 
			
		||||
                .message-action { color: pushBack($colorOvrFg, 20%); }
 | 
			
		||||
                .bottom-bar { text-align: left; }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .top-bar,
 | 
			
		||||
            .message-body {
 | 
			
		||||
                margin-bottom: $interiorMarginLg;
 | 
			
		||||
            text-align: center;
 | 
			
		||||
            .s-button {
 | 
			
		||||
                display: block;
 | 
			
		||||
                width: 100%;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
body.desktop .t-message-list {
 | 
			
		||||
    .message-contents .l-message { margin-right: $interiorMarginLg; }
 | 
			
		||||
    .w-message-contents { padding-right: $interiorMargin; }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Alert elements in views
 | 
			
		||||
 
 | 
			
		||||
@@ -19,11 +19,10 @@
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
.l-color-palette {
 | 
			
		||||
.l-palette {
 | 
			
		||||
	$d: 16px;
 | 
			
		||||
	$colorsPerRow: 10;
 | 
			
		||||
	$m: 1;
 | 
			
		||||
	$colorSelectedColor: #fff;
 | 
			
		||||
 | 
			
		||||
	box-sizing: border-box;
 | 
			
		||||
	padding: $interiorMargin !important;
 | 
			
		||||
@@ -33,46 +32,41 @@
 | 
			
		||||
		line-height: $d;
 | 
			
		||||
		width: ($d * $colorsPerRow) + ($m * $colorsPerRow);
 | 
			
		||||
 | 
			
		||||
        &.l-option-row {
 | 
			
		||||
            margin-bottom: $interiorMargin;
 | 
			
		||||
            .s-palette-item {
 | 
			
		||||
                border-color: $colorPaletteFg;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
		.l-palette-item {
 | 
			
		||||
			box-sizing: border-box;
 | 
			
		||||
			@include txtShdwSubtle(0.8);
 | 
			
		||||
			@include trans-prop-nice-fade(0.25s);
 | 
			
		||||
			border: 1px solid transparent;
 | 
			
		||||
			color: $colorSelectedColor;
 | 
			
		||||
			display: block;
 | 
			
		||||
			float: left;
 | 
			
		||||
			height: $d; width: $d;
 | 
			
		||||
			line-height: $d * 0.9;
 | 
			
		||||
			margin: 0 ($m * 1px) ($m * 1px) 0;
 | 
			
		||||
            position: relative;
 | 
			
		||||
			text-align: center;
 | 
			
		||||
            &:before {
 | 
			
		||||
                // Check mark for selected items
 | 
			
		||||
                font-size: 0.8em;
 | 
			
		||||
            }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.s-palette-item {
 | 
			
		||||
            border: 1px solid transparent;
 | 
			
		||||
            color: $colorPaletteFg;
 | 
			
		||||
            text-shadow: $shdwPaletteFg;
 | 
			
		||||
            @include trans-prop-nice-fade(0.25s);
 | 
			
		||||
			&:hover {
 | 
			
		||||
				@include trans-prop-nice-fade(0);
 | 
			
		||||
				border-color: $colorSelectedColor !important;
 | 
			
		||||
				border-color: $colorPaletteSelected !important;
 | 
			
		||||
			}
 | 
			
		||||
            &.selected {
 | 
			
		||||
                border-color: $colorPaletteSelected;
 | 
			
		||||
                box-shadow: $shdwPaletteSelected; //Needed to see selection rect on light colored swatches
 | 
			
		||||
            }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		.l-palette-item-label {
 | 
			
		||||
			margin-left: $interiorMargin;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		&.l-option-row {
 | 
			
		||||
			margin-bottom: $interiorMargin;
 | 
			
		||||
			.s-palette-item {
 | 
			
		||||
				border-color: $colorBodyFg;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
}
 | 
			
		||||
@@ -20,7 +20,19 @@
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
.section-header {
 | 
			
		||||
    border-radius: $basicCr;
 | 
			
		||||
    background: $colorFormSectionHeader;
 | 
			
		||||
    color: lighten($colorBodyFg, 20%);
 | 
			
		||||
    font-size: inherit;
 | 
			
		||||
    margin: $interiorMargin 0;
 | 
			
		||||
    padding: $formTBPad $formLRPad;
 | 
			
		||||
    text-transform: uppercase;
 | 
			
		||||
    .view-control {
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
        margin-right: $interiorMargin;
 | 
			
		||||
        width: 1em;
 | 
			
		||||
        height: 1em;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.form {
 | 
			
		||||
@@ -41,15 +53,6 @@
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .section-header {
 | 
			
		||||
        border-radius: $basicCr;
 | 
			
		||||
        background: $colorFormSectionHeader;
 | 
			
		||||
        $c: lighten($colorBodyFg, 20%);
 | 
			
		||||
        color: $c;
 | 
			
		||||
        font-size: 0.8em;
 | 
			
		||||
        padding: $formTBPad $formLRPad;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
	.form-row {
 | 
			
		||||
		$m: $interiorMargin;
 | 
			
		||||
		box-sizing: border-box;
 | 
			
		||||
@@ -57,9 +60,6 @@
 | 
			
		||||
        margin-bottom: $interiorMarginLg * 2;
 | 
			
		||||
		padding: $formTBPad 0;
 | 
			
		||||
		position: relative;
 | 
			
		||||
        //&ng-form {
 | 
			
		||||
        //    display: block;
 | 
			
		||||
        //}
 | 
			
		||||
 | 
			
		||||
		&.first {
 | 
			
		||||
			border-top: none;
 | 
			
		||||
@@ -171,3 +171,106 @@
 | 
			
		||||
		padding: $interiorMargin;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**************************************************************************** COMPACT FORM */
 | 
			
		||||
// ul > li > label, control
 | 
			
		||||
// Make a new UL for each form section
 | 
			
		||||
// Allow control-first, controls-below
 | 
			
		||||
// TO-DO: migrate work in branch ch-plot-styling that users .inspector-config to use classes below instead
 | 
			
		||||
 | 
			
		||||
.l-compact-form .tree ul li,
 | 
			
		||||
.l-compact-form ul li {
 | 
			
		||||
    padding: 2px 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.l-compact-form {
 | 
			
		||||
    $labelW: 40%;
 | 
			
		||||
    $minW: $labelW;
 | 
			
		||||
    ul {
 | 
			
		||||
        margin-bottom: $interiorMarginLg;
 | 
			
		||||
        li {
 | 
			
		||||
            @include display(flex);
 | 
			
		||||
            @include flex-wrap(wrap);
 | 
			
		||||
            @include align-items(center);
 | 
			
		||||
            label,
 | 
			
		||||
            .control {
 | 
			
		||||
                @include display(flex);
 | 
			
		||||
            }
 | 
			
		||||
            label {
 | 
			
		||||
                line-height: inherit;
 | 
			
		||||
                width: $labelW;
 | 
			
		||||
            }
 | 
			
		||||
            .controls {
 | 
			
		||||
                @include flex-grow(1);
 | 
			
		||||
                margin-left: $interiorMargin;
 | 
			
		||||
                input[type="text"],
 | 
			
		||||
                input[type="search"],
 | 
			
		||||
                input[type="number"],
 | 
			
		||||
                .select {
 | 
			
		||||
                    height: $btnStdH;
 | 
			
		||||
                    line-height: $btnStdH;
 | 
			
		||||
                    vertical-align: middle;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                .e-control {
 | 
			
		||||
                    // Individual form controls
 | 
			
		||||
                    &:not(:first-child) {
 | 
			
		||||
                        margin-left: $interiorMarginSm;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &.connects-to-previous {
 | 
			
		||||
                padding-top: 0;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &.section-header {
 | 
			
		||||
                margin-top: $interiorMarginLg;
 | 
			
		||||
                border-top: 1px solid $colorFormLines;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            &.controls-first {
 | 
			
		||||
                .control {
 | 
			
		||||
                    @include flex-grow(0);
 | 
			
		||||
                    margin-right: $interiorMargin;
 | 
			
		||||
                    min-width: 0;
 | 
			
		||||
                    order: 1;
 | 
			
		||||
                    width: auto;
 | 
			
		||||
                }
 | 
			
		||||
                label {
 | 
			
		||||
                    @include flex-grow(1);
 | 
			
		||||
                    order: 2;
 | 
			
		||||
                    width: auto;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &.controls-under {
 | 
			
		||||
                display: block;
 | 
			
		||||
                .control, label {
 | 
			
		||||
                    display: block;
 | 
			
		||||
                    width: auto;
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ul li {
 | 
			
		||||
                    border-top: none !important;
 | 
			
		||||
                    padding: 0;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .form-error {
 | 
			
		||||
        // Block element that visually flags an error and contains a message
 | 
			
		||||
        background-color: $colorFormFieldErrorBg;
 | 
			
		||||
        color: $colorFormFieldErrorFg;
 | 
			
		||||
        border-radius: $basicCr;
 | 
			
		||||
        display: block;
 | 
			
		||||
        padding: 1px 6px;
 | 
			
		||||
        &:before {
 | 
			
		||||
            content: $glyph-icon-alert-triangle;
 | 
			
		||||
            display: inline;
 | 
			
		||||
            font-family: symbolsfont;
 | 
			
		||||
            margin-right: $interiorMarginSm;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -129,9 +129,6 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-filter {
 | 
			
		||||
    input[type="search"] {
 | 
			
		||||
        @include input-base();
 | 
			
		||||
    }
 | 
			
		||||
    .clear-icon,
 | 
			
		||||
    .menu-icon,
 | 
			
		||||
    &:before {
 | 
			
		||||
 
 | 
			
		||||
@@ -79,6 +79,7 @@
 | 
			
		||||
 | 
			
		||||
    // Dialog boxes, size constrained and centered in desktop/tablet
 | 
			
		||||
    &.l-dialog {
 | 
			
		||||
        font-size: 0.8rem;
 | 
			
		||||
        .s-button {
 | 
			
		||||
            &:not(.major) {
 | 
			
		||||
                @include btnSubtle($bg: $colorOvrBtnBg, $bgHov: pullForward($colorOvrBtnBg, 10%), $fg: $colorOvrBtnFg, $fgHov: $colorOvrBtnFg, $ic: $colorOvrBtnFg, $icHov: $colorOvrBtnFg);
 | 
			
		||||
@@ -125,9 +126,9 @@
 | 
			
		||||
            @include containerSubtle($colorOvrBg, $colorOvrFg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .title {
 | 
			
		||||
        .dialog-title {
 | 
			
		||||
            @include ellipsize();
 | 
			
		||||
            font-size: 1.2em;
 | 
			
		||||
            font-size: 1.5em;
 | 
			
		||||
            line-height: 120%;
 | 
			
		||||
            margin-bottom: $interiorMargin;
 | 
			
		||||
        }
 | 
			
		||||
@@ -156,6 +157,8 @@
 | 
			
		||||
            left: 0;
 | 
			
		||||
            right: 0;
 | 
			
		||||
            overflow: auto;
 | 
			
		||||
            padding-right: $interiorMargin;
 | 
			
		||||
            padding-bottom: $interiorMargin;
 | 
			
		||||
            .field.l-input-med {
 | 
			
		||||
                input[type='text'] {
 | 
			
		||||
                    width: 100%;
 | 
			
		||||
 
 | 
			
		||||
@@ -52,21 +52,13 @@ ul.tree {
 | 
			
		||||
 | 
			
		||||
    .view-control {
 | 
			
		||||
        color: $colorItemTreeVC;
 | 
			
		||||
        font-size: 0.75em;
 | 
			
		||||
        margin-right: $interiorMargin;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        line-height: inherit;
 | 
			
		||||
        width: $treeVCW;
 | 
			
		||||
        &:before { display: none; }
 | 
			
		||||
        &.has-children {
 | 
			
		||||
            &:before {
 | 
			
		||||
                position: absolute;
 | 
			
		||||
                @include trans-prop-nice(transform, 100ms);
 | 
			
		||||
                content: "\e904";
 | 
			
		||||
                @include transform-origin(center);
 | 
			
		||||
            }
 | 
			
		||||
            &.expanded:before {
 | 
			
		||||
                @include transform(rotate(90deg));
 | 
			
		||||
            }
 | 
			
		||||
            &:before { display: block; }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -44,10 +44,13 @@
 | 
			
		||||
 | 
			
		||||
    &.t-object-type-timer,
 | 
			
		||||
    &.t-object-type-clock,
 | 
			
		||||
    &.t-object-type-hyperlink {
 | 
			
		||||
    &.t-object-type-hyperlink,
 | 
			
		||||
    &.t-object-type-summary-widget,
 | 
			
		||||
    &.no-frame .t-object-type-fixed-display,
 | 
			
		||||
    &.no-frame .t-object-type-layout {
 | 
			
		||||
        // Hide the right side buttons for objects where they don't make sense
 | 
			
		||||
        // Note that this will hide the view Switcher button if applied
 | 
			
		||||
        // to an object that it.
 | 
			
		||||
        // to an object that has it.
 | 
			
		||||
        .object-browse-bar .right { display: none; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -103,7 +106,7 @@
 | 
			
		||||
        }
 | 
			
		||||
        &.t-frame-outer > .t-rep-frame {
 | 
			
		||||
            &.contents {
 | 
			
		||||
                $m: 2px;
 | 
			
		||||
                $m: 0px;
 | 
			
		||||
                top: $m;
 | 
			
		||||
                right: $m;
 | 
			
		||||
                bottom: $m;
 | 
			
		||||
@@ -120,14 +123,26 @@
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.t-frame-outer .s-input-inline {
 | 
			
		||||
        // Prevent inline inputs from being edited when nested in a Layout
 | 
			
		||||
        pointer-events: none !important;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /********************************************************** OBJECT TYPES */
 | 
			
		||||
    .t-object-type-hyperlink {
 | 
			
		||||
    .t-object-type-hyperlink,
 | 
			
		||||
    .t-object-type-summary-widget {
 | 
			
		||||
        .object-holder {
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
        }
 | 
			
		||||
        .w-summary-widget,
 | 
			
		||||
        .l-summary-widget,
 | 
			
		||||
        .l-hyperlink.s-button {
 | 
			
		||||
            // When a hyperlink is a button in a frame, make it expand to fill out to the object-holder
 | 
			
		||||
            // Some object types expand to the full size of the object-holder.
 | 
			
		||||
            @extend .abs;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .l-summary-widget,
 | 
			
		||||
        .l-hyperlink.s-button {
 | 
			
		||||
            .label {
 | 
			
		||||
                @include ellipsize();
 | 
			
		||||
                @include transform(translateY(-50%));
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
.s-hover-border {
 | 
			
		||||
    border: 1px dotted transparent;
 | 
			
		||||
    border: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-status-editing {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<!-- look at action-button for example -->
 | 
			
		||||
<span class="t-filter l-filter s-filter"
 | 
			
		||||
<span class="t-filter l-filter"
 | 
			
		||||
      ng-controller="GetterSetterController">
 | 
			
		||||
	<input type="search"
 | 
			
		||||
           class="t-filter-input"
 | 
			
		||||
 
 | 
			
		||||
@@ -108,8 +108,11 @@ define(
 | 
			
		||||
 | 
			
		||||
                getMetadata();
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
            var mutation = $scope.ngModel.selectedObject.getCapability('mutation');
 | 
			
		||||
            var unlisten = mutation.listen(getMetadata);
 | 
			
		||||
            $scope.$on('$destroy', unlisten);
 | 
			
		||||
        }
 | 
			
		||||
        return ObjectInspectorController;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
 
 | 
			
		||||
@@ -39,10 +39,18 @@ define(
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                mockScope = jasmine.createSpyObj(
 | 
			
		||||
                    "$scope",
 | 
			
		||||
                    ["$watch"]
 | 
			
		||||
                    ["$watch", "$on"]
 | 
			
		||||
                );
 | 
			
		||||
                mockScope.ngModel = {};
 | 
			
		||||
                mockScope.ngModel.selectedObject = 'mock selected object';
 | 
			
		||||
                mockScope.ngModel.selectedObject = {
 | 
			
		||||
                    getCapability: function () {
 | 
			
		||||
                        return {
 | 
			
		||||
                            listen: function () {
 | 
			
		||||
                                return true;
 | 
			
		||||
                            }
 | 
			
		||||
                        };
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                mockObjectService = jasmine.createSpyObj(
 | 
			
		||||
                    "objectService",
 | 
			
		||||
 
 | 
			
		||||
@@ -201,13 +201,15 @@ $shdwItemTreeIcon: 0.6;
 | 
			
		||||
$colorThumbHoverBg: $colorItemTreeHoverBg;
 | 
			
		||||
 | 
			
		||||
// Scrollbar
 | 
			
		||||
$scrollbarTrackSize: 10px;
 | 
			
		||||
$scrollbarTrackShdw: rgba(#000, 0.7) 0 1px 5px;
 | 
			
		||||
$scrollbarTrackColorBg: rgba(#000, 0.4);
 | 
			
		||||
$scrollbarTrackSize: 7px;
 | 
			
		||||
$scrollbarTrackShdw: rgba(#000, 0.5) 0 1px 5px;
 | 
			
		||||
$scrollbarTrackColorBg: transparent; //rgba(#000, 0.4);
 | 
			
		||||
$scrollbarThumbColor: pullForward($colorBodyBg, 10%);
 | 
			
		||||
$scrollbarThumbColorHov: pullForward($scrollbarThumbColor, 2%);
 | 
			
		||||
$scrollbarThumbColorOverlay: pullForward($colorOvrBg, 10%);
 | 
			
		||||
$scrollbarThumbColorOverlayHov: pullForward($scrollbarThumbColorOverlay, 2%);
 | 
			
		||||
$scrollbarThumbColorMenu: pullForward($colorMenuBg, 20%);
 | 
			
		||||
$scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%);
 | 
			
		||||
 | 
			
		||||
// Splitter
 | 
			
		||||
// All splitterD* values MUST both be either odd or even numbers
 | 
			
		||||
@@ -241,6 +243,12 @@ $colorCalCellSelectedBg: $colorItemTreeSelectedBg;
 | 
			
		||||
$colorCalCellSelectedFg: $colorItemTreeSelectedFg;
 | 
			
		||||
$colorCalCellInMonthBg: pushBack($colorMenuBg, 5%);
 | 
			
		||||
 | 
			
		||||
// Palettes
 | 
			
		||||
$colorPaletteFg: pullForward($colorMenuBg, 30%);
 | 
			
		||||
$colorPaletteSelected: #fff;
 | 
			
		||||
$shdwPaletteFg: black 0 0 2px;
 | 
			
		||||
$shdwPaletteSelected: inset 0 0 0 1px #000;
 | 
			
		||||
 | 
			
		||||
// About Screen
 | 
			
		||||
$colorAboutLink: #84b3ff;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -201,13 +201,15 @@ $shdwItemTreeIcon: none;
 | 
			
		||||
$colorThumbHoverBg: $colorItemTreeHoverBg;
 | 
			
		||||
 | 
			
		||||
// Scrollbar
 | 
			
		||||
$scrollbarTrackSize: 10px;
 | 
			
		||||
$scrollbarTrackSize: 7px;
 | 
			
		||||
$scrollbarTrackShdw: rgba(#000, 0.2) 0 1px 2px;
 | 
			
		||||
$scrollbarTrackColorBg: rgba(#000, 0.2);
 | 
			
		||||
$scrollbarThumbColor: darken($colorBodyBg, 50%);
 | 
			
		||||
$scrollbarThumbColorHov: $colorKey;
 | 
			
		||||
$scrollbarThumbColorOverlay: darken($colorOvrBg, 50%);
 | 
			
		||||
$scrollbarThumbColorOverlayHov: $scrollbarThumbColorHov;
 | 
			
		||||
$scrollbarThumbColorMenu: pullForward($colorMenuBg, 10%);
 | 
			
		||||
$scrollbarThumbColorMenuHov: pullForward($scrollbarThumbColorMenu, 2%);
 | 
			
		||||
 | 
			
		||||
// Splitter
 | 
			
		||||
// All splitterD* values MUST both be either odd or even numbers
 | 
			
		||||
@@ -241,6 +243,12 @@ $colorCalCellSelectedBg: $colorItemTreeSelectedBg;
 | 
			
		||||
$colorCalCellSelectedFg: $colorItemTreeSelectedFg;
 | 
			
		||||
$colorCalCellInMonthBg: pullForward($colorMenuBg, 5%);
 | 
			
		||||
 | 
			
		||||
// Palettes
 | 
			
		||||
$colorPaletteFg: pullForward($colorMenuBg, 30%);
 | 
			
		||||
$colorPaletteSelected: #333;
 | 
			
		||||
$shdwPaletteFg: none;
 | 
			
		||||
$shdwPaletteSelected: inset 0 0 0 1px #fff;
 | 
			
		||||
 | 
			
		||||
// About Screen
 | 
			
		||||
$colorAboutLink: #84b3ff;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -94,31 +94,6 @@ define([
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        "extensions": {
 | 
			
		||||
            "versions": [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Version",
 | 
			
		||||
                    "value": "@@version",
 | 
			
		||||
                    "priority": 999
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Built",
 | 
			
		||||
                    "value": "@@timestamp",
 | 
			
		||||
                    "description": "The date on which this version of the client was built.",
 | 
			
		||||
                    "priority": 990
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Revision",
 | 
			
		||||
                    "value": "@@revision",
 | 
			
		||||
                    "description": "A unique revision identifier for the client sources.",
 | 
			
		||||
                    "priority": 995
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "Branch",
 | 
			
		||||
                    "value": "@@branch",
 | 
			
		||||
                    "description": "The name of the branch that was used during the build.",
 | 
			
		||||
                    "priority": 994
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "components": [
 | 
			
		||||
                {
 | 
			
		||||
                    "provides": "objectService",
 | 
			
		||||
 
 | 
			
		||||
@@ -23,10 +23,13 @@
 | 
			
		||||
define([
 | 
			
		||||
    "moment-timezone",
 | 
			
		||||
    "./src/indicators/ClockIndicator",
 | 
			
		||||
    "./src/indicators/FollowIndicator",
 | 
			
		||||
    "./src/services/TickerService",
 | 
			
		||||
    "./src/services/TimerService",
 | 
			
		||||
    "./src/controllers/ClockController",
 | 
			
		||||
    "./src/controllers/TimerController",
 | 
			
		||||
    "./src/controllers/RefreshingController",
 | 
			
		||||
    "./src/actions/FollowTimerAction",
 | 
			
		||||
    "./src/actions/StartTimerAction",
 | 
			
		||||
    "./src/actions/RestartTimerAction",
 | 
			
		||||
    "./src/actions/StopTimerAction",
 | 
			
		||||
@@ -37,10 +40,13 @@ define([
 | 
			
		||||
], function (
 | 
			
		||||
    MomentTimezone,
 | 
			
		||||
    ClockIndicator,
 | 
			
		||||
    FollowIndicator,
 | 
			
		||||
    TickerService,
 | 
			
		||||
    TimerService,
 | 
			
		||||
    ClockController,
 | 
			
		||||
    TimerController,
 | 
			
		||||
    RefreshingController,
 | 
			
		||||
    FollowTimerAction,
 | 
			
		||||
    StartTimerAction,
 | 
			
		||||
    RestartTimerAction,
 | 
			
		||||
    StopTimerAction,
 | 
			
		||||
@@ -80,6 +86,11 @@ define([
 | 
			
		||||
                        "CLOCK_INDICATOR_FORMAT"
 | 
			
		||||
                    ],
 | 
			
		||||
                    "priority": "preferred"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "implementation": FollowIndicator,
 | 
			
		||||
                    "depends": ["timerService"],
 | 
			
		||||
                    "priority": "fallback"
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "services": [
 | 
			
		||||
@@ -90,6 +101,11 @@ define([
 | 
			
		||||
                        "$timeout",
 | 
			
		||||
                        "now"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "timerService",
 | 
			
		||||
                    "implementation": TimerService,
 | 
			
		||||
                    "depends": ["openmct"]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "controllers": [
 | 
			
		||||
@@ -134,6 +150,15 @@ define([
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            "actions": [
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "timer.follow",
 | 
			
		||||
                    "implementation": FollowTimerAction,
 | 
			
		||||
                    "depends": ["timerService"],
 | 
			
		||||
                    "category": "contextual",
 | 
			
		||||
                    "name": "Follow Timer",
 | 
			
		||||
                    "cssClass": "icon-clock",
 | 
			
		||||
                    "priority": "optional"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "timer.start",
 | 
			
		||||
                    "implementation": StartTimerAction,
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										54
									
								
								platform/features/clock/src/actions/FollowTimerAction.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								platform/features/clock/src/actions/FollowTimerAction.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,54 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2009-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Designates a specific timer for following. Timelines, for example,
 | 
			
		||||
         * use the actively followed timer to display a time-of-interest line
 | 
			
		||||
         * and interpret time conductor bounds in the Timeline's relative
 | 
			
		||||
         * time frame.
 | 
			
		||||
         *
 | 
			
		||||
         * @implements {Action}
 | 
			
		||||
         * @memberof platform/features/clock
 | 
			
		||||
         * @constructor
 | 
			
		||||
         * @param {ActionContext} context the context for this action
 | 
			
		||||
         */
 | 
			
		||||
        function FollowTimerAction(timerService, context) {
 | 
			
		||||
            var domainObject = context.domainObject;
 | 
			
		||||
            this.perform =
 | 
			
		||||
                timerService.setTimer.bind(timerService, domainObject);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        FollowTimerAction.appliesTo = function (context) {
 | 
			
		||||
            var model =
 | 
			
		||||
                (context.domainObject && context.domainObject.getModel()) ||
 | 
			
		||||
                {};
 | 
			
		||||
 | 
			
		||||
            return model.type === 'timer';
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return FollowTimerAction;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										57
									
								
								platform/features/clock/src/indicators/FollowIndicator.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								platform/features/clock/src/indicators/FollowIndicator.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,57 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2009-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(
 | 
			
		||||
    ['moment'],
 | 
			
		||||
    function (moment) {
 | 
			
		||||
        var NO_TIMER = "No timer being followed";
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Indicator that displays the active timer, as well as its
 | 
			
		||||
         * current state.
 | 
			
		||||
         * @implements {Indicator}
 | 
			
		||||
         * @memberof platform/features/clock
 | 
			
		||||
         */
 | 
			
		||||
        function FollowIndicator(timerService) {
 | 
			
		||||
            this.timerService = timerService;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        FollowIndicator.prototype.getGlyphClass = function () {
 | 
			
		||||
            return "";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        FollowIndicator.prototype.getCssClass = function () {
 | 
			
		||||
            return (this.timerService.getTimer()) ? "icon-timer s-status-ok" : "icon-timer";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        FollowIndicator.prototype.getText = function () {
 | 
			
		||||
            var timer = this.timerService.getTimer();
 | 
			
		||||
            return (timer) ? 'Following timer ' + timer.getModel().name : NO_TIMER;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        FollowIndicator.prototype.getDescription = function () {
 | 
			
		||||
            return "";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return FollowIndicator;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										102
									
								
								platform/features/clock/src/services/TimerService.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										102
									
								
								platform/features/clock/src/services/TimerService.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,102 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2009-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(['EventEmitter'], function (EventEmitter) {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Tracks the currently-followed Timer object. Used by
 | 
			
		||||
     * timelines et al to synchronize to a particular timer.
 | 
			
		||||
     *
 | 
			
		||||
     * The TimerService emits `change` events when the active timer
 | 
			
		||||
     * is changed.
 | 
			
		||||
     */
 | 
			
		||||
    function TimerService(openmct) {
 | 
			
		||||
        EventEmitter.apply(this);
 | 
			
		||||
        this.time = openmct.time;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    TimerService.prototype = Object.create(EventEmitter.prototype);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Set (or clear, if `timer` is undefined) the currently active timer.
 | 
			
		||||
     * @param {DomainObject} timer the new active timer
 | 
			
		||||
     * @emits change
 | 
			
		||||
     */
 | 
			
		||||
    TimerService.prototype.setTimer = function (timer) {
 | 
			
		||||
        this.timer = timer;
 | 
			
		||||
        this.emit('change');
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the currently active timer.
 | 
			
		||||
     * @return {DomainObject} the active timer
 | 
			
		||||
     * @emits change
 | 
			
		||||
     */
 | 
			
		||||
    TimerService.prototype.getTimer = function () {
 | 
			
		||||
        return this.timer;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if there is a currently active timer.
 | 
			
		||||
     * @return {boolean} true if there is a timer
 | 
			
		||||
     */
 | 
			
		||||
    TimerService.prototype.hasTimer = function () {
 | 
			
		||||
        return !!this.timer;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Convert the provided timestamp to milliseconds relative to
 | 
			
		||||
     * the active timer.
 | 
			
		||||
     * @return {number} milliseconds since timer start
 | 
			
		||||
     */
 | 
			
		||||
    TimerService.prototype.convert = function (timestamp) {
 | 
			
		||||
        var clock = this.time.clock();
 | 
			
		||||
        var canConvert = this.hasTimer() &&
 | 
			
		||||
            !!clock &&
 | 
			
		||||
            this.timer.getModel().timerState !== 'stopped';
 | 
			
		||||
 | 
			
		||||
        if (!canConvert) {
 | 
			
		||||
            return undefined;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        var now = clock.currentValue();
 | 
			
		||||
        var model = this.timer.getModel();
 | 
			
		||||
        var delta = model.timerState === 'paused' ? now - model.pausedTime : 0;
 | 
			
		||||
        var epoch = model.timestamp;
 | 
			
		||||
 | 
			
		||||
        return timestamp - epoch - delta;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the value of the active clock, adjusted to be relative to the active
 | 
			
		||||
     * timer. If there is no clock or no active timer, this will return
 | 
			
		||||
     * `undefined`.
 | 
			
		||||
     * @return {number} milliseconds since the start of the active timer
 | 
			
		||||
     */
 | 
			
		||||
    TimerService.prototype.now = function () {
 | 
			
		||||
        var clock = this.time.clock();
 | 
			
		||||
        return clock && this.convert(clock.currentValue());
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return TimerService;
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,80 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2009-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    "../../src/actions/FollowTimerAction"
 | 
			
		||||
], function (FollowTimerAction) {
 | 
			
		||||
    var TIMER_SERVICE_METHODS =
 | 
			
		||||
        ['setTimer', 'getTimer', 'clearTimer', 'on', 'off'];
 | 
			
		||||
 | 
			
		||||
    describe("The Follow Timer action", function () {
 | 
			
		||||
        var testContext;
 | 
			
		||||
        var testModel;
 | 
			
		||||
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            testModel = {};
 | 
			
		||||
            testContext = { domainObject: { getModel: function () {
 | 
			
		||||
                return testModel;
 | 
			
		||||
            } } };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("is applicable to timers", function () {
 | 
			
		||||
            testModel.type = "timer";
 | 
			
		||||
            expect(FollowTimerAction.appliesTo(testContext)).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("is inapplicable to non-timers", function () {
 | 
			
		||||
            testModel.type = "folder";
 | 
			
		||||
            expect(FollowTimerAction.appliesTo(testContext)).toBe(false);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe("when instantiated", function () {
 | 
			
		||||
            var mockTimerService;
 | 
			
		||||
            var action;
 | 
			
		||||
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                mockTimerService = jasmine.createSpyObj(
 | 
			
		||||
                    'timerService',
 | 
			
		||||
                    TIMER_SERVICE_METHODS
 | 
			
		||||
                );
 | 
			
		||||
                action = new FollowTimerAction(mockTimerService, testContext);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("does not interact with the timer service", function () {
 | 
			
		||||
                TIMER_SERVICE_METHODS.forEach(function (method) {
 | 
			
		||||
                    expect(mockTimerService[method]).not.toHaveBeenCalled();
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            describe("and performed", function () {
 | 
			
		||||
                beforeEach(function () {
 | 
			
		||||
                    action.perform();
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                it("sets the active timer", function () {
 | 
			
		||||
                    expect(mockTimerService.setTimer)
 | 
			
		||||
                        .toHaveBeenCalledWith(testContext.domainObject);
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -0,0 +1,61 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2009-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(["../../src/indicators/FollowIndicator"], function (FollowIndicator) {
 | 
			
		||||
    var TIMER_SERVICE_METHODS =
 | 
			
		||||
        ['setTimer', 'getTimer', 'clearTimer', 'on', 'off'];
 | 
			
		||||
 | 
			
		||||
    describe("The timer-following indicator", function () {
 | 
			
		||||
        var mockTimerService;
 | 
			
		||||
        var indicator;
 | 
			
		||||
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            mockTimerService =
 | 
			
		||||
                jasmine.createSpyObj('timerService', TIMER_SERVICE_METHODS);
 | 
			
		||||
            indicator = new FollowIndicator(mockTimerService);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("implements the Indicator interface", function () {
 | 
			
		||||
            expect(indicator.getGlyphClass()).toEqual(jasmine.any(String));
 | 
			
		||||
            expect(indicator.getCssClass()).toEqual(jasmine.any(String));
 | 
			
		||||
            expect(indicator.getText()).toEqual(jasmine.any(String));
 | 
			
		||||
            expect(indicator.getDescription()).toEqual(jasmine.any(String));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe("when a timer is set", function () {
 | 
			
		||||
            var testModel;
 | 
			
		||||
            var mockDomainObject;
 | 
			
		||||
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                testModel = { name: "some timer!" };
 | 
			
		||||
                mockDomainObject = jasmine.createSpyObj('timer', ['getModel']);
 | 
			
		||||
                mockDomainObject.getModel.andReturn(testModel);
 | 
			
		||||
                mockTimerService.getTimer.andReturn(mockDomainObject);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("displays the timer's name", function () {
 | 
			
		||||
                expect(indicator.getText().indexOf(testModel.name))
 | 
			
		||||
                    .not.toEqual(-1);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										63
									
								
								platform/features/clock/test/services/TimerServiceSpec.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								platform/features/clock/test/services/TimerServiceSpec.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,63 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2009-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    '../../src/services/TimerService'
 | 
			
		||||
], function (TimerService) {
 | 
			
		||||
    describe("TimerService", function () {
 | 
			
		||||
        var callback;
 | 
			
		||||
        var mockmct;
 | 
			
		||||
        var timerService;
 | 
			
		||||
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            callback = jasmine.createSpy('callback');
 | 
			
		||||
            mockmct = { time: { clock: jasmine.createSpy('clock') } };
 | 
			
		||||
            timerService = new TimerService(mockmct);
 | 
			
		||||
            timerService.on('change', callback);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("initially emits no change events", function () {
 | 
			
		||||
            expect(callback).not.toHaveBeenCalled();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("reports no current timer", function () {
 | 
			
		||||
            expect(timerService.getTimer()).toBeUndefined();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe("setTimer", function () {
 | 
			
		||||
            var testTimer;
 | 
			
		||||
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                testTimer = { name: "I am some timer; you are nobody." };
 | 
			
		||||
                timerService.setTimer(testTimer);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("emits a change event", function () {
 | 
			
		||||
                expect(callback).toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("reports the current timer", function () {
 | 
			
		||||
                expect(timerService.getTimer()).toBe(testTimer);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
$ueTimeConductorH: (25px, 16px, 20px); // Heights for Ticks, Data Visualization, Controls elements
 | 
			
		||||
$ueTimeConductorRtH: (25px, 3px, 20px); // Heights for elements in Real-time mode
 | 
			
		||||
$timeCondInputTimeSysDefW: 165px; // Default width for datetime value inputs
 | 
			
		||||
$timeCondInputDeltaDefW: 60px; // Default width for delta value inputs, typically 00:00:00
 | 
			
		||||
$timeCondInputDeltaDefW: 65px; // Default width for delta value inputs, typically 00:00:00
 | 
			
		||||
$timeCondTOIIconD: 12px; // height and width of icon used for TOI indicator
 | 
			
		||||
$timeCondTOIValOffset: 0px;
 | 
			
		||||
$ticksBlockerFadeW: 50px;
 | 
			
		||||
 
 | 
			
		||||
@@ -162,9 +162,6 @@
 | 
			
		||||
            .l-time-conductor-inputs {
 | 
			
		||||
                pointer-events: auto;
 | 
			
		||||
            }
 | 
			
		||||
            input[type="text"] {
 | 
			
		||||
                @include trans-prop-nice(padding, 250ms);
 | 
			
		||||
            }
 | 
			
		||||
            .time-range-input input[type="text"] {
 | 
			
		||||
                width: $timeCondInputTimeSysDefW;
 | 
			
		||||
            }
 | 
			
		||||
@@ -290,18 +287,6 @@
 | 
			
		||||
 | 
			
		||||
        .l-time-conductor-inputs-holder {
 | 
			
		||||
            .l-time-range-input-w {
 | 
			
		||||
                input[type="text"]:not(.error) {
 | 
			
		||||
                    background: transparent;
 | 
			
		||||
                    box-shadow: none;
 | 
			
		||||
                    border-radius: 0;
 | 
			
		||||
                    padding-left: 0;
 | 
			
		||||
                    padding-right: 0;
 | 
			
		||||
                    &:hover,
 | 
			
		||||
                    &:focus {
 | 
			
		||||
                        @include nice-input();
 | 
			
		||||
                        padding: $inputTextP;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                .icon-calendar {
 | 
			
		||||
                    display: none;
 | 
			
		||||
                }
 | 
			
		||||
@@ -309,8 +294,11 @@
 | 
			
		||||
                    display: none;
 | 
			
		||||
                }
 | 
			
		||||
                &.end-date {
 | 
			
		||||
                    // Displays the current time
 | 
			
		||||
                    pointer-events: none;
 | 
			
		||||
                    input[type="text"] {
 | 
			
		||||
                        background: none;
 | 
			
		||||
                        box-shadow: none;
 | 
			
		||||
                        color: pullForward($colorTimeCondKeyBg, 5%);
 | 
			
		||||
                        margin-right: $interiorMargin;
 | 
			
		||||
                        tab-index: -1;
 | 
			
		||||
 
 | 
			
		||||
@@ -19,8 +19,8 @@
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<div class="contents">
 | 
			
		||||
    <div class="pane left menu-items">
 | 
			
		||||
<div class="w-menu">
 | 
			
		||||
    <div class="col menu-items">
 | 
			
		||||
        <ul>
 | 
			
		||||
            <li ng-repeat="metadata in ngModel.options"
 | 
			
		||||
                ng-click="ngModel.select(metadata)">
 | 
			
		||||
@@ -32,13 +32,15 @@
 | 
			
		||||
            </li>
 | 
			
		||||
        </ul>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="pane right menu-item-description">
 | 
			
		||||
    <div class="col menu-item-description">
 | 
			
		||||
        <div class="desc-area ui-symbol icon type-icon {{ngModel.activeMetadata.cssClass}}"></div>
 | 
			
		||||
        <div class="desc-area title">
 | 
			
		||||
            {{ngModel.activeMetadata.name}}
 | 
			
		||||
        </div>
 | 
			
		||||
        <div class="desc-area description">
 | 
			
		||||
            {{ngModel.activeMetadata.description}}
 | 
			
		||||
        <div class="w-title-desc">
 | 
			
		||||
            <div class="desc-area title">
 | 
			
		||||
                {{ngModel.activeMetadata.name}}
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="desc-area description">
 | 
			
		||||
                {{ngModel.activeMetadata.description}}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@
 | 
			
		||||
         ng-click="modeController.toggle()">
 | 
			
		||||
		<span class="title-label">{{ngModel.selected.name}}</span>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="menu super-menu mini mode-selector-menu"
 | 
			
		||||
    <div class="menu super-menu mini l-mode-selector-menu"
 | 
			
		||||
         ng-show="modeController.isActive()">
 | 
			
		||||
        <mct-include key="'mode-menu'"
 | 
			
		||||
                     ng-model="ngModel">
 | 
			
		||||
 
 | 
			
		||||
@@ -38,7 +38,7 @@
 | 
			
		||||
                                         ng-model="boundsModel"
 | 
			
		||||
                                         ng-blur="tcController.setOffsetsFromView(boundsModel)"
 | 
			
		||||
                                         field="'startOffset'"
 | 
			
		||||
                                         class="hrs-min-input">
 | 
			
		||||
                                         class="s-input-inline hrs-min-input">
 | 
			
		||||
                            </mct-control>
 | 
			
		||||
                        </span>
 | 
			
		||||
                    </span>
 | 
			
		||||
@@ -71,7 +71,7 @@
 | 
			
		||||
                                         ng-model="boundsModel"
 | 
			
		||||
                                         ng-blur="tcController.setOffsetsFromView(boundsModel)"
 | 
			
		||||
                                         field="'endOffset'"
 | 
			
		||||
                                         class="hrs-min-input">
 | 
			
		||||
                                         class="s-input-inline hrs-min-input">
 | 
			
		||||
                            </mct-control>
 | 
			
		||||
                        </span>
 | 
			
		||||
                    </span>
 | 
			
		||||
 
 | 
			
		||||
@@ -201,7 +201,7 @@ define(
 | 
			
		||||
            var options = [{
 | 
			
		||||
                key: 'fixed',
 | 
			
		||||
                name: 'Fixed Timespan Mode',
 | 
			
		||||
                description: 'Query and explore data that falls between two fixed datetimes',
 | 
			
		||||
                description: 'Query and explore data that falls between two fixed datetimes.',
 | 
			
		||||
                cssClass: 'icon-calendar'
 | 
			
		||||
            }];
 | 
			
		||||
            var clocks = {};
 | 
			
		||||
 
 | 
			
		||||
@@ -19,11 +19,11 @@
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<div class="frame frame-template t-frame-inner abs t-object-type-{{ representation.selected.key }}">
 | 
			
		||||
<div class="frame frame-template t-frame-inner abs t-object-type-{{ domainObject.getModel().type }}">
 | 
			
		||||
    <div class="abs object-browse-bar l-flex-row">
 | 
			
		||||
        <div class="left flex-elem l-flex-row grows">
 | 
			
		||||
            <mct-representation
 | 
			
		||||
                    key="'object-header'"
 | 
			
		||||
                    key="'object-header-frame'"
 | 
			
		||||
                    mct-object="domainObject"
 | 
			
		||||
                    class="l-flex-row flex-elem object-header grows">
 | 
			
		||||
            </mct-representation>
 | 
			
		||||
 
 | 
			
		||||
@@ -24,7 +24,7 @@ define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        var DIGITS = 3;
 | 
			
		||||
        var DIGITS = 2;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Wraps a `TelemetryFormatter` to provide formats for domain and
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,13 @@ define(
 | 
			
		||||
 | 
			
		||||
        PlotViewPolicy.prototype.hasNumericTelemetry = function (domainObject) {
 | 
			
		||||
            var adaptedObject = domainObject.useCapability('adapter');
 | 
			
		||||
 | 
			
		||||
            if (!adaptedObject.telemetry) {
 | 
			
		||||
                return domainObject.hasCapability('delegation') &&
 | 
			
		||||
                    domainObject.getCapability('delegation')
 | 
			
		||||
                            .doesDelegateCapability('telemetry');
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            var metadata = this.openmct.telemetry.getMetadata(adaptedObject);
 | 
			
		||||
            var rangeValues = metadata.valuesForHints(['range']);
 | 
			
		||||
            if (rangeValues.length === 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -27,17 +27,19 @@ define(
 | 
			
		||||
        describe("Plot view policy", function () {
 | 
			
		||||
            var testView,
 | 
			
		||||
                mockDomainObject,
 | 
			
		||||
                testAdaptedObject,
 | 
			
		||||
                openmct,
 | 
			
		||||
                telemetryMetadata,
 | 
			
		||||
                policy;
 | 
			
		||||
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                testView = { key: "plot" };
 | 
			
		||||
                testAdaptedObject = { telemetry: {} };
 | 
			
		||||
                mockDomainObject = jasmine.createSpyObj(
 | 
			
		||||
                    'domainObject',
 | 
			
		||||
                    ['useCapability']
 | 
			
		||||
                    ['useCapability', 'hasCapability', 'getCapability']
 | 
			
		||||
                );
 | 
			
		||||
                mockDomainObject.useCapability.andReturn('adaptedObject');
 | 
			
		||||
                mockDomainObject.useCapability.andReturn(testAdaptedObject);
 | 
			
		||||
                openmct = {
 | 
			
		||||
                    telemetry: jasmine.createSpyObj('telemetryAPI', [
 | 
			
		||||
                        'getMetadata'
 | 
			
		||||
@@ -56,7 +58,7 @@ define(
 | 
			
		||||
                expect(mockDomainObject.useCapability)
 | 
			
		||||
                    .toHaveBeenCalledWith('adapter');
 | 
			
		||||
                expect(openmct.telemetry.getMetadata)
 | 
			
		||||
                    .toHaveBeenCalledWith('adaptedObject');
 | 
			
		||||
                    .toHaveBeenCalledWith(testAdaptedObject);
 | 
			
		||||
                expect(telemetryMetadata.valuesForHints)
 | 
			
		||||
                    .toHaveBeenCalledWith(['range']);
 | 
			
		||||
            });
 | 
			
		||||
@@ -87,6 +89,30 @@ define(
 | 
			
		||||
                expect(policy.allow(testView, mockDomainObject)).toBe(true);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('returns true for telemetry delegators', function () {
 | 
			
		||||
                delete testAdaptedObject.telemetry;
 | 
			
		||||
                mockDomainObject.hasCapability.andCallFake(function (c) {
 | 
			
		||||
                    return c === 'delegation';
 | 
			
		||||
                });
 | 
			
		||||
                mockDomainObject.getCapability.andReturn(
 | 
			
		||||
                    jasmine.createSpyObj('delegation', [
 | 
			
		||||
                        'doesDelegateCapability'
 | 
			
		||||
                    ])
 | 
			
		||||
                );
 | 
			
		||||
                mockDomainObject.getCapability('delegation')
 | 
			
		||||
                    .doesDelegateCapability.andCallFake(function (c) {
 | 
			
		||||
                        return c === 'telemetry';
 | 
			
		||||
                    });
 | 
			
		||||
                expect(policy.allow(testView, mockDomainObject)).toBe(true);
 | 
			
		||||
                expect(openmct.telemetry.getMetadata).not.toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('returns true for non-telemetry non-delegators', function () {
 | 
			
		||||
                delete testAdaptedObject.telemetry;
 | 
			
		||||
                mockDomainObject.hasCapability.andReturn(false);
 | 
			
		||||
                expect(policy.allow(testView, mockDomainObject)).toBe(false);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("allows other views", function () {
 | 
			
		||||
                testView.key = "somethingElse";
 | 
			
		||||
                expect(policy.allow(testView, mockDomainObject)).toBe(true);
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,7 @@ define([
 | 
			
		||||
    "./src/controllers/TimelineTickController",
 | 
			
		||||
    "./src/controllers/TimelineTableController",
 | 
			
		||||
    "./src/controllers/TimelineGanttController",
 | 
			
		||||
    "./src/controllers/TimelineTOIController",
 | 
			
		||||
    "./src/controllers/ActivityModeValuesController",
 | 
			
		||||
    "./src/capabilities/ActivityTimespanCapability",
 | 
			
		||||
    "./src/capabilities/TimelineTimespanCapability",
 | 
			
		||||
@@ -59,6 +60,7 @@ define([
 | 
			
		||||
    TimelineTickController,
 | 
			
		||||
    TimelineTableController,
 | 
			
		||||
    TimelineGanttController,
 | 
			
		||||
    TimelineTOIController,
 | 
			
		||||
    ActivityModeValuesController,
 | 
			
		||||
    ActivityTimespanCapability,
 | 
			
		||||
    TimelineTimespanCapability,
 | 
			
		||||
@@ -502,6 +504,15 @@ define([
 | 
			
		||||
                        "TIMELINE_MAXIMUM_OFFSCREEN"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "TimelineTOIController",
 | 
			
		||||
                    "implementation": TimelineTOIController,
 | 
			
		||||
                    "depends": [
 | 
			
		||||
                        "openmct",
 | 
			
		||||
                        "timerService",
 | 
			
		||||
                        "$scope"
 | 
			
		||||
                    ]
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "ActivityModeValuesController",
 | 
			
		||||
                    "implementation": ActivityModeValuesController,
 | 
			
		||||
 
 | 
			
		||||
@@ -29,6 +29,44 @@
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Follow Line
 | 
			
		||||
    .l-follow-line {
 | 
			
		||||
        // TODO: move before and after into l-timeline-gantt so those only render in that pane
 | 
			
		||||
        pointer-events: none;
 | 
			
		||||
        position: absolute;
 | 
			
		||||
        top: 0; bottom: 0;
 | 
			
		||||
        width: 1px;
 | 
			
		||||
        z-index: 9; // Just below .l-hover-btns-holder
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.l-timeline-gantt {
 | 
			
		||||
    .l-follow-line {
 | 
			
		||||
        $d: 0.8rem;
 | 
			
		||||
        top: $interiorMargin;
 | 
			
		||||
        &:before,
 | 
			
		||||
        &:after {
 | 
			
		||||
            content: '';
 | 
			
		||||
            display: block;
 | 
			
		||||
            height: $d;
 | 
			
		||||
            width: $d;
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            top: 0;
 | 
			
		||||
            @include transform(translateX(-50%));
 | 
			
		||||
        }
 | 
			
		||||
        &:before {
 | 
			
		||||
            // Icon blocker
 | 
			
		||||
            width: 2 * $d;
 | 
			
		||||
        }
 | 
			
		||||
        &:after {
 | 
			
		||||
            // Icon
 | 
			
		||||
            font-size: $d;
 | 
			
		||||
            line-height: $d;
 | 
			
		||||
            text-align: center;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.s-timeline-gantt {
 | 
			
		||||
@@ -108,10 +146,9 @@
 | 
			
		||||
    }
 | 
			
		||||
    .s-hover-btns-holder {
 | 
			
		||||
        $bg: $timelineHeaderColorBg;
 | 
			
		||||
        $bga: 1;
 | 
			
		||||
        $l: 5%;
 | 
			
		||||
        @include user-select(none);
 | 
			
		||||
        @include background-image(linear-gradient(-90deg, rgba($bg, $bga), rgba($bg, $bga) 70%, rgba($bg, 0) 100%));
 | 
			
		||||
        @include background-image(linear-gradient(-90deg, rgba($bg, 1), rgba($bg, 1) 70%, rgba($bg, 0) 100%));
 | 
			
		||||
        .s-button {
 | 
			
		||||
            height: 16px;
 | 
			
		||||
            line-height: 16px;
 | 
			
		||||
@@ -129,4 +166,27 @@
 | 
			
		||||
            color: $timelineResourceGraphFg;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .s-follow-line {
 | 
			
		||||
        background: rgba($timeControllerToiLineColor, 0.5);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .s-timeline-gantt {
 | 
			
		||||
        .s-follow-line {
 | 
			
		||||
            &:after {
 | 
			
		||||
                // Icon
 | 
			
		||||
                color: $timeControllerToiLineColor;
 | 
			
		||||
                content: $glyph-icon-timer;
 | 
			
		||||
                font-family: symbolsfont;
 | 
			
		||||
                text-shadow: $shdwItemText;
 | 
			
		||||
            }
 | 
			
		||||
            &:before {
 | 
			
		||||
                // Blocker
 | 
			
		||||
                $bg: $timelineHeaderColorBg;
 | 
			
		||||
                $l: 30%;
 | 
			
		||||
                @include background-image(linear-gradient(90deg, rgba($bg, 0), rgba($bg, 1) $l, rgba($bg, 1) 100% - $l, rgba($bg, 0)));
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -75,6 +75,10 @@
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            &.l-timeline-gantt {
 | 
			
		||||
                .abs.l-timeline-gantt-header-w {
 | 
			
		||||
                    overflow: hidden;
 | 
			
		||||
                    height: $timelineTopPaneHeaderH;
 | 
			
		||||
                }
 | 
			
		||||
                .l-swimlanes-holder {
 | 
			
		||||
                    @include scrollV(scroll);
 | 
			
		||||
                    bottom: $scrollbarTrackSize;
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ $output-bourbon-deprecation-warnings: false;
 | 
			
		||||
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/mixins";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/glyphs";
 | 
			
		||||
@import "../../../../commonUI/themes/espresso/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/themes/espresso/res/sass/mixins";
 | 
			
		||||
@import "constants";
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ $output-bourbon-deprecation-warnings: false;
 | 
			
		||||
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/mixins";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/glyphs";
 | 
			
		||||
@import "../../../../commonUI/themes/snow/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/themes/snow/res/sass/mixins";
 | 
			
		||||
@import "constants";
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ $output-bourbon-deprecation-warnings: false;
 | 
			
		||||
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/mixins";
 | 
			
		||||
@import "../../../../commonUI/general/res/sass/glyphs";
 | 
			
		||||
@import "../../../../commonUI/themes/espresso/res/sass/constants";
 | 
			
		||||
@import "../../../../commonUI/themes/espresso/res/sass/mixins";
 | 
			
		||||
@import "constants";
 | 
			
		||||
 
 | 
			
		||||
@@ -96,109 +96,124 @@
 | 
			
		||||
 | 
			
		||||
    <!-- RIGHT PANE: GANTT AND RESOURCE PLOTS -->
 | 
			
		||||
    <span ng-controller="TimelineZoomController as zoomController" class="abs">
 | 
			
		||||
    <mct-split-pane anchor="bottom"
 | 
			
		||||
 | 
			
		||||
        <span class="toi-control-holder temp" ng-controller="TimelineTOIController as toiController">
 | 
			
		||||
            <mct-split-pane anchor="bottom"
 | 
			
		||||
                    position="pane.y"
 | 
			
		||||
                    class="abs split-pane-component l-timeline-pane l-pane-r t-pane-v">
 | 
			
		||||
 | 
			
		||||
        <!-- TOP PANE GANTT BARS -->
 | 
			
		||||
        <div class="split-pane-component l-timeline-pane t-pane-h l-pane-top t-timeline-gantt l-timeline-gantt s-timeline-gantt">
 | 
			
		||||
            <div class="l-hover-btns-holder s-hover-btns-holder">
 | 
			
		||||
                <a class="s-button icon-arrows-out"
 | 
			
		||||
                   ng-click="zoomController.fit()"
 | 
			
		||||
                   ng-show="true"
 | 
			
		||||
                   title="Zoom to fit">
 | 
			
		||||
                </a>
 | 
			
		||||
                <!-- TOP PANE GANTT BARS -->
 | 
			
		||||
                <div class="split-pane-component l-timeline-pane t-pane-h l-pane-top t-timeline-gantt l-timeline-gantt s-timeline-gantt">
 | 
			
		||||
                    <div class="l-hover-btns-holder s-hover-btns-holder">
 | 
			
		||||
                        <a class="s-button icon-timer"
 | 
			
		||||
                           ng-click="scroll.follow = true"
 | 
			
		||||
                           ng-show="!toiController.isFollowing() && toiController.isActive()"
 | 
			
		||||
                           title="Follow time bounds">
 | 
			
		||||
                        </a>
 | 
			
		||||
 | 
			
		||||
                <a class="s-button icon-magnify-in"
 | 
			
		||||
                   ng-click="zoomController.zoom(-1)"
 | 
			
		||||
                   ng-show="true"
 | 
			
		||||
                   title="Zoom in">
 | 
			
		||||
                </a>
 | 
			
		||||
                        <a class="s-button icon-arrows-out"
 | 
			
		||||
                           ng-click="scroll.follow = false; zoomController.fit()"
 | 
			
		||||
                           ng-show="true"
 | 
			
		||||
                           title="Zoom to fit">
 | 
			
		||||
                        </a>
 | 
			
		||||
 | 
			
		||||
                <a class="s-button icon-magnify-out"
 | 
			
		||||
                   ng-click="zoomController.zoom(1)"
 | 
			
		||||
                   ng-show="true"
 | 
			
		||||
                   title="Zoom out">
 | 
			
		||||
                </a>
 | 
			
		||||
            </div>
 | 
			
		||||
                        <a class="s-button icon-magnify-in"
 | 
			
		||||
                           ng-click="scroll.follow = false; zoomController.zoom(-1)"
 | 
			
		||||
                           ng-show="true"
 | 
			
		||||
                           title="Zoom in">
 | 
			
		||||
                        </a>
 | 
			
		||||
 | 
			
		||||
            <div style="overflow: hidden; position: absolute; left: 0; top: 0; right: 0; height: 30px;" mct-scroll-x="scroll.x">
 | 
			
		||||
                <mct-include key="'timeline-ticks'"
 | 
			
		||||
                             parameters="{
 | 
			
		||||
                                         fullWidth: zoomController.width(timelineController.end()),
 | 
			
		||||
                                         start: scroll.x,
 | 
			
		||||
                                         width: scroll.width,
 | 
			
		||||
                                         step: zoomController.toPixels(zoomController.zoom()),
 | 
			
		||||
                                         toMillis: zoomController.toMillis
 | 
			
		||||
                                         }">
 | 
			
		||||
                </mct-include>
 | 
			
		||||
            </div>
 | 
			
		||||
                        <a class="s-button icon-magnify-out"
 | 
			
		||||
                           ng-click="scroll.follow = false; zoomController.zoom(1)"
 | 
			
		||||
                           ng-show="true"
 | 
			
		||||
                           title="Zoom out">
 | 
			
		||||
                        </a>
 | 
			
		||||
                    </div>
 | 
			
		||||
 | 
			
		||||
            <div class="t-swimlanes-holder l-swimlanes-holder"
 | 
			
		||||
                 mct-scroll-x="scroll.x"
 | 
			
		||||
                 mct-scroll-y="scroll.y">
 | 
			
		||||
                <div class="l-width-control"
 | 
			
		||||
                     ng-style="{ width: zoomController.width(timelineController.end()) + 'px' }">
 | 
			
		||||
                    <div class="t-swimlane s-swimlane l-swimlane"
 | 
			
		||||
                         ng-repeat="swimlane in timelineController.swimlanes()"
 | 
			
		||||
                         ng-class="{
 | 
			
		||||
                                   exceeded: swimlane.exceeded(),
 | 
			
		||||
                                   selected: selection.selected(swimlane),
 | 
			
		||||
                                   'drop-into': swimlane.highlight(),
 | 
			
		||||
                                   'drop-after': swimlane.highlightBottom()
 | 
			
		||||
                                   }"
 | 
			
		||||
                         ng-click="selection.select(swimlane)"
 | 
			
		||||
                         mct-swimlane-drop="swimlane">
 | 
			
		||||
                    <div style="overflow: hidden; position: absolute; left: 0; top: 0; right: 0; height: 30px;" mct-scroll-x="scroll.x">
 | 
			
		||||
                        <mct-include key="'timeline-ticks'"
 | 
			
		||||
                                     parameters="{
 | 
			
		||||
                                                 fullWidth: zoomController.width(timelineController.end()),
 | 
			
		||||
                                                 start: scroll.x,
 | 
			
		||||
                                                 width: scroll.width,
 | 
			
		||||
                                                 step: zoomController.toPixels(zoomController.zoom()),
 | 
			
		||||
                                                 toMillis: zoomController.toMillis
 | 
			
		||||
                                                 }">
 | 
			
		||||
                        </mct-include>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div ng-if="toiController.isActive()" class="l-follow-line s-follow-line"
 | 
			
		||||
                         ng-style="{ left: toiController.x() - scroll.x + 'px' }"></div>
 | 
			
		||||
 | 
			
		||||
                        <mct-representation key="'gantt'"
 | 
			
		||||
                                            mct-object="swimlane.domainObject"
 | 
			
		||||
                                            parameters="{
 | 
			
		||||
                                                        scroll: scroll,
 | 
			
		||||
                                                        toPixels: zoomController.toPixels
 | 
			
		||||
                                                        }">
 | 
			
		||||
                        </mct-representation>
 | 
			
		||||
                    <div class="t-swimlanes-holder l-swimlanes-holder"
 | 
			
		||||
                         mct-scroll-x="scroll.x"
 | 
			
		||||
                         mct-scroll-y="scroll.y">
 | 
			
		||||
                        <div class="l-width-control"
 | 
			
		||||
                             ng-style="{ width: zoomController.width(timelineController.end()) + 'px' }">
 | 
			
		||||
                            <div class="t-swimlane s-swimlane l-swimlane"
 | 
			
		||||
                                 ng-repeat="swimlane in timelineController.swimlanes()"
 | 
			
		||||
                                 ng-class="{
 | 
			
		||||
                                           exceeded: swimlane.exceeded(),
 | 
			
		||||
                                           selected: selection.selected(swimlane),
 | 
			
		||||
                                           'drop-into': swimlane.highlight(),
 | 
			
		||||
                                           'drop-after': swimlane.highlightBottom()
 | 
			
		||||
                                           }"
 | 
			
		||||
                                 ng-click="selection.select(swimlane)"
 | 
			
		||||
                                 mct-swimlane-drop="swimlane">
 | 
			
		||||
 | 
			
		||||
                        <span ng-if="selection.selected(swimlane)">
 | 
			
		||||
                            <span ng-repeat="handle in timelineController.handles()"
 | 
			
		||||
                                  ng-style="handle.style(zoomController)"
 | 
			
		||||
                                  style="position: absolute; top: 0px; bottom: 0px;"
 | 
			
		||||
                                  class="handle"
 | 
			
		||||
                                  ng-class="{ start: $index === 0, mid: $index === 1, end: $index > 1 }"
 | 
			
		||||
                                  mct-drag-down="handle.begin()"
 | 
			
		||||
                                  mct-drag="handle.drag(delta[0], zoomController); timelineController.refresh()"
 | 
			
		||||
                                  mct-drag-up="handle.finish()">
 | 
			
		||||
                            </span>
 | 
			
		||||
                        </span>
 | 
			
		||||
                                <mct-representation key="'gantt'"
 | 
			
		||||
                                                    mct-object="swimlane.domainObject"
 | 
			
		||||
                                                    parameters="{
 | 
			
		||||
                                                                scroll: scroll,
 | 
			
		||||
                                                                toPixels: zoomController.toPixels
 | 
			
		||||
                                                                }">
 | 
			
		||||
                                </mct-representation>
 | 
			
		||||
 | 
			
		||||
                                <span ng-if="selection.selected(swimlane)">
 | 
			
		||||
                                    <span ng-repeat="handle in timelineController.handles()"
 | 
			
		||||
                                          ng-style="handle.style(zoomController)"
 | 
			
		||||
                                          style="position: absolute; top: 0px; bottom: 0px;"
 | 
			
		||||
                                          class="handle"
 | 
			
		||||
                                          ng-class="{ start: $index === 0, mid: $index === 1, end: $index > 1 }"
 | 
			
		||||
                                          mct-drag-down="handle.begin()"
 | 
			
		||||
                                          mct-drag="handle.drag(delta[0], zoomController); timelineController.refresh()"
 | 
			
		||||
                                          mct-drag-up="handle.finish()">
 | 
			
		||||
                                    </span>
 | 
			
		||||
                                </span>
 | 
			
		||||
                            </div>
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <!-- HORZ SPLITTER -->
 | 
			
		||||
        <mct-splitter></mct-splitter>
 | 
			
		||||
                <!-- HORZ SPLITTER -->
 | 
			
		||||
                <mct-splitter></mct-splitter>
 | 
			
		||||
 | 
			
		||||
        <!-- BOTTOM PANE RESOURCE GRAPHS AND RIGHT PANE HORIZONTAL SCROLL CONTROL -->
 | 
			
		||||
        <div class="split-pane-component l-timeline-resource-graph l-timeline-pane t-pane-h l-pane-btm">
 | 
			
		||||
            <div class="l-graphs-holder"
 | 
			
		||||
                 mct-resize="scroll.width = bounds.width">
 | 
			
		||||
                <div class="t-graphs l-graphs">
 | 
			
		||||
                    <mct-include key="'timeline-resource-graphs'"
 | 
			
		||||
                                 parameters="{
 | 
			
		||||
                                             origin: zoomController.toMillis(scroll.x),
 | 
			
		||||
                                             duration: zoomController.toMillis(scroll.width),
 | 
			
		||||
                                             graphs: timelineController.graphs()
 | 
			
		||||
                                             }">
 | 
			
		||||
                    </mct-include>
 | 
			
		||||
                <!-- BOTTOM PANE RESOURCE GRAPHS AND RIGHT PANE HORIZONTAL SCROLL CONTROL -->
 | 
			
		||||
                <div class="split-pane-component l-timeline-resource-graph l-timeline-pane t-pane-h l-pane-btm">
 | 
			
		||||
                    <div class="l-graphs-holder"
 | 
			
		||||
                         mct-resize="scroll.width = bounds.width">
 | 
			
		||||
                        <div class="t-graphs l-graphs">
 | 
			
		||||
                            <mct-include key="'timeline-resource-graphs'"
 | 
			
		||||
                                         parameters="{
 | 
			
		||||
                                                     origin: zoomController.toMillis(scroll.x),
 | 
			
		||||
                                                     duration: zoomController.toMillis(scroll.width),
 | 
			
		||||
                                                     graphs: timelineController.graphs()
 | 
			
		||||
                                                     }">
 | 
			
		||||
                            </mct-include>
 | 
			
		||||
                        </div>
 | 
			
		||||
                        <div ng-if="toiController.isActive()" class="l-follow-line s-follow-line"
 | 
			
		||||
                             ng-style="{ left: toiController.x() - scroll.x + 'px' }"></div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div mct-scroll-x="scroll.x"
 | 
			
		||||
                         class="t-pane-r-scroll-h-control l-scroll-control s-scroll-control">
 | 
			
		||||
                        <div class="l-width-control"
 | 
			
		||||
                             ng-style="{ width: zoomController.width(timelineController.end()) + 'px' }">
 | 
			
		||||
                        </div>
 | 
			
		||||
                    </div>
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div mct-scroll-x="scroll.x"
 | 
			
		||||
                 class="t-pane-r-scroll-h-control l-scroll-control s-scroll-control">
 | 
			
		||||
                <div class="l-width-control"
 | 
			
		||||
                     ng-style="{ width: zoomController.width(timelineController.end()) + 'px' }">
 | 
			
		||||
                </div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </mct-split-pane>
 | 
			
		||||
            </mct-split-pane>
 | 
			
		||||
        </span>
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    </span>
 | 
			
		||||
</mct-split-pane>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,111 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2009-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([], function () {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Tracks time-of-interest in timelines, updating both scroll state
 | 
			
		||||
     * (when appropriate) and positioning of the displayed line.
 | 
			
		||||
     */
 | 
			
		||||
    function TimelineTOIController(openmct, timerService, $scope) {
 | 
			
		||||
        this.openmct = openmct;
 | 
			
		||||
        this.timerService = timerService;
 | 
			
		||||
        this.$scope = $scope;
 | 
			
		||||
 | 
			
		||||
        this.change = this.change.bind(this);
 | 
			
		||||
        this.bounds = this.bounds.bind(this);
 | 
			
		||||
        this.destroy = this.destroy.bind(this);
 | 
			
		||||
 | 
			
		||||
        this.timerService.on('change', this.change);
 | 
			
		||||
        this.openmct.time.on('bounds', this.bounds);
 | 
			
		||||
 | 
			
		||||
        this.$scope.$on('$destroy', this.destroy);
 | 
			
		||||
 | 
			
		||||
        this.$scope.scroll.follow = this.timerService.hasTimer();
 | 
			
		||||
        if (this.$scope.zoomController) {
 | 
			
		||||
            this.bounds(this.openmct.time.bounds());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle a `change` event from the timer service; track the
 | 
			
		||||
     * new timer.
 | 
			
		||||
     */
 | 
			
		||||
    TimelineTOIController.prototype.change = function () {
 | 
			
		||||
        this.$scope.scroll.follow =
 | 
			
		||||
            this.$scope.scroll.follow || this.timerService.hasTimer();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle a `bounds` event from the time API; scroll the timeline
 | 
			
		||||
     * to match the current bounds, if currently in follow mode.
 | 
			
		||||
     */
 | 
			
		||||
    TimelineTOIController.prototype.bounds = function (bounds) {
 | 
			
		||||
        if (this.isFollowing()) {
 | 
			
		||||
            var start = this.timerService.convert(bounds.start);
 | 
			
		||||
            var end = this.timerService.convert(bounds.end);
 | 
			
		||||
            this.duration = bounds.end - bounds.start;
 | 
			
		||||
            this.$scope.zoomController.bounds(start, end);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle a `$destroy` event from scope; detach all observers.
 | 
			
		||||
     */
 | 
			
		||||
    TimelineTOIController.prototype.destroy = function () {
 | 
			
		||||
        this.timerService.off('change', this.change);
 | 
			
		||||
        this.openmct.time.off('bounds', this.bounds);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the x position of the time-of-interest line,
 | 
			
		||||
     * in pixels from the left edge of the timeline area.
 | 
			
		||||
     */
 | 
			
		||||
    TimelineTOIController.prototype.x = function () {
 | 
			
		||||
        var now = this.timerService.now();
 | 
			
		||||
 | 
			
		||||
        if (now === undefined) {
 | 
			
		||||
            return undefined;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return this.$scope.zoomController.toPixels(this.timerService.now());
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if there is an active time-of-interest to be shown.
 | 
			
		||||
     * @return {boolean} true when active
 | 
			
		||||
     */
 | 
			
		||||
    TimelineTOIController.prototype.isActive = function () {
 | 
			
		||||
        return this.x() !== undefined;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Check if the timeline should be following time conductor bounds.
 | 
			
		||||
     * @return {boolean} true when following
 | 
			
		||||
     */
 | 
			
		||||
    TimelineTOIController.prototype.isFollowing = function () {
 | 
			
		||||
        return !!this.$scope.scroll.follow && this.timerService.now() !== undefined;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return TimelineTOIController;
 | 
			
		||||
});
 | 
			
		||||
@@ -32,7 +32,8 @@ define(
 | 
			
		||||
            // Prefer to start with the middle index
 | 
			
		||||
            var zoomLevels = ZOOM_CONFIGURATION.levels || [1000],
 | 
			
		||||
                zoomIndex = Math.floor(zoomLevels.length / 2),
 | 
			
		||||
                tickWidth = ZOOM_CONFIGURATION.width || 200;
 | 
			
		||||
                tickWidth = ZOOM_CONFIGURATION.width || 200,
 | 
			
		||||
                lastWidth = Number.MAX_VALUE; // Don't constrain prematurely
 | 
			
		||||
 | 
			
		||||
            function toMillis(pixels) {
 | 
			
		||||
                return (pixels / tickWidth) * zoomLevels[zoomIndex];
 | 
			
		||||
@@ -55,19 +56,29 @@ define(
 | 
			
		||||
 | 
			
		||||
            function setScroll(x) {
 | 
			
		||||
                $window.requestAnimationFrame(function () {
 | 
			
		||||
                    $scope.scroll.x = x;
 | 
			
		||||
                    $scope.scroll.x = Math.min(
 | 
			
		||||
                        Math.max(x, 0),
 | 
			
		||||
                        lastWidth - $scope.scroll.width
 | 
			
		||||
                    );
 | 
			
		||||
                    $scope.$apply();
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            function initializeZoomFromTimespan(timespan) {
 | 
			
		||||
                var timelineDuration = timespan.getDuration();
 | 
			
		||||
            function initializeZoomFromStartEnd(start, end) {
 | 
			
		||||
                var duration = end - start;
 | 
			
		||||
                zoomIndex = 0;
 | 
			
		||||
                while (toMillis($scope.scroll.width) < timelineDuration &&
 | 
			
		||||
                while (toMillis($scope.scroll.width) < duration &&
 | 
			
		||||
                        zoomIndex < zoomLevels.length - 1) {
 | 
			
		||||
                    zoomIndex += 1;
 | 
			
		||||
                }
 | 
			
		||||
                setScroll(toPixels(timespan.getStart()));
 | 
			
		||||
                setScroll(toPixels(start));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            function initializeZoomFromTimespan(timespan) {
 | 
			
		||||
                return initializeZoomFromStartEnd(
 | 
			
		||||
                    timespan.getStart(),
 | 
			
		||||
                    timespan.getEnd()
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            function initializeZoom() {
 | 
			
		||||
@@ -101,6 +112,13 @@ define(
 | 
			
		||||
                    }
 | 
			
		||||
                    return zoomLevels[zoomIndex];
 | 
			
		||||
                },
 | 
			
		||||
                /**
 | 
			
		||||
                 * Adjust the current zoom bounds to fit both the
 | 
			
		||||
                 * start and the end time provided.
 | 
			
		||||
                 * @param {number} start the starting timestamp
 | 
			
		||||
                 * @param {number} end the ending timestamp
 | 
			
		||||
                 */
 | 
			
		||||
                bounds: initializeZoomFromStartEnd,
 | 
			
		||||
                /**
 | 
			
		||||
                 * Set the zoom level to fit the bounds of the timeline
 | 
			
		||||
                 * being viewed.
 | 
			
		||||
@@ -119,14 +137,14 @@ define(
 | 
			
		||||
                 */
 | 
			
		||||
                toMillis: toMillis,
 | 
			
		||||
                /**
 | 
			
		||||
                 * Get the pixel width necessary to fit the specified
 | 
			
		||||
                 * timestamp, expressed as an offset in milliseconds from
 | 
			
		||||
                 * the start of the timeline.
 | 
			
		||||
                 * Set the maximum timestamp value to be displayed, and get
 | 
			
		||||
                 * the pixel width necessary to display this value.
 | 
			
		||||
                 * @param {number} timestamp the time to display
 | 
			
		||||
                 */
 | 
			
		||||
                width: function (timestamp) {
 | 
			
		||||
                    var pixels = Math.ceil(toPixels(timestamp * (1 + PADDING)));
 | 
			
		||||
                    return Math.max($scope.scroll.width, pixels);
 | 
			
		||||
                    lastWidth = Math.max($scope.scroll.width, pixels);
 | 
			
		||||
                    return lastWidth;
 | 
			
		||||
                }
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,138 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2009-2016, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    "../../src/controllers/TimelineTOIController",
 | 
			
		||||
    "EventEmitter"
 | 
			
		||||
], function (TimelineTOIController, EventEmitter) {
 | 
			
		||||
    describe("The timeline TOI controller", function () {
 | 
			
		||||
        var mockmct;
 | 
			
		||||
        var mockTimerService;
 | 
			
		||||
        var mockScope;
 | 
			
		||||
        var controller;
 | 
			
		||||
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            mockmct = { time: new EventEmitter() };
 | 
			
		||||
            mockmct.time.bounds = jasmine.createSpy('bounds');
 | 
			
		||||
            mockTimerService = new EventEmitter();
 | 
			
		||||
            mockTimerService.getTimer = jasmine.createSpy('getTimer');
 | 
			
		||||
            mockTimerService.hasTimer = jasmine.createSpy('hasTimer');
 | 
			
		||||
            mockTimerService.now = jasmine.createSpy('now');
 | 
			
		||||
            mockTimerService.convert = jasmine.createSpy('convert');
 | 
			
		||||
            mockScope = new EventEmitter();
 | 
			
		||||
            mockScope.$on = mockScope.on.bind(mockScope);
 | 
			
		||||
            mockScope.zoomController = jasmine.createSpyObj('zoom', [
 | 
			
		||||
                'bounds',
 | 
			
		||||
                'toPixels'
 | 
			
		||||
            ]);
 | 
			
		||||
            mockScope.scroll = { x: 10, width: 1000 };
 | 
			
		||||
 | 
			
		||||
            spyOn(mockmct.time, "on").andCallThrough();
 | 
			
		||||
            spyOn(mockmct.time, "off").andCallThrough();
 | 
			
		||||
            spyOn(mockTimerService, "on").andCallThrough();
 | 
			
		||||
            spyOn(mockTimerService, "off").andCallThrough();
 | 
			
		||||
 | 
			
		||||
            controller = new TimelineTOIController(
 | 
			
		||||
                mockmct,
 | 
			
		||||
                mockTimerService,
 | 
			
		||||
                mockScope
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("reports an undefined x position initially", function () {
 | 
			
		||||
            expect(controller.x()).toBeUndefined();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("listens for bounds changes", function () {
 | 
			
		||||
            expect(mockmct.time.on)
 | 
			
		||||
                .toHaveBeenCalledWith('bounds', controller.bounds);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("listens for timer changes", function () {
 | 
			
		||||
            expect(mockTimerService.on)
 | 
			
		||||
                .toHaveBeenCalledWith('change', controller.change);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("is not active", function () {
 | 
			
		||||
            expect(controller.isActive()).toBe(false);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe("on $destroy from scope", function () {
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                mockScope.emit("$destroy");
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("unregisters listeners", function () {
 | 
			
		||||
                expect(mockmct.time.off)
 | 
			
		||||
                    .toHaveBeenCalledWith('bounds', controller.bounds);
 | 
			
		||||
                expect(mockTimerService.off)
 | 
			
		||||
                    .toHaveBeenCalledWith('change', controller.change);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe("when a timer and timestamp present", function () {
 | 
			
		||||
            var mockTimer;
 | 
			
		||||
            var testNow;
 | 
			
		||||
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                testNow = 333221;
 | 
			
		||||
                mockScope.zoomController.toPixels
 | 
			
		||||
                    .andCallFake(function (millis) {
 | 
			
		||||
                        return millis * 2;
 | 
			
		||||
                    });
 | 
			
		||||
                mockTimerService.emit('change', mockTimer);
 | 
			
		||||
                mockTimerService.now.andReturn(testNow);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("reports an x value from the zoomController", function () {
 | 
			
		||||
                var now = mockTimerService.now();
 | 
			
		||||
                var expected = mockScope.zoomController.toPixels(now);
 | 
			
		||||
                expect(controller.x()).toEqual(expected);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe("when follow mode is disabled", function () {
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                mockScope.scroll.follow = false;
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("ignores bounds events", function () {
 | 
			
		||||
                mockmct.time.emit('bounds', { start: 0, end: 1000 });
 | 
			
		||||
                expect(mockScope.zoomController.bounds)
 | 
			
		||||
                    .not.toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe("when follow mode is enabled", function () {
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                mockScope.scroll.follow = true;
 | 
			
		||||
                mockTimerService.now.andReturn(500);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("zooms on bounds events", function () {
 | 
			
		||||
                mockmct.time.emit('bounds', { start: 0, end: 1000 });
 | 
			
		||||
                expect(mockScope.zoomController.bounds)
 | 
			
		||||
                    .toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -24,21 +24,22 @@
 | 
			
		||||
 | 
			
		||||
    <span class="l-click-area" ng-click="toggle.toggle()"></span>
 | 
			
		||||
    <span class="color-swatch"
 | 
			
		||||
          ng-class="{'no-selection':ngModel[field] === 'transparent'}"
 | 
			
		||||
          ng-style="{
 | 
			
		||||
             background: ngModel[field]
 | 
			
		||||
             'background-color': ngModel[field]
 | 
			
		||||
         }">
 | 
			
		||||
    </span>
 | 
			
		||||
    <span class="title-label" ng-if="structure.text">
 | 
			
		||||
        {{structure.text}}
 | 
			
		||||
    </span>
 | 
			
		||||
 | 
			
		||||
    <div class="menu l-color-palette"
 | 
			
		||||
    <div class="menu l-palette l-color-palette"
 | 
			
		||||
        ng-controller="ColorController as colors"
 | 
			
		||||
        ng-show="toggle.isActive()">
 | 
			
		||||
        <div
 | 
			
		||||
            class="l-palette-row l-option-row"
 | 
			
		||||
            ng-if="!structure.mandatory">
 | 
			
		||||
            <div class="l-palette-item s-palette-item {{ngModel[field] === 'transparent' ? 'icon-check' : '' }}"
 | 
			
		||||
            <div class="l-palette-item s-palette-item no-selection {{ngModel[field] === 'transparent' ? 'selected' : '' }}"
 | 
			
		||||
                ng-click="ngModel[field] = 'transparent'">
 | 
			
		||||
            </div>
 | 
			
		||||
            <span class="l-palette-item-label">None</span>
 | 
			
		||||
@@ -46,7 +47,7 @@
 | 
			
		||||
        <div
 | 
			
		||||
            class="l-palette-row"
 | 
			
		||||
            ng-repeat="group in colors.groups()">
 | 
			
		||||
            <div class="l-palette-item s-palette-item {{ngModel[field] === color ? 'icon-check' : '' }}"
 | 
			
		||||
            <div class="l-palette-item s-palette-item {{ngModel[field] === color ? 'selected' : '' }}"
 | 
			
		||||
                ng-repeat="color in group"
 | 
			
		||||
                ng-style="{ background: color }"
 | 
			
		||||
                ng-click="ngModel[field] = color">
 | 
			
		||||
 
 | 
			
		||||
@@ -47,7 +47,7 @@ define([
 | 
			
		||||
                            "name": "Export as JSON",
 | 
			
		||||
                            "implementation": ExportAsJSONAction,
 | 
			
		||||
                            "category": "contextual",
 | 
			
		||||
                            "cssClass": "icon-save",
 | 
			
		||||
                            "cssClass": "icon-export",
 | 
			
		||||
                            "depends": [
 | 
			
		||||
                                "exportService",
 | 
			
		||||
                                "policyService",
 | 
			
		||||
@@ -59,7 +59,7 @@ define([
 | 
			
		||||
                            "name": "Import from JSON",
 | 
			
		||||
                            "implementation": ImportAsJSONAction,
 | 
			
		||||
                            "category": "contextual",
 | 
			
		||||
                            "cssClass": "icon-download",
 | 
			
		||||
                            "cssClass": "icon-import",
 | 
			
		||||
                            "depends": [
 | 
			
		||||
                                 "exportService",
 | 
			
		||||
                                 "identifierService",
 | 
			
		||||
 
 | 
			
		||||
@@ -25,10 +25,12 @@
 | 
			
		||||
 */
 | 
			
		||||
define(
 | 
			
		||||
    [
 | 
			
		||||
        '../../../src/api/objects/object-utils'
 | 
			
		||||
        '../../../src/api/objects/object-utils',
 | 
			
		||||
        'lodash'
 | 
			
		||||
    ],
 | 
			
		||||
    function (
 | 
			
		||||
        objectUtils
 | 
			
		||||
        objectUtils,
 | 
			
		||||
        _
 | 
			
		||||
    ) {
 | 
			
		||||
 | 
			
		||||
        var ZERO = function () {
 | 
			
		||||
@@ -189,14 +191,17 @@ define(
 | 
			
		||||
            return fullRequest;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        function asSeries(telemetry, defaultDomain, defaultRange, sourceMap) {
 | 
			
		||||
            function getValue(index, key) {
 | 
			
		||||
                return telemetry[index][sourceMap[key].source];
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
        function asSeries(telemetry, defaultDomain, defaultRange) {
 | 
			
		||||
            return {
 | 
			
		||||
                getRangeValue: function (index, range) {
 | 
			
		||||
                    return telemetry[index][range || defaultRange];
 | 
			
		||||
                    return getValue(index, range || defaultRange);
 | 
			
		||||
                },
 | 
			
		||||
                getDomainValue: function (index, domain) {
 | 
			
		||||
                    return telemetry[index][domain || defaultDomain];
 | 
			
		||||
                    return getValue(index, domain || defaultDomain);
 | 
			
		||||
                },
 | 
			
		||||
                getPointCount: function () {
 | 
			
		||||
                    return telemetry.length;
 | 
			
		||||
@@ -223,9 +228,11 @@ define(
 | 
			
		||||
            var telemetryAPI = this.openmct.telemetry;
 | 
			
		||||
 | 
			
		||||
            var metadata = telemetryAPI.getMetadata(domainObject);
 | 
			
		||||
            var defaultDomain = metadata.valuesForHints(['domain'])[0].source;
 | 
			
		||||
            var defaultDomain = metadata.valuesForHints(['domain'])[0].key;
 | 
			
		||||
            var defaultRange = metadata.valuesForHints(['range'])[0];
 | 
			
		||||
            defaultRange = defaultRange ? defaultRange.source : undefined;
 | 
			
		||||
            defaultRange = defaultRange ? defaultRange.key : undefined;
 | 
			
		||||
 | 
			
		||||
            var sourceMap = _.indexBy(metadata.values(), 'key');
 | 
			
		||||
 | 
			
		||||
            var isLegacyProvider = telemetryAPI.findRequestProvider(domainObject) ===
 | 
			
		||||
                telemetryAPI.legacyProvider;
 | 
			
		||||
@@ -250,7 +257,7 @@ define(
 | 
			
		||||
                    requestTelemetryFromService().then(getRelevantResponse);
 | 
			
		||||
            } else {
 | 
			
		||||
                return telemetryAPI.request(domainObject, fullRequest).then(function (telemetry) {
 | 
			
		||||
                    return asSeries(telemetry, defaultDomain, defaultRange);
 | 
			
		||||
                    return asSeries(telemetry, defaultDomain, defaultRange, sourceMap);
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
@@ -286,15 +293,17 @@ define(
 | 
			
		||||
            var telemetryAPI = this.openmct.telemetry;
 | 
			
		||||
 | 
			
		||||
            var metadata = telemetryAPI.getMetadata(domainObject);
 | 
			
		||||
            var defaultDomain = metadata.valuesForHints(['domain'])[0].source;
 | 
			
		||||
            var defaultDomain = metadata.valuesForHints(['domain'])[0].key;
 | 
			
		||||
            var defaultRange = metadata.valuesForHints(['range'])[0];
 | 
			
		||||
            defaultRange = defaultRange ? defaultRange.source : undefined;
 | 
			
		||||
            defaultRange = defaultRange ? defaultRange.key : undefined;
 | 
			
		||||
 | 
			
		||||
            var sourceMap = _.indexBy(metadata.values(), 'key');
 | 
			
		||||
 | 
			
		||||
            var isLegacyProvider = telemetryAPI.findSubscriptionProvider(domainObject) ===
 | 
			
		||||
                telemetryAPI.legacyProvider;
 | 
			
		||||
 | 
			
		||||
            function update(telemetry) {
 | 
			
		||||
                callback(asSeries([telemetry], defaultDomain, defaultRange));
 | 
			
		||||
                callback(asSeries([telemetry], defaultDomain, defaultRange, sourceMap));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Unpack the relevant telemetry series
 | 
			
		||||
 
 | 
			
		||||
@@ -34,6 +34,7 @@ define(
 | 
			
		||||
                mockUnsubscribe,
 | 
			
		||||
                telemetry,
 | 
			
		||||
                mockTelemetryAPI,
 | 
			
		||||
                mockMetadata,
 | 
			
		||||
                mockAPI;
 | 
			
		||||
 | 
			
		||||
            function mockPromise(value) {
 | 
			
		||||
@@ -90,14 +91,23 @@ define(
 | 
			
		||||
                    "findRequestProvider",
 | 
			
		||||
                    "findSubscriptionProvider"
 | 
			
		||||
                ]);
 | 
			
		||||
                mockTelemetryAPI.getMetadata.andReturn({
 | 
			
		||||
                    valuesForHints: function (hint) {
 | 
			
		||||
                        var metadatum = {};
 | 
			
		||||
                        metadatum[hint] = "foo";
 | 
			
		||||
                        return [metadatum];
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                mockMetadata = jasmine.createSpyObj('telemetryMetadata', [
 | 
			
		||||
                    'valuesForHints',
 | 
			
		||||
                    'values'
 | 
			
		||||
                ]);
 | 
			
		||||
 | 
			
		||||
                mockMetadata.valuesForHints.andCallFake(function (hints) {
 | 
			
		||||
                    var hint = hints[0];
 | 
			
		||||
                    var metadatum = {
 | 
			
		||||
                        key: 'default' + hint
 | 
			
		||||
                    };
 | 
			
		||||
                    metadatum[hint] = "foo";
 | 
			
		||||
                    return [metadatum];
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                mockTelemetryAPI.getMetadata.andReturn(mockMetadata);
 | 
			
		||||
 | 
			
		||||
                mockAPI = {
 | 
			
		||||
                    telemetry: mockTelemetryAPI,
 | 
			
		||||
                    time: {
 | 
			
		||||
@@ -150,8 +160,8 @@ define(
 | 
			
		||||
                        key: "testKey", // from model
 | 
			
		||||
                        start: 42, // from argument
 | 
			
		||||
                        domain: 'mockTimeSystem',
 | 
			
		||||
                        domains: [{ domain: "foo" }],
 | 
			
		||||
                        ranges: [{ range: "foo" }]
 | 
			
		||||
                        domains: [{ domain: "foo", key: 'defaultdomain' }],
 | 
			
		||||
                        ranges: [{ range: "foo", key: 'defaultrange' }]
 | 
			
		||||
                    }]);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
@@ -172,8 +182,8 @@ define(
 | 
			
		||||
                    start: 0,
 | 
			
		||||
                    end: 1,
 | 
			
		||||
                    domain: 'mockTimeSystem',
 | 
			
		||||
                    domains: [{ domain: "foo" }],
 | 
			
		||||
                    ranges: [{ range: "foo" }]
 | 
			
		||||
                    domains: [{ domain: "foo", key: 'defaultdomain' }],
 | 
			
		||||
                    ranges: [{ range: "foo", key: 'defaultrange' }]
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
@@ -191,8 +201,8 @@ define(
 | 
			
		||||
                    start: 0,
 | 
			
		||||
                    end: 1,
 | 
			
		||||
                    domain: 'mockTimeSystem',
 | 
			
		||||
                    domains: [{ domain: "foo" }],
 | 
			
		||||
                    ranges: [{ range: "foo" }]
 | 
			
		||||
                    domains: [{ domain: "foo", key: 'defaultdomain' }],
 | 
			
		||||
                    ranges: [{ range: "foo", key: 'defaultrange' }]
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
@@ -240,6 +250,21 @@ define(
 | 
			
		||||
                var mockProvider = {};
 | 
			
		||||
                var dunzo = false;
 | 
			
		||||
 | 
			
		||||
                mockMetadata.values.andReturn([
 | 
			
		||||
                    {
 | 
			
		||||
                        key: 'defaultrange',
 | 
			
		||||
                        source: 'prop1'
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        key: 'defaultdomain',
 | 
			
		||||
                        source: 'prop2'
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        key: 'prop3',
 | 
			
		||||
                        source: 'prop3'
 | 
			
		||||
                    }
 | 
			
		||||
                ]);
 | 
			
		||||
 | 
			
		||||
                mockTelemetryAPI.findRequestProvider.andReturn(mockProvider);
 | 
			
		||||
                mockTelemetryAPI.request.andReturn(Promise.resolve(mockTelemetry));
 | 
			
		||||
 | 
			
		||||
@@ -257,6 +282,18 @@ define(
 | 
			
		||||
                    expect(returnedTelemetry.getDomainValue).toBeDefined();
 | 
			
		||||
                    expect(returnedTelemetry.getRangeValue).toBeDefined();
 | 
			
		||||
                    expect(returnedTelemetry.getPointCount()).toBe(2);
 | 
			
		||||
                    // Default domain + remap should work.
 | 
			
		||||
                    expect(returnedTelemetry.getDomainValue(0)).toBe('val2');
 | 
			
		||||
                    expect(returnedTelemetry.getDomainValue(1)).toBe('val5');
 | 
			
		||||
                    // explicit domain should work
 | 
			
		||||
                    expect(returnedTelemetry.getDomainValue(0, 'prop3')).toBe('val3');
 | 
			
		||||
                    expect(returnedTelemetry.getDomainValue(1, 'prop3')).toBe('val6');
 | 
			
		||||
                    // default range + remap should work
 | 
			
		||||
                    expect(returnedTelemetry.getRangeValue(0)).toBe('val1');
 | 
			
		||||
                    expect(returnedTelemetry.getRangeValue(1)).toBe('val4');
 | 
			
		||||
                    // explicit range should work
 | 
			
		||||
                    expect(returnedTelemetry.getRangeValue(0, 'prop3')).toBe('val3');
 | 
			
		||||
                    expect(returnedTelemetry.getRangeValue(1, 'prop3')).toBe('val6');
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
@@ -275,8 +312,8 @@ define(
 | 
			
		||||
                        start: 0,
 | 
			
		||||
                        end: 1,
 | 
			
		||||
                        domain: 'mockTimeSystem',
 | 
			
		||||
                        domains: [{ domain: "foo" }],
 | 
			
		||||
                        ranges: [{ range: "foo" }]
 | 
			
		||||
                        domains: [{ domain: "foo", key: "defaultdomain" }],
 | 
			
		||||
                        ranges: [{ range: "foo", key: "defaultrange" }]
 | 
			
		||||
                    }]
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										17
									
								
								src/MCT.js
									
									
									
									
									
								
							
							
						
						
									
										17
									
								
								src/MCT.js
									
									
									
									
									
								
							@@ -106,9 +106,9 @@ define([
 | 
			
		||||
         *
 | 
			
		||||
         * @type {module:openmct.ViewRegistry}
 | 
			
		||||
         * @memberof module:openmct.MCT#
 | 
			
		||||
         * @name mainViews
 | 
			
		||||
         * @name objectViews
 | 
			
		||||
         */
 | 
			
		||||
        this.mainViews = new ViewRegistry();
 | 
			
		||||
        this.objectViews = new ViewRegistry();
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Registry for views which should appear in the Inspector area.
 | 
			
		||||
@@ -255,6 +255,19 @@ define([
 | 
			
		||||
            this.legacyExtension('types', legacyDefinition);
 | 
			
		||||
        }.bind(this));
 | 
			
		||||
 | 
			
		||||
        this.objectViews.providers.forEach(function (p) {
 | 
			
		||||
            this.legacyExtension('views', {
 | 
			
		||||
                key: 'vpid' + p.vpid,
 | 
			
		||||
                vpid: p.vpid,
 | 
			
		||||
                provider: p,
 | 
			
		||||
                name: p.name,
 | 
			
		||||
                cssClass: p.cssClass,
 | 
			
		||||
                description: p.description,
 | 
			
		||||
                editable: p.editable,
 | 
			
		||||
                template: '<mct-view mct-vpid="' + p.vpid + '"/>'
 | 
			
		||||
            });
 | 
			
		||||
        }, this);
 | 
			
		||||
 | 
			
		||||
        legacyRegistry.register('adapter', this.legacyBundle);
 | 
			
		||||
        legacyRegistry.enable('adapter');
 | 
			
		||||
        /**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Open MCT https://nasa.github.io/openmct/
 | 
			
		||||
 * Version: ${version}
 | 
			
		||||
 * Built: ${timestamp}
 | 
			
		||||
 * Revision: ${revision}
 | 
			
		||||
 * Branch: ${branch}
 | 
			
		||||
 */
 | 
			
		||||
@@ -24,7 +24,6 @@ define([
 | 
			
		||||
    'legacyRegistry',
 | 
			
		||||
    './actions/ActionDialogDecorator',
 | 
			
		||||
    './capabilities/AdapterCapability',
 | 
			
		||||
    './controllers/AdaptedViewController',
 | 
			
		||||
    './directives/MCTView',
 | 
			
		||||
    './services/Instantiate',
 | 
			
		||||
    './services/MissingModelCompatibilityDecorator',
 | 
			
		||||
@@ -32,13 +31,11 @@ define([
 | 
			
		||||
    './policies/AdapterCompositionPolicy',
 | 
			
		||||
    './policies/AdaptedViewPolicy',
 | 
			
		||||
    './runs/AlternateCompositionInitializer',
 | 
			
		||||
    './runs/TimeSettingsURLHandler',
 | 
			
		||||
    'text!./templates/adapted-view-template.html'
 | 
			
		||||
    './runs/TimeSettingsURLHandler'
 | 
			
		||||
], function (
 | 
			
		||||
    legacyRegistry,
 | 
			
		||||
    ActionDialogDecorator,
 | 
			
		||||
    AdapterCapability,
 | 
			
		||||
    AdaptedViewController,
 | 
			
		||||
    MCTView,
 | 
			
		||||
    Instantiate,
 | 
			
		||||
    MissingModelCompatibilityDecorator,
 | 
			
		||||
@@ -46,15 +43,15 @@ define([
 | 
			
		||||
    AdapterCompositionPolicy,
 | 
			
		||||
    AdaptedViewPolicy,
 | 
			
		||||
    AlternateCompositionInitializer,
 | 
			
		||||
    TimeSettingsURLHandler,
 | 
			
		||||
    adaptedViewTemplate
 | 
			
		||||
    TimeSettingsURLHandler
 | 
			
		||||
) {
 | 
			
		||||
    legacyRegistry.register('src/adapter', {
 | 
			
		||||
        "extensions": {
 | 
			
		||||
            "directives": [
 | 
			
		||||
                {
 | 
			
		||||
                    key: "mctView",
 | 
			
		||||
                    implementation: MCTView
 | 
			
		||||
                    implementation: MCTView,
 | 
			
		||||
                    depends: ["openmct"]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            capabilities: [
 | 
			
		||||
@@ -63,16 +60,6 @@ define([
 | 
			
		||||
                    implementation: AdapterCapability
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            controllers: [
 | 
			
		||||
                {
 | 
			
		||||
                    key: "AdaptedViewController",
 | 
			
		||||
                    implementation: AdaptedViewController,
 | 
			
		||||
                    depends: [
 | 
			
		||||
                        '$scope',
 | 
			
		||||
                        'openmct'
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            services: [
 | 
			
		||||
                {
 | 
			
		||||
                    key: "instantiate",
 | 
			
		||||
@@ -135,12 +122,6 @@ define([
 | 
			
		||||
                    depends: ["openmct", "$location", "$rootScope"]
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            views: [
 | 
			
		||||
                {
 | 
			
		||||
                    key: "adapted-view",
 | 
			
		||||
                    template: adaptedViewTemplate
 | 
			
		||||
                }
 | 
			
		||||
            ],
 | 
			
		||||
            licenses: [
 | 
			
		||||
                {
 | 
			
		||||
                    "name": "almond",
 | 
			
		||||
 
 | 
			
		||||
@@ -22,10 +22,12 @@
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    './synchronizeMutationCapability',
 | 
			
		||||
    './AlternateCompositionCapability'
 | 
			
		||||
    './AlternateCompositionCapability',
 | 
			
		||||
    './patchViewCapability'
 | 
			
		||||
], function (
 | 
			
		||||
    synchronizeMutationCapability,
 | 
			
		||||
    AlternateCompositionCapability
 | 
			
		||||
    AlternateCompositionCapability,
 | 
			
		||||
    patchViewCapability
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -46,6 +48,9 @@ define([
 | 
			
		||||
            capabilities.mutation =
 | 
			
		||||
                synchronizeMutationCapability(capabilities.mutation);
 | 
			
		||||
        }
 | 
			
		||||
        if (capabilities.view) {
 | 
			
		||||
            capabilities.view = patchViewCapability(capabilities.view);
 | 
			
		||||
        }
 | 
			
		||||
        if (AlternateCompositionCapability.appliesTo(model, id)) {
 | 
			
		||||
            capabilities.composition = function (domainObject) {
 | 
			
		||||
                return new AlternateCompositionCapability(this.$injector, domainObject);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										61
									
								
								src/adapter/capabilities/patchViewCapability.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								src/adapter/capabilities/patchViewCapability.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2017, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    'lodash'
 | 
			
		||||
], function (
 | 
			
		||||
    _
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    function patchViewCapability(viewConstructor) {
 | 
			
		||||
        return function makeCapability(domainObject) {
 | 
			
		||||
            var capability = viewConstructor(domainObject);
 | 
			
		||||
            var oldInvoke = capability.invoke.bind(capability);
 | 
			
		||||
 | 
			
		||||
            capability.invoke = function () {
 | 
			
		||||
                var availableViews = oldInvoke();
 | 
			
		||||
                var newDomainObject = capability
 | 
			
		||||
                    .domainObject
 | 
			
		||||
                    .useCapability('adapter');
 | 
			
		||||
 | 
			
		||||
                return _(availableViews).map(function (v, i) {
 | 
			
		||||
                    var vd = {
 | 
			
		||||
                        view: v,
 | 
			
		||||
                        priority: i + 100 // arbitrary to allow new views to
 | 
			
		||||
                        // be defaults by returning priority less than 100.
 | 
			
		||||
                    };
 | 
			
		||||
                    if (v.provider) {
 | 
			
		||||
                        vd.priority = v.provider.canView(newDomainObject);
 | 
			
		||||
                    }
 | 
			
		||||
                    return vd;
 | 
			
		||||
                })
 | 
			
		||||
                .sortBy('priority')
 | 
			
		||||
                .map('view')
 | 
			
		||||
                .value();
 | 
			
		||||
            };
 | 
			
		||||
            return capability;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return patchViewCapability;
 | 
			
		||||
});
 | 
			
		||||
@@ -21,18 +21,20 @@
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    'angular',
 | 
			
		||||
    './Region'
 | 
			
		||||
], function (
 | 
			
		||||
    angular,
 | 
			
		||||
    Region
 | 
			
		||||
) {
 | 
			
		||||
    function MCTView() {
 | 
			
		||||
    function MCTView(openmct) {
 | 
			
		||||
        return {
 | 
			
		||||
            restrict: 'A',
 | 
			
		||||
            restrict: 'E',
 | 
			
		||||
            link: function (scope, element, attrs) {
 | 
			
		||||
                var region = new Region(element[0]);
 | 
			
		||||
                scope.$watch(attrs.mctView, region.show.bind(region));
 | 
			
		||||
                var provider = openmct.objectViews.getByVPID(Number(attrs.mctVpid));
 | 
			
		||||
                var view = new provider.view(scope.domainObject.useCapability('adapter'));
 | 
			
		||||
                view.show(element[0]);
 | 
			
		||||
                if (view.destroy) {
 | 
			
		||||
                    scope.$on('$destroy', function () {
 | 
			
		||||
                        view.destroy(element[0]);
 | 
			
		||||
                    });
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 
 | 
			
		||||
@@ -29,9 +29,9 @@ define([], function () {
 | 
			
		||||
        view,
 | 
			
		||||
        legacyObject
 | 
			
		||||
    ) {
 | 
			
		||||
        if (view.key === 'adapted-view') {
 | 
			
		||||
        if (view.hasOwnProperty('vpid')) {
 | 
			
		||||
            var domainObject = legacyObject.useCapability('adapter');
 | 
			
		||||
            return this.openmct.mainViews.get(domainObject).length > 0;
 | 
			
		||||
            return view.provider.canView(domainObject);
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -35,7 +35,7 @@ define([
 | 
			
		||||
            name: 'Name'
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        metadata.domains.forEach(function (domain, index) {
 | 
			
		||||
        (metadata.domains || []).forEach(function (domain, index) {
 | 
			
		||||
            var valueMetadata = _.clone(domain);
 | 
			
		||||
            valueMetadata.hints = {
 | 
			
		||||
                domain: index + 1
 | 
			
		||||
@@ -43,11 +43,11 @@ define([
 | 
			
		||||
            valueMetadatas.push(valueMetadata);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        metadata.ranges.forEach(function (range, index) {
 | 
			
		||||
        (metadata.ranges || []).forEach(function (range, index) {
 | 
			
		||||
            var valueMetadata = _.clone(range);
 | 
			
		||||
            valueMetadata.hints = {
 | 
			
		||||
                range: index,
 | 
			
		||||
                priority: index + metadata.domains.length + 1
 | 
			
		||||
                priority: index + (metadata.domains || []).length + 1
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            if (valueMetadata.type === 'enum') {
 | 
			
		||||
 
 | 
			
		||||
@@ -25,7 +25,7 @@ define([
 | 
			
		||||
], function (
 | 
			
		||||
    _
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    // TODO: needs reference to formatService;
 | 
			
		||||
    function TelemetryValueFormatter(valueMetadata, formatService) {
 | 
			
		||||
        var numberFormatter = {
 | 
			
		||||
@@ -33,7 +33,12 @@ define([
 | 
			
		||||
                return Number(x);
 | 
			
		||||
            },
 | 
			
		||||
            format: function (x) {
 | 
			
		||||
                return x;
 | 
			
		||||
                var number = parseFloat(x);
 | 
			
		||||
                if (isNaN(number)){
 | 
			
		||||
                    return x;
 | 
			
		||||
                } else {
 | 
			
		||||
                    return number.toFixed(2);
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            validate: function (x) {
 | 
			
		||||
                return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
        <a class="close icon-x-in-circle"></a>
 | 
			
		||||
        <div class="abs inner-holder contents">
 | 
			
		||||
            <div class="abs top-bar">
 | 
			
		||||
                <div class="title"></div>
 | 
			
		||||
                <div class="dialog-title"></div>
 | 
			
		||||
                <div class="hint"></div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class='abs editor'>
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										45
									
								
								src/plugins/buildInfo/plugin.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/plugins/buildInfo/plugin.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,45 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * 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.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
], function (
 | 
			
		||||
) {
 | 
			
		||||
    return function (buildInfo) {
 | 
			
		||||
        return function (openmct) {
 | 
			
		||||
            var aliases = { timestamp: "Built" };
 | 
			
		||||
            var descriptions = {
 | 
			
		||||
                timestamp: "The date on which this version of Open MCT was built.",
 | 
			
		||||
                revision: "A unique revision identifier for the client sources.",
 | 
			
		||||
                branch: "The name of the branch that was used during the build."
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            Object.keys(buildInfo).forEach(function (key) {
 | 
			
		||||
                openmct.legacyExtension("versions", {
 | 
			
		||||
                    key: key,
 | 
			
		||||
                    name: aliases[key] || (key.charAt(0).toUpperCase() + key.substring(1)),
 | 
			
		||||
                    value: buildInfo[key],
 | 
			
		||||
                    description: descriptions[key]
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
});
 | 
			
		||||
@@ -20,26 +20,31 @@
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([], function () {
 | 
			
		||||
    function Region(element) {
 | 
			
		||||
        this.activeView = undefined;
 | 
			
		||||
        this.element = element;
 | 
			
		||||
    }
 | 
			
		||||
define([
 | 
			
		||||
    './plugin'
 | 
			
		||||
], function (plugin) {
 | 
			
		||||
    describe("The buildInfo plugin", function () {
 | 
			
		||||
        var mockmct;
 | 
			
		||||
        var testInfo;
 | 
			
		||||
 | 
			
		||||
    Region.prototype.clear = function () {
 | 
			
		||||
        if (this.activeView) {
 | 
			
		||||
            this.activeView.destroy();
 | 
			
		||||
            this.activeView = undefined;
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
        beforeEach(function () {
 | 
			
		||||
            mockmct = jasmine.createSpyObj('openmct', ['legacyExtension']);
 | 
			
		||||
            testInfo = { foo: 123, bar: "baz" };
 | 
			
		||||
            plugin(testInfo)(mockmct);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
    Region.prototype.show = function (view) {
 | 
			
		||||
        this.clear();
 | 
			
		||||
        this.activeView = view;
 | 
			
		||||
        if (this.activeView) {
 | 
			
		||||
            this.activeView.show(this.element);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return Region;
 | 
			
		||||
        it("registers versions extensions", function () {
 | 
			
		||||
            Object.keys(testInfo).forEach(function (key) {
 | 
			
		||||
                expect(mockmct.legacyExtension).toHaveBeenCalledWith(
 | 
			
		||||
                    "versions",
 | 
			
		||||
                    {
 | 
			
		||||
                        key: key,
 | 
			
		||||
                        name: jasmine.any(String),
 | 
			
		||||
                        value: testInfo[key],
 | 
			
		||||
                        description: undefined
 | 
			
		||||
                    }
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -27,7 +27,9 @@ define([
 | 
			
		||||
    '../../platform/features/autoflow/plugin',
 | 
			
		||||
    './timeConductor/plugin',
 | 
			
		||||
    '../../example/imagery/plugin',
 | 
			
		||||
    '../../platform/import-export/bundle'
 | 
			
		||||
    './summaryWidget/plugin',
 | 
			
		||||
    '../../platform/import-export/bundle',
 | 
			
		||||
    './telemetryMean/plugin'
 | 
			
		||||
], function (
 | 
			
		||||
    _,
 | 
			
		||||
    UTCTimeSystem,
 | 
			
		||||
@@ -35,7 +37,9 @@ define([
 | 
			
		||||
    AutoflowPlugin,
 | 
			
		||||
    TimeConductorPlugin,
 | 
			
		||||
    ExampleImagery,
 | 
			
		||||
    ImportExport
 | 
			
		||||
    SummaryWidget,
 | 
			
		||||
    ImportExport,
 | 
			
		||||
    TelemetryMean
 | 
			
		||||
) {
 | 
			
		||||
    var bundleMap = {
 | 
			
		||||
        CouchDB: 'platform/persistence/couch',
 | 
			
		||||
@@ -120,6 +124,8 @@ define([
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    plugins.ExampleImagery = ExampleImagery;
 | 
			
		||||
    plugins.SummaryWidget = SummaryWidget;
 | 
			
		||||
    plugins.TelemetryMean = TelemetryMean;
 | 
			
		||||
 | 
			
		||||
    return plugins;
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -20,21 +20,33 @@
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([], function () {
 | 
			
		||||
    function AdaptedViewController($scope, openmct) {
 | 
			
		||||
        function refresh(legacyObject) {
 | 
			
		||||
            if (!legacyObject) {
 | 
			
		||||
                $scope.view = undefined;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
define(
 | 
			
		||||
    [],
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
            var domainObject = legacyObject.useCapability('adapter');
 | 
			
		||||
            var providers = openmct.mainViews.get(domainObject);
 | 
			
		||||
            $scope.view = providers[0] && providers[0].view(domainObject);
 | 
			
		||||
        /**
 | 
			
		||||
         * Defines composition policy for Display Layout objects.
 | 
			
		||||
         * They cannot contain folders.
 | 
			
		||||
         * @constructor
 | 
			
		||||
         * @memberof platform/features/layout
 | 
			
		||||
         * @implements {Policy.<View, DomainObject>}
 | 
			
		||||
         */
 | 
			
		||||
        function SummaryWidgetsCompositionPolicy(openmct) {
 | 
			
		||||
            this.openmct = openmct;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        $scope.$watch('domainObject', refresh);
 | 
			
		||||
    }
 | 
			
		||||
        SummaryWidgetsCompositionPolicy.prototype.allow = function (parent, child) {
 | 
			
		||||
 | 
			
		||||
    return AdaptedViewController;
 | 
			
		||||
});
 | 
			
		||||
            var parentType = parent.getCapability('type');
 | 
			
		||||
            var newStyleChild = child.useCapability('adapter');
 | 
			
		||||
 | 
			
		||||
            if (parentType.instanceOf('summary-widget') && !this.openmct.telemetry.canProvideTelemetry(newStyleChild)) {
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        return SummaryWidgetsCompositionPolicy;
 | 
			
		||||
    }
 | 
			
		||||
);
 | 
			
		||||
							
								
								
									
										69
									
								
								src/plugins/summaryWidget/plugin.js
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										69
									
								
								src/plugins/summaryWidget/plugin.js
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,69 @@
 | 
			
		||||
define(['./src/SummaryWidget', './SummaryWidgetsCompositionPolicy'], function (SummaryWidget, SummaryWidgetsCompositionPolicy) {
 | 
			
		||||
 | 
			
		||||
    function plugin() {
 | 
			
		||||
 | 
			
		||||
        var widgetType = {
 | 
			
		||||
            name: 'Summary Widget',
 | 
			
		||||
            description: 'A compact status update for collections of telemetry-producing items',
 | 
			
		||||
            creatable: true,
 | 
			
		||||
            cssClass: 'icon-summary-widget',
 | 
			
		||||
            initialize: function (domainObject) {
 | 
			
		||||
                domainObject.composition = [];
 | 
			
		||||
                domainObject.configuration = {};
 | 
			
		||||
                domainObject.openNewTab = 'thisTab';
 | 
			
		||||
            },
 | 
			
		||||
            form: [
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "url",
 | 
			
		||||
                    "name": "URL",
 | 
			
		||||
                    "control": "textfield",
 | 
			
		||||
                    "pattern": "^(ftp|https?)\\:\\/\\/",
 | 
			
		||||
                    "required": false,
 | 
			
		||||
                    "cssClass": "l-input-lg"
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    "key": "openNewTab",
 | 
			
		||||
                    "name": "Tab to Open Hyperlink",
 | 
			
		||||
                    "control": "select",
 | 
			
		||||
                    "options": [
 | 
			
		||||
                            {
 | 
			
		||||
                                "value": "thisTab",
 | 
			
		||||
                                "name": "Open in this tab"
 | 
			
		||||
                            },
 | 
			
		||||
                            {
 | 
			
		||||
                                "value": "newTab",
 | 
			
		||||
                                "name": "Open in a new tab"
 | 
			
		||||
                            }
 | 
			
		||||
                        ],
 | 
			
		||||
                    "cssClass": "l-inline"
 | 
			
		||||
                }
 | 
			
		||||
            ]
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        function initViewProvider(openmct) {
 | 
			
		||||
            return {
 | 
			
		||||
                name: 'Widget View',
 | 
			
		||||
                view: function (domainObject) {
 | 
			
		||||
                    var summaryWidget = new SummaryWidget(domainObject, openmct);
 | 
			
		||||
                    return {
 | 
			
		||||
                        show: summaryWidget.show,
 | 
			
		||||
                        destroy: summaryWidget.destroy
 | 
			
		||||
                    };
 | 
			
		||||
                },
 | 
			
		||||
                canView: function (domainObject) {
 | 
			
		||||
                    return (domainObject.type === 'summary-widget');
 | 
			
		||||
                },
 | 
			
		||||
                editable: true
 | 
			
		||||
            };
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return function install(openmct) {
 | 
			
		||||
            openmct.types.addType('summary-widget', widgetType);
 | 
			
		||||
            openmct.objectViews.addProvider(initViewProvider(openmct));
 | 
			
		||||
            openmct.legacyExtension('policies', {category: 'composition',
 | 
			
		||||
                implementation: SummaryWidgetsCompositionPolicy, depends: ['openmct']});
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return plugin;
 | 
			
		||||
});
 | 
			
		||||
							
								
								
									
										11
									
								
								src/plugins/summaryWidget/res/conditionTemplate.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/plugins/summaryWidget/res/conditionTemplate.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,11 @@
 | 
			
		||||
<li class="t-condition">
 | 
			
		||||
    <label class="t-condition-context">when</label>
 | 
			
		||||
    <span class="controls">
 | 
			
		||||
        <span class="t-configuration"> </span>
 | 
			
		||||
        <span class="t-value-inputs"> </span>
 | 
			
		||||
    </span>
 | 
			
		||||
    <span class="flex-elem l-condition-action-buttons-wrapper">
 | 
			
		||||
        <a class="s-icon-button icon-duplicate t-duplicate" title="Duplicate this condition"></a>
 | 
			
		||||
        <a class="s-icon-button icon-trash t-delete" title="Delete this condition"></a>
 | 
			
		||||
    </span>
 | 
			
		||||
</li>
 | 
			
		||||
							
								
								
									
										10
									
								
								src/plugins/summaryWidget/res/input/paletteTemplate.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/plugins/summaryWidget/res/input/paletteTemplate.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,10 @@
 | 
			
		||||
<a class="e-control s-button s-menu-button menu-element">
 | 
			
		||||
   <span class="l-click-area"></span>
 | 
			
		||||
   <span class="t-swatch"></span>
 | 
			
		||||
   <div class="menu l-palette">
 | 
			
		||||
       <div class="l-palette-row l-option-row">
 | 
			
		||||
           <div class="l-palette-item s-palette-item no-selection"></div>
 | 
			
		||||
           <span class="l-palette-item-label">None</span>
 | 
			
		||||
       </div>
 | 
			
		||||
   </div>
 | 
			
		||||
</a>
 | 
			
		||||
							
								
								
									
										4
									
								
								src/plugins/summaryWidget/res/input/selectTemplate.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								src/plugins/summaryWidget/res/input/selectTemplate.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,4 @@
 | 
			
		||||
<div class="e-control select">
 | 
			
		||||
    <select>
 | 
			
		||||
    </select>
 | 
			
		||||
 </div>
 | 
			
		||||
							
								
								
									
										3
									
								
								src/plugins/summaryWidget/res/ruleImageTemplate.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								src/plugins/summaryWidget/res/ruleImageTemplate.html
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,3 @@
 | 
			
		||||
<div class="holder widget-rules-wrapper">
 | 
			
		||||
    <div class="t-drag-rule-image l-widget-rule s-widget-rule"></div>
 | 
			
		||||
</div>
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user