Compare commits

..

42 Commits

Author SHA1 Message Date
charlesh88
687f4b8d65 [Frontend] Significant mods to fluid-layouts
- Restructure code to make better use of mixins;
- Added .fl-mobile-only selector;
- Simplified layout logic for column/row/wrap styles;
2018-06-05 17:47:09 -07:00
charlesh88
6eb3ffcbd6 Merge latest 'master' into fluid-layouts
# Conflicts:
#	platform/commonUI/edit/res/templates/elements.html
2018-06-04 13:26:00 -07:00
Deep Tailor
721b966b0c fix failing test 2018-05-25 13:15:31 -07:00
Deep Tailor
1fc64e54b5 merge with master and fix coflicts 2018-05-25 13:11:27 -07:00
charlesh88
ec682d5734 [Frontend] Added new 12px grippy glyph
- Font files and CSS updates for Elements pool sorting styling;
2018-05-22 17:16:02 -07:00
charlesh88
6b8da63697 [Frontend] Added new 12px list view glyph
- Font files and CSS updates;
2018-05-22 16:30:39 -07:00
charlesh88
6040bafba8 [Frontend] Tweaks to Elements pool reordering styles
- "reorder-actor" added/removed from parent tree item;
- Refined styling for drag in process in list;
2018-05-22 16:12:35 -07:00
Deep Tailor
cb9ae92e69 stacked plots reload on composition change 2018-05-22 13:53:12 -07:00
Deep Tailor
d14c2cf62e add reorder-actor class to draggable item in elements pool when selected and remove class when dropped 2018-05-22 11:39:39 -07:00
charlesh88
03663488b9 [Frontend] Styles for reordering in Elements pool
- Changed class "dragging" to "reordering";
- Visual styling WIP;
- TODO: style "reorder-actor" when implemented;
2018-05-22 11:20:39 -07:00
charlesh88
34ccf45351 [Frontend] Allow editor to set mins dimensions for fluid layout
- Cleanups in CSS;
- Mod to LayoutController.js to use minWidth and minHeight;
2018-05-22 10:48:14 -07:00
Charles Hacskaylo
dff7e3d8a2 Merge branch 'fluid-layouts' of https://github.com/nasa/openmct into fluid-layouts 2018-05-21 16:07:29 -07:00
Charles Hacskaylo
5435e9d88b [Frontend] Added fl-mobile-best-fit 2018-05-21 16:05:38 -07:00
Deep Tailor
8c22ce23bf add maxHeight and maxWidth to layout frames 2018-05-21 13:39:51 -07:00
Deep Tailor
4b827e2c13 add ability to rearrange composition using drag gestures 2018-05-21 12:11:04 -07:00
Deep Tailor
25588c87d1 fix conflict 2018-05-21 10:17:26 -07:00
Deep Tailor
73a8f71740 merge latest to local 2018-05-21 10:15:54 -07:00
Deep Tailor
04f333f99b working drag and switch, need to mutate 2018-05-18 08:55:30 -07:00
charlesh88
5f592099fb [Frontend] More CSS tweaks
- WIP!
- Added .fl-phone-best-fit
2018-05-17 15:19:13 -07:00
charlesh88
9a9db2ddd9 [Frontend] Added .drag-vertical
- For use in Elements pool;
- Applied in elements.html;
2018-05-17 14:56:38 -07:00
charlesh88
5ae0e97e03 [Frontend] More CSS tweaks
- WIP!
2018-05-17 14:56:38 -07:00
charlesh88
62ccbd87ba [Frontend] Grid holder and class prefixing
- WIP!
- Edit grid-holder set to position: absolute
- Added "fl-" prefix to fluid layout class names;
2018-05-17 14:56:38 -07:00
charlesh88
4ce2b471d7 [Frontend] Add Advanced CSS property to Display Layouts
- WIP!
- Add property to bundle;
- Add CSS for column, row and fit-all classes;
2018-05-17 14:56:38 -07:00
Deep Tailor
202ca2e553 fixes issue #1999 - Use Object name as default export filename (#2001)
* fixes issue #1999
add dynamic name(object name) to exportAsCSV filename

