Compare commits

..

1 Commits

Author SHA1 Message Date
Pete Richards
536dc90705 [Telemetry] Gracefully handle no limits
Gracefully handle the case where a limit evaluator is not found.

Removes burden from views.
2017-07-27 10:08:02 -07:00
89 changed files with 666 additions and 3797 deletions

2
.gitignore vendored
View File

@@ -36,5 +36,3 @@ protractor/logs
# npm-debug log
npm-debug.log
package-lock.json

2
API.md
View File

@@ -505,7 +505,7 @@ MCT, it will be pre-configured to use the UTC time system, which is installed an
The time bounds of an Open MCT application are defined as numbers, and a Time
System gives meaning and context to these numbers so that they can be correctly
interpreted. Time Systems are JavaScript objects that provide some information
interpreted. Time Systems are javscript objects that provide some information
about the current time reference frame. An example of defining and registering
a new time system is given below:

View File

@@ -103,7 +103,7 @@
var data = [];
for (; nextStep < end && data.length < 5000; nextStep += step) {
for (; nextStep < end; nextStep += step) {
data.push({
utc: nextStep,
yesterday: nextStep - 60*60*24*1000,

View File

@@ -79,7 +79,7 @@ define([
var start = options.start;
var end = options.end;
var data = [];
while (start < end && data.length < 5000) {
while (start < end) {
data.push(pointForTimestamp(start));
start += 5000;
}

View File

@@ -16,7 +16,6 @@ define([
{ "key": "styleguide.intro", "name": "Introduction", "cssClass": "icon-page", "description": "Introduction and overview to the style guide" },
{ "key": "styleguide.standards", "name": "Standards", "cssClass": "icon-page", "description": "" },
{ "key": "styleguide.colors", "name": "Colors", "cssClass": "icon-page", "description": "" },
{ "key": "styleguide.status", "name": "status", "cssClass": "icon-page", "description": "Limits, telemetry paused, etc." },
{ "key": "styleguide.glyphs", "name": "Glyphs", "cssClass": "icon-page", "description": "Glyphs overview" },
{ "key": "styleguide.controls", "name": "Controls", "cssClass": "icon-page", "description": "Buttons, selects, HTML controls" },
{ "key": "styleguide.input", "name": "Text Inputs", "cssClass": "icon-page", "description": "Various text inputs" },
@@ -26,7 +25,6 @@ define([
{ "key": "styleguide.intro", "type": "styleguide.intro", "templateUrl": "templates/intro.html", "editable": false },
{ "key": "styleguide.standards", "type": "styleguide.standards", "templateUrl": "templates/standards.html", "editable": false },
{ "key": "styleguide.colors", "type": "styleguide.colors", "templateUrl": "templates/colors.html", "editable": false },
{ "key": "styleguide.status", "type": "styleguide.status", "templateUrl": "templates/status.html", "editable": false },
{ "key": "styleguide.glyphs", "type": "styleguide.glyphs", "templateUrl": "templates/glyphs.html", "editable": false },
{ "key": "styleguide.controls", "type": "styleguide.controls", "templateUrl": "templates/controls.html", "editable": false },
{ "key": "styleguide.input", "type": "styleguide.input", "templateUrl": "templates/input.html", "editable": false },
@@ -49,7 +47,6 @@ define([
"intro",
"standards",
"colors",
"status",
"glyphs",
"styleguide:ui-elements"
]

View File

@@ -28,8 +28,8 @@
color: $colorKey;
}
h1, h2, strong, b {
color: pullForward($colorBodyFg, 50%);
h1, h2 {
color: pullForward($colorBodyFg, 20%);
}
h2 {
@@ -45,10 +45,6 @@
text-transform: uppercase;
}
strong, b {
font-weight: normal;
}
.w-markup {
//Wrap markup example "pre" element
background-color: $colorCode;
@@ -58,12 +54,6 @@
position: relative;
}
.w-mct-example {
div {
margin-bottom: $interiorMarginLg;
}
}
code,
pre {
font-size: 0.8rem;
@@ -153,17 +143,6 @@
// Example grid of glyphs
.items-holder.grid {
table.details {
width: 100%;
td {
font-size: inherit;
&.label {
color: pushBack($colorBodyFg, 10%);
text-transform: uppercase;
white-space: nowrap;
}
}
}
.item.glyph-item,
.item.swatch-item {
margin-bottom: 50px;
@@ -176,6 +155,15 @@
margin: $interiorMarginLg 0;
text-align: center;
}
table.details td {
font-size: inherit;
&.label {
color: pushBack($colorBodyFg, 10%);
text-transform: uppercase;
white-space: nowrap;
}
}
}
.item.glyph-item {

View File

@@ -48,9 +48,7 @@
{ 'meaning': 'General usage plus symbol; used in timer object', 'cssClass': 'icon-plus', 'cssContent': 'e926', 'htmlEntity': '&amp;#xe926' },
{ 'meaning': 'Delete', 'cssClass': 'icon-trash', 'cssContent': 'e927', 'htmlEntity': '&amp;#xe927' },
{ 'meaning': 'Close, remove', 'cssClass': 'icon-x', 'cssContent': 'e928', 'htmlEntity': '&amp;#xe928' },
{ 'meaning': 'Enclosing, inclusive; used in Time Conductor', 'cssClass': 'icon-brackets', 'cssContent': 'e929', 'htmlEntity': '&amp;#xe929' },
{ 'meaning': 'Something is targeted', 'cssClass': 'icon-crosshair', 'cssContent': 'e930', 'htmlEntity': '&amp;#xe930' },
{ 'meaning': 'Draggable', 'cssClass': 'icon-grippy', 'cssContent': 'e931', 'htmlEntity': '&amp;#xe931' }
{ 'meaning': 'Enclosing, inclusive; used in Time Conductor', 'cssClass': 'icon-brackets', 'cssContent': 'e929', 'htmlEntity': '&amp;#xe929' }
]; controls= [{ 'meaning': 'Reset zoom/pam', 'cssClass': 'icon-arrows-out', 'cssContent': 'e1000', 'htmlEntity': '&amp;#xe1000' },
{ 'meaning': 'Expand vertically', 'cssClass': 'icon-arrows-right-left', 'cssContent': 'e1001', 'htmlEntity': '&amp;#xe1001' },
{ 'meaning': 'View scrolling', 'cssClass': 'icon-arrows-up-down', 'cssContent': 'e1002', 'htmlEntity': '&amp;#xe1002' },
@@ -86,17 +84,10 @@
{ 'meaning': 'Image thumbs strip; view items grid', 'cssClass': 'icon-thumbs-strip', 'cssContent': 'e1033', 'htmlEntity': '&amp;#xe1033' },
{ 'meaning': 'Two part item, both parts', 'cssClass': 'icon-two-parts-both', 'cssContent': 'e1034', 'htmlEntity': '&amp;#xe1034' },
{ 'meaning': 'Two part item, one only', 'cssClass': 'icon-two-parts-one-only', 'cssContent': 'e1035', 'htmlEntity': '&amp;#xe1035' },
{ 'meaning': 'Resync', 'cssClass': 'icon-resync', 'cssContent': 'e1036', 'htmlEntity': '&amp;#xe1036' },
{ 'meaning': 'Reset', 'cssClass': 'icon-reset', 'cssContent': 'e1037', 'htmlEntity': '&amp;#xe1037' },
{ 'meaning': 'Clear', 'cssClass': 'icon-x-in-circle', 'cssContent': 'e1038', 'htmlEntity': '&amp;#xe1038' },
{ 'meaning': 'Brightness', 'cssClass': 'icon-brightness', 'cssContent': 'e1039', 'htmlEntity': '&amp;#xe1039' },
{ 'meaning': 'Contrast', 'cssClass': 'icon-contrast', 'cssContent': 'e1040', 'htmlEntity': '&amp;#xe1040' },
{ 'meaning': 'Expand', 'cssClass': 'icon-expand', 'cssContent': 'e1041', 'htmlEntity': '&amp;#xe1041' },
{ 'meaning': 'View items in a tabular list', 'cssClass': 'icon-list-view', 'cssContent': 'e1042', 'htmlEntity': '&amp;#xe1042' },
{ 'meaning': 'Snap an object corner to a grid', 'cssClass': 'icon-grid-snap-to', 'cssContent': 'e1043', 'htmlEntity': '&amp;#xe1043' },
{ 'meaning': 'Do not snap an object corner to a grid', 'cssClass': 'icon-grid-snap-no', 'cssContent': 'e1044', 'htmlEntity': '&amp;#xe1044' },
{ 'meaning': 'Show an object frame in a Display Layout', 'cssClass': 'icon-frame-show', 'cssContent': 'e1045', 'htmlEntity': '&amp;#xe1045' },
{ 'meaning': 'Do not show an object frame in a Display Layout', 'cssClass': 'icon-frame-hide', 'cssContent': 'e1046', 'htmlEntity': '&amp;#xe1046' }
{ 'meaning': 'Expand', 'cssClass': 'icon-expand', 'cssContent': 'e1041', 'htmlEntity': '&amp;#xe1041' }
]; objects= [{ 'meaning': 'Activity', 'cssClass': 'icon-activity', 'cssContent': 'e1100', 'htmlEntity': '&amp;#xe1100' },
{ 'meaning': 'Activity Mode', 'cssClass': 'icon-activity-mode', 'cssContent': 'e1101', 'htmlEntity': '&amp;#xe1101' },
{ 'meaning': 'Auto-flow Tabular view', 'cssClass': 'icon-autoflow-tabular', 'cssContent': 'e1102', 'htmlEntity': '&amp;#xe1102' },
@@ -126,8 +117,7 @@
{ 'meaning': 'Timeline object', 'cssClass': 'icon-timeline', 'cssContent': 'e1126', 'htmlEntity': '&amp;#xe1126' },
{ 'meaning': 'Timer object', 'cssClass': 'icon-timer', 'cssContent': 'e1127', 'htmlEntity': '&amp;#xe1127' },
{ 'meaning': 'Data Topic', 'cssClass': 'icon-topic', 'cssContent': 'e1128', 'htmlEntity': '&amp;#xe1128' },
{ 'meaning': 'Fixed Position object', 'cssClass': 'icon-box-with-dashed-lines', 'cssContent': 'e1129', 'htmlEntity': '&amp;#xe1129' },
{ 'meaning': 'Summary Widget', 'cssClass': 'icon-summary-widget', 'cssContent': 'e1130', 'htmlEntity': '&amp;#xe1130' }
{ 'meaning': 'Fixed Position object', 'cssClass': 'icon-box-with-dashed-lines', 'cssContent': 'e1129', 'htmlEntity': '&amp;#xe1129' }
];
"></div>
@@ -151,8 +141,8 @@
<h2>How to Use Glyphs</h2>
<div class="cols cols1-1">
<div class="col">
<p>The easiest way to use a glyph is to include its CSS class in an element. The CSS adds a psuedo <code>:before</code> HTML element to whatever element it's attached to that makes proper use of the symbols font.</p>
<p>Alternately, you can use the <code>.ui-symbol</code> class in an object that contains encoded HTML entities. This method is only recommended if you cannot use the aforementioned CSS class approach.</p>
<p>The easiest way to use a glyph is to include its CSS class in element. The CSS adds a psuedo <code>:before</code> HTML element to whatever element it's attached to that makes proper use of the symbols font.</p>
<p>Alternately, you can use the <code>.ui-symbol</code> class in an object that contains encoded HTML entities. This method is only recommended if you cannot use the aforementioned CSS class approach for some reason.</p>
</div>
<mct-example><a class="s-button icon-gear" title="Settings"></a>
<br /><br />
@@ -170,8 +160,8 @@
<div class="item glyph-item" ng-repeat="glyph in general">
<div class="glyph" ng-class="glyph.cssClass"></div>
<table class="details">
<tr><td class="label">Class</td><td class="value">.{{glyph.cssClass}}</td></tr>
<tr><td class="label">Meaning</td><td class="value">{{glyph.meaning}}</td></tr>
<tr><td class="label">Class</td><td class="value">.{{glyph.cssClass}}</td></tr>
<tr><td class="label">CSS Content</td><td class="value">\{{glyph.cssContent}}</td></tr>
<tr><td class="label">HTML Entity</td><td class="value">{{glyph.htmlEntity}}</td></tr>
</table>
@@ -186,8 +176,8 @@
<div class="item glyph-item" ng-repeat="glyph in controls">
<div class="glyph" ng-class="glyph.cssClass"></div>
<table class="details">
<tr><td class="label">Class</td><td class="value">.{{glyph.cssClass}}</td></tr>
<tr><td class="label">Meaning</td><td class="value">{{glyph.meaning}}</td></tr>
<tr><td class="label">Class</td><td class="value">.{{glyph.cssClass}}</td></tr>
<tr><td class="label">CSS Content</td><td class="value">\{{glyph.cssContent}}</td></tr>
<tr><td class="label">HTML Entity</td><td class="value">{{glyph.htmlEntity}}</td></tr>
</table>
@@ -202,8 +192,8 @@
<div class="item glyph-item" ng-repeat="glyph in objects">
<div class="glyph" ng-class="glyph.cssClass"></div>
<table class="details">
<tr><td class="label">Class</td><td class="value">.{{glyph.cssClass}}</td></tr>
<tr><td class="label">Meaning</td><td class="value">{{glyph.meaning}}</td></tr>
<tr><td class="label">Class</td><td class="value">.{{glyph.cssClass}}</td></tr>
<tr><td class="label">CSS Content</td><td class="value">\{{glyph.cssContent}}</td></tr>
<tr><td class="label">HTML Entity</td><td class="value">{{glyph.htmlEntity}}</td></tr>
</table>

View File

@@ -4,5 +4,5 @@
<pre></pre>
</span>
<h3>Example</h3>
<div class="w-mct-example"></div>
<div></div>
</div>

View File

@@ -1,142 +0,0 @@
<!--
Open MCT, Copyright (c) 2014-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.
-->
<style>
.w-mct-example div[class*="s-limit"],
.w-mct-example div[class*="s-status"],
.w-mct-example div[class*="s-unsynced"],
.w-mct-example span[class*="s-limit"] {
border-radius: 4px;
padding: 3px 7px;
}
.w-mct-example table {
width: 100%;
}
</style>
<div class="l-style-guide s-text">
<p class="doc-title">Open MCT Style Guide</p>
<h1>Status Indication</h1>
<div class="l-section">
<h2>Overview</h2>
<p>Many elements in Open MCT need to articulate a dynamic status; Open MCT provides the following styles and conventions to handle this:</p>
<ul>
<li><strong>Limits</strong>: when telemetry values exceed minimum or maximum values, they can be violating limits. Limit styles include both color and iconography; color is used to indicate severity while icons are used to indicate direction, upper or lower.</li>
<li><strong>Status</strong>: Open MCT also provides a number or built-in Status styles allowing telemetry or other displayed information to be visually classified by type. Common uses for these classes are to visually denote event records.</li>
<li><strong>Synchronization</strong>: When the system is displaying real-time data, it is very important that displays clearly indicate when they are not doing so, such as when a plot if frozen while panning or zooming. Open MCT provides a style for this.</li>
</ul>
</div>
<div class="l-section">
<h2>Limits</h2>
<div class="cols cols1-1">
<div class="col">
<p>Limit CSS classes can be applied to any block or inline element. Open MCT limit classes set color and optionally an icon, but don't effect other properties. Yellow and red limit classes can be used as is, or allow the application of any custom icon available in Open MCT's glyphs library. &quot;Level&quot; limit classes - upper and lower - always use an icon in addition to a color; Open MCT doesn't support level limits without color.</p>
<ul>
<li>Color only</li>
<ul>
<li><code>s-limit-yellow</code>: A yellow limit.</li>
<li><code>s-limit-red</code>: A red limit.</li>
</ul>
<li>Color and icon</li>
<ul>
<li><code>s-limit-yellow-icon</code>: A yellow limit with icon.</li>
<li><code>s-limit-red-icon</code>: A red limit with icon.</li>
</ul>
<li>Upper and lower limit indicators. Must be used with a color limit class to be visible.</li>
<ul>
<li><code>s-limit-upr</code>: Upper limit.
</li>
<li><code>s-limit-lwr</code>: Lower limit.
</li>
</ul>
</ul>
</div>
<mct-example><div class="s-limit-yellow">Yellow limit</div>
<div class="s-limit-red">Red limit</div>
<div class="s-limit-yellow-icon">Yellow limit with icon</div>
<div class="s-limit-red-icon">Red limit with icon</div>
<div class="s-limit-yellow s-limit-lwr">Lower yellow limit</div>
<div class="s-limit-red s-limit-upr">Upper red limit</div>
<div class="s-limit-red icon-bell">Red Limit with a custom icon</div>
<div>Some text with an <span class="s-limit-yellow-icon">inline element</span> showing a yellow limit.</div>
<!-- Limits applied in a table -->
<table>
<tr class='header'><td>Name</td><td>Value 1</td><td>Value 2</td></tr>
<tr><td>ENG_PWR 4991</td><td>7.023</td><td class="s-limit-yellow s-limit-upr">70.23</td></tr>
<tr><td>ENG_PWR 4992</td><td>49.784</td><td class="s-limit-red s-limit-lwr">-121.22</td></tr>
<tr><td>ENG_PWR 4993</td><td class="s-limit-yellow icon-bell">0.451</td><td>1.007</td></tr>
</table>
</mct-example>
</div>
</div>
<div class="l-section">
<h2>Status</h2>
<div class="cols cols1-1">
<div class="col">
<p>Classes here can be applied to elements as needed.</p>
<ul>
<li>Color only</li>
<ul>
<li><code>s-status-warning-hi</code></li>
<li><code>s-status-warning-lo</code></li>
<li><code>s-status-diagnostic</code></li>
<li><code>s-status-info</code></li>
<li><code>s-status-ok</code></li>
</ul>
<li>Color and icon</li>
<ul>
<li><code>s-status-warning-hi-icon</code></li>
<li><code>s-status-warning-lo-icon</code></li>
<li><code>s-status-diagnostic-icon</code></li>
<li><code>s-status-info-icon</code></li>
<li><code>s-status-ok-icon</code></li>
</ul>
</ul>
</div>
<mct-example><div class="s-status-warning-hi">WARNING HI</div>
<div class="s-status-warning-lo">WARNING LOW</div>
<div class="s-status-diagnostic">DIAGNOSTIC</div>
<div class="s-status-info">INFO</div>
<div class="s-status-ok">OK</div>
<div class="s-status-warning-hi-icon">WARNING HI with icon</div>
<div class="s-status-warning-lo-icon">WARNING LOW with icon</div>
<div class="s-status-diagnostic-icon">DIAGNOSTIC with icon</div>
<div class="s-status-info-icon">INFO with icon</div>
<div class="s-status-ok-icon">OK with icon</div>
<div class="s-status-warning-hi icon-gear">WARNING HI with custom icon</div>
</mct-example>
</div>
</div>
<div class="l-section">
<h2>Synchronization</h2>
<div class="cols cols1-1">
<div class="col">
<p>When the system is operating in real-time streaming mode, it is important for views that display real-time data to clearly articulate when they are not, such as when a user zooms or pans a plot view, freezing that view. In that case, the CSS class <code>s-unsynced</code> should be applied to that view.</p>
</div>
<mct-example><div class="s-unsynced">This element is unsynced</div>
</mct-example>
</div>
</div>
</div>

View File

@@ -34,7 +34,6 @@ define(
pages['standards'] = { name: "Standards", type: "styleguide.standards", location: "styleguide:home" };
pages['colors'] = { name: "Colors", type: "styleguide.colors", location: "styleguide:home" };
pages['glyphs'] = { name: "Glyphs", type: "styleguide.glyphs", location: "styleguide:home" };
pages['status'] = { name: "Status Indication", type: "styleguide.status", location: "styleguide:home" };
pages['controls'] = { name: "Controls", type: "styleguide.controls", location: "styleguide:ui-elements" };
pages['input'] = { name: "Text Inputs", type: "styleguide.input", location: "styleguide:ui-elements" };
pages['menus'] = { name: "Menus", type: "styleguide.menus", location: "styleguide:ui-elements" };

View File

@@ -43,7 +43,6 @@
openmct.install(openmct.plugins.Generator());
openmct.install(openmct.plugins.ExampleImagery());
openmct.install(openmct.plugins.UTCTimeSystem());
openmct.install(openmct.plugins.ImportExport());
openmct.install(openmct.plugins.Conductor({
menuOptions: [
{

View File

@@ -21,7 +21,7 @@
"bower": "^1.7.7",
"git-rev-sync": "^1.4.0",
"glob": ">= 3.0.0",
"gulp": "^3.9.1",
"gulp": "^3.9.0",
"gulp-header": "^1.8.8",
"gulp-jscs": "^3.0.2",
"gulp-jshint": "^2.0.0",

View File

@@ -26,7 +26,6 @@ define([
"./src/InspectorPaneController",
"./src/BrowseObjectController",
"./src/MenuArrowController",
"./src/ObjectHeaderController",
"./src/navigation/NavigationService",
"./src/navigation/NavigateAction",
"./src/navigation/OrphanNavigationHandler",
@@ -49,7 +48,6 @@ define([
InspectorPaneController,
BrowseObjectController,
MenuArrowController,
ObjectHeaderController,
NavigationService,
NavigateAction,
OrphanNavigationHandler,
@@ -109,9 +107,7 @@ define([
"depends": [
"$scope",
"agentService",
"$window",
"$location",
"$attrs"
"$window"
]
},
{
@@ -138,16 +134,7 @@ define([
"$scope",
"agentService",
"$window",
"navigationService",
"$location",
"$attrs"
]
},
{
"key": "ObjectHeaderController",
"implementation": ObjectHeaderController,
"depends": [
"$scope"
"navigationService"
]
}
],

View File

@@ -24,9 +24,9 @@
<mct-include key="'topbar-browse'"></mct-include>
<div class="abs holder holder-main browse-area s-browse-area browse-wrapper"
ng-controller="PaneController as modelPaneTree"
ng-class="modelPaneTree.visible() ? 'pane-tree-showing' : 'pane-tree-hidden'" hide-parameter="hideTree">
ng-class="modelPaneTree.visible() ? 'pane-tree-showing' : 'pane-tree-hidden'">
<mct-split-pane class='abs contents'
anchor='left' alias="leftSide">
anchor='left'>
<div class='split-pane-component treeview pane left'>
<div class="abs holder l-flex-col holder-treeview-elements">
<mct-representation key="'create-button'"
@@ -58,10 +58,9 @@
<div class='holder holder-object-and-inspector abs' id='content-area'
ng-controller="InspectorPaneController as modelPaneInspect"
ng-class="modelPaneInspect.visible() ? 'pane-inspect-showing' : 'pane-inspect-hidden'"
hide-parameter="hideInspector">
ng-class="modelPaneInspect.visible() ? 'pane-inspect-showing' : 'pane-inspect-hidden'">
<mct-split-pane class='l-object-and-inspector contents abs' anchor='right' alias="rightSide">
<mct-split-pane class='l-object-and-inspector contents abs' anchor='right'>
<div class='split-pane-component t-object pane primary-pane left'>
<mct-representation mct-object="navigatedObject"
key="navigatedObject.getCapability('status').get('editing') ? 'edit-object' : 'browse-object'"
@@ -88,3 +87,4 @@
</div>
<mct-include key="'bottombar'"></mct-include>
</div>

View File

@@ -20,17 +20,16 @@
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 class="l-elem-wrapper l-flex-row flex-elem grows">
<span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span>
<span contenteditable="true"
class='title-label flex-elem holder flex-can-shrink s-inline-edit'
ng-class="{'s-status-editing': inlineEdit}"
ng-click="controller.edit()"
ng-blur="controller.updateName($event)"
ng-keypress="controller.updateName($event)">{{model.name}}</span>
<span class='title-label flex-elem holder flex-can-shrink'>{{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>
</span>
<a class="s-button icon-expand t-btn-view-large"
title="View large"
mct-trigger-modal>
</a>

View File

@@ -35,8 +35,9 @@ define(
* @param navigationService
* @constructor
*/
function InspectorPaneController($scope, agentService, $window, navigationService, $location, $attrs) {
PaneController.call(this, $scope, agentService, $window, $location, $attrs);
function InspectorPaneController($scope, agentService, $window, navigationService) {
PaneController.call(this, $scope, agentService, $window);
var statusListener,
self = this;

View File

@@ -1,76 +0,0 @@
/*****************************************************************************
* 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.$scope.inlineEdit = false;
}
/**
* Handler for the blur and enter/return key press events
* to update the object name.
*
* @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.$scope.domainObject.getCapability("type").typeDef.name;
event.currentTarget.innerHTML = name;
}
if (name !== this.$scope.domainObject.model.name) {
this.$scope.domainObject.getCapability('mutation').mutate(function (model) {
model.name = name;
});
}
this.$scope.inlineEdit = false;
if (event.which === 13) {
event.currentTarget.blur();
}
}
};
/**
* Handler for the click event to mark the filed as inline edit.
*/
ObjectHeaderController.prototype.edit = function () {
this.$scope.inlineEdit = true;
};
return ObjectHeaderController;
}
);

View File

@@ -31,17 +31,12 @@ define(
* @constructor
* @memberof platform/commonUI/browse
*/
function PaneController($scope, agentService, $window, $location, $attrs) {
function PaneController($scope, agentService, $window) {
var self = this;
this.agentService = agentService;
var hideParameterPresent = $location.search().hasOwnProperty($attrs.hideParameter);
if ($attrs.hideParameter && hideParameterPresent) {
this.state = false;
$location.search($attrs.hideParameter, undefined);
} else {
this.state = true;
}
// Fast and cheap: if this has been opened in a new window, hide panes by default
this.state = !$window.opener;
/**
* Callback to invoke when any selection occurs in the tree.
@@ -75,7 +70,7 @@ define(
* @returns {boolean} true when visible
*/
PaneController.prototype.visible = function () {
return !!this.state;
return this.state;
};
return PaneController;

View File

@@ -38,7 +38,6 @@ define(
this.urlService = urlService;
this.open = function () {
arguments[0] += "&hideTree=true&hideInspector=true";
$window.open.apply($window, arguments);
};

View File

@@ -33,9 +33,7 @@ define(
mockNavigationService,
mockNavigationUnlistener,
mockStatusUnlistener,
controller,
mockLocation,
mockAttrs;
controller;
beforeEach(function () {
mockScope = jasmine.createSpyObj("$scope", ["$on"]);
@@ -73,12 +71,7 @@ define(
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andReturn(mockStatusCapability);
mockLocation = jasmine.createSpyObj('location', ['search']);
mockLocation.search.andReturn({});
mockAttrs = {};
controller = new InspectorPaneController(mockScope, mockAgentService, mockWindow, mockNavigationService, mockLocation, mockAttrs);
controller = new InspectorPaneController(mockScope, mockAgentService, mockWindow, mockNavigationService);
});
it("listens for changes to navigation and attaches a status" +

View File

@@ -1,94 +0,0 @@
/*****************************************************************************
* 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,
mockMutationCapability,
mockEvent,
mockCurrentTarget,
controller;
function getModel() {
return {
name: 'Test name'
};
}
beforeEach(function () {
mockMutationCapability = jasmine.createSpyObj("mutation", ["mutate"]);
mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "model"]);
mockDomainObject.model = getModel();
mockDomainObject.getCapability.andReturn(mockMutationCapability);
mockScope = jasmine.createSpyObj("$scope", ["name"]);
mockScope.domainObject = mockDomainObject;
mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur"]);
mockCurrentTarget.blur.andReturn({ blur: function () {} });
mockEvent = jasmine.createSpyObj('event', ["which"]);
mockEvent.currentTarget = mockCurrentTarget;
controller = new ObjectHeaderController(mockScope);
});
it("updates the model with new name", function () {
mockScope.name = 'New name';
controller.updateName();
expect(mockMutationCapability.mutate).toHaveBeenCalledWith(jasmine.any(Function));
});
it("does not update the model for blank names", function () {
mockScope.name = "";
controller.updateName();
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
});
it("updates the model on enter keypress event only", function () {
mockScope.name = 'New name';
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).not.toHaveBeenCalled();
mockEvent.which = 13;
controller.updateName(mockEvent);
expect(mockMutationCapability.mutate).toHaveBeenCalled();
});
it("blurs the field on enter key press", function () {
mockEvent.which = 13;
controller.updateName(mockEvent);
expect(mockEvent.currentTarget.blur).toHaveBeenCalled();
});
});
}
);

View File

@@ -29,9 +29,7 @@ define(
mockAgentService,
mockDomainObjects,
mockWindow,
controller,
mockLocation,
mockAttrs;
controller;
// We want to reinstantiate for each test case
// because device state can influence constructor-time behavior
@@ -39,9 +37,7 @@ define(
return new PaneController(
mockScope,
mockAgentService,
mockWindow,
mockLocation,
mockAttrs
mockWindow
);
}
@@ -63,11 +59,6 @@ define(
["isMobile", "isPhone", "isTablet", "isPortrait", "isLandscape"]
);
mockWindow = jasmine.createSpyObj("$window", ["open"]);
mockLocation = jasmine.createSpyObj('location', ['search']);
mockLocation.search.andReturn({});
mockAttrs = {};
});
it("is initially visible", function () {
@@ -95,24 +86,6 @@ define(
// Tree should have collapsed
expect(controller.visible()).toBeFalsy();
});
describe("specifying hideParameter", function () {
beforeEach(function () {
mockAttrs = {hideParameter: 'hideTree'};
});
it("sets pane state to false when in location.search", function () {
mockLocation.search.andReturn({'hideTree': true});
expect(instantiateController().visible()).toBe(false);
expect(mockLocation.search).toHaveBeenCalledWith('hideTree', undefined);
});
it("sets state to true when not found in location.search", function () {
mockLocation.search.andReturn({});
expect(instantiateController().visible()).toBe(true);
expect(mockLocation.search).not.toHaveBeenCalledWith('hideTree', undefined);
});
});
});
}
);

View File

@@ -374,8 +374,7 @@ define([
"depends": [
"$parse",
"$log",
"$interval",
"$window"
"$interval"
]
},
{

View File

@@ -1,144 +1,207 @@
{
"metadata": {
"name": "openmct-symbols-12px",
"lastOpened": 0,
"created": 1502213994889
},
"iconSets": [
{
"selection": [
{
"order": 9,
"id": 6,
"name": "icon12-crosshair",
"prevSize": 12,
"code": 59696,
"tempChar": ""
},
{
"order": 6,
"id": 3,
"prevSize": 12,
"code": 921865,
"name": "icon12-folder",
"tempChar": ""
}
],
"id": 0,
"metadata": {
"name": "openmct-symbols-12px",
"importSize": {
"width": 384,
"height": 384
},
"designer": "Charles Hacskaylo"
},
"height": 1024,
"prevSize": 12,
"icons": [
{
"id": 6,
"paths": [
"M597.333 0h-170.667v256h170.667v-256z",
"M1024 426.667h-256v170.667h256v-170.667z",
"M597.333 768h-170.667v256h170.667v-256z",
"M256 426.667h-256v170.667h256v-170.667z"
],
"attrs": [
{},
{},
{},
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 0,
"tags": [
"icon12-crosshair"
],
"colorPermutations": {
"1161751": [
{},
{},
{},
{}
]
}
},
{
"id": 3,
"paths": [
"M938.667 170.667h-341.333l-110.32-110.32c-33.2-33.2-98.667-60.347-145.68-60.347h-256c-47.073 0.136-85.197 38.26-85.333 85.32l-0 341.346c0.136-47.073 38.26-85.197 85.32-85.333l853.346-0c47.073 0.136 85.197 38.26 85.333 85.32l0-170.654c-0.136-47.073-38.26-85.197-85.32-85.333z",
"M85.333 426.667h853.333c47.128 0 85.333 38.205 85.333 85.333v426.667c0 47.128-38.205 85.333-85.333 85.333h-853.333c-47.128 0-85.333-38.205-85.333-85.333v-426.667c0-47.128 38.205-85.333 85.333-85.333z"
],
"attrs": [],
"isMulticolor": false,
"grid": 0,
"tags": [
"icon12-folder"
],
"colorPermutations": {
"1161751": [
{
"f": 0
},
{
"f": 0
}
]
}
}
],
"invisible": false,
"colorThemes": [
[
[
0,
0,
0,
1
],
[
0,
161,
75,
1
]
]
],
"colorThemeIdx": 0
}
],
"preferences": {
"showGlyphs": true,
"showCodes": true,
"showQuickUse": true,
"showQuickUse2": true,
"showSVGs": true,
"fontPref": {
"prefix": "icon-",
"metadata": {
"fontFamily": "openmct-symbols-12px",
"majorVersion": 1,
"minorVersion": 0
},
"metrics": {
"emSize": 1024,
"baseline": 6.25,
"whitespace": 50
},
"embed": false
},
"imagePref": {
"prefix": "icon-",
"png": true,
"useClassSelector": true,
"color": 0,
"bgColor": 16777215
},
"historySize": 100,
"gridSize": 16
},
"uid": -1,
"time": 1502216581486
}
"metadata": {
"name": "openmct-symbols-12px",
"lastOpened": 1467322505818,
"created": 1467322503679
},
"iconSets": [
{
"selection": [
{
"order": 4,
"id": 2,
"prevSize": 12,
"code": 59671,
"name": "icon12-eye-open",
"tempChar": ""
},
{
"order": 7,
"id": 5,
"prevSize": 12,
"code": 921607,
"name": "icon12-pane-collapse-left",
"tempChar": ""
},
{
"order": 8,
"id": 4,
"prevSize": 12,
"code": 921608,
"name": "icon12-pane-collapse-right",
"tempChar": ""
},
{
"order": 6,
"id": 3,
"prevSize": 12,
"code": 921865,
"name": "icon12-folder",
"tempChar": ""
}
],
"id": 0,
"metadata": {
"name": "openmct-symbols-12px",
"importSize": {
"width": 320,
"height": 384
},
"designer": "Charles Hacskaylo"
},
"height": 1024,
"prevSize": 12,
"icons": [
{
"id": 2,
"paths": [
"M512 86c-257.92 0-471.28 185.147-506.667 426 35.493 240.853 248.853 426 506.667 426s471.28-185.147 506.667-426c-35.387-240.853-248.747-426-506.667-426zM738.373 685.2c-131.048 109.517-321.699 109.517-452.747 0-53.328-44.749-90.832-105.477-106.96-173.2 16.101-67.707 53.565-128.435 106.853-173.2 131.048-109.517 321.699-109.517 452.747 0 53.368 44.733 90.909 105.464 107.067 173.2-16.128 67.723-53.632 128.451-106.96 173.2z",
"M682.667 512c0 94.257-76.41 170.667-170.667 170.667s-170.667-76.41-170.667-170.667c0-94.257 76.41-170.667 170.667-170.667s170.667 76.41 170.667 170.667z"
],
"attrs": [],
"isMulticolor": false,
"grid": 0,
"tags": [
"icon12-eye-open"
],
"colorPermutations": {
"1161751": [
{
"f": 0
},
{
"f": 0
}
]
}
},
{
"id": 5,
"paths": [
"M0 0h170.667v1024h-170.667v-1024z",
"M853.333 256h-256v-256l-341.333 426.667 341.333 426.667v-256h256v-341.333z"
],
"attrs": [
{
"opacity": 1
},
{
"opacity": 1
}
],
"isMulticolor": false,
"width": 853,
"grid": 0,
"tags": [
"icon12-pane-collapse-left"
],
"colorPermutations": {
"1161751": [
{},
{}
]
}
},
{
"id": 4,
"paths": [
"M682.667 0h170.667v1024h-170.667v-1024z",
"M0 256h256v-256l341.333 426.667-341.333 426.667v-256h-256v-341.333z"
],
"attrs": [
{
"opacity": 1
},
{
"opacity": 1
}
],
"isMulticolor": false,
"width": 853,
"grid": 0,
"tags": [
"icon12-pane-collapse-right"
],
"colorPermutations": {
"1161751": [
{},
{}
]
}
},
{
"id": 3,
"paths": [
"M938.667 170.667h-341.333l-110.32-110.32c-33.2-33.2-98.667-60.347-145.68-60.347h-256c-47.073 0.136-85.197 38.26-85.333 85.32l-0 341.346c0.136-47.073 38.26-85.197 85.32-85.333l853.346-0c47.073 0.136 85.197 38.26 85.333 85.32l0-170.654c-0.136-47.073-38.26-85.197-85.32-85.333z",
"M85.333 426.667h853.333c47.128 0 85.333 38.205 85.333 85.333v426.667c0 47.128-38.205 85.333-85.333 85.333h-853.333c-47.128 0-85.333-38.205-85.333-85.333v-426.667c0-47.128 38.205-85.333 85.333-85.333z"
],
"attrs": [],
"isMulticolor": false,
"grid": 0,
"tags": [
"icon12-folder"
],
"colorPermutations": {
"1161751": [
{
"f": 0
},
{
"f": 0
}
]
}
}
],
"invisible": false,
"colorThemes": [
[
[
0,
0,
0,
1
],
[
0,
161,
75,
1
]
]
],
"colorThemeIdx": 0
}
],
"preferences": {
"showGlyphs": true,
"showCodes": true,
"showQuickUse": true,
"showQuickUse2": true,
"showSVGs": true,
"fontPref": {
"prefix": "icon-",
"metadata": {
"fontFamily": "openmct-symbols-12px",
"majorVersion": 1,
"minorVersion": 0
},
"metrics": {
"emSize": 1024,
"baseline": 6.25,
"whitespace": 50
},
"embed": false
},
"imagePref": {
"prefix": "icon-",
"png": true,
"useClassSelector": true,
"color": 0,
"bgColor": 16777215
},
"historySize": 100,
"gridSize": 16
},
"uid": -1
}

View File

@@ -2,7 +2,7 @@
"metadata": {
"name": "openmct-symbols-16px",
"lastOpened": 0,
"created": 1502487054429
"created": 1497475810461
},
"iconSets": [
{
@@ -252,29 +252,13 @@
"code": 59689,
"tempChar": ""
},
{
"order": 134,
"id": 114,
"name": "icon-crosshair",
"prevSize": 24,
"code": 59696,
"tempChar": ""
},
{
"order": 127,
"id": 109,
"name": "icon-grippy-v2",
"prevSize": 24,
"code": 59697,
"tempChar": ""
},
{
"order": 48,
"prevSize": 24,
"name": "icon-arrows-out",
"id": 43,
"code": 921600,
"tempChar": ""
"tempChar": ""
},
{
"order": 49,
@@ -282,7 +266,7 @@
"name": "icon-arrows-right-left",
"id": 44,
"code": 921601,
"tempChar": ""
"tempChar": ""
},
{
"order": 50,
@@ -290,7 +274,7 @@
"name": "icon-arrows-up-down",
"id": 45,
"code": 921602,
"tempChar": ""
"tempChar": ""
},
{
"order": 9,
@@ -298,7 +282,7 @@
"name": "icon-bullet",
"id": 4,
"code": 921604,
"tempChar": ""
"tempChar": ""
},
{
"order": 25,
@@ -306,7 +290,7 @@
"name": "icon-calendar",
"id": 20,
"code": 921605,
"tempChar": ""
"tempChar": ""
},
{
"order": 30,
@@ -314,7 +298,7 @@
"name": "icon-chain-links",
"id": 25,
"code": 921606,
"tempChar": ""
"tempChar": ""
},
{
"order": 109,
@@ -322,7 +306,7 @@
"prevSize": 24,
"code": 921607,
"name": "icon-pane-collapse-left",
"tempChar": ""
"tempChar": ""
},
{
"order": 110,
@@ -330,7 +314,7 @@
"prevSize": 24,
"code": 921608,
"name": "icon-pane-collapse-right",
"tempChar": ""
"tempChar": ""
},
{
"order": 5,
@@ -338,7 +322,7 @@
"prevSize": 24,
"code": 921609,
"name": "icon-download",
"tempChar": ""
"tempChar": ""
},
{
"order": 60,
@@ -346,7 +330,7 @@
"name": "icon-duplicate",
"id": 55,
"code": 921616,
"tempChar": ""
"tempChar": ""
},
{
"order": 61,
@@ -354,7 +338,7 @@
"name": "icon-folder-new",
"id": 56,
"code": 921617,
"tempChar": ""
"tempChar": ""
},
{
"order": 64,
@@ -362,7 +346,7 @@
"name": "icon-fullscreen-expand",
"id": 59,
"code": 921618,
"tempChar": ""
"tempChar": ""
},
{
"order": 63,
@@ -370,7 +354,7 @@
"name": "icon-fullscreen-collapse",
"id": 58,
"code": 921619,
"tempChar": ""
"tempChar": ""
},
{
"order": 67,
@@ -378,7 +362,7 @@
"name": "icon-layers",
"id": 62,
"code": 921620,
"tempChar": ""
"tempChar": ""
},
{
"order": 69,
@@ -386,7 +370,7 @@
"name": "icon-line-horz",
"id": 64,
"code": 921621,
"tempChar": ""
"tempChar": ""
},
{
"order": 73,
@@ -394,7 +378,7 @@
"name": "icon-magnify",
"id": 68,
"code": 921622,
"tempChar": ""
"tempChar": ""
},
{
"order": 71,
@@ -402,7 +386,7 @@
"name": "icon-magnify-in",
"id": 66,
"code": 921623,
"tempChar": ""
"tempChar": ""
},
{
"order": 72,
@@ -410,7 +394,7 @@
"name": "icon-magnify-out",
"id": 67,
"code": 921624,
"tempChar": ""
"tempChar": ""
},
{
"order": 74,
@@ -418,7 +402,7 @@
"name": "icon-menu",
"id": 69,
"code": 921625,
"tempChar": ""
"tempChar": ""
},
{
"order": 75,
@@ -426,7 +410,7 @@
"name": "icon-move",
"id": 70,
"code": 921632,
"tempChar": ""
"tempChar": ""
},
{
"order": 76,
@@ -434,7 +418,7 @@
"name": "icon-new-window",
"id": 71,
"code": 921633,
"tempChar": ""
"tempChar": ""
},
{
"order": 26,
@@ -442,7 +426,7 @@
"name": "icon-paint-bucket",
"id": 21,
"code": 921634,
"tempChar": ""
"tempChar": ""
},
{
"order": 81,
@@ -450,7 +434,7 @@
"name": "icon-pause",
"id": 76,
"code": 921635,
"tempChar": ""
"tempChar": ""
},
{
"order": 82,
@@ -458,7 +442,7 @@
"name": "icon-pencil",
"id": 77,
"code": 921636,
"tempChar": ""
"tempChar": ""
},
{
"order": 84,
@@ -466,7 +450,7 @@
"name": "icon-play",
"id": 79,
"code": 921637,
"tempChar": ""
"tempChar": ""
},
{
"order": 85,
@@ -474,7 +458,7 @@
"name": "icon-plot-resource",
"id": 80,
"code": 921638,
"tempChar": ""
"tempChar": ""
},
{
"order": 27,
@@ -482,7 +466,7 @@
"name": "icon-pointer-left",
"id": 22,
"code": 921639,
"tempChar": ""
"tempChar": ""
},
{
"order": 28,
@@ -490,7 +474,7 @@
"name": "icon-pointer-right",
"id": 23,
"code": 921640,
"tempChar": ""
"tempChar": ""
},
{
"order": 32,
@@ -498,7 +482,7 @@
"name": "icon-refresh",
"id": 27,
"code": 921641,
"tempChar": ""
"tempChar": ""
},
{
"order": 16,
@@ -506,7 +490,7 @@
"name": "icon-save",
"id": 11,
"code": 921648,
"tempChar": ""
"tempChar": ""
},
{
"order": 88,
@@ -514,7 +498,7 @@
"name": "icon-sine",
"id": 83,
"code": 921649,
"tempChar": ""
"tempChar": ""
},
{
"order": 102,
@@ -522,7 +506,7 @@
"name": "icon-T",
"id": 84,
"code": 921650,
"tempChar": ""
"tempChar": ""
},
{
"order": 92,
@@ -530,7 +514,7 @@
"name": "icon-thumbs-strip",
"id": 87,
"code": 921651,
"tempChar": ""
"tempChar": ""
},
{
"order": 96,
@@ -538,7 +522,7 @@
"name": "icon-two-parts-both",
"id": 91,
"code": 921652,
"tempChar": ""
"tempChar": ""
},
{
"order": 97,
@@ -546,7 +530,7 @@
"name": "icon-two-parts-one-only",
"id": 92,
"code": 921653,
"tempChar": ""
"tempChar": ""
},
{
"order": 21,
@@ -554,7 +538,7 @@
"name": "icon-resync",
"id": 16,
"code": 921654,
"tempChar": ""
"tempChar": ""
},
{
"order": 120,
@@ -562,7 +546,7 @@
"name": "icon-reset",
"prevSize": 24,
"code": 921655,
"tempChar": ""
"tempChar": ""
},
{
"order": 121,
@@ -570,7 +554,7 @@
"name": "icon-x-in-circle",
"prevSize": 24,
"code": 921656,
"tempChar": ""
"tempChar": ""
},
{
"order": 118,
@@ -578,7 +562,7 @@
"name": "icon-brightness",
"prevSize": 24,
"code": 921657,
"tempChar": ""
"tempChar": ""
},
{
"order": 119,
@@ -586,7 +570,7 @@
"name": "icon-contrast",
"prevSize": 24,
"code": 921664,
"tempChar": ""
"tempChar": ""
},
{
"order": 124,
@@ -594,47 +578,15 @@
"name": "icon-expand",
"prevSize": 24,
"code": 921665,
"tempChar": ""
"tempChar": ""
},
{
"order": 125,
"order": 123,
"id": 107,
"name": "icon-list-view",
"prevSize": 24,
"code": 921666,
"tempChar": ""
},
{
"order": 133,
"id": 112,
"name": "icon-grid-snap-to",
"prevSize": 24,
"code": 921667,
"tempChar": ""
},
{
"order": 128,
"id": 113,
"name": "icon-grid-snap-no",
"prevSize": 24,
"code": 921668,
"tempChar": ""
},
{
"order": 131,
"id": 110,
"name": "icon-frame-show",
"prevSize": 24,
"code": 921669,
"tempChar": ""
},
{
"order": 130,
"id": 111,
"name": "icon-frame-hide",
"prevSize": 24,
"code": 921670,
"tempChar": ""
"tempChar": ""
},
{
"order": 37,
@@ -642,7 +594,7 @@
"name": "icon-activity",
"id": 32,
"code": 921856,
"tempChar": ""
"tempChar": ""
},
{
"order": 36,
@@ -650,7 +602,7 @@
"name": "icon-activity-mode",
"id": 31,
"code": 921857,
"tempChar": ""
"tempChar": ""
},
{
"order": 52,
@@ -658,7 +610,7 @@
"name": "icon-autoflow-tabular",
"id": 47,
"code": 921858,
"tempChar": ""
"tempChar": ""
},
{
"order": 55,
@@ -666,7 +618,7 @@
"name": "icon-clock",
"id": 50,
"code": 921859,
"tempChar": ""
"tempChar": ""
},
{
"order": 58,
@@ -674,7 +626,7 @@
"name": "icon-database",
"id": 53,
"code": 921860,
"tempChar": ""
"tempChar": ""
},
{
"order": 57,
@@ -682,7 +634,7 @@
"name": "icon-database-query",
"id": 52,
"code": 921861,
"tempChar": ""
"tempChar": ""
},
{
"order": 17,
@@ -690,7 +642,7 @@
"name": "icon-dataset",
"id": 12,
"code": 921862,
"tempChar": ""
"tempChar": ""
},
{
"order": 22,
@@ -698,7 +650,7 @@
"name": "icon-datatable",
"id": 17,
"code": 921863,
"tempChar": ""
"tempChar": ""
},
{
"order": 59,
@@ -706,7 +658,7 @@
"name": "icon-dictionary",
"id": 54,
"code": 921864,
"tempChar": ""
"tempChar": ""
},
{
"order": 62,
@@ -714,7 +666,7 @@
"name": "icon-folder",
"id": 57,
"code": 921865,
"tempChar": ""
"tempChar": ""
},
{
"order": 66,
@@ -722,7 +674,7 @@
"name": "icon-image",
"id": 61,
"code": 921872,
"tempChar": ""
"tempChar": ""
},
{
"order": 68,
@@ -730,7 +682,7 @@
"name": "icon-layout",
"id": 63,
"code": 921873,
"tempChar": ""
"tempChar": ""
},
{
"order": 77,
@@ -738,7 +690,7 @@
"name": "icon-object",
"id": 72,
"code": 921874,
"tempChar": ""
"tempChar": ""
},
{
"order": 78,
@@ -746,7 +698,7 @@
"name": "icon-object-unknown",
"id": 73,
"code": 921875,
"tempChar": ""
"tempChar": ""
},
{
"order": 79,
@@ -754,7 +706,7 @@
"name": "icon-packet",
"id": 74,
"code": 921876,
"tempChar": ""
"tempChar": ""
},
{
"order": 80,
@@ -762,15 +714,15 @@
"name": "icon-page",
"id": 75,
"code": 921877,
"tempChar": ""
"tempChar": ""
},
{
"order": 135,
"order": 114,
"id": 99,
"name": "icon-plot-overlay",
"prevSize": 24,
"code": 921878,
"tempChar": ""
"tempChar": ""
},
{
"order": 113,
@@ -778,7 +730,7 @@
"name": "icon-plot-stacked",
"prevSize": 24,
"code": 921879,
"tempChar": ""
"tempChar": ""
},
{
"order": 10,
@@ -786,7 +738,7 @@
"name": "icon-session",
"id": 5,
"code": 921880,
"tempChar": ""
"tempChar": ""
},
{
"order": 24,
@@ -794,7 +746,7 @@
"name": "icon-tabular",
"id": 19,
"code": 921881,
"tempChar": ""
"tempChar": ""
},
{
"order": 7,
@@ -802,7 +754,7 @@
"name": "icon-tabular-lad",
"id": 2,
"code": 921888,
"tempChar": ""
"tempChar": ""
},
{
"order": 6,
@@ -810,7 +762,7 @@
"name": "icon-tabular-lad-set",
"id": 1,
"code": 921889,
"tempChar": ""
"tempChar": ""
},
{
"order": 8,
@@ -818,7 +770,7 @@
"name": "icon-tabular-realtime",
"id": 3,
"code": 921890,
"tempChar": ""
"tempChar": ""
},
{
"order": 23,
@@ -826,7 +778,7 @@
"name": "icon-tabular-scrolling",
"id": 18,
"code": 921891,
"tempChar": ""
"tempChar": ""
},
{
"order": 112,
@@ -834,7 +786,7 @@
"name": "icon-telemetry",
"id": 86,
"code": 921892,
"tempChar": ""
"tempChar": ""
},
{
"order": 90,
@@ -842,7 +794,7 @@
"name": "icon-telemetry-panel",
"id": 85,
"code": 921893,
"tempChar": ""
"tempChar": ""
},
{
"order": 93,
@@ -850,7 +802,7 @@
"name": "icon-timeline",
"id": 88,
"code": 921894,
"tempChar": ""
"tempChar": ""
},
{
"order": 116,
@@ -858,7 +810,7 @@
"name": "icon-timer-v1.5",
"prevSize": 24,
"code": 921895,
"tempChar": ""
"tempChar": ""
},
{
"order": 11,
@@ -866,7 +818,7 @@
"name": "icon-topic",
"id": 6,
"code": 921896,
"tempChar": ""
"tempChar": ""
},
{
"order": 115,
@@ -874,15 +826,7 @@
"name": "icon-box-with-dashed-lines",
"id": 29,
"code": 921897,
"tempChar": ""
},
{
"order": 126,
"id": 108,
"name": "icon-summary-widget",
"prevSize": 24,
"code": 921904,
"tempChar": ""
"tempChar": ""
}
],
"metadata": {
@@ -1529,92 +1473,6 @@
]
}
},
{
"id": 114,
"paths": [
"M574-2h-128v320h128v-320z",
"M1022 446h-320v128h320v-128z",
"M574 702h-128v320h128v-320z",
"M318 446h-320v128h320v-128z"
],
"attrs": [
{},
{},
{},
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 16,
"tags": [
"icon-crosshair"
],
"colorPermutations": {
"1161751207457516161751": [
{},
{},
{},
{}
]
}
},
{
"id": 109,
"paths": [
"M146.4 182.8c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M146.4 402.2c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M146.4 621.8c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M146.4 841.2c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M365.8 73.2c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M365.8 292.6c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M365.8 512c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M365.8 731.4c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M365.8 950.8c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M585.2 182.8c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M585.2 402.2c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M585.2 621.8c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z",
"M585.2 841.2c0 40.427-32.773 73.2-73.2 73.2s-73.2-32.773-73.2-73.2c0-40.427 32.773-73.2 73.2-73.2s73.2 32.773 73.2 73.2z"
],
"attrs": [
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{}
],
"width": 586,
"isMulticolor": false,
"isMulticolor2": false,
"grid": 16,
"tags": [
"icon-grippy-v2"
],
"colorPermutations": {
"1161751207457516161751": [
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{}
]
}
},
{
"paths": [
"M0 512l256 256v-512z",
@@ -2558,131 +2416,6 @@
]
}
},
{
"id": 112,
"paths": [
"M382 830h448v-448h-448v448zM510 510h192v192h-192v-192z",
"M-2 574h320v64h-320v-64z",
"M894 574h128v64h-128v-64z",
"M574-2h64v320h-64v-320z",
"M574 894h64v128h-64v-128z",
"M574 574h64v64h-64v-64z"
],
"attrs": [
{},
{},
{},
{},
{},
{}
],
"grid": 16,
"tags": [
"icon-grid-snap-to"
],
"isMulticolor": false,
"isMulticolor2": false,
"colorPermutations": {
"1161751207457516161751": [
{},
{},
{},
{},
{},
{}
]
}
},
{
"id": 113,
"paths": [
"M768 576h192v64h-192v-64z",
"M256 576h192v64h-192v-64z",
"M0 576h192v64h-192v-64z",
"M640 512h-64v64h-64v64h64v64h64v-64h64v-64h-64z",
"M576 256h64v192h-64v-192z",
"M576 0h64v192h-64v-192z",
"M576 768h64v192h-64v-192z"
],
"attrs": [
{},
{},
{},
{},
{},
{},
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 16,
"tags": [
"icon-grid-snap-no"
],
"colorPermutations": {
"1161751207457516161751": [
{},
{},
{},
{},
{},
{},
{}
]
}
},
{
"id": 110,
"paths": [
"M0 64v896h1024v-896h-1024zM896 832h-768v-640h768v640z",
"M192 256h384v128h-384v-128z"
],
"attrs": [
{},
{}
],
"grid": 16,
"tags": [
"icon-frame-show"
],
"isMulticolor": false,
"isMulticolor2": false,
"colorPermutations": {
"1161751207457516161751": [
{},
{}
]
}
},
{
"id": 111,
"paths": [
"M128 190h420l104-128h-652v802.4l128-157.4z",
"M896 830h-420l-104 128h652v-802.4l-128 157.4z",
"M832-2l-832 1024h192l832-1024z",
"M392 382l104-128h-304v128z"
],
"attrs": [
{},
{},
{},
{}
],
"grid": 16,
"tags": [
"icon-frame-hide"
],
"isMulticolor": false,
"isMulticolor2": false,
"colorPermutations": {
"1161751207457516161751": [
{},
{},
{},
{}
]
}
},
{
"paths": [
"M576 64h-256l320 320h-290.256c-44.264-76.516-126.99-128-221.744-128h-128v512h128c94.754 0 177.48-51.484 221.744-128h290.256l-320 320h256l448-448-448-448z"
@@ -3442,26 +3175,6 @@
{}
]
}
},
{
"id": 108,
"paths": [
"M896 0h-768c-70.4 0-128 57.6-128 128v768c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v-768c0-70.4-57.6-128-128-128zM847.8 610.4l-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"
],
"attrs": [
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 16,
"tags": [
"icon-summary-widget"
],
"colorPermutations": {
"1161751207457516161751": [
{}
]
}
}
],
"colorThemes": [

View File

@@ -7,6 +7,8 @@
<font-face units-per-em="1024" ascent="960" descent="-64" />
<missing-glyph horiz-adv-x="1024" />
<glyph unicode="&#x20;" horiz-adv-x="512" d="" />
<glyph unicode="&#xe930;" glyph-name="icon12-crosshair" d="M597.333 938.667h-170.667v-256h170.667v256zM1024 512h-256v-170.667h256v170.667zM597.333 170.667h-170.667v-256h170.667v256zM256 512h-256v-170.667h256v170.667z" />
<glyph unicode="&#xe917;" glyph-name="icon12-eye-open" d="M512 852.667c-257.92 0-471.28-185.147-506.667-426 35.493-240.853 248.853-426 506.667-426s471.28 185.147 506.667 426c-35.387 240.853-248.747 426-506.667 426zM738.373 253.467c-131.048-109.517-321.699-109.517-452.747 0-53.328 44.749-90.832 105.477-106.96 173.2 16.101 67.707 53.565 128.435 106.853 173.2 131.048 109.517 321.699 109.517 452.747 0 53.368-44.733 90.909-105.464 107.067-173.2-16.128-67.723-53.632-128.451-106.96-173.2zM682.667 426.667c0-94.257-76.41-170.667-170.667-170.667s-170.667 76.41-170.667 170.667c0 94.257 76.41 170.667 170.667 170.667s170.667-76.41 170.667-170.667z" />
<glyph unicode="&#xe1007;" glyph-name="icon12-pane-collapse-left" horiz-adv-x="853" d="M0 938.667h170.667v-1024h-170.667v1024zM853.333 682.667h-256v256l-341.333-426.667 341.333-426.667v256h256v341.333z" />
<glyph unicode="&#xe1008;" glyph-name="icon12-pane-collapse-right" horiz-adv-x="853" d="M682.667 938.667h170.667v-1024h-170.667v1024zM0 682.667h256v256l341.333-426.667-341.333-426.667v256h-256v341.333z" />
<glyph unicode="&#xe1109;" glyph-name="icon12-folder" d="M938.667 768h-341.333l-110.32 110.32c-33.2 33.2-98.667 60.347-145.68 60.347h-256c-47.073-0.136-85.197-38.26-85.333-85.32v-341.346c0.136 47.073 38.26 85.197 85.32 85.333h853.346c47.073-0.136 85.197-38.26 85.333-85.32v170.654c-0.136 47.073-38.26 85.197-85.32 85.333zM85.333 512h853.333c47.128 0 85.333-38.205 85.333-85.333v-426.667c0-47.128-38.205-85.333-85.333-85.333h-853.333c-47.128 0-85.333 38.205-85.333 85.333v426.667c0 47.128 38.205 85.333 85.333 85.333z" />
</font></defs></svg>
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@@ -37,8 +37,6 @@
<glyph unicode="&#xe927;" glyph-name="icon-trash" d="M832 832h-192.36v64c0 35.2-28.8 64-64 64h-128c-35.2 0-64-28.8-64-64v-64h-191.64c-105.6 0-192-72-192-160s0-160 0-160h64v-384c0-105.6 86.4-192 192-192h512c105.6 0 192 86.4 192 192v384h64c0 0 0 72 0 160s-86.4 160-192 160zM320 128h-128v384h128v-384zM576 128h-128v384h128v-384zM832 128h-128v384h128v-384z" />
<glyph unicode="&#xe928;" glyph-name="icon-x" d="M384 448l-365.332-365.332c-24.89-24.89-24.89-65.62 0-90.51l37.49-37.49c24.89-24.89 65.62-24.89 90.51 0 0 0 365.332 365.332 365.332 365.332l365.332-365.332c24.89-24.89 65.62-24.89 90.51 0l37.49 37.49c24.89 24.89 24.89 65.62 0 90.51l-365.332 365.332c0 0 365.332 365.332 365.332 365.332 24.89 24.89 24.89 65.62 0 90.51l-37.49 37.49c-24.89 24.89-65.62 24.89-90.51 0 0 0-365.332-365.332-365.332-365.332l-365.332 365.332c-24.89 24.89-65.62 24.89-90.51 0l-37.49-37.49c-24.89-24.89-24.89-65.62 0-90.51 0 0 365.332-365.332 365.332-365.332z" />
<glyph unicode="&#xe929;" glyph-name="icon-brackets" d="M832 960h-192v-192h191.66l0.34-0.34v-639.32l-0.34-0.34h-191.66v-192h192c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM384 128h-191.66l-0.34 0.34v639.32l0.34 0.34h191.66v192h-192c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h192v192z" />
<glyph unicode="&#xe930;" glyph-name="icon-crosshair" d="M574 962h-128v-320h128v320zM1022 514h-320v-128h320v128zM574 258h-128v-320h128v320zM318 514h-320v-128h320v128z" />
<glyph unicode="&#xe931;" glyph-name="icon-grippy-v2" horiz-adv-x="586" d="M146.4 777.2c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM146.4 557.8c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM146.4 338.2c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM146.4 118.8c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM365.8 886.8c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM365.8 667.4c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM365.8 448c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM365.8 228.6c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM365.8 9.2c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM585.2 777.2c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM585.2 557.8c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM585.2 338.2c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2zM585.2 118.8c0-40.427-32.773-73.2-73.2-73.2s-73.2 32.773-73.2 73.2c0 40.427 32.773 73.2 73.2 73.2s73.2-32.773 73.2-73.2z" />
<glyph unicode="&#xe1000;" glyph-name="icon-arrows-out" d="M0 448l256-256v512zM512 960l-256-256h512zM512-64l256 256h-512zM768 704v-512l256 256z" />
<glyph unicode="&#xe1001;" glyph-name="icon-arrows-right-left" d="M1024 448l-448-512v1024zM448 960l-448-512 448-512z" />
<glyph unicode="&#xe1002;" glyph-name="icon-arrows-up-down" d="M512 960l512-448h-1024zM0 384l512-448 512 448z" />
@@ -81,10 +79,6 @@
<glyph unicode="&#xe1040;" glyph-name="icon-contrast" d="M512 960c-282.78 0-512-229.24-512-512s229.22-512 512-512 512 229.24 512 512-229.22 512-512 512zM783.52 176.48c-69.111-69.481-164.785-112.481-270.502-112.481-0.358 0-0.716 0-1.074 0.001l0.055 768c212.070-0.010 383.982-171.929 383.982-384 0-106.034-42.977-202.031-112.462-271.52z" />
<glyph unicode="&#xe1041;" glyph-name="icon-expand" d="M960 960c0 0 0 0 0 0h-320v-128h165.4l-210.6-210.8c-25-25-25-65.6 0-90.6 12.4-12.4 28.8-18.8 45.2-18.8s32.8 6.2 45.2 18.8l210.8 210.8v-165.4h128v384h-64zM896 154.6l-210.8 210.6c-25 25-65.6 25-90.6 0s-25-65.6 0-90.6l210.8-210.6h-165.4v-128h384v384h-128v-165.4zM218.6 832h165.4v128h-320c0 0 0 0 0 0h-64v-384h128v165.4l210.8-210.8c12.4-12.4 28.8-18.8 45.2-18.8s32.8 6.2 45.2 18.8c25 25 25 65.6 0 90.6l-210.6 210.8zM338.8 365.2l-210.8-210.6v165.4h-128v-384h384v128h-165.4l210.8 210.8c25 25 25 65.6 0 90.6-25.2 24.8-65.6 24.8-90.6-0.2z" />
<glyph unicode="&#xe1042;" glyph-name="icon-list-view" d="M0 896h1024v-128h-1024v128zM0 640h1024v-128h-1024v128zM0 384h1024v-128h-1024v128zM0 128h1024v-128h-1024v128z" />
<glyph unicode="&#xe1043;" glyph-name="icon-grid-snap-to" d="M382 130h448v448h-448v-448zM510 450h192v-192h-192v192zM-2 386h320v-64h-320v64zM894 386h128v-64h-128v64zM574 962h64v-320h-64v320zM574 66h64v-128h-64v128zM574 386h64v-64h-64v64z" />
<glyph unicode="&#xe1044;" glyph-name="icon-grid-snap-no" d="M768 384h192v-64h-192v64zM256 384h192v-64h-192v64zM0 384h192v-64h-192v64zM640 448h-64v-64h-64v-64h64v-64h64v64h64v64h-64zM576 704h64v-192h-64v192zM576 960h64v-192h-64v192zM576 192h64v-192h-64v192z" />
<glyph unicode="&#xe1045;" glyph-name="icon-frame-show" d="M0 896v-896h1024v896h-1024zM896 128h-768v640h768v-640zM192 704h384v-128h-384v128z" />
<glyph unicode="&#xe1046;" glyph-name="icon-frame-hide" d="M128 770h420l104 128h-652v-802.4l128 157.4zM896 130h-420l-104-128h652v802.4l-128-157.4zM832 962l-832-1024h192l832 1024zM392 578l104 128h-304v-128z" />
<glyph unicode="&#xe1100;" glyph-name="icon-activity" d="M576 896h-256l320-320h-290.256c-44.264 76.516-126.99 128-221.744 128h-128v-512h128c94.754 0 177.48 51.484 221.744 128h290.256l-320-320h256l448 448-448 448z" />
<glyph unicode="&#xe1101;" glyph-name="icon-activity-mode" d="M512 960c-214.866 0-398.786-132.372-474.744-320h90.744c56.86 0 107.938-24.724 143.094-64h240.906l-192 192h256l320-320-320-320h-256l192 192h-240.906c-35.156-39.276-86.234-64-143.094-64h-90.744c75.958-187.628 259.878-320 474.744-320 282.77 0 512 229.23 512 512s-229.23 512-512 512z" />
<glyph unicode="&#xe1102;" glyph-name="icon-autoflow-tabular" d="M192 960c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h64v1024h-64zM384 960h256v-1024h-256v1024zM832 960h-64v-704h256v512c0 105.6-86.4 192-192 192z" />
@@ -115,5 +109,4 @@
<glyph unicode="&#xe1127;" glyph-name="icon-timer-v1.5" horiz-adv-x="896" d="M576 813.4v82.58c0 35.346-28.654 64-64 64h-128c-35.346 0-64-28.654-64-64v-82.58c-185.040-55.080-320-226.48-320-429.42 0-247.42 200.58-448 448-448s448 200.58 448 448c0 202.96-135 374.4-320 429.42zM468 363.98l-263.76-211c-57.105 59.935-92.24 141.251-92.24 230.772 0 0.080 0 0.16 0 0.24 0 185.268 150.72 335.988 336 335.988 6.72 0 13.38-0.22 20-0.62v-355.38z" />
<glyph unicode="&#xe1128;" 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="&#xe1129;" 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="&#xe1130;" 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" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 43 KiB

After

Width:  |  Height:  |  Size: 40 KiB

View File

@@ -21,7 +21,7 @@
*****************************************************************************/
/********************************************* COLUMN LAYOUTS STYLES */
@mixin cols($totalCols, $span) {
/*@mixin cols($totalCols, $span) {
$cw: 100% / $totalCols;
min-width: (500px / $totalCols) * $span;
@if ($totalCols != $span) {
@@ -89,7 +89,7 @@
@include clearfix;
padding: $interiorMargin 0;
}
}
}*/
/********************************************* FLEX STYLES */
.l-flex-row,

View File

@@ -111,9 +111,7 @@ $bubbleMaxW: 300px;
$reqSymbolW: 15px;
$reqSymbolM: $interiorMargin * 2;
$reqSymbolFontSize: 0.75em;
$inputTextPTopBtm: 3px;
$inputTextPLeftRight: 5px;
$inputTextP: $inputTextPTopBtm $inputTextPLeftRight;
$inputTextP: 3px 5px;
/*************** Wait Spinner Defaults */
$waitSpinnerD: 32px;
$waitSpinnerTreeD: 20px;

View File

@@ -21,11 +21,32 @@
*****************************************************************************/
.t-fixed-position {
&.l-fixed-position {
@extend .abs;
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
width: auto;
height: auto;
.l-grid-holder {
position: relative;
height: 100%;
width: 100%;
.l-grid {
position: absolute;
height: 100%;
width: 100%;
pointer-events: none;
z-index: 0;
}
}
}
.l-fixed-position-item {
position: absolute;
border: 1px solid transparent;
&.s-not-selected {
opacity: 0.8;
}
@@ -84,8 +105,37 @@
}
}
}
.l-fixed-position-item-handle {
$brd: 1px solid $colorKey;
background: rgba($colorKey, 0.5);
cursor: crosshair;
border: $brd;
position: absolute;
}
}
.s-status-editing {
.l-fixed-position-item-handle.edit-corner { display: block; }
.edit-mode .t-fixed-position {
&.l-fixed-position {
.l-grid-holder {
.l-grid {
&.l-grid-x {
@include bgTicks($colorGridLines, 'x');
}
&.l-grid-y {
@include bgTicks($colorGridLines, 'y');
}
}
}
}
.l-fixed-position-item {
&:not(.s-selected) {
border: 1px dotted rgba($colorKey, 0.75);
&:hover {
border: 1px dotted rgba($colorKey, 1.0);
}
}
}
}

View File

@@ -1,24 +1,3 @@
/*****************************************************************************
* 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.
*****************************************************************************/
@mixin glyphBefore($unicode, $family: 'symbolsfont') {
&:before {
content: $unicode;
@@ -65,8 +44,6 @@ $glyph-icon-plus: '\e926';
$glyph-icon-trash: '\e927';
$glyph-icon-x: '\e928';
$glyph-icon-brackets: '\e929';
$glyph-icon-crosshair: '\e930';
$glyph-icon-grippy: '\e931';
$glyph-icon-arrows-out: '\e1000';
$glyph-icon-arrows-right-left: '\e1001';
$glyph-icon-arrows-up-down: '\e1002';
@@ -109,10 +86,6 @@ $glyph-icon-brightness: '\e1039';
$glyph-icon-contrast: '\e1040';
$glyph-icon-expand: '\e1041';
$glyph-icon-list-view: '\e1042';
$glyph-icon-grid-snap-to: '\e1043';
$glyph-icon-grid-snap-no: '\e1044';
$glyph-icon-frame-show: '\e1045';
$glyph-icon-frame-hide: '\e1046';
$glyph-icon-activity: '\e1100';
$glyph-icon-activity-mode: '\e1101';
$glyph-icon-autoflow-tabular: '\e1102';
@@ -143,7 +116,6 @@ $glyph-icon-timeline: '\e1126';
$glyph-icon-timer: '\e1127';
$glyph-icon-topic: '\e1128';
$glyph-icon-box-with-dashed-lines: '\e1129';
$glyph-icon-summary-widget: '\e1130';
/************************** 16 PX CLASSES */
@@ -177,8 +149,6 @@ $glyph-icon-summary-widget: '\e1130';
.icon-trash { @include glyphBefore($glyph-icon-trash); }
.icon-x { @include glyphBefore($glyph-icon-x); }
.icon-brackets { @include glyphBefore($glyph-icon-brackets); }
.icon-crosshair { @include glyphBefore($glyph-icon-crosshair); }
.icon-grippy { @include glyphBefore($glyph-icon-grippy); }
.icon-arrows-out { @include glyphBefore($glyph-icon-arrows-out); }
.icon-arrows-right-left { @include glyphBefore($glyph-icon-arrows-right-left); }
.icon-arrows-up-down { @include glyphBefore($glyph-icon-arrows-up-down); }
@@ -221,10 +191,6 @@ $glyph-icon-summary-widget: '\e1130';
.icon-contrast { @include glyphBefore($glyph-icon-contrast); }
.icon-expand { @include glyphBefore($glyph-icon-expand); }
.icon-list-view { @include glyphBefore($glyph-icon-list-view); }
.icon-grid-snap-to { @include glyphBefore($glyph-icon-grid-snap-to); }
.icon-grid-snap-no { @include glyphBefore($glyph-icon-grid-snap-no); }
.icon-frame-show { @include glyphBefore($glyph-icon-frame-show); }
.icon-frame-hide { @include glyphBefore($glyph-icon-frame-hide); }
.icon-activity { @include glyphBefore($glyph-icon-activity); }
.icon-activity-mode { @include glyphBefore($glyph-icon-activity-mode); }
.icon-autoflow-tabular { @include glyphBefore($glyph-icon-autoflow-tabular); }
@@ -255,8 +221,10 @@ $glyph-icon-summary-widget: '\e1130';
.icon-timer { @include glyphBefore($glyph-icon-timer); }
.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); }
/************************** 12 PX CLASSES */
.icon-crosshair-12px { @include glyphBefore($glyph-icon-crosshair,'symbolsfont-12px'); }
.icon-eye-open-12px { @include glyphBefore($glyph-icon-eye-open,'symbolsfont-12px'); }
.icon-collapse-pane-left-12px { @include glyphBefore($glyph-icon-collapse-pane-left,'symbolsfont-12px'); }
.icon-collapse-pane-right-12px { @include glyphBefore($glyph-icon-collapse-pane-right,'symbolsfont-12px'); }
.icon-folder-12px { @include glyphBefore($glyph-icon-folder,'symbolsfont-12px'); }

View File

@@ -0,0 +1,39 @@
@mixin limitGlyph($iconColor, $glyph: $glyph-icon-alert-triangle) {
&:before {
color: $iconColor;
content: $glyph;
font-family: symbolsfont;
font-size: 0.8em;
display: inline;
margin-right: $interiorMarginSm;
}
}
.s-limit-red { background: $colorLimitRedBg !important; }
.s-limit-yellow { background: $colorLimitYellowBg !important; }
// Handle limit when applied to a tr
tr[class*="s-limit"] {
&.s-limit-red td:first-child {
@include limitGlyph($colorLimitRedIc);
}
&.s-limit-yellow td:first-child {
@include limitGlyph($colorLimitYellowIc);
}
&.s-limit-upr td:first-child:before { content: $glyph-icon-arrow-double-up; }
&.s-limit-lwr td:first-child:before { content: $glyph-icon-arrow-double-down; }
}
// Handle limit when applied directly to a non-tr element
// Assume this is applied to the element that displays the limit value
:not(tr)[class*="s-limit"] {
&.s-limit-red {
@include limitGlyph($colorLimitRedIc);
}
&.s-limit-yellow {
@include limitGlyph($colorLimitYellowIc);
}
&.s-limit-upr:before { content: $glyph-icon-arrow-double-up; }
&.s-limit-lwr:before { content: $glyph-icon-arrow-double-down; }
}

View File

@@ -27,7 +27,7 @@
@import "about";
@import "text";
@import "icons";
@import "status";
@import "limits";
@import "data-status";
@import "helpers/bubbles";
@import "helpers/splitter";

View File

@@ -316,25 +316,23 @@
text-shadow: $shdwItemText;
}
@mixin input-base() {
@mixin input-base($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
@include appearance(none);
border-radius: $controlCr;
box-sizing: border-box;
&:focus { outline: 0; }
box-shadow: inset $shdw;
background: $bg;
border: none;
color: $fg;
outline: none;
&.error {
background-color: $colorFormFieldErrorBg;
color: $colorFormFieldErrorFg;
}
}
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
@include input-base();
background: $bg;
box-shadow: inset $shdw;
border: none;
color: $fg;
outline: none;
padding: $inputTextPTopBtm $inputTextPLeftRight;
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg) {
@include input-base($bg, $fg);
}
@mixin contextArrow() {
@@ -346,7 +344,7 @@
}
@mixin nice-textarea($bg: $colorBodyBg, $fg: $colorBodyFg) {
@include nice-input($bg, $fg);
@include input-base($bg, $fg);
padding: $interiorMargin;
}

View File

@@ -1,86 +0,0 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*************************************************** MIXINS */
@mixin formulateStatusColors($c) {
// Sets bg and icon colors for elements
background: rgba($c, 0.4) !important;
&:before { color: $c !important; }
}
/*************************************************** GENERAL */
.s-limit-yellow,
.s-limit-red,
.s-limit-yellow-icon,
.s-limit-red-icon,
.s-status-warning-lo,
.s-status-warning-hi,
.s-status-diagnostic,
.s-status-command,
.s-status-info,
.s-status-ok,
.s-status-warning-lo-icon,
.s-status-warning-hi-icon,
.s-status-diagnostic-icon,
.s-status-command-icon,
.s-status-info-icon,
.s-status-ok-icon {
@include trans-prop-nice($props: background, $dur: 500ms);
&:before {
content:'';
font-family: symbolsfont;
font-size: 0.8em;
display: inline;
margin-right: $interiorMarginSm;
}
}
/*************************************************** LIMITS */
.s-limit-yellow, .s-limit-yellow-icon {
@include formulateStatusColors($colorWarningLo);
}
.s-limit-red, .s-limit-red-icon {
@include formulateStatusColors($colorWarningHi);
}
.s-limit-upr:before { content: $glyph-icon-arrow-double-up; }
.s-limit-lwr:before { content: $glyph-icon-arrow-double-down; }
.s-limit-yellow-icon:before,
.s-limit-red-icon:before { content: $glyph-icon-alert-triangle; }
/*************************************************** STATUS */
.s-status-warning-hi, .s-status-warning-hi-icon { @include formulateStatusColors($colorWarningHi); }
.s-status-warning-lo, .s-status-warning-lo-icon { @include formulateStatusColors($colorWarningLo); }
.s-status-diagnostic, .s-status-diagnostic-icon { @include formulateStatusColors($colorDiagnostic); }
.s-status-info, .s-status-info-icon { @include formulateStatusColors($colorInfo); }
.s-status-ok, .s-status-ok-icon { @include formulateStatusColors($colorOk); }
.s-status-warning-hi-icon:before { content: $glyph-icon-alert-triangle; }
.s-status-warning-lo-icon:before { content: $glyph-icon-alert-rect; }
.s-status-diagnostic-icon:before { content: $glyph-icon-eye-open; }
.s-status-info-icon:before { content: $glyph-icon-info; }
.s-status-ok-icon:before { content: $glyph-icon-check; }

View File

@@ -72,15 +72,6 @@
}
}
.s-hyperlink {
// Hyperlink objects
&:not(.s-button) {
color: $colorKey;
font-size: 0.8rem;
&:hover { color: $colorKeyHov; }
}
}
.s-icon-button {
// Clickable icon elements that have hover
@extend .ui-symbol;
@@ -243,24 +234,6 @@ input[type="number"] {
}
}
span[contenteditable].s-inline-edit {
@include trans-prop-nice((padding), 250ms);
@include input-base();
border: 1px solid transparent;
min-width: 20px;
&:hover {
border-color: rgba($colorBodyFg, 0.2);
padding-left: $inputTextPLeftRight;
padding-right: $inputTextPLeftRight;
}
}
span[contenteditable].s-inline-edit.s-status-editing {
@include nice-input();
vertical-align: baseline;
padding: 0 $inputTextPLeftRight;
}
.l-input-sm {
input[type="text"],
input[type="search"],
@@ -722,6 +695,11 @@ textarea {
}
}
.view-switcher,
.t-btn-view-large {
@include trans-prop-nice-fade($controlFadeMs);
}
/******************************************************** BROWSER ELEMENTS */
body.desktop {
::-webkit-scrollbar {

View File

@@ -39,7 +39,7 @@
// Status coloring
.ok, .info {
.status-indicator {
color: $colorInfo;
color: $colorStatusInfo;
}
}
@@ -224,15 +224,15 @@
}
&.ok,
&.info {
@include statusBannerColors($colorInfo);
@include statusBannerColors($colorStatusInfo);
}
&.caution,
&.warning,
&.alert {
@include statusBannerColors($colorWarningLo);
@include statusBannerColors($colorStatusAlert);
}
&.error {
@include statusBannerColors($colorWarningHi);
@include statusBannerColors($colorStatusError);
}
}
@@ -248,15 +248,15 @@
.message-severity-info .type-icon.message-type {
@extend .icon-info;
color: $colorInfo;
color: $colorStatusInfo;
}
.message-severity-alert .type-icon.message-type {
@extend .icon-bell;
color: $colorWarningLo;
color: $colorStatusAlert;
}
.message-severity-error .type-icon.message-type {
@extend .icon-alert-rect;
color: $colorWarningHi;
color: $colorStatusError;
}
}
/* Paths:

View File

@@ -19,24 +19,12 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
.t-edit-handle-holder { display: none; }
.l-grid-holder {
display: none;
position: relative;
height: 100%;
width: 100%;
.l-grid {
@extend .abs;
pointer-events: none;
z-index: 0;
&.l-grid-y { background-position: 0 1px; }
}
}
.s-status-editing {
$handleD: 5px;
.t-edit-handle-holder { display: block; }
.s-status-editing .l-object-wrapper,
.edit-main {
// .s-status-editing .l-object-wrapper is relevant to New Edit Mode;
// .edit-main is legacy for old edit mode.
$handleD: 15px;
$cr: 5px;
.edit-corner,
.edit-handle {
position: absolute;
@@ -44,59 +32,81 @@
}
.edit-corner {
background: rgba($colorSelectableSelectedPrimary, 0.5);
cursor: crosshair;
display: none; // Hide by default
border: 1px solid $colorSelectableSelectedPrimary;
width: $handleD;
height: $handleD;
$o: (-1 * $handleD) + 1px;
&:hover {
z-index: 11;
}
&.edit-resize-nw { top: $o; left: $o; }
&.edit-resize-ne { top: $o; right: $o; }
&.edit-resize-se { bottom: $o; right: $o; }
&.edit-resize-sw { bottom: $o; left: $o; }
&.edit-resize-nw {
border-bottom-right-radius: $cr;
cursor: nw-resize;
top: 0; left: 0;
}
&.edit-resize-ne {
border-bottom-left-radius: $cr;
cursor: ne-resize;
top: 0; right: 0;
}
&.edit-resize-se {
border-top-left-radius: $cr;
cursor: se-resize;
bottom: 0; right: 0;
}
&.edit-resize-sw {
border-top-right-radius: $cr;
cursor: sw-resize;
bottom: 0; left: 0;
}
}
.edit-handle.edit-move {
// main move box for the whole frame element
$m: 0;
left: $m;
right: $m;
top: $m;
bottom: $m;
z-index: 1;
.edit-handle {
top: $handleD; right: $handleD; bottom: $handleD; left: $handleD;
&.edit-move {
$m: 0; //$handleD;
cursor: move;
left: $m;
right: $m;
top: $m;
bottom: $m;
z-index: 1;
}
&.edit-resize-n {
top: 0px; bottom: auto;
height: $handleD;
cursor: n-resize;
}
&.edit-resize-e {
right: 0px; left: auto;
width: $handleD;
cursor: e-resize;
}
&.edit-resize-s {
bottom: 0px; top: auto;
height: $handleD;
cursor: s-resize;
}
&.edit-resize-w {
left: 0px; right: auto;
width: $handleD;
cursor: w-resize;
}
}
.frame.child-frame.panel {
&:hover {
@include boxShdwLarge();
border-color: $colorSelectableSelectedPrimary;
.view-switcher {
opacity: 1;
}
.edit-corner {
background-color: rgba($colorKey, 0.8);
&:hover {
background-color: rgba($colorKey, 1);
}
}
}
}
// Editing Grids
.l-grid-holder {
display: block;
.l-grid {
&.l-grid-x { @include bgTicks($colorGridLines, 'x'); }
&.l-grid-y { @include bgTicks($colorGridLines, 'y'); }
}
}
// Prevent nested frames from showing their grids
.t-frame-outer .l-grid-holder { display: none !important; }
// Prevent nested elements from showing s-hover-border
.t-frame-outer .s-hover-border {
border: none !important;
}
// Prevent nested frames from being selectable until we have proper sub-object editing
.t-frame-outer .t-frame-outer {
pointer-events: none;
}
}

View File

@@ -129,6 +129,9 @@
}
.s-filter {
input[type="search"] {
@include input-base();
}
.clear-icon,
.menu-icon,
&:before {

View File

@@ -193,7 +193,6 @@
@include animToParams(overlayIn, $dur: $durLargeViewExpand, $delay: 0);
background: $colorBodyBg;
z-index: 101;
.abs.inner-holder {
opacity: 0;
@@ -204,19 +203,10 @@
@include animToParams(contentsIn, $dur: 50ms, $delay: $durLargeViewExpand * 1.25);
}
// Hide View Large button
.t-btn-view-large {
display: none;
}
// But show View Large button when it's nested inside a Layout
.t-frame-inner .t-frame-inner .t-btn-view-large { display: block; }
}
}
// When multiple Large Views are visible, hide the blocker for all but the first
& + .l-large-view {
.blocker {
display: none;
z-index: 101;
}
}
}

View File

@@ -23,43 +23,28 @@
$ohH: $btnFrameH;
$bc: $colorInteriorBorder;
&.child-frame.panel {
background: $colorBodyBg;
border: 1px solid $bc;
z-index: 0; // Needed to prevent child-frame controls from showing through when another child-frame is above
&:not(.no-frame) {
background: $colorBodyBg;
border: 1px solid $bc;
&:hover {
border-color: lighten($bc, 10%);
}
&:hover {
border-color: lighten($bc, 10%);
}
}
.object-browse-bar {
font-size: 0.75em;
height: $ohH;
line-height: $ohH;
.right {
@include trans-prop-nice-fade($controlFadeMs);
padding-left: $interiorMargin;
}
}
&.t-object-type-timer,
&.t-object-type-clock,
&.t-object-type-hyperlink {
// 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.
.object-browse-bar .right { display: none; }
}
> .object-holder.abs {
top: $ohH + $interiorMargin;
}
.contents {
$m: $interiorMargin;
top: $m;
right: $m;
bottom: $m;
left: $m;
$myM: $interiorMargin;
top: $myM;
right: $myM;
bottom: $myM;
left: $myM;
}
&.frame-template {
.s-button,
@@ -82,67 +67,19 @@
}
}
.view-switcher {
margin-right: $interiorMargin; // Kick other top bar elements away when I'm present.
margin-left: $interiorMargin; // Kick other top bar elements away when I'm present.
// Hide the name when the view switcher is in a frame context
.title-label {
display: none;
}
}
&.no-frame {
background: transparent !important;
border: none !important;
.object-browse-bar .right {
$m: 0; // $interiorMarginSm;
background: rgba(black, 0.3);
border-radius: $basicCr;
padding: $interiorMarginSm;
position: absolute;
top: $m; right: $m;
z-index: 2;
}
&.t-frame-outer > .t-rep-frame {
&.contents {
$m: 2px;
top: $m;
right: $m;
bottom: $m;
left: $m;
}
> .t-frame-inner {
> .object-browse-bar .left {
display: none;
}
> .object-holder.abs {
top: 0 !important;
}
}
}
}
/********************************************************** OBJECT TYPES */
.t-object-type-hyperlink {
.s-hyperlink.s-button {
// When a hyperlink is a button in a frame, make it expand to fill out to the object-holder
@extend .abs;
.label {
@include ellipsize();
@include transform(translateY(-50%));
padding: 0 $interiorMargin;
position: absolute;
min-width: 0;
left: 0; right: 0;
text-align: center;
top: 50%;
}
}
}
}
body.desktop .frame {
// Hide local controls initially and show it them on hover when they're in an element that's in a frame context
// Frame template is used because we need to target the lowest nested frame
.right {
.view-switcher,
.t-btn-view-large {
opacity: 0;
pointer-events: none;
}
@@ -150,7 +87,8 @@ body.desktop .frame {
// Target the first descendant so that we only show the elements in the outermost container.
// Handles the case where we have layouts in layouts.
&:hover > .object-browse-bar {
.right {
.view-switcher,
.t-btn-view-large {
opacity: 1;
pointer-events: inherit;
}

View File

@@ -19,36 +19,21 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
.s-hover-border {
border: 1px dotted transparent;
}
.s-selectable {
border: 1px solid transparent;
.s-status-editing {
// Limit to editing mode until we have sub-object selection
.s-hover-border {
// Show a border by default so user can see object bounds and empty objects
border: 1px dotted rgba($colorSelectableSelectedPrimary, 0.3) !important;
&:hover {
border-color: rgba($colorSelectableSelectedPrimary, 0.7) !important;
}
&.s-hover {
// Styles when hovering over a selectable object
border-color: $colorSelectableHov !important;
}
.s-selected > .s-hover-border,
.s-selected.s-hover-border {
&.s-selected {
// Styles for a selected object. Also used by legacy Fixed Position/Panel objects.
border-color: $colorSelectableSelectedPrimary !important;
@include boxShdwLarge();
// Show edit-corners if you got 'em
.edit-corner {
display: block;
&:hover {
background-color: rgba($colorKey, 1);
}
}
}
.s-selected > .s-moveable,
.s-selected.s-moveable {
&.s-moveable {
@include boxShdwLarge();
cursor: move;
}
}
}

View File

@@ -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"
<span class="t-filter l-filter s-filter"
ng-controller="GetterSetterController">
<input type="search"
class="t-filter-input"

View File

@@ -93,21 +93,13 @@ define(
* @memberof platform/commonUI/general
* @constructor
*/
function MCTSplitPane($parse, $log, $interval, $window) {
function MCTSplitPane($parse, $log, $interval) {
function controller($scope, $element, $attrs) {
var anchorKey = $attrs.anchor || DEFAULT_ANCHOR,
positionParsed = $parse($attrs.position),
anchor,
activeInterval,
position,
splitterSize,
alias = $attrs.alias !== undefined ?
"mctSplitPane-" + $attrs.alias : undefined,
//convert string to number from localStorage
userWidthPreference = $window.localStorage.getItem(alias) === null ?
undefined : Number($window.localStorage.getItem(alias));
positionParsed = $parse($attrs.position),
position; // Start undefined, until explicitly set
// Get relevant size (height or width) of DOM element
function getSize(domElement) {
@@ -117,20 +109,16 @@ define(
// Apply styles to child elements
function updateChildren(children) {
if (alias) {
position = userWidthPreference || position;
}
// Pick out correct elements to update, flowing from
// selected anchor edge.
var first = children.eq(anchor.reversed ? 2 : 0),
splitter = children.eq(1),
last = children.eq(anchor.reversed ? 0 : 2),
splitterSize = getSize(splitter[0]),
firstSize;
splitterSize = getSize(splitter[0]);
first.css(anchor.edge, "0px");
first.css(anchor.dimension, position + 'px');
first.css(anchor.dimension, (position - splitterSize) + 'px');
// Get actual size (to obey min-width etc.)
firstSize = getSize(first[0]);
@@ -138,9 +126,10 @@ define(
splitter.css(anchor.edge, firstSize + 'px');
splitter.css(anchor.opposite, "auto");
last.css(anchor.edge, firstSize + splitterSize + 'px');
last.css(anchor.opposite, '0px');
position = firstSize;
last.css(anchor.edge, (firstSize + splitterSize) + 'px');
last.css(anchor.opposite, "0px");
position = firstSize + splitterSize;
}
// Update positioning of contained elements
@@ -177,20 +166,9 @@ define(
positionParsed.assign($scope, position);
}
}
return position;
}
function setUserWidthPreference(value) {
userWidthPreference = value;
}
function persistToLocalStorage(value) {
if (alias) {
$window.localStorage.setItem(alias, value);
}
}
// Dynamically apply a CSS class to elements when the user
// is actively resizing
function toggleClass(classToToggle) {
@@ -218,31 +196,18 @@ define(
activeInterval = $interval(function () {
getSetPosition(getSetPosition());
}, POLLING_INTERVAL, 0, false);
// ...and stop polling when we're destroyed.
$scope.$on('$destroy', function () {
$interval.cancel(activeInterval);
});
// Interface exposed by controller, for mct-splitter to user
return {
position: getSetPosition,
toggleClass: toggleClass,
anchor: function () {
return anchor;
},
position: function (newPosition) {
if (arguments.length === 0) {
return getSetPosition();
}
setUserWidthPreference(newPosition);
return getSetPosition(newPosition);
},
startResizing: function () {
toggleClass('resizing');
},
endResizing: function (finalPosition) {
persistToLocalStorage(finalPosition);
toggleClass('resizing');
}
};
}
@@ -254,7 +219,9 @@ define(
controller: ['$scope', '$element', '$attrs', controller]
};
}
return MCTSplitPane;
}
);

View File

@@ -37,16 +37,15 @@ define(
*/
function MCTSplitter() {
function link(scope, element, attrs, mctSplitPane) {
var initialPosition,
newPosition;
var initialPosition;
element.addClass("splitter");
scope.splitter = {
// Begin moving this splitter
startMove: function () {
mctSplitPane.startResizing();
initialPosition = mctSplitPane.position();
mctSplitPane.toggleClass('resizing');
},
// Handle user changes to splitter position
move: function (delta) {
@@ -56,16 +55,12 @@ define(
(anchor.reversed ? -1 : 1);
// Update the position of this splitter
newPosition = initialPosition + pixelDelta;
if (initialPosition !== newPosition) {
mctSplitPane.position(newPosition);
}
mctSplitPane.position(initialPosition + pixelDelta);
},
// Grab the event when the user is done moving
// the splitter and pass it on
endMove: function () {
mctSplitPane.endResizing(newPosition);
mctSplitPane.toggleClass('resizing');
}
};
}
@@ -88,3 +83,4 @@ define(
}
);

View File

@@ -38,8 +38,7 @@ define(
mockLog,
mockInterval,
mockParsed,
mctSplitPane,
mockWindow = {};
mctSplitPane;
beforeEach(function () {
mockParse = jasmine.createSpy('$parse');
@@ -49,23 +48,13 @@ define(
mockInterval.cancel = jasmine.createSpy('mockCancel');
mockParsed = jasmine.createSpy('parsed');
mockParsed.assign = jasmine.createSpy('assign');
mockParse.andReturn(mockParsed);
mockWindow.localStorage = {
store: {},
setItem: function (key, value) {
this.store[key] = value;
},
getItem: function (key) {
return this.store[key];
}
};
mockParse.andReturn(mockParsed);
mctSplitPane = new MCTSplitPane(
mockParse,
mockLog,
mockInterval,
mockWindow
mockInterval
);
});
@@ -96,7 +85,7 @@ define(
jasmine.createSpyObj('$scope', ['$apply', '$watch', '$on']);
mockElement =
jasmine.createSpyObj('element', JQLITE_METHODS);
testAttrs = {alias: 'rightSide'};
testAttrs = {};
mockChildren =
jasmine.createSpyObj('children', JQLITE_METHODS);
mockFirstPane =
@@ -140,7 +129,7 @@ define(
it("exposes its splitter's initial position", function () {
expect(controller.position()).toEqual(
mockFirstPane[0].offsetWidth
mockFirstPane[0].offsetWidth + mockSplitter[0].offsetWidth
);
});
@@ -153,14 +142,10 @@ define(
});
});
it("applies resizing class to children when resizing", function () {
controller.startResizing();
expect(mockChildren.toggleClass).toHaveBeenCalledWith('resizing');
});
it("removes resizing class from children when resizing action ends", function () {
controller.endResizing(0);
expect(mockChildren.toggleClass).toHaveBeenCalledWith('resizing');
it("allows classes to be toggled on contained elements", function () {
controller.toggleClass('resizing');
expect(mockChildren.toggleClass)
.toHaveBeenCalledWith('resizing');
});
it("allows positions to be set", function () {
@@ -168,7 +153,7 @@ define(
controller.position(testValue);
expect(mockFirstPane.css).toHaveBeenCalledWith(
'width',
(testValue) + 'px'
(testValue - mockSplitter[0].offsetWidth) + 'px'
);
});
@@ -200,11 +185,11 @@ define(
mockFirstPane[0].offsetWidth += 100;
// Should not reflect the change yet
expect(controller.position()).not.toEqual(
mockFirstPane[0].offsetWidth
mockFirstPane[0].offsetWidth + mockSplitter[0].offsetWidth
);
mockInterval.mostRecentCall.args[0]();
expect(controller.position()).toEqual(
mockFirstPane[0].offsetWidth
mockFirstPane[0].offsetWidth + mockSplitter[0].offsetWidth
);
});
@@ -213,12 +198,6 @@ define(
fireOn('$destroy');
expect(mockInterval.cancel).toHaveBeenCalled();
});
it("saves user preference to localStorage when user is done resizing", function () {
controller.endResizing(100);
expect(Number(mockWindow.localStorage.getItem('mctSplitPane-rightSide'))).toEqual(100);
});
});
});

View File

@@ -57,7 +57,7 @@ define(
testAttrs = {};
mockSplitPane = jasmine.createSpyObj(
'mctSplitPane',
['position', 'startResizing', 'endResizing', 'anchor']
['position', 'toggleClass', 'anchor']
);
mctSplitter.link(
@@ -86,9 +86,9 @@ define(
mockScope.splitter.startMove();
});
it("tell's the splitter when it is resizing", function () {
expect(mockSplitPane.startResizing)
.toHaveBeenCalled();
it("adds a 'resizing' class", function () {
expect(mockSplitPane.toggleClass)
.toHaveBeenCalledWith('resizing');
});
it("repositions during drag", function () {
@@ -97,10 +97,11 @@ define(
.toHaveBeenCalledWith(testPosition + 10);
});
it("tell's the splitter when it is done resizing", function () {
mockScope.splitter.move([10,0]);
it("removes the 'resizing' class when finished", function () {
mockSplitPane.toggleClass.reset();
mockScope.splitter.endMove();
expect(mockSplitPane.endResizing).toHaveBeenCalledWith(testPosition + 10);
expect(mockSplitPane.toggleClass)
.toHaveBeenCalledWith('resizing');
});
});

View File

@@ -53,15 +53,9 @@ $timeControllerToiLineColor: #00c2ff;
$timeControllerToiLineColorHov: #fff;
$colorTransLucBg: #666; // Used as a visual blocking element over variable backgrounds, like imagery
// Foundation Colors
// General Colors
$colorAlt1: #ffc700;
$colorAlert: #ff3c00;
$colorWarningHi: #cc0000;
$colorWarningLo: #ff9900;
$colorDiagnostic: #a4b442;
$colorCommand: #3693bd;
$colorInfo: #2294a2;
$colorOk: #33cc33;
$colorIconLink: #49dedb;
$colorPausedBg: #c56f01;
$colorPausedFg: #fff;
@@ -90,8 +84,8 @@ $colorCreateMenuText: $colorMenuFg;
// Form colors
$colorCheck: $colorKey;
$colorFormRequired: $colorAlt1;
$colorFormValid: $colorOk;
$colorFormError: $colorWarningHi;
$colorFormValid: #33cc33;
$colorFormError: #990000;
$colorFormInvalid: #ff3300;
$colorFormFieldErrorBg: $colorFormError;
$colorFormFieldErrorFg: rgba(#fff, 0.6);
@@ -115,8 +109,8 @@ $colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%);
// Status colors, mainly used for messaging and item ancillary symbols
$colorStatusFg: #ccc;
$colorStatusDefault: #ccc;
$colorStatusInfo: $colorInfo;
$colorStatusAlert: $colorAlert;
$colorStatusInfo: #62ba72;
$colorStatusAlert: #ffa66d;
$colorStatusError: #d4585c;
$colorStatusAvailable: $colorKey;
$colorStatusBtnBg: $colorBtnBg;
@@ -131,14 +125,14 @@ $animPausedPulseDur: 500ms;
$colorSelectBg: $colorBtnBg;
$colorSelectFg: $colorBtnFg;
// Limits, status and staleness colors
// Limits and staleness colors
$colorTelemFresh: pullForward($colorBodyFg, 20%);
$colorTelemStale: pushBack($colorBodyFg, 20%);
$styleTelemStale: italic;
$colorLimitYellowBg: rgba($colorWarningLo, 0.3);
$colorLimitYellowIc: $colorWarningLo;
$colorLimitRedBg: rgba($colorWarningHi, 0.3);
$colorLimitRedIc: $colorWarningHi;
$colorLimitYellowBg: rgba(#ffaa00, 0.3);
$colorLimitYellowIc: #ffaa00;
$colorLimitRedBg: rgba(red, 0.3);
$colorLimitRedIc: red;
// Bubble colors
$colorInfoBubbleBg: #ddd;

View File

@@ -13,10 +13,3 @@
// For dark interfaces, darker things move back - opposite for light interfaces
@return darken($c, $p);
}
@function bgFg($c) {
// Given a single color, return valid background and foreground versions of that color
$bg: darken($c, 20%);
$fg: lighten($c, 20%);
@return $bg, $fg;
}

View File

@@ -53,15 +53,9 @@ $timeControllerToiLineColor: $colorBodyFg;
$timeControllerToiLineColorHov: #0052b5;
$colorTransLucBg: #666; // Used as a visual blocking element over variable backgrounds, like imagery
// Foundation Colors
// General Colors
$colorAlt1: #776ba2;
$colorAlert: #ff3c00;
$colorWarningHi: #990000;
$colorWarningLo: #ff9900;
$colorDiagnostic: #a4b442;
$colorCommand: #3693bd;
$colorInfo: #2294a2;
$colorOk: #33cc33;
$colorIconLink: #49dedb;
$colorPausedBg: #ff9900;
$colorPausedFg: #fff;
@@ -90,8 +84,8 @@ $colorCreateMenuText: $colorBodyFg;
// Form colors
$colorCheck: $colorKey;
$colorFormRequired: $colorKey;
$colorFormValid: $colorOk;
$colorFormError: $colorWarningHi;
$colorFormValid: #33cc33;
$colorFormError: #990000;
$colorFormInvalid: #ff2200;
$colorFormFieldErrorBg: $colorFormError;
$colorFormFieldErrorFg: rgba(#fff, 0.6);
@@ -113,7 +107,7 @@ $colorInspectorSectionHeaderBg: pullForward($colorInspectorBg, 5%);
$colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%);
// Status colors, mainly used for messaging and item ancillary symbols
$colorStatusFg: #999;
$colorStatusFg: #fff;
$colorStatusDefault: #ccc;
$colorStatusInfo: #60ba7b;
$colorStatusAlert: #ffb66c;

View File

@@ -12,11 +12,3 @@
// For dark interfaces, darker things move back - opposite for light interfaces
@return lighten($c, $p);
}
@function bgFg($c) {
// Given a single color, return valid background and foreground versions of that color
$bg: darken($c, 20%);
$fg: lighten($c, 20%);
@return $bg, $fg;
}

View File

@@ -65,20 +65,6 @@ define(['csv'], function (CSV) {
this.saveAs(blob, filename);
};
/**
* Export an object as a JSON file. Triggers a download using the function
* provided when the ExportService was instantiated.
*
* @param {Object} obj an object to be exported as JSON
* @param {ExportOptions} [options] additional parameters for the file
* export
*/
ExportService.prototype.exportJSON = function (obj, options) {
var filename = (options && options.filename) || "test-export.json";
var jsonText = JSON.stringify(obj);
var blob = new Blob([jsonText], {type: "application/json"});
this.saveAs(blob, filename);
};
/**
* Additional parameters for file export.
* @typedef ExportOptions

View File

@@ -1,120 +0,0 @@
/*****************************************************************************
* 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/HyperlinkController',
'legacyRegistry',
'text!./res/templates/hyperlink.html'
], function (
HyperlinkController,
legacyRegistry,
hyperlinkTemplate
) {
legacyRegistry.register("platform/features/hyperlink", {
"name": "Hyperlink",
"description": "Insert a hyperlink to reference a link",
"extensions": {
"types": [
{
"key": "hyperlink",
"name": "Hyperlink",
"cssClass": "icon-chain-links",
"description": "A hyperlink to redirect to a different link",
"features": ["creation"],
"properties": [
{
"key": "url",
"name": "URL",
"control": "textfield",
"pattern": "^(ftp|https?)\\:\\/\\/",
"required": true,
"cssClass": "l-input-lg"
},
{
"key": "displayText",
"name": "Text to Display",
"control": "textfield",
"required": true,
"cssClass": "l-input-lg"
},
{
"key": "displayFormat",
"name": "Display Format",
"control": "select",
"options": [
{
"name": "Link",
"value": "link"
},
{
"value": "button",
"name": "Button"
}
],
"cssClass": "l-inline"
},
{
"key": "openNewTab",
"name": "Tab to Open Hyperlink",
"control": "select",
"options": [
{
"name": "Open in this tab",
"value": "thisTab"
},
{
"value": "newTab",
"name": "Open in a new tab"
}
],
"cssClass": "l-inline"
}
],
"model": {
"displayFormat": "link",
"openNewTab": "thisTab",
"removeTitle": true
}
}
],
"views": [
{
"key": "hyperlink",
"type": "hyperlink",
"name": "Hyperlink Display",
"template": hyperlinkTemplate,
"editable": false
}
],
"controllers": [
{
"key": "HyperlinkController",
"implementation": HyperlinkController,
"depends": ["$scope"]
}
]
}
});
});

View File

@@ -1,28 +0,0 @@
<!--
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.
-->
<a class="s-hyperlink" ng-controller="HyperlinkController as hyperlink" href="{{domainObject.getModel().url}}"
ng-attr-target="{{hyperlink.openNewTab() ? '_blank' : undefined}}"
ng-class="{
's-button': hyperlink.isButton()
}">
<div class="label">{{domainObject.getModel().displayText}}</div>
</a>

View File

@@ -1,58 +0,0 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/**
* This bundle adds the Hyperlink object type, which can be used to add hyperlinks as a domain Object type
and into display Layouts as either a button or link that can be chosen to open in either the same tab or
create a new tab to open the link in
* @namespace platform/features/hyperlink
*/
define(
[],
function () {
function HyperlinkController($scope) {
this.$scope = $scope;
}
/**Function to analyze the location in which to open the hyperlink
@returns true if the hyperlink is chosen to open in a different tab, false if the same tab
**/
HyperlinkController.prototype.openNewTab = function () {
if (this.$scope.domainObject.getModel().openNewTab === "thisTab") {
return false;
} else {
return true;
}
};
/**Function to specify the format in which the hyperlink should be created
@returns true if the hyperlink is chosen to be created as a button, false if a link
**/
HyperlinkController.prototype.isButton = function () {
if (this.$scope.domainObject.getModel().displayFormat === "link") {
return false;
}
return true;
};
return HyperlinkController;
}
);

View File

@@ -1,89 +0,0 @@
/*****************************************************************************
* 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/HyperlinkController"],
function (HyperlinkController) {
describe("The controller for hyperlinks", function () {
var domainObject,
controller,
scope;
beforeEach(function () {
scope = jasmine.createSpyObj(
"$scope",
["domainObject"]
);
domainObject = jasmine.createSpyObj(
"domainObject",
["getModel"]
);
scope.domainObject = domainObject;
controller = new HyperlinkController(scope);
});
it("knows when it should open a new tab", function () {
scope.domainObject.getModel.andReturn({
"displayFormat": "link",
"openNewTab": "newTab",
"showTitle": false
}
);
controller = new HyperlinkController(scope);
expect(controller.openNewTab())
.toBe(true);
});
it("knows when it is a button", function () {
scope.domainObject.getModel.andReturn({
"displayFormat": "button",
"openNewTab": "thisTab",
"showTitle": false
}
);
controller = new HyperlinkController(scope);
expect(controller.isButton())
.toEqual(true);
});
it("knows when it should open in the same tab", function () {
scope.domainObject.getModel.andReturn({
"displayFormat": "link",
"openNewTab": "thisTab",
"showTitle": false
}
);
controller = new HyperlinkController(scope);
expect(controller.openNewTab())
.toBe(false);
});
it("knows when it is a link", function () {
scope.domainObject.getModel.andReturn({
"displayFormat": "link",
"openNewTab": "thisTab",
"showTitle": false
}
);
controller = new HyperlinkController(scope);
expect(controller.openNewTab())
.toBe(false);
});
});
}
);

View File

@@ -62,29 +62,7 @@ define([
"type": "layout",
"template": layoutTemplate,
"editable": true,
"uses": [],
"toolbar": {
"sections": [
{
"items": [
{
"method": "showFrame",
"cssClass": "icon-frame-show",
"control": "button",
"title": "Show frame",
"description": "Show frame"
},
{
"method": "hideFrame",
"cssClass": "icon-frame-hide",
"control": "button",
"title": "Hide frame",
"description": "Hide frame"
}
]
}
]
}
"uses": []
},
{
"key": "fixed",

View File

@@ -25,20 +25,15 @@
<!-- Background grid -->
<div class="l-grid-holder" ng-click="controller.clearSelection()">
<div class="l-grid l-grid-x"
ng-if="!controller.getGridSize()[0] < 3"
ng-style="{ 'background-size': controller.getGridSize() [0] + 'px 100%' }"></div>
<div class="l-grid l-grid-y"
ng-if="!controller.getGridSize()[1] < 3"
ng-style="{ 'background-size': '100% ' + controller.getGridSize() [1] + 'px' }"></div>
</div>
<!-- Fixed position elements -->
<div ng-repeat="element in controller.getElements()"
class="l-fixed-position-item s-selectable s-moveable s-hover-border"
ng-class="{
's-not-selected': controller.selected() && !controller.selected(element),
's-selected': controller.selected(element)
}"
class="l-fixed-position-item"
ng-class="{ 's-not-selected': controller.selected() && !controller.selected(element) }"
ng-style="element.style"
ng-click="controller.select(element)">
<mct-include key="element.template"
@@ -48,15 +43,15 @@
</div>
<!-- Selection highlight, handles -->
<span class="s-selected s-moveable" ng-if="controller.selected()">
<div class="l-fixed-position-item t-edit-handle-holder"
<span ng-if="controller.selected()">
<div class="l-fixed-position-item s-selectable s-selected s-moveable"
mct-drag-down="controller.moveHandle().startDrag(controller.selected())"
mct-drag="controller.moveHandle().continueDrag(delta)"
mct-drag-up="controller.moveHandle().endDrag()"
ng-style="controller.selected().style">
</div>
<div ng-repeat="handle in controller.handles()"
class="l-fixed-position-item-handle edit-corner"
class="l-fixed-position-item-handle"
ng-style="handle.style()"
mct-drag-down="handle.startDrag()"
mct-drag="handle.continueDrag(delta)"

View File

@@ -19,31 +19,25 @@
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 abs">
<div class="abs object-browse-bar l-flex-row">
<div class="left flex-elem l-flex-row grows">
<mct-representation
key="'object-header'"
mct-object="domainObject"
class="l-flex-row flex-elem object-header grows">
key="'object-header'"
mct-object="domainObject"
class="l-flex-row flex-elem object-header grows">
</mct-representation>
</div>
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
<mct-representation
key="'switcher'"
ng-model="representation"
mct-object="domainObject">
<mct-representation key="'switcher'"
ng-model="representation"
mct-object="domainObject">
</mct-representation>
<a class="s-button icon-expand t-btn-view-large"
title="View large"
mct-trigger-modal>
</a>
</div>
</div>
<div class="abs object-holder">
<mct-representation
key="representation.selected.key"
mct-object="representation.selected.key && domainObject">
<mct-representation key="representation.selected.key"
mct-object="representation.selected.key && domainObject">
</mct-representation>
</div>
</div>

View File

@@ -19,33 +19,19 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div class="l-layout"
ng-controller="LayoutController as controller">
<div class="abs l-layout"
ng-controller="LayoutController as controller"
ng-click="controller.clearSelection()">
<!-- Background grid -->
<div class="l-grid-holder" ng-click="controller.clearSelection()">
<div class="l-grid l-grid-x"
ng-if="!controller.getGridSize()[0] < 3"
ng-style="{ 'background-size': controller.getGridSize() [0] + 'px 100%' }"></div>
<div class="l-grid l-grid-y"
ng-if="!controller.getGridSize()[1] < 3"
ng-style="{ 'background-size': '100% ' + controller.getGridSize() [1] + 'px' }"></div>
</div>
<div class='abs frame t-frame-outer child-frame panel s-selectable s-moveable s-hover-border'
ng-class="{ 'no-frame': !controller.hasFrame(childObject), 's-selected':controller.selected(childObject) }"
<div class='frame child-frame panel abs'
ng-repeat="childObject in composition"
ng-click="controller.select($event, childObject.getId())"
ng-style="controller.getFrameStyle(childObject.getId())">
<mct-representation key="'frame'"
class="t-rep-frame holder contents abs"
class="frame child-frame holder contents abs"
mct-object="childObject">
</mct-representation>
<!-- Drag handles -->
<span class="abs t-edit-handle-holder s-hover-border" ng-if="controller.selected(childObject)">
<span ng-show="domainObject.hasCapability('editor')">
<span class="edit-handle edit-move"
mct-drag-down="controller.startDrag(childObject.getId(), [1,1], [0,0])"
mct-drag="controller.continueDrag(delta)"

View File

@@ -33,10 +33,6 @@ define(
DEFAULT_GRID_SIZE = [32, 32],
MINIMUM_FRAME_SIZE = [320, 180];
var DEFAULT_HIDDEN_FRAME_TYPES = [
'hyperlink'
];
/**
* The LayoutController is responsible for supporting the
* Layout view. It arranges frames according to saved configuration
@@ -69,10 +65,13 @@ define(
return;
}
// Ensure that configuration field is populated
$scope.configuration = $scope.configuration || {};
// Make sure there is a "panels" field in the
// view configuration.
$scope.configuration.panels =
$scope.configuration.panels || {};
// Store the position of this panel.
$scope.configuration.panels[id] = {
position: [
Math.floor(position.x / self.gridSize[0]),
@@ -80,11 +79,6 @@ define(
],
dimensions: self.defaultDimensions()
};
// Store the id so that the newly-dropped object
// gets selected during refresh composition
self.droppedIdToSelectAfterRefresh = id;
// Mark change as persistable
if ($scope.commit) {
$scope.commit("Dropped a frame.");
@@ -117,13 +111,6 @@ define(
$scope.composition = composition;
self.layoutPanels(ids);
self.setFrames(ids);
// If there is a newly-dropped object, select it.
if (self.droppedIdToSelectAfterRefresh) {
self.select(null, self.droppedIdToSelectAfterRefresh);
delete self.droppedIdToSelectAfterRefresh;
}
}
});
}
@@ -136,18 +123,13 @@ define(
// saved by the EditRepresenter.
$scope.configuration =
$scope.configuration || {};
// Make sure there is a "panels" field in the
// view configuration.
$scope.configuration.panels =
$scope.configuration.panels || {};
// Store the position of this panel.
$scope.configuration.panels[self.activeDragId] =
$scope.configuration.panels[self.activeDragId] || {};
$scope.configuration.panels[self.activeDragId].position =
self.rawPositions[self.activeDragId].position;
$scope.configuration.panels[self.activeDragId].dimensions =
self.rawPositions[self.activeDragId].dimensions;
self.rawPositions[self.activeDragId];
// Mark this object as dirty to encourage persistence
if ($scope.commit) {
$scope.commit("Moved frame.");
@@ -162,10 +144,6 @@ define(
// Watch for changes to the grid size in the model
$scope.$watch("model.layoutGrid", updateGridSize);
$scope.$watch("selection", function (selection) {
this.selection = selection;
}.bind(this));
// Update composed objects on screen, and position panes
$scope.$watchCollection("model.composition", refreshComposition);
@@ -173,42 +151,6 @@ define(
$scope.$on("mctDrop", handleDrop);
}
// Utility function to copy raw positions from configuration,
// without writing directly to configuration (to avoid triggering
// persistence from watchers during drags).
function shallowCopy(obj, keys) {
var copy = {};
keys.forEach(function (k) {
copy[k] = obj[k];
});
return copy;
}
/**
* Set the frames value. If a configuration panel has "hasFrame' property,
* use that value, otherwise set a default value. A 'hyperlink' object should
* have no frame by default.
*
* @param {string[]} ids the object ids
* @private
*/
LayoutController.prototype.setFrames = function (ids) {
var panels = shallowCopy(this.$scope.configuration.panels || {}, ids);
this.frames = {};
this.$scope.composition.forEach(function (object) {
var id = object.getId();
panels[id] = panels[id] || {};
if (panels[id].hasOwnProperty('hasFrame')) {
this.frames[id] = panels[id].hasFrame;
} else {
this.frames[id] = DEFAULT_HIDDEN_FRAME_TYPES.indexOf(object.getModel().type) === -1;
}
}, this);
};
// Convert from { positions: ..., dimensions: ... } to an
// appropriate ng-style argument, to position frames.
LayoutController.prototype.convertPosition = function (raw) {
@@ -295,7 +237,6 @@ define(
this.gridSize
);
};
/**
* Continue an active drag gesture.
* @param {number[]} delta the offset, in pixels,
@@ -310,6 +251,17 @@ define(
}
};
// Utility function to copy raw positions from configuration,
// without writing directly to configuration (to avoid triggering
// persistence from watchers during drags).
function shallowCopy(obj, keys) {
var copy = {};
keys.forEach(function (k) {
copy[k] = obj[k];
});
return copy;
}
/**
* Compute panel positions based on the layout's object model.
* Defined as member function to facilitate testing.
@@ -341,99 +293,9 @@ define(
* view configuration.
*/
LayoutController.prototype.endDrag = function () {
this.dragInProgress = true;
setTimeout(function () {
this.dragInProgress = false;
}.bind(this), 0);
this.endDragInScope();
};
/**
* Check if the object is currently selected.
*
* @param {string} obj the object to check for selection
* @returns {boolean} true if selected, otherwise false
*/
LayoutController.prototype.selected = function (obj) {
return !!this.selectedId && this.selectedId === obj.getId();
};
/**
* Set the active user selection in this view.
*
* @param event the mouse event
* @param {string} id the object id
*/
LayoutController.prototype.select = function (event, id) {
if (event) {
event.stopPropagation();
if (this.selection) {
event.preventDefault();
}
}
this.selectedId = id;
var selectedObj = {};
selectedObj[this.frames[id] ? 'hideFrame' : 'showFrame'] = this.toggleFrame.bind(this, id);
if (this.selection) {
this.selection.select(selectedObj);
}
};
/**
* Callback to show/hide the object frame.
*
* @param {string} id the object id
* @private
*/
LayoutController.prototype.toggleFrame = function (id) {
var configuration = this.$scope.configuration;
if (!configuration.panels[id]) {
configuration.panels[id] = {};
}
this.frames[id] = configuration.panels[id].hasFrame = !this.frames[id];
this.select(undefined, id); // reselect so toolbar updates
};
/**
* Clear the current user selection.
*/
LayoutController.prototype.clearSelection = function () {
if (this.dragInProgress) {
return;
}
if (this.selection) {
this.selection.deselect();
delete this.selectedId;
}
};
/**
* Check if the object has frame.
*
* @param {object} obj the object
* @return {boolean} true if object has frame, otherwise false
*/
LayoutController.prototype.hasFrame = function (obj) {
return this.frames[obj.getId()];
};
/**
* Get the size of the grid, in pixels. The returned array
* is in the form `[x, y]`.
* @returns {number[]} the grid size
*/
LayoutController.prototype.getGridSize = function () {
return this.gridSize;
};
return LayoutController;
}
);

View File

@@ -27,6 +27,7 @@ define([
) {
var OVERLAY_TEMPLATE = '' +
'<div class="abs overlay l-large-view">' +
' <div class="abs blocker"></div>' +
' <div class="abs outer-holder">' +
' <a class="close icon-x-in-circle"></a>' +
@@ -36,7 +37,8 @@ define([
' <a class="t-done s-button major">Done</a>' +
' </div>' +
' </div>' +
' </div>';
' </div>' +
'</div>';
/**
* MCT Trigger Modal is intended for use in only one location: inside the
@@ -79,8 +81,7 @@ define([
function openOverlay() {
// Remove frame classes from being applied in a non-frame context
$(frame).removeClass('frame frame-template');
overlay = document.createElement('div');
$(overlay).addClass('abs overlay l-large-view');
overlay = document.createElement('span');
overlay.innerHTML = OVERLAY_TEMPLATE;
overlayContainer = overlay.querySelector('.t-contents');
closeButton = overlay.querySelector('a.close');

View File

@@ -49,30 +49,10 @@ define(
},
useCapability: function () {
return mockCompositionCapability;
},
getModel: function () {
if (id === 'b') {
return {
type : 'hyperlink'
};
} else {
return {};
}
}
};
}
// Utility function to find a watch for a given expression
function findWatch(expr) {
var watch;
mockScope.$watch.calls.forEach(function (call) {
if (call.args[0] === expr) {
watch = call.args[1];
}
});
return watch;
}
beforeEach(function () {
mockScope = jasmine.createSpyObj(
"$scope",
@@ -80,7 +60,7 @@ define(
);
mockEvent = jasmine.createSpyObj(
'event',
['preventDefault', 'stopPropagation']
['preventDefault']
);
testModel = {};
@@ -88,7 +68,6 @@ define(
mockComposition = ["a", "b", "c"];
mockCompositionObjects = mockComposition.map(mockDomainObject);
testConfiguration = {
panels: {
a: {
@@ -103,19 +82,10 @@ define(
mockScope.domainObject = mockDomainObject("mockDomainObject");
mockScope.model = testModel;
mockScope.configuration = testConfiguration;
mockScope.selection = jasmine.createSpyObj(
'selection',
['select', 'get', 'selected', 'deselect']
);
spyOn(mockScope.domainObject, "useCapability").andCallThrough();
controller = new LayoutController(mockScope);
spyOn(controller, "layoutPanels").andCallThrough();
findWatch("selection")(mockScope.selection);
jasmine.Clock.useMock();
});
// Model changes will indicate that panel positions
@@ -319,111 +289,6 @@ define(
expect(controller.getFrameStyle("b"))
.not.toEqual(oldStyle);
});
it("allows panels to be selected", function () {
mockScope.$watchCollection.mostRecentCall.args[1]();
var childObj = mockCompositionObjects[0];
controller.select(mockEvent, childObj.getId());
expect(mockEvent.stopPropagation).toHaveBeenCalled();
expect(controller.selected(childObj)).toBe(true);
});
it("allows selection to be cleared", function () {
mockScope.$watchCollection.mostRecentCall.args[1]();
var childObj = mockCompositionObjects[0];
controller.select(null, childObj.getId());
controller.clearSelection();
expect(controller.selected(childObj)).toBeFalsy();
});
it("prevents clearing selection while drag is in progress", function () {
mockScope.$watchCollection.mostRecentCall.args[1]();
var childObj = mockCompositionObjects[0];
var id = childObj.getId();
controller.select(mockEvent, id);
// Do a drag
controller.startDrag(id, [1, 1], [0, 0]);
controller.continueDrag([100, 100]);
controller.endDrag();
// Because mouse position could cause clearSelection to be called, this should be ignored.
controller.clearSelection();
expect(controller.selected(childObj)).toBe(true);
// Shoud be able to clear the selection after dragging is done.
jasmine.Clock.tick(0);
controller.clearSelection();
expect(controller.selected(childObj)).toBe(false);
});
it("clears selection after moving/resizing", function () {
mockScope.$watchCollection.mostRecentCall.args[1]();
var childObj = mockCompositionObjects[0];
var id = childObj.getId();
controller.select(mockEvent, id);
// Do a drag
controller.startDrag(id, [1, 1], [0, 0]);
controller.continueDrag([100, 100]);
controller.endDrag();
jasmine.Clock.tick(0);
controller.clearSelection();
expect(controller.selected(childObj)).toBe(false);
});
it("shows frames by default", function () {
mockScope.$watchCollection.mostRecentCall.args[1]();
expect(controller.hasFrame(mockCompositionObjects[0])).toBe(true);
});
it("hyperlinks hide frame by default", function () {
mockScope.$watchCollection.mostRecentCall.args[1]();
expect(controller.hasFrame(mockCompositionObjects[1])).toBe(false);
});
it("hides frame when selected object has frame ", function () {
mockScope.$watchCollection.mostRecentCall.args[1]();
var childObj = mockCompositionObjects[0];
controller.select(mockEvent, childObj.getId());
expect(mockScope.selection.select).toHaveBeenCalled();
var selectedObj = mockScope.selection.select.mostRecentCall.args[0];
expect(controller.hasFrame(childObj)).toBe(true);
expect(selectedObj.hideFrame).toBeDefined();
expect(selectedObj.hideFrame).toEqual(jasmine.any(Function));
});
it("shows frame when selected object has no frame", function () {
mockScope.$watchCollection.mostRecentCall.args[1]();
var childObj = mockCompositionObjects[1];
controller.select(mockEvent, childObj.getId());
expect(mockScope.selection.select).toHaveBeenCalled();
var selectedObj = mockScope.selection.select.mostRecentCall.args[0];
expect(controller.hasFrame(childObj)).toBe(false);
expect(selectedObj.showFrame).toBeDefined();
expect(selectedObj.showFrame).toEqual(jasmine.any(Function));
});
});
}
);

View File

@@ -24,8 +24,6 @@ define([
"./src/MCTForm",
"./src/MCTToolbar",
"./src/MCTControl",
"./src/MCTFileInput",
"./src/FileInputService",
"./src/controllers/AutocompleteController",
"./src/controllers/DateTimeController",
"./src/controllers/CompositeController",
@@ -44,14 +42,11 @@ define([
"text!./res/templates/controls/menu-button.html",
"text!./res/templates/controls/dialog.html",
"text!./res/templates/controls/radio.html",
"text!./res/templates/controls/file-input.html",
'legacyRegistry'
], function (
MCTForm,
MCTToolbar,
MCTControl,
MCTFileInput,
FileInputService,
AutocompleteController,
DateTimeController,
CompositeController,
@@ -70,7 +65,6 @@ define([
menuButtonTemplate,
dialogTemplate,
radioTemplate,
fileInputTemplate,
legacyRegistry
) {
@@ -94,13 +88,6 @@ define([
"templateLinker",
"controls[]"
]
},
{
"key": "mctFileInput",
"implementation": MCTFileInput,
"depends": [
"fileInputService"
]
}
],
"controls": [
@@ -155,10 +142,6 @@ define([
{
"key": "dialog-button",
"template": dialogTemplate
},
{
"key": "file-input",
"template": fileInputTemplate
}
],
"controllers": [
@@ -193,14 +176,6 @@ define([
"dialogService"
]
}
],
"components": [
{
"provides": "fileInputService",
"type": "provider",
"implementation": FileInputService
}
]
}
});

View File

@@ -1,30 +0,0 @@
<!--
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.
-->
<a class="s-button {{structure.cssClass}}"
ng-model="ngModel[field]"
ng-class="{ labeled: structure.text }"
mct-file-input>
<span class="title-label" ng-if="structure.text">
{{structure.text}}
</span>
</a>

View File

@@ -1,90 +0,0 @@
/*****************************************************************************
* 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(["zepto"], function ($) {
/**
* The FileInputService provides an interface for triggering a file input.
*
* @constructor
* @memberof platform/forms
*/
function FileInputService() {
}
/**
* Creates, triggers, and destroys a file picker element and returns a
* promise for an object containing the chosen file's name and contents.
*
* @returns {Promise} promise for an object containing file meta-data
*/
FileInputService.prototype.getInput = function () {
var input = this.newInput();
var read = this.readFile;
var fileInfo = {};
var file;
return new Promise(function (resolve, reject) {
input.trigger("click");
input.on('change', function (event) {
file = this.files[0];
input.remove();
if (file) {
read(file)
.then(function (contents) {
fileInfo.name = file.name;
fileInfo.body = contents;
resolve(fileInfo);
}, function () {
reject("File read error");
});
}
});
});
};
FileInputService.prototype.readFile = function (file) {
var fileReader = new FileReader();
return new Promise(function (resolve, reject) {
fileReader.onload = function (event) {
resolve(event.target.result);
};
fileReader.onerror = function () {
return reject(event.target.result);
};
fileReader.readAsText(file);
});
};
FileInputService.prototype.newInput = function () {
var input = $(document.createElement('input'));
input.attr("type", "file");
input.css("display", "none");
$('body').append(input);
return input;
};
return FileInputService;
});

View File

@@ -1,66 +0,0 @@
/*****************************************************************************
* 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(
['zepto'],
function ($) {
/**
* The mct-file-input handles behavior of the file input form control.
* @constructor
* @memberof platform/forms
*/
function MCTFileInput(fileInputService) {
function link(scope, element, attrs, control) {
function setText(fileName) {
scope.structure.text = fileName.length > 20 ?
fileName.substr(0, 20) + "..." :
fileName;
}
function handleClick() {
fileInputService.getInput().then(function (result) {
setText(result.name);
scope.ngModel[scope.field] = result;
control.$setValidity("file-input", true);
}, function () {
setText('Select File');
control.$setValidity("file-input", false);
});
}
control.$setValidity("file-input", false);
element.on('click', handleClick);
}
return {
restrict: "A",
require: "^form",
link: link
};
}
return MCTFileInput;
}
);

View File

@@ -1,74 +0,0 @@
/*****************************************************************************
* 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/FileInputService"],
function (FileInputService) {
describe("The FileInputService", function () {
var fileInputService,
mockInput;
beforeEach(function () {
fileInputService = new FileInputService();
mockInput = jasmine.createSpyObj('input',
[
'on',
'trigger',
'remove'
]
);
mockInput.on.andCallFake(function (event, changeHandler) {
changeHandler.apply(mockInput);
});
spyOn(fileInputService, "newInput").andReturn(
mockInput
);
});
it("can read a file", function () {
mockInput.files = [new File(["file content"], "file name")];
fileInputService.getInput().then(function (result) {
expect(result.name).toBe("file name");
expect(result.body).toBe("file content");
});
expect(mockInput.trigger).toHaveBeenCalledWith('click');
expect(mockInput.remove).toHaveBeenCalled();
});
it("catches file read errors", function () {
mockInput.files = ["GARBAGE"];
fileInputService.getInput().then(
function (result) {},
function (err) {
expect(err).toBe("File read error");
}
);
expect(mockInput.trigger).toHaveBeenCalledWith('click');
expect(mockInput.remove).toHaveBeenCalled();
});
});
}
);

View File

@@ -1,98 +0,0 @@
/*****************************************************************************
* 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/MCTFileInput"],
function (MCTFileInput) {
describe("The mct-file-input directive", function () {
var mockScope,
mockFileInputService,
mctFileInput,
element,
attrs,
control;
beforeEach(function () {
attrs = [];
control = jasmine.createSpyObj('control', ['$setValidity']);
element = jasmine.createSpyObj('element', ['on', 'trigger']);
mockFileInputService = jasmine.createSpyObj('fileInputService',
['getInput']
);
mockScope = jasmine.createSpyObj(
'$scope',
['$watch']
);
mockScope.structure = {text: 'Select File'};
mockScope.field = "file-input";
mockScope.ngModel = {"file-input" : undefined};
element.on.andCallFake(function (event, clickHandler) {
clickHandler();
});
mockFileInputService.getInput.andReturn(
Promise.resolve({name: "file-name", body: "file-body"})
);
mctFileInput = new MCTFileInput(mockFileInputService);
// Need to wait for mock promise
var init = false;
runs(function () {
mctFileInput.link(mockScope, element, attrs, control);
setTimeout(function () {
init = true;
}, 100);
});
waitsFor(function () {
return init;
}, "File selection should have beeen simulated");
});
it("is restricted to attributes", function () {
expect(mctFileInput.restrict).toEqual("A");
});
it("changes button text to match file name", function () {
expect(element.on).toHaveBeenCalledWith(
'click',
jasmine.any(Function)
);
expect(mockScope.structure.text).toEqual("file-name");
});
it("validates control on file selection", function () {
expect(control.$setValidity.callCount).toBe(2);
expect(control.$setValidity.argsForCall[0]).toEqual(
['file-input', false]
);
expect(control.$setValidity.argsForCall[1]).toEqual(
['file-input', true]
);
});
});
}
);

View File

@@ -1,76 +0,0 @@
/*****************************************************************************
* 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.
*****************************************************************************/
/*global define*/
define([
"./src/actions/ExportAsJSONAction",
"./src/actions/ImportAsJSONAction"
], function (
ExportAsJSONAction,
ImportAsJSONAction
) {
return function ImportExportPlugin() {
return function (openmct) {
ExportAsJSONAction.appliesTo = function (context) {
return openmct.$injector.get('policyService')
.allow("creation", context.domainObject.getCapability("type")
);
};
openmct.legacyRegistry.register("platform/import-export", {
"name": "Import-export plugin",
"description": "Allows importing / exporting of domain objects as JSON.",
"extensions": {
"actions": [
{
"key": "export.JSON",
"name": "Export as JSON",
"implementation": ExportAsJSONAction,
"category": "contextual",
"cssClass": "icon-save",
"depends": [
"exportService",
"policyService",
"identifierService"
]
},
{
"key": "import.JSON",
"name": "Import from JSON",
"implementation": ImportAsJSONAction,
"category": "contextual",
"cssClass": "icon-download",
"depends": [
"exportService",
"identifierService",
"dialogService",
"openmct"
]
}
]
}
});
openmct.legacyRegistry.enable('platform/import-export');
};
};
});

View File

@@ -1,162 +0,0 @@
/*****************************************************************************
* 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 () {
/**
* The ExportAsJSONAction is available from context menus and allows a user
* to export any creatable domain object as a JSON file.
*
* @implements {Action}
* @constructor
* @memberof platform/import-export
*/
function ExportAsJSONAction(
exportService,
policyService,
identifierService,
context
) {
this.root = {};
this.tree = {};
this.calls = 0;
this.context = context;
this.externalIdentifiers = [];
this.exportService = exportService;
this.policyService = policyService;
this.identifierService = identifierService;
}
ExportAsJSONAction.prototype.perform = function () {
this.root = this.context.domainObject;
this.tree[this.root.getId()] = this.root.getModel();
this.saveAs = function (completedTree) {
this.exportService.exportJSON(
completedTree,
{filename: this.root.getModel().name + '.json'}
);
};
this.write(this.root);
};
/**
* Traverses object hierarchy and populates tree object with models and
* identifiers.
*
* @private
* @param {Object} parent
*/
ExportAsJSONAction.prototype.write = function (parent) {
this.calls++;
if (parent.hasCapability('composition')) {
parent.useCapability('composition')
.then(function (children) {
children.forEach(function (child, index) {
// Only export if object is creatable
if (this.isCreatable(child)) {
// Prevents infinite export of self-contained objs
if (!this.tree.hasOwnProperty(child.getId())) {
// If object is a link to something absent from
// tree, generate new id and treat as new object
if (this.isExternal(child, parent)) {
this.rewriteLink(child, parent);
} else {
this.tree[child.getId()] = child.getModel();
}
this.write(child);
}
}
}.bind(this));
this.calls--;
if (this.calls === 0) {
this.saveAs(this.wrapTree());
}
}.bind(this));
} else {
this.calls--;
if (this.calls === 0) {
this.saveAs(this.wrapTree());
}
}
};
/**
* Exports an externally linked object as an entirely new object in the
* case where the original is not present in the exported tree.
*
* @private
*/
ExportAsJSONAction.prototype.rewriteLink = function (child, parent) {
this.externalIdentifiers.push(child.getId());
var parentModel = parent.getModel();
var childModel = child.getModel();
var index = parentModel.composition.indexOf(child.getId());
var newModel = this.copyModel(childModel);
var newId = this.identifierService.generate();
newModel.location = parent.getId();
this.tree[newId] = newModel;
this.tree[parent.getId()] = this.copyModel(parentModel);
this.tree[parent.getId()].composition[index] = newId;
};
ExportAsJSONAction.prototype.copyModel = function (model) {
var jsonString = JSON.stringify(model);
return JSON.parse(jsonString);
};
ExportAsJSONAction.prototype.isExternal = function (child, parent) {
if (child.getModel().location !== parent.getId() &&
!Object.keys(this.tree).includes(child.getModel().location) &&
child.getId() !== this.root.getId() ||
this.externalIdentifiers.includes(child.getId())) {
return true;
}
return false;
};
/**
* Wraps root object for identification on reimport and wraps entire
* exported JSON construct for validation.
*
* @private
*/
ExportAsJSONAction.prototype.wrapTree = function () {
return {
"openmct": this.tree,
"rootId": this.root.getId()
};
};
ExportAsJSONAction.prototype.isCreatable = function (domainObject) {
return this.policyService.allow(
"creation",
domainObject.getCapability("type")
);
};
return ExportAsJSONAction;
});

View File

@@ -1,175 +0,0 @@
/*****************************************************************************
* 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(['zepto'], function ($) {
/**
* The ImportAsJSONAction is available from context menus and allows a user
* to import a previously exported domain object into any domain object
* that has the composition capability.
*
* @implements {Action}
* @constructor
* @memberof platform/import-export
*/
function ImportAsJSONAction(
exportService,
identifierService,
dialogService,
openmct,
context
) {
this.openmct = openmct;
this.context = context;
this.exportService = exportService;
this.dialogService = dialogService;
this.identifierService = identifierService;
this.instantiate = openmct.$injector.get("instantiate");
}
ImportAsJSONAction.prototype.perform = function () {
this.dialogService.getUserInput(this.getFormModel(), {})
.then(function (form) {
var objectTree = form.selectFile.body;
if (this.validateJSON(objectTree)) {
this.importObjectTree(JSON.parse(objectTree));
} else {
this.displayError();
}
}.bind(this));
};
ImportAsJSONAction.prototype.importObjectTree = function (objTree) {
var parent = this.context.domainObject;
var tree = this.generateNewIdentifiers(objTree);
var rootId = tree.rootId;
var rootObj = this.instantiate(tree.openmct[rootId], rootId);
// Instantiate all objects in tree with their newly genereated ids,
// adding each to its rightful parent's composition
rootObj.getCapability("location").setPrimaryLocation(parent.getId());
this.deepInstantiate(rootObj, tree.openmct, []);
parent.getCapability("composition").add(rootObj);
};
ImportAsJSONAction.prototype.deepInstantiate = function (parent, tree, seen) {
// Traverses object tree, instantiates all domain object w/ new IDs and
// adds to parent's composition
if (parent.hasCapability("composition")) {
var parentModel = parent.getModel();
var newObj;
seen.push(parent.getId());
parentModel.composition.forEach(function (childId, index) {
if (!tree[childId] || seen.includes(childId)) {
return;
}
newObj = this.instantiate(tree[childId], childId);
parent.getCapability("composition").add(newObj);
newObj.getCapability("location")
.setPrimaryLocation(tree[childId].location);
this.deepInstantiate(newObj, tree, seen);
}, this);
}
};
ImportAsJSONAction.prototype.generateNewIdentifiers = function (tree) {
// For each domain object in the file, generate new ID, replace in tree
Object.keys(tree.openmct).forEach(function (domainObjectId) {
var newId = this.identifierService.generate();
tree = this.rewriteId(domainObjectId, newId, tree);
}, this);
return tree;
};
/**
* Rewrites all instances of a given id in the tree with a newly generated
* replacement to prevent collision.
*
* @private
*/
ImportAsJSONAction.prototype.rewriteId = function (oldID, newID, tree) {
tree = JSON.stringify(tree).replace(new RegExp(oldID, 'g'), newID);
return JSON.parse(tree);
};
ImportAsJSONAction.prototype.getFormModel = function () {
return {
name: "Import as JSON",
sections: [
{
name: "Import A File",
rows: [
{
name: 'Select File',
key: 'selectFile',
control: 'file-input',
required: true,
text: 'Select File'
}
]
}
]
};
};
ImportAsJSONAction.prototype.validateJSON = function (jsonString) {
var json;
try {
json = JSON.parse(jsonString);
} catch (e) {
return false;
}
if (!json.openmct || !json.rootId) {
return false;
}
return true;
};
ImportAsJSONAction.prototype.displayError = function () {
var dialog,
model = {
title: "Invalid File",
actionText: "The selected file was either invalid JSON or was " +
"not formatted properly for import into Open MCT.",
severity: "error",
options: [
{
label: "Ok",
callback: function () {
dialog.dismiss();
}
}
]
};
dialog = this.dialogService.showBlockingMessage(model);
};
ImportAsJSONAction.appliesTo = function (context) {
return context.domainObject !== undefined &&
context.domainObject.hasCapability("composition");
};
return ImportAsJSONAction;
});

View File

@@ -1,266 +0,0 @@
/*****************************************************************************
* 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/actions/ExportAsJSONAction",
"../../../entanglement/test/DomainObjectFactory"
],
function (ExportAsJSONAction, domainObjectFactory) {
describe("The export JSON action", function () {
var context,
action,
exportService,
identifierService,
policyService,
mockType,
exportedTree;
beforeEach(function () {
exportService = jasmine.createSpyObj('exportService',
['exportJSON']);
identifierService = jasmine.createSpyObj('identifierService',
['generate']);
policyService = jasmine.createSpyObj('policyService',
['allow']);
mockType =
jasmine.createSpyObj('type', ['hasFeature']);
mockType.hasFeature.andCallFake(function (feature) {
return feature === 'creation';
});
context = {};
context.domainObject = domainObjectFactory(
{
name: 'test',
id: 'someID',
capabilities: {type: mockType}
});
identifierService.generate.andReturn('brandNewId');
exportService.exportJSON.andCallFake(function (tree, options) {
exportedTree = tree;
});
policyService.allow.andCallFake(function (capability, type) {
return type.hasFeature(capability);
});
action = new ExportAsJSONAction(exportService, policyService,
identifierService, context);
});
it("initializes happily", function () {
expect(action).toBeDefined();
});
it("doesn't export non-creatable objects in tree", function () {
var nonCreatableType = {
hasFeature :
function (feature) {
return feature !== 'creation';
}
};
var parentComposition =
jasmine.createSpyObj('parentComposition', ['invoke']);
var parent = domainObjectFactory({
name: 'parent',
model: { name: 'parent', location: 'ROOT'},
id: 'parentId',
capabilities: {
composition: parentComposition,
type: mockType
}
});
var child = domainObjectFactory({
name: 'child',
model: { name: 'child', location: 'parentId' },
id: 'childId',
capabilities: {
type: nonCreatableType
}
});
parentComposition.invoke.andReturn(
Promise.resolve([child])
);
context.domainObject = parent;
var init = false;
runs(function () {
action.perform();
setTimeout(function () {
init = true;
}, 100);
});
waitsFor(function () {
return init;
}, "Exported tree sohuld have been built");
runs(function () {
expect(Object.keys(action.tree).length).toBe(1);
expect(action.tree.hasOwnProperty("parentId"))
.toBeTruthy();
});
});
it("can export self-containing objects", function () {
var infiniteParentComposition =
jasmine.createSpyObj('infiniteParentComposition',
['invoke']
);
var infiniteChildComposition =
jasmine.createSpyObj('infiniteChildComposition',
['invoke']
);
var parent = domainObjectFactory({
name: 'parent',
model: { name: 'parent', location: 'ROOT'},
id: 'infiniteParentId',
capabilities: {
composition: infiniteParentComposition,
type: mockType
}
});
var child = domainObjectFactory({
name: 'child',
model: { name: 'child', location: 'infiniteParentId' },
id: 'infiniteChildId',
capabilities: {
composition: infiniteChildComposition,
type: mockType
}
});
infiniteParentComposition.invoke.andReturn(
Promise.resolve([child])
);
infiniteChildComposition.invoke.andReturn(
Promise.resolve([parent])
);
context.domainObject = parent;
var init = false;
runs(function () {
action.perform();
setTimeout(function () {
init = true;
}, 100);
});
waitsFor(function () {
return init;
}, "Exported tree sohuld have been built");
runs(function () {
expect(Object.keys(action.tree).length).toBe(2);
expect(action.tree.hasOwnProperty("infiniteParentId"))
.toBeTruthy();
expect(action.tree.hasOwnProperty("infiniteChildId"))
.toBeTruthy();
});
});
it("exports links to external objects as new objects", function () {
var externallyLinkedComposition =
jasmine.createSpyObj('externallyLinkedComposition',
['invoke']
);
var parent = domainObjectFactory({
name: 'parent',
model: {
name: 'parent',
composition: ['externalId'],
location: 'ROOT'},
id: 'parentId',
capabilities: {
composition: externallyLinkedComposition,
type: mockType
}
});
var externalObject = domainObjectFactory({
name: 'external',
model: { name: 'external', location: 'outsideOfTree'},
id: 'externalId',
capabilities: {
type: mockType
}
});
externallyLinkedComposition.invoke.andReturn(
Promise.resolve([externalObject])
);
context.domainObject = parent;
var init = false;
runs(function () {
action.perform();
setTimeout(function () {
init = true;
}, 100);
});
waitsFor(function () {
return init;
}, "Exported tree sohuld have been built");
runs(function () {
expect(Object.keys(action.tree).length).toBe(2);
expect(action.tree.hasOwnProperty('parentId'))
.toBeTruthy();
expect(action.tree.hasOwnProperty('brandNewId'))
.toBeTruthy();
expect(action.tree.brandNewId.location).toBe('parentId');
});
});
it("exports object tree in the correct format", function () {
var init = false;
runs(function () {
action.perform();
setTimeout(function () {
init = true;
}, 100);
});
waitsFor(function () {
return init;
}, "Exported tree sohuld have been built");
runs(function () {
expect(Object.keys(exportedTree).length).toBe(2);
expect(exportedTree.hasOwnProperty('openmct')).toBeTruthy();
expect(exportedTree.hasOwnProperty('rootId')).toBeTruthy();
});
});
});
}
);

View File

@@ -1,240 +0,0 @@
/*****************************************************************************
* 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/actions/ImportAsJSONAction",
"../../../entanglement/test/DomainObjectFactory"
],
function (ImportAsJSONAction, domainObjectFactory) {
describe("The import JSON action", function () {
var context = {};
var action,
exportService,
identifierService,
dialogService,
openmct,
mockDialog,
compositionCapability,
mockInstantiate,
uniqueId,
newObjects;
beforeEach(function () {
uniqueId = 0;
newObjects = [];
openmct = {
$injector: jasmine.createSpyObj('$injector', ['get'])
};
mockInstantiate = jasmine.createSpy('instantiate').andCallFake(
function (model, id) {
var config = {
"model": model,
"id": id,
"capabilities": {}
};
var locationCapability = {
setPrimaryLocation: jasmine.createSpy
('setPrimaryLocation').andCallFake(
function (newLocation) {
config.model.location = newLocation;
}
)
};
config.capabilities.location = locationCapability;
if (model.composition) {
var compCapability =
jasmine.createSpy('compCapability')
.andReturn(model.composition);
compCapability.add = jasmine.createSpy('add')
.andCallFake(function (newObj) {
config.model.composition.push(newObj.getId());
});
config.capabilities.composition = compCapability;
}
newObjects.push(domainObjectFactory(config));
return domainObjectFactory(config);
});
openmct.$injector.get.andReturn(mockInstantiate);
dialogService = jasmine.createSpyObj('dialogService',
[
'getUserInput',
'showBlockingMessage'
]
);
identifierService = jasmine.createSpyObj('identifierService',
[
'generate'
]
);
identifierService.generate.andCallFake(function () {
uniqueId++;
return uniqueId;
});
compositionCapability = jasmine.createSpy('compositionCapability');
mockDialog = jasmine.createSpyObj("dialog", ["dismiss"]);
dialogService.showBlockingMessage.andReturn(mockDialog);
action = new ImportAsJSONAction(exportService, identifierService,
dialogService, openmct, context);
});
it("initializes happily", function () {
expect(action).toBeDefined();
});
it("only applies to objects with composition capability", function () {
var compDomainObject = domainObjectFactory({
name: 'compObject',
model: { name: 'compObject'},
capabilities: {"composition": compositionCapability}
});
var noCompDomainObject = domainObjectFactory();
context.domainObject = compDomainObject;
expect(ImportAsJSONAction.appliesTo(context)).toBe(true);
context.domainObject = noCompDomainObject;
expect(ImportAsJSONAction.appliesTo(context)).toBe(false);
});
it("displays error dialog on invalid file choice", function () {
dialogService.getUserInput.andReturn(Promise.resolve(
{
selectFile: {
body: JSON.stringify({badKey: "INVALID"}),
name: "fileName"
}
})
);
var init = false;
runs(function () {
action.perform();
setTimeout(function () {
init = true;
}, 100);
});
waitsFor(function () {
return init;
}, "Promise containing file data should have resolved");
runs(function () {
expect(dialogService.getUserInput).toHaveBeenCalled();
expect(dialogService.showBlockingMessage).toHaveBeenCalled();
});
});
it("can import self-containing objects", function () {
dialogService.getUserInput.andReturn(Promise.resolve(
{
selectFile: {
body: JSON.stringify({
"openmct": {
"infiniteParent": {
"composition": ["infinteChild"],
"name": "1",
"type": "folder",
"modified": 1503598129176,
"location": "mine",
"persisted": 1503598129176
},
"infinteChild": {
"composition": ["infiniteParent"],
"name": "2",
"type": "folder",
"modified": 1503598132428,
"location": "infiniteParent",
"persisted": 1503598132428
}
},
"rootId": "infiniteParent"
}),
name: "fileName"
}
})
);
var init = false;
runs(function () {
action.perform();
setTimeout(function () {
init = true;
}, 100);
});
waitsFor(function () {
return init;
}, "Promise containing file data should have resolved");
runs(function () {
expect(mockInstantiate.calls.length).toEqual(2);
});
});
it("assigns new ids to each imported object", function () {
dialogService.getUserInput.andReturn(Promise.resolve(
{
selectFile: {
body: JSON.stringify({
"openmct": {
"cce9f107-5060-4f55-8151-a00120f4222f": {
"composition": [],
"name": "test",
"type": "folder",
"modified": 1503596596639,
"location": "mine",
"persisted": 1503596596639
}
},
"rootId": "cce9f107-5060-4f55-8151-a00120f4222f"
}),
name: "fileName"
}
})
);
var init = false;
runs(function () {
action.perform();
setTimeout(function () {
init = true;
}, 100);
});
waitsFor(function () {
return init;
}, "Promise containing file data should have resolved");
runs(function () {
expect(mockInstantiate.calls.length).toEqual(1);
expect(newObjects[0].getId()).toBe('1');
});
});
});
}
);

View File

@@ -138,11 +138,6 @@ define(
typeRequest = (type && type.getDefinition().telemetry) || {},
modelTelemetry = domainObject.getModel().telemetry,
fullRequest = Object.create(typeRequest),
newObject = objectUtils.toNewFormat(
domainObject.getModel(),
domainObject.getId()
),
metadata = this.openmct.telemetry.getMetadata(newObject),
bounds,
timeSystem;
@@ -178,14 +173,6 @@ define(
}
}
if (!fullRequest.ranges) {
fullRequest.ranges = metadata.valuesForHints(['range']);
}
if (!fullRequest.domains) {
fullRequest.domains = metadata.valuesForHints(['domain']);
}
return fullRequest;
};
@@ -224,8 +211,7 @@ define(
var metadata = telemetryAPI.getMetadata(domainObject);
var defaultDomain = metadata.valuesForHints(['domain'])[0].source;
var defaultRange = metadata.valuesForHints(['range'])[0];
defaultRange = defaultRange ? defaultRange.source : undefined;
var defaultRange = metadata.valuesForHints(['range'])[0].source;
var isLegacyProvider = telemetryAPI.findRequestProvider(domainObject) ===
telemetryAPI.legacyProvider;
@@ -287,8 +273,7 @@ define(
var metadata = telemetryAPI.getMetadata(domainObject);
var defaultDomain = metadata.valuesForHints(['domain'])[0].source;
var defaultRange = metadata.valuesForHints(['range'])[0];
defaultRange = defaultRange ? defaultRange.source : undefined;
var defaultRange = metadata.valuesForHints(['range'])[0].source;
var isLegacyProvider = telemetryAPI.findSubscriptionProvider(domainObject) ===
telemetryAPI.legacyProvider;

View File

@@ -91,10 +91,8 @@ define(
"findSubscriptionProvider"
]);
mockTelemetryAPI.getMetadata.andReturn({
valuesForHints: function (hint) {
var metadatum = {};
metadatum[hint] = "foo";
return [metadatum];
valuesForHints: function () {
return [{}];
}
});
@@ -149,9 +147,7 @@ define(
source: "testSource", // from model
key: "testKey", // from model
start: 42, // from argument
domain: 'mockTimeSystem',
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
domain: 'mockTimeSystem'
}]);
});
@@ -171,9 +167,7 @@ define(
key: "testKey",
start: 0,
end: 1,
domain: 'mockTimeSystem',
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
domain: 'mockTimeSystem'
});
});
@@ -190,9 +184,7 @@ define(
key: "testId", // from domain object
start: 0,
end: 1,
domain: 'mockTimeSystem',
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
domain: 'mockTimeSystem'
});
});
@@ -274,9 +266,7 @@ define(
key: "testKey",
start: 0,
end: 1,
domain: 'mockTimeSystem',
domains: [{ domain: "foo" }],
ranges: [{ range: "foo" }]
domain: 'mockTimeSystem'
}]
);

View File

@@ -107,9 +107,7 @@ define([
}
this.last = params;
if (!params.timeSystem) {
this.updateQueryParams();
} else if (params.clock === 'fixed' && params.bounds) {
if (params.clock === 'fixed' && params.bounds) {
if (!this.time.timeSystem() ||
this.time.timeSystem().key !== params.timeSystem) {

View File

@@ -132,20 +132,6 @@ define([
};
});
it("initializes with missing time system", function () {
// This handles an odd transitory case where a url does not include
// a timeSystem. It's generally only experienced by those who
// based their code on the tutorial before it specified a time
// system.
search['tc.mode'] = 'clockA';
search['tc.timeSystem'] = undefined;
search['tc.startDelta'] = '123';
search['tc.endDelta'] = '456';
// We don't specify behavior right now other than "don't break."
expect(initialize).not.toThrow();
});
it("can initalize fixed mode from location", function () {
search['tc.mode'] = 'fixed';
search['tc.timeSystem'] = 'timeSystemA';

View File

@@ -148,7 +148,9 @@ define([
var limitEvaluator = oldObject.getCapability("limit");
if (!limitEvaluator) {
return;
return {
evaluate: function () {}
};
}
return {

View File

@@ -23,12 +23,10 @@
define([
'./TelemetryMetadataManager',
'./TelemetryValueFormatter',
'../objects/object-utils',
'lodash'
], function (
TelemetryMetadataManager,
TelemetryValueFormatter,
objectUtils,
_
) {
/**
@@ -227,15 +225,7 @@ define([
* telemetry data
*/
TelemetryAPI.prototype.request = function (domainObject) {
if (arguments.length === 1) {
arguments.length = 2;
arguments[1] = {};
}
this.standardizeRequestOptions(arguments[1]);
var provider = this.findRequestProvider.apply(this, arguments);
if (!provider) {
return Promise.reject('No provider found');
}
return provider.request.apply(provider, arguments);
};
@@ -250,45 +240,14 @@ define([
* which has associated telemetry
* @param {Function} callback the callback to invoke with new data, as
* it becomes available
* @param {module:openmct.TelemetryAPI~TelemetryRequest} options
* options for this request
* @returns {Function} a function which may be called to terminate
* the subscription
*/
TelemetryAPI.prototype.subscribe = function (domainObject, callback) {
var provider = this.findSubscriptionProvider(domainObject);
if (!this.subscribeCache) {
this.subscribeCache = {};
}
var keyString = objectUtils.makeKeyString(domainObject.identifier);
var subscriber = this.subscribeCache[keyString];
if (!subscriber) {
subscriber = this.subscribeCache[keyString] = {
callbacks: [callback]
};
if (provider) {
subscriber.unsubscribe = provider
.subscribe(domainObject, function (value) {
subscriber.callbacks.forEach(function (cb) {
cb(value);
});
});
} else {
subscriber.unsubscribe = function () {};
}
} else {
subscriber.callbacks.push(callback);
}
return function unsubscribe() {
subscriber.callbacks = subscriber.callbacks.filter(function (cb) {
return cb !== callback;
});
if (subscriber.callbacks.length === 0) {
subscriber.unsubscribe();
}
delete this.subscribeCache[keyString];
}.bind(this);
var provider = this.findSubscriptionProvider.apply(this, arguments);
return provider.subscribe.apply(provider, arguments);
};
/**

View File

@@ -1,278 +0,0 @@
define([
'./TelemetryAPI'
], function (
TelemetryAPI
) {
describe('Telemetry API', function () {
var openmct;
var telemetryAPI;
beforeEach(function () {
openmct = {
time: jasmine.createSpyObj('timeAPI', [
'timeSystem',
'bounds'
])
};
openmct.time.timeSystem.andReturn({key: 'system'});
openmct.time.bounds.andReturn({start: 0, end: 1});
telemetryAPI = new TelemetryAPI(openmct);
});
describe('telemetry providers', function () {
var telemetryProvider,
domainObject;
beforeEach(function () {
telemetryProvider = jasmine.createSpyObj('telemetryProvider', [
'supportsSubscribe',
'subscribe',
'supportsRequest',
'request'
]);
domainObject = {
identifier: {
key: 'a',
namespace: 'b'
},
type: 'sample-type'
};
});
it('provides consistent results without providers', function () {
var unsubscribe = telemetryAPI.subscribe(domainObject);
expect(unsubscribe).toEqual(jasmine.any(Function));
var response = telemetryAPI.request(domainObject);
expect(response).toEqual(jasmine.any(Promise));
});
it('skips providers that do not match', function () {
telemetryProvider.supportsSubscribe.andReturn(false);
telemetryProvider.supportsRequest.andReturn(false);
telemetryAPI.addProvider(telemetryProvider);
var callback = jasmine.createSpy('callback');
var unsubscribe = telemetryAPI.subscribe(domainObject, callback);
expect(telemetryProvider.supportsSubscribe)
.toHaveBeenCalledWith(domainObject);
expect(telemetryProvider.subscribe).not.toHaveBeenCalled();
expect(unsubscribe).toEqual(jasmine.any(Function));
var response = telemetryAPI.request(domainObject);
expect(telemetryProvider.supportsRequest)
.toHaveBeenCalledWith(domainObject, jasmine.any(Object));
expect(telemetryProvider.request).not.toHaveBeenCalled();
expect(response).toEqual(jasmine.any(Promise));
});
it('sends subscribe calls to matching providers', function () {
var unsubFunc = jasmine.createSpy('unsubscribe');
telemetryProvider.subscribe.andReturn(unsubFunc);
telemetryProvider.supportsSubscribe.andReturn(true);
telemetryAPI.addProvider(telemetryProvider);
var callback = jasmine.createSpy('callback');
var unsubscribe = telemetryAPI.subscribe(domainObject, callback);
expect(telemetryProvider.supportsSubscribe.calls.length).toBe(1);
expect(telemetryProvider.supportsSubscribe)
.toHaveBeenCalledWith(domainObject);
expect(telemetryProvider.subscribe.calls.length).toBe(1);
expect(telemetryProvider.subscribe)
.toHaveBeenCalledWith(domainObject, jasmine.any(Function));
var notify = telemetryProvider.subscribe.mostRecentCall.args[1];
notify('someValue');
expect(callback).toHaveBeenCalledWith('someValue');
expect(unsubscribe).toEqual(jasmine.any(Function));
expect(unsubFunc).not.toHaveBeenCalled();
unsubscribe();
expect(unsubFunc).toHaveBeenCalled();
notify('otherValue');
expect(callback).not.toHaveBeenCalledWith('otherValue');
});
it('subscribes once per object', function () {
var unsubFunc = jasmine.createSpy('unsubscribe');
telemetryProvider.subscribe.andReturn(unsubFunc);
telemetryProvider.supportsSubscribe.andReturn(true);
telemetryAPI.addProvider(telemetryProvider);
var callback = jasmine.createSpy('callback');
var callbacktwo = jasmine.createSpy('callback two');
var unsubscribe = telemetryAPI.subscribe(domainObject, callback);
var unsubscribetwo = telemetryAPI.subscribe(domainObject, callbacktwo);
expect(telemetryProvider.subscribe.calls.length).toBe(1);
var notify = telemetryProvider.subscribe.mostRecentCall.args[1];
notify('someValue');
expect(callback).toHaveBeenCalledWith('someValue');
expect(callbacktwo).toHaveBeenCalledWith('someValue');
unsubscribe();
expect(unsubFunc).not.toHaveBeenCalled();
notify('otherValue');
expect(callback).not.toHaveBeenCalledWith('otherValue');
expect(callbacktwo).toHaveBeenCalledWith('otherValue');
unsubscribetwo();
expect(unsubFunc).toHaveBeenCalled();
notify('anotherValue');
expect(callback).not.toHaveBeenCalledWith('anotherValue');
expect(callbacktwo).not.toHaveBeenCalledWith('anotherValue');
});
it('does subscribe/unsubscribe', function () {
var unsubFunc = jasmine.createSpy('unsubscribe');
telemetryProvider.subscribe.andReturn(unsubFunc);
telemetryProvider.supportsSubscribe.andReturn(true);
telemetryAPI.addProvider(telemetryProvider);
var callback = jasmine.createSpy('callback');
var unsubscribe = telemetryAPI.subscribe(domainObject, callback);
expect(telemetryProvider.subscribe.calls.length).toBe(1);
unsubscribe();
unsubscribe = telemetryAPI.subscribe(domainObject, callback);
expect(telemetryProvider.subscribe.calls.length).toBe(2);
unsubscribe();
});
it('subscribes for different object', function () {
var unsubFuncs = [];
var notifiers = [];
telemetryProvider.supportsSubscribe.andReturn(true);
telemetryProvider.subscribe.andCallFake(function (obj, cb) {
var unsubFunc = jasmine.createSpy('unsubscribe ' + unsubFuncs.length);
unsubFuncs.push(unsubFunc);
notifiers.push(cb);
return unsubFunc;
});
telemetryAPI.addProvider(telemetryProvider);
var otherDomainObject = JSON.parse(JSON.stringify(domainObject));
otherDomainObject.identifier.namespace = 'other';
var callback = jasmine.createSpy('callback');
var callbacktwo = jasmine.createSpy('callback two');
var unsubscribe = telemetryAPI.subscribe(domainObject, callback);
var unsubscribetwo = telemetryAPI.subscribe(otherDomainObject, callbacktwo);
expect(telemetryProvider.subscribe.calls.length).toBe(2);
notifiers[0]('someValue');
expect(callback).toHaveBeenCalledWith('someValue');
expect(callbacktwo).not.toHaveBeenCalledWith('someValue');
notifiers[1]('anotherValue');
expect(callback).not.toHaveBeenCalledWith('anotherValue');
expect(callbacktwo).toHaveBeenCalledWith('anotherValue');
unsubscribe();
expect(unsubFuncs[0]).toHaveBeenCalled();
expect(unsubFuncs[1]).not.toHaveBeenCalled();
unsubscribetwo();
expect(unsubFuncs[1]).toHaveBeenCalled();
});
it('sends requests to matching providers', function () {
var telemPromise = Promise.resolve([]);
telemetryProvider.supportsRequest.andReturn(true);
telemetryProvider.request.andReturn(telemPromise);
telemetryAPI.addProvider(telemetryProvider);
var result = telemetryAPI.request(domainObject);
expect(result).toBe(telemPromise);
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
domainObject,
jasmine.any(Object)
);
expect(telemetryProvider.request).toHaveBeenCalledWith(
domainObject,
jasmine.any(Object)
);
});
it('generates default request options', function () {
telemetryProvider.supportsRequest.andReturn(true);
telemetryAPI.addProvider(telemetryProvider);
telemetryAPI.request(domainObject);
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
jasmine.any(Object),
{
start: 0,
end: 1,
domain: 'system'
}
);
expect(telemetryProvider.request).toHaveBeenCalledWith(
jasmine.any(Object),
{
start: 0,
end: 1,
domain: 'system'
}
);
telemetryProvider.supportsRequest.reset();
telemetryProvider.request.reset();
telemetryAPI.request(domainObject, {});
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
jasmine.any(Object),
{
start: 0,
end: 1,
domain: 'system'
}
);
expect(telemetryProvider.request).toHaveBeenCalledWith(
jasmine.any(Object),
{
start: 0,
end: 1,
domain: 'system'
}
);
});
it('does not overwrite existing request options', function () {
telemetryProvider.supportsRequest.andReturn(true);
telemetryAPI.addProvider(telemetryProvider);
telemetryAPI.request(domainObject, {
start: 20,
end: 30,
domain: 'someDomain'
});
expect(telemetryProvider.supportsRequest).toHaveBeenCalledWith(
jasmine.any(Object),
{
start: 20,
end: 30,
domain: 'someDomain'
}
);
expect(telemetryProvider.request).toHaveBeenCalledWith(
jasmine.any(Object),
{
start: 20,
end: 30,
domain: 'someDomain'
}
);
});
});
});
});

View File

@@ -72,7 +72,6 @@ define([
'../platform/features/listview/bundle',
'../platform/features/my-items/bundle',
'../platform/features/pages/bundle',
'../platform/features/hyperlink/bundle',
'../platform/features/plot/bundle',
'../platform/features/static-markup/bundle',
'../platform/features/table/bundle',
@@ -119,7 +118,6 @@ define([
'platform/features/layout',
'platform/features/listview',
'platform/features/pages',
'platform/features/hyperlink',
'platform/features/plot',
'platform/features/timeline',
'platform/features/table',

View File

@@ -26,16 +26,14 @@ define([
'../../example/generator/plugin',
'../../platform/features/autoflow/plugin',
'./timeConductor/plugin',
'../../example/imagery/plugin',
'../../platform/import-export/bundle'
'../../example/imagery/plugin'
], function (
_,
UTCTimeSystem,
GeneratorPlugin,
AutoflowPlugin,
TimeConductorPlugin,
ExampleImagery,
ImportExport
ExampleImagery
) {
var bundleMap = {
CouchDB: 'platform/persistence/couch',
@@ -56,8 +54,6 @@ define([
plugins.UTCTimeSystem = UTCTimeSystem;
plugins.ImportExport = ImportExport;
/**
* A tabular view showing the latest values of multiple telemetry points at
* once. Formatted so that labels and values are aligned.