Compare commits

...

218 Commits

Author SHA1 Message Date
Henry
23dbbf965c Removed sysouts 2016-04-19 09:36:30 -07:00
Henry
a72f193e97 Register listener for status change 2016-04-18 09:15:25 -07:00
Henry
18e0aadfc1 Removing EditableDomainObject 2016-04-17 08:26:27 -07:00
Henry
64b3580cf6 Removed EditableDomainObject 2016-04-14 15:29:14 -07:00
Henry
08684fa14a Added navigation events 2016-04-14 14:05:08 -07:00
Henry
56a5a30f56 [Edit] Remove EditableDomainObject 2016-04-13 17:05:17 -07:00
Victor Woeltjen
d48871f204 Merge pull request #783 from nasa/open635
[Edit Mode] #635 Removed Edit-related concerns from ContextMenuGesture
2016-04-12 09:40:14 -07:00
Henry
519a9333ab Updated tests 2016-04-11 17:10:35 -07:00
Henry
2fe7ba982f Added 'Open in New Tab' to context menu in edit mode 2016-04-11 17:06:37 -07:00
Henry
7f108c3b24 [Edit Mode] #635 Removed Edit-related concerns from ContextMenuGesture 2016-04-11 15:39:35 -07:00
Pete Richards
c591ade479 Merge remote-tracking branch 'origin/781' 2016-04-06 10:35:40 -07:00
Victor Woeltjen
8f4f0cb78e Merge pull request #785 from nasa/open677_cleanup
[Timelines] #677 Removed temporary markup
2016-04-05 12:24:58 -07:00
Victor Woeltjen
e87280aa15 Merge pull request #821 from nasa/show-selected-color
[Control] Color input shows selected color
2016-04-05 12:20:14 -07:00
Pete Richards
e0a2d02d23 [Control] Color input shows selected color
Update color input to show selected color when expanded.
2016-04-05 11:57:45 -07:00
Victor Woeltjen
73012233b8 [Build] Bump version number
...to begin sprint Heinlein,
https://github.com/nasa/openmct/milestones/Heinlein
2016-04-04 09:33:58 -07:00
Victor Woeltjen
339916ccd4 [Build] Remove SNAPSHOT status
...to tag end of release Gibson,
https://github.com/nasa/openmct/milestones/Gibson
2016-04-04 09:32:21 -07:00
Victor Woeltjen
70acef6905 [Instantiation] Ensure new models have modified timestamp
...to avoid https://github.com/nasa/openmct/issues/745#issuecomment-204561163
2016-04-01 14:27:26 -07:00
Victor Woeltjen
da09ffd3fa [Persistence] Don't evict models on persist
https://github.com/nasa/openmct/issues/745#issuecomment-204559209
2016-04-01 13:38:13 -07:00
Pete Richards
5b98da6681 Merge pull request #807 from nasa/timeline-model-717
[Timeline] Add default values to model
2016-04-01 10:10:15 -07:00
Andrew Henry
2040abb768 Merge pull request #808 from nasa/revert-open-793
Revert "Merge remote-tracking branch 'origin/open793'"
2016-03-31 16:37:18 -07:00
Pete Richards
d35fccbbe8 Revert "Merge remote-tracking branch 'origin/open793'"
This reverts commit f49552779a, reversing
changes made to e068173f3e.
2016-03-31 16:30:35 -07:00
Victor Woeltjen
06c6832676 [Timeline] Add default values to model
Add default values to model, such that editing which occurs
before user supplies these properties does not cause errors
to occur. Directly addresses #717, indirectly addresses
remaining errant behavior associated with #790.
2016-03-31 15:46:56 -07:00
Pete Richards
f49552779a Merge remote-tracking branch 'origin/open793' 2016-03-31 14:14:08 -07:00
Henry
200a426f17 [Tables] Addressed style concerns from code review 2016-03-31 12:56:29 -07:00
Pete Richards
e068173f3e Merge remote-tracking branch 'origin/move-copy-policy-792' 2016-03-31 12:49:06 -07:00
Victor Woeltjen
4441e88769 Merge pull request #803 from nasa/drag-drop-688
[Firefox] Invoke preventDefault on drop
2016-03-31 11:02:26 -07:00
Victor Woeltjen
254a944d7a [Firefox] Invoke preventDefault on drop
...such that Firefox does not try to treat drop as a new URL
to navigate to. Addresses #688 and #527
2016-03-31 10:34:24 -07:00
Henry
0c00061cbc Added mutation listener 2016-03-31 10:26:34 -07:00
Andrew Henry
dee0613b81 Merge pull request #800 from nasa/timeline-reorder-789
[Timeline] Fix reordering behavior in timelines
2016-03-31 09:39:17 -07:00
Andrew Henry
6b6bada700 Merge pull request #788 from nasa/open445b
Review and integrate open445b
2016-03-31 09:36:03 -07:00
Victor Woeltjen
530b940a64 [Timeline] Fix reordering
Fix reordering behavior when dragging-and-dropping within timelines;
addresses #789.
2016-03-29 19:46:30 -07:00
Victor Woeltjen
e23bf5ed39 [Entanglement] Test CopyPolicy 2016-03-29 19:26:18 -07:00
Victor Woeltjen
6ecea9950d [Entanglement] Test MovePolicy 2016-03-29 19:22:22 -07:00
Victor Woeltjen
4816dddf41 [Entanglement] Wire in copy/move policies
#792
2016-03-29 13:14:08 -07:00
Victor Woeltjen
cae775f9bc [Entanglement] Add policies for Copy and Move
...to ensure that these are only performed on creatable and
mutable targets, respectively.
2016-03-29 13:10:35 -07:00
Henry
a4b79cdb5b [Tables] #793 Added fix for tables not appearing on refresh
Fixed failing tests
2016-03-28 17:48:01 -07:00
Henry
012a38cccd [Tables] Fix for table columns not being populated 2016-03-28 17:31:10 -07:00
Charles Hacskaylo
a01f7ddd2d [Frontend] Refinements to .loading and related
#445
Markup enhanced in wait-node.html;
More wait-spinner constants added;
Normalized appearance between tree-based
.loading and .s-status-pending;
Fixed .s-status-pending to work now that
mct-representation is gone from tree;
2016-03-24 15:10:22 -07:00
Charles Hacskaylo
e7e91e21fc [Frontend] Markup and CSS for loading tree items
#445
New wait-spinner constants;
Markup fixed in wait-node.html;
Styles for .loading when applied to
.tree-item.wait-node;
Changed from percent-of-parent-
width sizing of spinner to fixed size;
2016-03-24 15:10:02 -07:00
Pete Richards
cbea842c8b Merge branch 'timeline-highlight-767' 2016-03-24 13:33:56 -07:00
Pete Richards
cc5d14deec Merge branch '755a' 2016-03-24 13:21:59 -07:00
Pete Richards
4c5217d646 [Style] Standardize indentation 2016-03-24 13:20:49 -07:00
Pete Richards
5e54b193ca [Style] remove unnecessary parenthesis
See comment https://github.com/nasa/openmct/pull/782/files#r57380540
2016-03-24 13:14:53 -07:00
Pete Richards
cd7ff8ad85 Merge remote-tracking branch 'origin/timestamps-776' 2016-03-24 13:09:32 -07:00
Pete Richards
fa5d59bff8 Merge branch 'timeline-save-770b' 2016-03-24 13:06:53 -07:00
Pete Richards
ddbb72b88a [CacheService] Don't track ids twice
Track whether an object is in the cache based on whether it is
in the cache instead of utilizing a separate object for tracking
contents of cache.

See comment on https://github.com/nasa/openmct/pull/773/files
2016-03-24 12:57:53 -07:00
Charles Hacskaylo
88784d37fd [Frontend] Added priority
#787
2016-03-24 12:05:10 -07:00
Andrew Henry
700e605bbd Merge pull request #775 from nasa/timeline-drag-drop-679
[Timeline] Move (instead of link) when dragging and dropping within a timeline
2016-03-23 20:00:48 -07:00
Charles Hacskaylo
594f3b8ec2 [Frontend] Corrected wrong unicode value
#781
2016-03-23 19:30:20 -07:00
Charles Hacskaylo
b08d00ef3e [Frontend] Removed tab character
#781
2016-03-23 19:25:25 -07:00
Charles Hacskaylo
0643fb1f3f [Frontend] Updated icomoon project file
#781
2016-03-23 19:17:39 -07:00
Charles Hacskaylo
289debf19d [Frontend] Fixed hover problem with menu items
#781
#187
Noticed a problem with <a> tags in
Create menu items and fixed with display: block;
2016-03-23 19:10:59 -07:00
Charles Hacskaylo
7da1a4b2a3 [Frontend] Updated glyph defs and descriptions
#781
#187
Converted many glyph char defs to
their JSON unicode equivalents;
Updated descriptions for many domain
objects;
2016-03-23 19:04:32 -07:00
Charles Hacskaylo
528169de2c [Frontend] Updated glyphs
#781
Added multiple new and updated glyphs;
Updated glyph defs for Historic and
Real-Time Tables;
2016-03-23 17:42:58 -07:00
Victor Woeltjen
c13231b8e8 [Timeline] Remove NULL_ACTION, clarify logic
Per code review feedback,
https://github.com/nasa/openmct/pull/775/files#r57229759
2016-03-23 15:34:05 -07:00
Andrew Henry
3e4a3aeb9b Merge pull request #779 from nasa/precision-778b
[Data Formats] Format numeric values with full precision
2016-03-23 12:15:26 -07:00
Henry
650ef9bfa4 [Timelines] #677 Removed temporary markup 2016-03-23 11:27:40 -07:00
Victor Woeltjen
dd053f7e6e [Timeline] Invoke $apply from mct-swimlane-drop
...and add some checks to ensure this is necessary, to avoid
triggering a ton of digest cycles while dragging.
2016-03-22 17:16:41 -07:00
Victor Woeltjen
cb655d486b [Timeline] Test reordering within parent 2016-03-22 17:06:58 -07:00
Victor Woeltjen
3c52ceb71a [Timeline] Remove unused function
Removal of domain objects is handled by using the move action.
2016-03-22 17:01:45 -07:00
Victor Woeltjen
b2337dea97 [Timeline] Update failing specs
...and remove obsolete test case for handling drops in a timeline
2016-03-22 16:59:09 -07:00
Victor Woeltjen
dea6554e04 [Timeline] Allow drops from tree
Don't assume that all drops will be dropped swimlanes.
2016-03-22 12:26:01 -07:00
Victor Woeltjen
31d8c9a48f [Timeline] Allow linking during edit
...in cases where it is safe to do so (specifically, when the
linked-to object has already been persisted.)
2016-03-22 12:04:50 -07:00
Victor Woeltjen
f8682a7a29 Merge pull request #780 from nasa/open715
[Timelines] #715 Added a check to prevent mutation when modes are unchanged
2016-03-22 09:24:57 -07:00
Henry
e5544615cc [Timelines] #715 Added a check to prevent mutation when modes are unchanged 2016-03-21 17:01:38 -07:00
Victor Woeltjen
ec0cc572f6 [Add] Test model cache 2016-03-21 16:11:40 -07:00
Victor Woeltjen
6c2a28aba2 [Add] Add JSDoc to model cache 2016-03-21 16:05:05 -07:00
Victor Woeltjen
baccd005dc [Add] Update persistence capability spec
...to reflect removal of cached domain object models.
2016-03-21 15:08:27 -07:00
Victor Woeltjen
1e4ff5a73f [Add] Use cacheService from decorator spec 2016-03-21 15:05:28 -07:00
Victor Woeltjen
9f29382e18 [Add] Update spec for Instantiate
...to reflect usage of a model cache for #770
2016-03-21 15:04:07 -07:00
Victor Woeltjen
5f6b4adcda [Plot] Normalize number of digits
Use consistent number of digits for displayed plot values, to avoid
unreadable plot legends due to fix for #778
2016-03-21 14:45:00 -07:00
Victor Woeltjen
d6ab70447e [Data Format] Don't truncate data values 2016-03-21 14:35:58 -07:00
Victor Woeltjen
a411bac331 [Time Format] Append Z instead of zone offset
...for brevity (reduce visual noise)
2016-03-21 14:29:24 -07:00
Victor Woeltjen
5624c7d545 [Time Formats] Display UTC with milliseconds
#776
2016-03-21 13:04:59 -07:00
Victor Woeltjen
007741b4e7 [Timeline] Add move policy
...to restore suppression of Move for objects being edited
(relaxed for the specific case of moving one object being
edited into another object being edited, for use in Timelines.)
2016-03-21 12:07:19 -07:00
Victor Woeltjen
e0a69744e5 [Timeline] Deinline null action
...used for cases when no action is needed for timeline move
(and ids will just be reordered.)
2016-03-21 11:53:10 -07:00
Victor Woeltjen
e7a6c34bcc [Timeline] Handle drops for reordering
...as these would be disallowed by Move, normally.
2016-03-21 11:51:51 -07:00
Victor Woeltjen
7f3ac4077c [Timeline] Drop to correct targets 2016-03-21 11:43:02 -07:00
Victor Woeltjen
7eaffdc34a [Timeline] Don't suppress move during editing
...to allow this action to be used to support Timeline
drag-and-drop.
2016-03-21 11:42:33 -07:00
Victor Woeltjen
5034e88656 [Timeline] Use move action on drag-drop
...to avoid creating links when desired behavior is a move,
#679.
2016-03-21 11:18:18 -07:00
Charles Hacskaylo
aa48044345 [Frontend] Form styling
#772
Added ".l-controls-under" styling to allow
channel-selector layout;
Added new hint color constants and refined
style defs;
2016-03-21 11:13:43 -07:00
Victor Woeltjen
d12111d9b8 [Add] Fix promise chaining in AddAction 2016-03-21 10:32:02 -07:00
Victor Woeltjen
9c9db3c24f [Add] Remove obsolete variable reference
The cache has been externalized to allow writing to it
upon domain object instantiation.
2016-03-21 10:31:38 -07:00
Victor Woeltjen
3fe41575bd [Add] Add missing dependency
...to support caching of domain objects created during edit mode.
2016-03-21 10:31:09 -07:00
Victor Woeltjen
8fa030437e [Add] Remove edit awareness
Remove step where Added objects are persisted via the editor
capability; instead, persist via the usual persistence capability,
such that Edit mode may intervene (or not) as necessary.
As instantiated models are cached at least until persisted,
this workaround to allow newly-created models to be available
during editing is no longer necessary (and undesired consequences
such as #770 no longer occur)
2016-03-21 10:22:25 -07:00
Victor Woeltjen
17faf000b0 [Add] Cache models on instantiation
...to remove need for Edit to persist these immediately, which in
turn causes #770 and #678
2016-03-21 10:20:14 -07:00
Charles Hacskaylo
90c82f6ef2 [Frontend] Timeline tooltip and field input tweaks
#750
Refined tooltip for Resource Graphing;
Increased size of Activity Link input field;
2016-03-21 10:08:59 -07:00
Charles Hacskaylo
5e6fe16b93 [Frontend] Adding tooltips
#750
2016-03-17 16:21:04 -07:00
Charles Hacskaylo
f0ca6fdfdb [Frontend] Added tooltips
#750
Added tooltips to Timeline header elements;
2016-03-17 15:10:42 -07:00
Andrew Henry
ad4c456ca2 Merge pull request #763 from nasa/restrict-requirejs-version
[Package] Specify require minor version
2016-03-17 14:38:02 -07:00
Pete Richards
b0476edb8c [Package] Specify require minor version
Specify requirejs minor version of 2.1, as 2.2 is not compatible
with karma-requirejs.

Fixes build problems that appeared after latest requirejs version bump.
2016-03-17 14:28:22 -07:00
Pete Richards
8f6a287fb8 Merge remote-tracking branch 'origin/tree-refresh-745' 2016-03-17 11:40:53 -07:00
Victor Woeltjen
07d554d114 Merge pull request #759 from nasa/700a
Review and integrate 700a
2016-03-17 11:02:22 -07:00
Andrew Henry
24d2cecdcd Merge pull request #761 from nasa/open757
[Tables] #757 Added max row limit to streaming tables
2016-03-17 10:19:04 -07:00
Henry
8efa9c6aac [Tables] #757 Fixed code style issues 2016-03-17 10:09:59 -07:00
Henry
22e98274ca [Tables] #757 Added max row limit to streaming tables 2016-03-16 18:59:52 -07:00
Charles Hacskaylo
471b57f47c [Frontend] CSS tweaks
#750
Moved l-plot-resource cursor: pointer
to a more specific selector;
Added user-select: none to l-header;
Fixed s-status-editing styling so
that tabular labels only appear draggable
while editing;
2016-03-16 18:19:44 -07:00
Charles Hacskaylo
9c775c6715 [Frontend] Changed cursor property
#755
Changed s-timeline-gantt.mid to
use cursor: move instead of
ew-resize; Need to verify on Linux;
2016-03-16 17:36:07 -07:00
Charles Hacskaylo
1f09b7b0ac [Frontend] Fix for scrollbar flicker
#748
Was able to observe problem in Mac
Chrome. Moved body, html overflow: hidden
into startup-base.scss and change seems
to have fixed the problem;
2016-03-16 17:34:28 -07:00
Andrew Henry
b0cf9bbd29 Merge pull request #758 from nasa/error-message-753
[Tree] Don't assume context capability is present
2016-03-16 15:33:59 -07:00
Andrew Henry
4a1ca25e17 Merge pull request #754 from nasa/tree-status-styling-749
[Tree] Add status classes during editing
2016-03-16 15:26:40 -07:00
Charles Hacskaylo
cc97e567b6 [Frontend] Further style cleanups
#689
#740
Tweaked scrollbar thumb color;
Fixed color of icons in s-menu-btn
menus, particularly for Snow theme;
Removed commented code;
2016-03-16 15:17:08 -07:00
Charles Hacskaylo
53f03cddb7 [Frontend] Further cleanups to form elements
#689
Removed commented code;
2016-03-16 14:49:37 -07:00
Charles Hacskaylo
da1e6750a0 [Frontend] Removed reset.css and refs to modernizr
#700
Removed reset.css; Removed refs to
modernizr from licenses and readme.md;
2016-03-16 14:44:01 -07:00
Charles Hacskaylo
3258342783 [Frontend] Further cleanups to form elements
#700
#689
#740
Removed _selects.scss and moved classes
into _controls.scss;
Reorg'd _controls;
Moved classes into _elems.scss;
Added and fixed cssclass defs in multiple
bundle.js files to allow better field widths
in overlay dialogs;
Fixed overlay custom scrollbar colors;
Fixed alignment of required glyphs in forms;
2016-03-16 14:40:06 -07:00
Victor Woeltjen
73b7365ae2 [Tree] Don't assume context capability is present
Addresses #753 (newly-created objects may not have context,
causing errors when these are encountered by TreeNodeView)
2016-03-16 14:10:58 -07:00
Charles Hacskaylo
32a42bd679 [Frontend] CSS tweaks to fix required glyph positioning
#700
CSS modded to allow better cross-browser
positioning of 'required' form-row glyphs;
Other elem's CSS adjusted as a result;
2016-03-16 09:43:59 -07:00
Victor Woeltjen
324c2cac03 [Tree] Refresh properly on mutation
...by removing the incorrect expectation that a domain object
(and not just its model) will be passed in when mutation occurs.
Addresses #745.
2016-03-15 12:23:46 -07:00
Victor Woeltjen
42ac657105 [Tree] Add status classes during editing
Addresses #749
2016-03-15 12:16:58 -07:00
Pete Richards
d30532a8bc Merge remote-tracking branch 'origin/open742' 2016-03-14 16:37:58 -07:00
Pete Richards
936079da92 Merge remote-tracking branch 'origin/tree-732' 2016-03-14 16:15:05 -07:00
Andrew Henry
4e89ffbe07 Merge pull request #735 from nasa/open729
Review and integrate open729
2016-03-14 16:12:18 -07:00
Henry
f9ed73c55e [Table] #742 Fixed digest-related bug in RTTelemetryController
Fixed failing test
2016-03-14 16:00:36 -07:00
Charles Hacskaylo
bf3b964ad2 Removed commented code
#729
#735
2016-03-14 15:45:10 -07:00
Victor Woeltjen
55ae755522 [Tree] Fix error in test case
Correctly expect both arguments to $watch
2016-03-14 15:04:58 -07:00
Victor Woeltjen
d522570c0b [Tree] Add spec for mct-tree 2016-03-14 14:54:57 -07:00
Victor Woeltjen
d72aaf54ca [Tree] Test inner tree creation 2016-03-14 14:40:46 -07:00
Victor Woeltjen
8f94751a35 [Tree] Add capabilities to child objects for testing 2016-03-14 14:14:34 -07:00
Andrew Henry
dfb0a570a3 Merge pull request #728 from nasa/warp135b
[Timelines] Export as CSV
2016-03-14 13:20:28 -07:00
Pete Richards
5d06979866 Merge remote-tracking branch 'origin/open707' 2016-03-14 13:05:59 -07:00
Victor Woeltjen
8b51ae32d2 [Tree] Begin testing selection change 2016-03-14 13:04:46 -07:00
Victor Woeltjen
ecb37c54be [Tree] Add TreeView test cases 2016-03-14 12:52:33 -07:00
Victor Woeltjen
43492d31ba [Tree] Begin writing spec for TreeView 2016-03-14 12:22:09 -07:00
Victor Woeltjen
0e1df444df [Tree] Update test configuration
...to account for new dependency on Zepto (and its necessary
shim.)
2016-03-14 12:21:58 -07:00
Victor Woeltjen
f2c040367b [Timeline] Rename TimelineCSVExporter
...to TimelineColumnizer, clarifying its role/responsibilities in the
context of the CSV export task;
https://github.com/nasa/openmctweb/pull/728#discussion_r56031331
2016-03-14 12:00:31 -07:00
Victor Woeltjen
0ff360ced3 [Timelines] Remove excessive ternaries
...to improve readability of logic to determine which columns
are needed for a given group of domain objects for CSV export,
as requested during code review,
https://github.com/nasa/openmctweb/pull/728#discussion_r55910477
2016-03-14 11:53:28 -07:00
Henry
fc08df4f6f [Tables] #733 Made code style changes for conformance with style guide 2016-03-14 11:25:26 -07:00
Henry
c5de90a951 [Tables] Changed the way that new rows are added to table
Fixed failing tests
2016-03-13 20:15:47 -07:00
Henry
ea0b86fe72 [Tables] Fixed issue with historical tables composed of multiple objects 2016-03-13 19:12:55 -07:00
Victor Woeltjen
d789e91c18 [Tree] Add wait spinner 2016-03-11 18:00:58 -08:00
Victor Woeltjen
f7ba24c0b6 [Tree] Enable gestures on labels 2016-03-11 17:43:18 -08:00
Victor Woeltjen
02ec6db104 [Tree] Trigger digest on tree selection change 2016-03-11 17:37:11 -08:00
Victor Woeltjen
a3a9393d1b [Tree] Change selection on click 2016-03-11 17:32:57 -08:00
Victor Woeltjen
217e697079 [Tree] Display selection state 2016-03-11 17:26:00 -08:00
Victor Woeltjen
82b6166408 [Tree] Begin wiring in selection 2016-03-11 17:09:17 -08:00
Victor Woeltjen
03ab3bddc4 [Tree] Begin handling selection state 2016-03-11 17:00:55 -08:00
Andrew Henry
abd5913f02 Merge pull request #727 from nasa/open377
[Search] Index directly on mutation
2016-03-11 15:39:43 -08:00
Victor Woeltjen
107ecfe687 [Search] Don't index objects being edited
https://github.com/nasa/openmctweb/pull/727#issuecomment-195570183
2016-03-11 14:55:16 -08:00
Victor Woeltjen
4a8222a152 [Tree] Update labels on mutation 2016-03-11 14:47:50 -08:00
Victor Woeltjen
7ee8d0a3f7 [Tree] Display tree correctly 2016-03-11 14:40:04 -08:00
Victor Woeltjen
dc2b3e85cc [Tree] Show tree with toggle 2016-03-11 14:33:05 -08:00
Victor Woeltjen
d4b15525ca [Tree] Begin using mct-tree for tree representation 2016-03-11 14:23:08 -08:00
Victor Woeltjen
cbd9509260 [Tree] Use TreeView from mct-tree 2016-03-11 14:13:14 -08:00
Victor Woeltjen
c5ab6c6c97 [Tree] Implement label for tree 2016-03-11 14:10:30 -08:00
Andrew Henry
cd84a017b8 Merge pull request #723 from nasa/open672
[Build] Enforce code coverage threshold
2016-03-11 13:34:26 -08:00
Andrew Henry
d39dea971f Merge pull request #721 from nasa/open716
[Info Bubble] Fix bug with arrow positioning
2016-03-11 13:13:49 -08:00
Victor Woeltjen
4f293f22a6 [Tree] Add Zepto dependency
...to support implementation of a jQuery-less tree.
2016-03-11 12:38:40 -08:00
Victor Woeltjen
cebf9f73da [Tree] Begin adding tree label 2016-03-11 12:29:24 -08:00
Victor Woeltjen
37e6b5a352 [Tree] Continue breaking apart tree view 2016-03-11 11:39:10 -08:00
Victor Woeltjen
ece8f7fded [Tree] Begin separating out TreeView 2016-03-11 11:12:43 -08:00
Victor Woeltjen
3b0a3733b4 [Tree] Begin adding controller for refactored tree 2016-03-11 10:23:06 -08:00
Victor Woeltjen
baab0be5af [Tree] Begin adding mct-tree directive
...to reduce watch counts associated with the tree;
#732 and #315
2016-03-11 10:04:33 -08:00
Victor Woeltjen
d14a2a6366 Merge pull request #736 from nasa/open718
Review and integrate open718
2016-03-11 09:52:18 -08:00
Charles Hacskaylo
377d533ec7 [Frontend] Fixed markup
open #718
Removed class from markup;
2016-03-10 18:11:10 -08:00
Charles Hacskaylo
a4c5854561 [Frontend] Bug fixing
open #729
open #498
Fixed markup to use proper CSS classes
to allow tree items in Inspector Elements to
ellipsize properly, and to apply scroll regions
to the proper elements;
2016-03-10 14:33:01 -08:00
Victor Woeltjen
5296255fa6 [Representation] Test for false-positives on refresh
#732
2016-03-10 14:26:20 -08:00
Victor Woeltjen
5d084c2618 [Representation] Fix unchanged check
Fix logic in unchanged check; compare booleans to detect if
they have changed, instead of just anding them. Partially
addresses #732
2016-03-10 14:21:20 -08:00
Henry
5208631528 [Tables] #707 removed redundant bundles 2016-03-10 13:55:59 -08:00
Henry
a56edb9ff4 [table] #707 Fixed sorting on insert for numbers
Added metadata to event generator
2016-03-10 13:39:16 -08:00
Henry
7da1a218ba [Tables] #707 Added auto-scroll, addressed race condition in Sinewave and event telemetry providers
Fixed issue with visible padding row