* make requested changes
2018-05-17 14:56:38 -07:00
Nick Weingartner
e1397258e5 [Copyright] Update copyright year across platform code references
Fixes #2034.
2018-05-17 14:56:38 -07:00
Dhrubomoy Das Gupta
935386ef6e [TimeConductor] Fixes Issue #925 (#2020)
* [TimeConductor] Fixes Issue #925`
- Pressing enter in date field will update bounds properly in Safari
2018-05-17 14:56:37 -07:00
Nick Weingartner
e1c1a25d66 [Timer] Fix regression in timer visual indication and add tests 2018-05-17 14:56:37 -07:00
Even Stensberg
b8248aabfb fix: check if stats is present before reseting zoom (#2029) 2018-05-17 14:56:37 -07:00
charlesh88
7d32ea468f [Frontend] Added .drag-vertical
- For use in Elements pool;
- Applied in elements.html;
2018-05-17 14:50:19 -07:00
charlesh88
73ad8aa74f [Frontend] More CSS tweaks
- WIP!
2018-05-17 14:31:06 -07:00
charlesh88
6448269d5c [Frontend] Grid holder and class prefixing
- WIP!
- Edit grid-holder set to position: absolute
- Added "fl-" prefix to fluid layout class names;
2018-05-17 11:20:10 -07:00
charlesh88
00b8104023 [Frontend] Add Advanced CSS property to Display Layouts
- WIP!
- Add property to bundle;
- Add CSS for column, row and fit-all classes;
2018-05-16 16:43:01 -07:00
Charles Hacskaylo
18c1056800 [Frontend] Mods to imagery CSS
Fixes #2008
- Reduced size of image thumbnails;
- Changed min-heights of image and thumbnail
holders for .mobile.phone
2018-05-11 08:37:15 -07:00
Deep Tailor
853d21bb32 remove couchdb and reinstall localStorage 2018-05-10 14:43:23 -07:00
Deep Tailor
f265c3e495 Add touch functionality to mct-drag
it allows users to use the splitter in mobile
and include appropriate tests
2018-05-10 14:32:07 -07:00
charlesh88
336d58d45a [Frontend] Various
Fixes #2008
- Always show Timeline zoom controls;
- Prevent inline editing of object names in the main view when in
mobile;
2018-05-09 12:17:30 -07:00
Deep Tailor
c22659432d fixes multiple issues related to 2008
context menu firing too often - fixed by setting a isDragging flag
Add and Remove respective classes on mobile orientation change by using mathMedia
Close tree pane when navigating in mobile portrait only
2018-05-07 12:07:18 -07:00
charlesh88
5126e6b842 [Frontend] Significant mobile fixes for panes and viewport
Fixes #2008
Fixes #1770
Fixes #1928
- Left and right panes now positioning properly in mobile;
- Fixed body overflow problem for #2008 "viewport" issue;
2018-05-04 18:10:06 -07:00
charlesh88
e02e47f2a0 [Frontend] Hide TC ticks when on mobile
Fixes #2008
- Added class `mobile-hide` to <conductor-axis>
2018-05-04 18:10:06 -07:00
charlesh88
8a51e8ca48 [Frontend] Remove data visualization element in TC
Fixes #2008
- Note: this element holds the TOI indicator!
2018-05-04 18:10:06 -07:00
charlesh88
a60996abd4 [Frontend] Fix to Time Conductor for Safari
Fixes #2008
- CSS mod for gradient blockers in TC
2018-05-04 18:10:06 -07:00
charlesh88
2b58500508 [Frontend] Viewport metatag updated
Fixes #2008
- Added shrink-to-fit=no;
2018-05-04 18:10:06 -07:00
614 changed files with 22566 additions and 11325 deletions

View File

@@ -1,40 +0,0 @@
version: 2
jobs:
build:
docker:
- image: circleci/node:8-browsers
environment:
CHROME_BIN: "/usr/bin/google-chrome"
steps:
- checkout
- run:
name: Update npm
command: 'sudo npm install -g npm@latest'
- restore_cache:
key: dependency-cache-{{ checksum "package.json" }}-{{ checksum "bower.json" }}
- run:
name: Installing dependencies (npm install)
command: npm install
- save_cache:
key: dependency-cache-{{ checksum "package.json" }}-{{ checksum "bower.json" }}
paths:
- node_modules
- bower_components
- run:
name: npm run test
command: npm run test
- run:
name: npm run lint
command: npm run lint
- run:
name: npm run checkstyle
command: npm run checkstyle
- store_artifacts:
path: dist
prefix: dist
workflows:
version: 2
test:
jobs:
- build

117
API.md
View File

@@ -37,7 +37,7 @@
- [Time Systems and Bounds](#time-systems-and-bounds)
- [Defining and Registering Time Systems](#defining-and-registering-time-systems)
- [Getting and Setting the Active Time System](#getting-and-setting-the-active-time-system)
- [Time Bounds](#time-bounds)
- [Time Bounds](#time-bounds)
- [Clocks](#clocks)
- [Defining and registering clocks](#defining-and-registering-clocks)
- [Getting and setting active clock](#getting-and-setting-active-clock)
@@ -48,10 +48,7 @@
- [The Time Conductor](#the-time-conductor)
- [Time Conductor Configuration](#time-conductor-configuration)
- [Example conductor configuration](#example-conductor-configuration)
- [Indicators](#indicators)
- [The URL Status Indicator](#the-url-status-indicator)
- [Creating a Simple Indicator](#creating-a-simple-indicator)
- [Custom Indicators](#custom-indicators)
- [Included Plugins](#included-plugins)
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
@@ -691,7 +688,7 @@ openmct.time.timeSystem(utcTimeSystem, bounds);
Setting the active time system will trigger a [`'timeSystem'`](#time-events)
event. If you supplied bounds, a [`'bounds'`](#time-events) event will be triggered afterwards with your newly supplied bounds.
#### Time Bounds
### Time Bounds
The TimeAPI provides a getter/setter for querying and setting time bounds. Time
bounds are simply an object with a `start` and an end `end` attribute.
@@ -980,68 +977,58 @@ openmct.install(openmct.plugins.Conductor({
}));
```
## Indicators
## Included Plugins
Indicators are small widgets that reside at the bottom of the screen and are visible from
every screen in Open MCT. They can be used to convey system state using an icon and text.
Typically an indicator will display an icon (customizable with a CSS class) that will
reveal additional information when the mouse cursor is hovered over it.
Open MCT is packaged along with a few general-purpose plugins:
### The URL Status Indicator
* `openmct.plugins.Conductor` provides a user interface for working with time
within the application. If activated, configuration must be provided. This is
detailed in the section on [Time Conductor Configuration](#time-conductor-configuration).
* `openmct.plugins.CouchDB` is an adapter for using CouchDB for persistence
of user-created objects. This is a constructor that takes the URL for the
CouchDB database as a parameter, e.g.
```javascript
openmct.install(openmct.plugins.CouchDB('http://localhost:5984/openmct'))
```
* `openmct.plugins.Elasticsearch` is an adapter for using Elasticsearch for
persistence of user-created objects. This is a
constructor that takes the URL for the Elasticsearch instance as a
parameter. eg.
```javascript
openmct.install(openmct.plugins.CouchDB('http://localhost:9200'))
```
* `openmct.plugins.Espresso` and `openmct.plugins.Snow` are two different
themes (dark and light) available for Open MCT. Note that at least one
of these themes must be installed for Open MCT to appear correctly.
* `openmct.plugins.URLIndicatorPlugin` adds an indicator which shows the
availability of a URL with the following options:
- `url` : URL to indicate the status of
- `cssClass`: Icon to show in the status bar, defaults to `icon-database`, [list of all icons](https://nasa.github.io/openmct/style-guide/#/browse/styleguide:home?view=items)
- `interval`: Interval between checking the connection, defaults to `10000`
- `label` Name showing up as text in the status bar, defaults to url
```javascript
openmct.install(openmct.plugins.URLIndicatorPlugin({
url: 'http://google.com',
cssClass: 'check',
interval: 10000,
label: 'Google'
})
);
```
* `openmct.plugins.LocalStorage` provides persistence of user-created
objects in browser-local storage. This is particularly useful in
development environments.
* `openmct.plugins.MyItems` adds a top-level folder named "My Items"
when the application is first started, providing a place for a
user to store created items.
* `openmct.plugins.UTCTimeSystem` provides a default time system for Open MCT.
A common use case for indicators is to convey the state of some external system such as a
persistence backend or HTTP server. So long as this system is accessible via HTTP request,
Open MCT provides a general purpose indicator to show whether the server is available and
returing a 2xx status code. The URL Status Indicator is made available as a default plugin. See
the [documentation](./src/plugins/URLIndicatorPlugin) for details on how to install and configure the
URL Status Indicator.
### Creating a Simple Indicator
A simple indicator with an icon and some text can be created and added with minimal code. An indicator
of this type exposes functions for customizing the text, icon, and style of the indicator.
Generally, you will want to either install these plugins, or install
different plugins that provide persistence and an initial folder
hierarchy.
eg.
``` javascript
var myIndicator = openmct.indicators.simpleIndicator();
myIndicator.text("Hello World!");
openmct.indicators.add(myIndicator);
```javascript
openmct.install(openmct.plugins.LocalStorage());
openmct.install(openmct.plugins.MyItems());
```
This will create a new indicator and add it to the bottom of the screen in Open MCT.
By default, the indicator will appear as an information icon. Hovering over the icon will
reveal the text set via the call to `.text()`. The Indicator object returned by the API
call exposes a number of functions for customizing the content and appearance of the indicator:
* `.text([text])`: Gets or sets the text shown when the user hovers over the indicator.
Accepts an __optional__ `string` argument that, if provided, will be used to set the text.
Hovering over the indicator will expand it to its full size, revealing this text alongside
the icon. Returns the currently set text as a `string`.
* `.description([description])`: Gets or sets the indicator's description. Accepts an
__optional__ `string` argument that, if provided, will be used to set the text. The description
allows for more detail to be provided in a tooltip when the user hovers over the indicator.
Returns the currently set text as a `string`.
* `.iconClass([className])`: Gets or sets the CSS class used to define the icon. Accepts an __optional__
`string` parameter to be used to set the class applied to the indicator. Any of
[the built-in glyphs](https://nasa.github.io/openmct/style-guide/#/browse/styleguide:home/glyphs?view=styleguide.glyphs)
may be used here, or a custom CSS class can be provided. Returns the currently defined CSS
class as a `string`.
* `.statusClass([className])`: Gets or sets the CSS class used to determine status. Accepts an __optional __
`string` parameter to be used to set a status class applied to the indicator. May be used to apply
different colors to indicate status.
### Custom Indicators
A completely custom indicator can be added by simple providing a DOM element to place alongside other indicators.
``` javascript
var domNode = document.createElement('div');
domNode.innerText = new Date().toString();
setInterval(function () {
domNode.innerText = new Date().toString();
}, 1000);
openmct.indicators.add({
element: domNode
});
```

View File

@@ -20,8 +20,14 @@ API. Open MCT is also being refactored to minimize the dependencies that using
Open MCT imposes on developers, such as the current requirement to use
AngularJS.
This new API has not yet been heavily used and is likely to contain defects.
You can help by trying it out, and reporting any issues you encounter
using our GitHub issue tracker. Such issues may include bugs, suggestions,
missing documentation, or even just requests for help if you're having
trouble.
We want Open MCT to be as easy to use, install, run, and develop for as
possible, and your feedback will help us get there! Feedback can be provided via [GitHub issues](https://github.com/nasa/openmct/issues), or by emailing us at [arc-dl-openmct@nasa.gov](mailto:arc-dl-openmct@nasa.gov).
possible, and your feedback will help us get there!
## Building and Running Open MCT Locally

5
app.js
View File

@@ -19,7 +19,6 @@
// Defaults
options.port = options.port || options.p || 8080;
options.host = options.host || options.h || 'localhost'
options.directory = options.directory || options.D || '.';
['include', 'exclude', 'i', 'x'].forEach(function (opt) {
options[opt] = options[opt] || [];
@@ -79,7 +78,7 @@
app.use(express['static'](options.directory));
// Finally, open the HTTP server and log the instance to the console
app.listen(options.port, options.host, function() {
console.log('Open MCT application running at %s:%s', options.host, options.port)
app.listen(options.port, '0.0.0.0', function() {
console.log('Open MCT application running at localhost:' + options.port)
});
}());

View File

@@ -22,6 +22,7 @@
"eventemitter3": "^1.2.0",
"lodash": "3.10.1",
"almond": "~0.3.2",
"html2canvas": "^0.4.1",
"moment-timezone": "^0.5.13"
}
}
}

27
circle.yml Normal file
View File

@@ -0,0 +1,27 @@
machine:
node:
version: 8.11.0
dependencies:
pre:
- npm install -g npm@latest
deployment:
production:
branch: master
commands:
- npm install canvas nomnoml
- ./build-docs.sh
openmctweb-staging-deux:
branch: mobile
heroku:
appname: openmctweb-staging-deux
test:
post:
- gulp lint
- gulp checkstyle
general:
branches:
ignore:
- gh-pages

View File

@@ -60,8 +60,8 @@ define([
"source": "eventGenerator",
"domains": [
{
"key": "utc",
"name": "Timestamp",
"key": "time",
"name": "Time",
"format": "utc"
}
],

View File

@@ -30,7 +30,6 @@ define([
{
key: "sin",
name: "Sine",
formatString: '%0.2f',
hints: {
range: 1
}
@@ -38,7 +37,6 @@ define([
{
key: "cos",
name: "Cosine",
formatString: '%0.2f',
hints: {
range: 2
}

View File

@@ -72,7 +72,7 @@ define([
var data = [];
while (start <= end && data.length < 5000) {
data.push(pointForTimestamp(start, duration, domainObject.name));
start += duration;
start += 5000;
}
return Promise.resolve(data);
};

View File

@@ -38,8 +38,7 @@ define([
"provides": "identityService",
"type": "provider",
"depends": [
"dialogService",
"$q"
"dialogService"
]
}
]

View File

@@ -55,37 +55,21 @@ define(
* @implements {IdentityService}
* @memberof platform/identity
*/
function ExampleIdentityProvider(dialogService, $q) {
this.dialogService = dialogService;
this.$q = $q;
function ExampleIdentityProvider(dialogService) {
// Handle rejected dialog messages by treating the
// current user as undefined.
function echo(v) { return v; }
function giveUndefined() { return undefined; }
this.returnUser = this.returnUser.bind(this);
this.returnUndefined = this.returnUndefined.bind(this);
this.userPromise =
dialogService.getUserInput(DIALOG_STRUCTURE, DEFAULT_IDENTITY)
.then(echo, giveUndefined);
}
ExampleIdentityProvider.prototype.getUser = function () {
if (this.user) {
return this.$q.when(this.user);
} else {
return this.dialogService.getUserInput(DIALOG_STRUCTURE, DEFAULT_IDENTITY)
.then(this.returnUser, this.returnUndefined);
}
return this.userPromise;
};
/**
* @private
*/
ExampleIdentityProvider.prototype.returnUser = function (user) {
return this.user = user;
}
/**
* @private
*/
ExampleIdentityProvider.prototype.returnUndefined = function () {
return undefined;
}
return ExampleIdentityProvider;
}
);

View File

@@ -1,9 +1,9 @@
<span class="h-indicator" ng-controller="DialogLaunchController">
<span class="status block" ng-controller="DialogLaunchController">
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
<div class="ls-indicator icon-box-with-arrow s-status-available"><span class="label">
<a ng-click="launchProgress(true)">Known</a>
<a ng-click="launchProgress(false)">Unknown</a>
<a ng-click="launchError()">Error</a>
<span class="status-indicator icon-box-with-arrow"></span><span class="label">
<a ng-click="launchProgress(true)">Known</a> |
<a ng-click="launchProgress(false)">Unknown</a> |
<a ng-click="launchError()">Error</a> |
<a ng-click="launchInfo()">Info</a>
</span></div>
</span><span class="count"></span>
</span>

View File

@@ -1,9 +1,9 @@
<span class="h-indicator" ng-controller="NotificationLaunchController">
<span class="status block" ng-controller="NotificationLaunchController">
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
<div class="ls-indicator icon-bell s-status-available"><span class="label">
<a ng-click="newInfo()">Success</a>
<a ng-click="newError()">Error</a>
<a ng-click="newAlert()">Alert</a>
<span class="status-indicator icon-bell"></span><span class="label">
<a ng-click="newInfo()">Success</a> |
<a ng-click="newError()">Error</a> |
<a ng-click="newAlert()">Alert</a> |
<a ng-click="newProgress()">Progress</a>
</span></div>
</span><span class="count"></span>
</span>

View File

@@ -58,10 +58,7 @@
position: relative;
}
.w-mct-example {
color: #ccc;
> div { margin-bottom: $interiorMarginLg; }
}
.w-mct-example > div { margin-bottom: $interiorMarginLg; }
code,
pre {

View File

@@ -149,21 +149,12 @@
<h2>Local Controls</h2>
<div class="cols cols1-1">
<div class="col">
<p>Local controls are typically buttons and selects that provide actions in close proximity to a component.</p>
<p>These controls can optionally be hidden to reduce clutter until the user hovers their cursor over an enclosing element. To use this approach, apply the class <code>.has-local-controls</code> to the element that should be aware of the hover and ensure that element encloses <code>.h-local-controls</code>.</p>
<p>Local controls are typically buttons and selects that provide local control to an individual element. Typically, these controls are hidden in order to not block data display until the user hovers their cursor over an element, when the controls are displayed using a transition fade. Mousing out of the element fades the controls from view.</p>
</div>
<mct-example><div class="plot-display-area" style="padding: 10px; position: relative;">
Some content in here
<div class="h-local-controls h-local-controls-overlay-content l-btn-set">
<mct-example><div class="plot-display-area" style="height: 100px; padding: 10px; position: relative;">Hover over me
<div class="l-local-controls gl-plot-local-controls t-plot-display-controls">
<a class="s-button icon-arrow-left" title="Restore previous pan/zoom"></a>
<a class="s-button icon-reset" title="Reset pan/zoom"></a>
</div>
</div>
<div class="plot-display-area has-local-controls" style="padding: 10px; position: relative;">
Hover here
<div class="h-local-controls h-local-controls-overlay-content local-controls-hidden l-btn-set">
<a class="s-button icon-arrow-left" title="Restore previous pan/zoom"></a>
<a class="s-button icon-reset" title="Reset pan/zoom"></a>
<a class="s-button icon-arrows-out" title="Reset pan/zoom"></a>
</div>
</div></mct-example>
</div>

View File

@@ -20,12 +20,12 @@
at runtime from the About dialog for additional information.
-->
<style>
.w-mct-example div[class*="s-status"],
.w-mct-example span[class*="s-status"],
.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: 3px;
padding: 2px 5px;
border-radius: 4px;
padding: 3px 7px;
}
.w-mct-example table {
width: 100%;
@@ -36,12 +36,65 @@
<h1>Status Indication</h1>
<div class="l-section">
<h2>Status Classes</h2>
<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>Status classes allow any block or inline-block element to be decorated in order to articulate a
status. Provided classes include color-only and color plus icon; custom icons can easily be
employed by using a color-only status class in combination with an <a class="link" href="#/browse/styleguide:home/glyphs?tc.mode=local&tc.timeSystem=utc&tc.startDelta=1800000&tc.endDelta=0&view=styleguide.glyphs">glyph</a>.</p>
<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>
@@ -53,175 +106,37 @@
</ul>
<li>Color and icon</li>
<ul>
<li><code>s-status-icon-warning-hi</code></li>
<li><code>s-status-icon-warning-lo</code></li>
<li><code>s-status-icon-diagnostic</code></li>
<li><code>s-status-icon-info</code></li>
<li><code>s-status-icon-ok</code></li>
<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><!-- Color alone examples -->
<div class="s-status-warning-hi">WARNING HI</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>
<!-- Color and icon examples -->
<div class="s-status-icon-warning-hi">WARNING HI with icon</div>
<div class="s-status-icon-warning-lo">WARNING LOW with icon</div>
<div class="s-status-icon-diagnostic">DIAGNOSTIC with icon</div>
<div class="s-status-icon-info">INFO with icon</div>
<div class="s-status-icon-ok">OK with icon</div>
<div class="s-status-warning-hi icon-alert-triangle">WARNING HI with custom icon</div>
<div>Some text with an <span class="s-status-icon-diagnostic">inline element</span> showing a Diagnostic status.</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>Limit Classes</h2>
<h2>Synchronization</h2>
<div class="cols cols1-1">
<div class="col">
<p>Limit classes are a specialized form of status, specifically meant to be applied to telemetry
displays to indicate that a limit threshold has been violated. Open MCT provides both severity
and direction classes; severity (yellow and red) can be used alone or in combination
with direction (upper or lower). Direction classes cannot be used on their own.</p>
<p>Like Status classes, Limits can be used as color-only, or color plus icon. Custom icons can
be applied in the same fashion as described above.</p>
<ul>
<li>Severity color alone</li>
<ul>
<li><code>s-limit-yellow</code>: A yellow limit.</li>
<li><code>s-limit-red</code>: A red limit.</li>
</ul>
<li>Severity color and icon</li>
<ul>
<li><code>s-limit-icon-yellow</code>: A yellow limit with icon.</li>
<li><code>s-limit-icon-red</code>: A red limit with icon.</li>
</ul>
<li>Direction indicators. MUST be used with a &quot;color alone&quot; limit class. See
examples for more.</li>
<ul>
<li><code>s-limit-upr</code>: Upper limit.</li>
<li><code>s-limit-lwr</code>: Lower limit.</li>
</ul>
</ul>
<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><!-- Color alone examples -->
<div class="s-limit-yellow">Yellow limit</div>
<div class="s-limit-red">Red limit</div>
<!-- Color and icon examples -->
<div class="s-limit-icon-yellow">Yellow limit with icon</div>
<div class="s-limit-icon-red">Red limit with icon</div>
<div class="s-limit-red icon-alert-rect">Red Limit with a custom icon</div>
<div>Some text with an <span class="s-limit-icon-yellow">inline element</span> showing a yellow limit.</div>
<!-- Severity and direction examples -->
<div class="s-limit-yellow s-limit-lwr">Lower yellow limit</div>
<div class="s-limit-red s-limit-upr">Upper red 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-alert-triangle">0.451</td><td>1.007</td></tr>
</table>
<mct-example><div class="s-unsynced">This element is unsynced</div>
</mct-example>
</div>
</div>
<div class="l-section">
<h2>Status Bar Indicators</h2>
<div class="cols cols1-1">
<div class="col">
<p>Indicators are small iconic notification elements that appear in the Status Bar area of
the application at the window's bottom. Indicators should be used to articulate the state of a
system and optionally provide gestures related to that system. They use a combination of icon and
color to identify themselves and articulate a state respectively.</p>
<h3>Recommendations</h3>
<ul>
<li><strong>Keep the icon consistent</strong>. The icon is the principal identifier of the system and is a valuable
recall aid for the user. Don't change the icon as a system's state changes, use color and
text for that purpose.</li>
<li><strong>Don't use the same icon more than once</strong>. Select meaningful and distinct icons so the user
will be able to quickly identify what they're looking for.</li>
</ul>
<h3>States</h3>
<ul>
<li><strong>Disabled</strong>: The system is not available to the user.</li>
<li><strong>Off / Available</strong>: The system is accessible to the user but is not currently
&quot;On&quot; or has not been configured. If the Indicator directly provides gestures
related to the system, such as opening a configuration dialog box, then use
&quot;Available&quot;; if the user must act elsewhere or the system isn't user-controllable,
use &quot;Off&quot;.</li>
<li><strong>On</strong>: The system is enabled or configured; it is having an effect on the larger application.</li>
<li><strong>Alert / Error</strong>: There has been a problem with the system. Generally, &quot;Alert&quot;
should be used to call attention to an issue that isn't critical, while &quot;Error&quot;
should be used to call attention to a problem that the user should really be aware of or do
something about.</li>
</ul>
<h3>Structure</h3>
<p>Indicators consist of a <code>.ls-indicator</code>
wrapper element with <code>.icon-*</code> classes for the type of thing they represent and
<code>.s-status-*</code> classes to articulate the current state. Title attributes should be used
to provide more verbose information about the thing and/or its status.</p>
<p>The wrapper encloses a <code>.label</code> element that is displayed on hover. This element should
include a brief statement of the current status, and can also include clickable elements
as <code>&lt;a&gt;</code> tags. An optional <code>.count</code> element can be included to display
information such as a number of messages.</p>
<p>Icon classes are as defined on the
<a class="link" href="#/browse/styleguide:home/glyphs?tc.mode=local&tc.timeSystem=utc&tc.startDelta=1800000&tc.endDelta=0&view=styleguide.glyphs">
Glyphs page</a>. Status classes applicable to Indicators are as follows:</p>
<ul>
<li><code>s-status-disabled</code></li>
<li><code>s-status-off</code></li>
<li><code>s-status-available</code></li>
<li><code>s-status-on</code></li>
<li><code>s-status-alert</code></li>
<li><code>s-status-error</code></li>
</ul>
</div>
<mct-example><div class="s-ue-bottom-bar status-holder s-status-bar">
<span class="ls-indicator icon-database s-status-disabled" title="The system is currently disabled.">
<span class="label">System not enabled.</span>
</span>
</div>
<div class="s-ue-bottom-bar status-holder s-status-bar">
<span class="ls-indicator icon-database s-status-available" title="Configure data connection.">
<span class="label">Data connection available
<a class="icon-gear">Configure</a>
</span>
</span>
</div>
<div class="s-ue-bottom-bar status-holder s-status-bar">
<span class="ls-indicator icon-database s-status-on" title="Data connected.">
<span class="label">Connected to Skynet
<a class="icon-gear">Change</a>
<a>Disconnect</a>
</span>
</span>
</div>
<div class="s-ue-bottom-bar status-holder s-status-bar">
<span class="ls-indicator icon-database s-status-alert" title="System is self-aware.">
<span class="label">Skynet at Turing Level 5</span>
</span>
<span class="ls-indicator icon-bell s-status-error" title="You have alerts.">
<span class="label">
<a class="icon-alert-triangle">View Alerts</a>
</span>
<span class="count">495</span>
</span>
</div>
</mct-example>
</div>
</div>
</div>
</div>

View File

@@ -54,7 +54,7 @@ define(
return "icon-object-unknown";
},
getText: function () {
return "" + latest;
return latest;
},
getDescription: function () {
return "";

View File

@@ -31,6 +31,7 @@ var gulp = require('gulp'),
git = require('git-rev-sync'),
moment = require('moment'),
project = require('./package.json'),
_ = require('lodash'),
paths = {
main: 'openmct.js',
dist: 'dist',
@@ -139,7 +140,7 @@ gulp.task('checkstyle', function () {
var mkdirp = require('mkdirp');
var reportName = 'jscs-html-report.html';
var reportPath = path.resolve(paths.reports, 'checkstyle', reportName);
var moveReport = fs.rename.bind(fs, reportName, reportPath, function () {});
var moveReport = fs.rename.bind(fs, reportName, reportPath, _.noop);
mkdirp.sync(path.resolve(paths.reports, 'checkstyle'));
@@ -178,4 +179,4 @@ gulp.task('install', [ 'assets', 'scripts' ]);
gulp.task('verify', [ 'lint', 'test', 'checkstyle' ]);
gulp.task('build', [ 'verify', 'install' ]);
gulp.task('build', [ 'verify', 'install' ]);

View File

@@ -69,11 +69,9 @@
]
}));
openmct.install(openmct.plugins.SummaryWidget());
openmct.install(openmct.plugins.Notebook());
openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
openmct.time.timeSystem('utc');
openmct.start();
window.openmct = openmct;
});
</script>
<link rel="stylesheet" href="platform/commonUI/general/res/css/startup-base.css">

View File

@@ -37,10 +37,7 @@ module.exports = function(config) {
{pattern: 'bower_components/**/*.js', included: false},
{pattern: 'node_modules/d3-*/**/*.js', included: false},
{pattern: 'node_modules/vue/**/*.js', included: false},
{pattern: 'node_modules/printj/dist/*.js', included: false},
{pattern: 'src/**/*', included: false},
{pattern: 'node_modules/painterro/build/*.js', included: false},
{pattern: 'node_modules/html2canvas/dist/*', included: false},
{pattern: 'example/**/*.html', included: false},
{pattern: 'example/**/*.js', included: false},
{pattern: 'example/**/*.json', included: false},
@@ -65,7 +62,7 @@ module.exports = function(config) {
// Test results reporter to use
// Possible values: 'dots', 'progress'
// Available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage', 'html'],
reporters: ['progress', 'coverage', 'html', 'junit'],
// Web server port.
port: 9876,
@@ -81,7 +78,7 @@ module.exports = function(config) {
// Specify browsers to run tests in.
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: [
'ChromeHeadless'
'Chrome'
],
// Code coverage reporting.
@@ -104,6 +101,10 @@ module.exports = function(config) {
foldAll: false
},
junitReporter: {
outputDir: process.env.CIRCLE_TEST_REPORTS || 'dist/reports/junit'
},
// Continuous Integration mode.
// If true, Karma captures browsers, runs the tests and exits.
singleRun: true

View File

@@ -29,6 +29,7 @@ requirejs.config({
"csv": "bower_components/comma-separated-values/csv.min",
"EventEmitter": "bower_components/eventemitter3/index",
"es6-promise": "bower_components/es6-promise/es6-promise.min",
"html2canvas": "bower_components/html2canvas/build/html2canvas.min",
"moment": "bower_components/moment/moment",
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
"moment-timezone": "bower_components/moment-timezone/builds/moment-timezone-with-data",
@@ -41,17 +42,14 @@ requirejs.config({
"lodash": "bower_components/lodash/lodash",
"d3-selection": "node_modules/d3-selection/dist/d3-selection.min",
"d3-scale": "node_modules/d3-scale/build/d3-scale.min",
"d3-axis": "node_modules/d3-axis/dist/d3-axis.min",
"d3-array": "node_modules/d3-array/dist/d3-array.min",
"d3-collection": "node_modules/d3-collection/dist/d3-collection.min",
"d3-axis": "node_modules/d3-axis/build/d3-axis.min",
"d3-array": "node_modules/d3-array/build/d3-array.min",
"d3-collection": "node_modules/d3-collection/build/d3-collection.min",
"d3-color": "node_modules/d3-color/build/d3-color.min",
"d3-format": "node_modules/d3-format/build/d3-format.min",
"d3-interpolate": "node_modules/d3-interpolate/build/d3-interpolate.min",
"d3-time": "node_modules/d3-time/dist/d3-time.min",
"d3-time-format": "node_modules/d3-time-format/dist/d3-time-format.min",
"html2canvas": "node_modules/html2canvas/dist/html2canvas.min",
"painterro": "node_modules/painterro/build/painterro.min",
"printj": "node_modules/printj/dist/printj.min"
"d3-time": "node_modules/d3-time/build/d3-time.min",
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min"
},
"shim": {
"angular": {
@@ -63,12 +61,12 @@ requirejs.config({
"EventEmitter": {
"exports": "EventEmitter"
},
"html2canvas": {
"exports": "html2canvas"
},
"moment-duration-format": {
"deps": ["moment"]
},
"painterro": {
"exports": "Painterro"
},
"saveAs": {
"exports": "saveAs"
},
@@ -90,9 +88,6 @@ requirejs.config({
},
"d3-axis": {
"exports": "d3-axis"
},
"dom-to-image": {
"exports": "domtoimage"
}
}
});

View File

@@ -1,7 +1,7 @@
{
"name": "openmct",
"version": "0.14.0-SNAPSHOT",
"description": "The Open MCT core platform.",
"description": "The Open MCT core platform",
"dependencies": {
"d3-array": "1.2.x",
"d3-axis": "1.0.x",
@@ -15,7 +15,6 @@
"d3-time-format": "2.1.x",
"express": "^4.13.1",
"minimist": "^1.1.1",
"painterro": "^0.2.65",
"request": "^2.69.0",
"vue": "^2.5.6"
},
@@ -31,25 +30,25 @@
"gulp-requirejs-optimize": "^0.3.1",
"gulp-sass": "^3.1.0",
"gulp-sourcemaps": "^1.6.0",
"html2canvas": "^1.0.0-alpha.12",
"jasmine-core": "^3.1.0",
"jasmine-core": "^2.3.0",
"jscs-html-reporter": "^0.1.0",
"jsdoc": "^3.3.2",
"jshint": "^2.7.0",
"karma": "^2.0.3",
"karma-chrome-launcher": "^2.2.0",
"karma-cli": "^1.0.1",
"karma-coverage": "^1.1.2",
"karma": "^0.13.3",
"karma-chrome-launcher": "^0.1.12",
"karma-cli": "0.0.4",
"karma-coverage": "^0.5.3",
"karma-html-reporter": "^0.2.7",
"karma-jasmine": "^1.1.2",
"karma-requirejs": "^1.1.0",
"karma-jasmine": "^0.1.5",
"karma-junit-reporter": "^0.3.8",
"karma-requirejs": "^0.2.2",
"lodash": "^3.10.1",
"markdown-toc": "^0.11.7",
"marked": "^0.3.5",
"merge-stream": "^1.0.0",
"mkdirp": "^0.5.1",
"moment": "^2.11.1",
"node-bourbon": "^4.2.3",
"printj": "^1.1.0",
"requirejs": "2.1.x",
"split": "^1.0.0",
"v8-compile-cache": "^1.1.0"
@@ -58,8 +57,6 @@
"start": "node app.js",
"test": "karma start --single-run",
"jshint": "jshint platform example",
"lint": "./node_modules/gulp/bin/gulp.js lint",
"checkstyle": "./node_modules/gulp/bin/gulp.js checkstyle",
"watch": "karma start",
"jsdoc": "jsdoc -c jsdoc.json -R API.md -r -d dist/docs/api",
"otherdoc": "node docs/gendocs.js --in docs/src --out dist/docs --suppress-toc 'docs/src/index.md|docs/src/process/index.md'",

View File

@@ -65,7 +65,7 @@
<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'"
class="abs holder holder-object t-main-view">
class="abs holder holder-object">
</mct-representation>
<a class="mini-tab-icon anchor-right mobile-hide toggle-pane toggle-inspect flush-right"
title="{{ modelPaneInspect.visible()? 'Hide' : 'Show' }} the Inspection pane"

View File

@@ -19,46 +19,41 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div ng-controller="ObjectInspectorController as controller" class="grid-properties">
<ul class="l-inspector-part">
<h2 class="first">Properties</h2>
<li class="t-repeat grid-row"
ng-repeat="data in metadata"
ng-class="{ first:$index === 0 }">
<div class="grid-cell label">{{ data.name }}</div>
<div class="grid-cell value">{{ data.value }}</div>
</li>
</ul>
<ul class="l-inspector-part" ng-if="contextutalParents.length > 0">
<h2 title="The location of this linked object.">Location</h2>
<li class="grid-row">
<div class="label" ng-if="primaryParents.length > 0">This Link</div>
<div class="grid-cell value">
<div class="t-repeat inspector-location"
ng-repeat="parent in contextutalParents"
ng-class="{ last:($index + 1) === contextualParents.length }">
<mct-representation key="'label'"
mct-object="parent"
ng-click="parent.getCapability('action').perform('navigate')"
class="location-item">
</mct-representation>
</div>
<div ng-controller="ObjectInspectorController as controller">
<ul class="flex-elem grows l-inspector-part">
<li>
<em class="t-inspector-part-header">Properties</em>
<div class="inspector-properties"
ng-repeat="data in metadata"
ng-class="{ first:$index === 0 }">
<div class="label">{{ data.name }}</div>
<div class="value">{{ data.value }}</div>
</div>
</li>
<li class="grid-row" ng-if="primaryParents.length > 0">
<div class="grid-cell label">Original</div>
<div class="grid-cell value">
<div class="t-repeat inspector-location value"
ng-repeat="parent in primaryParents"
ng-class="{ last:($index + 1) === primaryParents.length }">
<mct-representation key="'label'"
mct-object="parent"
ng-click="parent.getCapability('action').perform('navigate')"
class="location-item">
</mct-representation>
</div>
</div>
<li ng-if="contextutalParents.length > 0">
<em class="t-inspector-part-header" title="The location of this linked object.">Location</em>
<div ng-if="primaryParents.length > 0" class="section-header">This Object</div>
<span class="inspector-location"
ng-repeat="parent in contextutalParents"
ng-class="{ last:($index + 1) === contextualParents.length }">
<mct-representation key="'label'"
mct-object="parent"
ng-click="parent.getCapability('action').perform('navigate')"
class="location-item">
</mct-representation>
</span>
</li>
<li ng-if="primaryParents.length > 0">
<div class="section-header">Object's Original</div>
<span class="inspector-location"
ng-repeat="parent in primaryParents"
ng-class="{ last:($index + 1) === primaryParents.length }">
<mct-representation key="'label'"
mct-object="parent"
ng-click="parent.getCapability('action').perform('navigate')"
class="location-item">
</mct-representation>
</span>
</li>
</ul>
</div>

View File

@@ -47,8 +47,8 @@ define(
urlService,
defaultPath
) {
var initialPath = ($route.current.params.ids || defaultPath).split("/"),
currentIds;
var initialPath = ($route.current.params.ids || defaultPath).split("/");
var currentIds;
$scope.treeModel = {
selectedObject: undefined,
@@ -56,24 +56,7 @@ define(
navigationService.setNavigation(object, true);
},
allowSelection: function (object) {
var domainObjectInView = navigationService.getNavigation(),
isInEditMode = domainObjectInView.getCapability('status').get('editing');
if (isInEditMode) {
var actions = object.getCapability('action'),
previewAction = actions.getActions({key: 'mct-preview-action'})[0];
if (previewAction && previewAction.perform) {
previewAction.perform();
return false;
} else {
return navigationService.shouldNavigate();
}
} else {
return true;
}
return navigationService.shouldNavigate();
}
};

View File

@@ -56,7 +56,7 @@ define(
// declared as a method but as a property which happens to
// be a function.
if (agentService.isPhone() && agentService.isPortrait()) {
// On phones, trees should collapse in portrait mode
// On phones, πs should collapse in portrait mode
// when something is navigated-to.
self.state = false;
}

View File

@@ -162,6 +162,7 @@ define(
*/
NavigationService.prototype.shouldWarnBeforeNavigate = function () {
var reasons = [];
this.checks.forEach(function (checkFn) {
var reason = checkFn();
if (reason) {

View File

@@ -19,7 +19,6 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global console*/
/**
* MCTRepresentationSpec. Created by vwoeltje on 11/6/14.
@@ -49,19 +48,9 @@ define(
controller;
function waitsForNavigation() {
return new Promise(function (resolve) {
mockNavigationService.setNavigation.and.callFake(function (obj) {
var returnValue;
try {
returnValue = NavigationService.prototype.setNavigation.call(mockNavigationService, obj);
} catch (err) {
console.error(err);
//Not rejecting because 'setNavigation' has been called, which is what's being tested here.
//Rejecting will fail tests.
}
resolve();
return returnValue;
});
var calls = mockNavigationService.setNavigation.calls.length;
waitsFor(function () {
return mockNavigationService.setNavigation.calls.length > calls;
});
}
@@ -89,7 +78,7 @@ define(
"urlService",
["urlForLocation"]
);
mockUrlService.urlForLocation.and.callFake(function (mode, object) {
mockUrlService.urlForLocation.andCallFake(function (mode, object) {
if (object === mockDefaultRootObject) {
return [mode, testDefaultRoot].join('/');
}
@@ -117,7 +106,7 @@ define(
"removeListener"
].forEach(function (method) {
spyOn(mockNavigationService, method)
.and.callThrough();
.andCallThrough();
});
mockRootObject = jasmine.createSpyObj(
"rootObjectContainer",
@@ -135,58 +124,60 @@ define(
"nestedDomainObject",
["getId", "getCapability", "getModel", "useCapability", "hasCapability"]
);
mockObjectService.getObjects.and.returnValue(Promise.resolve({
mockObjectService.getObjects.andReturn(Promise.resolve({
ROOT: mockRootObject
}));
mockRootObject.useCapability.and.returnValue(Promise.resolve([
mockRootObject.useCapability.andReturn(Promise.resolve([
mockOtherDomainObject,
mockDefaultRootObject
]));
mockRootObject.hasCapability.and.returnValue(true);
mockDefaultRootObject.useCapability.and.returnValue(Promise.resolve([
mockRootObject.hasCapability.andReturn(true);
mockDefaultRootObject.useCapability.andReturn(Promise.resolve([
mockNextObject
]));
mockDefaultRootObject.hasCapability.and.returnValue(true);
mockOtherDomainObject.hasCapability.and.returnValue(false);
mockNextObject.useCapability.and.returnValue(undefined);
mockNextObject.hasCapability.and.returnValue(false);
mockNextObject.getId.and.returnValue("next");
mockDefaultRootObject.getId.and.returnValue(testDefaultRoot);
mockDefaultRootObject.hasCapability.andReturn(true);
mockOtherDomainObject.hasCapability.andReturn(false);
mockNextObject.useCapability.andReturn(undefined);
mockNextObject.hasCapability.andReturn(false);
mockNextObject.getId.andReturn("next");
mockDefaultRootObject.getId.andReturn(testDefaultRoot);
instantiateController();
return waitsForNavigation();
waitsForNavigation();
});
it("uses composition to set the navigated object, if there is none", function () {
instantiateController();
return waitsForNavigation().then(function () {
waitsForNavigation();
runs(function () {
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDefaultRootObject);
.toHaveBeenCalledWith(mockDefaultRootObject);
});
});
it("navigates to a root-level object, even when default path is not found", function () {
mockDefaultRootObject.getId
.and.returnValue("something-other-than-the-" + testDefaultRoot);
.andReturn("something-other-than-the-" + testDefaultRoot);
instantiateController();
return waitsForNavigation().then(function () {
waitsForNavigation();
runs(function () {
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDefaultRootObject);
.toHaveBeenCalledWith(mockDefaultRootObject);
});
});
});
//
it("does not try to override navigation", function () {
mockNavigationService.getNavigation.and.returnValue(mockDefaultRootObject);
mockNavigationService.getNavigation.andReturn(mockDefaultRootObject);
instantiateController();
return waitsForNavigation().then(function () {
expect(mockScope.navigatedObject).toBe(mockDefaultRootObject);
});
waitsForNavigation();
expect(mockScope.navigatedObject).toBe(mockDefaultRootObject);
});
//
it("updates scope when navigated object changes", function () {
// Should have registered a listener - call it
mockNavigationService.addListener.calls.mostRecent().args[0](
mockNavigationService.addListener.mostRecentCall.args[0](
mockOtherDomainObject
);
expect(mockScope.navigatedObject).toEqual(mockOtherDomainObject);
@@ -198,18 +189,19 @@ define(
"$destroy",
jasmine.any(Function)
);
mockScope.$on.calls.mostRecent().args[1]();
mockScope.$on.mostRecentCall.args[1]();
// Should remove the listener it added earlier
expect(mockNavigationService.removeListener).toHaveBeenCalledWith(
mockNavigationService.addListener.calls.mostRecent().args[0]
mockNavigationService.addListener.mostRecentCall.args[0]
);
});
it("uses route parameters to choose initially-navigated object", function () {
mockRoute.current.params.ids = testDefaultRoot + "/next";
instantiateController();
return waitsForNavigation().then(function () {
waitsForNavigation();
runs(function () {
expect(mockScope.navigatedObject).toBe(mockNextObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockNextObject);
@@ -222,10 +214,12 @@ define(
// it hits an invalid ID.
mockRoute.current.params.ids = testDefaultRoot + "/junk";
instantiateController();
return waitsForNavigation().then(function () {
waitsForNavigation();
runs(function () {
expect(mockScope.navigatedObject).toBe(mockDefaultRootObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDefaultRootObject);
});
});
@@ -235,7 +229,8 @@ define(
// should stop at it since remaining IDs cannot be loaded.
mockRoute.current.params.ids = testDefaultRoot + "/next/junk";
instantiateController();
return waitsForNavigation().then(function () {
waitsForNavigation();
runs(function () {
expect(mockScope.navigatedObject).toBe(mockNextObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockNextObject);
@@ -249,11 +244,11 @@ define(
expect(mockRoute.current.pathParams.ids)
.not
.toBe(testDefaultRoot + '/next');
mockLocation.path.and.callFake(function () {
mockLocation.path.andCallFake(function () {
expect(mockRoute.current.pathParams.ids)
.toBe(testDefaultRoot + '/next');
});
mockNavigationService.addListener.calls.mostRecent().args[0](
mockNavigationService.addListener.mostRecentCall.args[0](
mockNextObject
);
expect(mockLocation.path).toHaveBeenCalledWith(

View File

@@ -20,6 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
["../src/BrowseObjectController"],
function (BrowseObjectController) {
@@ -32,7 +33,7 @@ define(
// Utility function; look for a $watch on scope and fire it
function fireWatch(expr, value) {
mockScope.$watch.calls.all().forEach(function (call) {
mockScope.$watch.calls.forEach(function (call) {
if (call.args[0] === expr) {
call.args[1](value);
}
@@ -49,7 +50,7 @@ define(
"$location",
["path", "search"]
);
mockLocation.search.and.returnValue({});
mockLocation.search.andReturn({});
controller = new BrowseObjectController(
mockScope,
@@ -64,7 +65,7 @@ define(
// Allows the path index to be checked
// prior to setting $route.current
mockLocation.path.and.returnValue("/browse/");
mockLocation.path.andReturn("/browse/");
});
it("sets the active view from query parameters", function () {
@@ -78,10 +79,10 @@ define(
{ key: 'xyz' }
];
mockDomainObject.useCapability.and.callFake(function (c) {
mockDomainObject.useCapability.andCallFake(function (c) {
return (c === 'view') && testViews;
});
mockLocation.search.and.returnValue({ view: 'def' });
mockLocation.search.andReturn({ view: 'def' });
fireWatch('domainObject', mockDomainObject);
expect(mockScope.representation.selected)

View File

@@ -50,14 +50,14 @@ define(
"navigationService",
["getNavigation", "addListener"]
);
mockNavigationService.addListener.and.returnValue(mockNavigationUnlistener);
mockNavigationService.addListener.andReturn(mockNavigationUnlistener);
mockStatusUnlistener = jasmine.createSpy("statusUnlistener");
mockStatusCapability = jasmine.createSpyObj(
"statusCapability",
["listen"]
);
mockStatusCapability.listen.and.returnValue(mockStatusUnlistener);
mockStatusCapability.listen.andReturn(mockStatusUnlistener);
mockDomainObject = jasmine.createSpyObj(
'domainObject',
@@ -68,13 +68,13 @@ define(
'hasCapability'
]
);
mockDomainObject.getId.and.returnValue("domainObject");
mockDomainObject.getModel.and.returnValue({});
mockDomainObject.hasCapability.and.returnValue(true);
mockDomainObject.getCapability.and.returnValue(mockStatusCapability);
mockDomainObject.getId.andReturn("domainObject");
mockDomainObject.getModel.andReturn({});
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andReturn(mockStatusCapability);
mockLocation = jasmine.createSpyObj('location', ['search']);
mockLocation.search.and.returnValue({});
mockLocation.search.andReturn({});
mockAttrs = {};
@@ -84,7 +84,7 @@ define(
it("listens for changes to navigation and attaches a status" +
" listener", function () {
expect(mockNavigationService.addListener).toHaveBeenCalledWith(jasmine.any(Function));
mockNavigationService.addListener.calls.mostRecent().args[0](mockDomainObject);
mockNavigationService.addListener.mostRecentCall.args[0](mockDomainObject);
expect(mockStatusCapability.listen).toHaveBeenCalledWith(jasmine.any(Function));
});
@@ -93,8 +93,8 @@ define(
controller.toggle();
// test pre-condition that inspector is hidden
expect(controller.visible()).toBe(false);
mockNavigationService.addListener.calls.mostRecent().args[0](mockDomainObject);
mockStatusCapability.listen.calls.mostRecent().args[0](["editing"]);
mockNavigationService.addListener.mostRecentCall.args[0](mockDomainObject);
mockStatusCapability.listen.mostRecentCall.args[0](["editing"]);
expect(controller.visible()).toBe(true);
});

View File

@@ -60,8 +60,8 @@ define(
mockActionContext.domainObject = mockDomainObject;
mockActionContext.event = mockEvent;
mockScope.domainObject = mockDomainObject;
mockDomainObject.getCapability.and.returnValue(mockContextMenuAction);
mockContextMenuAction.perform.and.returnValue(jasmine.any(Function));
mockDomainObject.getCapability.andReturn(mockContextMenuAction);
mockContextMenuAction.perform.andReturn(jasmine.any(Function));
controller = new MenuArrowController(mockScope);
});

View File

@@ -39,7 +39,7 @@ define(
mockMutationCapability = jasmine.createSpyObj("mutation", ["mutate"]);
mockTypeCapability = jasmine.createSpyObj("type", ["typeDef", "hasFeature"]);
mockTypeCapability.typeDef = { name: ""};
mockTypeCapability.hasFeature.and.callFake(function (feature) {
mockTypeCapability.hasFeature.andCallFake(function (feature) {
return feature === 'creation';
});
@@ -52,8 +52,8 @@ define(
name: "Test name"
};
mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "getModel"]);
mockDomainObject.getModel.and.returnValue(model);
mockDomainObject.getCapability.and.callFake(function (key) {
mockDomainObject.getModel.andReturn(model);
mockDomainObject.getCapability.andCallFake(function (key) {
return mockCapabilities[key];
});
@@ -62,7 +62,7 @@ define(
};
mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur", "textContent"]);
mockCurrentTarget.blur.and.returnValue(mockCurrentTarget);
mockCurrentTarget.blur.andReturn(mockCurrentTarget);
mockEvent = {
which: {},
@@ -109,7 +109,7 @@ define(
expect(mockMutationCapability.mutate).toHaveBeenCalledWith(jasmine.any(Function));
mockMutationCapability.mutate.calls.mostRecent().args[0](model);
mockMutationCapability.mutate.mostRecentCall.args[0](model);
expect(mockDomainObject.getModel().name).toBe("New name");
});
@@ -127,7 +127,7 @@ define(
});
it("disallows editting name when object is non-creatable", function () {
mockTypeCapability.hasFeature.and.returnValue(false);
mockTypeCapability.hasFeature.andReturn(false);
expect(controller.allowEdit()).toBe(false);

View File

@@ -53,8 +53,8 @@ define(
['getId', 'getModel', 'getCapability']
);
mockDomainObject.getId.and.returnValue(id);
mockDomainObject.getModel.and.returnValue({});
mockDomainObject.getId.andReturn(id);
mockDomainObject.getModel.andReturn({});
return mockDomainObject;
});
@@ -65,7 +65,7 @@ define(
mockWindow = jasmine.createSpyObj("$window", ["open"]);
mockLocation = jasmine.createSpyObj('location', ['search']);
mockLocation.search.and.returnValue({});
mockLocation.search.andReturn({});
mockAttrs = {};
});
@@ -83,9 +83,9 @@ define(
});
it("collapses on navigation changes on portrait-oriented phones", function () {
mockAgentService.isMobile.and.returnValue(true);
mockAgentService.isPhone.and.returnValue(true);
mockAgentService.isPortrait.and.returnValue(true);
mockAgentService.isMobile.andReturn(true);
mockAgentService.isPhone.andReturn(true);
mockAgentService.isPortrait.andReturn(true);
controller = instantiateController();
expect(controller.visible()).toBeTruthy();
@@ -102,13 +102,13 @@ define(
});
it("sets pane state to false when in location.search", function () {
mockLocation.search.and.returnValue({'hideTree': true});
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.and.returnValue({});
mockLocation.search.andReturn({});
expect(instantiateController().visible()).toBe(true);
expect(mockLocation.search).not.toHaveBeenCalledWith('hideTree', undefined);
});

View File

@@ -34,6 +34,17 @@ define([
mockDomainObject,
action;
function waitForCall() {
var called = false;
waitsFor(function () {
return called;
});
return function () {
called = true;
};
}
beforeEach(function () {
mockNavigationService = jasmine.createSpyObj(
"navigationService",
@@ -52,24 +63,26 @@ define([
});
it("sets navigation if it is allowed", function () {
mockNavigationService.shouldNavigate.and.returnValue(true);
return action.perform()
.then(function () {
expect(mockNavigationService.setNavigation)
mockNavigationService.shouldNavigate.andReturn(true);
action.perform()
.then(waitForCall());
runs(function () {
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDomainObject, true);
});
});
});
it("does not set navigation if it is not allowed", function () {
mockNavigationService.shouldNavigate.and.returnValue(false);
mockNavigationService.shouldNavigate.andReturn(false);
var onSuccess = jasmine.createSpy('onSuccess');
return action.perform()
.then(onSuccess, function () {
expect(onSuccess).not.toHaveBeenCalled();
expect(mockNavigationService.setNavigation)
.not
.toHaveBeenCalledWith(mockDomainObject);
});
action.perform()
.then(onSuccess, waitForCall());
runs(function () {
expect(onSuccess).not.toHaveBeenCalled();
expect(mockNavigationService.setNavigation)
.not
.toHaveBeenCalledWith(mockDomainObject);
});
});
it("is only applicable when a domain object is in context", function () {

View File

@@ -69,7 +69,7 @@ define(
navigationService.addListener(callback);
navigationService.setNavigation(testObject);
navigationService.setNavigation(testObject);
expect(callback.calls.count()).toEqual(1);
expect(callback.calls.length).toEqual(1);
});
it("stops notifying listeners after removal", function () {

View File

@@ -65,35 +65,34 @@ define([
mockActionCapability = jasmine.createSpyObj('action', ['perform']);
mockEditor = jasmine.createSpyObj('editor', ['isEditContextRoot']);
mockThrottle.and.callFake(function (fn) {
mockThrottle.andCallFake(function (fn) {
var mockThrottledFn =
jasmine.createSpy('throttled-' + mockThrottledFns.length);
mockThrottledFn.and.callFake(fn);
mockThrottledFn.andCallFake(fn);
mockThrottledFns.push(mockThrottledFn);
return mockThrottledFn;
});
mockTopic.and.returnValue(mockMutationTopic);
mockDomainObject.getId.and.returnValue(testId);
mockDomainObject.getCapability.and.callFake(function (c) {
mockTopic.andReturn(mockMutationTopic);
mockDomainObject.getId.andReturn(testId);
mockDomainObject.getCapability.andCallFake(function (c) {
return {
context: mockContext,
editor: mockEditor
}[c];
});
mockDomainObject.hasCapability.and.callFake(function (c) {
mockDomainObject.hasCapability.andCallFake(function (c) {
return !!mockDomainObject.getCapability(c);
});
mockParentObject.getCapability.and.callFake(function (c) {
mockParentObject.getCapability.andCallFake(function (c) {
return {
action: mockActionCapability
}[c];
});
testParentComposition = [];
mockParentObject.useCapability.and.returnValue(Promise.resolve(testParentComposition));
mockContext.getParent.and.returnValue(mockParentObject);
mockNavigationService.getNavigation.and.returnValue(mockDomainObject);
mockEditor.isEditContextRoot.and.returnValue(false);
mockParentObject.useCapability.andReturn(Promise.resolve(testParentComposition));
mockContext.getParent.andReturn(mockParentObject);
mockNavigationService.getNavigation.andReturn(mockDomainObject);
mockEditor.isEditContextRoot.andReturn(false);
return new OrphanNavigationHandler(
mockThrottle,
@@ -107,7 +106,7 @@ define([
expect(mockMutationTopic.listen)
.toHaveBeenCalledWith(jasmine.any(Function));
expect(mockThrottledFns.indexOf(
mockMutationTopic.listen.calls.mostRecent().args[0]
mockMutationTopic.listen.mostRecentCall.args[0]
)).not.toEqual(-1);
});
@@ -115,7 +114,7 @@ define([
expect(mockNavigationService.addListener)
.toHaveBeenCalledWith(jasmine.any(Function));
expect(mockThrottledFns.indexOf(
mockNavigationService.addListener.calls.mostRecent().args[0]
mockNavigationService.addListener.mostRecentCall.args[0]
)).not.toEqual(-1);
});
@@ -135,14 +134,28 @@ define([
function itNavigatesAsExpected() {
if (isOrphan && !isEditRoot) {
it("navigates to the parent", function () {
return Promise.resolve().then(function () {
var done = false;
waitsFor(function () {
return done;
});
setTimeout(function () {
done = true;
}, 5);
runs(function () {
expect(mockActionCapability.perform)
.toHaveBeenCalledWith('navigate');
});
});
} else {
it("does nothing", function () {
return Promise.resolve().then(function () {
var done = false;
waitsFor(function () {
return done;
});
setTimeout(function () {
done = true;
}, 5);
runs(function () {
expect(mockActionCapability.perform)
.not.toHaveBeenCalled();
});
@@ -152,12 +165,12 @@ define([
describe(caseName, function () {
beforeEach(function () {
mockEditor.isEditContextRoot.and.returnValue(isEditRoot);
mockEditor.isEditContextRoot.andReturn(isEditRoot);
});
describe("when navigation changes", function () {
beforeEach(function () {
mockNavigationService.addListener.calls.mostRecent()
mockNavigationService.addListener.mostRecentCall
.args[0](mockDomainObject);
});
itNavigatesAsExpected();
@@ -165,7 +178,7 @@ define([
describe("when mutation occurs", function () {
beforeEach(function () {
mockMutationTopic.listen.calls.mostRecent()
mockMutationTopic.listen.mostRecentCall
.args[0](mockParentObject);
});

View File

@@ -49,8 +49,8 @@ define(
);
mockDocument = [{}];
mockDomainObject.getModel.and.returnValue({ name: 'Test name' });
mockNavigationService.getNavigation.and.returnValue(mockDomainObject);
mockDomainObject.getModel.andReturn({ name: 'Test name' });
mockNavigationService.getNavigation.andReturn(mockDomainObject);
titler = new WindowTitler(
mockNavigationService,
@@ -64,12 +64,12 @@ define(
jasmine.any(Function),
jasmine.any(Function)
);
expect(mockRootScope.$watch.calls.mostRecent().args[0]())
expect(mockRootScope.$watch.mostRecentCall.args[0]())
.toEqual('Test name');
});
it("sets the title to the name of the navigated object", function () {
mockRootScope.$watch.calls.mostRecent().args[1]("Some name");
mockRootScope.$watch.mostRecentCall.args[1]("Some name");
expect(mockDocument[0].title).toEqual("Some name");
});

View File

@@ -4,10 +4,7 @@
<div class="top-bar">
<div class="title">{{ngModel.title}}</div>
</div>
<div class="hint" ng-hide="ngModel.hint === undefined">
{{ngModel.hint}}
<span ng-if="ngModel.timestamp !== undefined">[{{ngModel.timestamp}}]</span>
</div>
<div class="hint" ng-hide="ngModel.hint === undefined">{{ngModel.hint}}</div>
<div class="message-body">
<div class="message-action">
{{ngModel.actionText}}

View File

@@ -63,12 +63,12 @@ define(
["find"]
);
mockBody = jasmine.createSpyObj('body', ['on', 'off']);
mockDocument.find.and.returnValue(mockBody);
mockDocument.find.andReturn(mockBody);
mockDeferred.promise = "mock promise";
mockQ.defer.and.returnValue(mockDeferred);
mockOverlayService.createOverlay.and.returnValue(mockOverlay);
mockQ.defer.andReturn(mockDeferred);
mockOverlayService.createOverlay.andReturn(mockOverlay);
dialogService = new DialogService(
mockOverlayService,
@@ -85,7 +85,7 @@ define(
it("allows user input to be canceled", function () {
dialogService.getUserInput({}, { someKey: "some value" });
mockOverlayService.createOverlay.calls.mostRecent().args[1].cancel();
mockOverlayService.createOverlay.mostRecentCall.args[1].cancel();
expect(mockDeferred.reject).toHaveBeenCalled();
expect(mockDeferred.resolve).not.toHaveBeenCalled();
});
@@ -93,7 +93,7 @@ define(
it("passes back the result of user input when confirmed", function () {
var value = { someKey: 42 };
dialogService.getUserInput({}, value);
mockOverlayService.createOverlay.calls.mostRecent().args[1].confirm();
mockOverlayService.createOverlay.mostRecentCall.args[1].confirm();
expect(mockDeferred.reject).not.toHaveBeenCalled();
expect(mockDeferred.resolve).toHaveBeenCalledWith(value);
});
@@ -109,7 +109,7 @@ define(
it("can show multiple dialogs if prior ones are dismissed", function () {
dialogService.getUserInput({}, {});
expect(mockLog.warn).not.toHaveBeenCalled();
mockOverlayService.createOverlay.calls.mostRecent().args[1].confirm();
mockOverlayService.createOverlay.mostRecentCall.args[1].confirm();
dialogService.getUserInput({}, {});
expect(mockLog.warn).not.toHaveBeenCalled();
expect(mockDeferred.reject).not.toHaveBeenCalled();
@@ -148,13 +148,13 @@ define(
it("destroys the event listener when the dialog is cancelled", function () {
dialogService.getUserInput({}, {});
mockOverlayService.createOverlay.calls.mostRecent().args[1].cancel();
mockOverlayService.createOverlay.mostRecentCall.args[1].cancel();
expect(mockBody.off).toHaveBeenCalledWith("keydown", jasmine.any(Function));
});
it("cancels the dialog when an escape keydown event is triggered", function () {
dialogService.getUserInput({}, {});
mockBody.on.calls.mostRecent().args[1]({
mockBody.on.mostRecentCall.args[1]({
keyCode: 27
});
expect(mockDeferred.reject).toHaveBeenCalled();
@@ -163,7 +163,7 @@ define(
it("ignores non escape keydown events", function () {
dialogService.getUserInput({}, {});
mockBody.on.calls.mostRecent().args[1]({
mockBody.on.mostRecentCall.args[1]({
keyCode: 13
});
expect(mockDeferred.reject).not.toHaveBeenCalled();
@@ -197,7 +197,7 @@ define(
"overlay",
["dismiss"]
);
mockOverlayService.createOverlay.and.returnValue(secondMockOverlay);
mockOverlayService.createOverlay.andReturn(secondMockOverlay);
secondDialogHandle = dialogService.showBlockingMessage(dialogModel);
//Dismiss the first dialog. It should only dismiss if it

View File

@@ -46,10 +46,10 @@ define(
mockElement = jasmine.createSpyObj("element", ["remove"]);
mockScope = jasmine.createSpyObj("scope", ["$destroy"]);
mockDocument.find.and.returnValue(mockBody);
mockCompile.and.returnValue(mockTemplate);
mockRootScope.$new.and.returnValue(mockScope);
mockTemplate.and.returnValue(mockElement);
mockDocument.find.andReturn(mockBody);
mockCompile.andReturn(mockTemplate);
mockRootScope.$new.andReturn(mockScope);
mockTemplate.andReturn(mockElement);
overlayService = new OverlayService(
mockDocument,
@@ -61,7 +61,7 @@ define(
it("prepends an mct-include to create overlays", function () {
overlayService.createOverlay("test", {});
expect(mockCompile).toHaveBeenCalled();
expect(mockCompile.calls.mostRecent().args[0].indexOf("mct-include"))
expect(mockCompile.mostRecentCall.args[0].indexOf("mct-include"))
.not.toEqual(-1);
});

View File

@@ -39,6 +39,7 @@ define([
"./src/policies/EditableMovePolicy",
"./src/policies/EditContextualActionPolicy",
"./src/representers/EditRepresenter",
"./src/representers/EditToolbarRepresenter",
"./src/capabilities/EditorCapability",
"./src/capabilities/TransactionCapabilityDecorator",
"./src/services/TransactionManager",
@@ -77,6 +78,7 @@ define([
EditableMovePolicy,
EditContextualActionPolicy,
EditRepresenter,
EditToolbarRepresenter,
EditorCapability,
TransactionCapabilityDecorator,
TransactionManager,
@@ -188,7 +190,6 @@ define([
"name": "Remove",
"description": "Remove this object from its containing object.",
"depends": [
"dialogService",
"navigationService"
]
},
@@ -380,6 +381,12 @@ define([
"depends": [
"$log"
]
},
{
"implementation": EditToolbarRepresenter,
"depends": [
"openmct"
]
}
],
"constants": [
@@ -417,17 +424,6 @@ define([
"transactionService"
]
}
],
"runs": [
{
depends: [
"toolbars[]",
"openmct"
],
implementation: function (toolbars, openmct) {
toolbars.forEach(openmct.toolbars.addProvider, openmct.toolbars);
}
}
]
}
});

View File

@@ -24,8 +24,7 @@
<div class="items-select left flex-elem l-flex-row grows">
<mct-representation key="'back-arrow'"
mct-object="domainObject"
class="flex-elem l-back">
</mct-representation>
class="flex-elem l-back"></mct-representation>
<mct-representation key="'object-header'"
mct-object="domainObject"
class="l-flex-row flex-elem grows object-header">
@@ -49,8 +48,8 @@
<!-- Toolbar and Save/Cancel buttons -->
<div class="l-edit-controls flex-elem l-flex-row flex-align-end">
<mct-toolbar name="mctToolbar"
structure="editToolbar.structure"
ng-model="editToolbar.state"
structure="toolbar.structure"
ng-model="toolbar.state"
class="flex-elem grows">
</mct-toolbar>
<mct-representation key="'edit-action-buttons'"
@@ -62,6 +61,7 @@
<mct-representation key="representation.selected.key"
mct-object="representation.selected.key && domainObject"
class="abs flex-elem grows object-holder-main scroll"
toolbar="toolbar"
mct-selectable="{
item: domainObject.useCapability('adapter'),
oldItem: domainObject

View File

@@ -24,7 +24,7 @@
class="flex-elem holder"
ng-model="filterBy">
</mct-include>
<div class="flex-elem grows vscroll scroll-pad">
<div class="flex-elem grows vscroll">
<ul class="tree" id="inspector-elements-tree"
ng-if="composition.length > 0">
<li ng-repeat="containedObject in composition | filter:searchElements">

View File

@@ -23,125 +23,111 @@
/**
* Module defining RemoveAction. Created by vwoeltje on 11/17/14.
*/
define([
'./RemoveDialog'
], function (
RemoveDialog
) {
define(
[],
function () {
/**
* Construct an action which will remove the provided object manifestation.
* The object will be removed from its parent's composition; the parent
* is looked up via the "context" capability (so this will be the
* immediate ancestor by which this specific object was reached.)
*
* @param {DialogService} dialogService a service which will show the dialog
* @param {NavigationService} navigationService a service that maintains the current navigation state
* @param {ActionContext} context the context in which this action is performed
* @memberof platform/commonUI/edit
* @constructor
* @implements {Action}
*/
function RemoveAction(dialogService, navigationService, context) {
this.domainObject = (context || {}).domainObject;
this.dialogService = dialogService;
this.navigationService = navigationService;
}
/**
* Perform this action.
*/
RemoveAction.prototype.perform = function (skipWarning) {
var dialog,
dialogService = this.dialogService,
domainObject = this.domainObject,
navigationService = this.navigationService;
/*
* Check whether an object ID matches the ID of the object being
* removed (used to filter a parent's composition to handle the
* removal.)
/**
* Construct an action which will remove the provided object manifestation.
* The object will be removed from its parent's composition; the parent
* is looked up via the "context" capability (so this will be the
* immediate ancestor by which this specific object was reached.)
*
* @param {DomainObject} object the object to be removed
* @param {ActionContext} context the context in which this action is performed
* @memberof platform/commonUI/edit
* @constructor
* @implements {Action}
*/
function isNotObject(otherObjectId) {
return otherObjectId !== domainObject.getId();
function RemoveAction(navigationService, context) {
this.domainObject = (context || {}).domainObject;
this.navigationService = navigationService;
}
/*
* Mutate a parent object such that it no longer contains the object
* which is being removed.
/**
* Perform this action.
* @return {Promise} a promise which will be
* fulfilled when the action has completed.
*/
function doMutate(model) {
model.composition = model.composition.filter(isNotObject);
}
/*
* Checks current object and ascendants of current
* object with object being removed, if the current
* object or any in the current object's path is being removed,
* navigate back to parent of removed object.
*/
function checkObjectNavigation(object, parentObject) {
// Traverse object starts at current location
var traverseObject = (navigationService).getNavigation(),
context;
// Stop when object is not defined (above ROOT)
while (traverseObject) {
// If object currently traversed to is object being removed
// navigate to parent of current object and then exit loop
if (traverseObject.getId() === object.getId()) {
navigationService.setNavigation(parentObject);
return;
}
// Traverses to parent of current object, moving
// up the ascendant path
context = traverseObject.getCapability('context');
traverseObject = context && context.getParent();
}
}
/*
* Remove the object from its parent, as identified by its context
* capability. Based on object's location and selected object's location
* user may be navigated to existing parent object
*/
function removeFromContext(object) {
var contextCapability = object.getCapability('context'),
parent = contextCapability.getParent();
// If currently within path of removed object(s),
// navigates to existing object up tree
checkObjectNavigation(object, parent);
return parent.useCapability('mutation', doMutate);
}
if (skipWarning) {
removeFromContext(domainObject);
} else {
RemoveAction.prototype.perform = function () {
var navigationService = this.navigationService,
domainObject = this.domainObject;
/*
* Pass in the function to remove the domain object so it can be
* associated with an 'OK' button press
*/
dialog = new RemoveDialog(dialogService, domainObject, removeFromContext);
dialog.show();
}
};
* Check whether an object ID matches the ID of the object being
* removed (used to filter a parent's composition to handle the
* removal.)
*/
function isNotObject(otherObjectId) {
return otherObjectId !== domainObject.getId();
}
// Object needs to have a parent for Remove to be applicable
RemoveAction.appliesTo = function (context) {
var object = (context || {}).domainObject,
contextCapability = object && object.getCapability("context"),
parent = contextCapability && contextCapability.getParent(),
parentType = parent && parent.getCapability('type'),
parentCreatable = parentType && parentType.hasFeature('creation');
/*
* Mutate a parent object such that it no longer contains the object
* which is being removed.
*/
function doMutate(model) {
model.composition = model.composition.filter(isNotObject);
}
// Only creatable types should be modifiable
return parent !== undefined &&
Array.isArray(parent.getModel().composition) &&
parentCreatable;
};
/*
* Checks current object and ascendants of current
* object with object being removed, if the current
* object or any in the current object's path is being removed,
* navigate back to parent of removed object.
*/
function checkObjectNavigation(object, parentObject) {
// Traverse object starts at current location
var traverseObject = (navigationService).getNavigation(),
context;
return RemoveAction;
});
// Stop when object is not defined (above ROOT)
while (traverseObject) {
// If object currently traversed to is object being removed
// navigate to parent of current object and then exit loop
if (traverseObject.getId() === object.getId()) {
navigationService.setNavigation(parentObject);
return;
}
// Traverses to parent of current object, moving
// up the ascendant path
context = traverseObject.getCapability('context');
traverseObject = context && context.getParent();
}
}
/*
* Remove the object from its parent, as identified by its context
* capability. Based on object's location and selected object's location
* user may be navigated to existing parent object
*/
function removeFromContext(object) {
var contextCapability = object.getCapability('context'),
parent = contextCapability.getParent();
// If currently within path of removed object(s),
// navigates to existing object up tree
checkObjectNavigation(object, parent);
return parent.useCapability('mutation', doMutate);
}
return removeFromContext(domainObject);
};
// Object needs to have a parent for Remove to be applicable
RemoveAction.appliesTo = function (context) {
var object = (context || {}).domainObject,
contextCapability = object && object.getCapability("context"),
parent = contextCapability && contextCapability.getParent(),
parentType = parent && parent.getCapability('type'),
parentCreatable = parentType && parentType.hasFeature('creation');
// Only creatable types should be modifiable
return parent !== undefined &&
Array.isArray(parent.getModel().composition) &&
parentCreatable;
};
return RemoveAction;
}
);

View File

@@ -1,77 +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 () {
/**
* @callback removeCallback
* @param {DomainObject} domainObject the domain object to be removed
*/
/**
* Construct a new Remove dialog.
*
* @param {DialogService} dialogService the service that shows the dialog
* @param {DomainObject} domainObject the domain object to be removed
* @param {removeCallback} removeCallback callback that handles removal of the domain object
* @memberof platform/commonUI/edit
* @constructor
*/
function RemoveDialog(dialogService, domainObject, removeCallback) {
this.dialogService = dialogService;
this.domainObject = domainObject;
this.removeCallback = removeCallback;
}
/**
* Display a dialog to confirm the removal of a domain object.
*/
RemoveDialog.prototype.show = function () {
var dialog,
domainObject = this.domainObject,
removeCallback = this.removeCallback,
model = {
title: 'Remove ' + domainObject.getModel().name,
actionText: 'Warning! This action will permanently remove this object. Are you sure you want to continue?',
severity: 'alert',
primaryOption: {
label: 'OK',
callback: function () {
removeCallback(domainObject);
dialog.dismiss();
}
},
options: [
{
label: 'Cancel',
callback: function () {
dialog.dismiss();
}
}
]
};
dialog = this.dialogService.showBlockingMessage(model);
};
return RemoveDialog;
});

View File

@@ -20,110 +20,192 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
[
'../../../../../src/api/objects/object-utils',
'lodash'
],
function (
objectUtils,
_
) {
[],
function () {
// Utility functions for reducing truth arrays
function and(a, b) {
return a && b;
}
function or(a, b) {
return a || b;
}
/**
* Provides initial structure and state (as suitable for provision
* to the `mct-toolbar` directive) for a view's toolbar, based on
* that view's declaration of what belongs in its toolbar and on
* to the `mct-toolbar` directive) for a view's tool bar, based on
* that view's declaration of what belongs in its tool bar and on
* the current selection.
*
* @param $scope the Angular scope
* @param {Object} openmct the openmct object
* @param structure the toolbar structure
* @param structure toolbar structure, as provided by view definition
* @param {Function} commit callback to invoke after changes
* @memberof platform/commonUI/edit
* @constructor
*/
function EditToolbar($scope, openmct, structure) {
this.toolbarStructure = [];
this.properties = [];
this.toolbarState = [];
this.openmct = openmct;
this.domainObjectsById = {};
this.unobserveObjects = [];
this.stateTracker = [];
$scope.$watchCollection(this.getState.bind(this), this.handleStateChanges.bind(this));
$scope.$on("$destroy", this.destroy.bind(this));
this.updateToolbar(structure);
this.registerListeners(structure);
}
/**
* Updates the toolbar with a new structure.
*
* @param {Array} structure the toolbar structure
*/
EditToolbar.prototype.updateToolbar = function (structure) {
function EditToolbar(structure, commit) {
var self = this;
function addKey(item) {
self.stateTracker.push({
id: objectUtils.makeKeyString(item.domainObject.identifier),
domainObject: item.domainObject,
property: item.property
});
self.properties.push(item.property);
// Generate a new key for an item's property
function addKey(property) {
self.properties.push(property);
return self.properties.length - 1; // Return index of property
}
// Invoke all functions in selections with the given name
function invoke(method, value) {
if (method) {
// Make the change in the selection
self.selection.forEach(function (selected) {
if (typeof selected[method] === 'function') {
selected[method](value);
}
});
// ...and commit!
commit();
}
}
// Prepare a toolbar item based on current selection
function convertItem(item) {
var converted = Object.create(item || {});
if (item.property) {
converted.key = addKey(item);
converted.key = addKey(item.property);
}
if (item.method) {
converted.click = function (value) {
item.method(value);
converted.click = function (v) {
invoke(item.method, v);
};
}
return converted;
}
// Prepare a toolbar section
function convertSection(section) {
var converted = Object.create(section || {});
converted.items =
((section || {}).items || [])
.map(convertItem);
return converted;
}
this.toolbarState = [];
this.selection = undefined;
this.properties = [];
this.toolbarStructure = Object.create(structure || {});
this.toolbarStructure.sections =
((structure || {}).sections || []).map(convertSection);
}
// Check if all elements of the selection which have this
// property have the same value for this property.
EditToolbar.prototype.isConsistent = function (property) {
var self = this,
consistent = true,
observed = false,
state;
// Check if a given element of the selection is consistent
// with previously-observed elements for this property.
function checkConsistency(selected) {
var next;
// Ignore selections which don't have this property
if (selected[property] !== undefined) {
// Look up state of this element in the selection
next = self.lookupState(property, selected);
// Detect inconsistency
if (observed) {
consistent = consistent && (next === state);
}
// Track state for next iteration
state = next;
observed = true;
}
}
// Iterate through selections
self.selection.forEach(checkConsistency);
return consistent;
};
// Used to filter out items which are applicable (or not)
// to the current selection.
EditToolbar.prototype.isApplicable = function (item) {
var property = (item || {}).property,
method = (item || {}).method,
exclusive = !!(item || {}).exclusive;
// Check if a selected item defines this property
function hasProperty(selected) {
return (property && (selected[property] !== undefined)) ||
(method && (typeof selected[method] === 'function'));
}
return this.selection.map(hasProperty).reduce(
exclusive ? and : or,
exclusive
) && this.isConsistent(property);
};
// Look up the current value associated with a property
EditToolbar.prototype.lookupState = function (property, selected) {
var value = selected[property];
return (typeof value === 'function') ? value() : value;
};
/**
* Set the current selection. Visibility of sections
* and items in the toolbar will be updated to match this.
* @param {Array} s the new selection
*/
EditToolbar.prototype.setSelection = function (s) {
var self = this;
// Show/hide controls in this section per applicability
function refreshSectionApplicability(section) {
var count = 0;
// Show/hide each item
(section.items || []).forEach(function (item) {
item.hidden = !self.isApplicable(item);
count += item.hidden ? 0 : 1;
});
// Hide this section if there are no applicable items
section.hidden = !count;
}
// Get initial value for a given property
function initializeState(property) {
var result;
structure.forEach(function (item) {
if (item.property === property) {
result = _.get(item.domainObject, item.property);
}
// Look through all selections for this property;
// values should all match by the time we perform
// this lookup anyway.
self.selection.forEach(function (selected) {
result = (selected[property] !== undefined) ?
self.lookupState(property, selected) :
result;
});
return result;
}
// Tracks the domain object and property for every element in the state array
this.stateTracker = [];
this.toolbarStructure = structure.map(convertItem);
this.selection = s;
this.toolbarStructure.sections.forEach(refreshSectionApplicability);
this.toolbarState = this.properties.map(initializeState);
};
/**
* Gets the structure of the toolbar, as appropriate to
* Get the structure of the toolbar, as appropriate to
* pass to `mct-toolbar`.
*
* @returns {Array} the toolbar structure
* @returns the toolbar structure
*/
EditToolbar.prototype.getStructure = function () {
return this.toolbarStructure;
};
/**
* Gets the current state of the toolbar, as appropriate
* Get the current state of the toolbar, as appropriate
* to two-way bind to the state handled by `mct-toolbar`.
*
* @returns {Array} state of the toolbar
*/
EditToolbar.prototype.getState = function () {
@@ -131,124 +213,48 @@ define(
};
/**
* Mutates the domain object's property with a new value.
*
* @param {Object} dominObject the domain object
* @param {string} property the domain object's property to update
* @param value the property's new value
*/
EditToolbar.prototype.updateDomainObject = function (domainObject, property, value) {
this.openmct.objects.mutate(domainObject, property, value);
};
/**
* Updates state with the new value.
*
* Update state within the current selection.
* @param {number} index the index of the corresponding
* element in the state array
* @param value the new value to update the state array with
* @param value the new value to convey to the selection
*/
EditToolbar.prototype.updateState = function (index, value) {
this.toolbarState[index] = value;
};
/**
* Register listeners for domain objects to watch for updates.
*
* @param {Array} the toolbar structure
*/
EditToolbar.prototype.registerListeners = function (structure) {
var self = this;
function observeObject(domainObject, id) {
var unobserveObject = self.openmct.objects.observe(domainObject, '*', function (newObject) {
self.domainObjectsById[id].newObject = JSON.parse(JSON.stringify(newObject));
self.scheduleStateUpdate();
});
self.unobserveObjects.push(unobserveObject);
// Update value for this property in all elements of the
// selection which have this property.
function updateProperties(property, val) {
var changed = false;
// Update property in a selected element
function updateProperty(selected) {
// Ignore selected elements which don't have this property
if (selected[property] !== undefined) {
// Check if this is a setter, or just assignable
if (typeof selected[property] === 'function') {
changed =
changed || (selected[property]() !== val);
selected[property](val);
} else {
changed =
changed || (selected[property] !== val);
selected[property] = val;
}
}
}
// Update property in all selected elements
self.selection.forEach(updateProperty);
// Return whether or not anything changed
return changed;
}
structure.forEach(function (item) {
var domainObject = item.domainObject;
var id = objectUtils.makeKeyString(domainObject.identifier);
if (!self.domainObjectsById[id]) {
self.domainObjectsById[id] = {
domainObject: domainObject,
properties: []
};
observeObject(domainObject, id);
}
self.domainObjectsById[id].properties.push(item.property);
});
};
/**
* Delays updating the state.
*/
EditToolbar.prototype.scheduleStateUpdate = function () {
if (this.stateUpdateScheduled) {
return;
}
this.stateUpdateScheduled = true;
setTimeout(this.updateStateAfterMutation.bind(this));
};
EditToolbar.prototype.updateStateAfterMutation = function () {
this.stateTracker.forEach(function (state, index) {
if (!this.domainObjectsById[state.id].newObject) {
return;
}
var domainObject = this.domainObjectsById[state.id].domainObject;
var newObject = this.domainObjectsById[state.id].newObject;
var currentValue = _.get(domainObject, state.property);
var newValue = _.get(newObject, state.property);
state.domainObject = newObject;
if (currentValue !== newValue) {
this.updateState(index, newValue);
}
}, this);
Object.values(this.domainObjectsById).forEach(function (tracker) {
if (tracker.newObject) {
tracker.domainObject = tracker.newObject;
}
delete tracker.newObject;
});
this.stateUpdateScheduled = false;
};
/**
* Removes the listeners.
*/
EditToolbar.prototype.deregisterListeners = function () {
this.unobserveObjects.forEach(function (unobserveObject) {
unobserveObject();
});
this.unobserveObjects = [];
};
EditToolbar.prototype.handleStateChanges = function (state) {
(state || []).map(function (newValue, index) {
var domainObject = this.stateTracker[index].domainObject;
var property = this.stateTracker[index].property;
var currentValue = _.get(domainObject, property);
if (currentValue !== newValue) {
this.updateDomainObject(domainObject, property, newValue);
}
}, this);
};
EditToolbar.prototype.destroy = function () {
this.deregisterListeners();
return updateProperties(this.properties[index], value);
};
return EditToolbar;
}
);

View File

@@ -0,0 +1,154 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, 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(
['./EditToolbar', './EditToolbarSelection'],
function (EditToolbar, EditToolbarSelection) {
// No operation
var NOOP_REPRESENTER = {
represent: function () {},
destroy: function () {}
};
/**
* The EditToolbarRepresenter populates the toolbar in Edit mode
* based on a view's definition.
* @param {Scope} scope the Angular scope of the representation
* @memberof platform/commonUI/edit
* @constructor
* @implements {Representer}
*/
function EditToolbarRepresenter(openmct, scope, element, attrs) {
var self = this;
// Mark changes as ready to persist
function commit(message) {
if (scope.commit) {
scope.commit(message);
}
}
// Handle changes to the current selection
function updateSelection(selection) {
// Only update if there is a toolbar to update
if (self.toolbar) {
// Make sure selection is array-like
selection = Array.isArray(selection) ?
selection :
(selection ? [selection] : []);
// Update the toolbar's selection
self.toolbar.setSelection(selection);
// ...and expose its structure/state
self.toolbarObject.structure =
self.toolbar.getStructure();
self.toolbarObject.state =
self.toolbar.getState();
}
}
// Get state (to watch it)
function getState() {
return self.toolbarObject.state;
}
// Update selection models to match changed toolbar state
function updateState(state) {
// Update underlying state based on toolbar changes
var changed = (state || []).map(function (value, index) {
return self.toolbar.updateState(index, value);
}).reduce(function (a, b) {
return a || b;
}, false);
// Only commit if something actually changed
if (changed) {
// Commit the changes.
commit("Changes from toolbar.");
}
}
this.clearExposedToolbar = function () {
// Clear exposed toolbar state (if any)
if (attrs.toolbar) {
delete scope.$parent[attrs.toolbar];
}
};
this.exposeToolbar = function () {
scope.$parent[self.attrs.toolbar] = self.toolbarObject;
};
this.commit = commit;
this.attrs = attrs;
this.updateSelection = updateSelection;
this.toolbar = undefined;
this.toolbarObject = {};
this.openmct = openmct;
this.scope = scope;
// If this representation exposes a toolbar, set up watches
// to synchronize with it.
if (attrs && attrs.toolbar) {
// Detect and handle changes to state from the toolbar
scope.$watchCollection(getState, updateState);
// Watch for changes in the current selection state
scope.$watchCollection("selection.all()", updateSelection);
// Expose toolbar state under that name
scope.$parent[attrs.toolbar] = this.toolbarObject;
} else {
// No toolbar declared, so do nothing.
return NOOP_REPRESENTER;
}
}
// Represent a domain object using this definition
EditToolbarRepresenter.prototype.represent = function (representation) {
// Get the newest toolbar definition from the view
var definition = (representation || {}).toolbar || {};
// If we have been asked to expose toolbar state...
if (this.attrs.toolbar) {
// Initialize toolbar object
this.toolbar = new EditToolbar(definition, this.commit);
// Ensure toolbar state is exposed
this.exposeToolbar();
}
// Add toolbar selection to scope.
this.scope.selection = new EditToolbarSelection(
this.scope,
this.openmct
);
// Initialize toolbar to current selection
this.updateSelection(this.scope.selection.all());
};
// Destroy; remove toolbar object from parent scope
EditToolbarRepresenter.prototype.destroy = function () {
this.clearExposedToolbar();
};
return EditToolbarRepresenter;
}
);

View File

@@ -0,0 +1,157 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
[],
function () {
/**
* Tracks selection state for editable views. Selection is
* implemented such that (from the toolbar's perspective)
* up to two objects can be "selected" at any given time:
*
* * The view proxy (see the `proxy` method), which provides
* an interface for interacting with the view itself (e.g.
* for buttons like "Add")
* * The selection, for single selected elements within the
* view.
*
* @memberof platform/commonUI/edit
* @constructor
*/
function EditToolbarSelection($scope, openmct) {
this.selection = [{}];
this.selecting = false;
this.selectedObj = undefined;
this.openmct = openmct;
var self = this;
function setSelection(selection) {
var selected = selection[0];
if (selected && selected.context.toolbar) {
self.select(selected.context.toolbar);
} else {
self.deselect();
}
if (selected && selected.context.viewProxy) {
self.proxy(selected.context.viewProxy);
}
setTimeout(function () {
$scope.$apply();
});
}
$scope.$on("$destroy", function () {
self.openmct.selection.off('change', setSelection);
});
this.openmct.selection.on('change', setSelection);
setSelection(this.openmct.selection.get());
}
/**
* Check if an object is currently selected.
* @param {*} obj the object to check for selection
* @returns {boolean} true if selected, otherwise false
*/
EditToolbarSelection.prototype.selected = function (obj) {
return (obj === this.selectedObj) || (obj === this.selection[0]);
};
/**
* Select an object.
* @param obj the object to select
* @returns {boolean} true if selection changed
*/
EditToolbarSelection.prototype.select = function (obj) {
// Proxy is always selected
if (obj === this.selection[0]) {
return false;
}
// Clear any existing selection
this.deselect();
// Note the current selection state
this.selectedObj = obj;
this.selecting = true;
// Add the selection
this.selection.push(obj);
};
/**
* Clear the current selection.
* @returns {boolean} true if selection changed
*/
EditToolbarSelection.prototype.deselect = function () {
// Nothing to do if we don't have a selected object
if (this.selecting) {
// Clear state tracking
this.selecting = false;
this.selectedObj = undefined;
// Remove the selection
this.selection.pop();
return true;
}
return false;
};
/**
* Get the currently-selected object.
* @returns the currently selected object
*/
EditToolbarSelection.prototype.get = function () {
return this.selectedObj;
};
/**
* Get/set the view proxy (for toolbar actions taken upon
* the view itself.)
* @param [proxy] the view proxy (if setting)
* @returns the current view proxy
*/
EditToolbarSelection.prototype.proxy = function (p) {
if (arguments.length > 0) {
this.selection[0] = p;
}
return this.selection[0];
};
/**
* Get an array containing all selections, including the
* selection proxy. It is generally not advisable to
* mutate this array directly.
* @returns {Array} all selections
*/
EditToolbarSelection.prototype.all = function () {
return this.selection;
};
return EditToolbarSelection;
}
);

View File

@@ -49,7 +49,7 @@ define(
"getModel"
]
);
mockDomainObject.getModel.and.returnValue({});
mockDomainObject.getModel.andReturn({});
mockParentObject = jasmine.createSpyObj(
"parentObject",
@@ -57,7 +57,7 @@ define(
"getCapability"
]
);
mockParentObject.getCapability.and.callFake(function (name) {
mockParentObject.getCapability.andCallFake(function (name) {
return parentCapabilities[name];
});
@@ -77,14 +77,14 @@ define(
"getOriginal"
]
);
capabilities.location.getOriginal.and.returnValue(mockPromise(mockDomainObject));
capabilities.location.getOriginal.andReturn(mockPromise(mockDomainObject));
capabilities.context = jasmine.createSpyObj(
"contextCapability",
[
"getParent"
]
);
capabilities.context.getParent.and.returnValue(mockParentObject);
capabilities.context.getParent.andReturn(mockParentObject);
parentCapabilities.action = jasmine.createSpyObj(
"actionCapability",
@@ -97,37 +97,37 @@ define(
domainObject: mockDomainObject
};
mockDomainObject.getCapability.and.callFake(function (name) {
mockDomainObject.getCapability.andCallFake(function (name) {
return capabilities[name];
});
mockDomainObject.hasCapability.and.callFake(function (name) {
mockDomainObject.hasCapability.andCallFake(function (name) {
return !!capabilities[name];
});
capabilities.editor.finish.and.returnValue(mockPromise(true));
capabilities.editor.finish.andReturn(mockPromise(true));
action = new CancelAction(actionContext);
});
it("only applies to domain object that is being edited", function () {
capabilities.editor.isEditContextRoot.and.returnValue(true);
capabilities.editor.isEditContextRoot.andReturn(true);
expect(CancelAction.appliesTo(actionContext)).toBeTruthy();
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
capabilities.editor.isEditContextRoot.and.returnValue(false);
capabilities.editor.isEditContextRoot.andReturn(false);
expect(CancelAction.appliesTo(actionContext)).toBeFalsy();
mockDomainObject.hasCapability.and.returnValue(false);
mockDomainObject.hasCapability.andReturn(false);
expect(CancelAction.appliesTo(actionContext)).toBeFalsy();
});
it("invokes the editor capability's cancel functionality when" +
" performed", function () {
mockDomainObject.getModel.and.returnValue({persisted: 1});
mockDomainObject.getModel.andReturn({persisted: 1});
//Return true from navigate action
capabilities.action.perform.and.returnValue(mockPromise(true));
capabilities.action.perform.andReturn(mockPromise(true));
action.perform();
// Should have called finish
@@ -138,15 +138,15 @@ define(
});
it("navigates to object if existing using navigate action", function () {
mockDomainObject.getModel.and.returnValue({persisted: 1});
mockDomainObject.getModel.andReturn({persisted: 1});
//Return true from navigate action
capabilities.action.perform.and.returnValue(mockPromise(true));
capabilities.action.perform.andReturn(mockPromise(true));
action.perform();
expect(capabilities.action.perform).toHaveBeenCalledWith("navigate");
});
it("navigates to parent if new using navigate action", function () {
mockDomainObject.getModel.and.returnValue({persisted: undefined});
mockDomainObject.getModel.andReturn({persisted: undefined});
action.perform();
expect(parentCapabilities.action.perform).toHaveBeenCalledWith("navigate");
});

View File

@@ -66,11 +66,11 @@ define(
editor: mockEditor
};
mockDomainObject.getCapability.and.callFake(function (name) {
mockDomainObject.getCapability.andCallFake(function (name) {
return capabilities[name];
});
mockDomainObject.hasCapability.and.returnValue(true);
mockType.hasFeature.and.returnValue(true);
mockDomainObject.hasCapability.andReturn(true);
mockType.hasFeature.andReturn(true);
actionContext = { domainObject: mockDomainObject };
@@ -92,9 +92,9 @@ define(
});
it("is only applicable to objects not already in edit mode", function () {
mockEditor.isEditContextRoot.and.returnValue(false);
mockEditor.isEditContextRoot.andReturn(false);
expect(EditAction.appliesTo(actionContext)).toBe(true);
mockEditor.isEditContextRoot.and.returnValue(true);
mockEditor.isEditContextRoot.andReturn(true);
expect(EditAction.appliesTo(actionContext)).toBe(false);
});

View File

@@ -71,14 +71,14 @@ define(
mockActionCapability = jasmine.createSpyObj("actionCapability", ["getActions"]);
mockEditAction = jasmine.createSpyObj("editAction", ["perform"]);
mockDomainObject.getId.and.returnValue("test");
mockDomainObject.getCapability.and.returnValue(mockContext);
mockContext.getParent.and.returnValue(mockParent);
mockType.hasFeature.and.returnValue(true);
mockType.getKey.and.returnValue("layout");
mockComposition.invoke.and.returnValue(mockPromise(true));
mockComposition.add.and.returnValue(mockPromise(true));
mockActionCapability.getActions.and.returnValue([]);
mockDomainObject.getId.andReturn("test");
mockDomainObject.getCapability.andReturn(mockContext);
mockContext.getParent.andReturn(mockParent);
mockType.hasFeature.andReturn(true);
mockType.getKey.andReturn("layout");
mockComposition.invoke.andReturn(mockPromise(true));
mockComposition.add.andReturn(mockPromise(true));
mockActionCapability.getActions.andReturn([]);
capabilities = {
composition: mockComposition,
@@ -105,14 +105,14 @@ define(
});
it("enables edit mode for objects that have an edit action", function () {
mockActionCapability.getActions.and.returnValue([mockEditAction]);
mockActionCapability.getActions.andReturn([mockEditAction]);
action.perform();
expect(mockEditAction.perform).toHaveBeenCalled();
});
it("Does not enable edit mode for objects that do not have an" +
" edit action", function () {
mockActionCapability.getActions.and.returnValue([]);
mockActionCapability.getActions.andReturn([]);
action.perform();
expect(mockEditAction.perform).not.toHaveBeenCalled();
expect(mockComposition.add)

View File

@@ -71,8 +71,8 @@ define(
}
};
capabilities.type.hasFeature.and.returnValue(true);
capabilities.mutation.and.returnValue(true);
capabilities.type.hasFeature.andReturn(true);
capabilities.mutation.andReturn(true);
action = new PropertiesAction(dialogService, context);
});
@@ -80,7 +80,7 @@ define(
it("mutates an object when performed", function () {
action.perform();
expect(capabilities.mutation).toHaveBeenCalled();
capabilities.mutation.calls.mostRecent().args[0]({});
capabilities.mutation.mostRecentCall.args[0]({});
});
it("does not muate object upon cancel", function () {

View File

@@ -25,37 +25,50 @@ define(
function (RemoveAction) {
describe("The Remove action", function () {
var action,
actionContext,
capabilities,
mockContext,
mockDialogService,
mockDomainObject,
mockMutation,
var mockQ,
mockNavigationService,
mockDomainObject,
mockParent,
mockChildObject,
mockGrandchildObject,
mockRootObject,
mockContext,
mockChildContext,
mockGrandchildContext,
mockRootContext,
mockMutation,
mockType,
model;
actionContext,
model,
capabilities,
action;
function mockPromise(value) {
return {
then: function (callback) {
return mockPromise(callback(value));
}
};
}
beforeEach(function () {
mockDomainObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability", "getModel"]
["getId", "getCapability"]
);
mockMutation = jasmine.createSpyObj("mutation", ["invoke"]);
mockType = jasmine.createSpyObj("type", ["hasFeature"]);
mockType.hasFeature.and.returnValue(true);
capabilities = {
mutation: mockMutation,
type: mockType
};
model = {
composition: ["a", "test", "b"]
};
mockChildObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability"]
);
mockGrandchildObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability"]
);
mockRootObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability"]
);
mockQ = { when: mockPromise };
mockParent = {
getModel: function () {
return model;
@@ -67,12 +80,12 @@ define(
return capabilities[k].invoke(v);
}
};
mockDialogService = jasmine.createSpyObj(
"dialogService",
["showBlockingMessage"]
);
mockContext = jasmine.createSpyObj("context", ["getParent"]);
mockChildContext = jasmine.createSpyObj("context", ["getParent"]);
mockGrandchildContext = jasmine.createSpyObj("context", ["getParent"]);
mockRootContext = jasmine.createSpyObj("context", ["getParent"]);
mockMutation = jasmine.createSpyObj("mutation", ["invoke"]);
mockType = jasmine.createSpyObj("type", ["hasFeature"]);
mockNavigationService = jasmine.createSpyObj(
"navigationService",
[
@@ -82,27 +95,31 @@ define(
"removeListener"
]
);
mockNavigationService.getNavigation.and.returnValue(mockDomainObject);
mockNavigationService.getNavigation.andReturn(mockDomainObject);
mockContext = jasmine.createSpyObj("context", ["getParent"]);
mockContext.getParent.and.returnValue(mockParent);
mockDomainObject.getId.and.returnValue("test");
mockDomainObject.getCapability.and.returnValue(mockContext);
mockDomainObject.getModel.and.returnValue({name: 'test object'});
mockDomainObject.getId.andReturn("test");
mockDomainObject.getCapability.andReturn(mockContext);
mockContext.getParent.andReturn(mockParent);
mockType.hasFeature.andReturn(true);
mockContext.getParent.and.returnValue(mockParent);
mockType.hasFeature.and.returnValue(true);
capabilities = {
mutation: mockMutation,
type: mockType
};
model = {
composition: ["a", "test", "b"]
};
actionContext = { domainObject: mockDomainObject };
action = new RemoveAction(mockDialogService, mockNavigationService, actionContext);
action = new RemoveAction(mockNavigationService, actionContext);
});
it("only applies to objects with parents", function () {
expect(RemoveAction.appliesTo(actionContext)).toBeTruthy();
mockContext.getParent.and.returnValue(undefined);
mockContext.getParent.andReturn(undefined);
expect(RemoveAction.appliesTo(actionContext)).toBeFalsy();
@@ -110,157 +127,83 @@ define(
expect(mockType.hasFeature).toHaveBeenCalledWith('creation');
});
it("shows a blocking message dialog", function () {
mockParent = jasmine.createSpyObj(
"parent",
["getModel", "getCapability", "useCapability"]
);
it("mutates the parent when performed", function () {
action.perform();
expect(mockMutation.invoke)
.toHaveBeenCalledWith(jasmine.any(Function));
});
it("changes composition from its mutation function", function () {
var mutator, result;
action.perform();
mutator = mockMutation.invoke.mostRecentCall.args[0];
result = mutator(model);
// Should not have cancelled the mutation
expect(result).not.toBe(false);
// Simulate mutate's behavior (remove can either return a
// new model or modify this one in-place)
result = result || model;
// Should have removed "test" - that was our
// mock domain object's id.
expect(result.composition).toEqual(["a", "b"]);
});
it("removes parent of object currently navigated to", function () {
// Navigates to child object
mockNavigationService.getNavigation.andReturn(mockChildObject);
// Test is id of object being removed
// Child object has different id
mockDomainObject.getId.andReturn("test");
mockChildObject.getId.andReturn("not test");
// Sets context for the child and domainObject
mockDomainObject.getCapability.andReturn(mockContext);
mockChildObject.getCapability.andReturn(mockChildContext);
// Parents of child and domainObject are set
mockContext.getParent.andReturn(mockParent);
mockChildContext.getParent.andReturn(mockDomainObject);
mockType.hasFeature.andReturn(true);
action.perform();
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
// Also check that no mutation happens at this point
expect(mockParent.useCapability).not.toHaveBeenCalledWith("mutation", jasmine.any(Function));
// Expects navigation to parent of domainObject (removed object)
expect(mockNavigationService.setNavigation).toHaveBeenCalledWith(mockParent);
});
it("does not show a blocking message dialog when true is passed to perform", function () {
mockParent = jasmine.createSpyObj(
"parent",
["getModel", "getCapability", "useCapability"]
);
it("checks if removing object not in ascendent path (reaches ROOT)", function () {
// Navigates to grandchild of ROOT
mockNavigationService.getNavigation.andReturn(mockGrandchildObject);
action.perform(true);
// domainObject (grandparent) is set as ROOT, child and grandchild
// are set objects not being removed
mockDomainObject.getId.andReturn("test 1");
mockRootObject.getId.andReturn("ROOT");
mockChildObject.getId.andReturn("not test 2");
mockGrandchildObject.getId.andReturn("not test 3");
expect(mockDialogService.showBlockingMessage).not.toHaveBeenCalled();
// Sets context for the grandchild, child, and domainObject
mockRootObject.getCapability.andReturn(mockRootContext);
mockChildObject.getCapability.andReturn(mockChildContext);
mockGrandchildObject.getCapability.andReturn(mockGrandchildContext);
// Parents of grandchild and child are set
mockChildContext.getParent.andReturn(mockRootObject);
mockGrandchildContext.getParent.andReturn(mockChildObject);
mockType.hasFeature.andReturn(true);
action.perform();
// Expects no navigation to occur
expect(mockNavigationService.setNavigation).not.toHaveBeenCalled();
});
describe("after the remove callback is triggered", function () {
var mockChildContext,
mockChildObject,
mockDialogHandle,
mockGrandchildContext,
mockGrandchildObject,
mockRootContext,
mockRootObject;
beforeEach(function () {
mockChildObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability"]
);
mockDialogHandle = jasmine.createSpyObj(
"dialogHandle",
["dismiss"]
);
mockGrandchildObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability"]
);
mockRootObject = jasmine.createSpyObj(
"domainObject",
["getId", "getCapability"]
);
mockChildContext = jasmine.createSpyObj("context", ["getParent"]);
mockGrandchildContext = jasmine.createSpyObj("context", ["getParent"]);
mockRootContext = jasmine.createSpyObj("context", ["getParent"]);
mockDialogService.showBlockingMessage.and.returnValue(mockDialogHandle);
});
it("mutates the parent when performed", function () {
action.perform();
mockDialogService.showBlockingMessage.calls.mostRecent().args[0]
.primaryOption.callback();
expect(mockMutation.invoke)
.toHaveBeenCalledWith(jasmine.any(Function));
});
it("changes composition from its mutation function", function () {
var mutator, result;
action.perform();
mockDialogService.showBlockingMessage.calls.mostRecent().args[0]
.primaryOption.callback();
mutator = mockMutation.invoke.calls.mostRecent().args[0];
result = mutator(model);
// Should not have cancelled the mutation
expect(result).not.toBe(false);
// Simulate mutate's behavior (remove can either return a
// new model or modify this one in-place)
result = result || model;
// Should have removed "test" - that was our
// mock domain object's id.
expect(result.composition).toEqual(["a", "b"]);
});
it("removes parent of object currently navigated to", function () {
// Navigates to child object
mockNavigationService.getNavigation.and.returnValue(mockChildObject);
// Test is id of object being removed
// Child object has different id
mockDomainObject.getId.and.returnValue("test");
mockChildObject.getId.and.returnValue("not test");
// Sets context for the child and domainObject
mockDomainObject.getCapability.and.returnValue(mockContext);
mockChildObject.getCapability.and.returnValue(mockChildContext);
// Parents of child and domainObject are set
mockContext.getParent.and.returnValue(mockParent);
mockChildContext.getParent.and.returnValue(mockDomainObject);
mockType.hasFeature.and.returnValue(true);
action.perform();
mockDialogService.showBlockingMessage.calls.mostRecent().args[0]
.primaryOption.callback();
// Expects navigation to parent of domainObject (removed object)
expect(mockNavigationService.setNavigation).toHaveBeenCalledWith(mockParent);
});
it("checks if removing object not in ascendent path (reaches ROOT)", function () {
// Navigates to grandchild of ROOT
mockNavigationService.getNavigation.and.returnValue(mockGrandchildObject);
// domainObject (grandparent) is set as ROOT, child and grandchild
// are set objects not being removed
mockDomainObject.getId.and.returnValue("test 1");
mockRootObject.getId.and.returnValue("ROOT");
mockChildObject.getId.and.returnValue("not test 2");
mockGrandchildObject.getId.and.returnValue("not test 3");
// Sets context for the grandchild, child, and domainObject
mockRootObject.getCapability.and.returnValue(mockRootContext);
mockChildObject.getCapability.and.returnValue(mockChildContext);
mockGrandchildObject.getCapability.and.returnValue(mockGrandchildContext);
// Parents of grandchild and child are set
mockChildContext.getParent.and.returnValue(mockRootObject);
mockGrandchildContext.getParent.and.returnValue(mockChildObject);
mockType.hasFeature.and.returnValue(true);
action.perform();
mockDialogService.showBlockingMessage.calls.mostRecent().args[0]
.primaryOption.callback();
// Expects no navigation to occur
expect(mockNavigationService.setNavigation).not.toHaveBeenCalled();
});
});
});
}
);

View File

@@ -19,7 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global describe,it,expect,beforeEach,jasmine*/
/*global describe,it,expect,beforeEach,jasmine,waitsFor,runs*/
define(
["../../src/actions/SaveAction"],
@@ -81,13 +81,13 @@ define(
["info", "error"]
);
mockDomainObject.hasCapability.and.returnValue(true);
mockDomainObject.getCapability.and.callFake(function (capability) {
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andCallFake(function (capability) {
return capabilities[capability];
});
mockDomainObject.getModel.and.returnValue({persisted: 0});
mockEditorCapability.save.and.returnValue(mockPromise(true));
mockEditorCapability.isEditContextRoot.and.returnValue(true);
mockDomainObject.getModel.andReturn({persisted: 0});
mockEditorCapability.save.andReturn(mockPromise(true));
mockEditorCapability.isEditContextRoot.andReturn(true);
action = new SaveAction(mockDialogService, mockNotificationService, actionContext);
});
@@ -96,14 +96,14 @@ define(
expect(SaveAction.appliesTo(actionContext)).toBe(true);
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
mockDomainObject.hasCapability.and.returnValue(false);
mockDomainObject.getCapability.and.returnValue(undefined);
mockDomainObject.hasCapability.andReturn(false);
mockDomainObject.getCapability.andReturn(undefined);
expect(SaveAction.appliesTo(actionContext)).toBe(false);
});
it("only applies to domain object that has already been persisted",
function () {
mockDomainObject.getModel.and.returnValue({persisted: undefined});
mockDomainObject.getModel.andReturn({persisted: undefined});
expect(SaveAction.appliesTo(actionContext)).toBe(false);
});
@@ -118,11 +118,11 @@ define(
beforeEach(function () {
mockDialogHandle = jasmine.createSpyObj("dialogHandle", ["dismiss"]);
mockDialogService.showBlockingMessage.and.returnValue(mockDialogHandle);
mockDialogService.showBlockingMessage.andReturn(mockDialogHandle);
});
it("shows a dialog while saving", function () {
mockEditorCapability.save.and.returnValue(new Promise(function () {
mockEditorCapability.save.andReturn(new Promise(function () {
}));
action.perform();
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
@@ -137,8 +137,12 @@ define(
it("notifies if saving succeeded", function () {
var mockCallback = jasmine.createSpy("callback");
mockEditorCapability.save.and.returnValue(Promise.resolve());
return action.perform().then(mockCallback).then(function () {
mockEditorCapability.save.andReturn(Promise.resolve("success"));
action.perform().then(mockCallback);
waitsFor(function () {
return mockCallback.calls.length > 0;
});
runs(function () {
expect(mockNotificationService.info).toHaveBeenCalled();
expect(mockNotificationService.error).not.toHaveBeenCalled();
});
@@ -146,8 +150,12 @@ define(
it("notifies if saving failed", function () {
var mockCallback = jasmine.createSpy("callback");
mockEditorCapability.save.and.returnValue(Promise.reject("some failure reason"));
return action.perform().then(mockCallback).then(function () {
mockEditorCapability.save.andReturn(Promise.reject("some failure reason"));
action.perform().then(mockCallback);
waitsFor(function () {
return mockCallback.calls.length > 0;
});
runs(function () {
expect(mockNotificationService.error).toHaveBeenCalled();
expect(mockNotificationService.info).not.toHaveBeenCalled();
});

View File

@@ -86,13 +86,13 @@ define(
["info", "error"]
);
mockDomainObject.hasCapability.and.returnValue(true);
mockDomainObject.getCapability.and.callFake(function (capability) {
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andCallFake(function (capability) {
return capabilities[capability];
});
mockDomainObject.getModel.and.returnValue({ persisted: 0 });
mockEditorCapability.save.and.returnValue(mockPromise(true));
mockEditorCapability.isEditContextRoot.and.returnValue(true);
mockDomainObject.getModel.andReturn({ persisted: 0 });
mockEditorCapability.save.andReturn(mockPromise(true));
mockEditorCapability.isEditContextRoot.andReturn(true);
action = new SaveAndStopEditingAction(dialogService, notificationService, actionContext);
});
@@ -102,18 +102,18 @@ define(
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(true);
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
mockDomainObject.hasCapability.and.returnValue(false);
mockDomainObject.getCapability.and.returnValue(undefined);
mockDomainObject.hasCapability.andReturn(false);
mockDomainObject.getCapability.andReturn(undefined);
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
});
it("only applies to domain object that has already been persisted", function () {
mockDomainObject.getModel.and.returnValue({ persisted: undefined });
mockDomainObject.getModel.andReturn({ persisted: undefined });
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
});
it("does not close the editor before completing the save", function () {
mockEditorCapability.save.and.returnValue(new Promise(function () {
mockEditorCapability.save.andReturn(new Promise(function () {
}));
action.perform();
expect(mockEditorCapability.save).toHaveBeenCalled();

View File

@@ -19,7 +19,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global describe,it,expect,beforeEach,jasmine,spyOn*/
/*global describe,it,expect,beforeEach,jasmine,runs,waitsFor,spyOn*/
define(
["../../src/actions/SaveAsAction"],
@@ -63,12 +63,12 @@ define(
"getId"
]
);
mockDomainObject.hasCapability.and.returnValue(true);
mockDomainObject.getCapability.and.callFake(function (capability) {
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andCallFake(function (capability) {
return capabilities[capability];
});
mockDomainObject.getModel.and.returnValue({location: 'a', persisted: undefined});
mockDomainObject.getId.and.returnValue(0);
mockDomainObject.getModel.andReturn({location: 'a', persisted: undefined});
mockDomainObject.getId.andReturn(0);
mockClonedObject = jasmine.createSpyObj(
"clonedObject",
@@ -76,7 +76,7 @@ define(
"getId"
]
);
mockClonedObject.getId.and.returnValue(1);
mockClonedObject.getId.andReturn(1);
mockParent = jasmine.createSpyObj(
"parentObject",
@@ -91,9 +91,9 @@ define(
"editor",
["save", "finish", "isEditContextRoot"]
);
mockEditorCapability.save.and.returnValue(mockPromise(true));
mockEditorCapability.finish.and.returnValue(mockPromise(true));
mockEditorCapability.isEditContextRoot.and.returnValue(true);
mockEditorCapability.save.andReturn(mockPromise(true));
mockEditorCapability.finish.andReturn(mockPromise(true));
mockEditorCapability.isEditContextRoot.andReturn(true);
capabilities.editor = mockEditorCapability;
mockActionCapability = jasmine.createSpyObj(
@@ -106,7 +106,7 @@ define(
"objectService",
["getObjects"]
);
mockObjectService.getObjects.and.returnValue(mockPromise({'a': mockParent}));
mockObjectService.getObjects.andReturn(mockPromise({'a': mockParent}));
mockDialogService = jasmine.createSpyObj(
"dialogService",
@@ -115,7 +115,7 @@ define(
"showBlockingMessage"
]
);
mockDialogService.getUserInput.and.returnValue(mockPromise(undefined));
mockDialogService.getUserInput.andReturn(mockPromise(undefined));
mockCopyService = jasmine.createSpyObj(
"copyService",
@@ -123,7 +123,7 @@ define(
"perform"
]
);
mockCopyService.perform.and.returnValue(mockPromise(mockClonedObject));
mockCopyService.perform.andReturn(mockPromise(mockClonedObject));
mockNotificationService = jasmine.createSpyObj(
"notificationService",
@@ -146,10 +146,10 @@ define(
actionContext);
spyOn(action, "getObjectService");
action.getObjectService.and.returnValue(mockObjectService);
action.getObjectService.andReturn(mockObjectService);
spyOn(action, "createWizard");
action.createWizard.and.returnValue({
action.createWizard.andReturn({
getFormStructure: noop,
getInitialFormValue: noop,
populateObjectFromInput: function () {
@@ -163,8 +163,8 @@ define(
expect(SaveAsAction.appliesTo(actionContext)).toBe(true);
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
mockDomainObject.hasCapability.and.returnValue(false);
mockDomainObject.getCapability.and.returnValue(undefined);
mockDomainObject.hasCapability.andReturn(false);
mockDomainObject.getCapability.andReturn(undefined);
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
});
@@ -173,27 +173,35 @@ define(
expect(SaveAsAction.appliesTo(actionContext)).toBe(true);
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
mockDomainObject.getModel.and.returnValue({persisted: 0});
mockDomainObject.getModel.andReturn({persisted: 0});
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
});
it("uses the editor capability to save the object", function () {
mockEditorCapability.save.and.returnValue(Promise.resolve());
return action.perform().then(function () {
expect(mockEditorCapability.save).toHaveBeenCalled();
mockEditorCapability.save.andReturn(new Promise(function () {}));
runs(function () {
action.perform();
});
waitsFor(function () {
return mockEditorCapability.save.calls.length > 0;
}, "perform() should call EditorCapability.save");
runs(function () {
expect(mockEditorCapability.finish).not.toHaveBeenCalled();
});
});
it("uses the editor capability to finish editing the object", function () {
return action.perform().then(function () {
expect(mockEditorCapability.finish.calls.count()).toBeGreaterThan(0);
runs(function () {
action.perform();
});
waitsFor(function () {
return mockEditorCapability.finish.calls.length > 0;
}, "perform() should call EditorCapability.finish");
});
it("returns to browse after save", function () {
spyOn(action, "save");
action.save.and.returnValue(mockPromise(mockDomainObject));
action.save.andReturn(mockPromise(mockDomainObject));
action.perform();
expect(mockActionCapability.perform).toHaveBeenCalledWith(
"navigate"
@@ -210,33 +218,48 @@ define(
beforeEach(function () {
mockDialogHandle = jasmine.createSpyObj("dialogHandle", ["dismiss"]);
mockDialogService.showBlockingMessage.and.returnValue(mockDialogHandle);
mockDialogService.showBlockingMessage.andReturn(mockDialogHandle);
});
it("shows a blocking dialog indicating that saving is in progress", function () {
mockEditorCapability.save.and.returnValue(new Promise(function () {}));
mockEditorCapability.save.andReturn(new Promise(function () {}));
action.perform();
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
expect(mockDialogHandle.dismiss).not.toHaveBeenCalled();
});
it("hides the blocking dialog after saving finishes", function () {
return action.perform().then(function () {
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
var mockCallback = jasmine.createSpy();
action.perform().then(mockCallback);
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
waitsFor(function () {
return mockCallback.calls.length > 0;
});
runs(function () {
expect(mockDialogHandle.dismiss).toHaveBeenCalled();
});
});
it("notifies if saving succeeded", function () {
return action.perform().then(function () {
var mockCallback = jasmine.createSpy();
action.perform().then(mockCallback);
waitsFor(function () {
return mockCallback.calls.length > 0;
});
runs(function () {
expect(mockNotificationService.info).toHaveBeenCalled();
expect(mockNotificationService.error).not.toHaveBeenCalled();
});
});
it("notifies if saving failed", function () {
mockCopyService.perform.and.returnValue(Promise.reject("some failure reason"));
action.perform().then(function () {
mockCopyService.perform.andReturn(Promise.reject("some failure reason"));
var mockCallback = jasmine.createSpy();
action.perform().then(mockCallback);
waitsFor(function () {
return mockCallback.calls.length > 0;
});
runs(function () {
expect(mockNotificationService.error).toHaveBeenCalled();
expect(mockNotificationService.info).not.toHaveBeenCalled();
});

View File

@@ -60,8 +60,8 @@ define(
"cancel"
]
);
mockTransactionService.commit.and.returnValue(fastPromise());
mockTransactionService.cancel.and.returnValue(fastPromise());
mockTransactionService.commit.andReturn(fastPromise());
mockTransactionService.cancel.andReturn(fastPromise());
mockTransactionService.isActive = jasmine.createSpy('isActive');
mockStatusCapability = jasmine.createSpyObj(
@@ -76,23 +76,23 @@ define(
"contextCapability",
["getParent"]
);
mockContextCapability.getParent.and.returnValue(mockParentObject);
mockContextCapability.getParent.andReturn(mockParentObject);
capabilities = {
context: mockContextCapability,
status: mockStatusCapability
};
mockDomainObject.hasCapability.and.callFake(function (name) {
mockDomainObject.hasCapability.andCallFake(function (name) {
return capabilities[name] !== undefined;
});
mockDomainObject.getCapability.and.callFake(function (name) {
mockDomainObject.getCapability.andCallFake(function (name) {
return capabilities[name];
});
mockParentObject.getCapability.and.returnValue(mockParentStatus);
mockParentObject.hasCapability.and.returnValue(false);
mockParentObject.getCapability.andReturn(mockParentStatus);
mockParentObject.hasCapability.andReturn(false);
capability = new EditorCapability(
mockTransactionService,
@@ -112,18 +112,18 @@ define(
it("uses editing status to determine editing context root", function () {
capability.edit();
mockStatusCapability.get.and.returnValue(false);
mockStatusCapability.get.andReturn(false);
expect(capability.isEditContextRoot()).toBe(false);
mockStatusCapability.get.and.returnValue(true);
mockStatusCapability.get.andReturn(true);
expect(capability.isEditContextRoot()).toBe(true);
});
it("inEditingContext returns true if parent object is being" +
" edited", function () {
mockStatusCapability.get.and.returnValue(false);
mockParentStatus.get.and.returnValue(false);
mockStatusCapability.get.andReturn(false);
mockParentStatus.get.andReturn(false);
expect(capability.inEditContext()).toBe(false);
mockParentStatus.get.and.returnValue(true);
mockParentStatus.get.andReturn(true);
expect(capability.inEditContext()).toBe(true);
});
@@ -142,7 +142,7 @@ define(
describe("finish", function () {
beforeEach(function () {
mockTransactionService.isActive.and.returnValue(true);
mockTransactionService.isActive.andReturn(true);
capability.edit();
capability.finish();
});
@@ -156,7 +156,7 @@ define(
describe("finish", function () {
beforeEach(function () {
mockTransactionService.isActive.and.returnValue(false);
mockTransactionService.isActive.andReturn(false);
capability.edit();
});
@@ -175,15 +175,15 @@ define(
var model = {};
beforeEach(function () {
mockDomainObject.getModel.and.returnValue(model);
mockDomainObject.getModel.andReturn(model);
capability.edit();
capability.finish();
});
it("returns true if the object has been modified since it" +
" was last persisted", function () {
mockTransactionService.size.and.returnValue(0);
mockTransactionService.size.andReturn(0);
expect(capability.dirty()).toBe(false);
mockTransactionService.size.and.returnValue(1);
mockTransactionService.size.andReturn(1);
expect(capability.dirty()).toBe(true);
});
});

View File

@@ -37,7 +37,7 @@ define(
mockQ = {};
mockTransactionService = {};
mockCapabilityService = jasmine.createSpyObj("capabilityService", ["getCapabilities"]);
mockCapabilityService.getCapabilities.and.returnValue({
mockCapabilityService.getCapabilities.andReturn({
persistence: function () {}
});

View File

@@ -47,7 +47,7 @@ define(
testId = "test-id";
mockQ = jasmine.createSpyObj("$q", ["when"]);
mockQ.when.and.callFake(function (val) {
mockQ.when.andCallFake(function (val) {
return fastPromise(val);
});
mockTransactionManager = jasmine.createSpyObj(
@@ -58,15 +58,15 @@ define(
"persistenceCapability",
["persist", "refresh", "getSpace"]
);
mockPersistence.persist.and.returnValue(fastPromise());
mockPersistence.refresh.and.returnValue(fastPromise());
mockPersistence.persist.andReturn(fastPromise());
mockPersistence.refresh.andReturn(fastPromise());
mockDomainObject = jasmine.createSpyObj(
"domainObject",
["getModel", "getId"]
);
mockDomainObject.getModel.and.returnValue({persisted: 1});
mockDomainObject.getId.and.returnValue(testId);
mockDomainObject.getModel.andReturn({persisted: 1});
mockDomainObject.getId.andReturn(testId);
capability = new TransactionalPersistenceCapability(
mockQ,
@@ -78,24 +78,24 @@ define(
it("if no transaction is active, passes through to persistence" +
" provider", function () {
mockTransactionManager.isActive.and.returnValue(false);
mockTransactionManager.isActive.andReturn(false);
capability.persist();
expect(mockPersistence.persist).toHaveBeenCalled();
});
it("if transaction is active, persist and cancel calls are" +
" queued", function () {
mockTransactionManager.isActive.and.returnValue(true);
mockTransactionManager.isActive.andReturn(true);
capability.persist();
expect(mockTransactionManager.addToTransaction).toHaveBeenCalled();
mockTransactionManager.addToTransaction.calls.mostRecent().args[1]();
mockTransactionManager.addToTransaction.mostRecentCall.args[1]();
expect(mockPersistence.persist).toHaveBeenCalled();
mockTransactionManager.addToTransaction.calls.mostRecent().args[2]();
mockTransactionManager.addToTransaction.mostRecentCall.args[2]();
expect(mockPersistence.refresh).toHaveBeenCalled();
});
it("wraps getSpace", function () {
mockPersistence.getSpace.and.returnValue('foo');
mockPersistence.getSpace.andReturn('foo');
expect(capability.getSpace()).toEqual('foo');
});

View File

@@ -38,7 +38,7 @@ define(
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"])
];
mockedSaveActions.forEach(function (action) {
action.getMetadata.and.returnValue(mockSaveActionMetadata);
action.getMetadata.andReturn(mockSaveActionMetadata);
});
return mockedSaveActions;
} else if (actionContext.category === "conclude-editing") {
@@ -54,14 +54,14 @@ define(
beforeEach(function () {
mockActions = jasmine.createSpyObj("action", ["getActions"]);
mockActions.getActions.and.callFake(fakeGetActions);
mockActions.getActions.andCallFake(fakeGetActions);
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
mockScope.action = mockActions;
controller = new EditActionController(mockScope);
});
function makeControllerUpdateActions() {
mockScope.$watch.calls.mostRecent().args[1]();
mockScope.$watch.mostRecentCall.args[1]();
}
it("watches scope that may change applicable actions", function () {

View File

@@ -61,17 +61,17 @@ define(
mockLocation = jasmine.createSpyObj('$location',
["search"]
);
mockLocation.search.and.returnValue({"view": "fixed"});
mockLocation.search.andReturn({"view": "fixed"});
mockNavigationService = jasmine.createSpyObj('navigationService',
["checkBeforeNavigation"]
);
removeCheck = jasmine.createSpy('removeCheck');
mockNavigationService.checkBeforeNavigation.and.returnValue(removeCheck);
mockNavigationService.checkBeforeNavigation.andReturn(removeCheck);
mockObject.getId.and.returnValue("test");
mockObject.getModel.and.returnValue({ name: "Test object" });
mockObject.getCapability.and.callFake(function (key) {
mockObject.getId.andReturn("test");
mockObject.getModel.andReturn({ name: "Test object" });
mockObject.getCapability.andCallFake(function (key) {
return mockCapabilities[key];
});
@@ -81,10 +81,10 @@ define(
{ key: 'xyz' }
];
mockObject.useCapability.and.callFake(function (c) {
mockObject.useCapability.andCallFake(function (c) {
return (c === 'view') && testViews;
});
mockLocation.search.and.returnValue({ view: 'def' });
mockLocation.search.andReturn({ view: 'def' });
mockScope.domainObject = mockObject;
@@ -99,17 +99,17 @@ define(
expect(mockNavigationService.checkBeforeNavigation)
.toHaveBeenCalledWith(jasmine.any(Function));
var checkFn = mockNavigationService.checkBeforeNavigation.calls.mostRecent().args[0];
var checkFn = mockNavigationService.checkBeforeNavigation.mostRecentCall.args[0];
mockEditorCapability.isEditContextRoot.and.returnValue(false);
mockEditorCapability.dirty.and.returnValue(false);
mockEditorCapability.isEditContextRoot.andReturn(false);
mockEditorCapability.dirty.andReturn(false);
expect(checkFn()).toBe("Continuing will cause the loss of any unsaved changes.");
mockEditorCapability.isEditContextRoot.and.returnValue(true);
mockEditorCapability.isEditContextRoot.andReturn(true);
expect(checkFn()).toBe("Continuing will cause the loss of any unsaved changes.");
mockEditorCapability.dirty.and.returnValue(true);
mockEditorCapability.dirty.andReturn(true);
expect(checkFn())
.toBe("Continuing will cause the loss of any unsaved changes.");
@@ -119,7 +119,7 @@ define(
expect(mockScope.$on)
.toHaveBeenCalledWith("$destroy", jasmine.any(Function));
mockScope.$on.calls.mostRecent().args[1]();
mockScope.$on.mostRecentCall.args[1]();
expect(mockEditorCapability.finish).toHaveBeenCalled();
expect(removeCheck).toHaveBeenCalled();

View File

@@ -41,13 +41,13 @@ define(
['getTrueRoot']
);
mockDomainObject.getId.and.returnValue('test-id');
mockDomainObject.getCapability.and.returnValue(mockContext);
mockDomainObject.getId.andReturn('test-id');
mockDomainObject.getCapability.andReturn(mockContext);
// Return a new instance of the root object each time
mockContext.getTrueRoot.and.callFake(function () {
mockContext.getTrueRoot.andCallFake(function () {
var mockRoot = jasmine.createSpyObj('root', ['getId']);
mockRoot.getId.and.returnValue('root-id');
mockRoot.getId.andReturn('root-id');
return mockRoot;
});
@@ -63,7 +63,7 @@ define(
});
it("exposes the root object found via the object's context capability", function () {
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
// Verify that the correct capability was used
expect(mockDomainObject.getCapability)
@@ -76,10 +76,10 @@ define(
it("preserves the same root instance to avoid excessive refreshing", function () {
var firstRoot;
// Expose the domain object
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
firstRoot = controller.getRoot();
// Update!
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
// Should still have the same object instance, to avoid
// triggering the watch used by the template we're supporting
expect(controller.getRoot()).toBe(firstRoot);
@@ -90,18 +90,18 @@ define(
it("updates the root when it changes", function () {
var firstRoot;
// Expose the domain object
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
firstRoot = controller.getRoot();
// Change the exposed root
mockContext.getTrueRoot.and.callFake(function () {
mockContext.getTrueRoot.andCallFake(function () {
var mockRoot = jasmine.createSpyObj('root', ['getId']);
mockRoot.getId.and.returnValue('other-root-id');
mockRoot.getId.andReturn('other-root-id');
return mockRoot;
});
// Update!
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
// Should still have the same object instance, to avoid
// triggering the watch used by the template we're supporting

View File

@@ -63,13 +63,13 @@ define(
mockMutationCapability = jasmine.createSpyObj("mutationCapability", [
"listen"
]);
mockMutationCapability.listen.and.returnValue(mockUnlisten);
mockMutationCapability.listen.andReturn(mockUnlisten);
mockDomainObject = jasmine.createSpyObj("domainObject", [
"getCapability",
"useCapability"
]);
mockDomainObject.useCapability.and.returnValue(mockCompositionCapability);
mockDomainObject.getCapability.and.returnValue(mockMutationCapability);
mockDomainObject.useCapability.andReturn(mockCompositionCapability);
mockDomainObject.getCapability.andReturn(mockMutationCapability);
mockScope = jasmine.createSpyObj("$scope", ['$on']);
mockSelection = jasmine.createSpyObj("selection", [
@@ -77,7 +77,7 @@ define(
'off',
'get'
]);
mockSelection.get.and.returnValue([]);
mockSelection.get.andReturn([]);
mockOpenMCT = {
selection: mockSelection
};
@@ -88,7 +88,7 @@ define(
}
};
spyOn(ElementsController.prototype, 'refreshComposition').and.callThrough();
spyOn(ElementsController.prototype, 'refreshComposition').andCallThrough();
controller = new ElementsController(mockScope, mockOpenMCT);
});
@@ -123,29 +123,29 @@ define(
});
it("refreshes composition on selection", function () {
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
expect(ElementsController.prototype.refreshComposition).toHaveBeenCalledWith(mockDomainObject);
});
it("listens on mutation and refreshes composition", function () {
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
expect(mockDomainObject.getCapability).toHaveBeenCalledWith('mutation');
expect(mockMutationCapability.listen).toHaveBeenCalled();
expect(ElementsController.prototype.refreshComposition.calls.count()).toBe(1);
expect(ElementsController.prototype.refreshComposition.calls.length).toBe(1);
mockMutationCapability.listen.calls.mostRecent().args[0](mockDomainObject);
mockMutationCapability.listen.mostRecentCall.args[0](mockDomainObject);
expect(ElementsController.prototype.refreshComposition.calls.count()).toBe(2);
expect(ElementsController.prototype.refreshComposition.calls.length).toBe(2);
});
it("cleans up mutation listener when selection changes", function () {
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
expect(mockMutationCapability.listen).toHaveBeenCalled();
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
expect(mockUnlisten).toHaveBeenCalled();
});
@@ -156,7 +156,7 @@ define(
elementProxy: {}
}
};
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
expect(mockDomainObject.getCapability).not.toHaveBeenCalledWith('mutation');
});
@@ -167,13 +167,13 @@ define(
firstCompositionCallback,
secondCompositionCallback;
spyOn(mockCompositionCapability, "then").and.callThrough();
spyOn(mockCompositionCapability, "then").andCallThrough();
controller.refreshComposition(mockDomainObject);
controller.refreshComposition(mockDomainObject);
firstCompositionCallback = mockCompositionCapability.then.calls.all()[0].args[0];
secondCompositionCallback = mockCompositionCapability.then.calls.all()[1].args[0];
firstCompositionCallback = mockCompositionCapability.then.calls[0].args[0];
secondCompositionCallback = mockCompositionCapability.then.calls[1].args[0];
secondCompositionCallback(secondMockCompositionObjects);
firstCompositionCallback(mockCompositionObjects);

View File

@@ -51,9 +51,9 @@ define(
"hasFeature"
]
);
mockType.hasFeature.and.returnValue(true);
mockType.getName.and.returnValue(name);
mockType.getKey.and.returnValue(name);
mockType.hasFeature.andReturn(true);
mockType.getName.andReturn(name);
mockType.getKey.andReturn(name);
return mockType;
}
@@ -77,7 +77,7 @@ define(
mockTypeMap[type.getKey()] = type;
});
mockTypeService.getType.and.callFake(function (key) {
mockTypeService.getType.andCallFake(function (key) {
return mockTypeMap[key];
});

View File

@@ -49,8 +49,8 @@ define(
"hasFeature"
]
);
mockType.hasFeature.and.returnValue(true);
mockType.getName.and.returnValue(name);
mockType.hasFeature.andReturn(true);
mockType.getName.andReturn(name);
return mockType;
}
@@ -74,11 +74,11 @@ define(
return mockPolicyMap[type.getName()];
};
mockPolicyService.allow.and.callFake(function (category, type) {
mockPolicyService.allow.andCallFake(function (category, type) {
return category === "creation" && mockCreationPolicy(type) ? true : false;
});
mockTypeService.listTypes.and.returnValue(mockTypes);
mockTypeService.listTypes.andReturn(mockTypes);
provider = new CreateActionProvider(
mockTypeService,

View File

@@ -77,10 +77,10 @@ define(
"useCapability"
]
);
mockDomainObject.hasCapability.and.callFake(function (name) {
mockDomainObject.hasCapability.andCallFake(function (name) {
return !!capabilities[name];
});
mockDomainObject.getCapability.and.callFake(function (name) {
mockDomainObject.getCapability.andCallFake(function (name) {
return capabilities[name];
});
mockSaveAction = jasmine.createSpyObj(
@@ -117,14 +117,14 @@ define(
mockContext = {
domainObject: mockParent
};
mockParent.useCapability.and.returnValue(mockDomainObject);
mockParent.useCapability.andReturn(mockDomainObject);
mockType.getKey.and.returnValue("test");
mockType.getCssClass.and.returnValue("icon-telemetry");
mockType.getDescription.and.returnValue("a test type");
mockType.getName.and.returnValue("Test");
mockType.getProperties.and.returnValue([]);
mockType.getInitialModel.and.returnValue({});
mockType.getKey.andReturn("test");
mockType.getCssClass.andReturn("icon-telemetry");
mockType.getDescription.andReturn("a test type");
mockType.getName.andReturn("Test");
mockType.getProperties.andReturn([]);
mockType.getInitialModel.andReturn({});
action = new CreateAction(
mockType,
@@ -144,7 +144,7 @@ define(
describe("the perform function", function () {
var promise = jasmine.createSpyObj("promise", ["then"]);
beforeEach(function () {
capabilities.action.getActions.and.returnValue([mockEditAction]);
capabilities.action.getActions.andReturn([mockEditAction]);
});
it("uses the instantiation capability when performed", function () {
@@ -159,30 +159,30 @@ define(
it("uses the save-as action if object does not have an edit action" +
" available", function () {
capabilities.action.getActions.and.returnValue([]);
capabilities.action.perform.and.returnValue(mockPromise(undefined));
capabilities.editor.save.and.returnValue(promise);
capabilities.action.getActions.andReturn([]);
capabilities.action.perform.andReturn(mockPromise(undefined));
capabilities.editor.save.andReturn(promise);
action.perform();
expect(capabilities.action.perform).toHaveBeenCalledWith("save-as");
});
describe("uses to editor capability", function () {
beforeEach(function () {
capabilities.action.getActions.and.returnValue([]);
capabilities.action.perform.and.returnValue(promise);
capabilities.editor.save.and.returnValue(promise);
capabilities.action.getActions.andReturn([]);
capabilities.action.perform.andReturn(promise);
capabilities.editor.save.andReturn(promise);
});
it("to save the edit if user saves dialog", function () {
action.perform();
expect(promise.then).toHaveBeenCalled();
promise.then.calls.mostRecent().args[0]();
promise.then.mostRecentCall.args[0]();
expect(capabilities.editor.save).toHaveBeenCalled();
});
it("to finish the edit if user cancels dialog", function () {
action.perform();
promise.then.calls.mostRecent().args[1]();
promise.then.mostRecentCall.args[1]();
expect(capabilities.editor.finish).toHaveBeenCalled();
});
});

View File

@@ -49,10 +49,10 @@ define(
it("populates the scope with create actions", function () {
mockScope.action = mockActions;
mockActions.getActions.and.returnValue(["a", "b", "c"]);
mockActions.getActions.andReturn(["a", "b", "c"]);
// Call the watch
mockScope.$watch.calls.mostRecent().args[1]();
mockScope.$watch.mostRecentCall.args[1]();
// Should have grouped and ungrouped actions in scope now
expect(mockScope.createActions.length).toEqual(3);

View File

@@ -41,10 +41,10 @@ define(
"property" + name,
["getDefinition", "getValue", "setValue"]
);
mockProperty.getDefinition.and.returnValue({
mockProperty.getDefinition.andReturn({
control: "textfield"
});
mockProperty.getValue.and.returnValue(name);
mockProperty.getValue.andReturn(name);
return mockProperty;
}
@@ -74,12 +74,12 @@ define(
testModel = { someKey: "some value" };
mockType.getKey.and.returnValue("test");
mockType.getCssClass.and.returnValue("icon-telemetry");
mockType.getDescription.and.returnValue("a test type");
mockType.getName.and.returnValue("Test");
mockType.getInitialModel.and.returnValue(testModel);
mockType.getProperties.and.returnValue(mockProperties);
mockType.getKey.andReturn("test");
mockType.getCssClass.andReturn("icon-telemetry");
mockType.getDescription.andReturn("a test type");
mockType.getName.andReturn("Test");
mockType.getInitialModel.andReturn(testModel);
mockType.getProperties.andReturn(mockProperties);
mockDomainObject = jasmine.createSpyObj(
'domainObject',
@@ -87,9 +87,9 @@ define(
);
//Mocking the getCapability('type') call
mockDomainObject.getCapability.and.returnValue(mockType);
mockDomainObject.useCapability.and.returnValue();
mockDomainObject.getModel.and.returnValue(testModel);
mockDomainObject.getCapability.andReturn(mockType);
mockDomainObject.useCapability.andReturn();
mockDomainObject.getModel.andReturn(testModel);
wizard = new CreateWizard(
mockDomainObject,
@@ -147,11 +147,9 @@ define(
"C": "ValueC"
},
compareModel = wizard.createModel(formValue);
//populateObjectFromInput adds a .location attribute that is not added by createModel.
compareModel.location = undefined;
wizard.populateObjectFromInput(formValue);
expect(mockDomainObject.useCapability).toHaveBeenCalledWith('mutation', jasmine.any(Function));
expect(mockDomainObject.useCapability.calls.mostRecent().args[1]()).toEqual(compareModel);
expect(mockDomainObject.useCapability.mostRecentCall.args[1]()).toEqual(compareModel);
});
it("validates selection types using policy", function () {
@@ -170,7 +168,7 @@ define(
rows = structure.sections[sections.length - 1].rows,
locationRow = rows[rows.length - 1];
mockDomainObj.getCapability.and.returnValue(mockOtherType);
mockDomainObj.getCapability.andReturn(mockOtherType);
locationRow.validate(mockDomainObj);
// Should check policy to see if the user-selected location

View File

@@ -38,12 +38,12 @@ define(
});
it("allows creation of types with the creation feature", function () {
mockType.hasFeature.and.returnValue(true);
mockType.hasFeature.andReturn(true);
expect(policy.allow(mockType)).toBeTruthy();
});
it("disallows creation of types without the creation feature", function () {
mockType.hasFeature.and.returnValue(false);
mockType.hasFeature.andReturn(false);
expect(policy.allow(mockType)).toBeFalsy();
});
});

View File

@@ -103,33 +103,33 @@ define(
["persist", "getSpace"]
);
mockParentObject.getCapability.and.callFake(function (key) {
mockParentObject.getCapability.andCallFake(function (key) {
return mockCapabilities[key];
});
mockParentObject.useCapability.and.callFake(function (key, value) {
mockParentObject.useCapability.andCallFake(function (key, value) {
return mockCapabilities[key].invoke(value);
});
mockParentObject.getId.and.returnValue('parentId');
mockParentObject.getId.andReturn('parentId');
mockNewObject.getId.and.returnValue('newId');
mockNewObject.getCapability.and.callFake(function (c) {
mockNewObject.getId.andReturn('newId');
mockNewObject.getCapability.andCallFake(function (c) {
return c === 'persistence' ?
mockNewPersistenceCapability : undefined;
});
mockPersistenceCapability.persist
.and.returnValue(mockPromise(true));
.andReturn(mockPromise(true));
mockNewPersistenceCapability.persist
.and.returnValue(mockPromise(true));
.andReturn(mockPromise(true));
mockMutationCapability.invoke.and.returnValue(mockPromise(true));
mockPersistenceCapability.getSpace.and.returnValue("testSpace");
mockCompositionCapability.invoke.and.returnValue(
mockMutationCapability.invoke.andReturn(mockPromise(true));
mockPersistenceCapability.getSpace.andReturn("testSpace");
mockCompositionCapability.invoke.andReturn(
mockPromise([mockNewObject])
);
mockCompositionCapability.add.and.returnValue(mockPromise(true));
mockCreationCapability.instantiate.and.returnValue(mockNewObject);
mockCreationCapability.invoke.and.callFake(function (model) {
mockCompositionCapability.add.andReturn(mockPromise(true));
mockCreationCapability.instantiate.andReturn(mockNewObject);
mockCreationCapability.invoke.andCallFake(function (model) {
return mockCreationCapability.instantiate(model);
});
@@ -163,10 +163,10 @@ define(
mockCallback = jasmine.createSpy('callback');
// Act as if the object had been created
mockCompositionCapability.add.and.callFake(function (id) {
mockDomainObject.getId.and.returnValue(id);
mockCompositionCapability.add.andCallFake(function (id) {
mockDomainObject.getId.andReturn(id);
mockCompositionCapability.invoke
.and.returnValue(mockPromise([mockDomainObject]));
.andReturn(mockPromise([mockDomainObject]));
return mockPromise(mockDomainObject);
});
@@ -200,7 +200,7 @@ define(
// created object - this is an error.
var model = { someKey: "some value" };
mockCompositionCapability.add.and.returnValue(mockPromise(false));
mockCompositionCapability.add.andReturn(mockPromise(false));
creationService.createObject(model, mockParentObject);

View File

@@ -64,9 +64,9 @@ define(
["then"]
);
mockDomainObject.getCapability.and.returnValue(mockContext);
mockContext.getRoot.and.returnValue(mockRootObject);
mockObjectService.getObjects.and.returnValue(getObjectsPromise);
mockDomainObject.getCapability.andReturn(mockContext);
mockContext.getRoot.andReturn(mockRootObject);
mockObjectService.getObjects.andReturn(getObjectsPromise);
mockScope.ngModel = {};
mockScope.field = "someField";
@@ -76,7 +76,7 @@ define(
describe("when context is available", function () {
beforeEach(function () {
mockContext.getRoot.and.returnValue(mockRootObject);
mockContext.getRoot.andReturn(mockRootObject);
controller = new LocatorController(mockScope, mockTimeout, mockObjectService);
});
@@ -96,8 +96,8 @@ define(
it("changes its own model on embedded model updates", function () {
// Need to pass on selection changes as updates to
// the control's value
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockTimeout.calls.mostRecent().args[0]();
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockTimeout.mostRecentCall.args[0]();
expect(mockScope.ngModel.someField).toEqual(mockDomainObject);
expect(mockScope.rootObject).toEqual(mockRootObject);
@@ -109,11 +109,11 @@ define(
it("rejects changes which fail validation", function () {
mockScope.structure = { validate: jasmine.createSpy('validate') };
mockScope.structure.validate.and.returnValue(false);
mockScope.structure.validate.andReturn(false);
// Pass selection change
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockTimeout.calls.mostRecent().args[0]();
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockTimeout.mostRecentCall.args[0]();
expect(mockScope.structure.validate).toHaveBeenCalled();
// Change should have been rejected
@@ -126,13 +126,13 @@ define(
['$setValidity']
);
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockTimeout.calls.mostRecent().args[0]();
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockTimeout.mostRecentCall.args[0]();
expect(mockScope.ngModelController.$setValidity)
.toHaveBeenCalledWith(jasmine.any(String), true);
mockScope.$watch.calls.mostRecent().args[1](undefined);
mockTimeout.calls.mostRecent().args[0]();
mockScope.$watch.mostRecentCall.args[1](undefined);
mockTimeout.mostRecentCall.args[0]();
expect(mockScope.ngModelController.$setValidity)
.toHaveBeenCalledWith(jasmine.any(String), false);
});
@@ -141,27 +141,27 @@ define(
var defaultRoot = "DEFAULT_ROOT";
beforeEach(function () {
mockContext.getRoot.and.returnValue(undefined);
getObjectsPromise.then.and.callFake(function (callback) {
mockContext.getRoot.andReturn(undefined);
getObjectsPromise.then.andCallFake(function (callback) {
callback({'ROOT': defaultRoot});
});
controller = new LocatorController(mockScope, mockTimeout, mockObjectService);
});
it("provides a default context where none is available", function () {
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockTimeout.calls.mostRecent().args[0]();
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockTimeout.mostRecentCall.args[0]();
expect(mockScope.rootObject).toBe(defaultRoot);
});
it("does not issue redundant requests for the root object", function () {
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockTimeout.calls.mostRecent().args[0]();
mockScope.$watch.calls.mostRecent().args[1](undefined);
mockTimeout.calls.mostRecent().args[0]();
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockTimeout.calls.mostRecent().args[0]();
expect(mockObjectService.getObjects.calls.count())
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockTimeout.mostRecentCall.args[0]();
mockScope.$watch.mostRecentCall.args[1](undefined);
mockTimeout.mostRecentCall.args[0]();
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockTimeout.mostRecentCall.args[0]();
expect(mockObjectService.getObjects.calls.length)
.toEqual(1);
});

View File

@@ -58,10 +58,10 @@ define(
mockEditAction = jasmine.createSpyObj('edit', ['getMetadata']);
mockPropertiesAction = jasmine.createSpyObj('edit', ['getMetadata']);
mockDomainObject.getCapability.and.callFake(function (capability) {
mockDomainObject.getCapability.andCallFake(function (capability) {
return capabilities[capability];
});
mockDomainObject.hasCapability.and.callFake(function (capability) {
mockDomainObject.hasCapability.andCallFake(function (capability) {
return !!capabilities[capability];
});
@@ -71,13 +71,13 @@ define(
plotView = { key: "plot", editable: false };
testViews = [];
mockDomainObject.useCapability.and.callFake(function (c) {
mockDomainObject.useCapability.andCallFake(function (c) {
// Provide test views, only for the view capability
return c === 'view' && testViews;
});
mockEditAction.getMetadata.and.returnValue({ key: 'edit' });
mockPropertiesAction.getMetadata.and.returnValue({ key: 'properties' });
mockEditAction.getMetadata.andReturn({ key: 'edit' });
mockPropertiesAction.getMetadata.andReturn({ key: 'properties' });
testContext = {
domainObject: mockDomainObject,
@@ -111,20 +111,20 @@ define(
it("disallows the edit action when object is already being" +
" edited", function () {
testViews = [editableView];
mockEditorCapability.isEditContextRoot.and.returnValue(true);
mockEditorCapability.isEditContextRoot.andReturn(true);
expect(policy.allow(mockEditAction, testContext)).toBe(false);
});
it("allows editing of panels in plot view", function () {
testViews = [plotView];
mockTypeCapability.getKey.and.returnValue('telemetry.panel');
mockTypeCapability.getKey.andReturn('telemetry.panel');
expect(policy.allow(mockEditAction, testContext)).toBe(true);
});
it("disallows editing of plot view when object not a panel type", function () {
testViews = [plotView];
mockTypeCapability.getKey.and.returnValue('something.else');
mockTypeCapability.getKey.andReturn('something.else');
expect(policy.allow(mockEditAction, testContext)).toBe(false);
});

View File

@@ -41,20 +41,20 @@ define(
mockEditorCapability = jasmine.createSpyObj("editorCapability", ["isEditContextRoot", "inEditContext"]);
navigatedObject = jasmine.createSpyObj("navigatedObject", ["hasCapability", "getCapability"]);
navigatedObject.getCapability.and.returnValue(mockEditorCapability);
navigatedObject.hasCapability.and.returnValue(false);
navigatedObject.getCapability.andReturn(mockEditorCapability);
navigatedObject.hasCapability.andReturn(false);
mockDomainObject = jasmine.createSpyObj("domainObject", ["hasCapability", "getCapability"]);
mockDomainObject.hasCapability.and.returnValue(false);
mockDomainObject.getCapability.and.returnValue(mockEditorCapability);
mockDomainObject.hasCapability.andReturn(false);
mockDomainObject.getCapability.andReturn(mockEditorCapability);
navigationService = jasmine.createSpyObj("navigationService", ["getNavigation"]);
navigationService.getNavigation.and.returnValue(navigatedObject);
navigationService.getNavigation.andReturn(navigatedObject);
metadata = {key: "move"};
mockAction = jasmine.createSpyObj("action", ["getMetadata"]);
mockAction.getMetadata.and.returnValue(metadata);
mockAction.getMetadata.andReturn(metadata);
context = {domainObject: mockDomainObject};
@@ -67,8 +67,8 @@ define(
it('Allows "window" action when navigated object in edit mode,' +
' but selected object not in edit mode ', function () {
navigatedObject.hasCapability.and.returnValue(true);
mockEditorCapability.isEditContextRoot.and.returnValue(true);
navigatedObject.hasCapability.andReturn(true);
mockEditorCapability.isEditContextRoot.andReturn(true);
metadata.key = "window";
expect(policy.allow(mockAction, context)).toBe(true);
});
@@ -79,12 +79,12 @@ define(
var mockParent = jasmine.createSpyObj("parentObject", ["hasCapability"]),
mockContextCapability = jasmine.createSpyObj("contextCapability", ["getParent"]);
mockParent.hasCapability.and.returnValue(true);
mockContextCapability.getParent.and.returnValue(mockParent);
navigatedObject.hasCapability.and.returnValue(true);
mockParent.hasCapability.andReturn(true);
mockContextCapability.getParent.andReturn(mockParent);
navigatedObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.and.returnValue(mockContextCapability);
mockDomainObject.hasCapability.and.callFake(function (capability) {
mockDomainObject.getCapability.andReturn(mockContextCapability);
mockDomainObject.hasCapability.andCallFake(function (capability) {
switch (capability) {
case "editor": return false;
case "context": return true;
@@ -97,19 +97,19 @@ define(
it('Disallows "move" action when navigated object in edit mode,' +
' but selected object not in edit mode ', function () {
navigatedObject.hasCapability.and.returnValue(true);
mockEditorCapability.isEditContextRoot.and.returnValue(true);
mockEditorCapability.inEditContext.and.returnValue(false);
navigatedObject.hasCapability.andReturn(true);
mockEditorCapability.isEditContextRoot.andReturn(true);
mockEditorCapability.inEditContext.andReturn(false);
metadata.key = "move";
expect(policy.allow(mockAction, context)).toBe(false);
});
it('Disallows copy action when navigated object and' +
' selected object in edit mode', function () {
navigatedObject.hasCapability.and.returnValue(true);
mockDomainObject.hasCapability.and.returnValue(true);
mockEditorCapability.isEditContextRoot.and.returnValue(true);
mockEditorCapability.inEditContext.and.returnValue(true);
navigatedObject.hasCapability.andReturn(true);
mockDomainObject.hasCapability.andReturn(true);
mockEditorCapability.isEditContextRoot.andReturn(true);
mockEditorCapability.inEditContext.andReturn(true);
metadata.key = "copy";
expect(policy.allow(mockAction, context)).toBe(false);

View File

@@ -54,11 +54,11 @@ define(
mockPropertiesAction = jasmine.createSpyObj('properties', ['getMetadata']);
mockOtherAction = jasmine.createSpyObj('other', ['getMetadata']);
mockEditAction.getMetadata.and.returnValue({ key: 'edit' });
mockPropertiesAction.getMetadata.and.returnValue({ key: 'properties' });
mockOtherAction.getMetadata.and.returnValue({key: 'other'});
mockEditAction.getMetadata.andReturn({ key: 'edit' });
mockPropertiesAction.getMetadata.andReturn({ key: 'properties' });
mockOtherAction.getMetadata.andReturn({key: 'other'});
mockDomainObject.getId.and.returnValue('test:testId');
mockDomainObject.getId.andReturn('test:testId');
testContext = {
domainObject: mockDomainObject,
@@ -69,7 +69,7 @@ define(
});
it("Applies to edit action", function () {
mockObjectAPI.getProvider.and.returnValue({});
mockObjectAPI.getProvider.andReturn({});
expect(mockObjectAPI.getProvider).not.toHaveBeenCalled();
policy.allow(mockEditAction, testContext);
@@ -77,7 +77,7 @@ define(
});
it("Applies to properties action", function () {
mockObjectAPI.getProvider.and.returnValue({});
mockObjectAPI.getProvider.andReturn({});
expect(mockObjectAPI.getProvider).not.toHaveBeenCalled();
policy.allow(mockPropertiesAction, testContext);
@@ -85,7 +85,7 @@ define(
});
it("does not apply to other actions", function () {
mockObjectAPI.getProvider.and.returnValue({});
mockObjectAPI.getProvider.andReturn({});
expect(mockObjectAPI.getProvider).not.toHaveBeenCalled();
policy.allow(mockOtherAction, testContext);
@@ -93,10 +93,10 @@ define(
});
it("Tests object provider for editability", function () {
mockObjectAPI.getProvider.and.returnValue({});
mockObjectAPI.getProvider.andReturn({});
expect(policy.allow(mockEditAction, testContext)).toBe(false);
expect(mockObjectAPI.getProvider).toHaveBeenCalled();
mockObjectAPI.getProvider.and.returnValue({save: function () {}});
mockObjectAPI.getProvider.andReturn({save: function () {}});
expect(policy.allow(mockEditAction, testContext)).toBe(true);
});
});

View File

@@ -35,12 +35,12 @@ define(
'domainObject',
['hasCapability', 'getCapability']
);
mockDomainObject.getCapability.and.returnValue({
mockDomainObject.getCapability.andReturn({
inEditContext: function () {
return true;
}
});
mockDomainObject.hasCapability.and.callFake(function (c) {
mockDomainObject.hasCapability.andCallFake(function (c) {
return (c === 'editor') && testMode;
});

View File

@@ -52,8 +52,8 @@ define([
'useCapability'
]);
domainObject.getId.and.returnValue('anId');
domainObject.getModel.and.returnValue({name: 'anObject'});
domainObject.getId.andReturn('anId');
domainObject.getModel.andReturn({name: 'anObject'});
representation = {
key: 'someRepresentation'
@@ -75,7 +75,7 @@ define([
expect(domainObject.useCapability)
.toHaveBeenCalledWith('mutation', jasmine.any(Function));
var mutateValue = domainObject.useCapability.calls.all()[0].args[1]();
var mutateValue = domainObject.useCapability.calls[0].args[1]();
expect(mutateValue.configuration.someRepresentation)
.toEqual({some: 'config'});

View File

@@ -0,0 +1,156 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, 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/representers/EditToolbarRepresenter"],
function (EditToolbarRepresenter) {
describe("The Edit mode toolbar representer", function () {
var mockScope,
mockElement,
testAttrs,
mockUnwatch,
representer,
mockOpenMCT,
mockSelection;
beforeEach(function () {
mockScope = jasmine.createSpyObj(
'$scope',
['$on', '$watch', '$watchCollection', "commit", "$apply"]
);
mockElement = {};
testAttrs = { toolbar: 'testToolbar' };
mockScope.$parent = jasmine.createSpyObj(
'$parent',
['$watch', '$watchCollection']
);
mockUnwatch = jasmine.createSpy('unwatch');
mockScope.$parent.$watchCollection.andReturn(mockUnwatch);
mockSelection = jasmine.createSpyObj("selection", [
'on',
'off',
'get'
]);
mockSelection.get.andReturn([]);
mockOpenMCT = {
selection: mockSelection
};
representer = new EditToolbarRepresenter(
mockOpenMCT,
mockScope,
mockElement,
testAttrs
);
});
it("exposes toolbar state under a attr-defined name", function () {
// A structure/state object should have been added to the
// parent scope under the name provided in the "toolbar"
// attribute
expect(mockScope.$parent.testToolbar).toBeDefined();
});
it("is robust against lack of a toolbar definition", function () {
expect(function () {
representer.represent({});
}).not.toThrow();
});
it("watches for toolbar state changes", function () {
representer.represent({});
expect(mockScope.$watchCollection).toHaveBeenCalledWith(
jasmine.any(Function),
jasmine.any(Function)
);
expect(mockScope.$watchCollection.calls[0].args[0]())
.toBe(mockScope.$parent.testToolbar.state);
});
it("removes state from parent scope on destroy", function () {
// Verify precondition
expect(mockScope.$parent.testToolbar).toBeDefined();
// Destroy the representer
representer.destroy();
// Should have removed toolbar state from view
expect(mockScope.$parent.testToolbar).toBeUndefined();
});
// Verify a simple interaction between selection state and toolbar
// state; more complicated interactions are tested in EditToolbar.
it("conveys state changes", function () {
var testObject = { k: 123 };
// Provide a view which has a toolbar
representer.represent({
toolbar: { sections: [{ items: [{ property: 'k' }] }] }
});
// Update the selection
mockScope.selection.select(testObject);
expect(mockScope.$watchCollection.mostRecentCall.args[0])
.toEqual('selection.all()'); // Make sure we're using right watch
mockScope.$watchCollection.mostRecentCall.args[1]([testObject]);
// Update the state
mockScope.$parent.testToolbar.state[0] = 456;
// Invoke the first watch (assumed to be for toolbar state)
mockScope.$watchCollection.calls[0].args[1](
mockScope.$parent.testToolbar.state
);
// Should have updated the original object
expect(testObject.k).toEqual(456);
// Should have committed the change
expect(mockScope.commit).toHaveBeenCalled();
});
it("does not commit if nothing changed", function () {
var testObject = { k: 123 };
// Provide a view which has a toolbar
representer.represent({
toolbar: { sections: [{ items: [{ property: 'k' }] }] }
});
// Update the selection
mockScope.selection.select(testObject);
expect(mockScope.$watchCollection.mostRecentCall.args[0])
.toEqual('selection.all()'); // Make sure we're using right watch
mockScope.$watchCollection.mostRecentCall.args[1]([testObject]);
// Invoke the first watch (assumed to be for toolbar state)
mockScope.$watchCollection.calls[0].args[1](
mockScope.$parent.testToolbar.state
);
// Should have committed the change
expect(mockScope.commit).not.toHaveBeenCalled();
});
});
}
);

View File

@@ -0,0 +1,128 @@
/*****************************************************************************
* Open MCT, Copyright (c) 2014-2018, 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/representers/EditToolbarSelection'],
function (EditToolbarSelection) {
describe("The Edit mode selection manager", function () {
var testProxy,
testElement,
otherElement,
selection,
mockSelection,
mockOpenMCT,
mockScope;
beforeEach(function () {
testProxy = { someKey: "some value" };
testElement = { someOtherKey: "some other value" };
otherElement = { yetAnotherKey: 42 };
mockSelection = jasmine.createSpyObj("selection", [
// 'select',
'on',
'off',
'get'
]);
mockSelection.get.andReturn([]);
mockOpenMCT = {
selection: mockSelection
};
mockScope = jasmine.createSpyObj('$scope', [
'$on',
'$apply'
]);
selection = new EditToolbarSelection(mockScope, mockOpenMCT);
selection.proxy(testProxy);
});
it("adds the proxy to the selection array", function () {
expect(selection.all()).toEqual([testProxy]);
});
it("exposes view proxy", function () {
expect(selection.proxy()).toBe(testProxy);
});
it("includes selected objects alongside the proxy", function () {
selection.select(testElement);
expect(selection.all()).toEqual([testProxy, testElement]);
});
it("allows elements to be deselected", function () {
selection.select(testElement);
selection.deselect();
expect(selection.all()).toEqual([testProxy]);
});
it("replaces old selections with new ones", function () {
selection.select(testElement);
selection.select(otherElement);
expect(selection.all()).toEqual([testProxy, otherElement]);
});
it("allows retrieval of the current selection", function () {
selection.select(testElement);
expect(selection.get()).toBe(testElement);
selection.select(otherElement);
expect(selection.get()).toBe(otherElement);
});
it("can check if an element is selected", function () {
selection.select(testElement);
expect(selection.selected(testElement)).toBeTruthy();
expect(selection.selected(otherElement)).toBeFalsy();
selection.select(otherElement);
expect(selection.selected(testElement)).toBeFalsy();
expect(selection.selected(otherElement)).toBeTruthy();
});
it("considers the proxy to be selected", function () {
expect(selection.selected(testProxy)).toBeTruthy();
selection.select(testElement);
// Even when something else is selected...
expect(selection.selected(testProxy)).toBeTruthy();
});
it("treats selection of the proxy as a no-op", function () {
selection.select(testProxy);
expect(selection.all()).toEqual([testProxy]);
});
it("cleans up selection on scope destroy", function () {
expect(mockScope.$on).toHaveBeenCalledWith(
'$destroy',
jasmine.any(Function)
);
mockScope.$on.mostRecentCall.args[1]();
expect(mockOpenMCT.selection.off).toHaveBeenCalledWith(
'change',
jasmine.any(Function)
);
});
});
}
);

View File

@@ -25,10 +25,7 @@ define(
function (EditToolbar) {
describe("An Edit mode toolbar", function () {
var mockOpenMCT,
mockScope,
mockObjects,
mockDomainObject,
var mockCommit,
testStructure,
testAB,
testABC,
@@ -38,30 +35,35 @@ define(
testM,
toolbar;
function getVisibility(obj) {
return !obj.hidden;
}
beforeEach(function () {
mockOpenMCT = jasmine.createSpy('openmct', ['objects']);
mockObjects = jasmine.createSpyObj('objects', ['observe']);
mockObjects.observe.and.returnValue();
mockOpenMCT.objects = mockObjects;
mockScope = jasmine.createSpyObj("$scope", [
"$watchCollection",
"$on"
]);
mockScope.$watchCollection.and.returnValue();
mockDomainObject = jasmine.createSpyObj("domainObject", [
'identifier'
]);
testStructure = [
{ name: "A", property: "a", domainObject: mockDomainObject },
{ name: "B", property: "b", domainObject: mockDomainObject },
{ name: "C", property: "c", domainObject: mockDomainObject },
{ name: "X", property: "x", domainObject: mockDomainObject },
{ name: "Y", property: "y", domainObject: mockDomainObject },
{ name: "Z", property: "z", domainObject: mockDomainObject },
{ name: "M", method: "m", domainObject: mockDomainObject }
];
mockCommit = jasmine.createSpy('commit');
testStructure = {
sections: [
{
items: [
{ name: "A", property: "a", exclusive: true },
{ name: "B", property: "b", exclusive: true },
{ name: "C", property: "c", exclusive: true }
]
},
{
items: [
{ name: "X", property: "x" },
{ name: "Y", property: "y", exclusive: true },
{ name: "Z", property: "z", exclusive: true }
]
},
{
items: [
{ name: "M", method: "m", exclusive: true }
]
}
]
};
testAB = { a: 0, b: 1 };
testABC = { a: 0, b: 1, c: 2 };
testABC2 = { a: 4, b: 1, c: 2 }; // For inconsistent-state checking
@@ -69,17 +71,151 @@ define(
testABCYZ = { a: 0, b: 1, c: 2, y: 'Y!', z: 'Z!' };
testM = { m: jasmine.createSpy("method") };
toolbar = new EditToolbar(mockScope, mockOpenMCT, testStructure);
toolbar = new EditToolbar(testStructure, mockCommit);
});
it("provides properties from the original structure", function () {
expect(
new EditToolbar(testStructure, [testABC])
.getStructure()
.sections[0]
.items[1]
.name
).toEqual("B");
});
// This is needed by mct-toolbar
it("adds keys to form structure", function () {
expect(
new EditToolbar(testStructure, [testABC])
.getStructure()
.sections[0]
.items[1]
.key
).not.toBeUndefined();
});
it("marks empty sections as hidden", function () {
// Verify that all sections are included when applicable...
toolbar.setSelection([testABCXYZ]);
expect(toolbar.getStructure().sections.map(getVisibility))
.toEqual([true, true, false]);
// ...but omitted when only some are applicable
toolbar.setSelection([testABC]);
expect(toolbar.getStructure().sections.map(getVisibility))
.toEqual([true, false, false]);
});
it("reads properties from selections", function () {
var structure, state;
toolbar.setSelection([testABC]);
structure = toolbar.getStructure();
state = toolbar.getState();
expect(state[structure.sections[0].items[0].key])
.toEqual(testABC.a);
expect(state[structure.sections[0].items[1].key])
.toEqual(testABC.b);
expect(state[structure.sections[0].items[2].key])
.toEqual(testABC.c);
});
it("reads properties from getters", function () {
var structure, state;
testABC.a = function () {
return "from a getter!";
};
toolbar.setSelection([testABC]);
structure = toolbar.getStructure();
state = toolbar.getState();
expect(state[structure.sections[0].items[0].key])
.toEqual("from a getter!");
});
it("sets properties on update", function () {
toolbar.setSelection([testABC]);
toolbar.updateState(
toolbar.getStructure().sections[0].items[0].key,
"new value"
);
// Should have updated the underlying object
expect(testABC.a).toEqual("new value");
});
it("invokes setters on update", function () {
var structure;
testABC.a = jasmine.createSpy('a');
toolbar.setSelection([testABC]);
structure = toolbar.getStructure();
toolbar.updateState(
structure.sections[0].items[0].key,
"new value"
);
// Should have updated the underlying object
expect(testABC.a).toHaveBeenCalledWith("new value");
});
it("provides a return value describing update status", function () {
// Should return true if actually updated, otherwise false
var key;
toolbar.setSelection([testABC]);
key = toolbar.getStructure().sections[0].items[0].key;
expect(toolbar.updateState(key, testABC.a)).toBeFalsy();
expect(toolbar.updateState(key, "new value")).toBeTruthy();
});
it("removes inapplicable items", function () {
// First, verify with all items
toolbar.setSelection([testABC]);
expect(toolbar.getStructure().sections[0].items.map(getVisibility))
.toEqual([true, true, true]);
// Then, try with some items omitted
toolbar.setSelection([testABC, testAB]);
expect(toolbar.getStructure().sections[0].items.map(getVisibility))
.toEqual([true, true, false]);
});
it("removes inconsistent states", function () {
// Only two of three values match among these selections
toolbar.setSelection([testABC, testABC2]);
expect(toolbar.getStructure().sections[0].items.map(getVisibility))
.toEqual([false, true, true]);
});
it("allows inclusive items", function () {
// One inclusive item is in the set, property 'x' of the
// second section; make sure items are pruned down
// when only some of the selection has x,y,z properties
toolbar.setSelection([testABC, testABCXYZ]);
expect(toolbar.getStructure().sections[1].items.map(getVisibility))
.toEqual([true, false, false]);
});
it("removes inclusive items when there are no matches", function () {
toolbar.setSelection([testABCYZ]);
expect(toolbar.getStructure().sections[1].items.map(getVisibility))
.toEqual([false, true, true]);
});
it("adds click functions when a method is specified", function () {
var structure = toolbar.getStructure();
expect(structure[6].click).toBeDefined();
});
it("adds key for controls that define a property", function () {
var structure = toolbar.getStructure();
expect(structure[0].key).toEqual(0);
toolbar.setSelection([testM]);
// Verify precondition
expect(testM.m).not.toHaveBeenCalled();
// Click!
toolbar.getStructure().sections[2].items[0].click();
// Should have called the underlying function
expect(testM.m).toHaveBeenCalled();
// Should also have committed the change
expect(mockCommit).toHaveBeenCalled();
});
});
}

View File

@@ -44,10 +44,10 @@ define(
testId = 'test-id';
mockPromise = jasmine.createSpyObj('promise', ['then']);
mockOnCommit.and.returnValue(mockPromise);
mockOnCancel.and.returnValue(mockPromise);
mockOnCommit.andReturn(mockPromise);
mockOnCancel.andReturn(mockPromise);
mockTransactionService.addToTransaction.and.callFake(function () {
mockTransactionService.addToTransaction.andCallFake(function () {
var mockRemove =
jasmine.createSpy('remove-' + mockRemoves.length);
mockRemoves.push(mockRemove);
@@ -59,7 +59,7 @@ define(
it("delegates isActive calls", function () {
[false, true].forEach(function (state) {
mockTransactionService.isActive.and.returnValue(state);
mockTransactionService.isActive.andReturn(state);
expect(manager.isActive()).toBe(state);
});
});
@@ -84,12 +84,12 @@ define(
it("invokes passed-in callbacks from its own callbacks", function () {
expect(mockOnCommit).not.toHaveBeenCalled();
mockTransactionService.addToTransaction
.calls.mostRecent().args[0]();
.mostRecentCall.args[0]();
expect(mockOnCommit).toHaveBeenCalled();
expect(mockOnCancel).not.toHaveBeenCalled();
mockTransactionService.addToTransaction
.calls.mostRecent().args[1]();
.mostRecentCall.args[1]();
expect(mockOnCancel).toHaveBeenCalled();
});
@@ -99,7 +99,7 @@ define(
jasmine.createSpy(),
jasmine.createSpy()
);
expect(mockTransactionService.addToTransaction.calls.count())
expect(mockTransactionService.addToTransaction.calls.length)
.toEqual(1);
});
@@ -109,7 +109,7 @@ define(
jasmine.createSpy(),
jasmine.createSpy()
);
expect(mockTransactionService.addToTransaction.calls.count())
expect(mockTransactionService.addToTransaction.calls.length)
.toEqual(2);
});

View File

@@ -40,7 +40,7 @@ define(
beforeEach(function () {
mockQ = jasmine.createSpyObj("$q", ["all"]);
mockQ.all.and.returnValue(fastPromise());
mockQ.all.andReturn(fastPromise());
mockLog = jasmine.createSpyObj("$log", ["error"]);
transactionService = new TransactionService(mockQ, mockLog);
});

View File

@@ -92,7 +92,7 @@ define(
describe("and an exception is encountered during commit", function () {
beforeEach(function () {
mockCommit.and.callFake(function () {
mockCommit.andCallFake(function () {
throw new Error("test error");
});
transaction.commit();

View File

@@ -115,10 +115,8 @@ define([
UTCTimeFormat.prototype.format = function (value) {
if (arguments.length > 1) {
return getScaledFormat(value);
} else if (value !== undefined) {
return moment.utc(value).format(DATE_FORMAT) + "Z";
} else {
return value;
return moment.utc(value).format(DATE_FORMAT) + "Z";
}
};

View File

@@ -34,6 +34,7 @@ define([
"./src/controllers/ContextMenuController",
"./src/controllers/ClickAwayController",
"./src/controllers/ViewSwitcherController",
"./src/controllers/BottomBarController",
"./src/controllers/GetterSetterController",
"./src/controllers/SelectorController",
"./src/controllers/ObjectInspectorController",
@@ -48,14 +49,11 @@ define([
"./src/directives/MCTSplitPane",
"./src/directives/MCTSplitter",
"./src/directives/MCTTree",
"./src/directives/MCTIndicators",
"./src/directives/MCTPreview",
"./src/actions/MCTPreviewAction",
"./src/filters/ReverseFilter",
"text!./res/templates/bottombar.html",
"text!./res/templates/controls/action-button.html",
"text!./res/templates/controls/input-filter.html",
"text!./res/templates/angular-indicator.html",
"text!./res/templates/indicator.html",
"text!./res/templates/message-banner.html",
"text!./res/templates/progress-bar.html",
"text!./res/templates/controls/time-controller.html",
@@ -71,7 +69,6 @@ define([
"text!./res/templates/controls/selector.html",
"text!./res/templates/controls/datetime-picker.html",
"text!./res/templates/controls/datetime-field.html",
"text!./res/templates/preview.html",
'legacyRegistry'
], function (
UrlService,
@@ -87,6 +84,7 @@ define([
ContextMenuController,
ClickAwayController,
ViewSwitcherController,
BottomBarController,
GetterSetterController,
SelectorController,
ObjectInspectorController,
@@ -101,9 +99,6 @@ define([
MCTSplitPane,
MCTSplitter,
MCTTree,
MCTIndicators,
MCTPreview,
MCTPreviewAction,
ReverseFilter,
bottombarTemplate,
actionButtonTemplate,
@@ -124,7 +119,6 @@ define([
selectorTemplate,
datetimePickerTemplate,
datetimeFieldTemplate,
previewTemplate,
legacyRegistry
) {
@@ -281,6 +275,13 @@ define([
"$timeout"
]
},
{
"key": "BottomBarController",
"implementation": BottomBarController,
"depends": [
"indicators[]"
]
},
{
"key": "GetterSetterController",
"implementation": GetterSetterController,
@@ -394,37 +395,7 @@ define([
{
"key": "mctTree",
"implementation": MCTTree,
"depends": ['gestureService', 'openmct']
},
{
"key": "mctIndicators",
"implementation": MCTIndicators,
"depends": ['openmct']
},
{
"key": "mctPreview",
"implementation": MCTPreview,
"depends": [
"$document"
]
}
],
"actions": [
{
"key": "mct-preview-action",
"implementation": MCTPreviewAction,
"name": "Preview",
"cssClass": "hide-in-t-main-view icon-eye-open",
"description": "Preview in large dialog",
"category": [
"contextual",
"view-control"
],
"depends": [
"$compile",
"$rootScope"
],
"priority": "preferred"
"depends": ['gestureService']
}
],
"constants": [
@@ -540,10 +511,6 @@ define([
{
"key": "object-inspector",
"template": objectInspectorTemplate
},
{
"key": "mct-preview",
"template": previewTemplate
}
],
"controls": [

View File

@@ -2,7 +2,7 @@
"metadata": {
"name": "openmct-symbols-16px",
"lastOpened": 0,
"created": 1529545133464
"created": 1506973656040
},
"iconSets": [
{
@@ -40,7 +40,7 @@
"tempChar": ""
},
{
"order": 141,
"order": 44,
"prevSize": 24,
"name": "icon-arrow-right",
"id": 39,
@@ -48,7 +48,7 @@
"tempChar": ""
},
{
"order": 142,
"order": 41,
"prevSize": 24,
"name": "icon-arrow-double-up",
"id": 36,
@@ -213,7 +213,7 @@
"tempChar": ""
},
{
"order": 144,
"order": 29,
"prevSize": 24,
"name": "icon-person",
"id": 24,
@@ -221,7 +221,7 @@
"tempChar": ""
},
{
"order": 147,
"order": 86,
"prevSize": 24,
"name": "icon-plus",
"id": 81,
@@ -268,21 +268,13 @@
"code": 59697,
"tempChar": ""
},
{
"order": 148,
"id": 118,
"name": "icon-arrow-right-equilateral",
"prevSize": 24,
"code": 59698,
"tempChar": ""
},
{
"order": 48,
"prevSize": 24,
"name": "icon-arrows-out",
"id": 43,
"code": 921600,
"tempChar": ""
"tempChar": ""
},
{
"order": 49,
@@ -290,7 +282,7 @@
"name": "icon-arrows-right-left",
"id": 44,
"code": 921601,
"tempChar": ""
"tempChar": ""
},
{
"order": 50,
@@ -298,7 +290,7 @@
"name": "icon-arrows-up-down",
"id": 45,
"code": 921602,
"tempChar": ""
"tempChar": ""
},
{
"order": 9,
@@ -306,7 +298,7 @@
"name": "icon-bullet",
"id": 4,
"code": 921604,
"tempChar": ""
"tempChar": ""
},
{
"order": 25,
@@ -314,7 +306,7 @@
"name": "icon-calendar",
"id": 20,
"code": 921605,
"tempChar": ""
"tempChar": ""
},
{
"order": 30,
@@ -322,7 +314,7 @@
"name": "icon-chain-links",
"id": 25,
"code": 921606,
"tempChar": ""
"tempChar": ""
},
{
"order": 109,
@@ -330,7 +322,7 @@
"prevSize": 24,
"code": 921607,
"name": "icon-pane-collapse-left",
"tempChar": ""
"tempChar": ""
},
{
"order": 110,
@@ -338,7 +330,7 @@
"prevSize": 24,
"code": 921608,
"name": "icon-pane-collapse-right",
"tempChar": ""
"tempChar": ""
},
{
"order": 5,
@@ -346,7 +338,7 @@
"prevSize": 24,
"code": 921609,
"name": "icon-download",
"tempChar": ""
"tempChar": ""
},
{
"order": 60,
@@ -354,7 +346,7 @@
"name": "icon-duplicate",
"id": 55,
"code": 921616,
"tempChar": ""
"tempChar": ""
},
{
"order": 61,
@@ -362,7 +354,7 @@
"name": "icon-folder-new",
"id": 56,
"code": 921617,
"tempChar": ""
"tempChar": ""
},
{
"order": 64,
@@ -370,7 +362,7 @@
"name": "icon-fullscreen-expand",
"id": 59,
"code": 921618,
"tempChar": ""
"tempChar": ""
},
{
"order": 63,
@@ -378,7 +370,7 @@
"name": "icon-fullscreen-collapse",
"id": 58,
"code": 921619,
"tempChar": ""
"tempChar": ""
},
{
"order": 67,
@@ -386,23 +378,23 @@
"name": "icon-layers",
"id": 62,
"code": 921620,
"tempChar": ""
"tempChar": ""
},
{
"order": 145,
"order": 69,
"prevSize": 24,
"name": "icon-line-horz",
"id": 64,
"code": 921621,
"tempChar": ""
"tempChar": ""
},
{
"order": 146,
"order": 73,
"prevSize": 24,
"name": "icon-magnify",
"id": 68,
"code": 921622,
"tempChar": ""
"tempChar": ""
},
{
"order": 71,
@@ -410,7 +402,7 @@
"name": "icon-magnify-in",
"id": 66,
"code": 921623,
"tempChar": ""
"tempChar": ""
},
{
"order": 72,
@@ -418,7 +410,7 @@
"name": "icon-magnify-out",
"id": 67,
"code": 921624,
"tempChar": ""
"tempChar": ""
},
{
"order": 74,
@@ -426,7 +418,7 @@
"name": "icon-menu",
"id": 69,
"code": 921625,
"tempChar": ""
"tempChar": ""
},
{
"order": 75,
@@ -434,7 +426,7 @@
"name": "icon-move",
"id": 70,
"code": 921632,
"tempChar": ""
"tempChar": ""
},
{
"order": 76,
@@ -442,7 +434,7 @@
"name": "icon-new-window",
"id": 71,
"code": 921633,
"tempChar": ""
"tempChar": ""
},
{
"order": 26,
@@ -450,7 +442,7 @@
"name": "icon-paint-bucket",
"id": 21,
"code": 921634,
"tempChar": ""
"tempChar": ""
},
{
"order": 81,
@@ -458,7 +450,7 @@
"name": "icon-pause",
"id": 76,
"code": 921635,
"tempChar": ""
"tempChar": ""
},
{
"order": 82,
@@ -466,7 +458,7 @@
"name": "icon-pencil",
"id": 77,
"code": 921636,
"tempChar": ""
"tempChar": ""
},
{
"order": 84,
@@ -474,7 +466,7 @@
"name": "icon-play",
"id": 79,
"code": 921637,
"tempChar": ""
"tempChar": ""
},
{
"order": 85,
@@ -482,7 +474,7 @@
"name": "icon-plot-resource",
"id": 80,
"code": 921638,
"tempChar": ""
"tempChar": ""
},
{
"order": 27,
@@ -490,7 +482,7 @@
"name": "icon-pointer-left",
"id": 22,
"code": 921639,
"tempChar": ""
"tempChar": ""
},
{
"order": 28,
@@ -498,7 +490,7 @@
"name": "icon-pointer-right",
"id": 23,
"code": 921640,
"tempChar": ""
"tempChar": ""
},
{
"order": 32,
@@ -506,7 +498,7 @@
"name": "icon-refresh",
"id": 27,
"code": 921641,
"tempChar": ""
"tempChar": ""
},
{
"order": 16,
@@ -514,7 +506,7 @@
"name": "icon-save",
"id": 11,
"code": 921648,
"tempChar": ""
"tempChar": ""
},
{
"order": 88,
@@ -522,7 +514,7 @@
"name": "icon-sine",
"id": 83,
"code": 921649,
"tempChar": ""
"tempChar": ""
},
{
"order": 102,
@@ -530,7 +522,7 @@
"name": "icon-T",
"id": 84,
"code": 921650,
"tempChar": ""
"tempChar": ""
},
{
"order": 92,
@@ -538,7 +530,7 @@
"name": "icon-thumbs-strip",
"id": 87,
"code": 921651,
"tempChar": ""
"tempChar": ""
},
{
"order": 96,
@@ -546,7 +538,7 @@
"name": "icon-two-parts-both",
"id": 91,
"code": 921652,
"tempChar": ""
"tempChar": ""
},
{
"order": 97,
@@ -554,7 +546,7 @@
"name": "icon-two-parts-one-only",
"id": 92,
"code": 921653,
"tempChar": ""
"tempChar": ""
},
{
"order": 21,
@@ -562,7 +554,7 @@
"name": "icon-resync",
"id": 16,
"code": 921654,
"tempChar": ""
"tempChar": ""
},
{
"order": 120,
@@ -570,7 +562,7 @@
"name": "icon-reset",
"prevSize": 24,
"code": 921655,
"tempChar": ""
"tempChar": ""
},
{
"order": 121,
@@ -578,7 +570,7 @@
"name": "icon-x-in-circle",
"prevSize": 24,
"code": 921656,
"tempChar": ""
"tempChar": ""
},
{
"order": 118,
@@ -586,7 +578,7 @@
"name": "icon-brightness",
"prevSize": 24,
"code": 921657,
"tempChar": ""
"tempChar": ""
},
{
"order": 119,
@@ -594,7 +586,7 @@
"name": "icon-contrast",
"prevSize": 24,
"code": 921664,
"tempChar": ""
"tempChar": ""
},
{
"order": 124,
@@ -602,7 +594,7 @@
"name": "icon-expand",
"prevSize": 24,
"code": 921665,
"tempChar": ""
"tempChar": ""
},
{
"order": 125,
@@ -610,7 +602,7 @@
"name": "icon-list-view",
"prevSize": 24,
"code": 921666,
"tempChar": ""
"tempChar": ""
},
{
"order": 133,
@@ -618,7 +610,7 @@
"name": "icon-grid-snap-to",
"prevSize": 24,
"code": 921667,
"tempChar": ""
"tempChar": ""
},
{
"order": 128,
@@ -626,7 +618,7 @@
"name": "icon-grid-snap-no",
"prevSize": 24,
"code": 921668,
"tempChar": ""
"tempChar": ""
},
{
"order": 131,
@@ -634,7 +626,7 @@
"name": "icon-frame-show",
"prevSize": 24,
"code": 921669,
"tempChar": ""
"tempChar": ""
},
{
"order": 130,
@@ -642,7 +634,7 @@
"name": "icon-frame-hide",
"prevSize": 24,
"code": 921670,
"tempChar": ""
"tempChar": ""
},
{
"order": 138,
@@ -650,7 +642,7 @@
"name": "icon-import",
"prevSize": 24,
"code": 921671,
"tempChar": ""
"tempChar": ""
},
{
"order": 136,
@@ -658,7 +650,7 @@
"name": "icon-export",
"prevSize": 24,
"code": 921672,
"tempChar": ""
"tempChar": ""
},
{
"order": 37,
@@ -666,7 +658,7 @@
"name": "icon-activity",
"id": 32,
"code": 921856,
"tempChar": ""
"tempChar": ""
},
{
"order": 36,
@@ -674,7 +666,7 @@
"name": "icon-activity-mode",
"id": 31,
"code": 921857,
"tempChar": ""
"tempChar": ""
},
{
"order": 52,
@@ -682,7 +674,7 @@
"name": "icon-autoflow-tabular",
"id": 47,
"code": 921858,
"tempChar": ""
"tempChar": ""
},
{
"order": 55,
@@ -690,7 +682,7 @@
"name": "icon-clock",
"id": 50,
"code": 921859,
"tempChar": ""
"tempChar": ""
},
{
"order": 58,
@@ -698,7 +690,7 @@
"name": "icon-database",
"id": 53,
"code": 921860,
"tempChar": ""
"tempChar": ""
},
{
"order": 57,
@@ -706,7 +698,7 @@
"name": "icon-database-query",
"id": 52,
"code": 921861,
"tempChar": ""
"tempChar": ""
},
{
"order": 17,
@@ -714,7 +706,7 @@
"name": "icon-dataset",
"id": 12,
"code": 921862,
"tempChar": ""
"tempChar": ""
},
{
"order": 22,
@@ -722,7 +714,7 @@
"name": "icon-datatable",
"id": 17,
"code": 921863,
"tempChar": ""
"tempChar": ""
},
{
"order": 59,
@@ -730,7 +722,7 @@
"name": "icon-dictionary",
"id": 54,
"code": 921864,
"tempChar": ""
"tempChar": ""
},
{
"order": 62,
@@ -738,7 +730,7 @@
"name": "icon-folder",
"id": 57,
"code": 921865,
"tempChar": ""
"tempChar": ""
},
{
"order": 66,
@@ -746,7 +738,7 @@
"name": "icon-image",
"id": 61,
"code": 921872,
"tempChar": ""
"tempChar": ""
},
{
"order": 68,
@@ -754,7 +746,7 @@
"name": "icon-layout",
"id": 63,
"code": 921873,
"tempChar": ""
"tempChar": ""
},
{
"order": 77,
@@ -762,7 +754,7 @@
"name": "icon-object",
"id": 72,
"code": 921874,
"tempChar": ""
"tempChar": ""
},
{
"order": 78,
@@ -770,7 +762,7 @@
"name": "icon-object-unknown",
"id": 73,
"code": 921875,
"tempChar": ""
"tempChar": ""
},
{
"order": 79,
@@ -778,7 +770,7 @@
"name": "icon-packet",
"id": 74,
"code": 921876,
"tempChar": ""
"tempChar": ""
},
{
"order": 80,
@@ -786,7 +778,7 @@
"name": "icon-page",
"id": 75,
"code": 921877,
"tempChar": ""
"tempChar": ""
},
{
"order": 135,
@@ -794,7 +786,7 @@
"name": "icon-plot-overlay",
"prevSize": 24,
"code": 921878,
"tempChar": ""
"tempChar": ""
},
{
"order": 113,
@@ -802,7 +794,7 @@
"name": "icon-plot-stacked",
"prevSize": 24,
"code": 921879,
"tempChar": ""
"tempChar": ""
},
{
"order": 10,
@@ -810,7 +802,7 @@
"name": "icon-session",
"id": 5,
"code": 921880,
"tempChar": ""
"tempChar": ""
},
{
"order": 24,
@@ -818,7 +810,7 @@
"name": "icon-tabular",
"id": 19,
"code": 921881,
"tempChar": ""
"tempChar": ""
},
{
"order": 7,
@@ -826,7 +818,7 @@
"name": "icon-tabular-lad",
"id": 2,
"code": 921888,
"tempChar": ""
"tempChar": ""
},
{
"order": 6,
@@ -834,7 +826,7 @@
"name": "icon-tabular-lad-set",
"id": 1,
"code": 921889,
"tempChar": ""
"tempChar": ""
},
{
"order": 8,
@@ -842,7 +834,7 @@
"name": "icon-tabular-realtime",
"id": 3,
"code": 921890,
"tempChar": ""
"tempChar": ""
},
{
"order": 23,
@@ -850,7 +842,7 @@
"name": "icon-tabular-scrolling",
"id": 18,
"code": 921891,
"tempChar": ""
"tempChar": ""
},
{
"order": 112,
@@ -858,7 +850,7 @@
"name": "icon-telemetry",
"id": 86,
"code": 921892,
"tempChar": ""
"tempChar": ""
},
{
"order": 90,
@@ -866,7 +858,7 @@
"name": "icon-telemetry-panel",
"id": 85,
"code": 921893,
"tempChar": ""
"tempChar": ""
},
{
"order": 93,
@@ -874,7 +866,7 @@
"name": "icon-timeline",
"id": 88,
"code": 921894,
"tempChar": ""
"tempChar": ""
},
{
"order": 116,
@@ -882,7 +874,7 @@
"name": "icon-timer-v1.5",
"prevSize": 24,
"code": 921895,
"tempChar": ""
"tempChar": ""
},
{
"order": 11,
@@ -890,7 +882,7 @@
"name": "icon-topic",
"id": 6,
"code": 921896,
"tempChar": ""
"tempChar": ""
},
{
"order": 115,
@@ -898,7 +890,7 @@
"name": "icon-box-with-dashed-lines",
"id": 29,
"code": 921897,
"tempChar": ""
"tempChar": ""
},
{
"order": 126,
@@ -906,7 +898,7 @@
"name": "icon-summary-widget",
"prevSize": 24,
"code": 921904,
"tempChar": ""
"tempChar": ""
},
{
"order": 139,
@@ -914,7 +906,7 @@
"name": "icon-notebook",
"prevSize": 24,
"code": 921905,
"tempChar": ""
"tempChar": ""
}
],
"metadata": {
@@ -1647,26 +1639,6 @@
]
}
},
{
"id": 118,
"paths": [
"M962 512l-896 512v-1024z"
],
"attrs": [
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"grid": 16,
"tags": [
"icon-arrow-right-equilateral"
],
"colorPermutations": {
"1161751207457516161751": [
{}
]
}
},
{
"paths": [
"M0 512l256 256v-512z",
@@ -1966,7 +1938,7 @@
},
{
"paths": [
"M1024 896l-256.8-256.8c42.4-66.6 65-144 64.8-223.2 0-229.8-186.2-416-416-416s-416 186.2-416 416 186.2 416 416 416c79 0.2 156.4-22.4 223.2-64.8l256.8 256.8 128-128zM212.4 619.6c-112.4-112.4-112.4-294.8 0-407.2s294.8-112.4 407.2 0 112.4 294.8 0 407.2c-54 54-127.2 84.4-203.6 84.4-76.4 0.2-149.8-30.2-203.6-84.4z"
"M1024 896l-201.662-201.662c47.922-72.498 73.662-157.434 73.662-246.338 0-119.666-46.6-232.168-131.216-316.784s-197.118-131.216-316.784-131.216-232.168 46.6-316.784 131.216-131.216 197.118-131.216 316.784 46.6 232.168 131.216 316.784 197.118 131.216 316.784 131.216c88.904 0 173.84-25.74 246.338-73.662l201.662 201.662 128-128zM448 704c-141.16 0-256-114.842-256-256 0-141.16 114.84-256 256-256 141.158 0 256 114.84 256 256 0 141.158-114.842 256-256 256z"
],
"grid": 16,
"tags": [
@@ -1974,26 +1946,15 @@
],
"defaultCode": 77,
"id": 68,
"attrs": [
{
"fill": "rgb(0, 161, 75)"
}
],
"isMulticolor": false,
"isMulticolor2": false,
"attrs": [],
"colorPermutations": {
"1161751207457516161751": [
{
"f": 1
}
]
"1161751207457516161751": []
}
},
{
"paths": [
"M1024 896l-256.86-256.86c40.681-62.963 64.861-139.898 64.861-222.481 0-0.232-0-0.464-0.001-0.696l0 0.036c0-229.76-186.24-416-416-416s-416 186.24-416 416 186.24 416 416 416c0.196 0 0.427 0.001 0.659 0.001 82.583 0 159.518-24.18 224.112-65.846l-1.631 0.985 256.86 256.86zM212.36 619.64c-52.114-52.117-84.346-124.114-84.346-203.64 0-159.058 128.942-288 288-288s288 128.942 288 288c0 159.058-128.942 288-288 288-0.005 0-0.010-0-0.014-0l0.001 0c-0.242 0.001-0.529 0.001-0.815 0.001-79.271 0-151.010-32.251-202.811-84.348l-0.013-0.014z",
"M224 352h384v128h-384v-128z",
"M352 224h128v384h-128v-384z"
"M640 384h-128v-128h-128v128h-128v128h128v128h128v-128h128z",
"M1024 896l-201.662-201.662c47.922-72.498 73.662-157.434 73.662-246.338 0-119.666-46.6-232.168-131.216-316.784s-197.118-131.216-316.784-131.216c-119.666 0-232.168 46.6-316.784 131.216s-131.216 197.118-131.216 316.784c0 119.666 46.6 232.168 131.216 316.784s197.118 131.216 316.784 131.216c88.904 0 173.84-25.74 246.338-73.662l201.662 201.662 128-128zM448 704c-141.16 0-256-114.842-256-256 0-141.16 114.84-256 256-256 141.158 0 256 114.84 256 256 0 141.158-114.842 256-256 256z"
],
"grid": 16,
"tags": [
@@ -2001,37 +1962,15 @@
],
"defaultCode": 88,
"id": 66,
"attrs": [
{
"fill": "rgb(0, 161, 75)"
},
{
"fill": "rgb(0, 161, 75)"
},
{
"fill": "rgb(0, 161, 75)"
}
],
"isMulticolor": false,
"isMulticolor2": false,
"attrs": [],
"colorPermutations": {
"1161751207457516161751": [
{
"f": 1
},
{
"f": 1
},
{
"f": 1
}
]
"1161751207457516161751": []
}
},
{
"paths": [
"M767.2 639.2c42.4-66.6 65-144 64.8-223.2 0-229.8-186.2-416-416-416s-416 186.2-416 416 186.2 416 416 416c79 0.2 156.4-22.4 223.2-64.8l256.8 256.8 128-128-256.8-256.8zM619.6 619.6c-54 54-127.2 84.4-203.6 84.4-76.4 0.2-149.8-30.2-203.6-84.4-112.4-112.4-112.4-294.8 0-407.2s294.8-112.4 407.2 0c112.4 112.4 112.4 294.8 0 407.2z",
"M224 352h384v128h-384v-128z"
"M256 384h384v128h-384v-128z",
"M1024 896l-201.662-201.662c47.922-72.498 73.662-157.434 73.662-246.338 0-119.666-46.6-232.168-131.216-316.784s-197.118-131.216-316.784-131.216c-119.666 0-232.168 46.6-316.784 131.216s-131.216 197.118-131.216 316.784c0 119.666 46.6 232.168 131.216 316.784s197.118 131.216 316.784 131.216c88.904 0 173.84-25.74 246.338-73.662l201.662 201.662 128-128zM448 704c-141.16 0-256-114.842-256-256 0-141.16 114.84-256 256-256 141.158 0 256 114.84 256 256 0 141.158-114.842 256-256 256z"
],
"grid": 16,
"tags": [
@@ -2039,32 +1978,16 @@
],
"defaultCode": 89,
"id": 67,
"attrs": [
{
"fill": "rgb(0, 161, 75)"
},
{
"fill": "rgb(0, 161, 75)"
}
],
"isMulticolor": false,
"isMulticolor2": false,
"attrs": [],
"colorPermutations": {
"1161751207457516161751": [
{
"f": 1
},
{
"f": 1
}
]
"1161751207457516161751": []
}
},
{
"paths": [
"M0 128h1024v128h-1024v-128z",
"M0 448h1024v128h-1024v-128z",
"M0 768h1024v128h-1024v-128z"
"M0 0h1024v256h-1024v-256z",
"M0 384h1024v256h-1024v-256z",
"M0 768h1024v256h-1024v-256z"
],
"grid": 16,
"tags": [
@@ -2072,19 +1995,9 @@
],
"defaultCode": 109,
"id": 69,
"attrs": [
{},
{},
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"attrs": [],
"colorPermutations": {
"1161751207457516161751": [
{},
{},
{}
]
"1161751207457516161751": []
}
},
{

View File

@@ -39,7 +39,6 @@
<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="&#xe932;" glyph-name="icon-arrow-right-equilateral" d="M962 448l-896-512v1024z" />
<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" />
@@ -55,10 +54,10 @@
<glyph unicode="&#xe1013;" glyph-name="icon-fullscreen-collapse" d="M191.656 128c0.118-0.1 0.244-0.224 0.344-0.344v-191.656h192v192c0 105.6-86.4 192-192 192h-192v-192h191.656zM192 768.344c-0.1-0.118-0.224-0.244-0.344-0.344h-191.656v-192h192c105.6 0 192 86.4 192 192v192h-192v-191.656zM832 576h192v192h-191.656c-0.118 0.1-0.244 0.226-0.344 0.344v191.656h-192v-192c0-105.6 86.4-192 192-192zM832 127.656c0.1 0.118 0.224 0.244 0.344 0.344h191.656v192h-192c-105.6 0-192-86.4-192-192v-192h192v191.656z" />
<glyph unicode="&#xe1014;" glyph-name="icon-layers" d="M1024 576l-512 384-512-384 512-384zM512 64l-426.666 320-85.334-64 512-384 512 384-85.334 64z" />
<glyph unicode="&#xe1015;" glyph-name="icon-line-horz" d="M64 384c-35.346 0-64 28.654-64 64s28.654 64 64 64h896c35.346 0 64-28.654 64-64s-28.654-64-64-64h-896z" />
<glyph unicode="&#xe1016;" glyph-name="icon-magnify" d="M1024 64l-256.8 256.8c42.4 66.6 65 144 64.8 223.2 0 229.8-186.2 416-416 416s-416-186.2-416-416 186.2-416 416-416c79-0.2 156.4 22.4 223.2 64.8l256.8-256.8 128 128zM212.4 340.4c-112.4 112.4-112.4 294.8 0 407.2s294.8 112.4 407.2 0 112.4-294.8 0-407.2c-54-54-127.2-84.4-203.6-84.4-76.4-0.2-149.8 30.2-203.6 84.4z" />
<glyph unicode="&#xe1017;" glyph-name="icon-magnify-in" d="M1024 64l-256.86 256.86c40.681 62.963 64.861 139.898 64.861 222.481 0 0.232 0 0.464-0.001 0.696v-0.036c0 229.76-186.24 416-416 416s-416-186.24-416-416 186.24-416 416-416c0.196 0 0.427-0.001 0.659-0.001 82.583 0 159.518 24.18 224.112 65.846l-1.631-0.985 256.86-256.86zM212.36 340.36c-52.114 52.117-84.346 124.114-84.346 203.64 0 159.058 128.942 288 288 288s288-128.942 288-288c0-159.058-128.942-288-288-288-0.005 0-0.010 0-0.014 0h0.001c-0.242-0.001-0.529-0.001-0.815-0.001-79.271 0-151.010 32.251-202.811 84.348l-0.013 0.014zM224 608h384v-128h-384v128zM352 736h128v-384h-128v384z" />
<glyph unicode="&#xe1018;" glyph-name="icon-magnify-out" d="M767.2 320.8c42.4 66.6 65 144 64.8 223.2 0 229.8-186.2 416-416 416s-416-186.2-416-416 186.2-416 416-416c79-0.2 156.4 22.4 223.2 64.8l256.8-256.8 128 128-256.8 256.8zM619.6 340.4c-54-54-127.2-84.4-203.6-84.4-76.4-0.2-149.8 30.2-203.6 84.4-112.4 112.4-112.4 294.8 0 407.2s294.8 112.4 407.2 0c112.4-112.4 112.4-294.8 0-407.2zM224 608h384v-128h-384v128z" />
<glyph unicode="&#xe1019;" glyph-name="icon-menu" d="M0 832h1024v-128h-1024v128zM0 512h1024v-128h-1024v128zM0 192h1024v-128h-1024v128z" />
<glyph unicode="&#xe1016;" glyph-name="icon-magnify" d="M1024 64l-201.662 201.662c47.922 72.498 73.662 157.434 73.662 246.338 0 119.666-46.6 232.168-131.216 316.784s-197.118 131.216-316.784 131.216-232.168-46.6-316.784-131.216-131.216-197.118-131.216-316.784 46.6-232.168 131.216-316.784 197.118-131.216 316.784-131.216c88.904 0 173.84 25.74 246.338 73.662l201.662-201.662 128 128zM448 256c-141.16 0-256 114.842-256 256 0 141.16 114.84 256 256 256 141.158 0 256-114.84 256-256 0-141.158-114.842-256-256-256z" />
<glyph unicode="&#xe1017;" glyph-name="icon-magnify-in" d="M640 576h-128v128h-128v-128h-128v-128h128v-128h128v128h128zM1024 64l-201.662 201.662c47.922 72.498 73.662 157.434 73.662 246.338 0 119.666-46.6 232.168-131.216 316.784s-197.118 131.216-316.784 131.216c-119.666 0-232.168-46.6-316.784-131.216s-131.216-197.118-131.216-316.784c0-119.666 46.6-232.168 131.216-316.784s197.118-131.216 316.784-131.216c88.904 0 173.84 25.74 246.338 73.662l201.662-201.662 128 128zM448 256c-141.16 0-256 114.842-256 256 0 141.16 114.84 256 256 256 141.158 0 256-114.84 256-256 0-141.158-114.842-256-256-256z" />
<glyph unicode="&#xe1018;" glyph-name="icon-magnify-out" d="M256 576h384v-128h-384v128zM1024 64l-201.662 201.662c47.922 72.498 73.662 157.434 73.662 246.338 0 119.666-46.6 232.168-131.216 316.784s-197.118 131.216-316.784 131.216c-119.666 0-232.168-46.6-316.784-131.216s-131.216-197.118-131.216-316.784c0-119.666 46.6-232.168 131.216-316.784s197.118-131.216 316.784-131.216c88.904 0 173.84 25.74 246.338 73.662l201.662-201.662 128 128zM448 256c-141.16 0-256 114.842-256 256 0 141.16 114.84 256 256 256 141.158 0 256-114.84 256-256 0-141.158-114.842-256-256-256z" />
<glyph unicode="&#xe1019;" glyph-name="icon-menu" d="M0 960h1024v-256h-1024v256zM0 576h1024v-256h-1024v256zM0 192h1024v-256h-1024v256z" />
<glyph unicode="&#xe1020;" glyph-name="icon-move" d="M293.4 448l218.6 218.6 256-256v421.4c0 70.4-57.6 128-128 128h-512c-70.4 0-128-57.6-128-128v-512c0-70.4 57.6-128 128-128h421.4l-256 256zM1024 512h-128v-320l-384 384-128-128 384-384h-320v-128h576z" />
<glyph unicode="&#xe1021;" glyph-name="icon-new-window" d="M448 960v-128h320l-384-384 128-128 384 384v-320h128v576zM576 285.726v-157.382c-0.1-0.118-0.226-0.244-0.344-0.344h-383.312c-0.118 0.1-0.244 0.226-0.344 0.344v383.312c0.1 0.118 0.226 0.244 0.344 0.344h157.382l192 192h-349.726c-105.6 0-192-86.4-192-192v-384c0-105.6 86.4-192 192-192h384c105.6 0 192 86.4 192 192v349.726l-192-192z" />
<glyph unicode="&#xe1022;" glyph-name="icon-paint-bucket" d="M544 736v-224c0-88.4-71.6-160-160-160s-160 71.6-160 160v97.2l-197.4-196.4c-50-50-12.4-215.2 112.4-340s290-162.4 340-112.4l417 423.6-352 352zM896-64c70.6 0 128 57.4 128 128 0 108.6-128 192-128 192s-128-83.4-128-192c0-70.6 57.4-128 128-128zM384 448c-35.4 0-64 28.6-64 64v384c0 35.4 28.6 64 64 64s64-28.6 64-64v-384c0-35.4-28.6-64-64-64z" />

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

View File

@@ -157,57 +157,3 @@
.t-popup {
z-index: 75;
}
/********************************************* GRID STYLES */
.grid-two-column {
display: grid;
grid-row-gap: 0;
grid-template-columns: 1fr 2fr;
align-items: top;
}
.grid-two-column-span-cols {
grid-column: 1 / 3;
}
.grid-elem {
&:not(:first-child) {
border-top: 1px solid $colorInteriorBorder;
}
&.label {
background-color: rgba(0,0,128,0.2);
}
&.value {
background-color: rgba(0,128,0,0.2);
}
}
// Properties grids
.grid-properties {
@extend .grid-two-column;
}
.grid-row {
display: contents;
}
.grid-span-all {
@extend .grid-two-column-span-cols;
}
.grid-row {
.grid-cell {
padding: 3px $interiorMarginLg 3px 0;
&[title] {
// When a cell has a title, assume it's helpful text
cursor: help;
}
}
&.force-border,
&:not(:first-of-type) {
// Row borders, effected via border-top on child elements of the row
.grid-cell {
border-top: 1px solid $colorInspectorSectionHeaderBg;
}
}
}

View File

@@ -37,9 +37,25 @@
vertical-align: middle;
}
//.top-bar .btn-browse .badge {
// Moved to _controls.scss .btn.browse-btn
// border-radius: $controlCr * 1.5;
// $d: 20px;
// display: block;
// font-size: 1em;
// line-height: $d;
//// margin-top: -4px;
//
// position: absolute;
// top: 5px; left: 5px; bottom: 5px; right: auto;
// width: $d; height: auto;
//}
.super-menu .badge {
@include background-image(linear-gradient(lighten($colorCreateBtn, 10%), $colorCreateBtn));
border-radius: $controlCr;
@include boxShdwSubtle();
// display: inline-block;
// margin-right: 10px !important;
padding: 2px 7px;
}

View File

@@ -43,10 +43,10 @@ $ueColMargin: 1.5%;
$ueAppLogoW: 80px;
$ueEditToolBarH: 25px;
$ueCollapsedPaneEdgeM: 22px;
$uePaneMiniTabH: 36px;
$uePaneMiniTabW: 10px;
$uePaneMiniTabFontSize: 9px;
$uePaneMiniTabCollapsedW: 22px;
$uePaneMiniTabH: 22px;
$uePaneMiniTabW: 8px;
$uePaneMiniTabFontSize: 8px;
$uePaneMiniTabCollapsedW: 18px;
$ueEditLeftPaneW: 75%;
$treeSearchInputBarH: 25px;
/*************** Panes */
@@ -70,7 +70,7 @@ $ueBrowseGridItemTopBarH: 20px;
$ueBrowseGridItemBottomBarH: 30px;
$itemPadLR: 5px;
/*************** Tree */
$treeVCW: 16px;
$treeVCW: 10px;
$treeTypeIconH: 1.4em; // was 16px
$treeTypeIconHPx: 16px;
$treeTypeIconW: 18px;
@@ -111,7 +111,7 @@ $bubbleMaxW: 300px;
$reqSymbolW: 15px;
$reqSymbolM: $interiorMargin * 2;
$reqSymbolFontSize: 0.75em;
$inputTextPTopBtm: 2px;
$inputTextPTopBtm: 3px;
$inputTextPLeftRight: 5px;
$inputTextP: $inputTextPTopBtm $inputTextPLeftRight;
/*************** Wait Spinner Defaults */
@@ -132,7 +132,7 @@ $menuLineHPx: 24px;
$btnStdH: 25px;
$btnToolbarH: $btnStdH;
$controlBarH: $btnStdH;
$btnFrameH: 18px;
$btnFrameH: 16px;
/************************** PATHS */
// Paths need to be relative to /platform/commonUI/theme/<theme-name>/css/ directory

View File

@@ -141,6 +141,7 @@ a.disabled {
.s-status-missing {
// Labels. Expects .s-status-missing to be applied to mct-representation that contains
// .t-object-label
.t-object-label .t-item-icon:before {
content: $glyph-icon-object-unknown;
}
@@ -199,16 +200,7 @@ a.disabled {
}
.vscroll {
overflow-x: hidden;
overflow-y: auto;
&.scroll-pad {
padding-right: $interiorMargin;
}
}
.vscroll--persist {
overflow-x: hidden;
overflow-y: scroll;
}
.slidable {
@@ -232,13 +224,8 @@ a.disabled {
box-shadow: rgba(#000, 0.7) 0 4px 10px 2px;
}
.capitalize {
text-transform: capitalize;
}
.hide,
.hidden,
.t-main-view .hide-in-t-main-view {
.hidden {
display: none !important;
}
@@ -247,16 +234,14 @@ a.disabled {
pointer-events: none;
}
.invisible {
display: block;
.off {
visibility: hidden;
opacity: 0;
height: 0;
margin: 0;
padding: 0;
border: 0;
margin: 0 !important;
transform: scale(0);
pointer-events: none;
position: absolute;
}
.sep {

View File

@@ -33,14 +33,6 @@
}
}
[class*="icon-"].labeled {
// Moved from .s-button and generalized
&:before {
// Fend off label from icon when it's included
margin-right: $interiorMarginSm;
}
}
/************************** CHAR UNICODES */
$glyph-icon-alert-rect: '\e900';
@@ -75,7 +67,6 @@ $glyph-icon-x: '\e928';
$glyph-icon-brackets: '\e929';
$glyph-icon-crosshair: '\e930';
$glyph-icon-grippy: '\e931';
$glyph-icon-arrow-right-equilateral: '\e932';
$glyph-icon-arrows-out: '\e1000';
$glyph-icon-arrows-right-left: '\e1001';
$glyph-icon-arrows-up-down: '\e1002';
@@ -191,7 +182,6 @@ $glyph-icon-notebook: '\e1131';
.icon-brackets { @include glyphBefore($glyph-icon-brackets); }
.icon-crosshair { @include glyphBefore($glyph-icon-crosshair); }
.icon-grippy { @include glyphBefore($glyph-icon-grippy); }
.icon-arrow-right-equilateral { @include glyphBefore($glyph-icon-arrow-right-equilateral); }
.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); }

View File

@@ -19,15 +19,23 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/* Styles for the Inspector pane */
.l-inspect,
.l-inspect table tr td {
font-size: 0.75rem;
}
/* New grid layout for the Inspector pane */
.l-inspect {
// Overall layout
@extend .abs;
background: $colorInspectorBg;
color: $colorInspectorFg;
line-height: 140%;
.flex-elem.holder:not(:last-child) {
margin-bottom: $interiorMargin;
}
.pane-header {
color: pushBack($colorInspectorFg, 20%);
font-size: 0.8rem;
@@ -42,48 +50,80 @@
}
}
}
.l-inspector-part {
display: contents;
}
.tree {
.grid-properties {
box-sizing: border-box;
padding-right: $interiorMargin;
.tree .form {
margin-left: $treeVCW + $interiorMarginLg;
}
}
.grid-properties {
.label {
.section-header {
background: none;
color: $colorInspectorPropName;
border-radius: unset;
font-size: inherit;
padding: $interiorMarginSm 0;
}
.value {
color: $colorInspectorPropVal;
word-break: break-all;
&:first-child {
// If there is no preceding .label element, make value span columns
@extend .grid-two-column-span-cols;
mct-form:not(:last-child) .form {
border-bottom: 1px solid $colorInspectorSectionHeaderBg;
}
.form {
margin-bottom: $interiorMarginSm;
padding-bottom: $interiorMarginLg;
.l-section-body {
margin-bottom: 0;
&:not(.first) {
border-top: 1px solid $colorFormLines;
}
}
.form-row {
align-items: center;
border: none !important;
margin-bottom: 0 !important;
padding: $interiorMarginSm 0;
.label {
min-width: 80px;
}
input[type='text'],
input[type='search'] {
width: 100%;
}
}
}
}
.inspector-location {
display: inline-block;
ul li,
em.t-inspector-part-header {
display: block;
position: relative;
}
h2 {
// Headers for .l-inspector-part elements
@extend .grid-two-column-span-cols;
border-radius: $controlCr;
ul li {
margin-bottom: $interiorMarginLg;
}
em.t-inspector-part-header {
border-radius: $basicCr;
background-color: $colorInspectorSectionHeaderBg;
color: $colorInspectorSectionHeaderFg;
font-size: 0.8rem;
font-weight: normal;
margin: $interiorMarginLg 0 $interiorMarginSm 0;
margin-bottom: $interiorMargin;
padding: floor($formTBPad * .75) $formLRPad;
text-transform: uppercase;
&.first {
margin-top: 0;
}
.inspector-properties {
&:not(.first) {
border-top: 1px solid $colorInspectorSectionHeaderBg;
}
padding: $interiorMarginSm 0;
.label {
color: $colorInspectorPropName;
text-transform: uppercase;
}
.value {
color: $colorInspectorPropVal;
word-break: break-all;
}
}
@@ -122,34 +162,6 @@
width: 4px;
}
}
// Elements pool
.holder-elements {
.current-elements {
position: relative;
.tree-item {
.t-object-label {
// Elements pool is a flat list, so don't indent items.
font-size: 0.75rem;
left: 0;
}
}
}
}
}
/* Styles for the Inspector pane */
.l-inspect,
.l-inspect table tr td {
font-size: 0.75rem;
}
.l-inspect {
.flex-elem.holder:not(:last-child) {
margin-bottom: $interiorMargin;
}
.holder-elements {
.current-elements {
position: relative;

View File

@@ -42,7 +42,6 @@
@import "controls/lists";
@import "controls/menus";
@import "controls/messages";
@import "controls/indicators";
@import "mobile/controls/menus";
/********************************* FORMS */

View File

@@ -299,7 +299,7 @@
color: $ic;
}
@if $bgHov != none {
&:not([disabled="true"]):not(.disabled):hover {
&:not(.disabled):hover {
background: $bgHov;
color: $fgHov;
>.icon,
@@ -334,7 +334,7 @@
color: $fg;
}
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.5) 0 0px 2px) {
@mixin nice-input($bg: $colorInputBg, $fg: $colorInputFg, $shdw: rgba(black, 0.6) 0 1px 3px) {
@include s-input($bg, $fg, $shdw);
border: none;
outline: none;

View File

@@ -20,120 +20,66 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*************************************************** MIXINS */
@mixin elementStatusColors($c) {
@mixin formulateStatusColors($c) {
// Sets bg and icon colors for elements
background: rgba($c, 0.5) !important;
&:before {
color: $c !important;
}
background: rgba($c, 0.4) !important;
&:before { color: $c !important; }
}
@mixin indicatorStatusColors($c) {
&:before, .count {
color: $c;
}
}
/*************************************************** GENERAL */
.s-limit-upr,
.s-limit-lwr,
[class*='s-limit-icon'],
[class*='s-status-icon'] {
.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:'';
display: inline-block;
font-family: symbolsfont;
font-size: 0.8em;
margin-right: $interiorMarginSm;
}
}
/*************************************************** LIMITS */
[class*='s-limit'] {
&[class*='icon-'] {
&:before {
margin-right: $interiorMargin;
}
}
.s-limit-yellow, .s-limit-yellow-icon {
@include formulateStatusColors($colorWarningLo);
}
.s-limit-yellow, .s-limit-icon-yellow {
@include elementStatusColors($colorWarningLo);
.s-limit-red, .s-limit-red-icon {
@include formulateStatusColors($colorWarningHi);
}
.s-limit-red, .s-limit-icon-red {
@include elementStatusColors($colorWarningHi);
}
.s-limit {
&-upr,
&-lwr {
&:before {
margin-right: $interiorMargin;
}
}
&-upr:before { content: $glyph-icon-arrow-double-up; }
&-lwr:before { content: $glyph-icon-arrow-double-down; }
&-icon-yellow,
&-icon-red {
&:before {
content: $glyph-icon-alert-triangle;
}
}
}
.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 */
[class*='s-status'] {
&[class*='icon-'] {
&:before {
margin-right: $interiorMargin;
}
}
}
.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, .s-status-icon-warning-hi { @include elementStatusColors($colorWarningHi); }
.s-status-warning-lo, .s-status-icon-warning-lo { @include elementStatusColors($colorWarningLo); }
.s-status-diagnostic, .s-status-icon-diagnostic { @include elementStatusColors($colorDiagnostic); }
.s-status-info, .s-status-icon-info { @include elementStatusColors($colorInfo); }
.s-status-ok, .s-status-icon-ok { @include elementStatusColors($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; }
.s-status-icon-warning-hi:before { content: $glyph-icon-alert-triangle; }
.s-status-icon-warning-lo:before { content: $glyph-icon-alert-rect; }
.s-status-icon-diagnostic:before { content: $glyph-icon-eye-open; }
.s-status-icon-info:before { content: $glyph-icon-info; }
.s-status-icon-ok:before { content: $glyph-icon-check; }
/*************************************************** INDICATOR COLORING */
.ls-indicator {
&.s-status-info {
@include indicatorStatusColors($colorInfo);
}
&.s-status-disabled {
@include indicatorStatusColors($colorIndicatorDisabled);
}
&.s-status-available {
@include indicatorStatusColors($colorIndicatorAvailable);
}
&.s-status-on,
&.s-status-enabled {
@include indicatorStatusColors($colorIndicatorOn);
}
&.s-status-off {
@include indicatorStatusColors($colorIndicatorOff);
}
&.s-status-caution,
&.s-status-warning,
&.s-status-alert {
@include indicatorStatusColors($colorStatusAlert);
}
&.s-status-error {
@include indicatorStatusColors($colorStatusError);
}
}

View File

@@ -270,4 +270,37 @@
@extend .s-summary-widget;
@extend .l-summary-widget;
padding: $interiorMarginSm $interiorMargin;
}
// Hide and show elements in the rule-header on hover
.l-widget-rule,
.l-widget-test-data-item {
.grippy,
.l-rule-action-buttons-wrapper,
.l-condition-action-buttons-wrapper,
.l-widget-test-data-item-action-buttons-wrapper {
@include trans-prop-nice($props: opacity, $dur: 500ms);
opacity: 0;
}
&:hover {
.grippy,
.l-rule-action-buttons-wrapper,
.l-widget-test-data-item-action-buttons-wrapper {
@include trans-prop-nice($props: opacity, $dur: 0);
opacity: 1;
}
}
.l-rule-action-buttons-wrapper {
.t-delete {
margin-left: 10px;
}
}
.t-condition {
&:hover {
.l-condition-action-buttons-wrapper {
@include trans-prop-nice($props: opacity, $dur: 0);
opacity: 1;
}
}
}
}

View File

@@ -34,6 +34,11 @@ $pad: $interiorMargin * $baseRatio;
line-height: $btnStdH;
padding: 0 $pad;
&.labeled:before {
// Icon when it's included
margin-right: $interiorMarginSm;
}
&.lg {
font-size: 1rem;
}
@@ -54,10 +59,6 @@ $pad: $interiorMargin * $baseRatio;
.label, .title-label { display: none; }
}
&[disabled="true"] {
opacity: 0.3;
}
&.pause-play {
@extend .icon-pause;
&.paused {
@@ -113,11 +114,10 @@ body.desktop .mini-tab-icon {
.l-btn-set {
// Buttons that have a very tight conceptual grouping - no internal space between them.
font-size: 0; // Remove space between s-button elements due to white space in markup
white-space: nowrap;
.s-button {
border-radius: 0;
margin-left: 1px !important;
margin-left: 1px;
}
> .s-button {

Some files were not shown because too many files have changed in this diff Show More