Compare commits

...

50 Commits

Author SHA1 Message Date
dbed9b8712 Remove sizing row for objects when removed 2018-08-26 16:10:31 -07:00
e9e67e12be Remove magnifying glass on search box focus, add ellipses, add title to cells 2018-08-26 12:50:20 -07:00
255774cee0 Added table configuration 2018-08-26 11:10:21 -07:00
cb7151cea9 WIP 2018-08-24 11:46:25 -07:00
ed90aa04fc Adding table configuration 2018-08-23 20:13:56 -07:00
61ce16d3b0 Simplified TelemetryTableRow objects. Added resizing 2018-08-22 15:10:34 -07:00
edaebe005f Added row limit class to tables 2018-08-22 07:33:31 -07:00
575264d29d Do not default to 'sin' for limit evaluation 2018-08-22 07:32:41 -07:00
038377410a Added limit evaluation 2018-08-21 17:56:11 -07:00
73418dee77 Only evaluate sinewave generator limits for range values 2018-08-21 17:55:58 -07:00
1fbbab29ff Calculate column widths when headers set 2018-08-21 03:15:56 +02:00
4166811ec6 Removed 'this' invocation of EventEmitter.on. Was causing scope leakage of Vue change listeners 2018-08-20 18:14:22 +02:00
df332e6edf Fixed sorting on desc. sorted table 2018-08-10 14:44:20 -07:00
f07dfecf23 Added telemetry subscriptions 2018-08-09 22:15:49 -07:00
c86fe54ee5 Support removing object from composition 2018-08-08 09:20:16 -07:00
e2dcb6a7d4 Implemented filtering 2018-08-02 16:21:41 -07:00
5113ea9464 Re-enabled sorting 2018-08-01 11:27:42 -07:00
575583d9b4 Added styles and sizing row 2018-08-01 10:46:36 -07:00
7a2c1ea10e WIP 2018-07-18 06:39:11 -07:00
f2443a5c20 Initial implementation of Vue table that supports sorting and virtual scrolling 2018-07-17 12:49:15 -07:00
d5f6116226 Add overflow: auto when snapshotting table for Notebook
Fixes #2105
2018-07-12 18:28:02 -07:00
c45f857108 Local control tweaks
Fixes #2094
- Adjust timing;
- Added hover effects for .s-notebook-entry;
2018-07-12 18:28:02 -07:00
a94610ced2 View control fixes
Fixes #2094
- Add position: relative to .view-control main class;
- Add correct classes to markup;
- Fix Sum Widget field size while I was in there;
2018-07-12 18:28:02 -07:00
4c04aaf32a Fixes for main search input (#2106)
* Fix for input width

* Margin added to right of c-search-btn-wrapper element

Fixes #2094
2018-07-12 18:28:02 -07:00
60f5700dbf use correct duration for historical states 2018-07-12 18:28:02 -07:00
4685328fc7 Do not attempt to provide data for columns that object does not have telemetry for. Fixes #2027 2018-07-06 17:27:08 -07:00
bcac3164a0 Noop parsing for numbers in LocalTimeFormat 2018-07-06 17:15:16 -07:00
000037229d Collapse current time system columns 2018-07-03 16:10:20 -07:00
9e4b3d8052 Do not try to get column values for data that does not have those values 2018-07-03 13:58:54 -07:00
a4629633ef Use datum key of 'utc' for timestamp 2018-07-03 13:56:44 -07:00
433dee0314 Update test specs to use Jasmine 3 (#2089)
* Updated Karma and Jasmine versions

* Added DOMObserver class. Supports promise-based testing of DOM changes

Update asynchronous test specs to use promises or done() instead of waitsFor/runs

* Modified ActionCapability to duplicate context object properties as own properties for better object equality comparisons

* Global find + replace to fix syntax issues

* Fixed various issues caused by non-deterministic runtime order of tests in Jasmine 3. Fixed issues caused by changes to determination of object equality

* Addressed review comments

* Resolved merge conflicts with master

* Fixed style errors

* Use spy.calls.count() instead of manually tracking
2018-06-29 17:32:59 -07:00
013eba744d Basic sprintf support (#1965)
Implement optional format strings for valueMetadata which allows
developers to use c-style sprintf formatters as desired. Fixes #1562
2018-06-29 15:52:15 -07:00
29de11167f Merge pull request #2026 from nasa/plot-bug-hunt
[plot] misc bug fixes - Fixes Issues #2025, #2024, #2014
2018-06-29 13:23:31 -07:00
eaa9514453 Object has no children fix (#2038)
* Added files for PR 1904

* Added new lines

* space fix

* Implemented changes

* Space fix

* checkstyle fix

Fixes #1826
2018-06-29 11:57:45 -07:00
b8f278cabf [Tables] - Sticky headers (#2071)
* first revision

* [Frontend] Styling for sticky table headers

Fixes #1481
- WIP convert mct-table layout to use flex;
- TODO: fix flex layout when a small number of rows;
- Rename CSS classes used as selectors by JS;

* remove header height from calculations since it is outside in its own table now

* [Frontend] Styling for sticky table headers

Fixes #1481
- Fixed flex layout when a small number of rows;
- Refined input padding and dropshadow for more compactness;

* fix tests and verify tables works properly in layout and large view

* add mct-scroll to header table to allow scrolling in sync with the rest of mct-table

* Various fixes and polishing

Fixes #2071
- Fix headers height issue;
- Move inline styles to classes;
- First round fix for horz overflow due to scrollbar problem;

* WIP horz overflow

Fixes #2071
- Commented out CSS-based scrollbar with approach in
anticipation of better JS solution;

* Horz overflow/scrollbar problem fixed

Fixes #2071
- Added calcTableWidthPx to allow sizing-table to subtract
width of scrollbar;

* Remove commented code

* add clear icon back into filter text boxes

* Polishing on sticky table headers filtering

Fixes #1481
Fixes #2071
- Now hides the magnify glass in table header filters when typing;
2018-06-29 11:38:18 -07:00
63bb183bec [Plot] Misc bug fixes
* removed unused file

[Plot] Properly update yAxis on key change.

yAxis should update after the key for a series changes.

Fixes #2025.

[Plot] improve y-axis label handling

First, change the y-Axis label retrieval to retrieve the proper
value from the plot confoguration so that it uses the persisted
value, Fixes #2024

Secondly, when removing a series, if there are no series left in
the plot and a custom y-axis label has not been specified, then
clear the y-axis label.  Fixes #2014.

[Plot] don't use incorrect index in selected check

Alias the series form data so that it is not always necessary to
access it using $index.  This prevents $index getting clobbered
when looping over select options which results in the correct option
getting marked as selected.

Fixes bug reported in pull request review:
https://github.com/nasa/openmct/pull/2026#pullrequestreview-117404172
2018-06-29 11:26:22 -07:00
9d2c7a6de5 Review and integrate UI enhancements (#2078)
* [Frontend] WIP New local-controls classes

Fixes #2000
- h-local-controls
- Markup in plots changed
- Changed reset plot button's icon

* [Frontend] WIP local-controls classes

Fixes #2000
- Refactoring to use and apply local-control classes consistently;
- Plots and imagery done in main view and Display Layout contexts;

* [Frontend] WIP local-controls classes

Fixes #2000
- Use local-control classes in Timelines;
- Group Timeline buttons in l-btn-set;
- Use reset icon glyph;

* [Frontend] WIP local-controls classes

Fixes #2000
- Slight increase in size to buttons in frame context;

* [Frontend] local-controls classes

Fixes #2000
- Code cleanup;
- Update Style Guide content;
- Provisionally done, needs unit testing and double-checking;

* [Frontend] Better selecting in browse mode

Fixes #2000
- Better colors and approach to selecting in browse mode;

* [Frontend] Tweaks to pane collapse mini-tabs

Fixes #1758
Fixes #2000
- Enlarged mini-tabs and moved to screen top;
- Removed duplicative theme-based constants;

* [Frontend] Tweaks to "nav up" arrow button

Fixes #1758
Fixes #2000
- Increased hit area of .l-back "nav up" arrow in object-browse-bar;

* [Frontend] Glyph improvements

Fixes #1758
Fixes #2000
- New arrow glyph for view controls;
- Increased hit area of view controls in tree for mobile and desktop;
- Better "hamburger" menu glyph;

* [Frontend] Inspector refactor to CSS grid WIP

Fixes #1758
Fixes #2000
- WIP!!!;
- Good progress on Properties section;

* [Frontend] Inspector refactor to CSS grid WIP

Fixes #2000
- Significant mods to CSS and markup;
- New grid archetypes classes;
- Added title attribs to plot options edit and browse props;
- Added value, alarm markers to plot series browse props;
- Nearly done (?) but needs unit testing and cleanups;

* [Frontend] Minor tweaks to form and form-row

Fixes #2000
- Fixing margin problem with .form-row;
- h2 instead of div.section-header;

* [Frontend] Fixed H2 in Elements pool

Fixes #2000

* Refinements to Time Conductor

Fixes #2000
- Tweaks size of fixed position grab ticks;
- Positioning refinements to ticks and text;
- Hide major tick marks;

* Hide View Large button for nested hidden-frame Layouts

Fixes #2000
- When a layout is nested and has its frame hidden, hide the
View Large button;

* Better hiding of Time Conductor "Submit" button

Fixes #2000

* Re-added new icon-arrow-right-equilateral glyph;

Fixes #2000
Fixes #2078

* Remove commented styles/markup

Fixes #2000
Fixes #2078

* Repaired approach to hiding Time Conductor Submit button

Fixes #2000
Fixes #2078
- Renamed .off to .invisible and added refinements;

* Fixed wrong conflict resolutions; polish search

Fixes #2000
Fixes #2078
- .invisible instead of .off in search.html;
- Minor polishing to search;

fixes #1758
fixes #1763 
fixes #2011
2018-06-29 11:18:50 -07:00
07fb20c32f Json export fix (#2043)
* Refactoring export to json to use new style objects

* Added convenience function to Object API to get identifiers as strings

* Updated tests for ExportAsJSON

* Fixed bug with parent composition not being updated with new ID. Also rewrite IDs in configuration etc. Fixes #2042
2018-06-28 17:45:14 -07:00
90a6bbc13e Notebook integration deep (#1947)
* NASA - OPEN MCT NOTEBOOK UI PROTOTYPE CHALLENGE
https://www.topcoder.com/challenge-details/30059614/
Initial submission

* Code updates:
-Topcoder final fixes
-NASA review fixes

* drag and drop style fix, new entry focus, delete display fix

* NASA reported issues fixed:
objects saved in notebook, delete entry dialog, style files, and new entry from drag objects fixed.

* Annotation toolbar UI style fixes, added annotation functionality on new entry dialog

* painterro .map file issue fixed.

* NASA review fixes:

css files adjusted
notebook children tree removed
embed's title links to live object

* CouchDB documentation added

* CouchDB documentation added

Screenshots added.

* CouchDB setup documentation added

* Test case functional and cosmetic issues fixed.

* Test cases functional and cosmetic issues fixed.

* updated file saver library

* Code issues fixes:
NotificationLaunchIndicator deleted.
Inappropriate modifications to domain object models fixed.
Implemented $destroy listener on entryDnd directive.
Naming conventions fixed.
Unnecessary changes made to platform handled.
Painterro dependency handled
gulp verify fix.

* names and package fixes

* filenames fix

* [Notebook] Relocate to platform/features/notebook

* [Notebook] Remove obsolete README

* [Notebook] Restore original index.html

* [Notebook] Expose via openmct.plugins

* [Notebook] Remove demo entries

* [Notebook] Run gulp fixstyle

* [Notebook] Use dot notation instead of brackets

...for checkstyle

* [Notebook] Remove extra comma

* [Notebook] Run gulp fixstyle

* [Notebook] Use dot notation instead of brackets

...for checkstyle

* [Notebook] Fix lint issues

* [Notebook] Fix lint issues

* [Notebook] Fix lint issues

* [Notebook] Fix lint issues

* [Notebook] Fix lint issues

* [Notebook] Fix lint issues

* [Notebook] Fix lint issues

* [Notebook] Fix lint issues

* [Notebook] Fix lint issues

* [Notebook] Run gulp fixstyle

* [Notebook] Include painterro for tests

* [Notebook] Fix require config for painterro

* [Merge] WIP markup and styling

Fixes #1896
- Very much WIP, currently having issues with
hovering and jiggling

* [Merge] WIP markup and styling

Fixes #1896
- Very much WIP, attempting to convert
textarea to contenteditable;

* [Merge] JS debugging

Fixes #1896
- Very much WIP!

* [Merge] JS debugging

Fixes #1896
- Really, really WIP
- DnD doesn't work properly, and drag to
existing entry no longer works.

* [Front-end] Notebook thematic styling; test console

Fixes #1896
- Added thematic styles and config;
- Really, really, really WIP!!
- DnD doesn't work properly, and drag to
existing entry no longer works.

* [Merge] Cleanups in JS

Fixes #1896
- Removed and commented out logging statements

* [Merge] WIP SCSS and markup polishing

Fixes #1896
- Significant style and markup changes;
- Styles, layout, etc. relating to embed elements;
- Fixes in both notebook.html and embedControl.html;
- Class name normalization;

* [Merge] WIP Mods related to MCTModalNotebook.js

Fixes #1896
Fixes #1906

* fix drag and drop, delete entries

* [Front-end] Refined styling of entry embeds

Fixes #1896

* [Merge] Generalized hover hide/show of local controls

Fixes #1896

* [Merge] Generalized labeled icon-* elements

Fixes #1896

* [Frontend]  CSS normalizing, apply general styles in markup

Fixes #1896
- Notebook class names more individualized;
- Apply .labeled and .has-local-controls general classes;
- Apply .s-input-inline to contenteditable div;
- Look and feel cleanups for drag area and entry elements;

* added modifiedOn time for entries that are changed, and fixed issue regarding inner text being filled when new entry button clicked

* [Frontend]  CSS sanding and cleanups

Fixes #1896
- Removing unused classes;
- Finessed margin and padding;

* [Frontend]  Mobile styling

Fixes #1896
- Mod .has-local-controls to not apply when in touch context

* [Frontend]  WIP Mobile styling

Fixes #1896
- phone portrait entry layout optimization

* fix expand in layout, which was causing snapshot at expand

* [Frontend]  Fixes to search control

Fixes #1896
- Search control now more robust, added
.search-filter-by-type class selector;

* [Frontend]  Fix custom Selects

Fixes #1896
- Custom Selects now much more
solid, handle width compression better;

* remove duplicate code from MCTModalNotebook and roll changes into MCTTriggerModal

* [Frontend]  WIP Mobile styling

Fixes #1896
- Fixed general approach to portrait orientation in
mobile/_layout.scss to use media query;
- Fixed portrait layout in _notebook_base.scss
to use media query;

* prevent multiple new notebook entry divs from being created on open overlay, instead create on initialization

* [Frontend]  WIP Snapshot styling

Fixes #1896
- Better class names;
- Moved buttons in frame layout;

* remove frame layout duplicate and use frame.html

* fix issue of preserving line breaks when text is received from a persisted source

* add comments, clean out some code, and fix broken tests

* fix export image after merging with master

* include painterro in karma config

* Inlined templates for notebook

* disable view policy - to allow layouts to function - needs more investigation

* fix layout display overload, remove viewpolicy and notebookLayout.html. Fix delete error - issues found when deploying for testathon

* fix (not being able to focus on content editable div to add text, while in layout)
- when in layout, the first child of the outermost div is the only one that registers a click, this was causing an issue of not being able to edit notebook entries. My fix includes finding the first child of the div that registers the click and forcing a focus event.

* fix focus one new entry issue, cleanup of code related to finding elements, and write more reusable code

* abstract findElementById for reusability and improve performance from O^2 to O

* user findElementById in entrydnd

* change snapshot library to dom-to-image

* [Frontend]  WIP Snapshot styling

Fixes #1896
Fixes #1947
- Significant markup changes to template in ViewSnaphot.js
- WIP!!! Keeping own topic branch for now

* [Frontend]  WIP Snapshot styling

Fixes #1896
Fixes #1947
- Significant markup changes to ViewSnaphot.js;
- Change in imagery.scss to move non-layout styling
to appropriate class;

* Removed snapshot from version number to close sprint eagle

* Updated version number for Enterprise release

* Lock filesaver version (#1956)

Lock filesaver version as there have been a large number of broken
builds from what should be non-breaking version increases.

Fixes currently broken build.

* [Frontend]  Snapshot styling

Fixes #1896
Fixes #1947
- Final tweaks after rebase from
notebook-integration-deep-styling

* fixes issue of overlay not closing when context menu item in clicked when viewing snapshot

* [Frontend]  Painterro styling

Fixes #1896
Fixes #1947
- WIP
- Painterro styling overrides and config
- Removed commented code

* [Frontend]  Painterro styling

Fixes #1896
Fixes #1947
- WIP
- Painterro styling overrides and config

* fixes issue of overlay not closing when context menu item in clicked when viewing snapshot

* specify require paths for new library

* [Frontend]  Local controls CSS added for hide/show of trash can icons

Fixes #1896
Fixes #1947
- Also updated frame.scss to use same transition timing

* proper shimming

* dragging objects to notebook now only creates a link, clicking on snapshot from object view takes a snapshot of the current view, without re-rendering

* [Frontend]  Local controls CSS added for hide/show of trash can icons

Fixes #1896
Fixes #1947
- Also updated frame.scss to use same transition timing

* select correct div for snapshot

* [Frontend]  Adding background color to snapshot

Fixes #1896
Fixes #1947

* remove snapshot class after async image render

* [Frontend]  Adding background color to snapshot

Fixes #1896
Fixes #1947

* remove snapshot button from frames in layout

* remove snapshot from frame view, add it only to overlay, change mctSnapShot to accomodate taking snaps of overlay/object view

* add preview action, working, need styling for notebook action on preview

* fix checkstyle

* change glyph for preview, use similar tempalte to frame.html

* dont allow preview action on objects getting edited currently

* changes to browseController and NavigationService to block navigation and show preview of object when trying to navigate to object in tree in edit mode

* [Frontend]  Painterro styling and config

Fixes #1896
Fixes #1947
- Changes mainly related to toolbar styling and labels

* [Frontend]  Notebook/Preview related sanding and polishing

Fixes #1947
- Changed description for notebook-new-entry

* [Frontend]  Notebook/Preview related sanding and polishing

Fixes #1947
- Added new global "hide-in-t-main-view" class;
- Apply new class to Preview action to suppress
display of that button in main view of navigated object;

* code cleanup

* [Frontend]  Notebook/Preview related sanding and polishing

Fixes #1947
- Classes for Notebook Entry button spacing;

* abstract overlay into a service/api - to reduce code duplication
catch error produced by painterro because of async div creation by dialog service

* fix broken mcttriggermodal tests

* fix checkstyle and lint

* add functionality of being able to add buttons to the browse bar element of overlay when instantiating the overlay service

* Reduce frequency of template recompilation in mct-include

* Use updated painterro library. Fixes #1981

* add save flag and call done in both cases (clicking on cancel or ok)

* fixes #1951
persist modified empty entry on blur

* Bump Node Version

* fix checkstyle

* fixes issue where annotating snapshot that is already saved in notebook does not work

* fix painterro button styling issue
move jquery logic inside timeout block, because buttons are asynchronously created

* remove description required when saving snapshot to notebook

* remove create snapshot action from embeds, and add preview action to embeds

* fixes edge case for issue #1981
Add a reject callback in the edgecase that user presses the x icon or esc key to cancel annotation, which was leading to the drag drop issue

* Add default sort options on creation menu of Notebook

* fix auto focus on new entry when in oldest first order, both in layout and regular view

* [Frontend] Notebook mobile mods

- Hide entry area when mobile;
- Disallow entry edit or delete in mobile;

* fixes issue 2041 (#2049)

* fixes issue 2041
allows user to select caret position in notebook entries while in layout

* [Frontend] Restore class, refine selector

Fixes #2041
Fixes #2049
- Restored .s-input-inline to editable field;
- Refined pointer-events: none to properly target .title-label only;

* remove unused files/code and smoke test

* remove , add pre-wrap to css and use inner text

* make reviewer requested changes 'in progress still'

* make reviewer requested changes 'continued'

* replace html2canvas with dom-to-image
- add in progress dialog to export image service
- add error dialog to export image service

* Search UI refactored to use flex

Fixes #1947
- Fixes broken search inputs in main search and Notebook;
- Significant rewrite to search SCSS and markup;

* Fixes for Notebook custom selects; polishes to search

Fixes #1947
- Better flex styles for custom selects;
- Refinements to search styling;
- Much better mobile responsive layout for search and controls
in portrait layout;

* fix preview action for embeds, which was showing current domain object vs selected domain object

* Fixed hidden search dropdown menu

Fixes #1947

* Revert whitespace change

Revert change to whitespace in index.html.  #1947.

* [Export] Use html2canvas

Use html2canvas instead of dom-to-image.  Fixes issues with text
exports.  html2canvas is better supported and under active
development and is a better choice for this library.  Cleaned up
export code, ensure that images are properly saved as the correct
types.

related to feedback on #1947

* Don't show brackets when timestamp is not specified (#331)
2018-06-28 17:13:34 -07:00
73e38f1955 [Toolbar] Implement a public API for adding toolbars (#1908)
* [API] Implement a toolbar registry and a plugin to allow providing a toolbar for a selected object.
* Modify the mct-toolbar directive to get the toolbar structure from a provider based on selection.
* Implements the layout toolbar in the layout bundle
2018-06-27 13:30:01 -07:00
de8f8d174d Add a string formatter (#2087)
* add StringFormat to formats
 fix #2086
2018-06-27 11:02:24 -07:00
b187762d55 [Folder] List view load fix (#2069)
* [Folder] List view load fix

-List view data takes long time to display, has to do with Angular not triggering its digestive cycle when switching views
-Resolved issue by explicitly triggering the digestive cycle
-Fixes issue #2067

* Added comment to clarify code addition

fix #2069
2018-06-21 10:52:27 -07:00
45a152df86 Build columns from union of telemetry value metadata. (#2075)
* Build columns from union of telemetry value metadata. Do not manually clean up scope. Fixes #2027. Fixes #1884. Fixes #1817.

* Fixed tests that are failing on circle-ci

* Inlined getMetadataValues function
2018-06-21 10:50:43 -07:00
a3e78bbf91 Duplicate images (#2058)
* [Images] changed updateHistory to only compare the URL value and timestamp for equality
2018-06-20 14:26:13 -07:00
374e4afc32 allow clearing table filters with cancel button #1989 (#2005)
* fixes issue #1989 add cancel icon to filter input in table headers, which allows user to clear filter with one click
2018-06-20 14:18:54 -07:00
2f8a0c2c2b [Notifications] Added timestamp and object name to copy notifications (#2060)
* [Notifications] Added timestamp and object name to copy notifications \n

-Fixes issue #331 
-Added timestamps to all notifications
-Added object name to copy success notification
-Updated placement and style of notification timestamp as discussed with Charles.
2018-06-20 10:37:19 -07:00
163043635e Merge pull request #2073 from nasa/table-spinners
Added digest after showing / hiding spinner. Fix #1882
2018-06-15 11:26:46 -07:00
ec9fd59d4a Added digest after showing / hiding spinner 2018-06-15 11:15:03 -07:00
e03ea25392 Merge pull request #2065 from nasa/bind-to-loopback
Modified Express startup so that it only binds to loopback by default
2018-06-08 10:44:55 -07:00
56c16ed263 Modified Express startup so that it only binds to loopback by default 2018-06-08 09:54:18 -07:00
483 changed files with 10817 additions and 6855 deletions

5
app.js
View File

@ -19,6 +19,7 @@
// 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] || [];
@ -78,7 +79,7 @@
app.use(express['static'](options.directory));
// Finally, open the HTTP server and log the instance to the console
app.listen(options.port, function() {
console.log('Open MCT application running at localhost:' + options.port)
app.listen(options.port, options.host, function() {
console.log('Open MCT application running at %s:%s', options.host, options.port)
});
}());

View File

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

View File

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

View File

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

View File

@ -27,8 +27,14 @@ define([
) {
var RED = 0.9,
YELLOW = 0.5,
var RED = {
sin: 0.9,
cos: 0.9
},
YELLOW = {
sin: 0.5,
cos: 0.5
},
LIMITS = {
rh: {
cssClass: "s-limit-upr s-limit-red",
@ -67,17 +73,18 @@ define([
SinewaveLimitProvider.prototype.getLimitEvaluator = function (domainObject) {
return {
evaluate: function (datum, valueMetadata) {
var range = valueMetadata ? valueMetadata.key : 'sin'
if (datum[range] > RED) {
var range = valueMetadata && valueMetadata.key;
if (datum[range] > RED[range]) {
return LIMITS.rh;
}
if (datum[range] < -RED) {
if (datum[range] < -RED[range]) {
return LIMITS.rl;
}
if (datum[range] > YELLOW) {
if (datum[range] > YELLOW[range]) {
return LIMITS.yh;
}
if (datum[range] < -YELLOW) {
if (datum[range] < -YELLOW[range]) {
return LIMITS.yl;
}
}

View File

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

View File

@ -149,12 +149,21 @@
<h2>Local Controls</h2>
<div class="cols cols1-1">
<div class="col">
<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>
<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>
</div>
<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">
<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">
<a class="s-button icon-arrow-left" title="Restore previous pan/zoom"></a>
<a class="s-button icon-arrows-out" title="Reset 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>
</div>
</div></mct-example>
</div>

View File

@ -30,7 +30,7 @@
<script>
var THIRTY_MINUTES = 30 * 60 * 1000;
require(['openmct'], function (openmct) {
require(['openmct', './src/plugins/telemetryTable/plugin'], function (openmct, TelemetryTablePlugin) {
[
'example/eventGenerator',
'example/styleguide'
@ -69,6 +69,8 @@
]
}));
openmct.install(openmct.plugins.SummaryWidget());
openmct.install(openmct.plugins.Notebook());
openmct.install(TelemetryTablePlugin());
openmct.time.clock('local', {start: -THIRTY_MINUTES, end: 0});
openmct.time.timeSystem('utc');
openmct.start();

View File

@ -37,7 +37,10 @@ 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},
@ -62,7 +65,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', 'junit'],
reporters: ['progress', 'coverage', 'html'],
// Web server port.
port: 9876,
@ -78,7 +81,7 @@ module.exports = function(config) {
// Specify browsers to run tests in.
// available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
browsers: [
'Chrome'
'ChromeHeadless'
],
// Code coverage reporting.
@ -101,10 +104,6 @@ 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

68
notes.md Normal file
View File

@ -0,0 +1,68 @@
* Delete old table
* Update new table type and test backward compatibility.
* re-evaluate TableConfiguration object. Name doesn't make sense right now, and some duplicated code for configuration handling in components.
* Rebase over refactor branch
* Move css to new table location
* Test (see list of issues below)
* Push WIP PR
* [X] Remove column sizing rows on object removal (should be trivial since tracking by object ID already).
* [X] Look at optimizing styles in telemetry-table-row
- Right now profiling does not highlight this as a bottleneck?
* [X] Add title to table cells
* [X] Add elipses for overflow on table cells
* [X] On entry, filter boxes need to remove magnifying glass.
* [X] auto-scroll
* [X] Show / hide columns (ie. table configuration)
* [X] Why aren't limits being applied until I scroll or do something?
* [X] Handle window resizing
* [X] Fix memory leaks
* [X] Remove isFromObject and hasColumn from TelemetryTableRow
* [X] Remove format caching
* [X] Add filtering
* If the new filter string starts with the old filter string, filter based on the list of previously filtered results, not the base list.
* Add the clear filter button
* [X] Cache formatted values for "just in time" formatting. I think cache on row. Opportunity to cache on column to benefit from multiple rows with the same value, but memory management becomes a problem then as cache could grow infinitely if the table is left to run.
* [X] Do some more testing with multiple objects. Not working properly right now.
* [X] Rows not being removed when object removed from composition
* [X] Subscribe to realtime data
* [X] Column widths should be done on receipt of FIRST DATA, not on receipt of historical data.
* [X] Filter subscription data
* [X] Export
* [X] Add loading spinner
* [X] in 'mounted', should not be necessary to bind to 'this'.
* [X] Stop Vue from decorating EVERYTHING (but especially the telemetry collection)
* [X] Need minimum width on tables. Provided by calcTableWidthPx in MCTTableController
* [X] Limits
* Benchmark - loading 1 million rows
- Old tables: ~90s
- New tables: ~11s
* 1 million rows in 11 secs vs 90s
To Test
* Multiple instances of tables
* Make sure time columns are being correctly merged
* Test with MSL data sources
* Test with tutorial data sources
* Behavior at different widths.
* Short tables
* Test with bounds / clock / time system changes.
* Memory leaks
Post WIP PR
* Fix jitter on auto-scroll
* Look at scroll-x again. Sounded like there might be some subtlety missing there (something to do with small columns?).
* Split TelemetryTableComponent into more components. It's too large now.
* Performance
* Don't wrap row on load, do it on scroll.
* On batch insert, check bounds once, rather than on each insert.
* See if sticky headers can be simplified (eg. can we combine headers table with content table?)
* Default sort behavior, and sticking to the bottom for realtime numerical
* Look at setting top on tbody, instead of each tr
* Replace all "mct-table" classes
* Consider making the sizing row a separate component. Encapsulate all sizing logic in there.
* consider making the header table a separate component.
* Test where no time column present (what will it sort by)
* [X] Optimization - don't both sorting filtered rows initially, just copy over values from bounded row collection which have already been sorted.

View File

@ -29,7 +29,6 @@ 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",
@ -49,7 +48,10 @@ requirejs.config({
"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/build/d3-time.min",
"d3-time-format": "node_modules/d3-time-format/build/d3-time-format.min"
"d3-time-format": "node_modules/d3-time-format/build/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"
},
"shim": {
"angular": {
@ -61,12 +63,12 @@ requirejs.config({
"EventEmitter": {
"exports": "EventEmitter"
},
"html2canvas": {
"exports": "html2canvas"
},
"moment-duration-format": {
"deps": ["moment"]
},
"painterro": {
"exports": "Painterro"
},
"saveAs": {
"exports": "saveAs"
},
@ -88,6 +90,9 @@ requirejs.config({
},
"d3-axis": {
"exports": "d3-axis"
},
"dom-to-image": {
"exports": "domtoimage"
}
}
});

View File

@ -15,6 +15,7 @@
"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"
},
@ -30,18 +31,18 @@
"gulp-requirejs-optimize": "^0.3.1",
"gulp-sass": "^3.1.0",
"gulp-sourcemaps": "^1.6.0",
"jasmine-core": "^2.3.0",
"html2canvas": "^1.0.0-alpha.12",
"jasmine-core": "^3.1.0",
"jscs-html-reporter": "^0.1.0",
"jsdoc": "^3.3.2",
"jshint": "^2.7.0",
"karma": "^0.13.3",
"karma-chrome-launcher": "^0.1.12",
"karma-cli": "0.0.4",
"karma-coverage": "^0.5.3",
"karma": "^2.0.3",
"karma-chrome-launcher": "^2.2.0",
"karma-cli": "^1.0.1",
"karma-coverage": "^1.1.2",
"karma-html-reporter": "^0.2.7",
"karma-jasmine": "^0.1.5",
"karma-junit-reporter": "^0.3.8",
"karma-requirejs": "^0.2.2",
"karma-jasmine": "^1.1.2",
"karma-requirejs": "^1.1.0",
"lodash": "^3.10.1",
"markdown-toc": "^0.11.7",
"marked": "^0.3.5",
@ -49,6 +50,7 @@
"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"

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">
class="abs holder holder-object t-main-view">
</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,21 +19,23 @@
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">
<ul class="flex-elem grows l-inspector-part">
<li>
<em class="t-inspector-part-header">Properties</em>
<div class="inspector-properties"
<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="label">{{ data.name }}</div>
<div class="value">{{ data.value }}</div>
</div>
<div class="grid-cell label">{{ data.name }}</div>
<div class="grid-cell value">{{ data.value }}</div>
</li>
<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"
</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'"
@ -41,11 +43,13 @@
ng-click="parent.getCapability('action').perform('navigate')"
class="location-item">
</mct-representation>
</span>
</div>
</div>
</li>
<li ng-if="primaryParents.length > 0">
<div class="section-header">Object's Original</div>
<span class="inspector-location"
<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'"
@ -53,7 +57,8 @@
ng-click="parent.getCapability('action').perform('navigate')"
class="location-item">
</mct-representation>
</span>
</div>
</div>
</li>
</ul>
</div>

View File

@ -47,8 +47,8 @@ define(
urlService,
defaultPath
) {
var initialPath = ($route.current.params.ids || defaultPath).split("/");
var currentIds;
var initialPath = ($route.current.params.ids || defaultPath).split("/"),
currentIds;
$scope.treeModel = {
selectedObject: undefined,
@ -56,8 +56,25 @@ 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;
}
}
};
function idsForObject(domainObject) {

View File

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

View File

@ -19,6 +19,7 @@
* 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.
@ -48,9 +49,19 @@ define(
controller;
function waitsForNavigation() {
var calls = mockNavigationService.setNavigation.calls.length;
waitsFor(function () {
return mockNavigationService.setNavigation.calls.length > calls;
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;
});
});
}
@ -78,7 +89,7 @@ define(
"urlService",
["urlForLocation"]
);
mockUrlService.urlForLocation.andCallFake(function (mode, object) {
mockUrlService.urlForLocation.and.callFake(function (mode, object) {
if (object === mockDefaultRootObject) {
return [mode, testDefaultRoot].join('/');
}
@ -106,7 +117,7 @@ define(
"removeListener"
].forEach(function (method) {
spyOn(mockNavigationService, method)
.andCallThrough();
.and.callThrough();
});
mockRootObject = jasmine.createSpyObj(
"rootObjectContainer",
@ -124,32 +135,31 @@ define(
"nestedDomainObject",
["getId", "getCapability", "getModel", "useCapability", "hasCapability"]
);
mockObjectService.getObjects.andReturn(Promise.resolve({
mockObjectService.getObjects.and.returnValue(Promise.resolve({
ROOT: mockRootObject
}));
mockRootObject.useCapability.andReturn(Promise.resolve([
mockRootObject.useCapability.and.returnValue(Promise.resolve([
mockOtherDomainObject,
mockDefaultRootObject
]));
mockRootObject.hasCapability.andReturn(true);
mockDefaultRootObject.useCapability.andReturn(Promise.resolve([
mockRootObject.hasCapability.and.returnValue(true);
mockDefaultRootObject.useCapability.and.returnValue(Promise.resolve([
mockNextObject
]));
mockDefaultRootObject.hasCapability.andReturn(true);
mockOtherDomainObject.hasCapability.andReturn(false);
mockNextObject.useCapability.andReturn(undefined);
mockNextObject.hasCapability.andReturn(false);
mockNextObject.getId.andReturn("next");
mockDefaultRootObject.getId.andReturn(testDefaultRoot);
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);
instantiateController();
waitsForNavigation();
return waitsForNavigation();
});
it("uses composition to set the navigated object, if there is none", function () {
instantiateController();
waitsForNavigation();
runs(function () {
return waitsForNavigation().then(function () {
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDefaultRootObject);
});
@ -157,27 +167,26 @@ define(
it("navigates to a root-level object, even when default path is not found", function () {
mockDefaultRootObject.getId
.andReturn("something-other-than-the-" + testDefaultRoot);
.and.returnValue("something-other-than-the-" + testDefaultRoot);
instantiateController();
waitsForNavigation();
runs(function () {
return waitsForNavigation().then(function () {
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDefaultRootObject);
});
});
//
it("does not try to override navigation", function () {
mockNavigationService.getNavigation.andReturn(mockDefaultRootObject);
mockNavigationService.getNavigation.and.returnValue(mockDefaultRootObject);
instantiateController();
waitsForNavigation();
return waitsForNavigation().then(function () {
expect(mockScope.navigatedObject).toBe(mockDefaultRootObject);
});
//
});
it("updates scope when navigated object changes", function () {
// Should have registered a listener - call it
mockNavigationService.addListener.mostRecentCall.args[0](
mockNavigationService.addListener.calls.mostRecent().args[0](
mockOtherDomainObject
);
expect(mockScope.navigatedObject).toEqual(mockOtherDomainObject);
@ -189,19 +198,18 @@ define(
"$destroy",
jasmine.any(Function)
);
mockScope.$on.mostRecentCall.args[1]();
mockScope.$on.calls.mostRecent().args[1]();
// Should remove the listener it added earlier
expect(mockNavigationService.removeListener).toHaveBeenCalledWith(
mockNavigationService.addListener.mostRecentCall.args[0]
mockNavigationService.addListener.calls.mostRecent().args[0]
);
});
it("uses route parameters to choose initially-navigated object", function () {
mockRoute.current.params.ids = testDefaultRoot + "/next";
instantiateController();
waitsForNavigation();
runs(function () {
return waitsForNavigation().then(function () {
expect(mockScope.navigatedObject).toBe(mockNextObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockNextObject);
@ -214,12 +222,10 @@ define(
// it hits an invalid ID.
mockRoute.current.params.ids = testDefaultRoot + "/junk";
instantiateController();
waitsForNavigation();
runs(function () {
return waitsForNavigation().then(function () {
expect(mockScope.navigatedObject).toBe(mockDefaultRootObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDefaultRootObject);
});
});
@ -229,8 +235,7 @@ define(
// should stop at it since remaining IDs cannot be loaded.
mockRoute.current.params.ids = testDefaultRoot + "/next/junk";
instantiateController();
waitsForNavigation();
runs(function () {
return waitsForNavigation().then(function () {
expect(mockScope.navigatedObject).toBe(mockNextObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockNextObject);
@ -244,11 +249,11 @@ define(
expect(mockRoute.current.pathParams.ids)
.not
.toBe(testDefaultRoot + '/next');
mockLocation.path.andCallFake(function () {
mockLocation.path.and.callFake(function () {
expect(mockRoute.current.pathParams.ids)
.toBe(testDefaultRoot + '/next');
});
mockNavigationService.addListener.mostRecentCall.args[0](
mockNavigationService.addListener.calls.mostRecent().args[0](
mockNextObject
);
expect(mockLocation.path).toHaveBeenCalledWith(

View File

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

View File

@ -50,14 +50,14 @@ define(
"navigationService",
["getNavigation", "addListener"]
);
mockNavigationService.addListener.andReturn(mockNavigationUnlistener);
mockNavigationService.addListener.and.returnValue(mockNavigationUnlistener);
mockStatusUnlistener = jasmine.createSpy("statusUnlistener");
mockStatusCapability = jasmine.createSpyObj(
"statusCapability",
["listen"]
);
mockStatusCapability.listen.andReturn(mockStatusUnlistener);
mockStatusCapability.listen.and.returnValue(mockStatusUnlistener);
mockDomainObject = jasmine.createSpyObj(
'domainObject',
@ -68,13 +68,13 @@ define(
'hasCapability'
]
);
mockDomainObject.getId.andReturn("domainObject");
mockDomainObject.getModel.andReturn({});
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andReturn(mockStatusCapability);
mockDomainObject.getId.and.returnValue("domainObject");
mockDomainObject.getModel.and.returnValue({});
mockDomainObject.hasCapability.and.returnValue(true);
mockDomainObject.getCapability.and.returnValue(mockStatusCapability);
mockLocation = jasmine.createSpyObj('location', ['search']);
mockLocation.search.andReturn({});
mockLocation.search.and.returnValue({});
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.mostRecentCall.args[0](mockDomainObject);
mockNavigationService.addListener.calls.mostRecent().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.mostRecentCall.args[0](mockDomainObject);
mockStatusCapability.listen.mostRecentCall.args[0](["editing"]);
mockNavigationService.addListener.calls.mostRecent().args[0](mockDomainObject);
mockStatusCapability.listen.calls.mostRecent().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.andReturn(mockContextMenuAction);
mockContextMenuAction.perform.andReturn(jasmine.any(Function));
mockDomainObject.getCapability.and.returnValue(mockContextMenuAction);
mockContextMenuAction.perform.and.returnValue(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.andCallFake(function (feature) {
mockTypeCapability.hasFeature.and.callFake(function (feature) {
return feature === 'creation';
});
@ -52,8 +52,8 @@ define(
name: "Test name"
};
mockDomainObject = jasmine.createSpyObj("domainObject", ["getCapability", "getModel"]);
mockDomainObject.getModel.andReturn(model);
mockDomainObject.getCapability.andCallFake(function (key) {
mockDomainObject.getModel.and.returnValue(model);
mockDomainObject.getCapability.and.callFake(function (key) {
return mockCapabilities[key];
});
@ -62,7 +62,7 @@ define(
};
mockCurrentTarget = jasmine.createSpyObj("currentTarget", ["blur", "textContent"]);
mockCurrentTarget.blur.andReturn(mockCurrentTarget);
mockCurrentTarget.blur.and.returnValue(mockCurrentTarget);
mockEvent = {
which: {},
@ -109,7 +109,7 @@ define(
expect(mockMutationCapability.mutate).toHaveBeenCalledWith(jasmine.any(Function));
mockMutationCapability.mutate.mostRecentCall.args[0](model);
mockMutationCapability.mutate.calls.mostRecent().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.andReturn(false);
mockTypeCapability.hasFeature.and.returnValue(false);
expect(controller.allowEdit()).toBe(false);

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,10 @@
<div class="top-bar">
<div class="title">{{ngModel.title}}</div>
</div>
<div class="hint" ng-hide="ngModel.hint === undefined">{{ngModel.hint}}</div>
<div class="hint" ng-hide="ngModel.hint === undefined">
{{ngModel.hint}}
<span ng-if="ngModel.timestamp !== undefined">[{{ngModel.timestamp}}]</span>
</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.andReturn(mockBody);
mockDocument.find.and.returnValue(mockBody);
mockDeferred.promise = "mock promise";
mockQ.defer.andReturn(mockDeferred);
mockOverlayService.createOverlay.andReturn(mockOverlay);
mockQ.defer.and.returnValue(mockDeferred);
mockOverlayService.createOverlay.and.returnValue(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.mostRecentCall.args[1].cancel();
mockOverlayService.createOverlay.calls.mostRecent().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.mostRecentCall.args[1].confirm();
mockOverlayService.createOverlay.calls.mostRecent().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.mostRecentCall.args[1].confirm();
mockOverlayService.createOverlay.calls.mostRecent().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.mostRecentCall.args[1].cancel();
mockOverlayService.createOverlay.calls.mostRecent().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.mostRecentCall.args[1]({
mockBody.on.calls.mostRecent().args[1]({
keyCode: 27
});
expect(mockDeferred.reject).toHaveBeenCalled();
@ -163,7 +163,7 @@ define(
it("ignores non escape keydown events", function () {
dialogService.getUserInput({}, {});
mockBody.on.mostRecentCall.args[1]({
mockBody.on.calls.mostRecent().args[1]({
keyCode: 13
});
expect(mockDeferred.reject).not.toHaveBeenCalled();
@ -197,7 +197,7 @@ define(
"overlay",
["dismiss"]
);
mockOverlayService.createOverlay.andReturn(secondMockOverlay);
mockOverlayService.createOverlay.and.returnValue(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.andReturn(mockBody);
mockCompile.andReturn(mockTemplate);
mockRootScope.$new.andReturn(mockScope);
mockTemplate.andReturn(mockElement);
mockDocument.find.and.returnValue(mockBody);
mockCompile.and.returnValue(mockTemplate);
mockRootScope.$new.and.returnValue(mockScope);
mockTemplate.and.returnValue(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.mostRecentCall.args[0].indexOf("mct-include"))
expect(mockCompile.calls.mostRecent().args[0].indexOf("mct-include"))
.not.toEqual(-1);
});

View File

@ -39,7 +39,6 @@ define([
"./src/policies/EditableMovePolicy",
"./src/policies/EditContextualActionPolicy",
"./src/representers/EditRepresenter",
"./src/representers/EditToolbarRepresenter",
"./src/capabilities/EditorCapability",
"./src/capabilities/TransactionCapabilityDecorator",
"./src/services/TransactionManager",
@ -78,7 +77,6 @@ define([
EditableMovePolicy,
EditContextualActionPolicy,
EditRepresenter,
EditToolbarRepresenter,
EditorCapability,
TransactionCapabilityDecorator,
TransactionManager,
@ -381,12 +379,6 @@ define([
"depends": [
"$log"
]
},
{
"implementation": EditToolbarRepresenter,
"depends": [
"openmct"
]
}
],
"constants": [
@ -424,6 +416,17 @@ define([
"transactionService"
]
}
],
"runs": [
{
depends: [
"toolbars[]",
"openmct"
],
implementation: function (toolbars, openmct) {
toolbars.forEach(openmct.toolbars.addProvider, openmct.toolbars);
}
}
]
}
});

View File

@ -24,7 +24,8 @@
<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">
@ -48,8 +49,8 @@
<!-- Toolbar and Save/Cancel buttons -->
<div class="l-edit-controls flex-elem l-flex-row flex-align-end">
<mct-toolbar name="mctToolbar"
structure="toolbar.structure"
ng-model="toolbar.state"
structure="editToolbar.structure"
ng-model="editToolbar.state"
class="flex-elem grows">
</mct-toolbar>
<mct-representation key="'edit-action-buttons'"
@ -61,7 +62,6 @@
<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">
<div class="flex-elem grows vscroll scroll-pad">
<ul class="tree" id="inspector-elements-tree"
ng-if="composition.length > 0">
<li ng-repeat="containedObject in composition | filter:searchElements">

View File

@ -20,192 +20,110 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
define(
[],
function () {
// Utility functions for reducing truth arrays
function and(a, b) {
return a && b;
}
function or(a, b) {
return a || b;
}
[
'../../../../../src/api/objects/object-utils',
'lodash'
],
function (
objectUtils,
_
) {
/**
* Provides initial structure and state (as suitable for provision
* 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
* to the `mct-toolbar` directive) for a view's toolbar, based on
* that view's declaration of what belongs in its toolbar and on
* the current selection.
*
* @param structure toolbar structure, as provided by view definition
* @param {Function} commit callback to invoke after changes
* @param $scope the Angular scope
* @param {Object} openmct the openmct object
* @param structure the toolbar structure
* @memberof platform/commonUI/edit
* @constructor
*/
function EditToolbar(structure, commit) {
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) {
var self = this;
// Generate a new key for an item's property
function addKey(property) {
self.properties.push(property);
function addKey(item) {
self.stateTracker.push({
id: objectUtils.makeKeyString(item.domainObject.identifier),
domainObject: item.domainObject,
property: item.property
});
self.properties.push(item.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.property);
converted.key = addKey(item);
}
if (item.method) {
converted.click = function (v) {
invoke(item.method, v);
converted.click = function (value) {
item.method(value);
};
}
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;
// 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;
structure.forEach(function (item) {
if (item.property === property) {
result = _.get(item.domainObject, item.property);
}
});
return result;
}
this.selection = s;
this.toolbarStructure.sections.forEach(refreshSectionApplicability);
// Tracks the domain object and property for every element in the state array
this.stateTracker = [];
this.toolbarStructure = structure.map(convertItem);
this.toolbarState = this.properties.map(initializeState);
};
/**
* Get the structure of the toolbar, as appropriate to
* Gets the structure of the toolbar, as appropriate to
* pass to `mct-toolbar`.
* @returns the toolbar structure
*
* @returns {Array} the toolbar structure
*/
EditToolbar.prototype.getStructure = function () {
return this.toolbarStructure;
};
/**
* Get the current state of the toolbar, as appropriate
* Gets 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 () {
@ -213,48 +131,124 @@ define(
};
/**
* Update state within the current selection.
* 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.
*
* @param {number} index the index of the corresponding
* element in the state array
* @param value the new value to convey to the selection
* @param value the new value to update the state array with
*/
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;
// 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;
}
}
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 property in all selected elements
self.selection.forEach(updateProperty);
structure.forEach(function (item) {
var domainObject = item.domainObject;
var id = objectUtils.makeKeyString(domainObject.identifier);
// Return whether or not anything changed
return changed;
if (!self.domainObjectsById[id]) {
self.domainObjectsById[id] = {
domainObject: domainObject,
properties: []
};
observeObject(domainObject, id);
}
return updateProperties(this.properties[index], value);
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 EditToolbar;
}
);

View File

@ -1,154 +0,0 @@
/*****************************************************************************
* 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

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

View File

@ -66,11 +66,11 @@ define(
editor: mockEditor
};
mockDomainObject.getCapability.andCallFake(function (name) {
mockDomainObject.getCapability.and.callFake(function (name) {
return capabilities[name];
});
mockDomainObject.hasCapability.andReturn(true);
mockType.hasFeature.andReturn(true);
mockDomainObject.hasCapability.and.returnValue(true);
mockType.hasFeature.and.returnValue(true);
actionContext = { domainObject: mockDomainObject };
@ -92,9 +92,9 @@ define(
});
it("is only applicable to objects not already in edit mode", function () {
mockEditor.isEditContextRoot.andReturn(false);
mockEditor.isEditContextRoot.and.returnValue(false);
expect(EditAction.appliesTo(actionContext)).toBe(true);
mockEditor.isEditContextRoot.andReturn(true);
mockEditor.isEditContextRoot.and.returnValue(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.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([]);
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([]);
capabilities = {
composition: mockComposition,
@ -105,14 +105,14 @@ define(
});
it("enables edit mode for objects that have an edit action", function () {
mockActionCapability.getActions.andReturn([mockEditAction]);
mockActionCapability.getActions.and.returnValue([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.andReturn([]);
mockActionCapability.getActions.and.returnValue([]);
action.perform();
expect(mockEditAction.perform).not.toHaveBeenCalled();
expect(mockComposition.add)

View File

@ -71,8 +71,8 @@ define(
}
};
capabilities.type.hasFeature.andReturn(true);
capabilities.mutation.andReturn(true);
capabilities.type.hasFeature.and.returnValue(true);
capabilities.mutation.and.returnValue(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.mostRecentCall.args[0]({});
capabilities.mutation.calls.mostRecent().args[0]({});
});
it("does not muate object upon cancel", function () {

View File

@ -95,13 +95,13 @@ define(
"removeListener"
]
);
mockNavigationService.getNavigation.andReturn(mockDomainObject);
mockNavigationService.getNavigation.and.returnValue(mockDomainObject);
mockDomainObject.getId.andReturn("test");
mockDomainObject.getCapability.andReturn(mockContext);
mockContext.getParent.andReturn(mockParent);
mockType.hasFeature.andReturn(true);
mockDomainObject.getId.and.returnValue("test");
mockDomainObject.getCapability.and.returnValue(mockContext);
mockContext.getParent.and.returnValue(mockParent);
mockType.hasFeature.and.returnValue(true);
capabilities = {
mutation: mockMutation,
@ -119,7 +119,7 @@ define(
it("only applies to objects with parents", function () {
expect(RemoveAction.appliesTo(actionContext)).toBeTruthy();
mockContext.getParent.andReturn(undefined);
mockContext.getParent.and.returnValue(undefined);
expect(RemoveAction.appliesTo(actionContext)).toBeFalsy();
@ -136,7 +136,7 @@ define(
it("changes composition from its mutation function", function () {
var mutator, result;
action.perform();
mutator = mockMutation.invoke.mostRecentCall.args[0];
mutator = mockMutation.invoke.calls.mostRecent().args[0];
result = mutator(model);
// Should not have cancelled the mutation
@ -153,22 +153,22 @@ define(
it("removes parent of object currently navigated to", function () {
// Navigates to child object
mockNavigationService.getNavigation.andReturn(mockChildObject);
mockNavigationService.getNavigation.and.returnValue(mockChildObject);
// Test is id of object being removed
// Child object has different id
mockDomainObject.getId.andReturn("test");
mockChildObject.getId.andReturn("not test");
mockDomainObject.getId.and.returnValue("test");
mockChildObject.getId.and.returnValue("not test");
// Sets context for the child and domainObject
mockDomainObject.getCapability.andReturn(mockContext);
mockChildObject.getCapability.andReturn(mockChildContext);
mockDomainObject.getCapability.and.returnValue(mockContext);
mockChildObject.getCapability.and.returnValue(mockChildContext);
// Parents of child and domainObject are set
mockContext.getParent.andReturn(mockParent);
mockChildContext.getParent.andReturn(mockDomainObject);
mockContext.getParent.and.returnValue(mockParent);
mockChildContext.getParent.and.returnValue(mockDomainObject);
mockType.hasFeature.andReturn(true);
mockType.hasFeature.and.returnValue(true);
action.perform();
@ -178,25 +178,25 @@ define(
it("checks if removing object not in ascendent path (reaches ROOT)", function () {
// Navigates to grandchild of ROOT
mockNavigationService.getNavigation.andReturn(mockGrandchildObject);
mockNavigationService.getNavigation.and.returnValue(mockGrandchildObject);
// 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");
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.andReturn(mockRootContext);
mockChildObject.getCapability.andReturn(mockChildContext);
mockGrandchildObject.getCapability.andReturn(mockGrandchildContext);
mockRootObject.getCapability.and.returnValue(mockRootContext);
mockChildObject.getCapability.and.returnValue(mockChildContext);
mockGrandchildObject.getCapability.and.returnValue(mockGrandchildContext);
// Parents of grandchild and child are set
mockChildContext.getParent.andReturn(mockRootObject);
mockGrandchildContext.getParent.andReturn(mockChildObject);
mockChildContext.getParent.and.returnValue(mockRootObject);
mockGrandchildContext.getParent.and.returnValue(mockChildObject);
mockType.hasFeature.andReturn(true);
mockType.hasFeature.and.returnValue(true);
action.perform();

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

View File

@ -86,13 +86,13 @@ define(
["info", "error"]
);
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andCallFake(function (capability) {
mockDomainObject.hasCapability.and.returnValue(true);
mockDomainObject.getCapability.and.callFake(function (capability) {
return capabilities[capability];
});
mockDomainObject.getModel.andReturn({ persisted: 0 });
mockEditorCapability.save.andReturn(mockPromise(true));
mockEditorCapability.isEditContextRoot.andReturn(true);
mockDomainObject.getModel.and.returnValue({ persisted: 0 });
mockEditorCapability.save.and.returnValue(mockPromise(true));
mockEditorCapability.isEditContextRoot.and.returnValue(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.andReturn(false);
mockDomainObject.getCapability.andReturn(undefined);
mockDomainObject.hasCapability.and.returnValue(false);
mockDomainObject.getCapability.and.returnValue(undefined);
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
});
it("only applies to domain object that has already been persisted", function () {
mockDomainObject.getModel.andReturn({ persisted: undefined });
mockDomainObject.getModel.and.returnValue({ persisted: undefined });
expect(SaveAndStopEditingAction.appliesTo(actionContext)).toBe(false);
});
it("does not close the editor before completing the save", function () {
mockEditorCapability.save.andReturn(new Promise(function () {
mockEditorCapability.save.and.returnValue(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,runs,waitsFor,spyOn*/
/*global describe,it,expect,beforeEach,jasmine,spyOn*/
define(
["../../src/actions/SaveAsAction"],
@ -63,12 +63,12 @@ define(
"getId"
]
);
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andCallFake(function (capability) {
mockDomainObject.hasCapability.and.returnValue(true);
mockDomainObject.getCapability.and.callFake(function (capability) {
return capabilities[capability];
});
mockDomainObject.getModel.andReturn({location: 'a', persisted: undefined});
mockDomainObject.getId.andReturn(0);
mockDomainObject.getModel.and.returnValue({location: 'a', persisted: undefined});
mockDomainObject.getId.and.returnValue(0);
mockClonedObject = jasmine.createSpyObj(
"clonedObject",
@ -76,7 +76,7 @@ define(
"getId"
]
);
mockClonedObject.getId.andReturn(1);
mockClonedObject.getId.and.returnValue(1);
mockParent = jasmine.createSpyObj(
"parentObject",
@ -91,9 +91,9 @@ define(
"editor",
["save", "finish", "isEditContextRoot"]
);
mockEditorCapability.save.andReturn(mockPromise(true));
mockEditorCapability.finish.andReturn(mockPromise(true));
mockEditorCapability.isEditContextRoot.andReturn(true);
mockEditorCapability.save.and.returnValue(mockPromise(true));
mockEditorCapability.finish.and.returnValue(mockPromise(true));
mockEditorCapability.isEditContextRoot.and.returnValue(true);
capabilities.editor = mockEditorCapability;
mockActionCapability = jasmine.createSpyObj(
@ -106,7 +106,7 @@ define(
"objectService",
["getObjects"]
);
mockObjectService.getObjects.andReturn(mockPromise({'a': mockParent}));
mockObjectService.getObjects.and.returnValue(mockPromise({'a': mockParent}));
mockDialogService = jasmine.createSpyObj(
"dialogService",
@ -115,7 +115,7 @@ define(
"showBlockingMessage"
]
);
mockDialogService.getUserInput.andReturn(mockPromise(undefined));
mockDialogService.getUserInput.and.returnValue(mockPromise(undefined));
mockCopyService = jasmine.createSpyObj(
"copyService",
@ -123,7 +123,7 @@ define(
"perform"
]
);
mockCopyService.perform.andReturn(mockPromise(mockClonedObject));
mockCopyService.perform.and.returnValue(mockPromise(mockClonedObject));
mockNotificationService = jasmine.createSpyObj(
"notificationService",
@ -146,10 +146,10 @@ define(
actionContext);
spyOn(action, "getObjectService");
action.getObjectService.andReturn(mockObjectService);
action.getObjectService.and.returnValue(mockObjectService);
spyOn(action, "createWizard");
action.createWizard.andReturn({
action.createWizard.and.returnValue({
getFormStructure: noop,
getInitialFormValue: noop,
populateObjectFromInput: function () {
@ -163,8 +163,8 @@ define(
expect(SaveAsAction.appliesTo(actionContext)).toBe(true);
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
mockDomainObject.hasCapability.andReturn(false);
mockDomainObject.getCapability.andReturn(undefined);
mockDomainObject.hasCapability.and.returnValue(false);
mockDomainObject.getCapability.and.returnValue(undefined);
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
});
@ -173,35 +173,27 @@ define(
expect(SaveAsAction.appliesTo(actionContext)).toBe(true);
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
mockDomainObject.getModel.andReturn({persisted: 0});
mockDomainObject.getModel.and.returnValue({persisted: 0});
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
});
it("uses the editor capability to save the object", function () {
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();
mockEditorCapability.save.and.returnValue(Promise.resolve());
return action.perform().then(function () {
expect(mockEditorCapability.save).toHaveBeenCalled();
});
});
it("uses the editor capability to finish editing the object", function () {
runs(function () {
action.perform();
return action.perform().then(function () {
expect(mockEditorCapability.finish.calls.count()).toBeGreaterThan(0);
});
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.andReturn(mockPromise(mockDomainObject));
action.save.and.returnValue(mockPromise(mockDomainObject));
action.perform();
expect(mockActionCapability.perform).toHaveBeenCalledWith(
"navigate"
@ -218,48 +210,33 @@ define(
beforeEach(function () {
mockDialogHandle = jasmine.createSpyObj("dialogHandle", ["dismiss"]);
mockDialogService.showBlockingMessage.andReturn(mockDialogHandle);
mockDialogService.showBlockingMessage.and.returnValue(mockDialogHandle);
});
it("shows a blocking dialog indicating that saving is in progress", function () {
mockEditorCapability.save.andReturn(new Promise(function () {}));
mockEditorCapability.save.and.returnValue(new Promise(function () {}));
action.perform();
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
expect(mockDialogHandle.dismiss).not.toHaveBeenCalled();
});
it("hides the blocking dialog after saving finishes", function () {
var mockCallback = jasmine.createSpy();
action.perform().then(mockCallback);
return action.perform().then(function () {
expect(mockDialogService.showBlockingMessage).toHaveBeenCalled();
waitsFor(function () {
return mockCallback.calls.length > 0;
});
runs(function () {
expect(mockDialogHandle.dismiss).toHaveBeenCalled();
});
});
it("notifies if saving succeeded", function () {
var mockCallback = jasmine.createSpy();
action.perform().then(mockCallback);
waitsFor(function () {
return mockCallback.calls.length > 0;
});
runs(function () {
return action.perform().then(function () {
expect(mockNotificationService.info).toHaveBeenCalled();
expect(mockNotificationService.error).not.toHaveBeenCalled();
});
});
it("notifies if saving failed", 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 () {
mockCopyService.perform.and.returnValue(Promise.reject("some failure reason"));
action.perform().then(function () {
expect(mockNotificationService.error).toHaveBeenCalled();
expect(mockNotificationService.info).not.toHaveBeenCalled();
});

View File

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

View File

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

View File

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

View File

@ -38,7 +38,7 @@ define(
jasmine.createSpyObj("mockSaveAction", ["getMetadata", "perform"])
];
mockedSaveActions.forEach(function (action) {
action.getMetadata.andReturn(mockSaveActionMetadata);
action.getMetadata.and.returnValue(mockSaveActionMetadata);
});
return mockedSaveActions;
} else if (actionContext.category === "conclude-editing") {
@ -54,14 +54,14 @@ define(
beforeEach(function () {
mockActions = jasmine.createSpyObj("action", ["getActions"]);
mockActions.getActions.andCallFake(fakeGetActions);
mockActions.getActions.and.callFake(fakeGetActions);
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
mockScope.action = mockActions;
controller = new EditActionController(mockScope);
});
function makeControllerUpdateActions() {
mockScope.$watch.mostRecentCall.args[1]();
mockScope.$watch.calls.mostRecent().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.andReturn({"view": "fixed"});
mockLocation.search.and.returnValue({"view": "fixed"});
mockNavigationService = jasmine.createSpyObj('navigationService',
["checkBeforeNavigation"]
);
removeCheck = jasmine.createSpy('removeCheck');
mockNavigationService.checkBeforeNavigation.andReturn(removeCheck);
mockNavigationService.checkBeforeNavigation.and.returnValue(removeCheck);
mockObject.getId.andReturn("test");
mockObject.getModel.andReturn({ name: "Test object" });
mockObject.getCapability.andCallFake(function (key) {
mockObject.getId.and.returnValue("test");
mockObject.getModel.and.returnValue({ name: "Test object" });
mockObject.getCapability.and.callFake(function (key) {
return mockCapabilities[key];
});
@ -81,10 +81,10 @@ define(
{ key: 'xyz' }
];
mockObject.useCapability.andCallFake(function (c) {
mockObject.useCapability.and.callFake(function (c) {
return (c === 'view') && testViews;
});
mockLocation.search.andReturn({ view: 'def' });
mockLocation.search.and.returnValue({ view: 'def' });
mockScope.domainObject = mockObject;
@ -99,17 +99,17 @@ define(
expect(mockNavigationService.checkBeforeNavigation)
.toHaveBeenCalledWith(jasmine.any(Function));
var checkFn = mockNavigationService.checkBeforeNavigation.mostRecentCall.args[0];
var checkFn = mockNavigationService.checkBeforeNavigation.calls.mostRecent().args[0];
mockEditorCapability.isEditContextRoot.andReturn(false);
mockEditorCapability.dirty.andReturn(false);
mockEditorCapability.isEditContextRoot.and.returnValue(false);
mockEditorCapability.dirty.and.returnValue(false);
expect(checkFn()).toBe("Continuing will cause the loss of any unsaved changes.");
mockEditorCapability.isEditContextRoot.andReturn(true);
mockEditorCapability.isEditContextRoot.and.returnValue(true);
expect(checkFn()).toBe("Continuing will cause the loss of any unsaved changes.");
mockEditorCapability.dirty.andReturn(true);
mockEditorCapability.dirty.and.returnValue(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.mostRecentCall.args[1]();
mockScope.$on.calls.mostRecent().args[1]();
expect(mockEditorCapability.finish).toHaveBeenCalled();
expect(removeCheck).toHaveBeenCalled();

View File

@ -41,13 +41,13 @@ define(
['getTrueRoot']
);
mockDomainObject.getId.andReturn('test-id');
mockDomainObject.getCapability.andReturn(mockContext);
mockDomainObject.getId.and.returnValue('test-id');
mockDomainObject.getCapability.and.returnValue(mockContext);
// Return a new instance of the root object each time
mockContext.getTrueRoot.andCallFake(function () {
mockContext.getTrueRoot.and.callFake(function () {
var mockRoot = jasmine.createSpyObj('root', ['getId']);
mockRoot.getId.andReturn('root-id');
mockRoot.getId.and.returnValue('root-id');
return mockRoot;
});
@ -63,7 +63,7 @@ define(
});
it("exposes the root object found via the object's context capability", function () {
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockScope.$watch.calls.mostRecent().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.mostRecentCall.args[1](mockDomainObject);
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
firstRoot = controller.getRoot();
// Update!
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockScope.$watch.calls.mostRecent().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.mostRecentCall.args[1](mockDomainObject);
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
firstRoot = controller.getRoot();
// Change the exposed root
mockContext.getTrueRoot.andCallFake(function () {
mockContext.getTrueRoot.and.callFake(function () {
var mockRoot = jasmine.createSpyObj('root', ['getId']);
mockRoot.getId.andReturn('other-root-id');
mockRoot.getId.and.returnValue('other-root-id');
return mockRoot;
});
// Update!
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockScope.$watch.calls.mostRecent().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.andReturn(mockUnlisten);
mockMutationCapability.listen.and.returnValue(mockUnlisten);
mockDomainObject = jasmine.createSpyObj("domainObject", [
"getCapability",
"useCapability"
]);
mockDomainObject.useCapability.andReturn(mockCompositionCapability);
mockDomainObject.getCapability.andReturn(mockMutationCapability);
mockDomainObject.useCapability.and.returnValue(mockCompositionCapability);
mockDomainObject.getCapability.and.returnValue(mockMutationCapability);
mockScope = jasmine.createSpyObj("$scope", ['$on']);
mockSelection = jasmine.createSpyObj("selection", [
@ -77,7 +77,7 @@ define(
'off',
'get'
]);
mockSelection.get.andReturn([]);
mockSelection.get.and.returnValue([]);
mockOpenMCT = {
selection: mockSelection
};
@ -88,7 +88,7 @@ define(
}
};
spyOn(ElementsController.prototype, 'refreshComposition').andCallThrough();
spyOn(ElementsController.prototype, 'refreshComposition').and.callThrough();
controller = new ElementsController(mockScope, mockOpenMCT);
});
@ -123,29 +123,29 @@ define(
});
it("refreshes composition on selection", function () {
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
expect(ElementsController.prototype.refreshComposition).toHaveBeenCalledWith(mockDomainObject);
});
it("listens on mutation and refreshes composition", function () {
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
expect(mockDomainObject.getCapability).toHaveBeenCalledWith('mutation');
expect(mockMutationCapability.listen).toHaveBeenCalled();
expect(ElementsController.prototype.refreshComposition.calls.length).toBe(1);
expect(ElementsController.prototype.refreshComposition.calls.count()).toBe(1);
mockMutationCapability.listen.mostRecentCall.args[0](mockDomainObject);
mockMutationCapability.listen.calls.mostRecent().args[0](mockDomainObject);
expect(ElementsController.prototype.refreshComposition.calls.length).toBe(2);
expect(ElementsController.prototype.refreshComposition.calls.count()).toBe(2);
});
it("cleans up mutation listener when selection changes", function () {
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
expect(mockMutationCapability.listen).toHaveBeenCalled();
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
expect(mockUnlisten).toHaveBeenCalled();
});
@ -156,7 +156,7 @@ define(
elementProxy: {}
}
};
mockOpenMCT.selection.on.mostRecentCall.args[1](selectable);
mockOpenMCT.selection.on.calls.mostRecent().args[1](selectable);
expect(mockDomainObject.getCapability).not.toHaveBeenCalledWith('mutation');
});
@ -167,13 +167,13 @@ define(
firstCompositionCallback,
secondCompositionCallback;
spyOn(mockCompositionCapability, "then").andCallThrough();
spyOn(mockCompositionCapability, "then").and.callThrough();
controller.refreshComposition(mockDomainObject);
controller.refreshComposition(mockDomainObject);
firstCompositionCallback = mockCompositionCapability.then.calls[0].args[0];
secondCompositionCallback = mockCompositionCapability.then.calls[1].args[0];
firstCompositionCallback = mockCompositionCapability.then.calls.all()[0].args[0];
secondCompositionCallback = mockCompositionCapability.then.calls.all()[1].args[0];
secondCompositionCallback(secondMockCompositionObjects);
firstCompositionCallback(mockCompositionObjects);

View File

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

View File

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

View File

@ -77,10 +77,10 @@ define(
"useCapability"
]
);
mockDomainObject.hasCapability.andCallFake(function (name) {
mockDomainObject.hasCapability.and.callFake(function (name) {
return !!capabilities[name];
});
mockDomainObject.getCapability.andCallFake(function (name) {
mockDomainObject.getCapability.and.callFake(function (name) {
return capabilities[name];
});
mockSaveAction = jasmine.createSpyObj(
@ -117,14 +117,14 @@ define(
mockContext = {
domainObject: mockParent
};
mockParent.useCapability.andReturn(mockDomainObject);
mockParent.useCapability.and.returnValue(mockDomainObject);
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({});
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({});
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.andReturn([mockEditAction]);
capabilities.action.getActions.and.returnValue([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.andReturn([]);
capabilities.action.perform.andReturn(mockPromise(undefined));
capabilities.editor.save.andReturn(promise);
capabilities.action.getActions.and.returnValue([]);
capabilities.action.perform.and.returnValue(mockPromise(undefined));
capabilities.editor.save.and.returnValue(promise);
action.perform();
expect(capabilities.action.perform).toHaveBeenCalledWith("save-as");
});
describe("uses to editor capability", function () {
beforeEach(function () {
capabilities.action.getActions.andReturn([]);
capabilities.action.perform.andReturn(promise);
capabilities.editor.save.andReturn(promise);
capabilities.action.getActions.and.returnValue([]);
capabilities.action.perform.and.returnValue(promise);
capabilities.editor.save.and.returnValue(promise);
});
it("to save the edit if user saves dialog", function () {
action.perform();
expect(promise.then).toHaveBeenCalled();
promise.then.mostRecentCall.args[0]();
promise.then.calls.mostRecent().args[0]();
expect(capabilities.editor.save).toHaveBeenCalled();
});
it("to finish the edit if user cancels dialog", function () {
action.perform();
promise.then.mostRecentCall.args[1]();
promise.then.calls.mostRecent().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.andReturn(["a", "b", "c"]);
mockActions.getActions.and.returnValue(["a", "b", "c"]);
// Call the watch
mockScope.$watch.mostRecentCall.args[1]();
mockScope.$watch.calls.mostRecent().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.andReturn({
mockProperty.getDefinition.and.returnValue({
control: "textfield"
});
mockProperty.getValue.andReturn(name);
mockProperty.getValue.and.returnValue(name);
return mockProperty;
}
@ -74,12 +74,12 @@ define(
testModel = { someKey: "some value" };
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);
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);
mockDomainObject = jasmine.createSpyObj(
'domainObject',
@ -87,9 +87,9 @@ define(
);
//Mocking the getCapability('type') call
mockDomainObject.getCapability.andReturn(mockType);
mockDomainObject.useCapability.andReturn();
mockDomainObject.getModel.andReturn(testModel);
mockDomainObject.getCapability.and.returnValue(mockType);
mockDomainObject.useCapability.and.returnValue();
mockDomainObject.getModel.and.returnValue(testModel);
wizard = new CreateWizard(
mockDomainObject,
@ -147,9 +147,11 @@ 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.mostRecentCall.args[1]()).toEqual(compareModel);
expect(mockDomainObject.useCapability.calls.mostRecent().args[1]()).toEqual(compareModel);
});
it("validates selection types using policy", function () {
@ -168,7 +170,7 @@ define(
rows = structure.sections[sections.length - 1].rows,
locationRow = rows[rows.length - 1];
mockDomainObj.getCapability.andReturn(mockOtherType);
mockDomainObj.getCapability.and.returnValue(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.andReturn(true);
mockType.hasFeature.and.returnValue(true);
expect(policy.allow(mockType)).toBeTruthy();
});
it("disallows creation of types without the creation feature", function () {
mockType.hasFeature.andReturn(false);
mockType.hasFeature.and.returnValue(false);
expect(policy.allow(mockType)).toBeFalsy();
});
});

View File

@ -103,33 +103,33 @@ define(
["persist", "getSpace"]
);
mockParentObject.getCapability.andCallFake(function (key) {
mockParentObject.getCapability.and.callFake(function (key) {
return mockCapabilities[key];
});
mockParentObject.useCapability.andCallFake(function (key, value) {
mockParentObject.useCapability.and.callFake(function (key, value) {
return mockCapabilities[key].invoke(value);
});
mockParentObject.getId.andReturn('parentId');
mockParentObject.getId.and.returnValue('parentId');
mockNewObject.getId.andReturn('newId');
mockNewObject.getCapability.andCallFake(function (c) {
mockNewObject.getId.and.returnValue('newId');
mockNewObject.getCapability.and.callFake(function (c) {
return c === 'persistence' ?
mockNewPersistenceCapability : undefined;
});
mockPersistenceCapability.persist
.andReturn(mockPromise(true));
.and.returnValue(mockPromise(true));
mockNewPersistenceCapability.persist
.andReturn(mockPromise(true));
.and.returnValue(mockPromise(true));
mockMutationCapability.invoke.andReturn(mockPromise(true));
mockPersistenceCapability.getSpace.andReturn("testSpace");
mockCompositionCapability.invoke.andReturn(
mockMutationCapability.invoke.and.returnValue(mockPromise(true));
mockPersistenceCapability.getSpace.and.returnValue("testSpace");
mockCompositionCapability.invoke.and.returnValue(
mockPromise([mockNewObject])
);
mockCompositionCapability.add.andReturn(mockPromise(true));
mockCreationCapability.instantiate.andReturn(mockNewObject);
mockCreationCapability.invoke.andCallFake(function (model) {
mockCompositionCapability.add.and.returnValue(mockPromise(true));
mockCreationCapability.instantiate.and.returnValue(mockNewObject);
mockCreationCapability.invoke.and.callFake(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.andCallFake(function (id) {
mockDomainObject.getId.andReturn(id);
mockCompositionCapability.add.and.callFake(function (id) {
mockDomainObject.getId.and.returnValue(id);
mockCompositionCapability.invoke
.andReturn(mockPromise([mockDomainObject]));
.and.returnValue(mockPromise([mockDomainObject]));
return mockPromise(mockDomainObject);
});
@ -200,7 +200,7 @@ define(
// created object - this is an error.
var model = { someKey: "some value" };
mockCompositionCapability.add.andReturn(mockPromise(false));
mockCompositionCapability.add.and.returnValue(mockPromise(false));
creationService.createObject(model, mockParentObject);

View File

@ -64,9 +64,9 @@ define(
["then"]
);
mockDomainObject.getCapability.andReturn(mockContext);
mockContext.getRoot.andReturn(mockRootObject);
mockObjectService.getObjects.andReturn(getObjectsPromise);
mockDomainObject.getCapability.and.returnValue(mockContext);
mockContext.getRoot.and.returnValue(mockRootObject);
mockObjectService.getObjects.and.returnValue(getObjectsPromise);
mockScope.ngModel = {};
mockScope.field = "someField";
@ -76,7 +76,7 @@ define(
describe("when context is available", function () {
beforeEach(function () {
mockContext.getRoot.andReturn(mockRootObject);
mockContext.getRoot.and.returnValue(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.mostRecentCall.args[1](mockDomainObject);
mockTimeout.mostRecentCall.args[0]();
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockTimeout.calls.mostRecent().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.andReturn(false);
mockScope.structure.validate.and.returnValue(false);
// Pass selection change
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockTimeout.mostRecentCall.args[0]();
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockTimeout.calls.mostRecent().args[0]();
expect(mockScope.structure.validate).toHaveBeenCalled();
// Change should have been rejected
@ -126,13 +126,13 @@ define(
['$setValidity']
);
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockTimeout.mostRecentCall.args[0]();
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockTimeout.calls.mostRecent().args[0]();
expect(mockScope.ngModelController.$setValidity)
.toHaveBeenCalledWith(jasmine.any(String), true);
mockScope.$watch.mostRecentCall.args[1](undefined);
mockTimeout.mostRecentCall.args[0]();
mockScope.$watch.calls.mostRecent().args[1](undefined);
mockTimeout.calls.mostRecent().args[0]();
expect(mockScope.ngModelController.$setValidity)
.toHaveBeenCalledWith(jasmine.any(String), false);
});
@ -141,27 +141,27 @@ define(
var defaultRoot = "DEFAULT_ROOT";
beforeEach(function () {
mockContext.getRoot.andReturn(undefined);
getObjectsPromise.then.andCallFake(function (callback) {
mockContext.getRoot.and.returnValue(undefined);
getObjectsPromise.then.and.callFake(function (callback) {
callback({'ROOT': defaultRoot});
});
controller = new LocatorController(mockScope, mockTimeout, mockObjectService);
});
it("provides a default context where none is available", function () {
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
mockTimeout.mostRecentCall.args[0]();
mockScope.$watch.calls.mostRecent().args[1](mockDomainObject);
mockTimeout.calls.mostRecent().args[0]();
expect(mockScope.rootObject).toBe(defaultRoot);
});
it("does not issue redundant requests for the root object", function () {
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)
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())
.toEqual(1);
});

View File

@ -58,10 +58,10 @@ define(
mockEditAction = jasmine.createSpyObj('edit', ['getMetadata']);
mockPropertiesAction = jasmine.createSpyObj('edit', ['getMetadata']);
mockDomainObject.getCapability.andCallFake(function (capability) {
mockDomainObject.getCapability.and.callFake(function (capability) {
return capabilities[capability];
});
mockDomainObject.hasCapability.andCallFake(function (capability) {
mockDomainObject.hasCapability.and.callFake(function (capability) {
return !!capabilities[capability];
});
@ -71,13 +71,13 @@ define(
plotView = { key: "plot", editable: false };
testViews = [];
mockDomainObject.useCapability.andCallFake(function (c) {
mockDomainObject.useCapability.and.callFake(function (c) {
// Provide test views, only for the view capability
return c === 'view' && testViews;
});
mockEditAction.getMetadata.andReturn({ key: 'edit' });
mockPropertiesAction.getMetadata.andReturn({ key: 'properties' });
mockEditAction.getMetadata.and.returnValue({ key: 'edit' });
mockPropertiesAction.getMetadata.and.returnValue({ 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.andReturn(true);
mockEditorCapability.isEditContextRoot.and.returnValue(true);
expect(policy.allow(mockEditAction, testContext)).toBe(false);
});
it("allows editing of panels in plot view", function () {
testViews = [plotView];
mockTypeCapability.getKey.andReturn('telemetry.panel');
mockTypeCapability.getKey.and.returnValue('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.andReturn('something.else');
mockTypeCapability.getKey.and.returnValue('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.andReturn(mockEditorCapability);
navigatedObject.hasCapability.andReturn(false);
navigatedObject.getCapability.and.returnValue(mockEditorCapability);
navigatedObject.hasCapability.and.returnValue(false);
mockDomainObject = jasmine.createSpyObj("domainObject", ["hasCapability", "getCapability"]);
mockDomainObject.hasCapability.andReturn(false);
mockDomainObject.getCapability.andReturn(mockEditorCapability);
mockDomainObject.hasCapability.and.returnValue(false);
mockDomainObject.getCapability.and.returnValue(mockEditorCapability);
navigationService = jasmine.createSpyObj("navigationService", ["getNavigation"]);
navigationService.getNavigation.andReturn(navigatedObject);
navigationService.getNavigation.and.returnValue(navigatedObject);
metadata = {key: "move"};
mockAction = jasmine.createSpyObj("action", ["getMetadata"]);
mockAction.getMetadata.andReturn(metadata);
mockAction.getMetadata.and.returnValue(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.andReturn(true);
mockEditorCapability.isEditContextRoot.andReturn(true);
navigatedObject.hasCapability.and.returnValue(true);
mockEditorCapability.isEditContextRoot.and.returnValue(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.andReturn(true);
mockContextCapability.getParent.andReturn(mockParent);
navigatedObject.hasCapability.andReturn(true);
mockParent.hasCapability.and.returnValue(true);
mockContextCapability.getParent.and.returnValue(mockParent);
navigatedObject.hasCapability.and.returnValue(true);
mockDomainObject.getCapability.andReturn(mockContextCapability);
mockDomainObject.hasCapability.andCallFake(function (capability) {
mockDomainObject.getCapability.and.returnValue(mockContextCapability);
mockDomainObject.hasCapability.and.callFake(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.andReturn(true);
mockEditorCapability.isEditContextRoot.andReturn(true);
mockEditorCapability.inEditContext.andReturn(false);
navigatedObject.hasCapability.and.returnValue(true);
mockEditorCapability.isEditContextRoot.and.returnValue(true);
mockEditorCapability.inEditContext.and.returnValue(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.andReturn(true);
mockDomainObject.hasCapability.andReturn(true);
mockEditorCapability.isEditContextRoot.andReturn(true);
mockEditorCapability.inEditContext.andReturn(true);
navigatedObject.hasCapability.and.returnValue(true);
mockDomainObject.hasCapability.and.returnValue(true);
mockEditorCapability.isEditContextRoot.and.returnValue(true);
mockEditorCapability.inEditContext.and.returnValue(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.andReturn({ key: 'edit' });
mockPropertiesAction.getMetadata.andReturn({ key: 'properties' });
mockOtherAction.getMetadata.andReturn({key: 'other'});
mockEditAction.getMetadata.and.returnValue({ key: 'edit' });
mockPropertiesAction.getMetadata.and.returnValue({ key: 'properties' });
mockOtherAction.getMetadata.and.returnValue({key: 'other'});
mockDomainObject.getId.andReturn('test:testId');
mockDomainObject.getId.and.returnValue('test:testId');
testContext = {
domainObject: mockDomainObject,
@ -69,7 +69,7 @@ define(
});
it("Applies to edit action", function () {
mockObjectAPI.getProvider.andReturn({});
mockObjectAPI.getProvider.and.returnValue({});
expect(mockObjectAPI.getProvider).not.toHaveBeenCalled();
policy.allow(mockEditAction, testContext);
@ -77,7 +77,7 @@ define(
});
it("Applies to properties action", function () {
mockObjectAPI.getProvider.andReturn({});
mockObjectAPI.getProvider.and.returnValue({});
expect(mockObjectAPI.getProvider).not.toHaveBeenCalled();
policy.allow(mockPropertiesAction, testContext);
@ -85,7 +85,7 @@ define(
});
it("does not apply to other actions", function () {
mockObjectAPI.getProvider.andReturn({});
mockObjectAPI.getProvider.and.returnValue({});
expect(mockObjectAPI.getProvider).not.toHaveBeenCalled();
policy.allow(mockOtherAction, testContext);
@ -93,10 +93,10 @@ define(
});
it("Tests object provider for editability", function () {
mockObjectAPI.getProvider.andReturn({});
mockObjectAPI.getProvider.and.returnValue({});
expect(policy.allow(mockEditAction, testContext)).toBe(false);
expect(mockObjectAPI.getProvider).toHaveBeenCalled();
mockObjectAPI.getProvider.andReturn({save: function () {}});
mockObjectAPI.getProvider.and.returnValue({save: function () {}});
expect(policy.allow(mockEditAction, testContext)).toBe(true);
});
});

View File

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

View File

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

View File

@ -1,156 +0,0 @@
/*****************************************************************************
* 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

@ -1,128 +0,0 @@
/*****************************************************************************
* 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,7 +25,10 @@ define(
function (EditToolbar) {
describe("An Edit mode toolbar", function () {
var mockCommit,
var mockOpenMCT,
mockScope,
mockObjects,
mockDomainObject,
testStructure,
testAB,
testABC,
@ -35,35 +38,30 @@ define(
testM,
toolbar;
function getVisibility(obj) {
return !obj.hidden;
}
beforeEach(function () {
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 }
]
}
]
};
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 }
];
testAB = { a: 0, b: 1 };
testABC = { a: 0, b: 1, c: 2 };
testABC2 = { a: 4, b: 1, c: 2 }; // For inconsistent-state checking
@ -71,151 +69,17 @@ define(
testABCYZ = { a: 0, b: 1, c: 2, y: 'Y!', z: 'Z!' };
testM = { m: jasmine.createSpy("method") };
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]);
toolbar = new EditToolbar(mockScope, mockOpenMCT, testStructure);
});
it("adds click functions when a method is specified", function () {
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();
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);
});
});
}

View File

@ -44,10 +44,10 @@ define(
testId = 'test-id';
mockPromise = jasmine.createSpyObj('promise', ['then']);
mockOnCommit.andReturn(mockPromise);
mockOnCancel.andReturn(mockPromise);
mockOnCommit.and.returnValue(mockPromise);
mockOnCancel.and.returnValue(mockPromise);
mockTransactionService.addToTransaction.andCallFake(function () {
mockTransactionService.addToTransaction.and.callFake(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.andReturn(state);
mockTransactionService.isActive.and.returnValue(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
.mostRecentCall.args[0]();
.calls.mostRecent().args[0]();
expect(mockOnCommit).toHaveBeenCalled();
expect(mockOnCancel).not.toHaveBeenCalled();
mockTransactionService.addToTransaction
.mostRecentCall.args[1]();
.calls.mostRecent().args[1]();
expect(mockOnCancel).toHaveBeenCalled();
});
@ -99,7 +99,7 @@ define(
jasmine.createSpy(),
jasmine.createSpy()
);
expect(mockTransactionService.addToTransaction.calls.length)
expect(mockTransactionService.addToTransaction.calls.count())
.toEqual(1);
});
@ -109,7 +109,7 @@ define(
jasmine.createSpy(),
jasmine.createSpy()
);
expect(mockTransactionService.addToTransaction.calls.length)
expect(mockTransactionService.addToTransaction.calls.count())
.toEqual(2);
});

View File

@ -40,7 +40,7 @@ define(
beforeEach(function () {
mockQ = jasmine.createSpyObj("$q", ["all"]);
mockQ.all.andReturn(fastPromise());
mockQ.all.and.returnValue(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.andCallFake(function () {
mockCommit.and.callFake(function () {
throw new Error("test error");
});
transaction.commit();

View File

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

View File

@ -49,6 +49,8 @@ define([
"./src/directives/MCTSplitPane",
"./src/directives/MCTSplitter",
"./src/directives/MCTTree",
"./src/directives/MCTPreview",
"./src/actions/MCTPreviewAction",
"./src/filters/ReverseFilter",
"text!./res/templates/bottombar.html",
"text!./res/templates/controls/action-button.html",
@ -69,6 +71,7 @@ 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,
@ -99,6 +102,8 @@ define([
MCTSplitPane,
MCTSplitter,
MCTTree,
MCTPreview,
MCTPreviewAction,
ReverseFilter,
bottombarTemplate,
actionButtonTemplate,
@ -119,6 +124,7 @@ define([
selectorTemplate,
datetimePickerTemplate,
datetimeFieldTemplate,
previewTemplate,
legacyRegistry
) {
@ -395,7 +401,32 @@ define([
{
"key": "mctTree",
"implementation": MCTTree,
"depends": ['gestureService']
"depends": ['gestureService', '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"
}
],
"constants": [
@ -511,6 +542,10 @@ 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": 1506973656040
"created": 1529545133464
},
"iconSets": [
{
@ -40,7 +40,7 @@
"tempChar": ""
},
{
"order": 44,
"order": 141,
"prevSize": 24,
"name": "icon-arrow-right",
"id": 39,
@ -48,7 +48,7 @@
"tempChar": ""
},
{
"order": 41,
"order": 142,
"prevSize": 24,
"name": "icon-arrow-double-up",
"id": 36,
@ -213,7 +213,7 @@
"tempChar": ""
},
{
"order": 29,
"order": 144,
"prevSize": 24,
"name": "icon-person",
"id": 24,
@ -221,7 +221,7 @@
"tempChar": ""
},
{
"order": 86,
"order": 147,
"prevSize": 24,
"name": "icon-plus",
"id": 81,
@ -268,13 +268,21 @@
"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,
@ -282,7 +290,7 @@
"name": "icon-arrows-right-left",
"id": 44,
"code": 921601,
"tempChar": ""
"tempChar": ""
},
{
"order": 50,
@ -290,7 +298,7 @@
"name": "icon-arrows-up-down",
"id": 45,
"code": 921602,
"tempChar": ""
"tempChar": ""
},
{
"order": 9,
@ -298,7 +306,7 @@
"name": "icon-bullet",
"id": 4,
"code": 921604,
"tempChar": ""
"tempChar": ""
},
{
"order": 25,
@ -306,7 +314,7 @@
"name": "icon-calendar",
"id": 20,
"code": 921605,
"tempChar": ""
"tempChar": ""
},
{
"order": 30,
@ -314,7 +322,7 @@
"name": "icon-chain-links",
"id": 25,
"code": 921606,
"tempChar": ""
"tempChar": ""
},
{
"order": 109,
@ -322,7 +330,7 @@
"prevSize": 24,
"code": 921607,
"name": "icon-pane-collapse-left",
"tempChar": ""
"tempChar": ""
},
{
"order": 110,
@ -330,7 +338,7 @@
"prevSize": 24,
"code": 921608,
"name": "icon-pane-collapse-right",
"tempChar": ""
"tempChar": ""
},
{
"order": 5,
@ -338,7 +346,7 @@
"prevSize": 24,
"code": 921609,
"name": "icon-download",
"tempChar": ""
"tempChar": ""
},
{
"order": 60,
@ -346,7 +354,7 @@
"name": "icon-duplicate",
"id": 55,
"code": 921616,
"tempChar": ""
"tempChar": ""
},
{
"order": 61,
@ -354,7 +362,7 @@
"name": "icon-folder-new",
"id": 56,
"code": 921617,
"tempChar": ""
"tempChar": ""
},
{
"order": 64,
@ -362,7 +370,7 @@
"name": "icon-fullscreen-expand",
"id": 59,
"code": 921618,
"tempChar": ""
"tempChar": ""
},
{
"order": 63,
@ -370,7 +378,7 @@
"name": "icon-fullscreen-collapse",
"id": 58,
"code": 921619,
"tempChar": ""
"tempChar": ""
},
{
"order": 67,
@ -378,23 +386,23 @@
"name": "icon-layers",
"id": 62,
"code": 921620,
"tempChar": ""
"tempChar": ""
},
{
"order": 69,
"order": 145,
"prevSize": 24,
"name": "icon-line-horz",
"id": 64,
"code": 921621,
"tempChar": ""
"tempChar": ""
},
{
"order": 73,
"order": 146,
"prevSize": 24,
"name": "icon-magnify",
"id": 68,
"code": 921622,
"tempChar": ""
"tempChar": ""
},
{
"order": 71,
@ -402,7 +410,7 @@
"name": "icon-magnify-in",
"id": 66,
"code": 921623,
"tempChar": ""
"tempChar": ""
},
{
"order": 72,
@ -410,7 +418,7 @@
"name": "icon-magnify-out",
"id": 67,
"code": 921624,
"tempChar": ""
"tempChar": ""
},
{
"order": 74,
@ -418,7 +426,7 @@
"name": "icon-menu",
"id": 69,
"code": 921625,
"tempChar": ""
"tempChar": ""
},
{
"order": 75,
@ -426,7 +434,7 @@
"name": "icon-move",
"id": 70,
"code": 921632,
"tempChar": ""
"tempChar": ""
},
{
"order": 76,
@ -434,7 +442,7 @@
"name": "icon-new-window",
"id": 71,
"code": 921633,
"tempChar": ""
"tempChar": ""
},
{
"order": 26,
@ -442,7 +450,7 @@
"name": "icon-paint-bucket",
"id": 21,
"code": 921634,
"tempChar": ""
"tempChar": ""
},
{
"order": 81,
@ -450,7 +458,7 @@
"name": "icon-pause",
"id": 76,
"code": 921635,
"tempChar": ""
"tempChar": ""
},
{
"order": 82,
@ -458,7 +466,7 @@
"name": "icon-pencil",
"id": 77,
"code": 921636,
"tempChar": ""
"tempChar": ""
},
{
"order": 84,
@ -466,7 +474,7 @@
"name": "icon-play",
"id": 79,
"code": 921637,
"tempChar": ""
"tempChar": ""
},
{
"order": 85,
@ -474,7 +482,7 @@
"name": "icon-plot-resource",
"id": 80,
"code": 921638,
"tempChar": ""
"tempChar": ""
},
{
"order": 27,
@ -482,7 +490,7 @@
"name": "icon-pointer-left",
"id": 22,
"code": 921639,
"tempChar": ""
"tempChar": ""
},
{
"order": 28,
@ -490,7 +498,7 @@
"name": "icon-pointer-right",
"id": 23,
"code": 921640,
"tempChar": ""
"tempChar": ""
},
{
"order": 32,
@ -498,7 +506,7 @@
"name": "icon-refresh",
"id": 27,
"code": 921641,
"tempChar": ""
"tempChar": ""
},
{
"order": 16,
@ -506,7 +514,7 @@
"name": "icon-save",
"id": 11,
"code": 921648,
"tempChar": ""
"tempChar": ""
},
{
"order": 88,
@ -514,7 +522,7 @@
"name": "icon-sine",
"id": 83,
"code": 921649,
"tempChar": ""
"tempChar": ""
},
{
"order": 102,
@ -522,7 +530,7 @@
"name": "icon-T",
"id": 84,
"code": 921650,
"tempChar": ""
"tempChar": ""
},
{
"order": 92,
@ -530,7 +538,7 @@
"name": "icon-thumbs-strip",
"id": 87,
"code": 921651,
"tempChar": ""
"tempChar": ""
},
{
"order": 96,
@ -538,7 +546,7 @@
"name": "icon-two-parts-both",
"id": 91,
"code": 921652,
"tempChar": ""
"tempChar": ""
},
{
"order": 97,
@ -546,7 +554,7 @@
"name": "icon-two-parts-one-only",
"id": 92,
"code": 921653,
"tempChar": ""
"tempChar": ""
},
{
"order": 21,
@ -554,7 +562,7 @@
"name": "icon-resync",
"id": 16,
"code": 921654,
"tempChar": ""
"tempChar": ""
},
{
"order": 120,
@ -562,7 +570,7 @@
"name": "icon-reset",
"prevSize": 24,
"code": 921655,
"tempChar": ""
"tempChar": ""
},
{
"order": 121,
@ -570,7 +578,7 @@
"name": "icon-x-in-circle",
"prevSize": 24,
"code": 921656,
"tempChar": ""
"tempChar": ""
},
{
"order": 118,
@ -578,7 +586,7 @@
"name": "icon-brightness",
"prevSize": 24,
"code": 921657,
"tempChar": ""
"tempChar": ""
},
{
"order": 119,
@ -586,7 +594,7 @@
"name": "icon-contrast",
"prevSize": 24,
"code": 921664,
"tempChar": ""
"tempChar": ""
},
{
"order": 124,
@ -594,7 +602,7 @@
"name": "icon-expand",
"prevSize": 24,
"code": 921665,
"tempChar": ""
"tempChar": ""
},
{
"order": 125,
@ -602,7 +610,7 @@
"name": "icon-list-view",
"prevSize": 24,
"code": 921666,
"tempChar": ""
"tempChar": ""
},
{
"order": 133,
@ -610,7 +618,7 @@
"name": "icon-grid-snap-to",
"prevSize": 24,
"code": 921667,
"tempChar": ""
"tempChar": ""
},
{
"order": 128,
@ -618,7 +626,7 @@
"name": "icon-grid-snap-no",
"prevSize": 24,
"code": 921668,
"tempChar": ""
"tempChar": ""
},
{
"order": 131,
@ -626,7 +634,7 @@
"name": "icon-frame-show",
"prevSize": 24,
"code": 921669,
"tempChar": ""
"tempChar": ""
},
{
"order": 130,
@ -634,7 +642,7 @@
"name": "icon-frame-hide",
"prevSize": 24,
"code": 921670,
"tempChar": ""
"tempChar": ""
},
{
"order": 138,
@ -642,7 +650,7 @@
"name": "icon-import",
"prevSize": 24,
"code": 921671,
"tempChar": ""
"tempChar": ""
},
{
"order": 136,
@ -650,7 +658,7 @@
"name": "icon-export",
"prevSize": 24,
"code": 921672,
"tempChar": ""
"tempChar": ""
},
{
"order": 37,
@ -658,7 +666,7 @@
"name": "icon-activity",
"id": 32,
"code": 921856,
"tempChar": ""
"tempChar": ""
},
{
"order": 36,
@ -666,7 +674,7 @@
"name": "icon-activity-mode",
"id": 31,
"code": 921857,
"tempChar": ""
"tempChar": ""
},
{
"order": 52,
@ -674,7 +682,7 @@
"name": "icon-autoflow-tabular",
"id": 47,
"code": 921858,
"tempChar": ""
"tempChar": ""
},
{
"order": 55,
@ -682,7 +690,7 @@
"name": "icon-clock",
"id": 50,
"code": 921859,
"tempChar": ""
"tempChar": ""
},
{
"order": 58,
@ -690,7 +698,7 @@
"name": "icon-database",
"id": 53,
"code": 921860,
"tempChar": ""
"tempChar": ""
},
{
"order": 57,
@ -698,7 +706,7 @@
"name": "icon-database-query",
"id": 52,
"code": 921861,
"tempChar": ""
"tempChar": ""
},
{
"order": 17,
@ -706,7 +714,7 @@
"name": "icon-dataset",
"id": 12,
"code": 921862,
"tempChar": ""
"tempChar": ""
},
{
"order": 22,
@ -714,7 +722,7 @@
"name": "icon-datatable",
"id": 17,
"code": 921863,
"tempChar": ""
"tempChar": ""
},
{
"order": 59,
@ -722,7 +730,7 @@
"name": "icon-dictionary",
"id": 54,
"code": 921864,
"tempChar": ""
"tempChar": ""
},
{
"order": 62,
@ -730,7 +738,7 @@
"name": "icon-folder",
"id": 57,
"code": 921865,
"tempChar": ""
"tempChar": ""
},
{
"order": 66,
@ -738,7 +746,7 @@
"name": "icon-image",
"id": 61,
"code": 921872,
"tempChar": ""
"tempChar": ""
},
{
"order": 68,
@ -746,7 +754,7 @@
"name": "icon-layout",
"id": 63,
"code": 921873,
"tempChar": ""
"tempChar": ""
},
{
"order": 77,
@ -754,7 +762,7 @@
"name": "icon-object",
"id": 72,
"code": 921874,
"tempChar": ""
"tempChar": ""
},
{
"order": 78,
@ -762,7 +770,7 @@
"name": "icon-object-unknown",
"id": 73,
"code": 921875,
"tempChar": ""
"tempChar": ""
},
{
"order": 79,
@ -770,7 +778,7 @@
"name": "icon-packet",
"id": 74,
"code": 921876,
"tempChar": ""
"tempChar": ""
},
{
"order": 80,
@ -778,7 +786,7 @@
"name": "icon-page",
"id": 75,
"code": 921877,
"tempChar": ""
"tempChar": ""
},
{
"order": 135,
@ -786,7 +794,7 @@
"name": "icon-plot-overlay",
"prevSize": 24,
"code": 921878,
"tempChar": ""
"tempChar": ""
},
{
"order": 113,
@ -794,7 +802,7 @@
"name": "icon-plot-stacked",
"prevSize": 24,
"code": 921879,
"tempChar": ""
"tempChar": ""
},
{
"order": 10,
@ -802,7 +810,7 @@
"name": "icon-session",
"id": 5,
"code": 921880,
"tempChar": ""
"tempChar": ""
},
{
"order": 24,
@ -810,7 +818,7 @@
"name": "icon-tabular",
"id": 19,
"code": 921881,
"tempChar": ""
"tempChar": ""
},
{
"order": 7,
@ -818,7 +826,7 @@
"name": "icon-tabular-lad",
"id": 2,
"code": 921888,
"tempChar": ""
"tempChar": ""
},
{
"order": 6,
@ -826,7 +834,7 @@
"name": "icon-tabular-lad-set",
"id": 1,
"code": 921889,
"tempChar": ""
"tempChar": ""
},
{
"order": 8,
@ -834,7 +842,7 @@
"name": "icon-tabular-realtime",
"id": 3,
"code": 921890,
"tempChar": ""
"tempChar": ""
},
{
"order": 23,
@ -842,7 +850,7 @@
"name": "icon-tabular-scrolling",
"id": 18,
"code": 921891,
"tempChar": ""
"tempChar": ""
},
{
"order": 112,
@ -850,7 +858,7 @@
"name": "icon-telemetry",
"id": 86,
"code": 921892,
"tempChar": ""
"tempChar": ""
},
{
"order": 90,
@ -858,7 +866,7 @@
"name": "icon-telemetry-panel",
"id": 85,
"code": 921893,
"tempChar": ""
"tempChar": ""
},
{
"order": 93,
@ -866,7 +874,7 @@
"name": "icon-timeline",
"id": 88,
"code": 921894,
"tempChar": ""
"tempChar": ""
},
{
"order": 116,
@ -874,7 +882,7 @@
"name": "icon-timer-v1.5",
"prevSize": 24,
"code": 921895,
"tempChar": ""
"tempChar": ""
},
{
"order": 11,
@ -882,7 +890,7 @@
"name": "icon-topic",
"id": 6,
"code": 921896,
"tempChar": ""
"tempChar": ""
},
{
"order": 115,
@ -890,7 +898,7 @@
"name": "icon-box-with-dashed-lines",
"id": 29,
"code": 921897,
"tempChar": ""
"tempChar": ""
},
{
"order": 126,
@ -898,7 +906,7 @@
"name": "icon-summary-widget",
"prevSize": 24,
"code": 921904,
"tempChar": ""
"tempChar": ""
},
{
"order": 139,
@ -906,7 +914,7 @@
"name": "icon-notebook",
"prevSize": 24,
"code": 921905,
"tempChar": ""
"tempChar": ""
}
],
"metadata": {
@ -1639,6 +1647,26 @@
]
}
},
{
"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",
@ -1938,7 +1966,7 @@
},
{
"paths": [
"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"
"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"
],
"grid": 16,
"tags": [
@ -1946,15 +1974,26 @@
],
"defaultCode": 77,
"id": 68,
"attrs": [],
"attrs": [
{
"fill": "rgb(0, 161, 75)"
}
],
"isMulticolor": false,
"isMulticolor2": false,
"colorPermutations": {
"1161751207457516161751": []
"1161751207457516161751": [
{
"f": 1
}
]
}
},
{
"paths": [
"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"
"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"
],
"grid": 16,
"tags": [
@ -1962,15 +2001,37 @@
],
"defaultCode": 88,
"id": 66,
"attrs": [],
"attrs": [
{
"fill": "rgb(0, 161, 75)"
},
{
"fill": "rgb(0, 161, 75)"
},
{
"fill": "rgb(0, 161, 75)"
}
],
"isMulticolor": false,
"isMulticolor2": false,
"colorPermutations": {
"1161751207457516161751": []
"1161751207457516161751": [
{
"f": 1
},
{
"f": 1
},
{
"f": 1
}
]
}
},
{
"paths": [
"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"
"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"
],
"grid": 16,
"tags": [
@ -1978,16 +2039,32 @@
],
"defaultCode": 89,
"id": 67,
"attrs": [],
"attrs": [
{
"fill": "rgb(0, 161, 75)"
},
{
"fill": "rgb(0, 161, 75)"
}
],
"isMulticolor": false,
"isMulticolor2": false,
"colorPermutations": {
"1161751207457516161751": []
"1161751207457516161751": [
{
"f": 1
},
{
"f": 1
}
]
}
},
{
"paths": [
"M0 0h1024v256h-1024v-256z",
"M0 384h1024v256h-1024v-256z",
"M0 768h1024v256h-1024v-256z"
"M0 128h1024v128h-1024v-128z",
"M0 448h1024v128h-1024v-128z",
"M0 768h1024v128h-1024v-128z"
],
"grid": 16,
"tags": [
@ -1995,9 +2072,19 @@
],
"defaultCode": 109,
"id": 69,
"attrs": [],
"attrs": [
{},
{},
{}
],
"isMulticolor": false,
"isMulticolor2": false,
"colorPermutations": {
"1161751207457516161751": []
"1161751207457516161751": [
{},
{},
{}
]
}
},
{

View File

@ -39,6 +39,7 @@
<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" />
@ -54,10 +55,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-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="&#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="&#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,3 +157,57 @@
.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,25 +37,9 @@
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: 22px;
$uePaneMiniTabW: 8px;
$uePaneMiniTabFontSize: 8px;
$uePaneMiniTabCollapsedW: 18px;
$uePaneMiniTabH: 36px;
$uePaneMiniTabW: 10px;
$uePaneMiniTabFontSize: 9px;
$uePaneMiniTabCollapsedW: 22px;
$ueEditLeftPaneW: 75%;
$treeSearchInputBarH: 25px;
/*************** Panes */
@ -70,7 +70,7 @@ $ueBrowseGridItemTopBarH: 20px;
$ueBrowseGridItemBottomBarH: 30px;
$itemPadLR: 5px;
/*************** Tree */
$treeVCW: 10px;
$treeVCW: 16px;
$treeTypeIconH: 1.4em; // was 16px
$treeTypeIconHPx: 16px;
$treeTypeIconW: 18px;
@ -111,7 +111,7 @@ $bubbleMaxW: 300px;
$reqSymbolW: 15px;
$reqSymbolM: $interiorMargin * 2;
$reqSymbolFontSize: 0.75em;
$inputTextPTopBtm: 3px;
$inputTextPTopBtm: 2px;
$inputTextPLeftRight: 5px;
$inputTextP: $inputTextPTopBtm $inputTextPLeftRight;
/*************** Wait Spinner Defaults */
@ -132,7 +132,7 @@ $menuLineHPx: 24px;
$btnStdH: 25px;
$btnToolbarH: $btnStdH;
$controlBarH: $btnStdH;
$btnFrameH: 16px;
$btnFrameH: 18px;
/************************** PATHS */
// Paths need to be relative to /platform/commonUI/theme/<theme-name>/css/ directory

View File

@ -141,7 +141,6 @@ 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;
}
@ -200,7 +199,16 @@ a.disabled {
}
.vscroll {
overflow-x: hidden;
overflow-y: auto;
&.scroll-pad {
padding-right: $interiorMargin;
}
}
.vscroll--persist {
overflow-x: hidden;
overflow-y: scroll;
}
.slidable {
@ -224,8 +232,13 @@ a.disabled {
box-shadow: rgba(#000, 0.7) 0 4px 10px 2px;
}
.capitalize {
text-transform: capitalize;
}
.hide,
.hidden {
.hidden,
.t-main-view .hide-in-t-main-view {
display: none !important;
}
@ -234,14 +247,16 @@ a.disabled {
pointer-events: none;
}
.off {
.invisible {
display: block;
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,6 +33,14 @@
}
}
[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';
@ -67,6 +75,7 @@ $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';
@ -182,6 +191,7 @@ $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,23 +19,15 @@
* 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;
@ -50,80 +42,48 @@
}
}
}
.l-inspector-part {
box-sizing: border-box;
padding-right: $interiorMargin;
.tree .form {
display: contents;
}
.tree {
.grid-properties {
margin-left: $treeVCW + $interiorMarginLg;
}
.section-header {
background: none;
color: $colorInspectorPropName;
border-radius: unset;
font-size: inherit;
padding: $interiorMarginSm 0;
}
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%;
}
}
}
}
ul li,
em.t-inspector-part-header {
display: block;
position: relative;
}
ul li {
margin-bottom: $interiorMarginLg;
}
em.t-inspector-part-header {
border-radius: $basicCr;
background-color: $colorInspectorSectionHeaderBg;
color: $colorInspectorSectionHeaderFg;
margin-bottom: $interiorMargin;
padding: floor($formTBPad * .75) $formLRPad;
text-transform: uppercase;
}
.inspector-properties {
&:not(.first) {
border-top: 1px solid $colorInspectorSectionHeaderBg;
}
padding: $interiorMarginSm 0;
.grid-properties {
.label {
color: $colorInspectorPropName;
text-transform: uppercase;
}
.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;
}
}
}
.inspector-location {
display: inline-block;
}
h2 {
// Headers for .l-inspector-part elements
@extend .grid-two-column-span-cols;
border-radius: $controlCr;
background-color: $colorInspectorSectionHeaderBg;
color: $colorInspectorSectionHeaderFg;
font-size: 0.8rem;
font-weight: normal;
margin: $interiorMarginLg 0 $interiorMarginSm 0;
padding: floor($formTBPad * .75) $formLRPad;
text-transform: uppercase;
&.first {
margin-top: 0;
}
}
@ -162,6 +122,34 @@
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

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

View File

@ -271,36 +271,3 @@
@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,11 +34,6 @@ $pad: $interiorMargin * $baseRatio;
line-height: $btnStdH;
padding: 0 $pad;
&.labeled:before {
// Icon when it's included
margin-right: $interiorMarginSm;
}
&.lg {
font-size: 1rem;
}
@ -59,6 +54,10 @@ $pad: $interiorMargin * $baseRatio;
.label, .title-label { display: none; }
}
&[disabled="true"] {
opacity: 0.3;
}
&.pause-play {
@extend .icon-pause;
&.paused {
@ -114,10 +113,11 @@ 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;
margin-left: 1px !important;
}
> .s-button {

View File

@ -128,28 +128,72 @@
}
}
.l-local-controls {
// Control shown when hovering over an object, like plots and imagery
// Default position is upper right
$p: $interiorMargin;
position: absolute;
top: $p; right: $p; bottom: auto;
text-align: right;
z-index: 5;
/******************************************************** LOCAL CONTROLS */
// Controls placed in proximity to or overlaid on components and views
.local-controls-hidden {
// Used within .has-local-controls, hidden by default
}
.s-local-controls {
@include trans-prop-nice(opacity);
body.desktop .has-local-controls {
// Helper class, provides hover ability to show local controls
&:hover .local-controls-hidden {
@include trans-prop-nice($props: opacity, $dur: 50ms);
opacity: 1;
pointer-events: inherit;
}
.local-controls-hidden {
@include trans-prop-nice($props: opacity, $dur: 500ms);
opacity: 0;
pointer-events: none;
}
}
.h-local-controls {
// An explicit outer holder for controls. Typically placed in upper right.
align-items: center;
font-size: 0.7rem;
&.s-wrapper-transluc {
// Semi-opaque wrapper to visually distinguish a control
// from the background
background: rgba($colorTransLucBg, 0.7);
display: flex;
flex-direction: row;
justify-content: flex-end;
&.h-local-controls-overlay-content {
$p: $interiorMargin;
position: absolute;
top: $p; right: $p;
z-index: 2;
}
.l-btn-set,
.s-button {
&:not(:first-child) {
margin-left: $interiorMargin;
}
}
}
.h-local-controls-overlay-content {
background: $colorBodyBg;
border-radius: $controlCr + 1;
box-sizing: border-box;
border-radius: $controlCr;
padding: 1px;
.s-button {
background: $colorBtnBg;
}
}
.h-local-controls-trans {
background: rgba($colorTransLucBg, 0.5);
padding: $interiorMargin;
}
/******************************************************** VIEW CONTROLS */
// Expand/collapse > and v arrows, used in tree and plot legend
// Moved this over from a tree-only context 5/18/17
@ -159,10 +203,11 @@
cursor: pointer;
height: 1em; width: 1em;
line-height: inherit;
position: relative;
&:before {
position: absolute;
@include trans-prop-nice(transform, 100ms);
content: $glyph-icon-arrow-right;
content: $glyph-icon-arrow-right-equilateral;
@include transform-origin(center);
}
&.expanded:before {
@ -338,6 +383,7 @@ input[type="text"].s-input-inline,
@include btnSubtle($bg: $colorSelectBg);
@extend .icon-arrow-down; // Context arrow
display: inline-block;
flex: 0 0 auto; // When used in a flex context, controls need to hold their width
padding: 0 $interiorMargin;
overflow: hidden;
position: relative;
@ -760,13 +806,17 @@ textarea {
@extend .icon-arrow-right;
cursor: pointer;
font-size: 0.75em;
width: $treeVCW;
&:before {
// Arrow glyph
left: 50%;
position: absolute;
@include trans-prop-nice(transform, 100ms);
transform: translateX(-50%);
transform-origin: center;
}
&.expanded:before {
transform: rotate(90deg);
transform: translateX(-50%) rotate(90deg);
}
}

View File

@ -11,7 +11,6 @@
}
min-width: 150px;
.l-image-main {
background-color: $colorPlotBg;
margin-bottom: $interiorMargin;
}
.l-image-main-controlbar {
@ -76,6 +75,7 @@
}
.s-image-main {
background-color: $colorPlotBg;
border: 1px solid transparent;
&.paused {
@extend .s-unsynced;
@ -138,10 +138,14 @@
}
/*************************************** LOCAL CONTROLS */
.l-local-controls {
.t-imagery {
.h-local-controls.h-local-controls-overlay-content {
max-width: 200px;
min-width: 100px;
width: 35%;
align-items: center;
padding: $interiorMargin $interiorMarginLg;
input[type="range"] {
display: block;
width: 100%;
@ -175,17 +179,10 @@
margin-top: 2px;
}
}
&.s-wrapper-transluc {
left: auto;
padding: $interiorMargin $interiorMarginLg;
}
&.l-flex-row {
align-items: center;
}
}
/*************************************** WHEN IN FRAME */
.frame .t-imagery {
.l-image-main-wrapper {

View File

@ -41,6 +41,7 @@
width: 100%;
.l-form-section {
margin-bottom: $interiorMarginLg * 2;
position: relative;
&.grows {
.l-section-body,
@ -57,7 +58,6 @@
$m: $interiorMargin;
box-sizing: border-box;
border-top: 1px solid $colorFormLines;
margin-bottom: $interiorMarginLg * 2;
padding: $formTBPad 0;
position: relative;
@ -132,6 +132,7 @@
width: auto;
order: 2;
}
>.control,
>.controls {
flex: 0 0 auto;
margin-right: $interiorMargin;
@ -258,8 +259,9 @@
}
}
}
}
.form-error {
.form-error {
// Block element that visually flags an error and contains a message
background-color: $colorFormFieldErrorBg;
color: $colorFormFieldErrorFg;
@ -268,9 +270,8 @@
padding: 1px 6px;
&:before {
content: $glyph-icon-alert-triangle;
display: inline;
display: inline-block;
font-family: symbolsfont;
margin-right: $interiorMarginSm;
}
}
}

View File

@ -87,7 +87,6 @@
$iconD: $formInputH - ($iconEdgeM * 2);
@extend .icon-magnify;
// Adds a magnifying glass before, holds an input and a clear button
display: inline-block;
position: relative;
input[type="search"] {
@ -97,6 +96,7 @@
.menu-icon,
&:before {
box-sizing: border-box;
color: $colorInputIcon;
display: inline-block;
line-height: inherit;
position: absolute;
@ -107,11 +107,16 @@
&:before {
// Magnify glass icon
opacity: 0.7;
left: $interiorMargin;
@include trans-prop-nice(color, 250ms);
@include trans-prop-nice(opacity, 250ms);
pointer-events: none;
}
&:hover:before {
opacity: 1;
}
.clear-icon {
right: $iconEdgeM;
// Icon is visible only when there is text input

View File

@ -26,6 +26,20 @@
.tabular-holder {
@include absPosDefault();
display: flex;
flex-flow: column nowrap;
justify-content: flex-start;
> * {
position: relative;
flex: 0 0 auto;
}
&.l-sticky-headers {
.l-tabular-body {
flex: 1 1 99%;
overflow-x: auto;
}
}
}
.tabular,
@ -41,19 +55,20 @@ table {
tbody tr, .tbody .tr {
width: 100%;
}
thead, .thead {
border-bottom: 1px solid $colorTabHeaderBorder;
}
&:not(.fixed-header) tr th {
thead tr th {
// Add some bg to the headers. Note that this is overwritten below
// by .mct-table-headers-w when headers are wrapped by that container.
background-color: $colorTabHeaderBg;
}
tbody, .tbody {
display: table-row-group;
}
tr, .tr {
border-top: 1px solid $colorTabBorder;
}
}
tr, .tr {
display: table-row;
&:first-child .td {
border-top: none;
@ -118,41 +133,40 @@ table {
tbody, .tbody {
top: $tabularHeaderH * 2;
}
input[type="text"] {
.l-filter {
input[type="text"],
input[type="search"] {
$p: 20px;
transition: padding 200ms ease-in-out;
box-sizing: border-box;
padding-right: $p; // Fend off from icon
padding-left: $p; // Fend off from icon
width: 100%;
}
&.active {
// When user has typed something, hide the icon and collapse left padding
&:before {
opacity: 0;
}
input[type="text"],
input[type="search"] {
padding-left: $interiorMargin;
}
}
}
}
&.fixed-header {
height: 100%;
thead, .thead,
tbody tr, .tbody .tr {
display: table;
table-layout: fixed;
}
thead, .thead {
width: calc(100% - 10px);
&:before {
content: "";
display: block;
z-index: 0;
position: absolute;
width: 100%;
height: $tabularHeaderH;
background-color: $colorTabHeaderBg;
}
}
tbody, .tbody {
@include absPosDefault(0);
top: $tabularHeaderH;
display: block;
overflow-y: scroll;
}
}
&.t-event-messages {
td, .td {
min-width: 150px;
}
}
}
.mct-table-headers-w {
background: $colorTabHeaderBg;
overflow: hidden;
thead tr th {
background: none;
}
}

View File

@ -71,8 +71,8 @@ body.mobile {
.pane.left.treeview {
@include trans-prop-nice(opacity, 250ms, $delay: 250ms);
@include background-image(linear-gradient(90deg, rgba(black, 0) 98%, rgba(black, 0.3) 100%));
width: $proporMenuWithView !important;
right: auto !important;
width: $proporMenuWithView !important;
}
// Sets the right representation when the tree is shown.
.pane.right.items {
@ -91,7 +91,7 @@ body.mobile {
.object-browse-bar {
&.t-primary {
margin-left: 45px;
margin-left: 30px;
.title-label {
// Prevent inline editing of the object title in the main view in mobile
@ -136,20 +136,19 @@ body.mobile {
}
}
@media only screen and (max-device-width: $phoMaxW) and (orientation: portrait) {
body.mobile {
body.phone.portrait {
.pane-tree-showing {
.pane.left.treeview {
width: $proporMenuOnly !important;
}
.pane.right.items {
left: 0 !important;
transform: translateX($proporMenuOnly);
.holder-object-and-inspector {
opacity: 0;
}
}
}
}
}
body.desktop {

View File

@ -34,18 +34,7 @@ body.touch {
line-height: $mobileTreeItemH !important;
.view-control {
font-size: 1em;
margin-right: $interiorMargin;
width: ceil($mobileTreeItemH * 0.75);
&.has-children {
&:before {
content: $glyph-icon-arrow-down;
left: 50%;
transform: translateX(-50%) rotate(-90deg);
}
&.expanded:before {
transform: translateX(-50%) rotate(0deg);
}
}
}
.t-object-label {
line-height: inherit;

View File

@ -246,21 +246,6 @@
}
}
.gl-plot-display-area,
.plot-display-area,
.gl-plot-axis-area {
.gl-plot-local-controls,
.l-local-controls {
@include trans-prop-nice(opacity, 150ms);
opacity: 0;
pointer-events: none;
}
&:hover .gl-plot-local-controls,
&:hover .l-local-controls {
opacity: 1;
pointer-events: inherit;
}
}
.gl-plot-display-area,
.plot-display-area {

View File

@ -26,65 +26,59 @@
@include trans-prop-nice((opacity, color), 150ms);
}
.holder-search {
$iconWidth: 20px;
.search-bar {
$textInputHeight: 19px; // This is equal to the default value, 19px
$iconEdgeM: 4px;
$iconD: $treeSearchInputBarH - ($iconEdgeM*2);
@extend .icon-magnify;
font-size: 0.8em;
.c-search-btn-wrapper,
.c-search {
display: flex;
flex-flow: row nowrap;
align-items: center;
position: relative;
.search-input {
height: $treeSearchInputBarH;
line-height: $treeSearchInputBarH;
> * {
&:not(:first-child) { margin-left: $interiorMargin; }
}
}
.c-search-btn-wrapper {
// Holds c-search and Cancel button
//@include test();
&.holder {
margin-bottom: $interiorMargin;
}
&:before,
.clear-input,
.menu-icon {
// :before is magnify glass icon
box-sizing: border-box;
color: $colorInputIcon;
height: $iconD;
width: $iconD;
line-height: $iconD;
position: absolute;
text-align: center;
top: $iconEdgeM;
}
}
.search-input {
.c-search {
// New approach to search and filter inputs
// Block element
// Holds magnify glass icon, html input, cancel button, etc.
$m: $interiorMarginSm;
@include nice-input();
flex: 1 1 99%;
font-size: 0.8rem;
height: $btnStdH;
padding: 1px $interiorMargin;
> * {
display: inline-block;
flex: 0 0 auto;
position: relative;
width: 100%;
padding-left: $iconD + $interiorMargin !important;
padding-right: ($iconD * 2) + ($interiorMargin * 2) !important;
// Make work for mct-control textfield
input {
width: inherit; // was 100%
}
}
&:before {
// Magnify glass icon
left: $interiorMarginSm;
@include trans-prop-nice(color, 250ms);
content: $glyph-icon-magnify;
font-family: symbolsfont;
opacity: 0.3;
pointer-events: none;
z-index: 1;
transition: opacity 500ms;
}
// Make icon lighten when hovering over search bar
&:hover:before {
color: pullForward($colorInputIcon, 10%);
opacity: 0.6;
}
}
.clear-input {
// Hiding for now with addition of Cancel button
right: $iconD + $interiorMargin;
.c-search__clear-input {
// Icon is visible only when there is text input
visibility: hidden;
opacity: 0;
@ -94,39 +88,43 @@
}
&:hover {
color: pullForward($colorInputIcon, 10%);
}
opacity: 1;
}
}
.menu-icon {
// 'v' invoke menu icon
font-size: 0.8em;
padding-right: $iconEdgeM;
right: $iconEdgeM;
text-align: right;
&:hover {
color: pullForward($colorInputIcon, 10%);
}
}
input.c-search__search-input {
background: none !important;
box-shadow: none !important; // !important needed to override default for [input]
flex: 1 1 99%;
min-width: 10px;
width: 100%;
}
.search-menu-holder {
float: right;
left: -20px;
.c-search__search-menu-holder {
left: 100%;
position: absolute;
transform: translate(-30px, 10px);
z-index: 70;
transition: visibility .05s, opacity .05s;
}
}
.holder-search {
$iconWidth: 20px;
.c-search-btn-wrapper {
margin-right: $interiorMarginLg; // Fend off rights side from pane splitter control
}
.results-msg {
font-size: 0.8rem;
opacity: 0.6;
}
.active-filter-display {
$s: 0.7em;
$s: 0.7rem;
$p: $interiorMargin;
box-sizing: border-box;
line-height: 130%;
padding-left: $s * 2;
padding-left: $s * 1.5;
font-size: $s;
.clear-filters {

View File

@ -64,16 +64,18 @@
left: $m;
}
&.frame-template {
.h-local-controls {
.s-button,
.s-menu-button {
height: $ohH;
line-height: $ohH;
height: $btnFrameH;
line-height: $btnFrameH;
padding: 0 $interiorMargin;
> span,
&:before {
font-size: 0.65rem;
}
}
}
.s-menu-button:after {
font-size: 8px;
@ -96,8 +98,6 @@
border-color: transparent;
.object-browse-bar .right {
$m: 0;
background: rgba(black, 0.3);
border-radius: $basicCr;
padding: $interiorMarginSm;
position: absolute;
top: $m; right: $m;
@ -111,10 +111,23 @@
bottom: $m;
left: $m;
}
> .t-frame-inner {
> .object-browse-bar .left {
&.t-object-type-layout {
> .object-browse-bar {
.t-btn-view-large {
// When a nested layout has its frame hidden, don't display a view large button
display: none;
}
}
}
> .object-browse-bar {
.left {
display: none;
}
}
> .object-holder.abs {
overflow: hidden;
top: 0 !important;
@ -123,8 +136,8 @@
}
}
&.t-frame-outer .s-input-inline {
// Prevent inline inputs from being edited when nested in a Layout
&.t-frame-outer .title-label.s-input-inline {
// Prevent frame titles from being edited when nested in a Layout
pointer-events: none !important;
}
@ -161,6 +174,7 @@ body.desktop .frame {
// Hide local controls initially and show it them on hover when they're in an element that's in a frame context
// Frame template is used because we need to target the lowest nested frame
.object-browse-bar .btn-bar {
@include trans-prop-nice($props: opacity, $dur: 250ms);
opacity: 0;
pointer-events: none;
}
@ -169,6 +183,7 @@ body.desktop .frame {
// Handles the case where we have layouts in layouts.
&:hover > .object-browse-bar {
.btn-bar {
@include trans-prop-nice($props: opacity, $dur: 10ms);
opacity: 1;
pointer-events: inherit;
}

View File

@ -145,20 +145,18 @@
body.desktop .pane .mini-tab-icon.toggle-pane {
$hi: splitterHandleInset($splitterD, $splitterHandleD);
$paneExpandedOffset: $hi + $splitterHandleD + $uePaneMiniTabW;
top: $bodyMargin + ($ueTopBarH - $uePaneMiniTabH)/2;
top: 0;
&.toggle-tree.anchor-left.collapsed,
&.toggle-inspect.anchor-right:not(.collapsed) {
@extend .icon-arrow-right;
border-bottom-right-radius: $controlCr;
border-top-right-radius: $controlCr;
}
&.toggle-tree.anchor-left:not(.collapsed),
&.toggle-inspect.anchor-right.collapsed {
@extend .icon-arrow-left;
border-bottom-left-radius: $controlCr;
border-top-left-radius: $controlCr;
}
&.toggle-tree.anchor-left {
@ -240,7 +238,6 @@ body.desktop .pane .mini-tab-icon.toggle-pane {
}
}
.object-browse-bar .s-button,
.top-bar .buttons-main .s-button,
.top-bar .s-menu-button,
.tool-bar .s-button,
@ -268,7 +265,12 @@ body.desktop .pane .mini-tab-icon.toggle-pane {
.left {
.l-back {
margin-right: $interiorMarginLg;
a {
display: inline-block;
text-align: center;
width: 24px;
}
margin-right: $interiorMargin;
&.s-status-editing { display: none; }
}
}

View File

@ -19,14 +19,19 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
.s-hover-border {
border: 1px solid transparent;
&:hover {
border-color: rgba($colorSelectableSelectedPrimary, 0.5) !important;
}
}
.s-status-editing {
body.desktop {
.s-hover-border {
&:hover {
border-color: rgba($colorBodyFg, 0.3) !important;
}
}
.s-status-editing {
// Limit to editing mode
$o: 0.5;
$oHover: 0.8;
@ -45,18 +50,9 @@
}
}
.s-selected {
&.s-moveable {
&:not(.s-drilled-in) {
cursor: move;
}
}
}
}
.s-selected > .s-hover-border,
.s-selected.s-hover-border {
> .s-hover-border,
&.s-hover-border {
// Styles for a selected object. Also used by legacy Fixed Position/Panel objects.
border-color: $colorSelectableSelectedPrimary !important;
@include boxShdwLarge();
// Show edit-corners if you got 'em
.edit-corner {
@ -65,6 +61,21 @@
background-color: rgba($colorKey, 1);
}
}
}
&.s-moveable {
&:not(.s-drilled-in) {
cursor: move;
}
}
}
}
.s-selected > .s-hover-border,
.s-selected.s-hover-border {
border-color: $colorSelectableSelectedPrimary !important;
//z-index: 1; // Bring selected item from beneath others. BUT, this breaks editing in Fixed Position.
}
}

View File

@ -23,17 +23,6 @@
ng-controller="SelectorController as selector">
<div class='col col-15'>
<div class='line field-hints'>Available</div>
<!--div id='_form_filter' class='line filter'>
<input type='text' class='control filter' name='filter-available' />
<a class='icon ui-symbol t-available-trigger'
href=''
title="Filter is case sensitive">M</a>
</div>
<div class="line">
Showing {{shown}} of {{count}} available options.
</div -->
<div class='line treeview' name='available'>
<mct-representation key="'tree'"
mct-object="selector.root()"
@ -55,18 +44,6 @@
</div>
<div class='col col-15'>
<div class='line field-hints'>Selected</div>
<!-- div id='_form_filter' class='line filter'>
<input type='text' class='control filter' name='filter-selected' />
<a class='icon ui-symbol t-selected-trigger'
href=''
title="Filter is case sensitive">
M
</a>
</div>
<div class="line">
Showing {{shown}} of {{count}} available options.
</div -->
<div class='line treeview l-tree-item-flat-list' name='selected'>
<ul class="tree">
<li ng-repeat="selectedObject in selector.selected()">

View File

@ -29,14 +29,14 @@
key="'inspector-region'"
mct-object="domainObject"
ng-model="ngModel"
class="flex-elem grows vscroll l-flex-col">
class="flex-elem grows vscroll scroll-pad l-flex-col inspector-properties">
</mct-representation>
</div>
</div>
<mct-splitter class="splitter-inspect-panel mobile-hide"></mct-splitter>
<div class="split-pane-component pane bottom">
<div class="abs holder holder-elements l-flex-col">
<em class="flex-elem t-inspector-part-header">Elements</em>
<h2>Elements</h2>
<mct-representation
key="'edit-elements'"
mct-object="domainObject"

View File

@ -0,0 +1,45 @@
<!--
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.
-->
<div class="t-frame-inner abs t-object-type-{{ domainObject.getModel().type }}" mct-preview>
<div class="abs object-browse-bar l-flex-row">
<div class="left flex-elem l-flex-row grows">
<mct-representation
key="'object-header-frame'"
mct-object="domainObject"
class="l-flex-row flex-elem object-header grows">
</mct-representation>
</div>
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
<mct-representation
key="'switcher'"
ng-model="representation"
mct-object="domainObject">
</mct-representation>
</div>
</div>
<div class="abs object-holder">
<mct-representation
key="representation.selected.key"
mct-object="representation.selected.key && domainObject">
</mct-representation>
</div>
</div>

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