Incremental improvements

Added tests

Added tests for sorted insert, and fixed lint errors
2016-03-10 13:21:57 -08:00
Henry
a4eb9d6a94 [Tables] #707 Supporting realtime telemetry tables
Added real-time table type
2016-03-10 13:21:57 -08:00
Henry
20f1dcef45 Fixed scrolling 2016-03-10 13:21:01 -08:00
Charles Hacskaylo
4983d35ca6 [Frontend] Cleanups to Inspector config elements
open #729
Spacing tweaks; set PlotOptionsForm.js > Autoscale
to not use control-first layout;
Checked in snow theme;
2016-03-10 13:18:57 -08:00
Charles Hacskaylo
7171fd01e3 [Frontend] Cleanups to Inspector config elements
open #729
In-progress
Moved CSS def to be more globally applicable;
Simplified layout obj props location display;
2016-03-10 11:07:26 -08:00
Charles Hacskaylo
0957fbc6f9 [Frontend] Cleanups to Inspector config elements
open #729
In-progress
Moved reduced-min-width into _inspector.scss;
Removed <style> defs in markup files;
2016-03-10 10:50:00 -08:00
Charles Hacskaylo
bdbb045005 [Frontend] Cleanups to Inspector config elements
open #729
In-progress!
Markup and CSS mods continued;
Config params added to PlotOptionsForm.js to
allow control-first layout per form row;
Changed titles of Inspector parts;
2016-03-10 10:31:05 -08:00
Charles Hacskaylo
318df9878d [Frontend] Cleanups to Inspector config elements
open #729
In-progress!
Markup and CSS modified to cleanup control layout
and styling in Plot and Table config options;
gulpfile.js modified to include SASS source line numbers
in rendered CSS;
2016-03-09 17:22:41 -08:00
Victor Woeltjen
406a31889e [Timeline] Add specs for remaining columns 2016-03-08 12:34:08 -08:00
Victor Woeltjen
9e4e3e9c43 [Timeline] Add JSDoc
Add JSDoc to classes implemented Export Timeline as CSV
2016-03-08 11:59:53 -08:00
Victor Woeltjen
bd7cb98a4c [Timeline] Add missing semicolon
...to pass code style checks
2016-03-08 11:40:54 -08:00
Victor Woeltjen
0d419fa5fd [Timeline] Test TimelineTraverser 2016-03-08 11:30:26 -08:00
Victor Woeltjen
5ee5e7fea1 [Timeline] Add capabilities to test inputs 2016-03-08 10:47:01 -08:00
Victor Woeltjen
66b1a92554 [Timeline] Add test cases for TimelineTraverser 2016-03-08 10:43:13 -08:00
Victor Woeltjen
c23c2b84bf [Timeline] Test inclusion of timespan properties
...in prepared data for CSV export
2016-03-08 10:31:31 -08:00
Victor Woeltjen
0c2285719e [Timeline] Test inclusion of metadata headers 2016-03-08 10:27:50 -08:00
Victor Woeltjen
fd92c5f970 [Timeline] Add more tests for rows 2016-03-08 10:22:46 -08:00
Victor Woeltjen
938c266b4e [Timeline] Add Id column to CSV export 2016-03-08 10:20:25 -08:00
Victor Woeltjen
9e6e33983b [Timeline] Add more objects to test case 2016-03-08 10:17:10 -08:00
Victor Woeltjen
40895ec1b9 [Timelines] Begin spec for exporter 2016-03-08 10:07:21 -08:00
Victor Woeltjen
43db52fd70 [Timeline] Simplify interface
...such that responsibility for knowing exportService interface
is more localized.
2016-03-08 10:04:09 -08:00
Victor Woeltjen
75d6803c9f [Timeline] Test mode columns in CSV Export 2016-03-08 09:59:54 -08:00
Victor Woeltjen
ed679756b3 [Timelines] Test metadata columns in CSV Export
...and additionally refactor to run in a test environment
(don't use Array.prototype.find)
2016-03-08 09:56:21 -08:00
Victor Woeltjen
dd66cb60d8 [Timeline] Test export task 2016-03-08 09:47:09 -08:00
Victor Woeltjen
d5283d57e4 [Timeline] Add missing semicolon 2016-03-07 16:35:40 -08:00
Victor Woeltjen
7c140c06dc [Timeline] Test CSV Export action itself 2016-03-07 16:33:03 -08:00
Victor Woeltjen
f9ff9921a9 [Timelines] Continue testing CSV Export
...with initial test cases for the action itself.
2016-03-07 16:22:39 -08:00
Victor Woeltjen
cdac0ad67f [Timeline] Add test cases for CSV Export 2016-03-07 16:17:19 -08:00
Victor Woeltjen
5d771edcf7 [Timeline] Begin testing CSV Export 2016-03-07 16:13:23 -08:00
Victor Woeltjen
c4f1c4ad1f [Timeline] Show progress notification during export 2016-03-07 16:09:23 -08:00
Victor Woeltjen
14b8e02f27 [Timeline] Format exported start/end times 2016-03-07 16:02:33 -08:00
Victor Woeltjen
b383921f2a [Timeline] Export start/end to CSV 2016-03-07 16:00:13 -08:00
Victor Woeltjen
a509dfb840 [Timelines] Remove unused TaskService
https://developer.nasa.gov/mct/warp/issues/135
2016-03-07 15:30:57 -08:00
Victor Woeltjen
b7a44a7557 Merge branch 'master' into warp135b 2016-03-07 15:21:28 -08:00
Victor Woeltjen
2d305415b3 [Search] Index directly on mutation
Pass model directly when indexing is triggered via object mutation,
to avoid issuing an extra, unnecessary request to the server.

Additionally supports indexing of objects which have been created
but not yet persisted.

Addresses #377.
2016-03-07 14:46:36 -08:00
Victor Woeltjen
ff5f37dfbe [Build] Bump version number
...and add SNAPSHOT status, to begin sprint Gibson.
https://github.com/nasa/openmctweb/milestones/Gibson
2016-03-04 13:59:41 -08:00
Victor Woeltjen
7c2ddf3926 [Build] Remove snapshot status
...to close sprint Ellison,
https://github.com/nasa/openmctweb/milestones/Ellison
2016-03-04 13:48:31 -08:00
Victor Woeltjen
18167eddf8 [Build] Enforce code coverage threshold
Addresses #672
2016-03-03 17:14:04 -08:00
Victor Woeltjen
f302bd6cb2 [Info Bubble] Test arrow class application
#716
2016-03-03 16:17:01 -08:00
Victor Woeltjen
071a908c10 [Info Bubble] Don't clobber arrow classes
#716
2016-03-03 15:58:28 -08:00
Pete Richards
7e60593501 Merge remote-tracking branch 'origin/open670' 2016-03-03 11:28:28 -08:00
Henry
f653362247 Fixed issue with non-named columns 2016-03-03 10:12:25 -08:00
Henry
b63b7b1e5d [Tables] #670 Addressed issues from code review 2016-03-03 09:26:12 -08:00
Henry
55e00baeaf [Table] #670 Addressed comments from code review 2016-03-02 21:40:56 -08:00
Victor Woeltjen
75178576dd Merge pull request #712 from nasa/open627_no_regions_master
[Edit Mode] #627 Remove edit-related concerns from Browse controllers
2016-03-02 12:12:11 -08:00
Henry
670c06103f [Edit Mode] Rebased over master 2016-03-02 11:45:15 -08:00
Henry
b9a7ee423a Merge branch 'master' into open670_master 2016-03-01 12:56:08 -08:00
Henry
b5c6b70993 Merge branch 'master' into open670_master 2016-03-01 12:55:45 -08:00
Henry
f04c3692c1 [Table] #670 Name column only prepended if multiple objects 2016-02-26 11:22:16 -08:00
Henry
ffa497f22f [Table] #670 Added new view type 'table' 2016-02-26 11:09:51 -08:00
Victor Woeltjen
273cf1c14f [Timeline] Fix columns exported 2016-02-08 18:07:03 -08:00
Victor Woeltjen
303e870b0d Merge branch 'open649' into warp135 2016-02-08 17:42:30 -08:00
Victor Woeltjen
b42ccebd5a [Timeline] Fix imports, dependencies
Fix imports and dependencies needed by Export Timeline as CSV
2016-02-08 17:42:26 -08:00
Victor Woeltjen
a444fc01ad [Timeline] Fix column module definitions 2016-02-08 17:34:10 -08:00
Victor Woeltjen
a126e43286 [Timelines] Handle columns during CSV export 2016-02-08 16:11:00 -08:00
Victor Woeltjen
32fc50bbd3 [Timelines] Begin sketching in taskService
...to separate out immediate commonality with other long-running
actions which need to show a blocking progress dialog.
2016-02-08 15:04:39 -08:00
Victor Woeltjen
4adb075a2b [Timelines] Separate out timeline traversal
...from rest of CSV export.
2016-02-08 13:59:34 -08:00
Victor Woeltjen
d8b1e570d9 [CSV Export] Begin implementing
Begin implementing initial step, wherein timelines composition
is traversed to build up a list of objects to export.
2016-02-08 13:36:25 -08:00
Victor Woeltjen
5033e2cdbb [Timeline] Begin adding Export as CSV
Sketch in solution for
https://developer.nasa.gov/mct/warp/issues/135
2016-02-08 13:04:41 -08:00
222 changed files with 8991 additions and 21061 deletions

View File

@@ -309,30 +309,6 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
---
### Modernizr
#### Info
* Link: http://modernizr.com
* Version: 2.6.2
* Author: Faruk Ateş
* Description: Browser/device capability finding
#### License
Copyright (c) 20092015
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
### Normalize.css
#### Info
@@ -476,6 +452,44 @@ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLI
---
### Zepto
#### Info
* Link: http://zeptojs.com/
* Version: 1.1.6
* Authors: Thomas Fuchs
* Description: DOM manipulation
#### License
Copyright (c) 2010-2016 Thomas Fuchs
http://zeptojs.com/
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
### Json.NET
#### Info

View File

@@ -17,6 +17,7 @@
"screenfull": "^3.0.0",
"node-uuid": "^1.4.7",
"comma-separated-values": "^3.6.4",
"FileSaver.js": "^0.0.2"
"FileSaver.js": "^0.0.2",
"zepto": "^1.1.6"
}
}

View File

@@ -32,7 +32,7 @@ define([
legacyRegistry.register("example/eventGenerator", {
"name": "Event Message Generator",
"description": "Example of a component that produces event data.",
"description": "For development use. Creates sample event message data that mimics a live data stream.",
"extensions": {
"components": [
{
@@ -49,16 +49,26 @@ define([
{
"key": "eventGenerator",
"name": "Event Message Generator",
"glyph": "f",
"description": "An event message generator",
"glyph": "\u0066",
"description": "For development use. Creates sample event message data that mimics a live data stream.",
"priority": 10,
"features": "creation",
"model": {
"telemetry": {}
},
"telemetry": {
"source": "eventGenerator",
"domains": [
{
"key": "time",
"name": "Time",
"format": "utc"
}
],
"ranges": [
{
"key": "message",
"name": "Message",
"format": "string"
}
]

View File

@@ -37,7 +37,8 @@ define(
var
subscriptions = [],
genInterval = 1000,
startTime = Date.now();
generating = false,
id = Math.random() * 100000;
//
function matchesSource(request) {
@@ -79,11 +80,13 @@ define(
}
function startGenerating() {
generating = true;
$timeout(function () {
//console.log("startGenerating... " + Date.now());
handleSubscriptions();
if (subscriptions.length > 0) {
if (generating && subscriptions.length > 0) {
startGenerating();
} else {
generating = false;
}
}, genInterval);
}
@@ -93,7 +96,6 @@ define(
callback: callback,
requests: requests
};
function unsubscribe() {
subscriptions = subscriptions.filter(function (s) {
return s !== subscription;
@@ -101,8 +103,7 @@ define(
}
subscriptions.push(subscription);
if (subscriptions.length === 1) {
if (!generating) {
startGenerating();
}

View File

@@ -36,7 +36,7 @@ define([
legacyRegistry.register("example/generator", {
"name": "Sine Wave Generator",
"description": "Example of a component that produces dataa.",
"description": "For development use. Generates example streaming telemetry data using a simple sine wave algorithm.",
"extensions": {
"components": [
{
@@ -86,8 +86,9 @@ define([
{
"key": "generator",
"name": "Sine Wave Generator",
"glyph": "T",
"description": "A sine wave generator",
"glyph": "\u0054",
"description": "For development use. Generates example streaming telemetry data using a simple sine wave algorithm.",
"priority": 10,
"features": "creation",
"model": {
"telemetry": {
@@ -126,7 +127,7 @@ define([
{
"name": "Period",
"control": "textfield",
"cssclass": "l-small l-numeric",
"cssclass": "l-input-sm l-numeric",
"key": "period",
"required": true,
"property": [

View File

@@ -34,7 +34,8 @@ define(
* @constructor
*/
function SinewaveTelemetryProvider($q, $timeout) {
var subscriptions = [];
var subscriptions = [],
generating = false;
//
function matchesSource(request) {
@@ -75,10 +76,13 @@ define(
}
function startGenerating() {
generating = true;
$timeout(function () {
handleSubscriptions();
if (subscriptions.length > 0) {
if (generating && subscriptions.length > 0) {
startGenerating();
} else {
generating = false;
}
}, 1000);
}
@@ -97,7 +101,7 @@ define(
subscriptions.push(subscription);
if (subscriptions.length === 1) {
if (!generating) {
startGenerating();
}

View File

@@ -49,8 +49,10 @@ define([
{
"key": "imagery",
"name": "Example Imagery",
"glyph": "T",
"glyph": "\u00e3",
"features": "creation",
"description": "For development use. Creates example imagery data that mimics a live imagery stream.",
"priority": 10,
"model": {
"telemetry": {}
},

View File

@@ -54,7 +54,7 @@ define([
{
"name": "Measurement",
"key": "msl.measurement",
"glyph": "T",
"glyph": "\u0054",
"model": {"telemetry": {}},
"telemetry": {
"source": "rems.source",

View File

@@ -80,9 +80,10 @@ define([
"types": [
{
"key": "plot",
"name": "Telemetry Plot",
"glyph": "t",
"description": "A plot for displaying telemetry",
"name": "Example Telemetry Plot",
"glyph": "\u0074",
"description": "For development use. A plot for displaying telemetry.",
"priority": 10,
"delegates": [
"telemetry"
],

View File

@@ -60,7 +60,8 @@ var gulp = require('gulp'),
singleRun: true
},
sass: {
includePaths: bourbon.includePaths
includePaths: bourbon.includePaths,
sourceComments: true
},
replace: {
variables: {

View File

@@ -81,7 +81,12 @@ module.exports = function(config) {
coverageReporter: {
dir: process.env.CIRCLE_ARTIFACTS ?
process.env.CIRCLE_ARTIFACTS + '/coverage' :
"dist/coverage"
"dist/coverage",
check: {
global: {
lines: 80
}
}
},
// HTML test reporting.

View File

@@ -33,7 +33,8 @@ requirejs.config({
"saveAs": "bower_components/FileSaver.js/FileSaver.min",
"screenfull": "bower_components/screenfull/dist/screenfull.min",
"text": "bower_components/text/text",
"uuid": "bower_components/node-uuid/uuid"
"uuid": "bower_components/node-uuid/uuid",
"zepto": "bower_components/zepto/zepto.min"
},
"shim": {
"angular": {
@@ -44,6 +45,9 @@ requirejs.config({
},
"moment-duration-format": {
"deps": [ "moment" ]
},
"zepto": {
"exports": "Zepto"
}
}
});
@@ -70,13 +74,12 @@ define([
'./platform/exporters/bundle',
'./platform/telemetry/bundle',
'./platform/features/clock/bundle',
'./platform/features/events/bundle',
'./platform/features/imagery/bundle',
'./platform/features/layout/bundle',
'./platform/features/pages/bundle',
'./platform/features/plot/bundle',
'./platform/features/scrolling/bundle',
'./platform/features/timeline/bundle',
'./platform/features/table/bundle',
'./platform/forms/bundle',
'./platform/identity/bundle',
'./platform/persistence/aggregator/bundle',

View File

@@ -1,7 +1,7 @@
{
"name": "openmctweb",
"version": "0.9.2-SNAPSHOT",
"description": "The Open MCT Web core platform",
"version": "0.10.0-SNAPSHOT",
"description": "The Open MCT core platform",
"dependencies": {
"express": "^4.13.1",
"minimist": "^1.1.1",
@@ -38,7 +38,7 @@
"moment": "^2.11.1",
"node-bourbon": "^4.2.3",
"phantomjs-prebuilt": "^2.1.0",
"requirejs": "^2.1.17",
"requirejs": "2.1.x",
"split": "^1.0.0"
},
"scripts": {

View File

@@ -135,9 +135,7 @@ define([
"depends": [
"$scope",
"$location",
"$route",
"$q",
"navigationService"
"$route"
]
},
{
@@ -248,12 +246,6 @@ define([
"implementation": NavigationService
}
],
"services": [
{
"key": "navigationService",
"implementation": NavigationService
}
],
"policies": [
{
"implementation": CreationPolicy,

View File

@@ -44,22 +44,7 @@
</div>
</div>
<div class="holder l-flex-col flex-elem grows l-object-wrapper">
<div ng-if="isEditable" class="holder l-flex-col flex-elem grows l-object-wrapper-inner">
<!-- Toolbar and Save/Cancel buttons -->
<div class="l-edit-controls flex-elem l-flex-row flex-align-end">
<mct-representation key="'edit-action-buttons'"
mct-object="domainObject"
class='flex-elem conclude-editing'>
</mct-representation>
</div>
<mct-representation key="representation.selected.key"
mct-object="representation.selected.key && domainObject"
class="abs flex-elem grows object-holder-main scroll"
toolbar="toolbar">
</mct-representation>
</div>
<div ng-if="!isEditable" class="holder l-flex-col flex-elem grows l-object-wrapper-inner">
<div class="holder l-flex-col flex-elem grows l-object-wrapper-inner">
<!-- Toolbar and Save/Cancel buttons -->
<div class="l-edit-controls flex-elem l-flex-row flex-align-end">
<mct-representation key="'edit-action-buttons'"

View File

@@ -32,6 +32,7 @@
</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"
ng-repeat="parent in contextutalParents"
ng-class="{ last:($index + 1) === contextualParents.length }">
@@ -44,7 +45,7 @@
</span>
</li>
<li ng-if="primaryParents.length > 0">
<em class="t-inspector-part-header" title="The location of the original object that this was linked from.">Original Location</em>
<div class="section-header">Object's Original</div>
<span class="inspector-location"
ng-repeat="parent in primaryParents"
ng-class="{ last:($index + 1) === primaryParents.length }">

View File

@@ -29,5 +29,5 @@
-->
<mct-representation mct-object="domainObject"
key="viewObjectTemplate || 'browse-object'"
class="abs holder holder-object">
class="abs holder">
</mct-representation>

View File

@@ -32,9 +32,7 @@ define(
function (GestureConstants) {
"use strict";
var ROOT_ID = "ROOT",
DEFAULT_PATH = "mine",
CONFIRM_MSG = "Unsaved changes will be lost if you leave this page.";
var ROOT_ID = "ROOT";
/**
* The BrowseController is used to populate the initial scope in Browse

View File

@@ -32,7 +32,7 @@ define(
* @memberof platform/commonUI/browse
* @constructor
*/
function BrowseObjectController($scope, $location, $route, $q, navigationService) {
function BrowseObjectController($scope, $location, $route) {
var navigatedObject;
function setViewForDomainObject(domainObject) {

View File

@@ -93,27 +93,23 @@ define(
return wizard.populateObjectFromInput(formValue, newObject);
}
function addToParent (populatedObject) {
parentObject.getCapability('composition').add(populatedObject);
return parentObject.getCapability('persistence').persist().then(function(){
return parentObject;
});
function persistAndReturn(domainObject) {
return domainObject.getCapability('persistence')
.persist()
.then(function () {
return domainObject;
});
}
function save(object) {
/*
It's necessary to persist the new sub-object in order
that it can be retrieved for composition in the parent.
Future refactoring that allows temporary objects to be
retrieved from object services will make this unnecessary.
*/
return object.getCapability('editor').save(true);
function addToParent (populatedObject) {
parentObject.getCapability('composition').add(populatedObject);
return persistAndReturn(parentObject);
}
return this.dialogService
.getUserInput(wizard.getFormStructure(false), wizard.getInitialFormValue())
.then(populateObjectFromInput)
.then(save)
.then(persistAndReturn)
.then(addToParent);
};

View File

@@ -25,11 +25,8 @@
* Module defining CreateAction. Created by vwoeltje on 11/10/14.
*/
define(
[
'./CreateWizard',
'../../../edit/src/objects/EditableDomainObject'
],
function (CreateWizard, EditableDomainObject) {
[],
function () {
"use strict";
/**
@@ -88,22 +85,19 @@ define(
CreateAction.prototype.perform = function () {
var newModel = this.type.getInitialModel(),
parentObject = this.navigationService.getNavigation(),
newObject,
editableObject;
newObject;
newModel.type = this.type.getKey();
newObject = parentObject.useCapability('instantiation', newModel);
editableObject = new EditableDomainObject(newObject, this.$q);
editableObject.setOriginalObject(parentObject);
editableObject.getCapability('status').set('editing', true);
editableObject.useCapability('mutation', function(model){
newObject.useCapability('mutation', function(model){
model.location = parentObject.getId();
});
if (countEditableViews(editableObject) > 0 && editableObject.hasCapability('composition')) {
this.navigationService.setNavigation(editableObject);
if (countEditableViews(newObject) > 0 && newObject.hasCapability('composition')) {
this.navigationService.setNavigation(newObject);
newObject.getCapability("action").perform("edit");
} else {
return editableObject.getCapability('action').perform('save');
return newObject.getCapability('action').perform('save');
}
};

View File

@@ -34,9 +34,16 @@ define([
"./src/actions/SaveAction",
"./src/actions/CancelAction",
"./src/policies/EditActionPolicy",
"./src/policies/EditableLinkPolicy",
"./src/policies/EditableMovePolicy",
"./src/policies/EditNavigationPolicy",
"./src/policies/EditContextualActionPolicy",
"./src/representers/EditRepresenter",
"./src/representers/EditToolbarRepresenter",
"./src/capabilities/EditorCapability",
"./src/capabilities/TransactionDecorator",
"./src/services/TransactionService",
"./src/services/DirtyModelCache",
"text!./res/templates/library.html",
"text!./res/templates/edit-object.html",
"text!./res/templates/edit-action-buttons.html",
@@ -56,9 +63,16 @@ define([
SaveAction,
CancelAction,
EditActionPolicy,
EditableLinkPolicy,
EditableMovePolicy,
EditNavigationPolicy,
EditContextualActionPolicy,
EditRepresenter,
EditToolbarRepresenter,
EditorCapability,
TransactionDecorator,
TransactionService,
DirtyModelCache,
libraryTemplate,
editObjectTemplate,
editActionButtonsTemplate,
@@ -176,10 +190,7 @@ define([
"implementation": CancelAction,
"name": "Cancel",
"description": "Discard changes made to these objects.",
"depends": [
"$injector",
"navigationService"
]
"depends": []
}
],
"policies": [
@@ -187,13 +198,23 @@ define([
"category": "action",
"implementation": EditActionPolicy
},
{
"category": "action",
"implementation": EditContextualActionPolicy,
"depends": ["navigationService"]
},
{
"category": "action",
"implementation": EditableMovePolicy
},
{
"category": "action",
"implementation": EditableLinkPolicy
},
{
"category": "navigation",
"message": "There are unsaved changes.",
"implementation": EditNavigationPolicy,
"depends": [
"$window"
]
"implementation": EditNavigationPolicy
}
],
@@ -236,6 +257,35 @@ define([
"template": topbarEditTemplate
}
],
"components": [
{
"type": "decorator",
"provides": "capabilityService",
"implementation": TransactionDecorator,
"depends": [
"$q",
"transactionService",
"dirtyModelCache"
]
},
{
"type": "provider",
"provides": "transactionService",
"implementation": TransactionService,
"depends": [
"$q",
"dirtyModelCache"
]
},
{
"type": "provider",
"provides": "dirtyModelCache",
"implementation": DirtyModelCache,
"depends": [
"topic"
]
}
],
"representers": [
{
"implementation": EditRepresenter,
@@ -247,7 +297,19 @@ define([
{
"implementation": EditToolbarRepresenter
}
]
],
"capabilities": [
{
"key": "editor",
"name": "Editor Capability",
"description": "Provides transactional editing capabilities",
"implementation": EditorCapability,
"depends": [
"transactionService",
"dirtyModelCache"
]
}
],
}
});
});

View File

@@ -19,16 +19,19 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div ng-controller="ElementsController">
<div ng-controller="ElementsController" class="flex-elem l-flex-col holder grows">
<mct-include key="'input-filter'"
class="flex-elem holder"
ng-model="filterBy">
</mct-include>
<div class="current-elements abs" style="height: 100%;">
<div class="flex-elem grows vscroll">
<ul class="tree">
<li ng-repeat="containedObject in composition | filter:searchText">
<span class="tree-item">
<mct-representation key="'label'" mct-object="containedObject">
<mct-representation
class="rep-object-label"
key="'label'"
mct-object="containedObject">
</mct-representation>
</span>
</li>

View File

@@ -33,10 +33,8 @@ define(
* @memberof platform/commonUI/edit
* @implements {Action}
*/
function CancelAction($injector, navigationService, context) {
function CancelAction(context) {
this.domainObject = context.domainObject;
this.navigationService = navigationService;
this.objectService = $injector.get('objectService');
}
/**
@@ -46,30 +44,16 @@ define(
* cancellation has completed
*/
CancelAction.prototype.perform = function () {
var domainObject = this.domainObject,
self = this;
var domainObject = this.domainObject;
// Look up the object's "editor.completion" capability;
// this is introduced by EditableDomainObject which is
// used to insulate underlying objects from changes made
// during editing.
function getEditorCapability() {
return domainObject.getCapability("editor");
function returnToBrowse () {
var parent;
domainObject.getCapability("location").getOriginal().then(function (original) {
parent = original.getCapability("context").getParent();
parent.getCapability("action").perform("navigate");
});
}
// Invoke any save behavior introduced by the editor.completion
// capability.
function doCancel(editor) {
return editor.cancel();
}
//Discard current 'editable' object, and retrieve original
// un-edited object.
function returnToBrowse() {
return self.navigationService.setNavigation(self.domainObject.getOriginalObject());
}
return doCancel(getEditorCapability())
return this.domainObject.getCapability("editor").cancel()
.then(returnToBrowse);
};
@@ -82,7 +66,7 @@ define(
CancelAction.appliesTo = function (context) {
var domainObject = (context || {}).domainObject;
return domainObject !== undefined &&
domainObject.hasCapability("editor");
domainObject.getCapability("status").get("editing");
};
return CancelAction;

View File

@@ -25,8 +25,8 @@
* Module defining EditAction. Created by vwoeltje on 11/14/14.
*/
define(
['../objects/EditableDomainObject'],
function (EditableDomainObject) {
[],
function () {
"use strict";
// A no-op action to return in the event that the action cannot
@@ -73,25 +73,12 @@ define(
*/
EditAction.prototype.perform = function () {
var self = this;
if (!this.domainObject.hasCapability("editor")) {
//TODO: This is only necessary because the drop gesture is
// wrapping the object itself, need to refactor this later.
// All responsibility for switching into edit mode should be
// in the edit action, and not duplicated in the gesture
this.domainObject = new EditableDomainObject(this.domainObject, this.$q);
}
this.navigationService.setNavigation(this.domainObject);
this.domainObject.getCapability('status').set('editing', true);
//Register a listener to automatically cancel this edit action
//if the user navigates away from this object.
function cancelEditing(navigatedTo){
if (!navigatedTo || navigatedTo.getId() !== self.domainObject.getId()) {
self.domainObject.getCapability('editor').cancel();
self.navigationService.removeListener(cancelEditing);
}
function cancelEditing(){
self.domainObject.getCapability('editor').cancel();
self.navigationService.removeListener(cancelEditing);
}
this.navigationService.addListener(cancelEditing);
this.domainObject.useCapability("editor");
};
/**

View File

@@ -115,15 +115,11 @@ define(
return copyService.perform(domainObject, parent, allowClone);
}
function cancelEditingAfterClone(clonedObject) {
return domainObject.getCapability("editor").cancel()
function saveEdit(clonedObject) {
return domainObject.getCapability("editor").save()
.then(resolveWith(clonedObject));
}
// Invoke any save behavior introduced by the editor capability;
// this is introduced by EditableDomainObject which is
// used to insulate underlying objects from changes made
// during editing.
function doSave() {
//This is a new 'virtual object' that has not been persisted
// yet.
@@ -132,11 +128,10 @@ define(
.then(doWizardSave)
.then(getParent)
.then(cloneIntoParent)
.then(cancelEditingAfterClone)
.then(saveEdit)
.catch(resolveWith(false));
} else {
return domainObject.getCapability("editor").save()
.then(resolveWith(domainObject.getOriginalObject()));
return domainObject.getCapability("editor").save();
}
}
@@ -162,7 +157,7 @@ define(
SaveAction.appliesTo = function (context) {
var domainObject = (context || {}).domainObject;
return domainObject !== undefined &&
domainObject.hasCapability("editor");
domainObject.getCapability("status").get("editing");
};
return SaveAction;

View File

@@ -1,60 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
function () {
'use strict';
var DISALLOWED_ACTIONS = ["move", "copy", "link", "window", "follow"];
/**
* Editable Action Capability. Overrides the action capability
* normally exhibited by a domain object and filters out certain
* actions not applicable when an object is in edit mode.
*
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
* @constructor
* @memberof platform/commonUI/edit
* @implements {PersistenceCapability}
*/
function EditableActionCapability(
actionCapability,
editableObject,
domainObject,
cache
) {
var action = Object.create(actionCapability);
action.getActions = function(domainObject) {
return actionCapability.getActions(domainObject).filter(function(action){
return DISALLOWED_ACTIONS.indexOf(action.getMetadata().key) === -1;
});
};
return action;
}
return EditableActionCapability;
}
);

View File

@@ -1,60 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
['./EditableLookupCapability'],
function (EditableLookupCapability) {
'use strict';
/**
* Wrapper for the "composition" capability;
* ensures that any domain objects reachable in Edit mode
* are also wrapped as EditableDomainObjects.
*
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
* @constructor
* @memberof platform/commonUI/edit
* @implements {CompositionCapability}
*/
return function EditableCompositionCapability(
contextCapability,
editableObject,
domainObject,
cache
) {
// This is a "lookup" style capability (it looks up other
// domain objects), but we do not want to return the same
// specific value every time (composition may change)
return new EditableLookupCapability(
contextCapability,
editableObject,
domainObject,
cache,
false // Not idempotent
);
};
}
);

View File

@@ -1,78 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
['./EditableLookupCapability'],
function (EditableLookupCapability) {
'use strict';
/**
* Wrapper for the "context" capability;
* ensures that any domain objects reachable in Edit mode
* are also wrapped as EditableDomainObjects.
*
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
* @constructor
* @memberof platform/commonUI/edit
* @implements {ContextCapability}
*/
return function EditableContextCapability(
contextCapability,
editableObject,
domainObject,
cache
) {
// This is a "lookup" style capability (it looks up other
// domain objects), and it should be idempotent
var capability = new EditableLookupCapability(
contextCapability,
editableObject,
domainObject,
cache,
true // Idempotent
),
// Track the real root object for the Elements pane
trueRoot = capability.getRoot();
// Provide access to the real root, for the Elements pane.
capability.getTrueRoot = function () {
return trueRoot;
};
// Hide ancestry after the root of this subgraph
if (cache.isRoot(domainObject)) {
capability.getRoot = function () {
return editableObject;
};
capability.getPath = function () {
return [editableObject];
};
}
return capability;
};
}
);

View File

@@ -1,60 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
['./EditableLookupCapability'],
function (EditableLookupCapability) {
'use strict';
/**
* Wrapper for the "instantiation" capability;
* ensures that any domain objects instantiated in Edit mode
* are also wrapped as EditableDomainObjects.
*
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
* @constructor
* @memberof platform/commonUI/edit
* @implements {CompositionCapability}
*/
return function EditableInstantiationCapability(
contextCapability,
editableObject,
domainObject,
cache
) {
// This is a "lookup" style capability (it looks up other
// domain objects), but we do not want to return the same
// specific value every time (composition may change)
return new EditableLookupCapability(
contextCapability,
editableObject,
domainObject,
cache,
false // Not idempotent
);
};
}
);

View File

@@ -1,125 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
[],
function () {
'use strict';
/**
* Wrapper for both "context" and "composition" capabilities;
* ensures that any domain objects reachable in Edit mode
* are also wrapped as EditableDomainObjects.
*
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
* @constructor
* @memberof platform/commonUI/edit
*/
return function EditableLookupCapability(
contextCapability,
editableObject,
domainObject,
cache,
idempotent
) {
var capability = Object.create(contextCapability),
method;
// Check for domain object interface. If something has these
// three methods, we assume it's a domain object.
function isDomainObject(obj) {
return obj !== undefined &&
typeof obj.getId === 'function' &&
typeof obj.getModel === 'function' &&
typeof obj.getCapability === 'function';
}
// Check an object returned by the wrapped capability; if it
// is a domain object, we want to make it editable and/or get
// it from the cache of editable domain objects. This will
// prevent changes made in edit mode from modifying the actual
// underlying domain object.
function makeEditableObject(obj) {
return isDomainObject(obj) ?
cache.getEditableObject(obj) :
obj;
}
// Wrap a returned value (see above); if it's an array, wrap
// all elements.
function makeEditable(returnValue) {
return Array.isArray(returnValue) ?
returnValue.map(makeEditableObject) :
makeEditableObject(returnValue);
}
// Wrap a returned value (see above); if it's a promise, wrap
// the resolved value.
function wrapResult(result) {
return (result && result.then) ? // promise-like
result.then(makeEditable) :
makeEditable(result);
}
// Return a wrapped version of a function, which ensures
// all results are editable domain objects.
function wrapFunction(fn) {
return function () {
return wrapResult(contextCapability[fn].apply(
capability,
arguments
));
};
}
// Wrap a method such that it only delegates once.
function oneTimeFunction(fn) {
return function () {
var result = wrapFunction(fn).apply(this, arguments);
capability[fn] = function () {
return result;
};
return result;
};
}
// Wrap a method of this capability
function wrapMethod(fn) {
if (typeof capability[fn] === 'function') {
capability[fn] =
(idempotent ? oneTimeFunction : wrapFunction)(fn);
}
}
// Wrap all methods; return only editable domain objects.
for (method in contextCapability) {
wrapMethod(method);
}
return capability;
};
}
);

View File

@@ -1,68 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
function () {
'use strict';
/**
* Editable Persistence Capability. Overrides the persistence capability
* normally exhibited by a domain object to ensure that changes made
* during edit mode are not immediately stored to the database or other
* backing storage.
*
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
* @constructor
* @memberof platform/commonUI/edit
* @implements {PersistenceCapability}
*/
function EditablePersistenceCapability(
persistenceCapability,
editableObject,
domainObject,
cache
) {
var persistence = Object.create(persistenceCapability);
// Simply trigger refresh of in-view objects; do not
// write anything to database.
persistence.persist = function () {
return cache.markDirty(editableObject);
};
// Delegate refresh to the original object; this avoids refreshing
// the editable instance of the object, and ensures that refresh
// correctly targets the "real" version of the object.
persistence.refresh = function () {
return domainObject.getCapability('persistence').refresh();
};
return persistence;
}
return EditablePersistenceCapability;
}
);

View File

@@ -1,60 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
['./EditableLookupCapability'],
function (EditableLookupCapability) {
'use strict';
/**
* Wrapper for the "relationship" capability;
* ensures that any domain objects reachable in Edit mode
* are also wrapped as EditableDomainObjects.
*
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
* @constructor
* @memberof platform/commonUI/edit
* @implements {RelationshipCapability}
*/
return function EditableRelationshipCapability(
relationshipCapability,
editableObject,
domainObject,
cache
) {
// This is a "lookup" style capability (it looks up other
// domain objects), but we do not want to return the same
// specific value every time (composition may change)
return new EditableLookupCapability(
relationshipCapability,
editableObject,
domainObject,
cache,
false // Not idempotent
);
};
}
);

View File

@@ -26,117 +26,61 @@ define(
function () {
'use strict';
/**
* Implements "save" and "cancel" as capabilities of
* the object. In editing mode, user is seeing/using
* a copy of the object (an EditableDomainObject)
* which is disconnected from persistence; the Save
* and Cancel actions can use this capability to
* propagate changes from edit mode to the underlying
* actual persistable object.
*
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
* @constructor
* @memberof platform/commonUI/edit
*/
function EditorCapability(
persistenceCapability,
editableObject,
domainObject,
cache
transactionService,
dirtyModelCache,
domainObject
) {
this.editableObject = editableObject;
this.transactionService = transactionService;
this.dirtyModelCache = dirtyModelCache;
this.domainObject = domainObject;
this.cache = cache;
}
// Simulate Promise.resolve (or $q.when); the former
// causes a delayed reaction from Angular (since it
// does not trigger a digest) and the latter is not
// readily accessible, since we're a few classes
// removed from the layer which gets dependency
// injection.
function resolvePromise(value) {
return (value && value.then) ? value : {
then: function (callback) {
return resolvePromise(callback(value));
}
};
EditorCapability.prototype.edit = function () {
this.transactionService.startTransaction();
this.domainObject.getCapability('status').set('editing', true);
};
function isEditing (domainObject) {
return domainObject.getCapability('status').get('editing') ||
domainObject.hasCapability('context') && isEditing(domainObject.getCapability('context').getParent());
}
/**
* Save any changes that have been made to this domain object
* (as well as to others that might have been retrieved and
* modified during the editing session)
* @param {boolean} nonrecursive if true, save only this
* object (and not other objects with associated changes)
* @returns {Promise} a promise that will be fulfilled after
* persistence has completed.
* @memberof platform/commonUI/edit.EditorCapability#
* Determines whether this object, or any of its ancestors are
* currently being edited.
* @returns boolean
*/
EditorCapability.prototype.save = function (nonrecursive) {
var domainObject = this.domainObject,
editableObject = this.editableObject,
self = this,
cache = this.cache,
returnPromise;
EditorCapability.prototype.isEditing = function () {
return isEditing(this.domainObject);
};
// Update the underlying, "real" domain object's model
// with changes made to the copy used for editing.
function doMutate() {
return domainObject.useCapability('mutation', function () {
return editableObject.getModel();
});
}
// Persist the underlying domain object
function doPersist() {
return domainObject.getCapability('persistence').persist();
}
editableObject.getCapability("status").set("editing", false);
if (nonrecursive) {
returnPromise = resolvePromise(doMutate())
.then(doPersist)
.then(function(){
self.cancel();
});
} else {
returnPromise = resolvePromise(cache.saveAll());
}
//Return the original (non-editable) object
return returnPromise.then(function() {
return domainObject.getOriginalObject ? domainObject.getOriginalObject() : domainObject;
EditorCapability.prototype.save = function () {
var domainObject = this.domainObject;
return this.transactionService.commit().then(function() {
domainObject.getCapability('status').set('editing', false);
});
};
/**
* Cancel editing; Discard any changes that have been made to
* this domain object (as well as to others that might have
* been retrieved and modified during the editing session)
* @returns {Promise} a promise that will be fulfilled after
* cancellation has completed.
* @memberof platform/commonUI/edit.EditorCapability#
*/
EditorCapability.prototype.invoke = EditorCapability.prototype.edit;
EditorCapability.prototype.cancel = function () {
this.editableObject.getCapability("status").set("editing", false);
this.cache.markClean();
return resolvePromise(undefined);
var domainObject = this.domainObject;
return this.transactionService.cancel().then(function(){
domainObject.getCapability("status").set("editing", false);
return domainObject;
});
};
/**
* Check if there are any unsaved changes.
* @returns {boolean} true if there are unsaved changes
* @memberof platform/commonUI/edit.EditorCapability#
*/
EditorCapability.prototype.dirty = function () {
return this.cache.dirty();
return this.dirtyModelCache.isDirty(this.domainObject);
};
EditorCapability.prototype.appliesTo = function(context) {
var domainObject = context.domainObject;
return domainObject && domainObject.getType().hasFeature("creation");
}
return EditorCapability;
}
);

View File

@@ -0,0 +1,68 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
['./TransactionalPersistenceCapability'],
function (TransactionalPersistenceCapability) {
'use strict';
function TransactionDecorator(
$q,
transactionService,
dirtyModelCache,
capabilityService
) {
this.capabilityService = capabilityService;
this.transactionService = transactionService;
this.dirtyModelCache = dirtyModelCache;
this.$q = $q;
}
/**
* Decorate PersistenceCapability to ignore persistence calls when a
* transaction is in progress.
*/
TransactionDecorator.prototype.getCapabilities = function (model) {
var self = this,
capabilities = this.capabilityService.getCapabilities(model),
persistenceCapability = capabilities.persistence;
capabilities.persistence = function (domainObject) {
var original =
(typeof persistenceCapability === 'function') ?
persistenceCapability(domainObject) :
persistenceCapability;
return new TransactionalPersistenceCapability(
self.$q,
self.transactionService,
self.dirtyModelCache,
original,
domainObject
);
};
return capabilities;
};
return TransactionDecorator;
}
);

View File

@@ -0,0 +1,75 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
[],
function () {
'use strict';
function TransactionalPersistenceCapability(
$q,
transactionService,
dirtyModelCache,
persistenceCapability,
domainObject
) {
this.transactionService = transactionService;
this.dirtyModelCache = dirtyModelCache;
this.persistenceCapability = Object.create(persistenceCapability);
this.domainObject = domainObject;
this.$q = $q;
}
TransactionalPersistenceCapability.prototype.persist = function () {
var domainObject = this.domainObject,
dirtyModelCache = this.dirtyModelCache;
if (this.transactionService.isActive() && !this.transactionService.isCommitting()) {
dirtyModelCache.markDirty(domainObject);
//Using $q here because need to return something
// from which 'catch' can be chained
return this.$q.when(true);
} else {
return this.persistenceCapability.persist().then(function (result) {
dirtyModelCache.markClean(domainObject);
return result;
});
}
};
TransactionalPersistenceCapability.prototype.refresh = function () {
var domainObject = this.domainObject,
dirtyModelCache = this.dirtyModelCache;
return this.persistenceCapability.refresh().then(function (result) {
dirtyModelCache.markClean(domainObject);
return result;
});
};
TransactionalPersistenceCapability.prototype.getSpace = function () {
return this.persistenceCapability.getSpace();
};
return TransactionalPersistenceCapability;
}
);

View File

@@ -1,132 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
/**
* Defines EditableDomainObject, which wraps domain objects
* such that user code may work with and mutate a copy of the
* domain object model; these changes may then be propagated
* up to the real domain object (or not) by way of invoking
* save or cancel behaviors of the "editor.completion"
* capability (a capability intended as internal to edit
* mode; invoked by way of the Save and Cancel actions.)
*/
define(
[
'../capabilities/EditablePersistenceCapability',
'../capabilities/EditableContextCapability',
'../capabilities/EditableCompositionCapability',
'../capabilities/EditableRelationshipCapability',
'../capabilities/EditableInstantiationCapability',
'../capabilities/EditorCapability',
'../capabilities/EditableActionCapability',
'./EditableDomainObjectCache'
],
function (
EditablePersistenceCapability,
EditableContextCapability,
EditableCompositionCapability,
EditableRelationshipCapability,
EditableInstantiationCapability,
EditorCapability,
EditableActionCapability,
EditableDomainObjectCache
) {
"use strict";
var capabilityFactories = {
persistence: EditablePersistenceCapability,
context: EditableContextCapability,
composition: EditableCompositionCapability,
relationship: EditableRelationshipCapability,
instantiation: EditableInstantiationCapability,
editor: EditorCapability
};
// Handle special case where "editor.completion" wraps persistence
// (other capability overrides wrap capabilities of the same type.)
function getDelegateArguments(name, args) {
return name === "editor" ? ['persistence'] : args;
}
/**
* An EditableDomainObject overrides capabilities
* which need to behave differently in edit mode,
* and provides a "working copy" of the object's
* model to allow changes to be easily cancelled.
* @constructor
* @memberof platform/commonUI/edit
* @implements {DomainObject}
*/
function EditableDomainObject(domainObject, $q) {
// The cache will hold all domain objects reached from
// the initial EditableDomainObject; this ensures that
// different versions of the same editable domain object
// are not shown in different sections of the same Edit
// UI, which might thereby fall out of sync.
var cache,
originalObject = domainObject,
cachedObject;
// Constructor for EditableDomainObject, which adheres
// to the same shared cache.
function EditableDomainObjectImpl(domainObject, model) {
var editableObject = Object.create(domainObject);
// Only provide the cloned model.
editableObject.getModel = function () { return model; };
// Override certain capabilities
editableObject.getCapability = function (name) {
var delegateArguments = getDelegateArguments(name, arguments),
capability = domainObject.getCapability.apply(
this,
delegateArguments
),
Factory = capabilityFactories[name];
return (Factory && capability) ?
new Factory(capability, editableObject, domainObject, cache) :
capability;
};
editableObject.setOriginalObject = function(object) {
originalObject = object;
};
editableObject.getOriginalObject = function() {
return originalObject;
};
return editableObject;
}
cache = new EditableDomainObjectCache(EditableDomainObjectImpl, $q);
cachedObject = cache.getEditableObject(domainObject);
return cachedObject;
}
return EditableDomainObject;
}
);

View File

@@ -1,173 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
/*
* An editable domain object cache stores domain objects that have been
* made editable, in a group that can be saved all-at-once. This supports
* Edit mode, which is launched for a specific object but may contain
* changes across many objects.
*
* Editable domain objects have certain specific capabilities overridden
* to ensure that changes made while in edit mode do not propagate up
* to the objects used in browse mode (or to persistence) until the user
* initiates a Save.
*/
define(
["./EditableModelCache"],
function (EditableModelCache) {
'use strict';
/**
* Construct a new cache for editable domain objects. This can be used
* to get-or-create editable objects, particularly to support wrapping
* of objects retrieved via composition or context capabilities as
* editable domain objects.
*
* @param {Constructor<DomainObject>} EditableDomainObject a
* constructor function which takes a regular domain object as
* an argument, and returns an editable domain object as its
* result.
* @param $q Angular's $q, for promise handling
* @memberof platform/commonUI/edit
* @constructor
*/
function EditableDomainObjectCache(EditableDomainObject, $q) {
this.cache = new EditableModelCache();
this.dirtyObjects = {};
this.root = undefined;
this.$q = $q;
this.EditableDomainObject = EditableDomainObject;
}
/**
* Wrap this domain object in an editable form, or pull such
* an object from the cache if one already exists.
*
* @param {DomainObject} domainObject the regular domain object
* @returns {DomainObject} the domain object in an editable form
*/
EditableDomainObjectCache.prototype.getEditableObject = function (domainObject) {
var type = domainObject.getCapability('type'),
EditableDomainObject = this.EditableDomainObject,
editableObject,
statusListener;
// Track the top-level domain object; this will have
// some special behavior for its context capability.
this.root = this.root || domainObject;
// Avoid double-wrapping (WTD-1017)
if (domainObject.hasCapability('editor')) {
return domainObject;
}
// Don't bother wrapping non-editable objects
if (!type || !type.hasFeature('creation')) {
return domainObject;
}
// Provide an editable form of the object
editableObject = new EditableDomainObject(
domainObject,
this.cache.getCachedModel(domainObject)
);
return editableObject;
};
/**
* Check if a domain object is (effectively) the top-level
* object in this editable subgraph.
* @returns {boolean} true if it is the root
*/
EditableDomainObjectCache.prototype.isRoot = function (domainObject) {
return domainObject === this.root;
};
/**
* Mark an editable domain object (presumably already cached)
* as having received modifications during editing; it should be
* included in the bulk save invoked when editing completes.
*
* @param {DomainObject} domainObject the domain object
* @memberof platform/commonUI/edit.EditableDomainObjectCache#
*/
EditableDomainObjectCache.prototype.markDirty = function (domainObject) {
this.dirtyObjects[domainObject.getId()] = domainObject;
return this.$q.when(true);
};
/**
* Mark an object (presumably already cached) as having had its
* changes saved (and thus no longer needing to be subject to a
* save operation.)
*
* @param {DomainObject} domainObject the domain object
*/
EditableDomainObjectCache.prototype.markClean = function (domainObject) {
var self = this;
if (!domainObject) {
Object.keys(this.dirtyObjects).forEach(function(key) {
delete self.dirtyObjects[key];
});
} else {
delete this.dirtyObjects[domainObject.getId()];
}
};
/**
* Initiate a save on all objects that have been cached.
* @return {Promise} A promise which will resolve when all objects are
* persisted.
*/
EditableDomainObjectCache.prototype.saveAll = function () {
// Get a list of all dirty objects
var dirty = this.dirtyObjects,
objects = Object.keys(dirty).map(function (k) {
return dirty[k];
});
// Clear dirty set, since we're about to save.
this.dirtyObjects = {};
// Most save logic is handled by the "editor.completion"
// capability, so that is delegated here.
return this.$q.all(objects.map(function (object) {
// Save; pass a nonrecursive flag to avoid looping
return object.getCapability('editor').save(true);
}));
};
/**
* Check if any objects have been marked dirty in this cache.
* @returns {boolean} true if objects are dirty
*/
EditableDomainObjectCache.prototype.dirty = function () {
return Object.keys(this.dirtyObjects).length > 0;
};
return EditableDomainObjectCache;
}
);

View File

@@ -1,62 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
[],
function () {
"use strict";
/**
* An editable model cache stores domain object models that have been
* made editable, to support a group that can be saved all-at-once.
* This is useful in Edit mode, which is launched for a specific
* object but may contain changes across many objects.
* @memberof platform/commonUI/edit
* @constructor
*/
function EditableModelCache() {
this.cache = {};
}
// Deep-copy a model. Models are JSONifiable, so this can be
// done by stringification then destringification
function clone(model) {
return JSON.parse(JSON.stringify(model));
}
/**
* Get this domain object's model from the cache (or
* place it in the cache if it isn't in the cache yet)
* @returns a clone of the domain object's model
*/
EditableModelCache.prototype.getCachedModel = function (domainObject) {
var id = domainObject.getId(),
cache = this.cache;
return (cache[id] =
cache[id] || clone(domainObject.getModel()));
};
return EditableModelCache;
}
);

View File

@@ -38,14 +38,6 @@ define(
this.policyService = policyService;
}
function applicableView(key){
return ['plot', 'scrolling'].indexOf(key) >= 0;
}
function editableType(key){
return key === 'telemetry.panel';
}
/**
* Get a count of views which are not flagged as non-editable.
* @private
@@ -65,7 +57,8 @@ define(
// A view is editable unless explicitly flagged as not
(views || []).forEach(function (view) {
if (view.editable === true || (applicableView(view.key) && editableType(type.getKey()))) {
if (view.editable === true ||
(view.key === 'plot' && type.getKey() === 'telemetry.panel')) {
count++;
}
});

View File

@@ -0,0 +1,64 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
[],
function () {
"use strict";
/**
* Policy controlling whether the context menu is visible when
* objects are being edited
* @memberof platform/commonUI/edit
* @constructor
* @implements {Policy.<Action, ActionContext>}
*/
function EditContextualActionPolicy(navigationService) {
this.navigationService = navigationService;
//The list of objects disallowed on target object when in edit mode
this.editBlacklist = ["copy", "follow", "window"];
//The list of objects disallowed on target object that is not in
// edit mode (ie. the context menu in the tree on the LHS).
this.nonEditBlacklist = ["copy", "follow", "properties", "move", "link", "remove"];
}
EditContextualActionPolicy.prototype.allow = function (action, context) {
var selectedObject = context.domainObject,
navigatedObject = this.navigationService.getNavigation(),
actionMetadata = action.getMetadata ? action.getMetadata() : {};
if (navigatedObject.hasCapability('editor')) {
if (!selectedObject.hasCapability('editor')){
//Target is in the context menu
return this.nonEditBlacklist.indexOf(actionMetadata.key) === -1;
} else {
return this.editBlacklist.indexOf(actionMetadata.key) === -1;
}
} else {
return true;
}
};
return EditContextualActionPolicy;
}
);

View File

@@ -33,8 +33,7 @@ define(
* @constructor
* @implements {Policy.<Action, ActionContext>}
*/
function EditNavigationPolicy($window, policyService) {
this.window = $window;
function EditNavigationPolicy(policyService) {
this.policyService = policyService;
}

View File

@@ -21,44 +21,33 @@
*****************************************************************************/
/*global define*/
define([
"./src/ScrollingListController",
"text!./res/templates/scrolling.html",
'legacyRegistry'
], function (
ScrollingListController,
scrollingTemplate,
legacyRegistry
) {
define([], function () {
"use strict";
legacyRegistry.register("platform/features/scrolling", {
"name": "Scrolling Lists",
"description": "Time-ordered list of latest data.",
"extensions": {
"views": [
{
"key": "scrolling",
"name": "Scrolling",
"glyph": "5",
"description": "Scrolling list of data values.",
"template": scrollingTemplate,
"needs": [
"telemetry"
],
"delegation": true
}
],
"controllers": [
{
"key": "ScrollingListController",
"implementation": ScrollingListController,
"depends": [
"$scope",
"telemetryFormatter"
]
}
]
/**
* Policy suppressing links when the linked-to domain object is in
* edit mode. Domain objects being edited may not have been persisted,
* so creating links to these can result in inconsistent state.
*
* @memberof platform/commonUI/edit
* @constructor
* @implements {Policy.<View, DomainObject>}
*/
function EditableLinkPolicy() {
}
EditableLinkPolicy.prototype.allow = function (action, context) {
var key = action.getMetadata().key,
object;
if (key === 'link') {
object = context.selectedObject || context.domainObject;
return !(object.hasCapability("editor") && object.getCapability("editor").isEditing());
}
});
// Like all policies, allow by default.
return true;
};
return EditableLinkPolicy;
});

View File

@@ -0,0 +1,51 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define([], function () {
"use strict";
/**
* Policy suppressing move actions among editable and non-editable
* domain objects.
* @memberof platform/commonUI/edit
* @constructor
* @implements {Policy.<View, DomainObject>}
*/
function EditableMovePolicy() {
}
EditableMovePolicy.prototype.allow = function (action, context) {
var domainObject = context.domainObject,
selectedObject = context.selectedObject,
key = action.getMetadata().key;
if (key === 'move' && domainObject.hasCapability('editor') && domainObject.getCapability('editor').isEditing()) {
return !!selectedObject && selectedObject.hasCapability('editor') && selectedObject.getCapability('editor').isEditing();
}
// Like all policies, allow by default.
return true;
};
return EditableMovePolicy;
});

View File

@@ -39,7 +39,7 @@ define(
// If a view is flagged as non-editable, only allow it
// while we're not in Edit mode.
if ((view || {}).editable === false) {
return !domainObject.hasCapability('editor');
return !(domainObject.hasCapability('editor') && domainObject.getCapability('editor').isEditing());
}
// Like all policies, allow by default.

View File

@@ -118,8 +118,6 @@ define(
// Track the represented object
this.domainObject = representedObject;
this.scope.isEditable = representedObject.getCapability('status').get('editing');
// Ensure existing watches are released
this.destroy();

View File

@@ -19,33 +19,29 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
.select {
@include btnSubtle($colorSelectBg);
@if $shdwBtns != none {
margin: 0 0 2px 0; // Needed to avoid dropshadow from being clipped by parent containers
}
padding: 0 $interiorMargin;
overflow: hidden;
position: relative;
line-height: $formInputH;
select {
@include appearance(none);
box-sizing: border-box;
background: none;
color: $colorSelectFg;
cursor: pointer;
border: none !important;
padding: 4px 25px 2px 0px;
width: 130%;
option {
margin: $interiorMargin 0; // Firefox
/*global define*/
define(
[],
function() {
function DirtyModelCache(topic) {
this.cache = {};
}
}
&:after {
@include contextArrow();
pointer-events: none;
color: rgba($colorSelectFg, percentToDecimal($contrastInvokeMenuPercent));
position: absolute;
right: $interiorMargin; top: 0;
}
}
DirtyModelCache.prototype.get = function () {
return this.cache;
};
DirtyModelCache.prototype.isDirty = function (domainObject) {
return !!this.cache[domainObject.getId()];
};
DirtyModelCache.prototype.markDirty = function (domainObject) {
this.cache[domainObject.getId()] = domainObject;
};
DirtyModelCache.prototype.markClean = function (domainObject) {
delete this.cache[domainObject.getId()];
};
return DirtyModelCache;
});

View File

@@ -0,0 +1,118 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define(
[],
function() {
/**
* Implements an application-wide transaction state. Once a
* transaction is started, calls to PersistenceCapability.persist()
* will be deferred until a subsequent call to
* TransactionService.commit() is made.
*
* @param $q
* @constructor
*/
function TransactionService($q, dirtyModelCache) {
this.$q = $q;
this.transaction = false;
this.committing = false;
this.cache = dirtyModelCache;
}
TransactionService.prototype.startTransaction = function () {
if (this.transaction)
console.error("Transaction already in progress")
this.transaction = true;
};
TransactionService.prototype.isActive = function () {
return this.transaction;
};
TransactionService.prototype.isCommitting = function () {
return this.committing;
};
/**
* All persist calls deferred since the beginning of the transaction
* will be committed. Any failures will be reported via a promise
* rejection.
* @returns {*}
*/
TransactionService.prototype.commit = function () {
var self = this;
cache = this.cache.get();
this.committing = true;
function keyToObject(key) {
return cache[key];
}
function objectToPromise(object) {
return object.getCapability('persistence').persist();
}
return this.$q.all(
Object.keys(cache)
.map(keyToObject)
.map(objectToPromise))
.then(function () {
self.transaction = false;
this.committing = false;
}).catch(function() {
return this.committing = false;
});
};
/**
* Cancel the current transaction, replacing any dirty objects from
* persistence. Not a true rollback, as it cannot be used to undo any
* persist calls that were successful in the event one of a batch of
* persists failing.
*
* @returns {*}
*/
TransactionService.prototype.cancel = function () {
var self = this,
cache = this.cache.get();
function keyToObject(key) {
return cache[key];
}
function objectToPromise(object) {
return self.$q.when(object.getModel().persisted && object.getCapability('persistence').refresh());
}
return this.$q.all(Object.keys(cache)
.map(keyToObject)
.map(objectToPromise))
.then(function () {
self.transaction = false;
this.committing = false;
});
};
return TransactionService;
});

View File

@@ -1,75 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine*/
define(
["../../src/capabilities/EditableCompositionCapability"],
function (EditableCompositionCapability) {
"use strict";
describe("An editable composition capability", function () {
var mockContext,
mockEditableObject,
mockDomainObject,
mockTestObject,
someValue,
mockFactory,
capability;
beforeEach(function () {
// EditableContextCapability should watch ALL
// methods for domain objects, so give it an
// arbitrary interface to wrap.
mockContext =
jasmine.createSpyObj("context", [ "getDomainObject" ]);
mockTestObject = jasmine.createSpyObj(
"domainObject",
[ "getId", "getModel", "getCapability" ]
);
mockFactory =
jasmine.createSpyObj("factory", ["getEditableObject"]);
someValue = { x: 42 };
mockContext.getDomainObject.andReturn(mockTestObject);
mockFactory.getEditableObject.andReturn(someValue);
capability = new EditableCompositionCapability(
mockContext,
mockEditableObject,
mockDomainObject,
mockFactory
);
});
// Most behavior is tested for EditableLookupCapability,
// so just verify that this isse
it("presumes non-idempotence of its wrapped capability", function () {
expect(capability.getDomainObject())
.toEqual(capability.getDomainObject());
expect(mockContext.getDomainObject.calls.length).toEqual(2);
});
});
}
);

View File

@@ -1,89 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine*/
define(
["../../src/capabilities/EditableContextCapability"],
function (EditableContextCapability) {
"use strict";
describe("An editable context capability", function () {
var mockContext,
mockEditableObject,
mockDomainObject,
mockTestObject,
someValue,
mockFactory,
capability;
beforeEach(function () {
// EditableContextCapability should watch ALL
// methods for domain objects, so give it an
// arbitrary interface to wrap.
mockContext =
jasmine.createSpyObj("context", [ "getDomainObject", "getRoot" ]);
mockTestObject = jasmine.createSpyObj(
"domainObject",
[ "getId", "getModel", "getCapability" ]
);
mockFactory = jasmine.createSpyObj(
"factory",
["getEditableObject", "isRoot"]
);
someValue = { x: 42 };
mockContext.getRoot.andReturn(mockTestObject);
mockContext.getDomainObject.andReturn(mockTestObject);
mockFactory.getEditableObject.andReturn(someValue);
mockFactory.isRoot.andReturn(true);
capability = new EditableContextCapability(
mockContext,
mockEditableObject,
mockDomainObject,
mockFactory
);
});
it("presumes idempotence of its wrapped capability", function () {
expect(capability.getDomainObject())
.toEqual(capability.getDomainObject());
expect(mockContext.getDomainObject.calls.length).toEqual(1);
});
it("hides the root object", function () {
expect(capability.getRoot()).toEqual(mockEditableObject);
expect(capability.getPath()).toEqual([mockEditableObject]);
});
it("exposes the root object through a different method", function () {
// Should still go through the factory...
expect(capability.getTrueRoot()).toEqual(someValue);
// ...with value of the unwrapped capability's getRoot
expect(mockFactory.getEditableObject)
.toHaveBeenCalledWith(mockTestObject);
});
});
}
);

View File

@@ -1,146 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine*/
define(
["../../src/capabilities/EditableLookupCapability"],
function (EditableLookupCapability) {
"use strict";
describe("An editable lookup capability", function () {
var mockContext,
mockEditableObject,
mockDomainObject,
mockTestObject,
someValue,
factory,
capability;
beforeEach(function () {
// EditableContextCapability should watch ALL
// methods for domain objects, so give it an
// arbitrary interface to wrap.
mockContext = jasmine.createSpyObj(
"context",
[
"getSomething",
"getDomainObject",
"getDomainObjectArray"
]
);
mockTestObject = jasmine.createSpyObj(
"domainObject",
[ "getId", "getModel", "getCapability" ]
);
factory = {
getEditableObject: function (v) {
return {
isFromTestFactory: true,
calledWith: v
};
}
};
someValue = { x: 42 };
mockContext.getSomething.andReturn(someValue);
mockContext.getDomainObject.andReturn(mockTestObject);
mockContext.getDomainObjectArray.andReturn([mockTestObject]);
capability = new EditableLookupCapability(
mockContext,
mockEditableObject,
mockDomainObject,
factory,
false
);
});
it("wraps retrieved domain objects", function () {
var object = capability.getDomainObject();
expect(object.isFromTestFactory).toBe(true);
expect(object.calledWith).toEqual(mockTestObject);
});
it("wraps retrieved domain object arrays", function () {
var object = capability.getDomainObjectArray()[0];
expect(object.isFromTestFactory).toBe(true);
expect(object.calledWith).toEqual(mockTestObject);
});
it("does not wrap non-domain-objects", function () {
expect(capability.getSomething()).toEqual(someValue);
});
it("caches idempotent lookups", function () {
capability = new EditableLookupCapability(
mockContext,
mockEditableObject,
mockDomainObject,
factory,
true // idempotent
);
expect(capability.getDomainObject())
.toEqual(capability.getDomainObject());
expect(mockContext.getDomainObject.calls.length).toEqual(1);
});
it("does not cache non-idempotent lookups", function () {
capability = new EditableLookupCapability(
mockContext,
mockEditableObject,
mockDomainObject,
factory,
false // Not idempotent
);
expect(capability.getDomainObject())
.toEqual(capability.getDomainObject());
expect(mockContext.getDomainObject.calls.length).toEqual(2);
});
it("wraps inherited methods", function () {
var CapabilityClass = function(){
};
CapabilityClass.prototype.inheritedMethod=function () {
return "an inherited method";
};
mockContext = new CapabilityClass();
capability = new EditableLookupCapability(
mockContext,
mockEditableObject,
mockDomainObject,
factory,
false
);
expect(capability.inheritedMethod()).toEqual("an inherited method");
expect(capability.hasOwnProperty('inheritedMethod')).toBe(true);
// The presence of an own property indicates that the method
// has been wrapped on the object itself and this is a valid
// test that the inherited method has been wrapped.
});
});
}
);

View File

@@ -1,96 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine*/
define(
["../../src/capabilities/EditablePersistenceCapability"],
function (EditablePersistenceCapability) {
"use strict";
describe("An editable persistence capability", function () {
var mockPersistence,
mockEditableObject,
mockDomainObject,
mockCache,
mockPromise,
capability;
beforeEach(function () {
mockPersistence = jasmine.createSpyObj(
"persistence",
[ "persist", "refresh" ]
);
mockEditableObject = jasmine.createSpyObj(
"editableObject",
[ "getId", "getModel", "getCapability" ]
);
mockDomainObject = jasmine.createSpyObj(
"editableObject",
[ "getId", "getModel", "getCapability" ]
);
mockCache = jasmine.createSpyObj(
"cache",
[ "markDirty" ]
);
mockPromise = jasmine.createSpyObj("promise", ["then"]);
mockCache.markDirty.andReturn(mockPromise);
mockDomainObject.getCapability.andReturn(mockPersistence);
capability = new EditablePersistenceCapability(
mockPersistence,
mockEditableObject,
mockDomainObject,
mockCache
);
});
it("marks objects as dirty (in the cache) upon persist", function () {
capability.persist();
expect(mockCache.markDirty)
.toHaveBeenCalledWith(mockEditableObject);
});
it("does not invoke the underlying persistence capability", function () {
capability.persist();
expect(mockPersistence.persist).not.toHaveBeenCalled();
});
it("refreshes using the original domain object's persistence", function () {
// Refreshing needs to delegate via the unwrapped domain object.
// Otherwise, only the editable version of the object will be updated;
// we instead want the real version of the object to receive these
// changes.
expect(mockDomainObject.getCapability).not.toHaveBeenCalled();
expect(mockPersistence.refresh).not.toHaveBeenCalled();
capability.refresh();
expect(mockDomainObject.getCapability).toHaveBeenCalledWith('persistence');
expect(mockPersistence.refresh).toHaveBeenCalled();
});
it("returns a promise from persist", function () {
expect(capability.persist().then).toEqual(jasmine.any(Function));
});
});
}
);

View File

@@ -1,75 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine*/
define(
["../../src/capabilities/EditableRelationshipCapability"],
function (EditableRelationshipCapability) {
"use strict";
describe("An editable relationship capability", function () {
var mockContext,
mockEditableObject,
mockDomainObject,
mockTestObject,
someValue,
mockFactory,
capability;
beforeEach(function () {
// EditableContextCapability should watch ALL
// methods for domain objects, so give it an
// arbitrary interface to wrap.
mockContext =
jasmine.createSpyObj("context", [ "getDomainObject" ]);
mockTestObject = jasmine.createSpyObj(
"domainObject",
[ "getId", "getModel", "getCapability" ]
);
mockFactory =
jasmine.createSpyObj("factory", ["getEditableObject"]);
someValue = { x: 42 };
mockContext.getDomainObject.andReturn(mockTestObject);
mockFactory.getEditableObject.andReturn(someValue);
capability = new EditableRelationshipCapability(
mockContext,
mockEditableObject,
mockDomainObject,
mockFactory
);
});
// Most behavior is tested for EditableLookupCapability,
// so just verify that this isse
it("presumes non-idempotence of its wrapped capability", function () {
expect(capability.getDomainObject())
.toEqual(capability.getDomainObject());
expect(mockContext.getDomainObject.calls.length).toEqual(2);
});
});
}
);

View File

@@ -1,180 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine*/
define(
["../../src/objects/EditableDomainObjectCache"],
function (EditableDomainObjectCache) {
'use strict';
describe("Editable domain object cache", function () {
var captured,
completionCapability,
object,
mockQ,
mockType,
cache;
// Constructors for test objects
function TestObject(id) {
return {
getId: function () { return id; },
getModel: function () { return {}; },
getCapability: function (key) {
return {
editor: completionCapability,
type: mockType
}[key];
},
hasCapability: function (key) {
return false;
}
};
}
function WrapObject(domainObject, model) {
var result = Object.create(domainObject);
result.wrapped = true;
result.wrappedModel = model;
result.hasCapability = function (name) {
return name === 'editor';
};
captured.wraps = (captured.wraps || 0) + 1;
return result;
}
beforeEach(function () {
mockQ = jasmine.createSpyObj('$q', ['when', 'all']);
mockType = jasmine.createSpyObj('type', ['hasFeature']);
mockType.hasFeature.andReturn(true);
captured = {};
completionCapability = {
save: function () {
captured.saved = (captured.saved || 0) + 1;
}
};
cache = new EditableDomainObjectCache(WrapObject, mockQ);
});
it("wraps objects using provided constructor", function () {
var domainObject = new TestObject('test-id'),
wrappedObject = cache.getEditableObject(domainObject);
expect(wrappedObject.wrapped).toBeTruthy();
expect(wrappedObject.getId()).toEqual(domainObject.getId());
});
it("wraps objects repeatedly, wraps models once", function () {
var domainObject = new TestObject('test-id'),
wrappedObjects = [];
// Verify precondition
expect(captured.wraps).toBeUndefined();
// Invoke a few more times; expect count not to increment
wrappedObjects.push(cache.getEditableObject(domainObject));
expect(captured.wraps).toEqual(1);
wrappedObjects.push(cache.getEditableObject(domainObject));
expect(captured.wraps).toEqual(2);
wrappedObjects.push(cache.getEditableObject(domainObject));
expect(captured.wraps).toEqual(3);
// Verify that the last call still gave us a wrapped object
expect(wrappedObjects[0].wrapped).toBeTruthy();
expect(wrappedObjects[0].getId()).toEqual(domainObject.getId());
// Verify that objects are distinct but models are identical
expect(wrappedObjects[0].wrappedModel)
.toBe(wrappedObjects[1].wrappedModel);
expect(wrappedObjects[0]).not
.toBe(wrappedObjects[1]);
});
it("saves objects that have been marked dirty", function () {
var objects = ['a', 'b', 'c'].map(TestObject).map(function (domainObject) {
return cache.getEditableObject(domainObject);
});
cache.markDirty(objects[0]);
cache.markDirty(objects[2]);
cache.saveAll();
expect(captured.saved).toEqual(2);
});
it("does not save objects that have been marked clean", function () {
var objects = ['a', 'b', 'c'].map(TestObject).map(function (domainObject) {
return cache.getEditableObject(domainObject);
});
cache.markDirty(objects[0]);
cache.markDirty(objects[2]);
cache.markClean(objects[0]);
cache.saveAll();
expect(captured.saved).toEqual(1);
});
it("tracks the root object of the Edit mode subgraph", function () {
// Root object is the first object exposed to the cache
var domainObjects = ['a', 'b', 'c'].map(TestObject);
domainObjects.forEach(function (obj) {
cache.getEditableObject(obj);
});
expect(cache.isRoot(domainObjects[0])).toBeTruthy();
expect(cache.isRoot(domainObjects[1])).toBeFalsy();
expect(cache.isRoot(domainObjects[2])).toBeFalsy();
});
it("does not double-wrap objects", function () {
var domainObject = new TestObject('test-id'),
wrappedObject = cache.getEditableObject(domainObject);
// Same instance should be returned if you try to wrap
// twice. This is necessary, since it's possible to (e.g.)
// use a context capability on an object retrieved via
// composition, in which case a result will already be
// wrapped.
expect(cache.getEditableObject(wrappedObject))
.toBe(wrappedObject);
});
it("does not wrap non-editable objects", function () {
var domainObject = new TestObject('test-id');
mockType.hasFeature.andCallFake(function (key) {
return key !== 'creation';
});
expect(cache.getEditableObject(domainObject))
.toBe(domainObject);
});
});
}
);

View File

@@ -1,81 +0,0 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine*/
define(
["../../src/objects/EditableModelCache"],
function (EditableModelCache) {
"use strict";
describe("The editable model cache", function () {
var mockObject,
mockOtherObject,
testModel,
testId,
otherModel,
otherId,
cache;
beforeEach(function () {
testId = "test";
testModel = { someKey: "some value" };
otherId = "other";
otherModel = { someKey: "some other value" };
mockObject = jasmine.createSpyObj(
"domainObject",
[ "getId", "getModel" ]
);
mockOtherObject = jasmine.createSpyObj(
"domainObject",
[ "getId", "getModel" ]
);
mockObject.getId.andReturn(testId);
mockObject.getModel.andReturn(testModel);
mockOtherObject.getId.andReturn(otherId);
mockOtherObject.getModel.andReturn(otherModel);
cache = new EditableModelCache();
});
it("provides clones of domain object models", function () {
var model = cache.getCachedModel(mockObject);
// Should be identical...
expect(model).toEqual(testModel);
// ...but not pointer-identical
expect(model).not.toBe(testModel);
});
it("provides only one clone per object", function () {
var model = cache.getCachedModel(mockObject);
expect(cache.getCachedModel(mockObject)).toBe(model);
});
it("maintains separate caches per-object", function () {
expect(cache.getCachedModel(mockObject))
.not.toEqual(cache.getCachedModel(mockOtherObject));
});
});
}
);

View File

@@ -35,19 +35,43 @@ define(
mockDomainObject,
mockEditAction,
mockPropertiesAction,
mockTypeCapability,
mockStatusCapability,
capabilities,
plotView,
policy;
beforeEach(function () {
mockDomainObject = jasmine.createSpyObj(
'domainObject',
[ 'useCapability' ]
[
'useCapability',
'hasCapability',
'getCapability'
]
);
mockStatusCapability = jasmine.createSpyObj('statusCapability', ['get']);
mockStatusCapability.get.andReturn(false);
mockTypeCapability = jasmine.createSpyObj('type', ['getKey']);
capabilities = {
'status': mockStatusCapability,
'type': mockTypeCapability
};
mockEditAction = jasmine.createSpyObj('edit', ['getMetadata']);
mockPropertiesAction = jasmine.createSpyObj('edit', ['getMetadata']);
mockDomainObject.getCapability.andCallFake(function(capability){
return capabilities[capability];
});
mockDomainObject.hasCapability.andCallFake(function(capability){
return !!capabilities[capability];
});
editableView = { editable: true };
nonEditableView = { editable: false };
undefinedView = { someKey: "some value" };
plotView = { key: "plot", editable: false };
testViews = [];
mockDomainObject.useCapability.andCallFake(function (c) {
@@ -66,38 +90,53 @@ define(
policy = new EditActionPolicy();
});
//TODO: Disabled for NEM Beta
xit("allows the edit action when there are editable views", function () {
it("allows the edit action when there are editable views", function () {
testViews = [ editableView ];
expect(policy.allow(mockEditAction, testContext)).toBeTruthy();
// No edit flag defined; should be treated as editable
testViews = [ undefinedView, undefinedView ];
expect(policy.allow(mockEditAction, testContext)).toBeTruthy();
expect(policy.allow(mockEditAction, testContext)).toBe(true);
});
//TODO: Disabled for NEM Beta
xit("allows the edit properties action when there are no editable views", function () {
it("allows the edit properties action when there are no editable views", function () {
testViews = [ nonEditableView, nonEditableView ];
expect(policy.allow(mockPropertiesAction, testContext)).toBeTruthy();
expect(policy.allow(mockPropertiesAction, testContext)).toBe(true);
});
//TODO: Disabled for NEM Beta
xit("disallows the edit action when there are no editable views", function () {
it("disallows the edit action when there are no editable views", function () {
testViews = [ nonEditableView, nonEditableView ];
expect(policy.allow(mockEditAction, testContext)).toBeFalsy();
expect(policy.allow(mockEditAction, testContext)).toBe(false);
});
//TODO: Disabled for NEM Beta
xit("disallows the edit properties action when there are" +
it("disallows the edit properties action when there are" +
" editable views", function () {
testViews = [ editableView ];
expect(policy.allow(mockPropertiesAction, testContext)).toBeFalsy();
expect(policy.allow(mockPropertiesAction, testContext)).toBe(false);
});
it("disallows the edit action when object is already being" +
" edited", function () {
testViews = [ editableView ];
mockStatusCapability.get.andReturn(true);
expect(policy.allow(mockEditAction, testContext)).toBe(false);
});
it("allows editing of panels in plot view", function () {
testViews = [ plotView ];
mockTypeCapability.getKey.andReturn('telemetry.panel');
expect(policy.allow(mockEditAction, testContext)).toBe(true);
});
it("disallows editing of plot view when object not a panel type", function () {
testViews = [ plotView ];
mockTypeCapability.getKey.andReturn('something.else');
expect(policy.allow(mockEditAction, testContext)).toBe(false);
});
it("allows the edit properties outside of the 'view-control' category", function () {
testViews = [ nonEditableView ];
testContext.category = "something-else";
expect(policy.allow(mockPropertiesAction, testContext)).toBeTruthy();
expect(policy.allow(mockPropertiesAction, testContext)).toBe(true);
});
});
}

View File

@@ -0,0 +1,85 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,describe,it,expect,beforeEach,jasmine,xit,xdescribe*/
define(
["../../src/policies/EditContextualActionPolicy"],
function (EditContextualActionPolicy) {
"use strict";
describe("The Edit contextual action policy", function () {
var policy,
navigationService,
mockAction,
context,
navigatedObject,
mockDomainObject,
metadata;
beforeEach(function () {
navigatedObject = jasmine.createSpyObj("navigatedObject", ["hasCapability"]);
navigatedObject.hasCapability.andReturn(false);
mockDomainObject = jasmine.createSpyObj("domainObject", ["hasCapability"]);
mockDomainObject.hasCapability.andReturn(false);
navigationService = jasmine.createSpyObj("navigationService", ["getNavigation"]);
navigationService.getNavigation.andReturn(navigatedObject);
metadata = {key: "move"};
mockAction = jasmine.createSpyObj("action", ["getMetadata"]);
mockAction.getMetadata.andReturn(metadata);
context = {domainObject: mockDomainObject};
policy = new EditContextualActionPolicy(navigationService);
});
it('Allows all actions when navigated object not in edit mode', function() {
expect(policy.allow(mockAction, context)).toBe(true);
});
it('Allows "window" action when navigated object in edit mode,' +
' but selected object not in edit mode ', function() {
navigatedObject.hasCapability.andReturn(true);
metadata.key = "window";
expect(policy.allow(mockAction, context)).toBe(true);
});
it('Disallows "move" action when navigated object in edit mode,' +
' but selected object not in edit mode ', function() {
navigatedObject.hasCapability.andReturn(true);
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);
metadata.key = "copy";
expect(policy.allow(mockAction, context)).toBe(false);
});
});
}
);

View File

@@ -28,9 +28,10 @@ define([
) {
"use strict";
var DATE_FORMAT = "YYYY-MM-DD HH:mm:ss",
var DATE_FORMAT = "YYYY-MM-DD HH:mm:ss.SSS",
DATE_FORMATS = [
DATE_FORMAT,
"YYYY-MM-DD HH:mm:ss",
"YYYY-MM-DD HH:mm",
"YYYY-MM-DD"
];
@@ -48,7 +49,7 @@ define([
}
UTCTimeFormat.prototype.format = function (value) {
return moment.utc(value).format(DATE_FORMAT);
return moment.utc(value).format(DATE_FORMAT) + "Z";
};
UTCTimeFormat.prototype.parse = function (text) {

View File

@@ -40,6 +40,12 @@ define(
expect(moment.utc(formatted).valueOf()).toEqual(timestamp);
});
it("displays with millisecond precision", function () {
var timestamp = 12345670789,
formatted = format.format(timestamp);
expect(moment.utc(formatted).valueOf()).toEqual(timestamp);
});
it("validates time inputs", function () {
expect(format.validate("1977-05-25 11:21:22")).toBe(true);
expect(format.validate("garbage text")).toBe(false);

View File

@@ -49,6 +49,7 @@ define([
"./src/directives/MCTScroll",
"./src/directives/MCTSplitPane",
"./src/directives/MCTSplitter",
"./src/directives/MCTTree",
"text!./res/templates/bottombar.html",
"text!./res/templates/controls/action-button.html",
"text!./res/templates/controls/input-filter.html",
@@ -97,6 +98,7 @@ define([
MCTScroll,
MCTSplitPane,
MCTSplitter,
MCTTree,
bottombarTemplate,
actionButtonTemplate,
inputFilterTemplate,
@@ -175,10 +177,6 @@ define([
{
"stylesheetUrl": "css/normalize.min.css",
"priority": "mandatory"
},
{
"stylesheetUrl": "css/reset.css",
"priority": "mandatory"
}
],
"templates": [
@@ -389,6 +387,11 @@ define([
{
"key": "mctSplitter",
"implementation": MCTSplitter
},
{
"key": "mctTree",
"implementation": MCTTree,
"depends": [ '$parse', 'gestureService' ]
}
],
"constants": [
@@ -516,16 +519,6 @@ define([
}
],
"licenses": [
{
"name": "Modernizr",
"version": "2.6.2",
"description": "Browser/device capability finding",
"author": "Faruk Ateş",
"website": "http://modernizr.com",
"copyright": "Copyright (c) 20092015",
"license": "license-mit",
"link": "http://modernizr.com/license/"
},
{
"name": "Normalize.css",
"version": "1.1.2",
@@ -535,6 +528,16 @@ define([
"copyright": "Copyright (c) Nicolas Gallagher and Jonathan Neal",
"license": "license-mit",
"link": "https://github.com/necolas/normalize.css/blob/v1.1.2/LICENSE.md"
},
{
"name": "Zepto",
"version": "1.1.6",
"description": "DOM manipulation",
"author": "Thomas Fuchs",
"website": "http://zeptojs.com/",
"copyright": "Copyright (c) 2010-2016 Thomas Fuchs",
"license": "license-mit",
"link": "https://github.com/madrobby/zepto/blob/master/MIT-LICENSE"
}
]
}

File diff suppressed because one or more lines are too long

View File

@@ -80,7 +80,7 @@
<glyph unicode="&#xe601;" glyph-name="icon-datatable" d="M1024 768c0-106.039-229.23-192-512-192s-512 85.961-512 192c0 106.039 229.23 192 512 192s512-85.961 512-192zM512 448c-282.8 0-512 86-512 192v-512c0-106 229.2-192 512-192s512 86 512 192v512c0-106-229.2-192-512-192zM896 385v-256c-36.6-15.6-79.8-28.8-128-39.4v256c48.2 10.6 91.4 23.8 128 39.4zM256 345.6v-256c-48.2 10.4-91.4 23.8-128 39.4v256c36.6-15.6 79.8-28.8 128-39.4zM384 70v256c41-4 83.8-6 128-6s87 2.2 128 6v-256c-41-4-83.8-6-128-6s-87 2.2-128 6z" />
<glyph unicode="&#xe602;" glyph-name="icon-tabular-scrolling" d="M64 960c-35.2 0-64-28.8-64-64v-192h448v256h-384zM1024 704v192c0 35.2-28.8 64-64 64h-384v-256h448zM0 576v-192c0-35.2 28.8-64 64-64h384v256h-448zM960 320c35.2 0 64 28.8 64 64v192h-448v-256h384zM512-64l-256 256h512z" />
<glyph unicode="&#xe603;" glyph-name="icon-alert-triangle" d="M998.208 111.136l-422.702 739.728c-34.928 61.124-92.084 61.124-127.012 0l-422.702-739.728c-34.928-61.126-5.906-111.136 64.494-111.136h843.428c70.4 0 99.422 50.010 64.494 111.136zM512 128c-35.2 0-64 28.8-64 64s28.8 64 64 64 64-28.8 64-64c0-35.2-28.8-64-64-64zM627.448 577.242l-38.898-194.486c-6.902-34.516-41.35-62.756-76.55-62.756s-69.648 28.24-76.552 62.758l-38.898 194.486c-6.902 34.516 16.25 62.756 51.45 62.756h128c35.2 0 58.352-28.24 51.448-62.758z" />
<glyph unicode="&#xe604;" glyph-name="icon-tabular" d="M0 896v-192h448v256h-384c-35.2 0-64-28.8-64-64zM960 960h-384v-256h448v192c0 35.2-28.8 64-64 64zM576 576h448v-256h-448v256zM0 576h448v-256h-448v256zM0 0c0-35.2 28.8-64 64-64h384v256h-448v-192zM576-64h384c35.2 0 64 28.8 64 64v192h-448v-256z" />
<glyph unicode="&#xe604;" glyph-name="icon-tabular" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM640 512h-256v192h256v-192zM384 448h256v-192h-256v192zM320 256h-256v192h256v-192zM320 704v-192h-256v192h256zM128 0c-17 0-33 6.6-45.2 18.8s-18.8 28.2-18.8 45.2v128h256v-192h-192zM384 0v192h256v-192h-256zM960 64c0-17-6.6-33-18.8-45.2s-28.2-18.8-45.2-18.8h-192v192h256v-128zM960 256h-256v192h256v-192zM960 512h-256v192h256v-192z" />
<glyph unicode="&#xe605;" glyph-name="icon-calendar" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM640 512h-256v192h256v-192zM384 448h256v-192h-256v192zM320 256h-256v192h256v-192zM320 704v-192h-256v192h256zM128 0c-17 0-33 6.6-45.2 18.8s-18.8 28.2-18.8 45.2v128h256v-192h-192zM384 0v192h256v-192h-256zM960 64c0-17-6.6-33-18.8-45.2s-28.2-18.8-45.2-18.8h-192v192h256v-128zM960 256h-256v192h256v-192zM960 512h-256v192h256v-192z" />
<glyph unicode="&#xe606;" 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" />
<glyph unicode="&#xe607;" glyph-name="icon-x-in-circle" d="M512 960c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM832 256l-128-128-192 192-192-192-128 128 192 192-192 192 128 128 192-192 192 192 128-128-192-192 192-192z" />
@@ -94,8 +94,11 @@
<glyph unicode="&#xe614;" glyph-name="icon-collapse-pane-right" d="M768 960h256v-1024h-256c-105.6 0-192 86.4-192 192v640c0 105.6 86.4 192 192 192zM512 640l-512-320v640z" />
<glyph unicode="&#xe615;" glyph-name="icon-eye-open" d="M512 896c-261 0-480.6-195.4-512-448 31.4-252.6 251-448 512-448s480.6 195.4 512 448c-31.4 252.6-251 448-512 448zM768.2 225.4c-71.4-62.8-162.8-97.4-257.6-97.4s-186.2 34.6-257.6 97.4c-66.6 58.6-110.6 137.2-125 222.6 0 0 0 0.2 0 0.2 76.8 154 220.8 257.6 384 257.6s307.2-103.8 384-257.6c0 0 0-0.2 0-0.2-14.4-85.4-61.2-164-127.8-222.6zM512 672c-123.8 0-224-100.2-224-224s100.2-224 224-224 224 100.2 224 224-100.2 224-224 224z" />
<glyph unicode="&#xe616;" glyph-name="icon-eye-open-no-gleam" d="M512 896c-261 0-480.6-195.4-512-448 31.4-252.6 251-448 512-448s480.6 195.4 512 448c-31.4 252.6-251 448-512 448zM768.2 225.4c-71.4-62.8-162.8-97.4-257.6-97.4s-186.2 34.6-257.6 97.4c-66.6 58.6-110.6 137.2-125 222.6 0 0 0 0.2 0 0.2 76.8 154 220.8 257.6 384 257.6s307.2-103.8 384-257.6c0 0 0-0.2 0-0.2-14.4-85.4-61.2-164-127.8-222.6zM512 672c-123.8 0-224-100.2-224-224s100.2-224 224-224 224 100.2 224 224-100.2 224-224 224zM576 416c-53 0-96 43-96 96s43 96 96 96 96-43 96-96c0-53-43-96-96-96z" />
<glyph unicode="&#xe617;" glyph-name="icon-topic" d="M546.4 528.8l32 24c31.6 23.8 91.6 23.8 123.2 0l32-24c10.8-8 22.2-15.2 34.4-21.4v201.2c-38 19.6-82.2 30-128 30-60.4 0-118.2-18.2-162.4-51.4l-32-24c-31.6-23.8-91.6-23.8-123.2 0l-32 24c-10.8 8-22.2 15.2-34.4 21.4v-201.2c38-19.6 82.2-30 128-30 60.4 0 118.2 18.2 162.4 51.4zM640 418.6c-60.4 0-118.2-18.2-162.4-51.4l-32-24c-31.6-23.8-91.6-23.8-123.2 0l-32 24c-10.8 8-22.2 15.2-34.4 21.4v-201.2c38-19.6 82.2-30 128-30 60.4 0 118.2 18.2 162.4 51.4l32 24c31.6 23.8 91.6 23.8 123.2 0l32-24c10.8-8 22.2-15.2 34.4-21.4v201.2c-38 19.6-82.2 30-128 30zM832 960h-128v-192h127.6c0.2 0 0.2-0.2 0.4-0.4v-639.4c0-0.2-0.2-0.2-0.4-0.4h-127.6v-192h128c105.6 0 192 86.4 192 192v640.2c0 105.6-86.4 192-192 192zM320 128h-127.6c-0.2 0-0.2 0.2-0.4 0.4v639.4c0 0.2 0.2 0.2 0.4 0.4h127.6v191.8h-128c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h128v192z" />
<glyph unicode="&#xe618;" glyph-name="icon-session" d="M923 521.8l-151 100.6c-36 24-103.8 24-139.8 0l-151-100.6c-44.6-29.8-102.6-46.2-163-46.2s-118.4 16.4-163 46.2l-151.4 100.6c-1.8 1.2-3.8 2.4-5.8 3.6v-208c36.6-7.4 70.6-20.8 99-39.8l151-100.6c36-24 103.8-24 139.8 0l151 100.6c44.6 29.8 102.6 46.2 163 46.2s118.4-16.4 163-46.2l151-100.6c1.8-1.2 3.8-2.4 5.8-3.6v208c-36.2 7.2-70.2 20.8-98.6 39.8zM923 137.8l-151 100.6c-36 24-103.8 24-139.8 0l-151-100.6c-44.6-29.8-102.6-46.2-163-46.2s-118.4 16.4-163 46.2l-151.4 100.6c-1.8 1.2-3.8 2.4-5.8 3.6v-112c0-105.6 86.4-192 192-192h640c94.8 0 174.2 69.8 189.4 160.4-35.6 7.4-68.6 20.8-96.4 39.4zM97 762.2l151-100.6c36-24 103.8-24 139.8 0l151 100.6c44.8 29.8 102.6 46.2 163.2 46.2s118.4-16.4 163-46.2l151-100.6c1.8-1.2 3.8-2.4 5.8-3.6v112c0 105.6-86.4 192-192 192h-639.8c-94.8 0-174.2-69.8-189.4-160.4 35.6-7.4 68.6-20.8 96.4-39.4z" />
<glyph unicode="&#xe617;" glyph-name="icon-topic" d="M454.36 483.36l86.3 86.3c9.088 8.965 21.577 14.502 35.36 14.502s26.272-5.537 35.366-14.507l86.294-86.294c19.328-19.358 42.832-34.541 69.047-44.082l1.313 171.722-57.64 57.64c-34.407 34.33-81.9 55.558-134.35 55.558s-99.943-21.228-134.354-55.562l-86.296-86.297c-9.088-8.965-21.577-14.502-35.36-14.502s-26.272 5.537-35.366 14.507l-28.674 28.654v-172.14c19.045-7.022 41.040-11.084 63.984-11.084 52.463 0 99.966 21.239 134.379 55.587zM505.64 412.64l-86.3-86.3c-9.088-8.965-21.577-14.502-35.36-14.502s-26.272 5.537-35.366 14.507l-86.294 86.294c-2 2-4.2 4-6.36 6v-197.36c33.664-30.72 78.65-49.537 128.031-49.537 52.44 0 99.923 21.22 134.333 55.541l86.296 86.296c9.088 8.965 21.577 14.502 35.36 14.502s26.272-5.537 35.366-14.507l86.294-86.294c2-2 4.2-4 6.36-6v197.36c-33.664 30.72-78.65 49.537-128.031 49.537-52.44 0-99.923-21.22-134.333-55.541zM832 960h-128v-192h127.66l0.34-0.34v-639.32l-0.34-0.34h-127.66v-192h128c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM320 128h-127.66l-0.34 0.34v639.32l0.34 0.34h127.66v192h-128c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h128v192z" />
<glyph unicode="&#xe618;" glyph-name="icon-session" d="M635.6 435.6c6.6-4.2 13.2-8.6 19.2-13.6l120.4-96.4c29.6-23.8 83.8-23.8 113.4 0l135.2 108c0.2 4.8 0.2 9.4 0.2 14.2 0 52.2-7.8 102.4-22.2 149.8l-154.8-123.6c-58.2-46.6-140.2-59.2-211.4-38.4zM248.6 325.8l120.4 96.4c58 46.4 140 59.2 211.2 38.4-6.6 4.2-13.2 8.6-19.2 13.6l-120.4 96.4c-29.6 23.8-83.8 23.8-113.4 0l-120.2-96.6c-40-32-91.4-48-143-48-21.6 0-43 2.8-63.8 8.4 0-0.6 0-1.2 0-1.6 5-3.4 10-6.8 14.6-10.6l120.4-96.4c29.8-23.8 83.8-23.8 113.4 0zM120.6 581.8l120.4 96.4c80.2 64.2 205.6 64.2 285.8 0l120.4-96.4c29.6-23.8 83.8-23.8 113.4 0l181 144.8c-91.2 140.4-249.6 233.4-429.6 233.4-238.6 0-439.2-163.2-496-384.2 30.8-17.6 77.8-15.6 104.6 6zM689 218l-120.4 96.4c-29.6 23.8-83.8 23.8-113.4 0l-120.2-96.4c-40-32-91.4-48-143-48-47.8 0-95.4 13.8-134.2 41.4 85.6-163.6 256.8-275.4 454.2-275.4s368.6 111.8 454.2 275.4c-80.4-57.4-199.8-55.2-277.2 6.6z" />
<glyph unicode="&#xe619;" glyph-name="icon-bullet" d="M832 208c0-44-36-80-80-80h-480c-44 0-80 36-80 80v480c0 44 36 80 80 80h480c44 0 80-36 80-80v-480z" />
<glyph unicode="&#xe620;" glyph-name="icon-tabular-realtime" d="M896 960h-768c-70.606-0.215-127.785-57.394-128-127.979v-768.021c0.215-70.606 57.394-127.785 127.979-128h768.021c70.606 0.215 127.785 57.394 128 127.979v768.021c-0.215 70.606-57.394 127.785-127.979 128zM448 668l25.060-25.32c7.916-7.922 18.856-12.822 30.94-12.822s23.024 4.9 30.94 12.822l75.5 76.3c29.97 30.338 71.571 49.128 117.56 49.128s87.59-18.79 117.544-49.112l50.456-50.997v-152.2c-24.111 8.83-44.678 22.255-61.542 39.342l-75.518 76.318c-7.916 7.922-18.856 12.822-30.94 12.822s-23.024-4.9-30.94-12.822l-75.5-76.3c-29.971-30.343-71.575-49.137-117.568-49.137-20.084 0-39.331 3.584-57.137 10.146l1.145 151.831zM320 0h-192c-35.26 0.214-63.786 28.74-64 63.98v128.020h256v-192zM320 256h-256v192h256v-192zM320 512h-256v192h256v-192zM640 0h-256v192h256v-192zM448 323.38v174.5c1.88-1.74 3.74-3.5 5.56-5.34l75.5-76.3c7.916-7.922 18.856-12.822 30.94-12.822s23.024 4.9 30.94 12.822l75.5 76.3c29.966 30.333 71.56 49.119 117.542 49.119 43.28 0 82.673-16.644 112.128-43.879l-0.11-174.399c-1.88 1.74-3.74 3.5-5.56 5.34l-75.5 76.3c-7.916 7.922-18.856 12.822-30.94 12.822s-23.024-4.9-30.94-12.822l-75.5-76.3c-29.966-30.333-71.56-49.119-117.542-49.119-43.28 0-82.673 16.644-112.128 43.879zM960 64c-0.214-35.26-28.74-63.786-63.98-64h-192.020v192h256v-128z" />
<glyph unicode="&#xe621;" glyph-name="icon-tabular-lad" d="M896 960h-768c-70.606-0.215-127.785-57.394-128-127.979v-768.021c0.215-70.606 57.394-127.785 127.979-128h768.021c70.606 0.215 127.785 57.394 128 127.979v768.021c-0.215 70.606-57.394 127.785-127.979 128zM64 704h256v-192h-256v192zM64 448h256v-192h-256v192zM128 0c-35.26 0.214-63.786 28.74-64 63.98v128.020h256v-192h-192zM384 0v192h256v-192h-256zM960 64c-0.214-35.26-28.74-63.786-63.98-64h-192.020v192h256v-128zM960 448v-192h-576v192h64v64h-64v192h576v-192h-64v-64h64zM782.32 412.62l-110.32 55.16v172.22c0 17.673-14.327 32-32 32s-32-14.327-32-32v-211.78l145.68-72.84c4.172-2.133 9.1-3.383 14.32-3.383 17.675 0 32.003 14.328 32.003 32.003 0 12.454-7.114 23.247-17.501 28.536z" />
<glyph unicode="&#xe622;" glyph-name="icon-tabular-lad-set" d="M128 192v576c-70.606-0.215-127.785-57.394-128-127.979v-576.021c0.215-70.606 57.394-127.785 127.979-128h576.021c70.606 0.215 127.785 57.394 128 127.979l-576 0.021c-70.606 0.215-127.785 57.394-128 127.979zM896 960h-576c-70.606-0.215-127.785-57.394-128-127.979v-576.021c0.215-70.606 57.394-127.785 127.979-128h576.021c70.606 0.215 127.785 57.394 128 127.979v576.021c-0.215 70.606-57.394 127.785-127.979 128zM256 768h192v-128h-192v128zM256 576h192v-192h-192v192zM320 192c-35.26 0.214-63.786 28.74-64 63.98v64.020h192v-128h-128zM512 192v128h192v-128h-192zM960 256c-0.214-35.26-28.74-63.786-63.98-64h-128.020v128h192v-64zM960 384h-448v384h448v-384zM832 480c0.002 0 0.005 0 0.007 0 17.673 0 32 14.327 32 32 0 14.055-9.062 25.994-21.662 30.293l-74.345 24.767v104.94c0 17.673-14.327 32-32 32s-32-14.327-32-32v-151.060l117.88-39.3c3.018-1.040 6.495-1.64 10.113-1.64 0.003 0 0.005 0 0.008 0z" />
<glyph unicode="&#xe642;" glyph-name="icon-x" d="M384 448l-365.332-365.332c-24.89-24.89-24.89-65.62 0-90.51l37.49-37.49c24.89-24.89 65.62-24.89 90.51 0 0 0 365.332 365.332 365.332 365.332l365.332-365.332c24.89-24.89 65.62-24.89 90.51 0l37.49 37.49c24.89 24.89 24.89 65.62 0 90.51l-365.332 365.332c0 0 365.332 365.332 365.332 365.332 24.89 24.89 24.89 65.62 0 90.51l-37.49 37.49c-24.89 24.89-65.62 24.89-90.51 0 0 0-365.332-365.332-365.332-365.332l-365.332 365.332c-24.89 24.89-65.62 24.89-90.51 0l-37.49-37.49c-24.89-24.89-24.89-65.62 0-90.51 0 0 365.332-365.332 365.332-365.332z" />
</font></defs></svg>

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 35 KiB

View File

@@ -98,6 +98,11 @@ $bubbleMaxW: 300px;
$reqSymbolW: 15px;
$reqSymbolM: $interiorMargin * 2;
$reqSymbolFontSize: 0.7em;
// Wait Spinner Defaults
$waitSpinnerD: 32px;
$waitSpinnerTreeD: 20px;
$waitSpinnerBorderW: 5px;
$waitSpinnerTreeBorderW: 4px;
/************************** CONTROLS */
$controlDisabledOpacity: 0.3;

View File

@@ -53,7 +53,6 @@ body, html {
font-weight: 200;
height: 100%;
width: 100%;
overflow: hidden;
}
em {
@@ -85,6 +84,8 @@ p {
margin-bottom: $interiorMarginLg;
}
ol, ul { padding-left: 0; }
mct-container {
display: block;
}

View File

@@ -61,9 +61,24 @@
.l-inspector-part {
box-sizing: border-box;
padding-right: $interiorMargin;
.form {
.tree .form {
margin-left: $treeVCW + $interiorMarginLg;
margin-bottom: $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;
.form-section {
margin-bottom: 0;
&:not(.first) {
@@ -72,7 +87,14 @@
.form-row {
@include align-items(center);
border: none;
padding: 0;
padding: $interiorMarginSm 0;
.label {
min-width: 80px;
}
input[type='text'],
input[type='search'] {
width: 100%;
}
}
}
}

View File

@@ -45,7 +45,6 @@
/********************************* FORMS */
@import "forms/elems";
@import "forms/selects";
@import "forms/channel-selector";
@import "forms/datetime";
@import "forms/validation";

View File

@@ -35,15 +35,15 @@
}
}
mct-representation {
mct-representation,
.rep-object-label {
&.s-status-pending {
.t-object-label {
.t-item-icon {
&:before {
$spinBW: 4px;
@include spinner($spinBW);
@include spinner($waitSpinnerTreeBorderW, $colorLoadingFg);
content: "";
padding: 30%;
height: $waitSpinnerTreeD; width: $waitSpinnerTreeD;
}
.t-item-icon-glyph {
display: none;
@@ -57,7 +57,10 @@ mct-representation {
}
}
.selected mct-representation.s-status-pending .t-object-label .t-item-icon:before {
border-color: rgba($colorItemTreeSelectedFg, 0.25) !important;
border-top-color: rgba($colorItemTreeSelectedFg, 1.0) !important;
.selected mct-representation,
.selected .rep-object-label {
.s-status-pending .t-object-label .t-item-icon:before {
border-color: rgba($colorItemTreeSelectedFg, 0.25) !important;
border-top-color: rgba($colorItemTreeSelectedFg, 1.0) !important;
}
}

View File

@@ -74,6 +74,12 @@
.l-composite-control {
vertical-align: middle;
&:not(.l-inline) {
margin-bottom: $interiorMargin;
}
&.l-inline {
display: inline-block;
}
&.l-checkbox {
.composite-control-label {
line-height: 18px;
@@ -108,12 +114,14 @@
font-size: 0.7rem;
}
/******************************************************** CUSTOM CHECKBOXES */
label.checkbox.custom,
label.radio.custom {
$bg: pullForward($colorBodyBg, 10%);
$d: $formRowCtrlsH;
cursor: pointer;
display: inline-block;
line-height: 120%;
margin-right: $interiorMargin * 4;
padding-left: $d + $interiorMargin;
position: relative;
@@ -161,7 +169,40 @@ label.radio.custom {
label.checkbox.custom input:checked ~ em:before { content: "\32"; }
label.radio.custom input:checked ~ em:before { content: "\e619"; }
.s-menu-btn label.checkbox.custom {
margin-left: 5px;
}
.item .checkbox {
&.checked label {
box-shadow: none;
border-bottom: none;
}
}
label.form-control.checkbox {
input {
margin-right: $interiorMargin;
vertical-align: top;
}
}
/******************************************************** INPUTS */
input[type="text"],
input[type="search"] {
@include nice-input();
&.numeric {
text-align: right;
}
}
.l-input-lg input[type="text"] { width: 100% !important; }
.l-input-med input[type="text"] { width: 200px !important; }
.l-input-sm input[type="text"] { width: 50px !important; }
.l-numeric input[type="text"] { text-align: right; }
.input-labeled {
// Used in toolbar
margin-left: $interiorMargin;
label {
display: inline-block;
@@ -175,28 +216,36 @@ label.radio.custom input:checked ~ em:before { content: "\e619"; }
}
}
.s-menu-btn label.checkbox.custom {
margin-left: 5px;
}
.item .checkbox {
&.checked label {
box-shadow: none;
border-bottom: none;
/******************************************************** SELECTS */
.select {
@include btnSubtle($colorSelectBg);
@if $shdwBtns != none {
margin: 0 0 2px 0; // Needed to avoid dropshadow from being clipped by parent containers
}
}
.context-available,
.s-icon-btn {
$c: $colorKey;
color: $c;
&:hover {
color: lighten($c, 10%);
padding: 0 $interiorMargin;
overflow: hidden;
position: relative;
line-height: $formInputH;
select {
@include appearance(none);
box-sizing: border-box;
background: none;
color: $colorSelectFg;
cursor: pointer;
border: none !important;
padding: 4px 25px 2px 0px;
width: 130%;
option {
margin: $interiorMargin 0; // Firefox
}
}
&:after {
@include contextArrow();
pointer-events: none;
color: rgba($colorSelectFg, percentToDecimal($contrastInvokeMenuPercent));
position: absolute;
right: $interiorMargin; top: 0;
}
}
.view-switcher {
@include trans-prop-nice-fade($controlFadeMs);
}
/******************************************************** OBJECT-HEADER */
@@ -330,7 +379,6 @@ body.desktop .object-header {
}
/******************************************************** SLIDERS */
.slider {
$knobH: 100%;
.slot {
@@ -424,7 +472,7 @@ body.desktop .object-header {
border-top: 1px solid $colorInteriorBorder
}
.l-time-selects {
line-height: $formInputH;
line-height: inherit;
}
}
@@ -478,11 +526,31 @@ body.desktop .object-header {
}
}
/******************************************************** BROWSER ELEMENTS */
/******************************************************** TEXTAREA */
textarea {
@include nice-textarea($colorInputBg, $colorInputFg);
position: absolute;
height: 100%;
width: 100%;
}
/******************************************************** MISC */
.context-available,
.s-icon-btn {
$c: $colorKey;
color: $c;
&:hover {
color: lighten($c, 10%);
}
}
.view-switcher {
@include trans-prop-nice-fade($controlFadeMs);
}
/******************************************************** BROWSER ELEMENTS */
body.desktop {
::-webkit-scrollbar {
border-radius: 2px;
box-sizing: border-box;
box-shadow: inset $scrollbarTrackShdw;
background-color: $scrollbarTrackColorBg;
@@ -491,15 +559,15 @@ body.desktop {
}
::-webkit-scrollbar-thumb {
$bg: $scrollbarThumbColor;
$hc: $scrollbarThumbColorHov;
$gr: 5%;
@include background-image(linear-gradient(lighten($bg, $gr), $bg 20px));
border-radius: 2px;
box-sizing: border-box;
&:hover {
@include background-image(linear-gradient(lighten($hc, $gr), $hc 20px));
}
background: $scrollbarThumbColor;
&:hover { background: $scrollbarThumbColorHov; }
}
.overlay ::-webkit-scrollbar-thumb {
$lr: 15%;
background: $scrollbarThumbColorOverlay;
&:hover { background: $scrollbarThumbColorOverlayHov; }
}
::-webkit-scrollbar-corner {

View File

@@ -51,9 +51,6 @@
.title-label {
font-size: 1rem;
}
//&:after {
// color: rgba($colorInvokeMenu, 0.5);
//}
}
.menu {
@@ -113,12 +110,13 @@
.menu,
.context-menu,
.super-menu {
.super-menu,
.s-menu-btn .menu {
pointer-events: auto;
ul li {
//padding-left: 25px;
a {
color: $colorMenuFg;
display: block;
}
.icon {
color: $colorMenuIc;
@@ -126,9 +124,6 @@
.type-icon {
left: $interiorMargin;
}
&:hover .icon {
//color: lighten($colorMenuIc, 5%);
}
}
}
@@ -146,7 +141,7 @@
height: $d;
width: $d;
&:before {
font-size: 7px !important;// $d/2;
font-size: 7px !important;
height: $d;
width: $d;
line-height: $d;
@@ -173,7 +168,6 @@
.pane {
box-sizing: border-box;
&.left {
//@include test();
border-right: 1px solid pullForward($colorMenuBg, 10%);
left: 0;
padding-right: $interiorMargin;
@@ -190,7 +184,6 @@
}
}
&.right {
//@include test(red);
left: auto;
right: 0;
padding: $interiorMargin * 5;
@@ -216,7 +209,6 @@
margin-bottom: 0.5em;
}
&.description {
//color: lighten($colorMenuBg, 30%);
color: $colorCreateMenuText;
font-size: 0.8em;
line-height: 1.5em;
@@ -258,4 +250,4 @@
left: auto;
right: 0;
width: auto;
}
}

View File

@@ -20,13 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
.section-header {
border-radius: $basicCr;
background: $colorFormSectionHeader;
$c: lighten($colorBodyFg, 20%);
color: $c;
font-size: 0.8em;
padding: $formTBPad $formLRPad;
text-transform: uppercase;
text-transform: uppercase;
}
.form {
@@ -37,12 +31,20 @@
margin-bottom: $interiorMarginLg * 2;
}
.section-header {
border-radius: $basicCr;
background: $colorFormSectionHeader;
$c: lighten($colorBodyFg, 20%);
color: $c;
font-size: 0.8em;
padding: $formTBPad $formLRPad;
}
.form-row {
$m: $interiorMargin;
box-sizing: border-box;
@include clearfix;
border-top: 1px solid $colorFormLines;
margin-top: $m;
padding: $formTBPad 0;
position: relative;
&.first {
@@ -52,10 +54,7 @@
>.label,
>.controls {
box-sizing: border-box;
@include clearfix;
font-size: 0.8rem;
line-height: $formInputH;
min-height: $formInputH;
}
>.label {
@@ -83,27 +82,12 @@
margin-right: 5px;
}
}
.l-med input[type="text"] {
width: 200px;
}
.l-small input[type="text"] {
width: 50px;
}
.l-numeric input[type="text"] {
text-align: right;
}
.select {
margin-right: $interiorMargin;
}
}
.field-hints {
color: darken($colorBodyFg, 20%);
}
.hint, .field-hints { color: $colorFieldHint; }
.selector-list {
// Used in create overlay to display tree view
@@ -124,25 +108,31 @@
}
}
.l-controls-first {
.form .form-row {
margin-top: $interiorMarginSm;
>.label,
>.controls {
line-height: inherit;
min-height: inherit;;
}
>.label {
@include flex(1 1 auto);
min-width: 0;
width: auto;
order: 2;
}
>.controls {
@include flex(0 0 auto);
margin-right: $interiorMargin;
order: 1;
}
.l-controls-first .form .form-row,
.form .form-row.l-controls-first {
>.label,
>.controls {
line-height: inherit;
min-height: inherit;;
}
>.label {
@include flex(1 1 auto);
min-width: 0;
width: auto;
order: 2;
}
>.controls {
@include flex(0 0 auto);
margin-right: $interiorMargin;
order: 1;
}
}
.l-controls-under.l-flex-row {
// Change to use column layout
@include flex-direction(column);
.flex-elem {
margin-bottom: $interiorMarginLg;
}
}
@@ -155,13 +145,6 @@
}
}
label.form-control.checkbox {
input {
margin-right: $interiorMargin;
vertical-align: top;
}
}
.hint,
.s-hint {
font-size: 0.9em;
@@ -181,19 +164,4 @@ label.form-control.checkbox {
color: lighten($colorFormInvalid, 30%);
padding: $interiorMargin;
}
}
input[type="text"],
input[type="search"] {
@include nice-input();
&.numeric {
text-align: right;
}
}
textarea {
@include nice-textarea($colorInputBg, $colorInputFg);
position: absolute;
height: 100%;
width: 100%;
}

View File

@@ -23,9 +23,13 @@
> .label {
padding-right: $reqSymbolM; // Keep room for validation element
&::after {
float: right;
position: absolute;
right: $interiorMargin;
font-family: symbolsfont;
font-size: $reqSymbolFontSize;
height: 100%;
line-height: 200%;
}
}
&.invalid,

View File

@@ -28,7 +28,7 @@
100% { @include transform(translate(-50%, -50%) rotate(360deg)); }
}
@mixin spinner($b: 5px, $c: $colorKey) {
@mixin spinner($b: 5px, $c: $colorKey) {
@include transform-origin(center);
@include animation-name(rotation-centered);
@include animation-duration(0.5s);
@@ -46,10 +46,7 @@
}
.wait-spinner {
$d: 5%;
@include spinner(0.5em, $colorKey);
height: auto; width: auto;
padding: $d; // Will size object based on parent container WIDTH
@include spinner($waitSpinnerBorderW, $colorKey);
pointer-events: none;
z-index: 2;
&.inline {
@@ -60,15 +57,6 @@
}
}
.treeview .wait-spinner {
// Only used in subtree.html, which I don't think this is actually being used
$d: 10px;
height: $d; width: $d;
margin: 0 !important;
padding: 0 !important;
top: 2px; left: 0;
}
.loading {
// Can be applied to any block element with height and width
pointer-events: none;
@@ -77,8 +65,8 @@
content: '';
}
&:before {
@include spinner(5px, $colorLoadingFg);
padding: 5%;
@include spinner($waitSpinnerBorderW, $colorLoadingFg);
height: $waitSpinnerD; width: $waitSpinnerD;
z-index: 10;
}
&:after {
@@ -87,8 +75,22 @@
display: block;
z-index: 9;
}
&.tree-item:before {
padding: $menuLineH / 4;
border-width: 2px;
&.tree-item.t-wait-node {
$d: $waitSpinnerTreeD;
$spinnerL: $treeVCW + $interiorMargin + 3px + $d/2;
padding-left: $spinnerL + $d/2 + $interiorMargin;
.t-title-label {
font-style: italic;
opacity: 0.6;
}
&:before {
height: $d;
width: $d;
border-width: 4px;
left: $spinnerL;
}
&:after {
display: none;
}
}
}
}

View File

@@ -35,7 +35,6 @@
z-index: 100;
}
> .holder {
//$i: 15%;
@include containerSubtle($colorOvrBg, $colorOvrFg);
border-radius: $basicCr * 3;
color: $colorOvrFg;
@@ -57,15 +56,8 @@
right: $m;
bottom: $m;
left: $m;
//.top-bar,
//.editor,
//.bottom-bar {
// @include absPosDefault();
//}
}
}
.title {
@include ellipsize();
font-size: 1.2em;
@@ -73,9 +65,7 @@
margin-bottom: $interiorMargin;
}
.hint {
color: pushBack($colorOvrFg, 20%);
}
.hint, .field-hints { color: $colorFieldHintOverlay !important; }
.abs.top-bar {
height: $ovrTopBarH;
@@ -88,7 +78,7 @@
left: 0;
right: 0;
overflow: auto;
.field.l-med {
.field.l-input-med {
input[type='text'] {
width: 100%;
}
@@ -120,7 +110,6 @@
bottom: 0;
left: 0;
overflow: visible;
//font-size: 1em;
height: $ovrFooterH;
}
@@ -132,11 +121,14 @@
margin: .5em 0;
width: 100%;
}
.select {
box-shadow: $shdwBtnsOverlay;
}
}
.t-dialog-sm .overlay > .holder {
// Used for blocker and in-progress dialogs, modal alerts, etc.
//@include test(red);
$h: 225px;
min-height: $h;
height: $h;

View File

@@ -26,6 +26,10 @@
top: $m; right: $m * 1.25; bottom: $m; left: $m * 1.25;
}
body, html {
overflow: hidden;
}
.l-splash-holder {
// Main outer holder.
@include transition-property(opacity);

View File

@@ -40,7 +40,7 @@
<mct-representation
key="'edit-elements'"
mct-object="domainObject"
class="flex-elem holder grows vscroll current-elements">
class="flex-elem l-flex-col holder grows current-elements">
</mct-representation>
</div>
</div>

View File

@@ -19,18 +19,6 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<ul class="tree">
<li ng-if="!composition">
<span class="tree-item">
<span class="icon wait-spinner"></span>
<span class="title-label">Loading...</span>
</span>
</li>
<li ng-repeat="child in composition">
<mct-representation key="'tree-node'"
mct-object="child"
parameters="parameters"
ng-model="ngModel">
</mct-representation>
</li>
</ul>
<mct-tree mct-object="domainObject" mct-model="ngModel.selectedObject">
</mct-tree>

View File

@@ -0,0 +1,4 @@
<span class="tree-item menus-to-left">
</span>
<span class="tree-item-subtree">
</span>

View File

@@ -0,0 +1,2 @@
<span class='ui-symbol view-control flex-elem'>
</span>

View File

@@ -0,0 +1,8 @@
<span class="rep-object-label">
<div class="t-object-label l-flex-row flex-elem grows">
<div class="t-item-icon flex-elem">
<div class="t-item-icon-glyph"></div>
</div>
<div class='t-title-label flex-elem grows'></div>
</div>
</span>

View File

@@ -19,11 +19,6 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div class="w1">
<div class="w2"
ng-controller="RTEventListController as rtevent">
<mct-rt-data-table headers="rtevent.headers()" rows="rtevent.rows()" ascending-scroll="true"></mct-rt-data-table>
</div>
</div>
<li class='tree-item t-wait-node loading'>
<span class="t-title-label">Loading...</span>
</li>

View File

@@ -0,0 +1,54 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define([
'angular',
'../ui/TreeView'
], function (angular, TreeView) {
function MCTTree($parse, gestureService) {
function link(scope, element, attrs) {
var treeView = new TreeView(gestureService),
expr = $parse(attrs.mctModel),
unobserve = treeView.observe(function (domainObject) {
if (domainObject !== expr(scope.$parent)) {
expr.assign(scope.$parent, domainObject);
scope.$apply();
}
});
element.append(angular.element(treeView.elements()));
scope.$parent.$watch(attrs.mctModel, treeView.value.bind(treeView));
scope.$watch('mctObject', treeView.model.bind(treeView));
scope.$on('$destroy', unobserve);
}
return {
restrict: "E",
link: link,
scope: { mctObject: "=" }
};
}
return MCTTree;
});

View File

@@ -0,0 +1,65 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define([
'zepto',
'text!../../res/templates/tree/toggle.html'
], function ($, toggleTemplate) {
function ToggleView(state) {
this.expanded = !!state;
this.callbacks = [];
this.el = $(toggleTemplate);
this.el.on('click', function () {
this.value(!this.expanded);
}.bind(this));
}
ToggleView.prototype.value = function (state) {
this.expanded = state;
if (state) {
this.el.addClass('expanded');
} else {
this.el.removeClass('expanded');
}
this.callbacks.forEach(function (callback) {
callback(state);
});
};
ToggleView.prototype.observe = function (callback) {
this.callbacks.push(callback);
return function () {
this.callbacks = this.callbacks.filter(function (c) {
return c !== callback;
});
}.bind(this);
};
ToggleView.prototype.elements = function () {
return this.el;
};
return ToggleView;
});

View File

@@ -0,0 +1,90 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define([
'zepto',
'text!../../res/templates/tree/tree-label.html'
], function ($, labelTemplate) {
'use strict';
function TreeLabelView(gestureService) {
this.el = $(labelTemplate);
this.gestureService = gestureService;
}
function getGlyph(domainObject) {
var type = domainObject.getCapability('type');
return type.getGlyph();
}
function isLink(domainObject) {
var location = domainObject.getCapability('location');
return location.isLink();
}
TreeLabelView.prototype.updateView = function (domainObject) {
var titleEl = this.el.find('.t-title-label'),
glyphEl = this.el.find('.t-item-icon-glyph'),
iconEl = this.el.find('.t-item-icon');
titleEl.text(domainObject ? domainObject.getModel().name : "");
glyphEl.text(domainObject ? getGlyph(domainObject) : "");
if (domainObject && isLink(domainObject)) {
iconEl.addClass('l-icon-link');
} else {
iconEl.removeClass('l-icon-link');
}
};
TreeLabelView.prototype.model = function (domainObject) {
if (this.unlisten) {
this.unlisten();
delete this.unlisten;
}
if (this.activeGestures) {
this.activeGestures.destroy();
delete this.activeGestures;
}
this.updateView(domainObject);
if (domainObject) {
this.unlisten = domainObject.getCapability('mutation')
.listen(this.updateView.bind(this, domainObject));
this.activeGestures = this.gestureService.attachGestures(
this.elements(),
domainObject,
[ 'info', 'menu', 'drag' ]
);
}
};
TreeLabelView.prototype.elements = function () {
return this.el;
};
return TreeLabelView;
});

View File

@@ -0,0 +1,157 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define([
'zepto',
'text!../../res/templates/tree/node.html',
'./ToggleView',
'./TreeLabelView'
], function ($, nodeTemplate, ToggleView, TreeLabelView) {
'use strict';
function TreeNodeView(gestureService, subtreeFactory, selectFn) {
this.li = $('<li>');
this.statusClasses = [];
this.toggleView = new ToggleView(false);
this.toggleView.observe(function (state) {
if (state) {
if (!this.subtreeView) {
this.subtreeView = subtreeFactory();
this.subtreeView.model(this.activeObject);
this.li.find('.tree-item-subtree').eq(0)
.append($(this.subtreeView.elements()));
}
$(this.subtreeView.elements()).removeClass('hidden');
} else if (this.subtreeView) {
$(this.subtreeView.elements()).addClass('hidden');
}
}.bind(this));
this.labelView = new TreeLabelView(gestureService);
$(this.labelView.elements()).on('click', function () {
selectFn(this.activeObject);
}.bind(this));
this.li.append($(nodeTemplate));
this.li.find('span').eq(0)
.append($(this.toggleView.elements()))
.append($(this.labelView.elements()));
this.model(undefined);
}
TreeNodeView.prototype.updateStatusClasses = function (statuses) {
this.statusClasses.forEach(function (statusClass) {
this.li.removeClass(statusClass);
}.bind(this));
this.statusClasses = statuses.map(function (status) {
return 's-status-' + status;
});
this.statusClasses.forEach(function (statusClass) {
this.li.addClass(statusClass);
}.bind(this));
};
TreeNodeView.prototype.model = function (domainObject) {
if (this.unlisten) {
this.unlisten();
}
this.activeObject = domainObject;
if (domainObject && domainObject.hasCapability('composition')) {
$(this.toggleView.elements()).addClass('has-children');
} else {
$(this.toggleView.elements()).removeClass('has-children');
}
if (domainObject && domainObject.hasCapability('status')) {
this.unlisten = domainObject.getCapability('status')
.listen(this.updateStatusClasses.bind(this));
this.updateStatusClasses(
domainObject.getCapability('status').list()
);
}
this.labelView.model(domainObject);
if (this.subtreeView) {
this.subtreeView.model(domainObject);
}
};
function getIdPath(domainObject) {
var context = domainObject && domainObject.getCapability('context');
function getId(domainObject) {
return domainObject.getId();
}
return context ? context.getPath().map(getId) : [];
}
TreeNodeView.prototype.value = function (domainObject) {
var activeIdPath = getIdPath(this.activeObject),
selectedIdPath = getIdPath(domainObject);
if (this.onSelectionPath) {
this.li.find('.tree-item').eq(0).removeClass('selected');
if (this.subtreeView) {
this.subtreeView.value(undefined);
}
}
this.onSelectionPath =
!!domainObject &&
!!this.activeObject &&
(activeIdPath.length <= selectedIdPath.length) &&
activeIdPath.every(function (id, index) {
return selectedIdPath[index] === id;
});
if (this.onSelectionPath) {
if (activeIdPath.length === selectedIdPath.length) {
this.li.find('.tree-item').eq(0).addClass('selected');
} else {
// Expand to reveal the selection
this.toggleView.value(true);
this.subtreeView.value(domainObject);
}
}
};
/**
*
* @returns {HTMLElement[]}
*/
TreeNodeView.prototype.elements = function () {
return this.li;
};
return TreeNodeView;
});

View File

@@ -0,0 +1,141 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define([
'zepto',
'./TreeNodeView',
'text!../../res/templates/tree/wait-node.html'
], function ($, TreeNodeView, spinnerTemplate) {
'use strict';
function TreeView(gestureService, selectFn) {
this.ul = $('<ul class="tree"></ul>');
this.nodeViews = [];
this.callbacks = [];
this.selectFn = selectFn || this.value.bind(this);
this.gestureService = gestureService;
this.pending = false;
}
TreeView.prototype.newTreeView = function () {
return new TreeView(this.gestureService, this.selectFn);
};
TreeView.prototype.setSize = function (sz) {
var nodeView;
while (this.nodeViews.length < sz) {
nodeView = new TreeNodeView(
this.gestureService,
this.newTreeView.bind(this),
this.selectFn
);
this.nodeViews.push(nodeView);
this.ul.append($(nodeView.elements()));
}
while (this.nodeViews.length > sz) {
nodeView = this.nodeViews.pop();
$(nodeView.elements()).remove();
}
};
TreeView.prototype.loadComposition = function () {
var self = this,
domainObject = this.activeObject;
function addNode(domainObject, index) {
self.nodeViews[index].model(domainObject);
}
function addNodes(domainObjects) {
if (self.pending) {
self.pending = false;
self.nodeViews = [];
self.ul.empty();
}
if (domainObject === self.activeObject) {
self.setSize(domainObjects.length);
domainObjects.forEach(addNode);
self.updateNodeViewSelection();
}
}
domainObject.useCapability('composition')
.then(addNodes);
};
TreeView.prototype.model = function (domainObject) {
if (this.unlisten) {
this.unlisten();
}
this.activeObject = domainObject;
this.ul.empty();
if (domainObject && domainObject.hasCapability('composition')) {
this.pending = true;
this.ul.append($(spinnerTemplate));
this.unlisten = domainObject.getCapability('mutation')
.listen(this.loadComposition.bind(this));
this.loadComposition(domainObject);
} else {
this.setSize(0);
}
};
TreeView.prototype.updateNodeViewSelection = function () {
this.nodeViews.forEach(function (nodeView) {
nodeView.value(this.selectedObject);
}.bind(this));
};
TreeView.prototype.value = function (domainObject) {
this.selectedObject = domainObject;
this.updateNodeViewSelection();
this.callbacks.forEach(function (callback) {
callback(domainObject);
});
};
TreeView.prototype.observe = function (callback) {
this.callbacks.push(callback);
return function () {
this.callbacks = this.callbacks.filter(function (c) {
return c !== callback;
});
}.bind(this);
};
/**
*
* @returns {HTMLElement[]}
*/
TreeView.prototype.elements = function () {
return this.ul;
};
return TreeView;
});

View File

@@ -0,0 +1,95 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,describe,beforeEach,jasmine,it,expect*/
define([
'../../src/directives/MCTTree'
], function (MCTTree) {
describe("The mct-tree directive", function () {
var mockParse,
mockGestureService,
mockExpr,
mctTree;
beforeEach(function () {
mockGestureService = jasmine.createSpyObj(
'gestureService',
[ 'attachGestures' ]
);
mockParse = jasmine.createSpy('$parse');
mockExpr = jasmine.createSpy('expr');
mockExpr.assign = jasmine.createSpy('assign');
mockParse.andReturn(mockExpr);
mctTree = new MCTTree(mockParse, mockGestureService);
});
it("is applicable as an element", function () {
expect(mctTree.restrict).toEqual("E");
});
it("two-way binds to mctObject", function () {
expect(mctTree.scope).toEqual({ mctObject: "=" });
});
describe("link", function () {
var mockScope,
mockElement,
testAttrs;
beforeEach(function () {
mockScope = jasmine.createSpyObj('$scope', ['$watch', '$on']);
mockElement = jasmine.createSpyObj('element', ['append']);
testAttrs = { mctModel: "some-expression" };
mockScope.$parent =
jasmine.createSpyObj('$scope', ['$watch', '$on']);
mctTree.link(mockScope, mockElement, testAttrs);
});
it("populates the mct-tree element", function () {
expect(mockElement.append).toHaveBeenCalled();
});
it("watches for mct-model's expression in the parent", function () {
expect(mockScope.$parent.$watch).toHaveBeenCalledWith(
testAttrs.mctModel,
jasmine.any(Function)
);
});
it("watches for changes to mct-object", function () {
expect(mockScope.$watch).toHaveBeenCalledWith(
"mctObject",
jasmine.any(Function)
);
});
it("listens for the $destroy event", function () {
expect(mockScope.$on).toHaveBeenCalledWith(
"$destroy",
jasmine.any(Function)
);
});
});
});
});

View File

@@ -0,0 +1,313 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,describe,beforeEach,jasmine,it,expect*/
define([
'../../src/ui/TreeView',
'zepto'
], function (TreeView, $) {
'use strict';
describe("TreeView", function () {
var mockGestureService,
mockGestureHandle,
mockDomainObject,
mockMutation,
mockUnlisten,
testCapabilities,
treeView;
function makeMockDomainObject(id, model, capabilities) {
var mockDomainObject = jasmine.createSpyObj(
'domainObject-' + id,
[
'getId',
'getModel',
'getCapability',
'hasCapability',
'useCapability'
]
);
mockDomainObject.getId.andReturn(id);
mockDomainObject.getModel.andReturn(model);
mockDomainObject.hasCapability.andCallFake(function (c) {
return !!(capabilities[c]);
});
mockDomainObject.getCapability.andCallFake(function (c) {
return capabilities[c];
});
mockDomainObject.useCapability.andCallFake(function (c) {
return capabilities[c] && capabilities[c].invoke();
});
return mockDomainObject;
}
beforeEach(function () {
mockGestureService = jasmine.createSpyObj(
'gestureService',
[ 'attachGestures' ]
);
mockGestureHandle = jasmine.createSpyObj('gestures', ['destroy']);
mockGestureService.attachGestures.andReturn(mockGestureHandle);
mockMutation = jasmine.createSpyObj('mutation', ['listen']);
mockUnlisten = jasmine.createSpy('unlisten');
mockMutation.listen.andReturn(mockUnlisten);
testCapabilities = { mutation: mockMutation };
mockDomainObject =
makeMockDomainObject('parent', {}, testCapabilities);
treeView = new TreeView(mockGestureService);
});
describe("elements", function () {
var elements;
beforeEach(function () {
elements = treeView.elements();
});
it("is an unordered list", function () {
expect(elements[0].tagName.toLowerCase())
.toEqual('ul');
});
});
describe("model", function () {
var mockComposition;
function makeGenericCapabilities() {
var mockContext =
jasmine.createSpyObj('context', [ 'getPath' ]),
mockType =
jasmine.createSpyObj('type', [ 'getGlyph' ]),
mockLocation =
jasmine.createSpyObj('location', [ 'isLink' ]),
mockMutation =
jasmine.createSpyObj('mutation', [ 'listen' ]),
mockStatus =
jasmine.createSpyObj('status', [ 'listen', 'list' ]);
mockStatus.list.andReturn([]);
return {
context: mockContext,
type: mockType,
mutation: mockMutation,
location: mockLocation,
status: mockStatus
};
}
function waitForCompositionCallback() {
var calledBack = false;
testCapabilities.composition.invoke().then(function (c) {
calledBack = true;
});
waitsFor(function () {
return calledBack;
});
}
beforeEach(function () {
mockComposition = ['a', 'b', 'c'].map(function (id) {
var testCapabilities = makeGenericCapabilities(),
mockChild =
makeMockDomainObject(id, {}, testCapabilities);
testCapabilities.context.getPath
.andReturn([mockDomainObject, mockChild]);
return mockChild;
});
testCapabilities.composition =
jasmine.createSpyObj('composition', ['invoke']);
testCapabilities.composition.invoke
.andReturn(Promise.resolve(mockComposition));
treeView.model(mockDomainObject);
waitForCompositionCallback();
});
it("adds one node per composition element", function () {
expect(treeView.elements()[0].childElementCount)
.toEqual(mockComposition.length);
});
it("listens for mutation", function () {
expect(testCapabilities.mutation.listen)
.toHaveBeenCalledWith(jasmine.any(Function));
});
describe("when mutation occurs", function () {
beforeEach(function () {
mockComposition.pop();
testCapabilities.mutation.listen
.mostRecentCall.args[0](mockDomainObject.getModel());
waitForCompositionCallback();
});
it("continues to show one node per composition element", function () {
expect(treeView.elements()[0].childElementCount)
.toEqual(mockComposition.length);
});
});
describe("when replaced with a non-compositional domain object", function () {
beforeEach(function () {
delete testCapabilities.composition;
treeView.model(mockDomainObject);
});
it("stops listening for mutation", function () {
expect(mockUnlisten).toHaveBeenCalled();
});
it("removes all tree nodes", function () {
expect(treeView.elements()[0].childElementCount)
.toEqual(0);
});
});
describe("when selection state changes", function () {
var selectionIndex = 1;
beforeEach(function () {
treeView.value(mockComposition[selectionIndex]);
});
it("communicates selection state to an appropriate node", function () {
var selected = $(treeView.elements()[0]).find('.selected');
expect(selected.length).toEqual(1);
});
});
describe("when a context-less object is selected", function () {
beforeEach(function () {
var testCapabilities = makeGenericCapabilities(),
mockDomainObject =
makeMockDomainObject('xyz', {}, testCapabilities);
delete testCapabilities.context;
treeView.value(mockDomainObject);
});
it("clears all selection state", function () {
var selected = $(treeView.elements()[0]).find('.selected');
expect(selected.length).toEqual(0);
});
});
describe("when children contain children", function () {
beforeEach(function () {
var newCapabilities = makeGenericCapabilities(),
gcCapabilities = makeGenericCapabilities(),
mockNewChild =
makeMockDomainObject('d', {}, newCapabilities),
mockGrandchild =
makeMockDomainObject('gc', {}, gcCapabilities),
calledBackInner = false;
newCapabilities.composition =
jasmine.createSpyObj('composition', [ 'invoke' ]);
newCapabilities.composition.invoke
.andReturn(Promise.resolve([mockGrandchild]));
mockComposition.push(mockNewChild);
newCapabilities.context.getPath.andReturn([
mockDomainObject,
mockNewChild
]);
gcCapabilities.context.getPath.andReturn([
mockDomainObject,
mockNewChild,
mockGrandchild
]);
testCapabilities.mutation.listen
.mostRecentCall.args[0](mockDomainObject);
waitForCompositionCallback();
runs(function () {
// Select the innermost object to force expansion,
// such that we can verify the subtree is present.
treeView.value(mockGrandchild);
newCapabilities.composition.invoke().then(function () {
calledBackInner = true;
});
});
waitsFor(function () {
return calledBackInner;
});
});
it("creates inner trees", function () {
expect($(treeView.elements()[0]).find('ul').length)
.toEqual(1);
});
});
describe("when status changes", function () {
var testStatuses;
beforeEach(function () {
var mockStatus = mockComposition[1].getCapability('status');
testStatuses = [ 'foo' ];
mockStatus.list.andReturn(testStatuses);
mockStatus.listen.mostRecentCall.args[0](testStatuses);
});
it("reflects the status change in the tree", function () {
expect($(treeView.elements()).find('.s-status-foo').length)
.toEqual(1);
});
});
});
describe("observe", function () {
var mockCallback,
unobserve;
beforeEach(function () {
mockCallback = jasmine.createSpy('callback');
unobserve = treeView.observe(mockCallback);
});
it("notifies listeners when value is changed", function () {
treeView.value(mockDomainObject);
expect(mockCallback).toHaveBeenCalledWith(mockDomainObject);
});
it("does not notify listeners when deactivated", function () {
unobserve();
treeView.value(mockDomainObject);
expect(mockCallback).not.toHaveBeenCalled();
});
});
});
});

View File

@@ -85,7 +85,6 @@ define(
popup.goesUp() ? 'arw-btm' : 'arw-top',
popup.goesLeft() ? 'arw-right' : 'arw-left'
].join(' ');
scope.bubbleLayout = 'arw-top arw-left';
// Create the info bubble, now that we know how to
// point the arrow...

View File

@@ -109,6 +109,35 @@ define(
);
});
[ false, true ].forEach(function (goesLeft) {
[ false, true].forEach(function (goesUp) {
var vertical = goesUp ? "up" : "down",
horizontal = goesLeft ? "left" : "right",
location = [ vertical, horizontal].join('-');
describe("when bubble goes " + location, function () {
var expectedLocation = [
goesUp ? "bottom" : "top",
goesLeft ? "right" : "left"
].join('-');
beforeEach(function () {
mockPopup.goesUp.andReturn(goesUp);
mockPopup.goesDown.andReturn(!goesUp);
mockPopup.goesLeft.andReturn(goesLeft);
mockPopup.goesRight.andReturn(!goesLeft);
service.display('', '', {}, [ 10, 10 ]);
});
it("positions the arrow in the " + expectedLocation, function () {
expect(mockScope.bubbleLayout).toEqual([
goesUp ? "arw-btm" : "arw-top",
goesLeft ? "arw-right" : "arw-left"
].join(' '));
});
});
});
});
});
}
);

View File

@@ -48,7 +48,11 @@ define(
});
}
$scope.regions = filterRegions(typeCapability.getDefinition().inspector || new InspectorRegion());
function setRegions() {
$scope.regions = filterRegions(typeCapability.getDefinition().inspector || new InspectorRegion());
}
setRegions();
}
return InspectorController;

View File

@@ -27,6 +27,7 @@ $colorBtnIcon: $colorKey;
$colorInvokeMenu: #fff;
$contrastInvokeMenuPercent: 20%;
$shdwBtns: rgba(black, 0.2) 0 1px 2px;
$shdwBtnsOverlay: rgba(black, 0.5) 0 1px 5px;
$sliderColorBase: $colorKey;
$sliderColorRangeHolder: rgba(black, 0.1);
$sliderColorRange: rgba($sliderColorBase, 0.3);
@@ -76,6 +77,7 @@ $colorInputBg: rgba(#000, 0.1);
$colorInputFg: pullForward($colorBodyFg, 20%);
$colorFormText: rgba(#fff, 0.5);
$colorInputIcon: pushBack($colorBodyFg, 15%);
$colorFieldHint: pullForward($colorBodyFg, 20%);
// Inspector
$colorInspectorBg: pullForward($colorBodyBg, 3%);
@@ -124,6 +126,7 @@ $colorOvrBg: pullForward($colorBodyBg, 10%);
$colorOvrFg: pullForward($colorBodyFg, 30%);
$colorOvrBtnBg: pullForward($colorOvrBg, 20%);
$colorOvrBtnFg: #fff;
$colorFieldHintOverlay: pullForward($colorOvrBg, 30%);
// Items
$colorItemBg: lighten($colorBodyBg, 5%);
@@ -173,6 +176,8 @@ $scrollbarTrackShdw: rgba(#000, 0.7) 0 1px 5px;
$scrollbarTrackColorBg: rgba(#000, 0.4);
$scrollbarThumbColor: lighten($colorBodyBg, 10%);
$scrollbarThumbColorHov: lighten($scrollbarThumbColor, 2%);
$scrollbarThumbColorOverlay: lighten($colorOvrBg, 10%);
$scrollbarThumbColorOverlayHov: lighten($scrollbarThumbColorOverlay, 2%);
// Splitter
$splitterD: 25px; // splitterD and HandleD should both be odd, or even

View File

@@ -27,6 +27,7 @@ $colorBtnIcon: #eee;
$colorInvokeMenu: #000;
$contrastInvokeMenuPercent: 40%;
$shdwBtns: none;
$shdwBtnsOverlay: none;
$sliderColorBase: $colorKey;
$sliderColorRangeHolder: rgba(black, 0.07);
$sliderColorRange: rgba($sliderColorBase, 0.2);
@@ -76,6 +77,7 @@ $colorInputBg: $colorGenBg;
$colorInputFg: $colorBodyFg;
$colorFormText: pushBack($colorBodyFg, 10%);
$colorInputIcon: pushBack($colorBodyFg, 25%);
$colorFieldHint: pullForward($colorBodyFg, 40%);
// Inspector
$colorInspectorBg: pullForward($colorBodyBg, 5%);
@@ -124,6 +126,7 @@ $colorOvrBg: $colorBodyBg;
$colorOvrFg: $colorBodyFg;
$colorOvrBtnBg: pullForward($colorOvrBg, 40%);
$colorOvrBtnFg: #fff;
$colorFieldHintOverlay: pullForward($colorOvrBg, 40%);
// Items
$colorItemBg: #ddd;
@@ -170,9 +173,11 @@ $shdwItemTreeIcon: none;
// Scrollbar
$scrollbarTrackSize: 10px;
$scrollbarTrackShdw: rgba(#000, 0.2) 0 1px 2px;
$scrollbarTrackColorBg: rgba(#000, 0.1);
$scrollbarThumbColor: darken($colorBodyBg, 50%);//
$scrollbarTrackColorBg: rgba(#000, 0.2);
$scrollbarThumbColor: darken($colorBodyBg, 50%);
$scrollbarThumbColorHov: $colorKey;
$scrollbarThumbColorOverlay: darken($colorOvrBg, 50%);
$scrollbarThumbColorOverlayHov: $scrollbarThumbColorHov;
// Splitter
$splitterD: 24px;

View File

@@ -27,6 +27,7 @@ define([
"./src/models/StaticModelProvider",
"./src/models/RootModelProvider",
"./src/models/ModelAggregator",
"./src/models/ModelCacheService",
"./src/models/PersistedModelProvider",
"./src/models/CachingModelDecorator",
"./src/models/MissingModelDecorator",
@@ -58,6 +59,7 @@ define([
StaticModelProvider,
RootModelProvider,
ModelAggregator,
ModelCacheService,
PersistedModelProvider,
CachingModelDecorator,
MissingModelDecorator,
@@ -182,7 +184,10 @@ define([
{
"provides": "modelService",
"type": "decorator",
"implementation": CachingModelDecorator
"implementation": CachingModelDecorator,
"depends": [
"cacheService"
]
},
{
"provides": "modelService",
@@ -248,21 +253,22 @@ define([
"property": "name",
"pattern": "\\S+",
"required": true,
"cssclass": "l-med"
"cssclass": "l-input-lg"
}
]
},
{
"key": "root",
"name": "Root",
"glyph": "F"
"glyph": "\u0046"
},
{
"key": "folder",
"name": "Folder",
"glyph": "F",
"glyph": "\u0046",
"features": "creation",
"description": "Useful for storing and organizing domain objects.",
"description": "Create folders to organize other objects or links to objects.",
"priority": 1000,
"model": {
"composition": []
}
@@ -270,11 +276,11 @@ define([
{
"key": "unknown",
"name": "Unknown Type",
"glyph": "?"
"glyph": "\u003f"
},
{
"name": "Unknown Type",
"glyph": "?"
"glyph": "\u003f"
}
],
"capabilities": [
@@ -319,6 +325,7 @@ define([
"key": "persistence",
"implementation": PersistenceCapability,
"depends": [
"cacheService",
"persistenceService",
"identifierService",
"notificationService",
@@ -349,11 +356,16 @@ define([
"implementation": InstantiationCapability,
"depends": [
"$injector",
"identifierService"
"identifierService",
"now"
]
}
],
"services": [
{
"key": "cacheService",
"implementation": ModelCacheService
},
{
"key": "now",
"implementation": Now
@@ -384,7 +396,8 @@ define([
"implementation": Instantiate,
"depends": [
"capabilityService",
"identifierService"
"identifierService",
"cacheService"
]
}
],

View File

@@ -28,7 +28,7 @@ define(
[],
function () {
"use strict";
var DISALLOWED_ACTIONS = ["move", "copy", "link", "window", "follow"];
/**
* The ActionCapability allows applicable Actions to be retrieved and
* performed for specific domain objects, e.g.:
@@ -54,37 +54,22 @@ define(
this.domainObject = domainObject;
}
function isEditable(domainObject){
return domainObject.getCapability('status').get('editing');
}
function hasEditableAncestor(domainObject){
return domainObject.hasCapability('context') &&
domainObject
.getCapability('context')
.getPath()
.some(function isEditable (ancestor){
return ancestor.getCapability('status').get('editing');
});
}
/**
* Retrieve the actions applicable to the domain object in the given
* context.
* Perform an action. This will find and perform the
* first matching action available for the specified
* context or key.
*
* @param {ActionContext|string} context the context in which
* to assess the applicability of the available actions; this is
* passed along to the action service to match against available
* to perform the action; this is passed along to
* the action service to match against available
* actions. The "domainObject" field will automatically
* be populated with the domain object that exposed
* this capability. If given as a string, this will
* be taken as the "key" field to match against
* specific actions.
*
* Additionally, this function will limit the actions
* available for an object in Edit Mode
* @returns {Array<Action>} The actions applicable to this domain
* object in the given context
* @returns {Promise} the result of the action that was
* performed, or undefined if no matching action
* was found.
* @memberof platform/core.ActionCapability#
*/
ActionCapability.prototype.getActions = function (context) {
@@ -93,19 +78,11 @@ define(
// but additionally adds a domainObject field.
var baseContext = typeof context === 'string' ?
{ key: context } : (context || {}),
actionContext = Object.create(baseContext),
actions;
actionContext = Object.create(baseContext);
actionContext.domainObject = this.domainObject;
actions = this.actionService.getActions(actionContext) || [];
if (isEditable(this.domainObject) || hasEditableAncestor(this.domainObject)){
return actions.filter(function(action){
return DISALLOWED_ACTIONS.indexOf(action.getMetadata().key) === -1;
});
} else {
return actions;
}
return this.actionService.getActions(actionContext);
};
/**

View File

@@ -35,10 +35,16 @@ define(
* @param $injector Angular's `$injector`
* @implements {Capability}
*/
function InstantiationCapability($injector, identifierService, domainObject) {
function InstantiationCapability(
$injector,
identifierService,
now,
domainObject
) {
this.$injector = $injector;
this.identifierService = identifierService;
this.domainObject = domainObject;
this.now = now;
}
/**
@@ -57,6 +63,8 @@ define(
space = parsedId.getDefinedSpace(),
id = this.identifierService.generate(space);
model.modified = this.now();
// Lazily initialize; instantiate depends on capabilityService,
// which depends on all capabilities, including this one.
this.instantiateFn = this.instantiateFn ||

View File

@@ -46,6 +46,7 @@ define(
* @implements {Capability}
*/
function PersistenceCapability(
cacheService,
persistenceService,
identifierService,
notificationService,
@@ -56,6 +57,7 @@ define(
this.modified = domainObject.getModel().modified;
this.domainObject = domainObject;
this.cacheService = cacheService;
this.identifierService = identifierService;
this.persistenceService = persistenceService;
this.notificationService = notificationService;
@@ -130,6 +132,7 @@ define(
domainObject = this.domainObject,
model = domainObject.getModel(),
modified = model.modified,
cacheService = this.cacheService,
persistenceService = this.persistenceService,
persistenceFn = model.persisted !== undefined ?
this.persistenceService.updateObject :
@@ -170,13 +173,10 @@ define(
}, modified);
}
// Only update if we don't have unsaved changes
return (model.modified === model.persisted) ?
this.persistenceService.readObject(
return this.persistenceService.readObject(
this.getSpace(),
this.domainObject.getId()
).then(updateModel) :
fastPromise(false);
).then(updateModel);
};
/**

View File

@@ -35,9 +35,8 @@ define(
* @param {ModelService} modelService this service to decorate
* @implements {ModelService}
*/
function CachingModelDecorator(modelService) {
this.cache = {};
this.cached = {};
function CachingModelDecorator(cacheService, modelService) {
this.cacheService = cacheService;
this.modelService = modelService;
}
@@ -51,17 +50,16 @@ define(
}
CachingModelDecorator.prototype.getModels = function (ids) {
var cache = this.cache,
cached = this.cached,
var cacheService = this.cacheService,
neededIds = ids.filter(function notCached(id) {
return !cached[id];
return !cacheService.has(id);
});
// Update the cached instance of a model to a new value.
// We update in-place to ensure there is only ever one instance
// of any given model exposed by the modelService as a whole.
function updateModel(id, model) {
var oldModel = cache[id];
var oldModel = cacheService.get(id);
// Same object instance is a possibility, so don't copy
if (oldModel === model) {
@@ -71,7 +69,7 @@ define(
// If we'd previously cached an undefined value, or are now
// seeing undefined, replace the item in the cache entirely.
if (oldModel === undefined || model === undefined) {
cache[id] = model;
cacheService.put(id, model);
return model;
}
@@ -91,15 +89,15 @@ define(
// Store the provided models in our cache
function cacheAll(models) {
Object.keys(models).forEach(function (id) {
cache[id] = cached[id] ?
var model = cacheService.has(id) ?
updateModel(id, models[id]) : models[id];
cached[id] = true;
cacheService.put(id, model);
});
}
// Expose the cache (for promise chaining)
function giveCache() {
return cache;
return cacheService.all();
}
// Look up if we have unknown IDs
@@ -110,7 +108,7 @@ define(
}
// Otherwise, just expose the cache directly
return fastPromise(cache);
return fastPromise(cacheService.all());
};
return CachingModelDecorator;

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