Compare commits

..

412 Commits

Author SHA1 Message Date
Pete Richards
a2bcc828eb More hacks 2016-06-17 16:26:34 -07:00
Pete Richards
7c6fa305ad basic objects working, need to standardize key usage 2016-06-17 12:38:35 -07:00
Pete Richards
7b68b2971e random notes 2016-05-12 13:36:34 -07:00
Pete Richards
f43cc60720 start api index readme 2016-05-10 11:02:18 -07:00
Pete Richards
f68ce2fc80 Stub in docs 2016-05-10 09:05:36 -07:00
Pete Richards
7b2762e034 stub in placeholders 2016-05-09 18:12:27 -07:00
Pete Richards
66c68e44bd start utilizing api in telemetry table 2016-05-06 16:02:54 -07:00
Pete Richards
04f59750b7 Throw in a readme to keep me ontrack 2016-05-06 16:01:24 -07:00
Pete Richards
58a2ec6d94 telemetry api caches formatters and evaluators 2016-05-06 14:55:05 -07:00
Pete Richards
04c11612c9 sinewave only has limits on cosine and sine 2016-05-06 14:54:38 -07:00
Pete Richards
030fc18c38 Flesh out formatting in telemetry API 2016-05-06 14:21:44 -07:00
Pete Richards
c5ec132484 Update sinewave definitions, limits, etc 2016-05-06 14:20:18 -07:00
Pete Richards
c3e5d0d155 remove comment 2016-05-06 12:32:43 -07:00
Pete Richards
d8e14a457b Sinewave provider functions like a real provider now 2016-05-06 12:22:25 -07:00
Pete Richards
8ca366a009 WIP 2016-05-05 17:25:38 -07:00
Pete Richards
761fbfe665 Init telemetry API bundle 2016-05-05 13:45:40 -07:00
Andrew Henry
01f290dc45 Merge pull request #873 from nasa/open871
Review and integrate open871
2016-05-03 14:20:56 -07:00
Charles Hacskaylo
ff36d9ee80 [Frontend] Removed bullets from ol, ul
open #869
- This should be cherry-picked into main
branches as well.
(cherry picked from commit 4c97413)
2016-04-29 10:54:28 -07:00
Pete Richards
9e5689f7dd Merge remote-tracking branch 'origin/revert-839-revert-822-open769' 2016-04-22 13:02:39 -07:00
Victor Woeltjen
0ccb696ee2 [Build] Bump version number, add -SNAPSHOT
...to begin sprint Herbert,
https://github.com/nasa/openmct/milestones/Herbert
2016-04-22 10:51:12 -07:00
Victor Woeltjen
d385e55e76 [Build] Remove snapshot suffix
Closes sprint Heinlein,
https://github.com/nasa/openmct/milestones/Heinlein
2016-04-22 10:46:07 -07:00
Andrew Henry
6bf1ef5bcc Revert "Revert "[Tables] Fix to correct sorting in realtime tables"" 2016-04-22 09:44:34 -07:00
Victor Woeltjen
abb511521b Merge pull request #837 from nasa/open794_fix
[Edit Mode] #794 Modified policy to show remove action in context for non-editable domain object types
2016-04-21 12:23:45 -07:00
Victor Woeltjen
3a9b1ee901 Merge pull request #839 from nasa/revert-822-open769
Revert "[Tables] Fix to correct sorting in realtime tables"
2016-04-21 09:21:12 -07:00
Andrew Henry
8b390e7fb9 Revert "[Tables] Fix to correct sorting in realtime tables" 2016-04-20 19:31:54 -07:00
Andrew Henry
29bce69eea Merge pull request #822 from nasa/open769
[Tables] Fix to correct sorting in realtime tables
2016-04-20 19:30:04 -07:00
Henry
aac5a6d250 #769 - Removed empty code block and addressed some excessive guard code 2016-04-20 19:18:27 -07:00
Henry
06436c488a [Edit Mode] #794 Modified policy to show remove action in context for non-editable domain object types 2016-04-18 19:05:46 -07:00
Victor Woeltjen
8b7af43d6c Merge pull request #823 from nasa/version-process-725
[Documentation] Add Version Guide
2016-04-14 17:30:55 -07:00
Victor Woeltjen
abb47eed36 [Documentation] Remove superfluous space
ddc241c0d0 (r59808305)
2016-04-14 16:30:17 -07:00
Andrew Henry
027d86ef4b Merge pull request #828 from nasa/build-win-827
[Build] Fix build on Windows
2016-04-14 16:23:42 -07:00
Andrew Henry
6cb9619fbe Merge pull request #829 from nasa/open630
[Edit mode] Simplify SaveAction
2016-04-14 16:11:49 -07:00
Henry
8c3616da32 Addressed code review points 2016-04-14 16:04:15 -07:00
Victor Woeltjen
ffd5faf9a2 [Persistence] Remove obsolete caching decorator
#831
2016-04-14 10:15:40 -07:00
Victor Woeltjen
00bf05c929 Merge pull request #830 from nasa/time-conductor-ux
Time Conductor updates query on blur, mobile support
2016-04-14 10:04:17 -07:00
Pete Richards
b682cf8340 [Style] Remove outdated comments 2016-04-13 17:41:24 -07:00
Pete Richards
22a5122ab7 [Conductor] Style for Phone and Tablet
Specify styles for time conductor on phone an tablet to hide the slider and
utilize space better.

https://github.com/nasa/openmct/issues/318
2016-04-13 17:17:52 -07:00
Pete Richards
7a7877d7c4 [Conductor] Add basic style for phone
Add styling for time conductor on mobile that removes slider and rearranges
inputs to utilize space more effectively.

https://github.com/nasa/openmct/issues/318
2016-04-13 16:17:17 -07:00
Pete Richards
69c059c943 [Conductor] Update inner bound on blur
The time conductor updates the inner and outer bounds when the input is
blurred, which results in the query updating without dragging.

Also allows time conductor to be utilized on mobile devices by entering
dates directly.

https://github.com/nasa/openmct/issues/318

User request:
https://github.jpl.nasa.gov/MissionControl/vista/issues/175
2016-04-13 13:49:23 -07:00
Pete Richards
6d58f23c0c [Style] Switch to prototype
Switch TimeRangeController to prototype style, and update tests
and template to utilize new style.
2016-04-13 13:23:33 -07:00
Henry
26e368f52d [Edit mode] Simplify SaveAction 2016-04-12 14:40:19 -07:00
Victor Woeltjen
1d78af8f1d [Build] Fix build on Windows
* In the prepublish step, run bower and gulp via node, instead of
  relying on shebang interpretation. (Forward-slash path separators
  appear to get normalized by node itself before executing the scripts.)
* In the gulp build, replace hard-coded *nix-style separators with
  path.sep; this allows stylesheets to be output to expected locations
  when building on Windows.

Addresses #827.
2016-04-12 13:02:48 -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
Henry
6322964dec Addressed comments from code review of #822 2016-04-11 14:30:21 -07:00
Henry
1bb6e17829 Minor code change to improve clarity 2016-04-11 13:37:31 -07:00
Henry
f34e8ba61b Modified code to call resize on every row add. Removed optimization to only resize when needed, because in fact resuze is necessary on every update in order to set vertical scroll size 2016-04-11 13:09:02 -07:00
Henry
2fb9b65652 Made comment a little more accurate 2016-04-11 12:57:27 -07:00
Henry
0c6b4a5a23 [Tables] Fix to correct sorting in realtime tables 2016-04-11 12:57:27 -07:00
Henry
20672ad028 [Tables] #801 Documented MctTable directive 2016-04-11 12:55:56 -07:00
Henry
99ba9edb95 Merged
Resolved merge conflicts

Resolved merge conflicts
2016-04-11 12:55:53 -07:00
Henry
23a8c305c1 [Table] #798 Simplified markup, moved styles to external stylesheet 2016-04-11 12:23:36 -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
ddc241c0d0 [Documentation] Add Version Guide
Migrate relevant information from existing version guide;
add instructions for incrementing versions per #725
2016-04-05 11:55:15 -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
7b5218c5ba [Edit Mode] #627 Fixed failing tests
Removed reference to defunct NavigationServiceDecorator

Removed virtual panels from drop gesture
2016-03-02 11:12:41 -08:00
Henry
f192544be3 Addressing issues from code review 2016-03-02 11:10:49 -08:00
Henry
2cc2c6a9d3 [Edit Mode] #627 removed edit concerns from browse controllers and markup
Fixed elements not appearing in edit mode

Fixed failing tests
2016-03-02 11:05:23 -08:00
Henry
a910fa8f37 Removed unused 'controller as' 2016-03-02 11:01:34 -08:00
Henry
65ca78d8aa Added missing dependency on 2016-03-02 11:00:08 -08:00
Henry
2f036a89e4 Refactoring out regions 2016-03-02 11:00:08 -08:00
Henry
fa46d31ac2 [Edit Mode] #627 slightly modified edit representer to detect newly created objects
Added some comments, renamed controller variable in markup

Removed edit references from BrowseController
2016-03-02 10:57:05 -08:00
Henry
549dfab5aa [Edit Mode] #627 remove edit concerns from browse controller 2016-03-02 10:55:18 -08:00
Victor Woeltjen
494212a448 Merge pull request #653 from nasa/open499
[Notifications] #499 All notifications now dismissable by default.
2016-03-01 14:50:56 -08:00
Victor Woeltjen
8511dc93b5 Merge pull request #714 from nasa/ci-test-reporter
[Build] run JSHint on circleci, generate test reports
2016-03-01 13:47:24 -08:00
Pete Richards
751414a686 [CI] Save coverage in artifacts
Save code coverage results in artifacts when building on circleci.
2016-03-01 13:37:52 -08:00
Pete Richards
668b09b789 [Style] Pull functions out of loop
Pull functions out of loop for jshint compliance.
2016-03-01 13:25:37 -08:00
Pete Richards
b9e0a77655 [CI] Run JSHINT after tests 2016-03-01 13:07:16 -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
Pete Richards
d9b2034550 [Tests] Add jUnit reporter
Add jUnit reporter to allow CircleCI to store test results.
2016-03-01 12:53:32 -08:00
Pete Richards
183bd9793c Merge branch 'open677' 2016-03-01 11:33:31 -08:00
Pete Richards
d176797307 [Style] Add missing semicolon 2016-03-01 10:59:23 -08:00
Pete Richards
96d9f8c194 [Templates] load plot templates with require
Load templates with requirejs.

https://github.com/nasa/openmctweb/issues/673
2016-03-01 10:52:07 -08:00
Pete Richards
748673f99b Merge branch 'master' into open638_rebase 2016-03-01 10:48:53 -08:00
Pete Richards
78374f8241 Merge branch 'open401' 2016-03-01 10:37:12 -08:00
Pete Richards
bc6185f76d [Browse] Remove unused constant
https://github.com/nasa/openmctweb/issues/401
2016-03-01 10:36:30 -08:00
Henry
747a98d130 Addressed issues from code review 2016-02-29 18:42:48 -08:00
Andrew Henry
7daaecbf8f Merge pull request #710 from nasa/open673
[Templates] Load templates using RequireJS text plugin
2016-02-29 18:45:46 +00:00
Andrew Henry
6f9e78a14f Merge pull request #711 from nasa/open442a
[Frontend] Markup, CSS changes
2016-02-29 17:36:54 +00:00
Victor Woeltjen
beee4136a6 Merge pull request #702 from nasa/open164
Review and integrate open164
2016-02-26 16:49:26 -08:00
Charles Hacskaylo
5a9bcfa938 [Frontend] Markup, CSS changes
#442
Removed white space from markup;
Moved getGlyphClass up to status-block-holder
element out of status-block;
CSS mods to selectors and style defs
in _messages.scss;
2016-02-26 16:48:23 -08:00
Victor Woeltjen
721557b814 [Templates] Exercise selection method
...add to TimelineSwimlanePopulator to reflect changes to
time at which selection object may become available as
a consequence to changes in the way templates are normally
loaded. #673
2016-02-26 16:29:06 -08:00
Victor Woeltjen
70ed16491a [Templates] Change watch order
...to work around order-sensitive test case
2016-02-26 16:26:31 -08:00
Victor Woeltjen
7240ff4f8d [Templates] Update mct-control spec
...to reflect usage of templateLinker, to support including
templates via RequireJS text plugin
2016-02-26 16:22:55 -08:00
Victor Woeltjen
3a6e0be2d7 [Templates] Update FixedController spec
...to reflect changes to how selection object is obtained,
which in turn reflects change to using templates obtained
via RequireJS text plugin, instead of loading by URL.
2016-02-26 16:19:14 -08:00
Victor Woeltjen
9b21b0b7f2 [Templates] Update mct-container spec
...to reflect change to template over templateUrl
2016-02-26 16:17:33 -08:00
Victor Woeltjen
164c2faf07 Merge branch 'master' into open673
Merge latest from master into topic branch for #673
2016-02-26 15:54:41 -08:00
Victor Woeltjen
894cf5c461 [Templates] Include templates in test configuration
...such that they are available to the RequireJS text plugin
for loading.
2016-02-26 15:53:35 -08:00
Victor Woeltjen
fe419714f5 [Templates] Check for availability of timespan
...as ordering changes due to change from templateUrl to template
may mean this is not available when first initialized.
2016-02-26 15:50:07 -08:00
Victor Woeltjen
f3fd2e67fc [Templates] Watch for selection object
...from Timeline, to ensure toolbar appears etc.
Reflects changes to ordering triggered by use of
template instead of templateUrl
2016-02-26 15:49:21 -08:00
Victor Woeltjen
931fa77cbe [Templates] Handle deferred selection availability
Loading templates via RequireJS text plugin means they are
immediately available; appears to have caused a change in
ordering wherein controllers for views may be initialized
before representers have installed things like selection
state. As such, need to watch for changes instead of simply
checking for a selection object when the controller is
initialized.
2016-02-26 15:37:19 -08:00
Andrew Henry
872c4021e3 Merge pull request #82 from tarikozket/patch-1
Fixed typo
2016-02-26 23:28:24 +00:00
Andrew Henry
26d29c3d92 Merge pull request #652 from nasa/open649
[CSV Export] Implement exportService
2016-02-26 23:18:12 +00:00
Victor Woeltjen
596735352a [Templates] Simplify MCTToolbar
Use mct-form as a basis; simply change the template.
2016-02-26 15:17:31 -08:00
Henry
402512a461 Merged from master to resolve conflict 2016-02-26 15:15:22 -08:00
Victor Woeltjen
2d03e3e6d4 [Templates] Remove unused template path calculation 2016-02-26 15:03:45 -08:00
Victor Woeltjen
19b442cc0b [Templates] Require data table templates
...via text plugin
2016-02-26 15:02:04 -08:00
Victor Woeltjen
5c3d8508a2 [Templates] Use templateLinker for forms
...for compatibility with both template and templateUrl
2016-02-26 15:01:40 -08:00
Victor Woeltjen
8581547a9c [Templates] Allow only template property for containers
...to work around difficulties with transclusion using
templateLinker.
2016-02-26 14:49:55 -08:00
Charles Hacskaylo
192bbae6e5 [Frontend] Fix paths, includes
#702
Per https://github.com/nasa/openmctweb/pull/702;
Removed include of _logo-and-bg.scss into _about.scss;
2016-02-26 14:49:34 -08:00
Victor Woeltjen
e61711688e [Templates] Use templateLinker from MCTContainer
...for compatibility with both template and templateUrl.
2016-02-26 14:24:41 -08:00
Victor Woeltjen
a73f1ebbbd Merge pull request #637 from nasa/rems_data
[Examples] Rems data integration
2016-02-26 14:21:30 -08:00
Henry
4674918b4b [Examples] #359 Updated to attempt connection to remote data source and fallback to local if unavailable
Minor change to readme

Fixed JSLint errors

More JSLint errors

[Example] Rems data integration - disabled bundle by default.

[Examples] REMS data integration - added newlines at end of files

[Example] Added time conductor support to REMS data integration

Added caching of results

[Examples] Added domain format to REMS data #359

[Example] #637 Added local proxy to app.js to allow cross-origin requests

Updated readme
2016-02-26 14:03:10 -08:00
Victor Woeltjen
741d4476e6 [Templates] Use text plugin for toolbar 2016-02-26 13:12:35 -08:00
Victor Woeltjen
bf1fa0ac4c [Templates] Include templates using text plugin
Resolves #673
2016-02-26 13:07:50 -08:00
Victor Woeltjen
60efdb4ad3 [Templates] Add in-place rewrite step 2016-02-26 13:07:32 -08:00
Victor Woeltjen
8ea56486c5 [Templates] Normalize spacing 2016-02-26 13:03:06 -08:00
Victor Woeltjen
e13e068b6e [Templates] Begin teplacing templateUrl properties 2016-02-26 13:00:50 -08:00
Victor Woeltjen
852faf061e [Templates] Add parameter names for required templates 2016-02-26 12:52:02 -08:00
Victor Woeltjen
f2e4b01721 [Templates] Add template paths
...with text! prefix
2016-02-26 12:50:28 -08:00
Victor Woeltjen
930fed83e8 [Templates] Create variable names by template URL 2016-02-26 12:17:57 -08:00
Victor Woeltjen
4666292907 [Templates] Begin writing migration script
...to rewrite bundle.js files to load templates via
the RequireJS text plugin. #673
2016-02-26 12:12:13 -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
0068348bb2 Merge pull request #704 from nasa/open703
[Examples] #703 Changed imagery telemetry metadata to use 'utc' format
2016-02-26 11:00:26 -08:00
Charles Hacskaylo
bc3eb4ab8d [Frontend] New logo art
#164
New logo art for Open MCT added;
Removed console.log;
2016-02-26 10:59:54 -08:00
Charles Hacskaylo
d203f3adc0 [Frontend] New logo art; paths changed
#164
Per comments in #702, abs paths changed
to relative;
New logo art for Open MCT added;
CSS tweaked as needed;
2016-02-26 10:15:15 -08:00
Henry
5e7eb7e87e [Examples] #703 Changed imagery telemetry metadata to use 'utc' format for time 2016-02-26 09:32:03 -08:00
Charles Hacskaylo
1a2a2e66ca [Frontend] Removed commented styling
open #164
2016-02-25 12:41:54 -08:00
Charles Hacskaylo
129b554f9d [Frontend] Significant markup/CSS mods for splash screen
#164
https://github.jpl.nasa.gov/MissionControl/vista/issues/299
App logo and bg files renamed;
Added openmct.scss to hold openmct-specific styles;
Renamed _startup.scss to startup-base.scss
which now renders its own .css file;

Still to-do: apply to WARP including needed
mods to its About dialog screen;
2016-02-24 17:47:24 -08:00
Charles Hacskaylo
164d959f60 [Frontend] Significant markup/CSS mods for splash screen
#164
Markup in index.html and about-dialog.html
changed to simplify and use :before/:after psuedos;
CSS in _logo-and-bg.scss modded for same;
Added _startup.scss to hold general CSS for
the startup screen;
Renamed startup.scss to startup-open.scss;
Modified SplashScreenManager.js to target renamed
outer container .l-splash-holder;
Added media query for startup screen on phone;
Cleanup: moved classes out of _effects into _global;
Still to-do: apply to WARP and VISTA, including needed
mods to their About dialog screens;
2016-02-23 18:30:21 -08:00
Charles Hacskaylo
99cf690ad4 Merge branch 'master' into open164 2016-02-23 16:03:24 -08:00
Henry
aabeb72203 [Plots] #638 Fixed failing test 2016-02-23 15:22:21 -08:00
Pete Richards
fcdf89a4ee Merge branch 'master' into open638_rebase 2016-02-23 10:56:13 -08:00
Pete Richards
77a2e0a70b Merge branch 'master' into open639 2016-02-23 10:46:33 -08:00
Victor Woeltjen
f379db55e7 Merge pull request #699 from nasa/remove-compass
Remove compass, add bourbon
2016-02-23 10:00:01 -08:00
Pete Richards
51fbbfe601 [Gulp] Revert accidental change 2016-02-22 19:07:36 -08:00
Pete Richards
eaab70741a [Build] Generate CSS sourcemaps
Generate CSS sourcemaps to aide in debugging.

https://github.com/nasa/openmctweb/issues/698
2016-02-22 18:57:05 -08:00
Pete Richards
a05d6d8ee8 [Build] Rebuild scss when starting server
Rebuild scss when starting the development server.

https://github.com/nasa/openmctweb/issues/698
2016-02-22 18:30:07 -08:00
Pete Richards
88945c48d4 [Build] Gracefully handle sass error
https://github.com/nasa/openmctweb/issues/698
2016-02-22 18:29:26 -08:00
Pete Richards
bd7ad85bd7 [Build] Remove unused dependency
https://github.com/nasa/openmctweb/issues/698
2016-02-22 18:28:45 -08:00
Pete Richards
9b3c8dce25 [SCSS] Remove old references to compass
Remove any old references to compass.

https://github.com/nasa/openmctweb/issues/698
2016-02-22 18:22:44 -08:00
Pete Richards
4d800d26e2 [CSS] Add reset to replace compass/reset
Add reset.css which replaces compass/reset.

https://github.com/nasa/openmctweb/issues/698
2016-02-22 18:18:06 -08:00
Pete Richards
0a71835687 [Build] Switch compass to bourbon
Change mixin library to bourbon.  Significantly reduces sass build time.

https://github.com/nasa/openmctweb/issues/698
2016-02-22 18:02:16 -08:00
Pete Richards
25f3b1e110 [Frontend] Add splash screen manager
Add a runtime extension that detects the splash screen and triggers a fade out
after the application has loaded.  Once the fade out has ended, it removes the
element from the page.

Related to https://github.com/nasa/openmctweb/issues/164
2016-02-22 16:39:20 -08:00
Charles Hacskaylo
31a983966b [Frontend] In-progress on adding branded per-app screens
open #164
CSS, markup;
2016-02-22 15:44:57 -08:00
Victor Woeltjen
d3e274bfdd Merge branch 'master' into open401
Resolve conflicts for #416

Conflicts:
	platform/commonUI/browse/bundle.json
	platform/commonUI/browse/src/BrowseController.js
2016-02-22 14:27:21 -08:00
Charles Hacskaylo
626cc502fb [Frontend] Removed -moz-osx-font-smoothing property
open #687
2016-02-18 13:24:06 -08:00
Charles Hacskaylo
95f1768fb7 [Frontend] Refactoring to use Victorizr instead of media queries
open #639
open #683
open #169
Tweak to espresso tree view control color and hover color
for espresso theme; reordered elements in _constants;
2016-02-18 13:10:54 -08:00
Charles Hacskaylo
fb20af24bc [Frontend] Refactoring to use Victorizr instead of media queries
open #639
open #683
open #169
open #335
    Fixed wrong application of body.desktop.mini-tab...;
    Increased size of pane collapse/expand icons;
    Removed max-width applied to search input holder;
2016-02-18 11:25:12 -08:00
Charles Hacskaylo
f6cb76354e [Frontend] Refactoring to use Victorizr instead of media queries
open #639
open #683
open #169
MQs refactored in mobile/_layout.scss;
2016-02-17 16:34:33 -08:00
Charles Hacskaylo
66905cbcbb [Frontend] Refactoring to use Victorizr instead of media queries
open #639
open #683
open #169
open #494
Replaced MQ around mobile/_tree.scss ul.tree;
Removed MQ desktop around hover in mixin btnBase;
Reversed orientation of mobile tree arrows for #494;
2016-02-17 16:12:18 -08:00
Charles Hacskaylo
a4f24adb8a [Frontend] Refactoring to use Victorizr instead of media queries
open #639
Replaced MQ around _controls webkit-scrollbar CSS;
2016-02-17 10:26:42 -08:00
Charles Hacskaylo
242e02e9af Added compass_scripts directory
open #639
Added dir to .gitignore
2016-02-17 10:20:58 -08:00
Charles Hacskaylo
0ddaa52a8a [Frontend] Refactor CSS to not use 'desktop' media query
open #639
Refactored all usage of @include desktop to use CSS selector body.desktop
instead; Still to-do: deal with desktopandtablet usage with hover bubbles
and mixins btnBase;
2016-02-16 18:38:06 -08:00
Melanie Lean
53c60ee64f [Timelines] #677 Applied fix to prevent editing of timelines in browse mode
Fixed failing test
2016-02-11 21:52:05 -08:00
Henry
7d0de68db9 [Plot] #638 Changed plot series to an array 2016-02-10 20:27:04 -08:00
Henry
24c750b41e [Plot] Fixed jsLint, removed onchange
Removed ngChange from mct-control

Removed ng-change
2016-02-09 21:19:47 -08:00
Henry
ab1c79f25d [Plot] Switched to $watchCollection on form model 2016-02-09 20:52:47 -08:00
Victor Woeltjen
437b235361 [CSV Export] Update JSDoc
Fill in complete JSDoc and separate out callback documentation
per code review:

https://github.com/nasa/openmctweb/pull/652/files#r52263213
https://github.com/nasa/openmctweb/pull/652/files#r52264447
2016-02-09 12:30:53 -08:00
Victor Woeltjen
6880c82719 [CSV Export] Restructure example
Restructure CSV export example to reflect recommended style
for plugins, per code review;
https://github.com/nasa/openmctweb/pull/652#discussion_r52263869
2016-02-09 12:13:33 -08:00
Henry
645bd5743f [Plots] #638 Addressing feedback from code review
[Plots] #638 Fixing failing tests

[Plot] Changed PlotOptionsController to prototype form

Fixed spacing

Fixed jslint issue
2016-02-08 23:36:45 -08:00
Victor Woeltjen
273cf1c14f [Timeline] Fix columns exported 2016-02-08 18:07:03 -08:00
Henry
be031285b9 Added form-level change event 2016-02-08 17:46:21 -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
Victor Woeltjen
b40ac6f44f Merge remote-tracking branch 'origin/master' into open649 2016-02-08 12:25:25 -08:00
Henry
5292b27e7d [Notifications] #499 All notifications now dismissable by default.
jslint
2016-02-05 17:51:31 -08:00
Victor Woeltjen
3adc5f1e26 [CSV Export] Upgrade to phantomjs launcher 1.0.0 2016-02-05 16:56:26 -08:00
Victor Woeltjen
92e49d6b76 [CSV Export] Add licensing info for run-time
Add licensing info for CSV.js and FileSaver.js as licenses
which can be displayed at run-time.
2016-02-05 16:10:30 -08:00
Victor Woeltjen
659d05f73a [CSV Export] Update LICENSES.md
...to reflect usage of CSV.js and FileSaver.js, added to
support export.
2016-02-05 16:05:41 -08:00
Victor Woeltjen
2f0fd8eebd [CSV Export] Add JSDoc to ExportService 2016-02-05 15:12:47 -08:00
Victor Woeltjen
882cf80ba9 [CSV Export] Include exportService as active bundle 2016-02-05 15:07:51 -08:00
Victor Woeltjen
8c1264ab22 [CSV Export] Add example of exportService usage 2016-02-05 15:07:18 -08:00
Victor Woeltjen
cb0f191ab3 [CSV Export] Add FileSaver dependency
...to handle export part of CSV export.
2016-02-05 14:39:28 -08:00
Victor Woeltjen
c07dc0ea8b [CSV Export] Test with specified filename 2016-02-05 14:08:47 -08:00
Victor Woeltjen
c4d5643ea7 [CSV Export] Test with headers specified 2016-02-05 14:06:40 -08:00
Victor Woeltjen
300d71ddc2 [CSV Export] Verify CSV data content 2016-02-05 14:03:15 -08:00
Victor Woeltjen
54c67b891c [CSV Export] Update PhantomJS version
Use version 2.1+ for availability of Linux binaries;
incidentally addresses #258.
2016-02-05 13:59:03 -08:00
Victor Woeltjen
013690e0df [CSV Export] Add test case which examines CSV 2016-02-05 13:58:17 -08:00
Victor Woeltjen
8868b6a130 [CSV Export] Begin testing exportService
...including fixes to immediately-identified errors.
2016-02-05 13:32:21 -08:00
Victor Woeltjen
750a5648d2 [CSV Export] Upgrade PhantomJS
...for Blob support.
2016-02-05 13:31:08 -08:00
Victor Woeltjen
cec6295d24 [CSV Export] Sketch in exportService 2016-02-05 13:02:21 -08:00
Victor Woeltjen
15eb4b047f [CSV Export] Add empty scripts for CSV export 2016-02-05 12:47:57 -08:00
Victor Woeltjen
3ae8fcc8b4 [CSV Export] Add CSV library as dependency
For use in general-purpose CSV export service, #649
2016-02-05 12:21:09 -08:00
Henry
9371fcbc4c [Plot] #638 Added a new plot options example bundle and rebased
Fixed jsdoc

Fixed incorrect memberof declaration

Corrected memberof statement
2016-02-04 15:17:07 -08:00
Henry
abf5f22155 [Plots] #638 added onchange handling in order to synchronize forms with domain object model.
Fixed failing test

Added tests

jslint errors

Minor refactoring of layout bundle

revert layout/bundle.json
2016-02-04 14:26:21 -08:00
Charles Hacskaylo
f2903f4030 [Frontend] Final styling on properties form in Inspector
open #638
Added custom radio button control and modified
PlotOptionsController / plotOptionsStructure
accordingly; spacing, borders, etc. are
all as finally intended;
2016-02-04 14:25:02 -08:00
Charles Hacskaylo
371669fbce [Frontend] Mods in progress to form layout
open #638
Major progress on form-row markup and CSS when
in Inspector 'part' context; General fixes cleanups
to custom checkbox/radio CSS;
2016-02-04 14:23:29 -08:00
Charles Hacskaylo
68f3cd087d [Frontend] Mods in progress to form layout
open #638
In progress;
2016-02-04 14:23:29 -08:00
Charles Hacskaylo
115ffe7963 [Frontend] Fixes to scrolling and layout in Inspector
open #638
In progress;
2016-02-04 14:23:29 -08:00
Henry
e3a0cae5fd [Plot] #638 Fleshing out form structures 2016-02-04 14:23:29 -08:00
Charles Hacskaylo
8bb5a47b88 CSS updated to use new e619 character
open #638
2016-02-04 14:23:28 -08:00
Charles Hacskaylo
f1b6d7f749 [Frontend] New custom radio mctControl
open #638
Markup and initial CSS
2016-02-04 14:23:28 -08:00
Henry
6fb6761abf [Plots] #638 New plot display options 2016-02-04 14:23:28 -08:00
Henry
c091063b83 [Examples] #359 Cleaned up REMS data integration example. 2016-01-22 10:49:40 -08:00
Henry
2e65a6a63e Updating code to conform to code style 2015-12-11 15:39:53 -08:00
Victor Woeltjen
43f6981ba1 [Browse] Test navigation when path is not found 2015-12-11 13:21:52 -08:00
Victor Woeltjen
b8206b8824 [Browse] Ensure selection at startup
...even when domain object identified by default path is
not found.
2015-12-11 13:18:25 -08:00
Victor Woeltjen
5f7f349f29 [Browse] Specify default selection in a constant
https://github.com/nasa/openmctweb/issues/401
2015-12-11 12:31:06 -08:00
Henry
ef0a918b59 Merge branch 'open338' into rems_data 2015-12-03 19:02:28 -08:00
Henry
5fd1f6a055 Merge branch 'open338' into rems_data 2015-12-03 18:57:07 -08:00
Henry
d45c5e2ffb Added 'setLocation' flag 2015-12-03 18:56:59 -08:00
Henry
1fef6b30b7 Merge branch 'open338' into rems_data 2015-12-03 18:41:50 -08:00
Henry
461cc59b3e #338 changed isLink check to check whether location is set 2015-12-03 18:41:13 -08:00
Henry
c038ccd0d2 Removed unused parameter 2015-12-03 18:24:38 -08:00
Henry
e16b156d1d Merge branch 'open338' into rems_data 2015-12-03 15:28:25 -08:00
Henry
1f6284257e Merge branch 'open338' into rems_data 2015-12-03 14:48:02 -08:00
Henry
16bf800257 Merge branch 'open338' into rems_data 2015-12-02 19:19:08 -08:00
Henry
7fad2f6f2e Merge branch 'open338' into rems_data 2015-12-02 19:10:33 -08:00
Henry
73ca30e654 Merged changes from Master 2015-12-01 10:44:42 -08:00
Andrew Henry
fc751b1332 Merge remote-tracking branch 'origin/open181' into rems_data_merge 2015-10-22 21:31:45 -07:00
Andrew Henry
cdc2a407dc Fixed erroneous data 2015-10-22 21:30:13 -07:00
Andrew Henry
14722a6ef5 Reset histories before fetching 2015-10-16 08:32:44 -07:00
Andrew Henry
0538d6e60f Initial working version 2015-10-12 19:54:03 -07:00
Andrew Henry
1fcf900271 Added telemetry request ID prefix 2015-10-12 10:41:21 -07:00
Andrew Henry
183468fcbf Trying to figure out why requests have no 'source' property 2015-10-10 12:17:30 -07:00
Henry
9b11d95437 shuttle 2015-10-08 16:04:14 -07:00
Henry
67d78772fa Added providers, adapters, data dictionary 2015-10-08 08:46:44 -07:00
Tarik
7f0f03e787 Fixed typo 2015-08-25 14:20:27 +03:00
354 changed files with 15819 additions and 21532 deletions

1
.gitignore vendored
View File

@@ -8,6 +8,7 @@
*.sass-cache
*COMPILE.css
*.css
*.css.map
# Intellij project configuration files
*.idea

View File

@@ -1,6 +0,0 @@
source "https://rubygems.org"
group :development do
gem "compass", ">= 1.0.3"
gem "sass", "~> 3.4.18"
end

View File

@@ -1,32 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
chunky_png (1.3.5)
compass (1.0.3)
chunky_png (~> 1.2)
compass-core (~> 1.0.2)
compass-import-once (~> 1.0.5)
rb-fsevent (>= 0.9.3)
rb-inotify (>= 0.9)
sass (>= 3.3.13, < 3.5)
compass-core (1.0.3)
multi_json (~> 1.0)
sass (>= 3.3.0, < 3.5)
compass-import-once (1.0.5)
sass (>= 3.2, < 3.5)
ffi (1.9.10)
multi_json (1.11.2)
rb-fsevent (0.9.7)
rb-inotify (0.9.7)
ffi (>= 0.5.0)
sass (3.4.21)
PLATFORMS
ruby
DEPENDENCIES
compass (>= 1.0.3)
sass (~> 3.4.18)
BUNDLED WITH
1.10.6

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
@@ -416,6 +392,104 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
---
### CSV.js
#### Info
* Link: https://github.com/knrz/CSV.js
* Version: 3.6.4
* Authors: Kash Nouroozi
* Description: Encoder for CSV (comma separated values) export
#### License
Copyright (c) 2014 Kash Nouroozi
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.
---
### FileSaver.js
#### Info
* Link: https://github.com/eligrey/FileSaver.js/
* Version: 0.0.2
* Authors: Eli Grey
* Description: File download initiator (for file exports)
#### License
Copyright © 2015 Eli Grey.
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.
---
### 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

@@ -45,7 +45,7 @@ When `npm test` is run, test results will be written as HTML to
The tests described above are all at the unit-level; an additional
test suite using [Protractor](https://angular.github.io/protractor/)
us under development, in the `protractor` folder.
is under development, in the `protractor` folder.
To run:

20
api/README.md Normal file
View File

@@ -0,0 +1,20 @@
# API
This directory is for draft API documentation and design. The API is organized into a few major components, which are documented in their own READMEs. See the following:
* Domain Objects
Capabilities
Events
Mutation
Etc
* [Object API](object-api/README.md) (encapsulates persistence), should include roots
* [Region API](region-api/README.md)
* [Telemetry API](telemetry-api/README.md)
* [Type API](type-api/README.md)
Not yet started:
* [Action API](action-api/README.md)
* [Indicators API](indicators-api/README.md) -- potentially compress into regions?
* [Plugin API](plugin-api/README.md)

View File

@@ -0,0 +1,93 @@
define([
], function (
) {
var PROVIDER_REGISTRY = [];
function getProvider (object) {
return PROVIDER_REGISTRY.filter(function (p) {
return p.appliesTo(object);
})[0];
};
function composition(object) {
var provider = getProvider(object);
if (!provider) {
return;
}
return new CompositionCollection(object, provider);
};
composition.addProvider = function (provider) {
PROVIDER_REGISTRY.unshift(provider);
};
window.MCT = window.MCT || {};
window.MCT.composition = composition;
function CompositionCollection(domainObject, provider) {
this.domainObject = domainObject;
this.provider = provider;
};
CompositionCollection.prototype.add = function (child, skipMutate) {
if (!this._children) {
throw new Error("Must load composition before you can add!");
}
// we probably should not add until we have loaded.
// todo: should we modify parent?
if (!skipMutate) {
this.provider.add(this.domainObject, child);
}
this.children.push(child);
this.emit('add', child);
};
CompositionCollection.prototype.load = function () {
return this.provider.load(this.domainObject)
.then(function (children) {
this._children = [];
children.map(function (c) {
this.add(c, true);
}, this);
this.emit('load');
// Todo: set up listener for changes via provider?
}.bind(this));
};
CompositionCollection.prototype.remove = function (child) {
var index = this.children.indexOf(child);
if (index === -1) {
throw new Error("Unable to remove child: not found in composition");
}
this.provider.remove(this.domainObject, child);
this.children.splice(index, 1);
this.emit('remove', index, child);
};
var DefaultCompositionProvider = {
appliesTo: function (domainObject) {
return !!domainObject.composition;
},
load: function (domainObject) {
return Promise.all(domainObject.composition.map(MCT.objects.get));
},
add: function (domainObject, child) {
domainObject.composition.push(child.key);
}
};
composition.addProvider(DefaultCompositionProvider);
function Injector() {
console.log('composition api injected!');
}
return Injector;
});

View File

@@ -0,0 +1,35 @@
# Composition API - Overview
The composition API is straightforward:
MCT.composition(object) -- returns a `CompositionCollection` if the object has
composition, returns undefined if it doesn't.
## CompositionCollection
Has three events:
* `load`: when the collection has completed loading.
* `add`: when a new object has been added to the collection.
* `remove` when an object has been removed from the collection.
Has three methods:
`Collection.load()` -- returns a promise that is fulfilled when the composition
has loaded.
`Collection.add(object)` -- add a domain object to the composition.
`Collection.remove(object)` -- remove the object from the composition.
## Composition providers
composition providers are anything that meets the following interface:
* `provider.appliesTo(domainObject)` -> return true if this provider can provide
composition for a given domain object.
* `provider.add(domainObject, childObject)` -> adds object
* `provider.remove(domainObject, childObject)` -> immediately removes objects
* `provider.load(domainObject)` -> returns promise for array of children
There is a default composition provider which handles loading composition for
any object with a `composition` property. If you want specialized composition
loading behavior, implement your own composition provider and register it with
`MCT.composition.addProvider(myProvider)`

View File

@@ -22,41 +22,26 @@
/*global define*/
define([
"./src/ScrollingListController",
'./CompositionAPI',
'legacyRegistry'
], function (
ScrollingListController,
CompositionAPI,
legacyRegistry
) {
"use strict";
legacyRegistry.register("platform/features/scrolling", {
"name": "Scrolling Lists",
"description": "Time-ordered list of latest data.",
"extensions": {
"views": [
legacyRegistry.register('api/composition-api', {
name: 'Composition API',
description: 'The public Composition API',
extensions: {
runs: [
{
"key": "scrolling",
"name": "Scrolling",
"glyph": "5",
"description": "Scrolling list of data values.",
"templateUrl": "templates/scrolling.html",
"needs": [
"telemetry"
],
"delegation": true
}
],
"controllers": [
{
"key": "ScrollingListController",
"implementation": ScrollingListController,
"depends": [
"$scope",
"telemetryFormatter"
key: "CompositionAPI",
priority: "mandatory",
implementation: CompositionAPI,
depends: [
]
}
]
}
});
});

200
api/object-api/ObjectAPI.js Normal file
View File

@@ -0,0 +1,200 @@
define([
'lodash'
], function (
_
) {
/**
Object API. Intercepts the existing object API while also exposing
A new Object API.
MCT.objects.get('mine')
.then(function (root) {
console.log(root);
MCT.objects.getComposition(root)
.then(function (composition) {
console.log(composition)
})
});
*/
var Objects = {},
ROOT_REGISTRY = [],
PROVIDER_REGISTRY = {},
FALLBACK_PROVIDER;
window.MCT = window.MCT || {};
window.MCT.objects = Objects;
// take a key string and turn it into a key object
// 'scratch:root' ==> {namespace: 'scratch', identifier: 'root'}
function parseKeyString(key) {
if (typeof key === 'object') {
return key;
}
var namespace = '',
identifier = key;
for (var i = 0, escaped = false, len=key.length; i < len; i++) {
if (key[i] === ":" && !escaped) {
namespace = key.slice(0, i);
identifier = key.slice(i + 1);
break;
}
}
return {
namespace: namespace,
identifier: identifier
};
};
// take a key and turn it into a key string
// {namespace: 'scratch', identifier: 'root'} ==> 'scratch:root'
function makeKeyString(key) {
if (typeof key === 'string') {
return key;
}
if (!key.namespace) {
return key.identifier;
}
return [
key.namespace.replace(':', '\\:'),
key.identifier.replace(':', '\\:')
].join(':');
};
// Converts composition to use key strings instead of keys
function toOldFormat(model) {
delete model.key;
if (model.composition) {
model.composition = model.composition.map(makeKeyString);
}
return model;
};
// converts composition to use keys instead of key strings
function toNewFormat(model, key) {
model.key = key;
if (model.composition) {
model.composition = model.composition.map(parseKeyString);
}
return model;
};
// Root provider is hardcoded in; can't be skipped.
var RootProvider = {
'get': function () {
return Promise.resolve({
name: 'The root object',
type: 'root',
composition: ROOT_REGISTRY
});
}
};
// Retrieve the provider for a given key.
function getProvider(key) {
if (key.identifier === 'ROOT') {
return RootProvider;
}
return PROVIDER_REGISTRY[key.namespace] || FALLBACK_PROVIDER;
};
Objects.addProvider = function (namespace, provider) {
PROVIDER_REGISTRY[namespace] = provider;
};
[
'save',
'delete',
'get'
].forEach(function (method) {
Objects[method] = function () {
var key = arguments[0],
provider = getProvider(key);
if (!provider) {
throw new Error('No Provider Matched');
}
if (!provider[method]) {
throw new Error('Provider does not support [' + method + '].');
}
return provider[method].apply(provider, arguments);
};
});
Objects.addRoot = function (key) {
ROOT_REGISTRY.unshift(key);
};
Objects.removeRoot = function (key) {
ROOT_REGISTRY = ROOT_REGISTRY.filter(function (k) {
return (
k.identifier !== key.identifier ||
k.namespace !== key.namespace
);
});
};
function ObjectServiceProvider(objectService, instantiate) {
this.objectService = objectService;
this.instantiate = instantiate;
}
ObjectServiceProvider.prototype.save = function (object) {
var key = object.key,
keyString = makeKeyString(key),
newObject = this.instantiate(toOldFormat(object), keyString);
return object.getCapability('persistence')
.persist()
.then(function () {
return toNewFormat(object, key);
});
};
ObjectServiceProvider.prototype.delete = function (object) {
// TODO!
};
ObjectServiceProvider.prototype.get = function (key) {
var keyString = makeKeyString(key);
return this.objectService.getObjects([keyString])
.then(function (results) {
var model = JSON.parse(JSON.stringify(results[keyString].getModel()));
return toNewFormat(model, key);
});
};
// Injects new object API as a decorator so that it hijacks all requests.
// Object providers implemented on new API should just work, old API should just work, many things may break.
function ObjectAPIInjector(ROOTS, instantiate, objectService) {
this.getObjects = function (keys) {
var results = {},
promises = keys.map(function (keyString) {
var key = parseKeyString(keyString);
return Objects.get(key)
.then(function (object) {
object = toOldFormat(object)
results[keyString] = instantiate(object, keyString);
});
});
return Promise.all(promises)
.then(function () {
return results;
});
};
FALLBACK_PROVIDER = new ObjectServiceProvider(objectService, instantiate);
ROOTS.forEach(function (r) {
ROOT_REGISTRY.push(parseKeyString(r.id));
});
return this;
}
return ObjectAPIInjector;
});

101
api/object-api/README.md Normal file
View File

@@ -0,0 +1,101 @@
# Object API - Overview
The object API provides methods for fetching domain objects.
# Keys
Keys are a composite identifier that is used to create and persist objects. Ex:
```javascript
{
namespace: 'elastic',
identifier: 'myIdentifier'
}
```
In old MCT days, we called this an "id", and we encoded it in a single string.
The above key would encode into the identifier, `elastic:myIdentifier`.
When interacting with the API you will be dealing with key objects.
# Configuring the Object API
The following methods should be used before calling run. They allow you to
configure the persistence space of MCT.
* `MCT.objects.addRoot(key)` -- add a "ROOT" to Open MCT by specifying it's
key.
* `MCT.objects.removeRoot(key)` -- Remove a "ROOT" from Open MCT by key.
* `MCT.objects.addProvider(namespace, provider)` -- register an object provider
for a specific namespace. See below for documentation on the provider
interface.
# Using the object API
The object API provides methods for getting, saving, and deleting objects.
* MCT.objects.get(key) -> returns promise for an object
* MCT.objects.save(object) -> returns promise that is resolved when object
has been saved
* MCT.objects.delete(object) -> returns promise that is resolved when object has
been deleted
## Configuration Example: Adding a groot
The following example adds a new root object for groot and populates it with
some pieces of groot.
```javascript
var ROOT_KEY = {
namespace: 'groot',
identifier: 'groot'
};
var GROOT_ROOT = {
name: 'I am groot',
type: 'folder',
composition: [
{
namespace: 'groot',
identifier: 'arms'
},
{
namespace: 'groot',
identifier: 'legs'
},
{
namespace: 'groot',
identifier: 'torso'
}
]
};
var GrootProvider = {
get: function (key) {
if (key.identifier === 'groot') {
return Promise.resolve(GROOT_ROOT);
}
return Promise.resolve({
name: 'Groot\'s ' + key.identifier
});
}
};
MCT.objects.addRoot(ROOT_KEY);
MCT.objects.addProvider('groot', GrootProvider);
MCT.run();
```
### Making a custom provider:
All methods on the provider interface are optional, so you do not need
to modify them.
* `provider.get(key)` -> promise for a domain object.
* `provider.save(domainObject)` -> returns promise that is fulfilled when object
has been saved.
* `provider.delete(domainObject)` -> returns promise that is fulfilled when
object has been deleted.

50
api/object-api/bundle.js Normal file
View File

@@ -0,0 +1,50 @@
/*****************************************************************************
* 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([
'./ObjectAPI',
'legacyRegistry'
], function (
ObjectAPI,
legacyRegistry
) {
legacyRegistry.register('api/object-api', {
name: 'Object API',
description: 'The public Objects API',
extensions: {
components: [
{
provides: "objectService",
type: "decorator",
priority: "mandatory",
implementation: ObjectAPI,
depends: [
"roots[]",
"instantiate"
]
}
]
}
});
});

64
api/region-api/README.md Normal file
View File

@@ -0,0 +1,64 @@
# Region API - Overview
The region API provides a method for specifying which views should display in a given region for a given domain object. As such, they also define the basic view interface that components must define.
### MCT.region.Region
The base region type, all regions implement this interface.
`register(view)`
`getViews(domainObject)`
Additionally, Regions may have subregions for different modes of the application. Specifying a view for a region
### MCT.region.View
The basic type for views. You can extend this to implement your own functionality, or you can create your own object so long as it meets the interface.
`attribute` | `type` | `note`
--- | --- | ---
`label` | `string` or `Function` | The name of the view. Used in the view selector when more than one view exists for an object.
`glyph` | `string` or `Function` | The glyph to associate with this view. Used in the view selector when more than one view exists for an object.
`instantiate` | `Function` | constructor for a view. Will be invoked with two arguments, `container` and `domainObject`. It should return an object with a `destroy` method that is called when the view is removed.
`appliesTo` | `Function` | Determines if a view applies to a specific domain object. Will be invoked with a domainObject. Should return a number, `priority` if the view applies to a given object. If multiple views return a truthy value for a given object, they will be ordered by priority, and the largest priority value will be the default view for the object. Return `false` if a view should not apply to an object.
Basic Hello World:
```javascript
function HelloWorldView(container, domainObject) {
container.innerHTML = 'Hello World!';
}
HelloWorldView.label = 'Hello World';
HelloWorldView.glyph = 'whatever';
HelloWorldView.appliesTo = function (domainObject) {
return 10;
};
HelloWorldView.prototype.destroy = function () {
// clean up outstanding handlers;
};
MCT.regions.Main.register(HelloWorldView);
```
## Region Hierarchy
Regions are organized in a hierarchy, with the most specific region taking precedence over less specific regions.
If you specify a view for the Main Region, it will be used for both Edit and View modes. You can override the Main Region view for a specific mode by registering the view with that specific mode.
### MCT.regions.Tree
### MCT.regions.Main
### MCT.regions.Main.View
### MCT.regions.Main.Edit
### MCT.regions.Inspector
### MCT.regions.Inspector.View
### MCT.regions.Inspector.Edit
### MCT.regions.Toolbar
### MCT.regions.Toolbar.View
### MCT.regions.Toolbar.Edit

View File

@@ -0,0 +1,11 @@
define([
], function () {
function RegionAPI() {
window.MCT = window.MCT || {};
window.MCT.regions = {};
}
return RegionAPI;
})

45
api/region-api/bundle.js Normal file
View File

@@ -0,0 +1,45 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
define([
'./RegionAPI',
'legacyRegistry'
], function (
RegionAPI,
legacyRegistry
) {
legacyRegistry.register('api/region-api', {
name: 'Region API',
description: 'The public Region API',
extensions: {
runs: [
{
key: "RegionAPI",
implementation: RegionAPI,
depends: [
]
}
]
}
});
});

View File

@@ -0,0 +1,71 @@
# Telemetry API - Overview
The Telemetry API provides basic methods for retrieving historical and realtime telemetry data, retrieving telemetry metadata, and registering additional telemetry providers.
The Telemetry API also provides a set of helpers built upon these basics-- TelemetryFormatters help you format telemetry values for display purposes, LimitEvaluators help you display evaluate and display alarm states, while TelemetryCollections provide a method for seamlessly combining historical and realtime data, while supporting more advanced client side filtering and interactivity.
## Getting Telemetry Data
### `MCT.telemetry.request(domainObject, options)`
Request historical telemetry for a domain object. Options allows you to specify filters (start, end, etc.), sort order, and strategies for retrieving telemetry (aggregation, latest available, etc.).
Returns a `Promise` for an array of telemetry values.
### `MCT.telemetry.subscribe(domainObject, callback, options)`
Subscribe to realtime telemetry for a specific domain object. callback will be called whenever data is received from a realtime provider. Options allows you to specify ???
## Understanding Telemetry
### `MCT.telemetry.getMetadata(domainObject)`
Retrieve telemetry metadata for a domain object. Telemetry metadata helps you understand the sort of telemetry data a domain object can provide-- for instances, the possible enumerations or states, the units, and more.
### `MCT.telemetry.Formatter`
Telemetry formatters help you format telemetry values for display. Under the covers, they use telemetry metadata to interpret your telemetry data, and then they use the format API to format that data for display.
### `MCT.telemetry.LimitEvaluator`
Limit Evaluators help you evaluate limit and alarm status of individual telemetry datums for display purposes without having to interact directly with the Limit API.
## Adding new telemetry sources
### `MCT.telemetry.registerProvider(telemetryProvider)`
Register a telemetry provider with the telemetry service. This allows you to connect alternative telemetry sources to For more information, see the `MCT.telemetry.BaseProvider`
### `MCT.telemetry.BaseProvider`
The base provider is a great starting point for developers who would like to implement their own telemetry provider. At the same time, you can implement your own telemetry provider as long as it meets the TelemetryProvider (see other docs).
## Other tools
### `MCT.telemetry.TelemetryCollection`
The TelemetryCollection is a useful tool for building advanced displays. It helps you seamlessly handle both historical and realtime telemetry data, while making it easier to deal with large data sets and interactive displays that need to frequently requery data.
# API Reference (TODO)
* Telemetry Metadata
* Request Options
-- start
-- end
-- sort
-- ???
-- strategies -- specify which strategies you want. an array provides for fallback strategies without needing decoration. Design fallbacks into API.
### `MCT.telemetry.request(domainObject, options)`
### `MCT.telemetry.subscribe(domainObject, callback, options)`
### `MCT.telemetry.getMetadata(domainObject)`
### `MCT.telemetry.Formatter`
### `MCT.telemetry.LimitEvaluator`
### `MCT.telemetry.registerProvider(telemetryProvider)`
### `MCT.telemetry.BaseProvider`
### `MCT.telemetry.TelemetryCollection`

View File

@@ -0,0 +1,239 @@
/*global define,window,console,MCT*/
/**
var key = '114ced6c-deb7-4169-ae71-68c571665514';
MCT.objects.getObject([key])
.then(function (results) {
console.log('got results');
return results[key];
})
.then(function (domainObject) {
console.log('got object');
MCT.telemetry.subscribe(domainObject, function (datum) {
console.log('gotData!', datum);
});
});
});
*/
define([
'lodash',
'eventemitter2'
], function (
_,
EventEmitter
) {
// format map is a placeholder until we figure out format service.
var FORMAT_MAP = {
generic: function (range) {
return function (datum) {
return datum[range.key];
};
},
enum: function (range) {
var enumMap = _.indexBy(range.enumerations, 'value');
return function (datum) {
try {
return enumMap[datum[range.valueKey]].text;
} catch (e) {
return datum[range.valueKey];
}
};
}
};
FORMAT_MAP.number =
FORMAT_MAP.float =
FORMAT_MAP.integer =
FORMAT_MAP.ascii =
FORMAT_MAP.generic;
function TelemetryAPI(
formatService
) {
var FORMATTER_CACHE = new WeakMap(),
EVALUATOR_CACHE = new WeakMap();
function testAPI() {
var key = '114ced6c-deb7-4169-ae71-68c571665514';
window.MCT.objects.getObjects([key])
.then(function (results) {
console.log('got results');
return results[key];
})
.then(function (domainObject) {
var formatter = new MCT.telemetry.Formatter(domainObject);
console.log('got object');
window.MCT.telemetry.subscribe(domainObject, function (datum) {
var formattedValues = {};
Object.keys(datum).forEach(function (key) {
formattedValues[key] = formatter.format(datum, key);
});
console.log(
'datum:',
datum,
'formatted:',
formattedValues
);
});
});
}
function getFormatter(range) {
if (FORMAT_MAP[range.type]) {
return FORMAT_MAP[range.type](range);
}
try {
var format = formatService.getFormat(range.type).format.bind(
formatService.getFormat(range.type)
),
formatter = function (datum) {
return format(datum[range.key]);
};
return formatter;
} catch (e) {
console.log('could not retrieve format', range, e, e.message);
return FORMAT_MAP.generic(range);
}
}
function TelemetryFormatter(domainObject) {
this.metadata = domainObject.getCapability('telemetry').getMetadata();
this.formats = {};
var ranges = this.metadata.ranges.concat(this.metadata.domains);
ranges.forEach(function (range) {
this.formats[range.key] = getFormatter(range);
}, this);
}
/**
* Retrieve the 'key' from the datum and format it accordingly to
* telemetry metadata in domain object.
*/
TelemetryFormatter.prototype.format = function (datum, key) {
return this.formats[key](datum);
};
function LimitEvaluator(domainObject) {
this.domainObject = domainObject;
this.evaluator = domainObject.getCapability('limit');
if (!this.evaluator) {
this.evalute = function () {
return '';
}
}
}
/** TODO: Do we need a telemetry parser, or do we assume telemetry
is numeric by default? */
LimitEvaluator.prototype.evaluate = function (datum, key) {
return this.evaluator.evaluate(datum, key);
};
/** Basic telemetry collection, needs more magic. **/
function TelemetryCollection(domainObject) {
this.domainObject = domainObject;
this.data = [];
}
_.extend(TelemetryCollection.prototype, EventEmitter.prototype);
TelemetryCollection.prototype.request = function (options) {
request(this.domainObject, options).then(function (data) {
data.forEach(function (datum) {
this.addDatum(datum);
}, this);
}.bind(this));
};
TelemetryCollection.prototype.addDatum = function (datum) {
this.data.push(datum);
this.emit('add', datum);
};
TelemetryCollection.prototype.subscribe = function (options) {
if (this.unsubscribe) {
this.unsubscribe();
delete this.unsubscribe;
}
this.unsubscribe = subscribe(
this.domainObject,
function (telemetrySeries) {
telemetrySeries.getData().forEach(this.addDatum, this);
}.bind(this),
options
);
};
function registerProvider(provider) {
// Not yet implemented.
console.log('registering provider', provider);
}
function registerEvaluator(evaluator) {
// not yet implemented.
console.log('registering evaluator', evaluator);
}
function request(domainObject, options) {
return domainObject.getCapability('telemetry')
.requestData(options)
.then(function (telemetrySeries) {
return telemetrySeries.getData();
});
}
function subscribe(domainObject, callback, options) {
return domainObject.getCapability('telemetry')
.subscribe(function (series) {
series.getData().forEach(callback);
}, options);
}
var Telemetry = {
registerProvider: registerProvider,
registerEvaluator: registerEvaluator,
request: request,
subscribe: subscribe,
getMetadata: function (domainObject) {
return domainObject.getCapability('telemetry').getMetadata();
},
Formatter: function (domainObject) {
if (!FORMATTER_CACHE.has(domainObject)) {
FORMATTER_CACHE.set(
domainObject,
new TelemetryFormatter(domainObject)
);
}
return FORMATTER_CACHE.get(domainObject);
},
LimitEvaluator: function (domainObject) {
if (!EVALUATOR_CACHE.has(domainObject)) {
EVALUATOR_CACHE.set(
domainObject,
new LimitEvaluator(domainObject)
);
}
return EVALUATOR_CACHE.get(domainObject);
}
};
window.MCT = window.MCT || {};
window.MCT.telemetry = Telemetry;
window.testAPI = testAPI;
return Telemetry;
}
return TelemetryAPI;
});

View File

@@ -0,0 +1,46 @@
/*****************************************************************************
* 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([
'./TelemetryAPI',
'legacyRegistry'
], function (
TelemetryAPI,
legacyRegistry
) {
legacyRegistry.register('api/telemetry-api', {
name: 'Telemetry API',
description: 'The public Telemetry API',
extensions: {
runs: [
{
key: "TelemetryAPI",
implementation: TelemetryAPI,
depends: [
'formatService'
]
}
]
}
});
});

31
api/type-api/README.md Normal file
View File

@@ -0,0 +1,31 @@
# Type API - Overview
The Type API allows you to register type information for domain objects, and allows you to retrieve type information about a given domain object. Crucially, type information allows you to add new creatible object types.
### MCT.types.Type
The basic interface for a type. You can extend this to implement your own type,
or you can provide an object that implements the same interface.
`attribute` | `type` | `note`
--- | --- | ---
`label` | `String` | The human readible name of the type.
`key` | `String` | The unique identifier for this type.
`glyph` | `String` | The glyph identifier for the type. Displayed in trees, labels, and other locations.
`description` | `String` | A basic description of the type visible in the create menu.
`isCreatible` | `Boolean`, `Number`, or `Function` | If truthy, this type will be visible in the create menu. Note that objects not in the create menu can be instantiated via other means.
`namespace` | `String` | The object namespace that provides instances of this type. This allows you to implement custom object providers for specific types while still utilizing other namespaces for persistence.
`properties` | `Object` | Object defining properties of an instance of this class. Properties are used for automatic form generation and automated metadata display. For more information on the definition of this object, look at (some resource-- jsonschema?)
`canContain` | `Function` | determins whether objects of this type can contain other objects. Will be invoked with a domain object. Return true to allow composition, return false to disallow composition.
### MCT.types.register(type)
Register a type with the type API. Registering a type with the same key as another type will replace the original type definition.
### MCT.types.getType(typeKey)
Returns the type definition for a given typeKey. returns undefined if type does not exist.
### MCT.types.getType(domainObject)
Return the type definition for a given domain object.

10
api/type-api/TypeAPI.js Normal file
View File

@@ -0,0 +1,10 @@
define([
], function () {
function TypeAPI() {
window.MCT = window.MCT || {};
window.MCT.types = {};
}
return TypeAPI;
});

47
api/type-api/bundle.js Normal file
View File

@@ -0,0 +1,47 @@
/*****************************************************************************
* 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([
'./TypeAPI',
'legacyRegistry'
], function (
TypeAPI,
legacyRegistry
) {
legacyRegistry.register('api/type-api', {
name: 'Type API',
description: 'The public Type API',
extensions: {
runs: [
{
key: "TypeAPI",
implementation: TypeAPI,
depends: [
'typeService'
]
}
]
}
});
});

11
app.js
View File

@@ -14,7 +14,8 @@
options = require('minimist')(process.argv.slice(2)),
express = require('express'),
app = express(),
fs = require('fs');
fs = require('fs'),
request = require('request');
// Defaults
options.port = options.port || options.p || 8080;
@@ -61,6 +62,14 @@
res.send(JSON.stringify(bundles));
});
app.use('/proxyUrl', function proxyRequest(req, res, next) {
console.log('Proxying request to: ', req.query.url);
req.pipe(request({
url: req.query.url,
strictSSL: false
}).on('error', next)).pipe(res);
});
// Expose everything else as static files
app.use(express['static']('.'));

View File

@@ -15,6 +15,11 @@
"text": "requirejs-text#^2.0.14",
"es6-promise": "^3.0.2",
"screenfull": "^3.0.0",
"node-uuid": "^1.4.7"
"node-uuid": "^1.4.7",
"comma-separated-values": "^3.6.4",
"FileSaver.js": "^0.0.2",
"zepto": "^1.1.6",
"eventemitter2": "^1.0.0",
"lodash": "3.10.1"
}
}

View File

@@ -13,3 +13,6 @@ deployment:
branch: mobile
heroku:
appname: openmctweb-staging-deux
test:
post:
- npm run jshint --silent

View File

@@ -6,12 +6,13 @@ Victor Woeltjen
September 23, 2015
Document Version 1.1
Date | Version | Summary of Changes | Author
------------------- | --------- | ----------------------- | ---------------
April 29, 2015 | 0 | Initial Draft | Victor Woeltjen
May 12, 2015 | 0.1 | | Victor Woeltjen
June 4, 2015 | 1.0 | Name Changes | Victor Woeltjen
October 4, 2015 | 1.1 | Conversion to MarkDown | Andrew Henry
Date | Version | Summary of Changes | Author
------------------- | --------- | ------------------------- | ---------------
April 29, 2015 | 0 | Initial Draft | Victor Woeltjen
May 12, 2015 | 0.1 | | Victor Woeltjen
June 4, 2015 | 1.0 | Name Changes | Victor Woeltjen
October 4, 2015 | 1.1 | Conversion to MarkDown | Andrew Henry
April 5, 2016 | 1.2 | Added Mct-table directive | Andrew Henry
# Introduction
The purpose of this guide is to familiarize software developers with the Open
@@ -910,7 +911,24 @@ A capability's implementation may also expose a static method `appliesTo(model)`
which should return a boolean value, and will be used by the platform to filter
down capabilities to those which should be exposed by specific domain objects,
based on their domain object models.
## Containers Category
Containers provide options for the `mct-container` directive.
The definition for an extension in the `containers` category should include:
* `key`: An identifier for the container.
* `template`: An Angular template for the container, including an
`ng-transclude` where contained content should go.
* `attributes`: An array of attribute names. The values associated with
these attributes will be exposed in the template's scope under the
name provided by the `alias` property.
* `alias`: The property name in scope under which attributes will be
exposed. Optional; defaults to "container".
Note that `templateUrl` is not supported for `containers`.
## Controls Category
Controls provide options for the `mct-control` directive.
@@ -1583,6 +1601,61 @@ there are items .
]
}
## Table
The `mct-table` directive provides a generic table component, with optional
sorting and filtering capabilities. The table can be pre-populated with data
by setting the `rows` parameter, and it can be updated in real-time using the
`add:row` and `remove:row` broadcast events. The table will expand to occupy
100% of the size of its containing element. The table is highly optimized for
very large data sets.
### Events
The table supports two events for notifying that the rows have changed. For
performance reasons, the table does not monitor the content of `rows`
constantly.
* `add:row`: A `$broadcast` event that will notify the table that a new row
has been added to the table.
eg. The code below adds a new row, and alerts the table using the `add:row`
event. Sorting and filtering will be applied automatically by the table component.
```
$scope.rows.push(newRow);
$scope.$broadcast('add:row', $scope.rows.length-1);
```
* `remove:row`: A `$broadcast` event that will notify the table that a row
should be removed from the table.
eg. The code below removes a row from the rows array, and then alerts the table
to its removal.
```
$scope.rows.slice(5, 1);
$scope.$broadcast('remove:row', 5);
```
### Parameters
* `headers`: An array of string values which will constitute the column titles
that appear at the top of the table. Corresponding values are specified in
the rows using the header title provided here.
* `rows`: An array of objects containing row values. Each element in the
array must be an associative array, where the key corresponds to a column header.
* `enableFilter`: A boolean that if true, will enable searching and result
filtering. When enabled, each column will have a text input field that can be
used to filter the table rows in real time.
* `enableSort`: A boolean determining whether rows can be sorted. If true,
sorting will be enabled allowing sorting by clicking on column headers. Only
one column may be sorted at a time.
* `autoScroll`: A boolean value that if true, will cause the table to automatically
scroll to the bottom as new data arrives. Auto-scroll can be disengaged manually
by scrolling away from the bottom of the table, and can also be enabled manually
by scrolling to the bottom of the table rows.
# Services
The Open MCT Web platform provides a variety of services which can be retrieved

View File

@@ -151,11 +151,9 @@ emphasis on testing.
ensuring software passes that testing in order to ship on time;
may prefer to disable malfunctioning components and fix them
in a subsequent sprint, for example.
* __Ship.__ Tag a code snapshot that has passed acceptance
testing and deploy that version. (Only true if acceptance
testing has passed by this point; if acceptance testing has not
* [__Ship.__](version.md) Tag a code snapshot that has passed release/sprint
testing and deploy that version. (Only true if relevant
testing has passed by this point; if testing has not
been passed, will need to make ad hoc decisions with stakeholders,
e.g. "extend the sprint" or "defer shipment until end of next
sprint.")

View File

@@ -3,8 +3,10 @@
The process used to develop Open MCT Web is described in the following
documents:
* [Development Cycle](cycle.md): Describes how and when specific
* The [Development Cycle](cycle.md) describes how and when specific
process points are repeated during development.
* The [Version Guide](version.md) describes version numbering for
Open MCT (both semantics and process.)
* Testing is described in two documents:
* The [Test Plan](testing/plan.md) summarizes the approaches used
to test Open MCT Web.

142
docs/src/process/version.md Normal file
View File

@@ -0,0 +1,142 @@
# Version Guide
This document describes semantics and processes for providing version
numbers for Open MCT, and additionally provides guidelines for dependent
projects developed by the same team.
Versions are incremented at specific points in Open MCT's
[Development Cycle](cycle.md); see that document for a description of
sprints and releases.
## Audience
Individuals interested in consuming version numbers can be categorized as
follows:
* _Users_: Generally disinterested, occasionally wish to identify version
to cross-reference against documentation, or to report issues.
* _Testers_: Want to identify which version of the software they are
testing, e.g. to file issues for defects.
* _Internal developers_: Often, inverse of testers; want to identify which
version of software was/is in use when certain behavior is observed. Want
to be able to correlate versions in use with “streams” of development
(e.g. dev vs. prod), when possible.
* _External developers_: Need to understand which version of software is
in use when developing/maintaining plug-ins, in order to ensure
compatibility of their software.
## Version Reporting
Software versions should be reflected in the user interface of the
application in three ways:
* _Version number_: A semantic version (see below) which serves both to
uniquely identify releases, as well as to inform plug-in developers
about compatibility with previous releases.
* _Revision identifier_: While using git, the commit hash. Supports
internal developers and testers by uniquely identifying client
software snapshots.
* _Branding_: Identifies which variant is in use. (Typically, Open MCT
is re-branded when deployed for a specific mission or center.)
## Version Numbering
Open MCT shall provide version numbers consistent with
[Semantic Versioning 2.0.0](http://semver.org/). In summary, versions
are expressed in a "major.minor.patch" form, and incremented based on
nature of changes to external API. Breaking changes require a "major"
version increment; backwards-compatible changes require a "minor"
version increment; neutral changes (such as bug fixes) require a "patch"
version increment. A hyphen-separated suffix indicates a pre-release
version, which may be unstable or may not fully meet compatibility
requirements.
Additionally, the following project-specific standards will be used:
* During development, a "-SNAPSHOT" suffix shall be appended to the
version number. The version number before the suffix shall reflect
the next expected version number for release.
* Prior to a 1.0.0 release, the _minor_ version will be incremented
on a per-release basis; the _patch_ version will be incremented on a
per-sprint basis.
* Starting at version 1.0.0, version numbers will be updated with each
completed sprint. The version number for the sprint shall be
determined relative to the previous released version; the decision
to increment the _major_, _minor_, or _patch_ version should be
made based on the nature of changes during that release. (It is
recommended that these numbers are incremented as changes are
introduced, such that at end of release the version number may
be chosen by simply removing the suffix.)
* The first three sprints in a release may be unstable; in these cases, a
unique version identifier should still be generated, but a suffix
should be included to indicate that the version is not necessarily
production-ready. Recommended suffixes are:
Sprint | Suffix
:------:|:--------:
1 | `-alpha`
2 | `-beta`
3 | `-rc`
### Scope of External API
"External API" refers to the API exposed to, documented for, and used by
plug-in developers. Changes to interfaces used internally by Open MCT
(or otherwise not documented for use externally) require only a _patch_
version bump.
## Incrementing Versions
At the end of a sprint, the [project manager](cycle.md#roles)
should update (or delegate the task of updating) Open MCT version
numbers by the following process:
1. Update version number in `package.json`
1. Remove `-SNAPSHOT` suffix.
2. Verify that resulting version number meets semantic versioning
requirements relative to previous stable version. Increment if
necessary.
3. If version is considered unstable (which may be the case during
the first three sprints of a release), apply a new suffix per
[Version Numbering](#version-numbering) guidance above.
2. Tag the release.
1. Commit changes to `package.json` on the `master` branch.
The commit message should reference the sprint being closed,
preferably by a URL reference to the associated Milestone in
GitHub.
2. Verify that build still completes, that application passes
smoke-testing, and that only differences from tested versions
are the changes to version number above.
3. Push the `master` branch.
4. Tag this commit with the version number, prepending the letter "v".
(e.g. `git tag v0.9.3-alpha`)
5. Push the tag to GitHub. (e.g. `git push origin v0.9.3-alpha`).
3. Upload a release archive.
1. Run `npm pack` to generate the archive.
2. Use the [GitHub release interface](https://github.com/nasa/openmct/releases)
to draft a new release.
3. Choose the existing tag for the new version (created and pushed above.)
Enter the tag name as the release name as well; see existing releases
for examples.
4. Attach the release archive.
5. Designate the release as a "pre-release" as appropriate (for instance,
when the version number has been suffixed as unstable, or when
the version number is below 1.0.0.)
4. Restore snapshot status in `package.json`
1. Remove any suffix from the version number, or increment the
_patch_ version if there is no suffix.
2. Append a `-SNAPSHOT` suffix.
3. Commit changes to `package.json` on the `master` branch.
The commit message should reference the sprint being opened,
preferably by a URL reference to the associated Milestone in
GitHub.
4. Verify that build still completes, that application passes
smoke-testing.
5. Push the `master` branch.
Projects dependent on Open MCT being co-developed by the Open MCT
team should follow a similar process, except that they should
additionally update their dependency on Open MCT to point to the
latest archive when removing their `-SNAPSHOT` status, and
that they should be pointed back to the `master` branch after
this has completed.

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

@@ -0,0 +1,89 @@
/*****************************************************************************
* 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 example of using the `exportService`; queries for telemetry
* and provides the results as a CSV file.
* @param {platform/exporters.ExportService} exportService the
* service which will handle the CSV export
* @param {ActionContext} context the action's context
* @constructor
* @memberof example/export
* @implements {Action}
*/
function ExportTelemetryAsCSVAction(exportService, context) {
this.exportService = exportService;
this.context = context;
}
ExportTelemetryAsCSVAction.prototype.perform = function () {
var context = this.context,
domainObject = context.domainObject,
telemetry = domainObject.getCapability("telemetry"),
metadata = telemetry.getMetadata(),
domains = metadata.domains,
ranges = metadata.ranges,
exportService = this.exportService;
function getName(domainOrRange) {
return domainOrRange.name;
}
telemetry.requestData({}).then(function (series) {
var headers = domains.map(getName).concat(ranges.map(getName)),
rows = [],
row,
i;
function copyDomainsToRow(row, index) {
domains.forEach(function (domain) {
row[domain.name] = series.getDomainValue(index, domain.key);
});
}
function copyRangesToRow(row, index) {
ranges.forEach(function (range) {
row[range.name] = series.getRangeValue(index, range.key);
});
}
for (i = 0; i < series.getPointCount(); i += 1) {
row = {};
copyDomainsToRow(row, i);
copyRangesToRow(row, i);
rows.push(row);
}
exportService.exportCSV(rows, { headers: headers });
});
};
ExportTelemetryAsCSVAction.appliesTo = function (context) {
return context.domainObject &&
context.domainObject.hasCapability("telemetry");
};
return ExportTelemetryAsCSVAction;
});

45
example/export/bundle.js Normal file
View File

@@ -0,0 +1,45 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
define([
'legacyRegistry',
'./ExportTelemetryAsCSVAction'
], function (legacyRegistry, ExportTelemetryAsCSVAction) {
"use strict";
legacyRegistry.register("example/export", {
"name": "Example of using CSV Export",
"extensions": {
"actions": [
{
"key": "example.export",
"name": "Export Telemetry as CSV",
"implementation": ExportTelemetryAsCSVAction,
"category": "contextual",
"glyph": "\u0033",
"depends": [ "exportService" ]
}
]
}
});
});

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": {
@@ -99,26 +100,46 @@ define([
"domains": [
{
"key": "time",
"name": "Time"
"name": "Time",
"type": "utc"
},
{
"key": "yesterday",
"name": "Yesterday"
"name": "Yesterday",
"type": "utc"
},
{
"key": "delta",
"name": "Delta",
"format": "example.delta"
"type": "example.delta"
}
],
"ranges": [
{
"key": "sin",
"name": "Sine"
"name": "Sine",
"type": "generic"
},
{
"key": "cos",
"name": "Cosine"
"name": "Cosine",
"type": "generic"
},
{
"key": "positive",
"name": "Positive Sine?",
"type": "enum",
"valueKey": "positive",
"enumerations": [
{
"value": 0,
"text": "FALSE"
},
{
"value": 1,
"text": "TRUE"
}
]
}
]
},
@@ -126,7 +147,7 @@ define([
{
"name": "Period",
"control": "textfield",
"cssclass": "l-small l-numeric",
"cssclass": "l-input-sm l-numeric",
"key": "period",
"required": true,
"property": [

View File

@@ -62,6 +62,9 @@ define(
},
evaluate: function (datum, range) {
range = range || 'sin';
if (['sin', 'cos'].indexOf(range) === -1) {
return '';
}
if (datum[range] > RED) {
return LIMITS.rh;
}
@@ -84,4 +87,4 @@ define(
return SinewaveLimitCapability;
}
);
);

View File

@@ -19,10 +19,11 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,Promise*/
/*global define,setInterval,clearInterval*/
/**
* Module defining SinewaveTelemetryProvider. Created by vwoeltje on 11/12/14.
* Rewritten by larkin on 05/06/2016.
*/
define(
["./SinewaveTelemetrySeries"],
@@ -34,82 +35,109 @@ define(
* @constructor
*/
function SinewaveTelemetryProvider($q, $timeout) {
var subscriptions = [];
//
function matchesSource(request) {
return request.source === "generator";
}
// Used internally; this will be repacked by doPackage
function generateData(request) {
return {
key: request.key,
telemetry: new SinewaveTelemetrySeries(request)
};
}
//
function doPackage(results) {
var packaged = {};
results.forEach(function (result) {
packaged[result.key] = result.telemetry;
});
// Format as expected (sources -> keys -> telemetry)
return { generator: packaged };
}
function requestTelemetry(requests) {
return $timeout(function () {
return doPackage(requests.filter(matchesSource).map(generateData));
}, 0);
}
function handleSubscriptions() {
subscriptions.forEach(function (subscription) {
var requests = subscription.requests;
subscription.callback(doPackage(
requests.filter(matchesSource).map(generateData)
));
});
}
function startGenerating() {
$timeout(function () {
handleSubscriptions();
if (subscriptions.length > 0) {
startGenerating();
}
}, 1000);
}
function subscribe(callback, requests) {
var subscription = {
callback: callback,
requests: requests
};
function unsubscribe() {
subscriptions = subscriptions.filter(function (s) {
return s !== subscription;
});
}
subscriptions.push(subscription);
if (subscriptions.length === 1) {
startGenerating();
}
return unsubscribe;
}
return {
requestTelemetry: requestTelemetry,
subscribe: subscribe
};
this.$q = $q;
this.$timeout = $timeout;
}
SinewaveTelemetryProvider.prototype.canHandleRequest = function (request) {
return request.source === 'generator';
};
SinewaveTelemetryProvider.prototype.requestTelemetry = function (requests) {
var sinewaveRequests = requests.filter(this.canHandleRequest, this),
response = {
generator: {}
};
sinewaveRequests.forEach(function (request) {
response.generator[request.key] = this.singleRequest(request);
}, this);
return response;
};
SinewaveTelemetryProvider.prototype.subscribe = function (callback, requests) {
var sinewaveRequests = requests.filter(this.canHandleRequest, this),
unsubscribers = sinewaveRequests.map(function (request) {
return this.singleSubscribe(
function (series) {
var response = {
generator: {}
};
response.generator[request.key] = series;
callback(response);
},
request
);
}, this);
return function () {
unsubscribers.forEach(function (unsubscribe) {
unsubscribe();
});
};
};
SinewaveTelemetryProvider.prototype.singleRequest = function (request) {
var start = Math.floor(request.start / 1000) * 1000,
end = Math.floor(request.end / 1000) * 1000,
period = request.period || 30,
data = [],
current,
i;
for (current = start; current <= end; current += 2000) {
i = Math.floor((current - start) / 1000);
data.push({
sin: Math.sin(i * Math.PI * 2 / period),
cos: Math.cos(i * Math.PI * 2 / period),
positive: Math.sin(i * Math.PI * 2 / period) >= 0,
time: current,
yesterday: current - (60 * 60 * 24 * 1000),
delta: current
});
}
return new SinewaveTelemetrySeries(data);
};
SinewaveTelemetryProvider.prototype.singleSubscribe = function (callback, options) {
// calculate interval position based on start - end; such that this data will line up with data generated by singleRequest.
var start = Math.floor((options.start || Date.now()) / 1000) * 1000,
currentTime = Math.floor((options.end || Date.now()) / 1000) * 1000,
period = options.period || 30,
unsubscribe,
generatePoint,
interval;
generatePoint = function () {
var i = Math.floor((currentTime - start) / 1000),
point = {
sin: Math.sin(i * Math.PI * 2 / period),
cos: Math.cos(i * Math.PI * 2 / period),
positive: Math.sin(i * Math.PI * 2 / period) >= 0,
time: currentTime,
yesterday: currentTime - (60 * 60 * 24 * 1000),
delta: currentTime
};
currentTime += 1000;
return point;
};
interval = setInterval(function () {
var series = new SinewaveTelemetrySeries(generatePoint());
callback(series);
}, 1000);
unsubscribe = function () {
clearInterval(interval);
};
return unsubscribe;
};
return SinewaveTelemetryProvider;
}
);

View File

@@ -32,47 +32,37 @@ define(
var ONE_DAY = 60 * 60 * 24,
firstObservedTime = Math.floor(SinewaveConstants.START_TIME / 1000);
/**
*
* @constructor
*/
function SinewaveTelemetrySeries(request) {
var timeOffset = (request.domain === 'yesterday') ? ONE_DAY : 0,
latestTime = Math.floor(Date.now() / 1000) - timeOffset,
firstTime = firstObservedTime - timeOffset,
endTime = (request.end !== undefined) ?
Math.floor(request.end / 1000) : latestTime,
count = Math.min(endTime, latestTime) - firstTime,
period = +request.period || 30,
generatorData = {},
requestStart = (request.start === undefined) ? firstTime :
Math.max(Math.floor(request.start / 1000), firstTime),
offset = requestStart - firstTime;
if (request.size !== undefined) {
offset = Math.max(offset, count - request.size);
function SinewaveTelemetrySeries(data) {
if (!Array.isArray(data)) {
data = [data];
}
generatorData.getPointCount = function () {
return count - offset;
};
generatorData.getDomainValue = function (i, domain) {
// delta uses the same numeric values as the default domain,
// so it's not checked for here, just formatted for display
// differently.
return (i + offset) * 1000 + firstTime * 1000 -
(domain === 'yesterday' ? (ONE_DAY * 1000) : 0);
};
generatorData.getRangeValue = function (i, range) {
range = range || "sin";
return Math[range]((i + offset) * Math.PI * 2 / period);
};
return generatorData;
this.data = data;
}
SinewaveTelemetrySeries.prototype.getPointCount = function () {
return this.data.length;
};
SinewaveTelemetrySeries.prototype.getDomainValue = function (i, domain) {
return this.getDatum(i)[domain];
};
SinewaveTelemetrySeries.prototype.getRangeValue = function (i, range) {
return this.getDatum(i)[range];
};
SinewaveTelemetrySeries.prototype.getDatum = function (i) {
if (i >= this.data.length || i < 0) {
throw new Error('IndexOutOfRange: index not available in series.');
}
return this.data[i];
};
SinewaveTelemetrySeries.prototype.getData = function () {
return this.data;
};
return SinewaveTelemetrySeries;
}
);

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": {}
},
@@ -60,7 +62,7 @@ define([
{
"name": "Time",
"key": "time",
"format": "timestamp"
"format": "utc"
}
],
"ranges": [

View File

@@ -1,26 +0,0 @@
# Require any additional compass plugins here.
# require "compass-growl"
# Set this to the root of your project when deployed:
http_path = "/"
css_dir = "css"
sass_dir = "sass"
images_dir = "images"
javascripts_dir = "js"
# You can select your preferred output style here (can be overridden via the command line):
# :expanded, :compressed, :nested
output_style = :nested
# To enable relative paths to assets via compass helper functions. Uncomment:
relative_assets = true
# To disable debugging comments that display the original location of your selectors. Uncomment:
# line_comments = false
# If you prefer the indented syntax, you might want to regenerate this
# project again passing --syntax sass, or you can uncomment this:
# preferred_syntax = :sass
# and then run:
# sass-convert -R --from scss --to sass vfn_platform/static/sass scss && rm -rf sass && mv scss sass

View File

@@ -1,103 +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.
*****************************************************************************/
/*****************************************************************************
* 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.
*****************************************************************************/
/************************** FEATURES */
/************************** VERY INFLUENTIAL GLOBAL DIMENSIONS */
/************************** RATIOS */
/************************** LAYOUT */
/************************** CONTROLS */
/************************** PATHS */
/************************** TIMINGS */
/************************** LIMITS */
/*****************************************************************************
* 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.
*****************************************************************************/
/************************** MOBILE REPRESENTATION ITEMS DIMENSIONS */
/************************** MOBILE TREE MENU DIMENSIONS */
/************************** WINDOW DIMENSIONS FOR RWD */
/************************** MEDIA QUERIES: WINDOW CHECKS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
/************************** MEDIA QUERIES: WINDOWS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
/************************** DEVICE PARAMETERS FOR MENUS/REPRESENTATIONS */
/*****************************************************************************
* 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.
*****************************************************************************/
/* REQUIRES mobile/_constants */
@media screen and (orientation: portrait) and (max-width: 514px) and (max-height: 740px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (max-height: 514px) and (max-width: 740px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (max-height: 514px) and (max-width: 740px) and (max-device-width: 1024px) and (max-device-height: 799px), screen and (orientation: portrait) and (min-width: 515px) and (max-width: 799px) and (min-height: 741px) and (max-height: 1024px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (min-height: 515px) and (max-height: 799px) and (min-width: 741px) and (max-width: 1024px) and (max-device-width: 799px) and (max-device-height: 1024px), screen and (orientation: landscape) and (min-height: 515px) and (max-height: 799px) and (min-width: 741px) and (max-width: 1024px) and (max-device-width: 1024px) and (max-device-height: 799px) {
/* line 28, ../sass/mobile-example.scss */
.create-btn-holder {
display: block !important; } }

20
example/msl/README.md Normal file
View File

@@ -0,0 +1,20 @@
To use this bundle, add the following paths to /main.js -
'./platform/features/conductor/bundle',
'./example/msl/bundle',
An example plugin that integrates with public data from the Curiosity rover.
The data shown used by this plugin is published by the Centro de
Astrobiología (CSIC-INTA) at http://cab.inta-csic.es/rems/
Fetching data from this source requires a cross-origin request which will
fail on most modern browsers due to restrictions on such requests. As such,
it is proxied through a local proxy defined in app.js. In order to use this
example you will need to run app.js locally.
This example shows integration with an historical telemetry source, as
opposed to a real-time data source that is streaming back current information
about the state of a system. This example is atypical of a historical data
source in that it fetches all data in one request. The server infrastructure
of an historical telemetry source should ideally allow queries bounded by
time and other data attributes.

118
example/msl/bundle.js Normal file
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([
"./src/RemsTelemetryServerAdapter",
"./src/RemsTelemetryInitializer",
"./src/RemsTelemetryModelProvider",
"./src/RemsTelemetryProvider",
'legacyRegistry',
"module"
], function (
RemsTelemetryServerAdapter,
RemsTelemetryInitializer,
RemsTelemetryModelProvider,
RemsTelemetryProvider,
legacyRegistry
) {
"use strict";
legacyRegistry.register("example/notifications", {
"name" : "Mars Science Laboratory Data Adapter",
"extensions" : {
"types": [
{
"name":"Mars Science Laboratory",
"key": "msl.curiosity",
"glyph": "o"
},
{
"name": "Instrument",
"key": "msl.instrument",
"glyph": "o",
"model": {"composition": []}
},
{
"name": "Measurement",
"key": "msl.measurement",
"glyph": "\u0054",
"model": {"telemetry": {}},
"telemetry": {
"source": "rems.source",
"domains": [
{
"name": "Time",
"key": "timestamp",
"format": "utc"
}
]
}
}
],
"constants": [
{
"key": "REMS_WS_URL",
"value": "/proxyUrl?url=http://cab.inta-csic.es/rems/wp-content/plugins/marsweather-widget/api.php"
}
],
"roots": [
{
"id": "msl:curiosity",
"priority" : "preferred",
"model": {
"type": "msl.curiosity",
"name": "Mars Science Laboratory",
"composition": []
}
}
],
"services": [
{
"key":"rems.adapter",
"implementation": RemsTelemetryServerAdapter,
"depends": ["$q", "$http", "$log", "REMS_WS_URL"]
}
],
"runs": [
{
"implementation": RemsTelemetryInitializer,
"depends": ["rems.adapter", "objectService"]
}
],
"components": [
{
"provides": "modelService",
"type": "provider",
"implementation": RemsTelemetryModelProvider,
"depends": ["rems.adapter"]
},
{
"provides": "telemetryService",
"type": "provider",
"implementation": RemsTelemetryProvider,
"depends": ["rems.adapter", "$q"]
}
]
}
});
});

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,79 @@
/*****************************************************************************
* 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(
[],
/**
* A data dictionary describes the telemetry available from a data
* source and its data types. The data dictionary will be parsed by a custom
* server provider for this data source (in this case
* {@link RemsTelemetryServerAdapter}).
*
* Typically a data dictionary would be made available alongside the
* telemetry data source itself.
*/
function () {
return {
"name": "Mars Science Laboratory",
"identifier": "msl",
"instruments": [
{
"name":"rems",
"identifier": "rems",
"measurements": [
{
"name": "Min. Air Temperature",
"identifier": "min_temp",
"units": "degrees",
"type": "float"
},
{
"name": "Max. Air Temperature",
"identifier": "max_temp",
"units": "degrees",
"type": "float"
},
{
"name": "Atmospheric Pressure",
"identifier": "pressure",
"units": "pascals",
"type": "float"
},
{
"name": "Min. Ground Temperature",
"identifier": "min_gts_temp",
"units": "degrees",
"type": "float"
},
{
"name": "Max. Ground Temperature",
"identifier": "max_gts_temp",
"units": "degrees",
"type": "float"
}
]
}
]
};
}
);

View File

@@ -0,0 +1,71 @@
/*****************************************************************************
* 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 TAXONOMY_ID = "msl:curiosity",
PREFIX = "msl_tlm:";
/**
* Function that is executed on application startup and populates
* the navigation tree with objects representing the MSL REMS
* telemetry points. The tree is populated based on the data
* dictionary on the provider.
*
* @param {RemsTelemetryServerAdapter} adapter The server adapter
* (necessary in order to retrieve data dictionary)
* @param objectService the ObjectService which allows for lookup of
* objects by ID
* @constructor
*/
function RemsTelemetryInitializer(adapter, objectService) {
function makeId(element) {
return PREFIX + element.identifier;
}
function initializeTaxonomy(dictionary) {
function getTaxonomyObject(domainObjects) {
return domainObjects[TAXONOMY_ID];
}
function populateModel (taxonomyObject) {
return taxonomyObject.useCapability(
"mutation",
function (model) {
model.name = dictionary.name;
model.composition = dictionary.instruments.map(makeId);
}
);
}
objectService.getObjects([TAXONOMY_ID])
.then(getTaxonomyObject)
.then(populateModel);
}
initializeTaxonomy(adapter.dictionary);
}
return RemsTelemetryInitializer;
}
);

View File

@@ -0,0 +1,87 @@
/*****************************************************************************
* 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 PREFIX = "msl_tlm:",
FORMAT_MAPPINGS = {
float: "number",
integer: "number",
string: "string"
};
function RemsTelemetryModelProvider(adapter){
function isRelevant(id) {
return id.indexOf(PREFIX) === 0;
}
function makeId(element){
return PREFIX + element.identifier;
}
function buildTaxonomy(dictionary){
var models = {};
function addMeasurement(measurement){
var format = FORMAT_MAPPINGS[measurement.type];
models[makeId(measurement)] = {
type: "msl.measurement",
name: measurement.name,
telemetry: {
key: measurement.identifier,
ranges: [{
key: "value",
name: measurement.units,
units: measurement.units,
format: format
}]
}
};
}
function addInstrument(subsystem) {
var measurements = (subsystem.measurements || []);
models[makeId(subsystem)] = {
type: "msl.instrument",
name: subsystem.name,
composition: measurements.map(makeId)
};
measurements.forEach(addMeasurement);
}
(dictionary.instruments || []).forEach(addInstrument);
return models;
}
return {
getModels: function (ids) {
return ids.some(isRelevant) ? buildTaxonomy(adapter.dictionary) : {};
}
};
}
return RemsTelemetryModelProvider;
}
);

View File

@@ -0,0 +1,83 @@
/*****************************************************************************
* 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 (
['./RemsTelemetrySeries'],
function (RemsTelemetrySeries) {
"use strict";
var SOURCE = "rems.source";
function RemsTelemetryProvider(adapter, $q) {
this.adapter = adapter;
this.$q = $q;
}
/**
* Retrieve telemetry from this telemetry source.
* @memberOf example/msl
* @param {Array<TelemetryRequest>} requests An array of all request
* objects (which needs to be filtered to only those relevant to this
* source)
* @returns {Promise} A {@link Promise} resolved with a {@link RemsTelemetrySeries}
* object that wraps the telemetry returned from the telemetry source.
*/
RemsTelemetryProvider.prototype.requestTelemetry = function (requests) {
var packaged = {},
relevantReqs,
adapter = this.adapter;
function matchesSource(request) {
return (request.source === SOURCE);
}
function addToPackage(history) {
packaged[SOURCE][history.id] =
new RemsTelemetrySeries(history.values);
}
function handleRequest(request) {
return adapter.history(request).then(addToPackage);
}
relevantReqs = requests.filter(matchesSource);
packaged[SOURCE] = {};
return this.$q.all(relevantReqs.map(handleRequest))
.then(function () {
return packaged;
});
};
/**
* This data source does not support real-time subscriptions
*/
RemsTelemetryProvider.prototype.subscribe = function (callback, requests) {
return function() {};
};
RemsTelemetryProvider.prototype.unsubscribe = function (callback, requests) {
return function() {};
};
return RemsTelemetryProvider;
}
);

View File

@@ -0,0 +1,84 @@
/*****************************************************************************
* 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";
/**
* @typedef {Object} RemsTelemetryValue
* @memberOf example/msl
* @property {number} date The date/time of the telemetry value. Constitutes the domain value of this value pair
* @property {number} value The value of this telemetry datum.
* A floating point value representing some observable quantity (eg.
* temperature, air pressure, etc.)
*/
/**
* A representation of a collection of telemetry data. The REMS
* telemetry data is time ordered, with the 'domain' value
* constituting the time stamp of each data value and the
* 'range' being the value itself.
*
* TelemetrySeries will typically wrap an array of telemetry data,
* and provide an interface for retrieving individual an telemetry
* value.
* @memberOf example/msl
* @param {Array<RemsTelemetryValue>} data An array of telemetry values
* @constructor
*/
function RemsTelemetrySeries(data) {
this.data = data;
}
/**
* @returns {number} A count of the number of data values available in
* this series
*/
RemsTelemetrySeries.prototype.getPointCount = function() {
return this.data.length;
};
/**
* The domain value at the given index. The Rems telemetry data is
* time ordered, so the domain value is the time stamp of each data
* value.
* @param index
* @returns {number} the time value in ms since 1 January 1970
*/
RemsTelemetrySeries.prototype.getDomainValue = function(index) {
return this.data[index].date;
};
/**
* The range value of the REMS data set is the value of the thing
* being measured, be it temperature, air pressure, etc.
* @param index The datum in the data series to return the range
* value of.
* @returns {number} A floating point number
*/
RemsTelemetrySeries.prototype.getRangeValue = function(index) {
return this.data[index].value;
};
return RemsTelemetrySeries;
}
);

View File

@@ -0,0 +1,142 @@
/*****************************************************************************
* 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*/
/*jslint es5: true */
define(
[
"./MSLDataDictionary",
"module"
],
function (MSLDataDictionary, module) {
"use strict";
var TERRESTRIAL_DATE = "terrestrial_date",
LOCAL_DATA = "../data/rems.json";
/**
* Fetches historical data from the REMS instrument on the Curiosity
* Rover.
* @memberOf example/msl
* @param $q
* @param $http
* @param REMS_WS_URL The location of the REMS telemetry data.
* @constructor
*/
function RemsTelemetryServerAdapter($q, $http, $log, REMS_WS_URL) {
this.localDataURI = module.uri.substring(0, module.uri.lastIndexOf('/') + 1) + LOCAL_DATA;
this.deferreds = {};
this.REMS_WS_URL = REMS_WS_URL;
this.$q = $q;
this.$http = $http;
this.$log = $log;
this.cache = undefined;
}
/**
* The data dictionary for this data source.
* @type {MSLDataDictionary}
*/
RemsTelemetryServerAdapter.prototype.dictionary = MSLDataDictionary;
/**
* Fetches historical data from source, and associates it with the
* given request ID.
* @private
*/
RemsTelemetryServerAdapter.prototype.requestHistory = function(request) {
var self = this,
id = request.key,
deferred = this.$q.defer();
function processResponse(response){
var data = [];
/*
* Currently all data is returned for entire history of the mission. Cache response to avoid unnecessary re-queries.
*/
self.cache = response;
/*
* History data is organised by Sol. Iterate over sols...
*/
response.data.soles.forEach(function(solData){
/*
* Check that valid data exists
*/
if (!isNaN(solData[id])) {
/*
* Append each data point to the array of values
* for this data point property (min. temp, etc).
*/
data.unshift({
date: Date.parse(solData[TERRESTRIAL_DATE]),
value: solData[id]
});
}
});
return data;
}
function fallbackToLocal() {
self.$log.warn("Loading REMS data failed, probably due to" +
" cross origin policy. Falling back to local data");
return self.$http.get(self.localDataURI);
}
//Filter results to match request parameters
function filterResults(results) {
return results.filter(function(result){
return result.date >= (request.start || Number.MIN_VALUE) &&
result.date <= (request.end || Number.MAX_VALUE);
});
}
function packageAndResolve(results){
deferred.resolve({id: id, values: results});
}
this.$q.when(this.cache || this.$http.get(this.REMS_WS_URL))
.catch(fallbackToLocal)
.then(processResponse)
.then(filterResults)
.then(packageAndResolve);
return deferred.promise;
};
/**
* Requests historical telemetry for the named data attribute. In
* the case of REMS, this data source exposes multiple different
* data variables from the REMS instrument, including temperature
* and others
* @param id The telemetry data point key to be queried.
* @returns {Promise | Array<RemsTelemetryValue>} that resolves with an Array of {@link RemsTelemetryValue} objects for the request data key.
*/
RemsTelemetryServerAdapter.prototype.history = function(request) {
var id = request.key;
return this.requestHistory(request);
};
return RemsTelemetryServerAdapter;
}
);

View File

@@ -1,10 +1,9 @@
<span class="status block ok" ng-controller="DialogLaunchController">
<span class="ui-symbol status-indicator">&#xe600;</span>
<span class="label">
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
<span class="ui-symbol status-indicator">&#xe600;</span><span class="label">
<a ng-click="launchProgress(true)">Known</a> |
<a ng-click="launchProgress(false)">Unknown</a> |
<a ng-click="launchError()">Error</a> |
<a ng-click="launchInfo()">Info</a>
</span>
<span class="count">Dialogs</span>
</span><span class="count">Dialogs</span>
</span>

View File

@@ -1,10 +1,9 @@
<span class="status block ok" ng-controller="NotificationLaunchController">
<span class="ui-symbol status-indicator">&#xe600;</span>
<span class="label">
<!-- DO NOT ADD SPACES BETWEEN THE SPANS - IT ADDS WHITE SPACE!! -->
<span class="ui-symbol status-indicator">&#xe600;</span><span class="label">
<a ng-click="newInfo()">Success</a> |
<a ng-click="newError()">Error</a> |
<a ng-click="newAlert()">Alert</a> |
<a ng-click="newProgress()">Progress</a>
</span>
<span class="count">Notifications</span>
</span><span class="count">Notifications</span>
</span>

View File

@@ -0,0 +1,146 @@
/*****************************************************************************
* 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([
'legacyRegistry',
'../../platform/commonUI/browse/src/InspectorRegion',
'../../platform/commonUI/regions/src/Region'
], function (
legacyRegistry,
InspectorRegion,
Region
) {
"use strict";
/**
* Add a 'plot options' region part to the inspector region for the
* Telemetry Plot type only. {@link InspectorRegion} is a default region
* implementation that is added automatically to all types. In order to
* customize what appears in the inspector region, you can start from a
* blank slate by using Region, or customize the default inspector
* region by using {@link InspectorRegion}.
*/
var plotInspector = new InspectorRegion(),
/**
* Two region parts are defined here. One that appears only in browse
* mode, and one that appears only in edit mode. For not they both point
* to the same representation, but a different key could be used here to
* include a customized representation for edit mode.
*/
plotOptionsBrowseRegion = new Region({
name: "plot-options",
title: "Plot Options",
modes: ['browse'],
content: {
key: "plot-options-browse"
}
}),
plotOptionsEditRegion = new Region({
name: "plot-options",
title: "Plot Options",
modes: ['edit'],
content: {
key: "plot-options-browse"
}
});
/**
* Both parts are added, and policies of type 'region' will determine
* which is shown based on domain object state. A default policy is
* provided which will check the 'modes' attribute of the region part
* definition.
*/
plotInspector.addRegion(plotOptionsBrowseRegion);
plotInspector.addRegion(plotOptionsEditRegion);
legacyRegistry.register("example/plotType", {
"name": "Plot Type",
"description": "Example illustrating registration of a new object type",
"extensions": {
"types": [
{
"key": "plot",
"name": "Example Telemetry Plot",
"glyph": "\u0074",
"description": "For development use. A plot for displaying telemetry.",
"priority": 10,
"delegates": [
"telemetry"
],
"features": "creation",
"contains": [
{
"has": "telemetry"
}
],
"model": {
"composition": []
},
"inspector": plotInspector,
"telemetry": {
"source": "generator",
"domains": [
{
"key": "time",
"name": "Time"
},
{
"key": "yesterday",
"name": "Yesterday"
},
{
"key": "delta",
"name": "Delta",
"format": "example.delta"
}
],
"ranges": [
{
"key": "sin",
"name": "Sine"
},
{
"key": "cos",
"name": "Cosine"
}
]
},
"properties": [
{
"name": "Period",
"control": "textfield",
"cssclass": "l-small l-numeric",
"key": "period",
"required": true,
"property": [
"telemetry",
"period"
],
"pattern": "^\\d*(\\.\\d*)?$"
}
]
}
]
}
});
});

View File

@@ -24,7 +24,9 @@
var gulp = require('gulp'),
requirejsOptimize = require('gulp-requirejs-optimize'),
sourcemaps = require('gulp-sourcemaps'),
compass = require('gulp-compass'),
rename = require('gulp-rename'),
sass = require('gulp-sass'),
bourbon = require('node-bourbon'),
jshint = require('gulp-jshint'),
jscs = require('gulp-jscs'),
replace = require('gulp-replace-task'),
@@ -38,7 +40,7 @@ var gulp = require('gulp'),
main: 'main.js',
dist: 'dist',
assets: 'dist/assets',
scss: 'platform/**/*.scss',
scss: ['./platform/**/*.scss', './example/**/*.scss'],
scripts: [ 'main.js', 'platform/**/*.js', 'src/**/*.js' ],
static: [
'index.html',
@@ -57,10 +59,9 @@ var gulp = require('gulp'),
configFile: path.resolve(__dirname, 'karma.conf.js'),
singleRun: true
},
compass: {
sass: __dirname,
css: paths.assets,
sourcemap: true
sass: {
includePaths: bourbon.includePaths,
sourceComments: true
},
replace: {
variables: {
@@ -70,40 +71,7 @@ var gulp = require('gulp'),
branch: fs.existsSync('.git') ? git.branch() : 'Unknown'
}
}
},
stream = require('stream');
/**
* Returns a transform stream that allows us to customize the destination
* paths for individual sass files. Wraps compass.
*/
function customCompass() {
var compassWrapper = new stream.Transform({objectMode: true});
compassWrapper._transform = function (chunk, encoding, done) {
if (/\/_[^\/]*.scss$/.test(chunk.path)) {
return done();
}
var baseDir = 'platform/' + chunk.relative.replace(/sass\/.*$/, ''),
options = {
project: __dirname,
sass: baseDir + 'sass/',
css: baseDir + 'css/',
comments: true,
bundle_exec: true
};
compass(options)
.on('data', function (file) {
this.push(file);
}.bind(this))
.on('error', done)
.on('end', done)
.end(chunk);
};
return compassWrapper;
}
gulp.task('scripts', function () {
return gulp.src(paths.main)
@@ -118,11 +86,17 @@ gulp.task('test', function (done) {
new karma.Server(options.karma, done).start();
});
gulp.task('compass');
gulp.task('stylesheets', function () {
return gulp.src(paths.scss)
.pipe(customCompass());
return gulp.src(paths.scss, {base: '.'})
.pipe(sourcemaps.init())
.pipe(sass(options.sass).on('error', sass.logError))
.pipe(rename(function (file) {
file.dirname =
file.dirname.replace(path.sep + 'sass', path.sep + 'css');
return file;
}))
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(__dirname));
});
gulp.task('lint', function () {
@@ -159,7 +133,7 @@ gulp.task('serve', function () {
var app = require('./app.js');
});
gulp.task('develop', ['serve', 'watch']);
gulp.task('develop', ['serve', 'stylesheets', 'watch']);
gulp.task('install', [ 'static', 'scripts' ]);

View File

@@ -33,13 +33,18 @@
mct.run();
});
</script>
<link rel="stylesheet" href="platform/commonUI/general/res/css/startup-base.css">
<link rel="stylesheet" href="platform/commonUI/general/res/css/openmct.css">
<link rel="icon" type="image/png" href="platform/commonUI/general/res/images/favicons/favicon-32x32.png" sizes="32x32">
<link rel="icon" type="image/png" href="platform/commonUI/general/res/images/favicons/favicon-96x96.png" sizes="96x96">
<link rel="icon" type="image/png" href="platform/commonUI/general/res/images/favicons/favicon-16x16.png" sizes="16x16">
<link rel="shortcut icon" href="platform/commonUI/general/res/images/favicons/favicon.ico">
</head>
<body class="user-environ" ng-view>
<body class="user-environ">
<div class="l-splash-holder s-splash-holder">
<div class="l-splash s-splash"></div>
</div>
<div ng-view></div>
</body>
</html>

View File

@@ -20,7 +20,7 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global module*/
/*global module,process*/
module.exports = function(config) {
config.set({
@@ -39,6 +39,7 @@ module.exports = function(config) {
{pattern: 'example/**/*.js', included: false},
{pattern: 'platform/**/*.js', included: false},
{pattern: 'warp/**/*.js', included: false},
{pattern: 'platform/**/*.html', included: false},
'test-main.js'
],
@@ -57,7 +58,7 @@ module.exports = function(config) {
// Test results reporter to use
// Possible values: 'dots', 'progress'
// Available reporters: https://npmjs.org/browse/keyword/karma-reporter
reporters: ['progress', 'coverage', 'html'],
reporters: ['progress', 'coverage', 'html', 'junit'],
// Web server port.
port: 9876,
@@ -78,7 +79,14 @@ module.exports = function(config) {
// Code coverage reporting.
coverageReporter: {
dir: "dist/coverage"
dir: process.env.CIRCLE_ARTIFACTS ?
process.env.CIRCLE_ARTIFACTS + '/coverage' :
"dist/coverage",
check: {
global: {
lines: 80
}
}
},
// HTML test reporting.
@@ -88,6 +96,10 @@ module.exports = function(config) {
foldAll: false
},
junitReporter: {
outputDir: process.env.CIRCLE_TEST_REPORTS || 'target/junit'
},
// Continuous Integration mode.
// If true, Karma captures browsers, runs the tests and exits.
singleRun: true

21
main.js
View File

@@ -26,12 +26,17 @@ requirejs.config({
"legacyRegistry": "src/legacyRegistry",
"angular": "bower_components/angular/angular.min",
"angular-route": "bower_components/angular-route/angular-route.min",
"csv": "bower_components/comma-separated-values/csv.min",
"es6-promise": "bower_components/es6-promise/promise.min",
"moment": "bower_components/moment/moment",
"moment-duration-format": "bower_components/moment-duration-format/lib/moment-duration-format",
"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",
"eventemitter2": "bower_components/eventemitter2/lib/eventemitter2",
"lodash": "bower_components/lodash/lodash"
},
"shim": {
"angular": {
@@ -42,6 +47,9 @@ requirejs.config({
},
"moment-duration-format": {
"deps": [ "moment" ]
},
"zepto": {
"exports": "Zepto"
}
}
});
@@ -65,15 +73,15 @@ define([
'./platform/commonUI/notification/bundle',
'./platform/containment/bundle',
'./platform/execution/bundle',
'./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',
@@ -83,6 +91,11 @@ define([
'./platform/entanglement/bundle',
'./platform/search/bundle',
'./platform/status/bundle',
'./platform/commonUI/regions/bundle',
'./api/telemetry-api/bundle',
'./api/object-api/bundle',
'./api/composition-api/bundle',
'./example/scratchpad/bundle',
'./example/imagery/bundle',
'./example/eventGenerator/bundle',
@@ -96,4 +109,4 @@ define([
return new Main().run(legacyRegistry);
}
};
});
});

View File

@@ -1,21 +1,23 @@
{
"name": "openmctweb",
"version": "0.9.2-SNAPSHOT",
"description": "The Open MCT Web core platform",
"version": "0.10.1-SNAPSHOT",
"description": "The Open MCT core platform",
"dependencies": {
"express": "^4.13.1",
"minimist": "^1.1.1"
"minimist": "^1.1.1",
"request": "^2.69.0"
},
"devDependencies": {
"bower": "^1.7.7",
"git-rev-sync": "^1.4.0",
"glob": ">= 3.0.0",
"gulp": "^3.9.0",
"gulp-compass": "^2.1.0",
"gulp-jscs": "^3.0.2",
"gulp-jshint": "^2.0.0",
"gulp-rename": "^1.2.2",
"gulp-replace-task": "^0.11.0",
"gulp-requirejs-optimize": "^0.3.1",
"gulp-sass": "^2.2.0",
"gulp-sourcemaps": "^1.6.0",
"jasmine-core": "^2.3.0",
"jsdoc": "^3.3.2",
@@ -26,26 +28,28 @@
"karma-coverage": "^0.5.3",
"karma-html-reporter": "^0.2.7",
"karma-jasmine": "^0.1.5",
"karma-phantomjs-launcher": "^0.2.3",
"karma-junit-reporter": "^0.3.8",
"karma-phantomjs-launcher": "^1.0.0",
"karma-requirejs": "^0.2.2",
"lodash": "^3.10.1",
"markdown-toc": "^0.11.7",
"marked": "^0.3.5",
"mkdirp": "^0.5.1",
"moment": "^2.11.1",
"phantomjs": "^1.9.19",
"requirejs": "^2.1.17",
"node-bourbon": "^4.2.3",
"phantomjs-prebuilt": "^2.1.0",
"requirejs": "2.1.x",
"split": "^1.0.0"
},
"scripts": {
"start": "node app.js",
"test": "karma start --single-run",
"jshint": "jshint platform example || exit 0",
"jshint": "jshint platform example",
"watch": "karma start",
"jsdoc": "jsdoc -c jsdoc.json -r -d target/docs/api",
"otherdoc": "node docs/gendocs.js --in docs/src --out target/docs --suppress-toc 'docs/src/index.md|docs/src/process/index.md'",
"docs": "npm run jsdoc ; npm run otherdoc",
"prepublish": "./node_modules/bower/bin/bower install && bundle install && ./node_modules/gulp/bin/gulp.js install"
"prepublish": "node ./node_modules/bower/bin/bower install && node ./node_modules/gulp/bin/gulp.js install"
},
"repository": {
"type": "git",

View File

@@ -26,12 +26,26 @@ define([
"./src/LogoController",
"./src/AboutController",
"./src/LicenseController",
"text!./res/templates/app-logo.html",
"text!./res/templates/about-logo.html",
"text!./res/templates/overlay-about.html",
"text!./res/templates/license-apache.html",
"text!./res/templates/license-mit.html",
"text!./res/templates/licenses.html",
"text!./res/templates/licenses-export-md.html",
'legacyRegistry'
], function (
aboutDialogTemplate,
LogoController,
AboutController,
LicenseController,
appLogoTemplate,
aboutLogoTemplate,
overlayAboutTemplate,
licenseApacheTemplate,
licenseMitTemplate,
licensesTemplate,
licensesExportMdTemplate,
legacyRegistry
) {
"use strict";
@@ -43,12 +57,12 @@ define([
{
"key": "app-logo",
"priority": "optional",
"templateUrl": "templates/app-logo.html"
"template": appLogoTemplate
},
{
"key": "about-logo",
"priority": "preferred",
"templateUrl": "templates/about-logo.html"
"template": aboutLogoTemplate
},
{
"key": "about-dialog",
@@ -56,15 +70,15 @@ define([
},
{
"key": "overlay-about",
"templateUrl": "templates/overlay-about.html"
"template": overlayAboutTemplate
},
{
"key": "license-apache",
"templateUrl": "templates/license-apache.html"
"template": licenseApacheTemplate
},
{
"key": "license-mit",
"templateUrl": "templates/license-mit.html"
"template": licenseMitTemplate
}
],
"controllers": [
@@ -156,11 +170,11 @@ define([
"routes": [
{
"when": "/licenses",
"templateUrl": "templates/licenses.html"
"template": licensesTemplate
},
{
"when": "/licenses-md",
"templateUrl": "templates/licenses-export-md.html"
"template": licensesExportMdTemplate
}
]
}

View File

@@ -20,11 +20,7 @@
at runtime from the About dialog for additional information.
-->
<div class="abs t-about l-about t-about-openmctweb s-about" ng-controller = "AboutController as about">
<div class="l-logo-holder s-logo-holder">
<div class="l-logo s-logo s-logo-nasa"></div>
<div class="l-logo l-logo-app s-logo s-logo-openmctweb"></div>
</div>
<div class="l-splash s-splash"></div>
<div class="s-text l-content">
<h1 class="l-title s-title">OpenMCT Web</h1>
<div class="l-description s-description">

View File

@@ -37,6 +37,18 @@ define([
"./src/creation/AddActionProvider",
"./src/creation/CreationService",
"./src/windowing/WindowTitler",
"text!./res/templates/browse.html",
"text!./res/templates/create/locator.html",
"text!./res/templates/browse-object.html",
"text!./res/templates/create/create-button.html",
"text!./res/templates/create/create-menu.html",
"text!./res/templates/items/grid-item.html",
"text!./res/templates/browse/object-header.html",
"text!./res/templates/menu-arrow.html",
"text!./res/templates/back-arrow.html",
"text!./res/templates/items/items.html",
"text!./res/templates/browse/object-properties.html",
"text!./res/templates/browse/inspector-region.html",
'legacyRegistry'
], function (
BrowseController,
@@ -54,6 +66,18 @@ define([
AddActionProvider,
CreationService,
WindowTitler,
browseTemplate,
locatorTemplate,
browseObjectTemplate,
createButtonTemplate,
createMenuTemplate,
gridItemTemplate,
objectHeaderTemplate,
menuArrowTemplate,
backArrowTemplate,
itemsTemplate,
objectPropertiesTemplate,
inspectorRegionTemplate,
legacyRegistry
) {
"use strict";
@@ -63,15 +87,22 @@ define([
"routes": [
{
"when": "/browse/:ids*",
"templateUrl": "templates/browse.html",
"template": browseTemplate,
"reloadOnSearch": false
},
{
"when": "",
"templateUrl": "templates/browse.html",
"template": browseTemplate,
"reloadOnSearch": false
}
],
"constants": [
{
"key": "DEFAULT_PATH",
"value": "mine",
"priority": "fallback"
}
],
"controllers": [
{
"key": "BrowseController",
@@ -80,10 +111,12 @@ define([
"$scope",
"$route",
"$location",
"$q",
"$window",
"objectService",
"navigationService",
"urlService"
"urlService",
"policyService",
"DEFAULT_PATH"
]
},
{
@@ -102,9 +135,7 @@ define([
"depends": [
"$scope",
"$location",
"$route",
"$q",
"navigationService"
"$route"
]
},
{
@@ -134,13 +165,17 @@ define([
"controls": [
{
"key": "locator",
"templateUrl": "templates/create/locator.html"
"template": locatorTemplate
}
],
"representations": [
{
"key": "view-object",
"templateUrl": "templates/view-object.html"
},
{
"key": "browse-object",
"templateUrl": "templates/browse-object.html",
"template": browseObjectTemplate,
"gestures": [
"drop"
],
@@ -150,18 +185,18 @@ define([
},
{
"key": "create-button",
"templateUrl": "templates/create/create-button.html"
"template": createButtonTemplate
},
{
"key": "create-menu",
"templateUrl": "templates/create/create-menu.html",
"template": createMenuTemplate,
"uses": [
"action"
]
},
{
"key": "grid-item",
"templateUrl": "templates/items/grid-item.html",
"template": gridItemTemplate,
"uses": [
"type",
"action",
@@ -174,14 +209,14 @@ define([
},
{
"key": "object-header",
"templateUrl": "templates/browse/object-header.html",
"template": objectHeaderTemplate,
"uses": [
"type"
]
},
{
"key": "menu-arrow",
"templateUrl": "templates/menu-arrow.html",
"template": menuArrowTemplate,
"uses": [
"action"
],
@@ -194,7 +229,15 @@ define([
"uses": [
"context"
],
"templateUrl": "templates/back-arrow.html"
"template": backArrowTemplate
},
{
"key": "object-properties",
"template": objectPropertiesTemplate
},
{
"key": "inspector-region",
"template": inspectorRegionTemplate
}
],
"services": [
@@ -250,7 +293,7 @@ define([
"name": "Items",
"glyph": "9",
"description": "Grid of available items",
"templateUrl": "templates/items/items.html",
"template": itemsTemplate,
"uses": [
"composition"
],

View File

@@ -47,11 +47,6 @@
<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-toolbar name="mctToolbar"
structure="toolbar.structure"
ng-model="toolbar.state"
class="flex-elem grows">
</mct-toolbar>
<mct-representation key="'edit-action-buttons'"
mct-object="domainObject"
class='flex-elem conclude-editing'>
@@ -60,9 +55,8 @@
</div>
<mct-representation key="representation.selected.key"
mct-object="representation.selected.key && domainObject"
class="abs flex-elem grows object-holder-main scroll"
toolbar="toolbar">
class="abs flex-elem grows object-holder-main scroll">
</mct-representation>
</div><!--/ l-object-wrapper-inner -->
</div>
</div>
</div>

View File

@@ -63,7 +63,7 @@
<mct-split-pane class='l-object-and-inspector contents abs' anchor='right'>
<div class='split-pane-component t-object pane primary-pane left'>
<mct-representation mct-object="navigatedObject"
key="'browse-object'"
key="'view-object'"
class="abs holder holder-object">
</mct-representation>
</div>

View File

@@ -19,14 +19,12 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<div content="jquery-wrapper"
class="abs holder-all edit-mode"
ng-controller="EditController as editMode"
mct-before-unload="editMode.getUnloadWarning()">
<mct-representation key="'edit-object'" mct-object="editMode.navigatedObject()">
</mct-representation>
<mct-include key="'bottombar'"></mct-include>
<div ng-controller="InspectorController">
<div ng-repeat="region in regions">
<mct-representation
key="region.content.key"
mct-object="domainObject"
ng-model="ngModel">
</mct-representation>
</div>
</div>

View File

@@ -0,0 +1,61 @@
<!--
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.
-->
<div ng-controller="ObjectInspectorController as controller">
<ul class="flex-elem grows l-inspector-part">
<li>
<em class="t-inspector-part-header">Properties</em>
<div class="inspector-properties"
ng-repeat="data in metadata"
ng-class="{ first:$index === 0 }">
<div class="label">{{ data.name }}</div>
<div class="value">{{ data.value }}</div>
</div>
</li>
<li ng-if="contextutalParents.length > 0">
<em class="t-inspector-part-header" title="The location of this linked object.">Location</em>
<div ng-if="primaryParents.length > 0" class="section-header">This Object</div>
<span class="inspector-location"
ng-repeat="parent in contextutalParents"
ng-class="{ last:($index + 1) === contextualParents.length }">
<mct-representation key="'label'"
mct-object="parent"
ng-model="ngModel"
ng-click="ngModel.selectedObject = parent"
class="location-item">
</mct-representation>
</span>
</li>
<li ng-if="primaryParents.length > 0">
<div class="section-header">Object's Original</div>
<span class="inspector-location"
ng-repeat="parent in primaryParents"
ng-class="{ last:($index + 1) === primaryParents.length }">
<mct-representation key="'label'"
mct-object="parent"
ng-model="ngModel"
ng-click="ngModel.selectedObject = parent"
class="location-item">
</mct-representation>
</span>
</li>
</ul>
</div>

View File

@@ -0,0 +1,33 @@
<!--
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.
-->
<!--
A representation that allows the 'View' region of an object view to change
dynamically (eg. between browse and edit modes). Values correspond to a
representation key, and currently defaults to 'browse-object'.
In the case of edit, the EditRepresenter will change this to editable
representation of the object as needed.
-->
<mct-representation mct-object="domainObject"
key="viewObjectTemplate || 'browse-object'"
class="abs holder">
</mct-representation>

View File

@@ -27,15 +27,12 @@
*/
define(
[
'../../../representation/src/gestures/GestureConstants',
'../../edit/src/objects/EditableDomainObject'
'../../../representation/src/gestures/GestureConstants'
],
function (GestureConstants, EditableDomainObject) {
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
@@ -47,18 +44,21 @@ define(
* @memberof platform/commonUI/browse
* @constructor
*/
function BrowseController($scope, $route, $location, $q, objectService, navigationService, urlService) {
function BrowseController(
$scope,
$route,
$location,
$window,
objectService,
navigationService,
urlService,
policyService,
defaultPath
) {
var path = [ROOT_ID].concat(
($route.current.params.ids || DEFAULT_PATH).split("/")
($route.current.params.ids || defaultPath).split("/")
);
function isDirty(){
var editorCapability = $scope.navigatedObject &&
$scope.navigatedObject.getCapability("editor"),
hasChanges = editorCapability && editorCapability.dirty();
return hasChanges;
}
function updateRoute(domainObject) {
var priorRoute = $route.current,
// Act as if params HADN'T changed to avoid page reload
@@ -75,31 +75,35 @@ define(
// urlService.urlForLocation used to adjust current
// path to new, addressed, path based on
// domainObject
$location.path(urlService.urlForLocation("browse",
domainObject.hasCapability('editor') ?
domainObject.getOriginalObject() : domainObject));
$location.path(urlService.urlForLocation("browse", domainObject));
}
// Callback for updating the in-scope reference to the object
// that is currently navigated-to.
function setNavigation(domainObject) {
var navigationAllowed = true;
if (domainObject === $scope.navigatedObject){
//do nothing;
return;
}
if (isDirty() && !confirm(CONFIRM_MSG)) {
$scope.treeModel.selectedObject = $scope.navigatedObject;
navigationService.setNavigation($scope.navigatedObject);
} else {
if ($scope.navigatedObject && $scope.navigatedObject.hasCapability("editor")){
$scope.navigatedObject.getCapability("editor").cancel();
}
policyService.allow("navigation", $scope.navigatedObject, domainObject, function(message){
navigationAllowed = $window.confirm(message + "\r\n\r\n" +
" Are you sure you want to continue?");
});
if (navigationAllowed) {
$scope.navigatedObject = domainObject;
$scope.treeModel.selectedObject = domainObject;
navigationService.setNavigation(domainObject);
updateRoute(domainObject);
} else {
//If navigation was unsuccessful (ie. blocked), reset
// the selected object in the tree to the currently
// navigated object
$scope.treeModel.selectedObject = $scope.navigatedObject ;
}
}
@@ -143,6 +147,12 @@ define(
} else {
doNavigate(nextObject, index + 1);
}
} else if (index === 1 && c.length > 0) {
// Roots are in a top-level container that we don't
// want to be selected, so if we couldn't find an
// object at the path we wanted, at least select
// one of its children.
navigateTo(c[c.length - 1]);
} else {
// Couldn't find the next element of the path
// so navigate to the last path object we did find
@@ -170,18 +180,13 @@ define(
selectedObject: navigationService.getNavigation()
};
$scope.beforeUnloadWarning = function() {
return isDirty() ?
"Unsaved changes will be lost if you leave this page." :
undefined;
};
// Listen for changes in navigation state.
navigationService.addListener(setNavigation);
// Also listen for changes which come from the tree
// Also listen for changes which come from the tree. Changes in
// the tree will trigger a change in browse navigation state.
$scope.$watch("treeModel.selectedObject", setNavigation);
// Clean up when the scope is destroyed
$scope.$on("$destroy", function () {
navigationService.removeListener(setNavigation);

View File

@@ -22,11 +22,8 @@
/*global define,Promise*/
define(
[
'../../../representation/src/gestures/GestureConstants',
'../../edit/src/objects/EditableDomainObject'
],
function (GestureConstants, EditableDomainObject) {
[],
function () {
"use strict";
/**
@@ -35,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) {
@@ -57,10 +54,9 @@ define(
function updateQueryParam(viewKey) {
var unlisten,
priorRoute = $route.current,
isEditMode = $scope.domainObject && $scope.domainObject.hasCapability('editor');
priorRoute = $route.current;
if (viewKey && !isEditMode) {
if (viewKey) {
$location.search('view', viewKey);
unlisten = $scope.$on('$locationChangeSuccess', function () {
// Checks path to make sure /browse/ is at front
@@ -76,10 +72,6 @@ define(
$scope.$watch('domainObject', setViewForDomainObject);
$scope.$watch('representation.selected.key', updateQueryParam);
$scope.cancelEditing = function() {
navigationService.setNavigation($scope.domainObject.getDomainObject());
};
$scope.doAction = function (action){
return $scope[action] && $scope[action]();
};

View File

@@ -0,0 +1,69 @@
/*****************************************************************************
* 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,window*/
define(
[
'../../regions/src/Region'
],
function (Region) {
"use strict";
/**
* Defines the a default Inspector region. Captured in a class to
* allow for modular extension and customization of regions based on
* the typical case.
* @memberOf platform/commonUI/regions
* @constructor
*/
function InspectorRegion() {
Region.call(this, {'name': 'Inspector'});
this.buildRegion();
}
InspectorRegion.prototype = Object.create(Region.prototype);
InspectorRegion.prototype.constructor = Region;
/**
* @private
*/
InspectorRegion.prototype.buildRegion = function() {
var metadataRegion = {
name: 'metadata',
title: 'Metadata Region',
// Which modes should the region part be visible in? If
// nothing provided here, then assumed that part is visible
// in both. The visibility or otherwise of a region part
// should be decided by a policy. In this case, 'modes' is a
// shortcut that is used by the EditableRegionPolicy.
modes: ['browse', 'edit'],
content: {
key: 'object-properties'
}
};
this.addRegion(new Region(metadataRegion), 0);
};
return InspectorRegion;
}
);

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

@@ -59,6 +59,7 @@ define(
callback(value);
});
}
return true;
};
/**

View File

@@ -29,8 +29,7 @@ define(
function (BrowseController) {
"use strict";
//TODO: Disabled for NEM Beta
xdescribe("The browse controller", function () {
describe("The browse controller", function () {
var mockScope,
mockRoute,
mockLocation,
@@ -40,6 +39,9 @@ define(
mockUrlService,
mockDomainObject,
mockNextObject,
mockWindow,
mockPolicyService,
testDefaultRoot,
controller;
function mockPromise(value) {
@@ -50,7 +52,32 @@ define(
};
}
function instantiateController() {
controller = new BrowseController(
mockScope,
mockRoute,
mockLocation,
mockWindow,
mockObjectService,
mockNavigationService,
mockUrlService,
mockPolicyService,
testDefaultRoot
);
}
beforeEach(function () {
mockWindow = jasmine.createSpyObj('$window', [
"confirm"
]);
mockWindow.confirm.andReturn(true);
mockPolicyService = jasmine.createSpyObj('policyService', [
'allow'
]);
testDefaultRoot = "some-root-level-domain-object";
mockScope = jasmine.createSpyObj(
"$scope",
[ "$on", "$watch" ]
@@ -101,41 +128,28 @@ define(
]));
mockNextObject.useCapability.andReturn(undefined);
mockNextObject.getId.andReturn("next");
mockDomainObject.getId.andReturn("mine");
mockDomainObject.getId.andReturn(testDefaultRoot);
controller = new BrowseController(
mockScope,
mockRoute,
mockLocation,
mockObjectService,
mockNavigationService,
mockUrlService
);
instantiateController();
});
it("uses composition to set the navigated object, if there is none", function () {
controller = new BrowseController(
mockScope,
mockRoute,
mockLocation,
mockObjectService,
mockNavigationService,
mockUrlService
);
instantiateController();
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDomainObject);
});
it("navigates to a root-level object, even when default path is not found", function () {
mockDomainObject.getId
.andReturn("something-other-than-the-" + testDefaultRoot);
instantiateController();
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDomainObject);
});
it("does not try to override navigation", function () {
mockNavigationService.getNavigation.andReturn(mockDomainObject);
controller = new BrowseController(
mockScope,
mockRoute,
mockLocation,
mockObjectService,
mockNavigationService,
mockUrlService
);
instantiateController();
expect(mockScope.navigatedObject).toBe(mockDomainObject);
});
@@ -162,14 +176,8 @@ define(
});
it("uses route parameters to choose initially-navigated object", function () {
mockRoute.current.params.ids = "mine/next";
controller = new BrowseController(
mockScope,
mockRoute,
mockLocation,
mockObjectService,
mockNavigationService
);
mockRoute.current.params.ids = testDefaultRoot + "/next";
instantiateController();
expect(mockScope.navigatedObject).toBe(mockNextObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockNextObject);
@@ -179,14 +187,8 @@ define(
// Idea here is that if we get a bad path of IDs,
// browse controller should traverse down it until
// it hits an invalid ID.
mockRoute.current.params.ids = "mine/junk";
controller = new BrowseController(
mockScope,
mockRoute,
mockLocation,
mockObjectService,
mockNavigationService
);
mockRoute.current.params.ids = testDefaultRoot + "/junk";
instantiateController();
expect(mockScope.navigatedObject).toBe(mockDomainObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockDomainObject);
@@ -196,14 +198,8 @@ define(
// Idea here is that if we get a path which passes
// through an object without a composition, browse controller
// should stop at it since remaining IDs cannot be loaded.
mockRoute.current.params.ids = "mine/next/junk";
controller = new BrowseController(
mockScope,
mockRoute,
mockLocation,
mockObjectService,
mockNavigationService
);
mockRoute.current.params.ids = testDefaultRoot + "/next/junk";
instantiateController();
expect(mockScope.navigatedObject).toBe(mockNextObject);
expect(mockNavigationService.setNavigation)
.toHaveBeenCalledWith(mockNextObject);
@@ -230,7 +226,10 @@ define(
// prior to setting $route.current
mockLocation.path.andReturn("/browse/");
mockNavigationService.setNavigation.andReturn(true);
// Exercise the Angular workaround
mockNavigationService.addListener.mostRecentCall.args[0]();
mockScope.$on.mostRecentCall.args[1]();
expect(mockUnlisten).toHaveBeenCalled();
@@ -241,6 +240,36 @@ define(
);
});
it("after successful navigation event sets the selected tree " +
"object", function () {
mockScope.navigatedObject = mockDomainObject;
mockNavigationService.setNavigation.andReturn(true);
//Simulate a change in selected tree object
mockScope.treeModel = {selectedObject: mockDomainObject};
mockScope.$watch.mostRecentCall.args[1](mockNextObject);
expect(mockScope.treeModel.selectedObject).toBe(mockNextObject);
expect(mockScope.treeModel.selectedObject).not.toBe(mockDomainObject);
});
it("after failed navigation event resets the selected tree" +
" object", function () {
mockScope.navigatedObject = mockDomainObject;
mockWindow.confirm.andReturn(false);
mockPolicyService.allow.andCallFake(function(category, object, context, callback){
callback("unsaved changes");
return false;
});
//Simulate a change in selected tree object
mockScope.treeModel = {selectedObject: mockDomainObject};
mockScope.$watch.mostRecentCall.args[1](mockNextObject);
expect(mockScope.treeModel.selectedObject).not.toBe(mockNextObject);
expect(mockScope.treeModel.selectedObject).toBe(mockDomainObject);
});
});
}
);

View File

@@ -0,0 +1,45 @@
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
* Administration. All rights reserved.
*
* Open MCT Web is licensed under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*
* Open MCT Web includes source code licensed under additional open source
* licenses. See the Open Source Licenses file (LICENSES.md) included with
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
/**
* MCTIncudeSpec. Created by vwoeltje on 11/6/14.
*/
define(
["../src/InspectorRegion"],
function (InspectorRegion) {
"use strict";
describe("The inspector region", function () {
var inspectorRegion;
beforeEach(function () {
inspectorRegion = new InspectorRegion();
});
it("creates default region parts", function () {
expect(inspectorRegion.regions.length).toBe(1);
});
});
}
);

View File

@@ -86,4 +86,4 @@ define(
});
}
);
);

View File

@@ -24,10 +24,24 @@
define([
"./src/DialogService",
"./src/OverlayService",
"text!./res/templates/overlay-dialog.html",
"text!./res/templates/overlay-options.html",
"text!./res/templates/dialog.html",
"text!./res/templates/overlay-blocking-message.html",
"text!./res/templates/message.html",
"text!./res/templates/overlay-message-list.html",
"text!./res/templates/overlay.html",
'legacyRegistry'
], function (
DialogService,
OverlayService,
overlayDialogTemplate,
overlayOptionsTemplate,
dialogTemplate,
overlayBlockingMessageTemplate,
messageTemplate,
overlayMessageListTemplate,
overlayTemplate,
legacyRegistry
) {
"use strict";
@@ -57,33 +71,33 @@ define([
"templates": [
{
"key": "overlay-dialog",
"templateUrl": "templates/overlay-dialog.html"
"template": overlayDialogTemplate
},
{
"key": "overlay-options",
"templateUrl": "templates/overlay-options.html"
"template": overlayOptionsTemplate
},
{
"key": "form-dialog",
"templateUrl": "templates/dialog.html"
"template": dialogTemplate
},
{
"key": "overlay-blocking-message",
"templateUrl": "templates/overlay-blocking-message.html"
"template": overlayBlockingMessageTemplate
},
{
"key": "message",
"templateUrl": "templates/message.html"
"template": messageTemplate
},
{
"key": "overlay-message-list",
"templateUrl": "templates/overlay-message-list.html"
"template": overlayMessageListTemplate
}
],
"containers": [
{
"key": "overlay",
"templateUrl": "templates/overlay.html"
"template": overlayTemplate
}
]
}

View File

@@ -6,7 +6,9 @@
</div>
</div>
<div class="abs message-body">
<mct-include ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'" key="'message'" ng-model="msg"></mct-include>
<mct-include
ng-repeat="msg in ngModel.dialog.messages | orderBy: '-'"
key="'message'" ng-model="msg.model"></mct-include>
</div>
<div class="abs bottom-bar">
<a ng-repeat="dialogAction in ngModel.dialog.actions"

View File

@@ -22,58 +22,63 @@
/*global define*/
define([
"./src/controllers/EditController",
"./src/controllers/EditActionController",
"./src/controllers/EditPanesController",
"./src/controllers/ElementsController",
"./src/controllers/EditObjectController",
"./src/directives/MCTBeforeUnload",
"./src/actions/LinkAction",
"./src/actions/EditAction",
"./src/actions/PropertiesAction",
"./src/actions/RemoveAction",
"./src/actions/SaveAction",
"./src/actions/SaveAsAction",
"./src/actions/CancelAction",
"./src/policies/EditActionPolicy",
"./src/policies/EditableLinkPolicy",
"./src/policies/EditableMovePolicy",
"./src/policies/EditNavigationPolicy",
"./src/policies/EditContextualActionPolicy",
"./src/representers/EditRepresenter",
"./src/representers/EditToolbarRepresenter",
"text!./res/templates/library.html",
"text!./res/templates/edit-object.html",
"text!./res/templates/edit-action-buttons.html",
"text!./res/templates/elements.html",
"text!./res/templates/topbar-edit.html",
'legacyRegistry'
], function (
EditController,
EditActionController,
EditPanesController,
ElementsController,
EditObjectController,
MCTBeforeUnload,
LinkAction,
EditAction,
PropertiesAction,
RemoveAction,
SaveAction,
SaveAsAction,
CancelAction,
EditActionPolicy,
EditableLinkPolicy,
EditableMovePolicy,
EditNavigationPolicy,
EditContextualActionPolicy,
EditRepresenter,
EditToolbarRepresenter,
libraryTemplate,
editObjectTemplate,
editActionButtonsTemplate,
elementsTemplate,
topbarEditTemplate,
legacyRegistry
) {
"use strict";
legacyRegistry.register("platform/commonUI/edit", {
"extensions": {
"routes": [
{
"when": "/edit",
"templateUrl": "templates/edit.html"
}
],
"controllers": [
{
"key": "EditController",
"implementation": EditController,
"depends": [
"$scope",
"$q",
"navigationService"
]
},
{
"key": "EditActionController",
"implementation": EditActionController,
@@ -94,6 +99,15 @@ define([
"depends": [
"$scope"
]
},
{
"key": "EditObjectController",
"implementation": EditObjectController,
"depends": [
"$scope",
"$location",
"policyService"
]
}
],
"directives": [
@@ -155,6 +169,15 @@ define([
"implementation": SaveAction,
"name": "Save",
"description": "Save changes made to these objects.",
"depends": [],
"priority": "mandatory"
},
{
"key": "save",
"category": "conclude-editing",
"implementation": SaveAsAction,
"name": "Save",
"description": "Save changes made to these objects.",
"depends": [
"$injector",
"policyService",
@@ -180,32 +203,54 @@ define([
{
"category": "action",
"implementation": EditActionPolicy
},
{
"category": "action",
"implementation": EditContextualActionPolicy,
"depends": ["navigationService", "editModeBlacklist", "nonEditContextBlacklist"]
},
{
"category": "action",
"implementation": EditableMovePolicy
},
{
"category": "action",
"implementation": EditableLinkPolicy
},
{
"category": "navigation",
"message": "There are unsaved changes.",
"implementation": EditNavigationPolicy
}
],
"templates": [
{
"key": "edit-library",
"templateUrl": "templates/library.html"
"template": libraryTemplate
}
],
"representations": [
{
"key": "edit-object",
"templateUrl": "templates/edit-object.html",
"template": editObjectTemplate,
"uses": [
"view"
],
"gestures": [
"drop"
]
},
{
"key": "edit-action-buttons",
"templateUrl": "templates/edit-action-buttons.html",
"template": editActionButtonsTemplate,
"uses": [
"action"
]
},
{
"key": "edit-elements",
"templateUrl": "templates/elements.html",
"template": elementsTemplate,
"uses": [
"composition"
],
@@ -215,7 +260,7 @@ define([
},
{
"key": "topbar-edit",
"templateUrl": "templates/topbar-edit.html"
"template": topbarEditTemplate
}
],
"representers": [
@@ -229,6 +274,16 @@ define([
{
"implementation": EditToolbarRepresenter
}
],
"constants": [
{
"key":"editModeBlacklist",
"value": ["copy", "follow", "window", "link", "locate"]
},
{
"key": "nonEditContextBlacklist",
"value": ["copy", "follow", "properties", "move", "link", "remove", "locate"]
}
]
}
});

View File

@@ -19,50 +19,51 @@
this source code distribution or the Licensing information page available
at runtime from the About dialog for additional information.
-->
<mct-representation key="'topbar-edit'"
mct-object="domainObject"
ng-model="representation">
</mct-representation>
<div class="holder edit-area abs">
<mct-split-pane class='contents abs' anchor='right'>
<div class='split-pane-component pane left edit-main'>
<mct-toolbar name="mctToolbar"
structure="toolbar.structure"
ng-model="toolbar.state">
</mct-toolbar>
<mct-representation key="representation.selected.key"
toolbar="toolbar"
mct-object="representation.selected.key && domainObject"
class="holder abs object-holder work-area">
<div class="abs l-flex-col" ng-controller="EditObjectController as EditObjectController">
<div mct-before-unload="EditObjectController.getUnloadWarning()"
class="holder flex-elem l-flex-row object-browse-bar ">
<div class="items-select left flex-elem l-flex-row grows">
<mct-representation key="'back-arrow'"
mct-object="domainObject"
class="flex-elem l-back"></mct-representation>
<mct-representation key="'object-header'"
mct-object="domainObject"
class="l-flex-row flex-elem grows object-header">
</mct-representation>
</div>
<mct-splitter></mct-splitter>
<div
class='split-pane-component pane right edit-objects menus-to-left'
ng-controller='EditPanesController as editPanes'
>
<mct-split-pane class='contents abs' anchor='bottom'>
<div
class="abs pane top accordion"
ng-controller="ToggleController as toggle"
>
<mct-container key="accordion" label="Library">
<mct-representation key="'tree'"
mct-object="editPanes.getRoot()">
</mct-representation>
</mct-container>
</div>
<mct-splitter></mct-splitter>
<div
class="abs pane bottom accordion"
ng-controller="ToggleController as toggle"
>
<mct-container key="accordion" label="Elements">
<mct-representation key="'edit-elements'" mct-object="domainObject">
</mct-representation>
</mct-container>
</div>
</mct-split-pane>
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
<mct-representation key="'switcher'"
mct-object="domainObject"
ng-model="representation">
</mct-representation>
<!-- Temporarily, on mobile, the action buttons are hidden-->
<mct-representation key="'action-group'"
mct-object="domainObject"
parameters="{ category: 'view-control' }"
class="mobile-hide">
</mct-representation>
</div>
</mct-split-pane>
</div>
<div class="holder l-flex-col flex-elem grows l-object-wrapper">
<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-toolbar name="mctToolbar"
structure="toolbar.structure"
ng-model="toolbar.state"
class="flex-elem grows">
</mct-toolbar>
<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><!--/ l-object-wrapper-inner -->
</div>
</div>

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

@@ -72,13 +72,26 @@ define(
* Enter edit mode.
*/
EditAction.prototype.perform = function () {
var editableObject;
var self = this;
if (!this.domainObject.hasCapability("editor")) {
editableObject = new EditableDomainObject(this.domainObject, this.$q);
editableObject.getCapability('status').set('editing', true);
this.navigationService.setNavigation(editableObject);
//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.$location.path("/edit");
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);
}
}
this.navigationService.addListener(cancelEditing);
};
/**

View File

@@ -24,8 +24,8 @@
define(
['../../../browse/src/creation/CreateWizard'],
function (CreateWizard) {
[],
function () {
'use strict';
/**
@@ -37,31 +37,11 @@ define(
* @memberof platform/commonUI/edit
*/
function SaveAction(
$injector,
policyService,
dialogService,
creationService,
copyService,
context
) {
this.domainObject = (context || {}).domainObject;
this.injectObjectService = function(){
this.objectService = $injector.get("objectService");
};
this.policyService = policyService;
this.dialogService = dialogService;
this.creationService = creationService;
this.copyService = copyService;
}
SaveAction.prototype.getObjectService = function(){
// Lazily acquire object service (avoids cyclical dependency)
if (!this.objectService) {
this.injectObjectService();
}
return this.objectService;
};
/**
* Save changes and conclude editing.
*
@@ -70,9 +50,7 @@ define(
* @memberof platform/commonUI/edit.SaveAction#
*/
SaveAction.prototype.perform = function () {
var domainObject = this.domainObject,
copyService = this.copyService,
self = this;
var domainObject = this.domainObject;
function resolveWith(object){
return function () {
@@ -80,64 +58,13 @@ define(
};
}
function doWizardSave(parent) {
var context = domainObject.getCapability("context"),
wizard = new CreateWizard(
domainObject,
parent,
self.policyService
);
return self.dialogService
.getUserInput(
wizard.getFormStructure(true),
wizard.getInitialFormValue()
)
.then(wizard.populateObjectFromInput.bind(wizard));
}
function fetchObject(objectId){
return self.getObjectService().getObjects([objectId]).then(function(objects){
return objects[objectId];
});
}
function getParent(object){
return fetchObject(object.getModel().location);
}
function allowClone(objectToClone) {
return (objectToClone.getId() === domainObject.getId()) ||
objectToClone.getCapability('location').isOriginal();
}
function cloneIntoParent(parent) {
return copyService.perform(domainObject, parent, allowClone);
}
function cancelEditingAfterClone(clonedObject) {
return domainObject.getCapability("editor").cancel()
.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.
if (domainObject.getModel().persisted === undefined){
return getParent(domainObject)
.then(doWizardSave)
.then(getParent)
.then(cloneIntoParent)
.then(cancelEditingAfterClone)
.catch(resolveWith(false));
} else {
return domainObject.getCapability("editor").save()
.then(resolveWith(domainObject.getOriginalObject()));
}
return domainObject.getCapability("editor").save()
.then(resolveWith(domainObject.getOriginalObject()));
}
// Discard the current root view (which will be the editing
@@ -162,7 +89,8 @@ define(
SaveAction.appliesTo = function (context) {
var domainObject = (context || {}).domainObject;
return domainObject !== undefined &&
domainObject.hasCapability("editor");
domainObject.hasCapability("editor") &&
domainObject.getModel().persisted !== undefined;
};
return SaveAction;

View File

@@ -0,0 +1,169 @@
/*****************************************************************************
* 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*/
/*jslint es5: true */
define(
['../../../browse/src/creation/CreateWizard'],
function (CreateWizard) {
'use strict';
/**
* The "Save" action; the action triggered by clicking Save from
* Edit Mode. Exits the editing user interface and invokes object
* capabilities to persist the changes that have been made.
* @constructor
* @implements {Action}
* @memberof platform/commonUI/edit
*/
function SaveAsAction(
$injector,
policyService,
dialogService,
creationService,
copyService,
context
) {
this.domainObject = (context || {}).domainObject;
this.injectObjectService = function(){
this.objectService = $injector.get("objectService");
};
this.policyService = policyService;
this.dialogService = dialogService;
this.creationService = creationService;
this.copyService = copyService;
}
/**
* @private
*/
SaveAsAction.prototype.createWizard = function (parent) {
return new CreateWizard(
this.domainObject,
parent,
this.policyService
);
};
/**
* @private
*/
SaveAsAction.prototype.getObjectService = function(){
// Lazily acquire object service (avoids cyclical dependency)
if (!this.objectService) {
this.injectObjectService();
}
return this.objectService;
};
function resolveWith(object){
return function () {
return object;
};
}
/**
* Save changes and conclude editing.
*
* @returns {Promise} a promise that will be fulfilled when
* cancellation has completed
* @memberof platform/commonUI/edit.SaveAction#
*/
SaveAsAction.prototype.perform = function () {
// Discard the current root view (which will be the editing
// UI, which will have been pushed atop the Browse UI.)
function returnToBrowse(object) {
if (object) {
object.getCapability("action").perform("navigate");
}
return object;
}
return this.save().then(returnToBrowse);
};
/**
* @private
*/
SaveAsAction.prototype.save = function () {
var self = this,
domainObject = this.domainObject,
copyService = this.copyService;
function doWizardSave(parent) {
var wizard = self.createWizard(parent);
return self.dialogService
.getUserInput(wizard.getFormStructure(true),
wizard.getInitialFormValue()
).then(wizard.populateObjectFromInput.bind(wizard));
}
function fetchObject(objectId){
return self.getObjectService().getObjects([objectId]).then(function(objects){
return objects[objectId];
});
}
function getParent(object){
return fetchObject(object.getModel().location);
}
function allowClone(objectToClone) {
return (objectToClone.getId() === domainObject.getId()) ||
objectToClone.getCapability('location').isOriginal();
}
function cloneIntoParent(parent) {
return copyService.perform(domainObject, parent, allowClone);
}
function cancelEditingAfterClone(clonedObject) {
return domainObject.getCapability("editor").cancel()
.then(resolveWith(clonedObject));
}
return getParent(domainObject)
.then(doWizardSave)
.then(getParent)
.then(cloneIntoParent)
.then(cancelEditingAfterClone)
.catch(resolveWith(false));
};
/**
* Check if this action is applicable in a given context.
* This will ensure that a domain object is present in the context,
* and that this domain object is in Edit mode.
* @returns true if applicable
*/
SaveAsAction.appliesTo = function (context) {
var domainObject = (context || {}).domainObject;
return domainObject !== undefined &&
domainObject.hasCapability("editor") &&
domainObject.getModel().persisted === undefined;
};
return SaveAsAction;
}
);

View File

@@ -124,7 +124,6 @@ define(
*/
EditorCapability.prototype.cancel = function () {
this.editableObject.getCapability("status").set("editing", false);
//TODO: Reset the cache as well here.
this.cache.markClean();
return resolvePromise(undefined);
};

View File

@@ -26,41 +26,45 @@
* @namespace platform/commonUI/edit
*/
define(
["../objects/EditableDomainObject"],
function (EditableDomainObject) {
[],
function () {
"use strict";
/**
* Controller which is responsible for populating the scope for
* Edit mode; introduces an editable version of the currently
* navigated domain object into the scope.
* Edit mode
* @memberof platform/commonUI/edit
* @constructor
*/
function EditController($scope, $q, navigationService) {
var self = this;
function EditObjectController($scope, $location, policyService) {
this.scope = $scope;
this.policyService = policyService;
function setNavigation(domainObject) {
// Wrap the domain object such that all mutation is
// confined to edit mode (until Save)
self.navigatedDomainObject =
domainObject && new EditableDomainObject(domainObject, $q);
var navigatedObject;
function setViewForDomainObject(domainObject) {
var locationViewKey = $location.search().view;
function selectViewIfMatching(view) {
if (view.key === locationViewKey) {
$scope.representation = $scope.representation || {};
$scope.representation.selected = view;
}
}
if (locationViewKey) {
((domainObject && domainObject.useCapability('view')) || [])
.forEach(selectViewIfMatching);
}
navigatedObject = domainObject;
}
setNavigation(navigationService.getNavigation());
navigationService.addListener(setNavigation);
$scope.$on("$destroy", function () {
navigationService.removeListener(setNavigation);
});
}
$scope.$watch('domainObject', setViewForDomainObject);
/**
* Get the domain object which is navigated-to.
* @returns {DomainObject} the domain object that is navigated-to
*/
EditController.prototype.navigatedObject = function () {
return this.navigatedDomainObject;
};
$scope.doAction = function (action){
return $scope[action] && $scope[action]();
};
}
/**
* Get the warning to show if the user attempts to navigate
@@ -68,17 +72,18 @@ define(
* @returns {string} the warning to show, or undefined if
* there are no unsaved changes
*/
EditController.prototype.getUnloadWarning = function () {
var navigatedObject = this.navigatedDomainObject,
editorCapability = navigatedObject &&
navigatedObject.getCapability("editor"),
hasChanges = editorCapability && editorCapability.dirty();
EditObjectController.prototype.getUnloadWarning = function () {
var navigatedObject = this.scope.domainObject,
policyMessage;
this.policyService.allow("navigation", navigatedObject, undefined, function(message) {
policyMessage = message;
});
return policyMessage;
return hasChanges ?
"Unsaved changes will be lost if you leave this page." :
undefined;
};
return EditController;
return EditObjectController;
}
);

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,74 @@
/*****************************************************************************
* 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
* @param navigationService
* @param editModeBlacklist A blacklist of actions disallowed from
* context menu when navigated object is being edited
* @param nonEditContextBlacklist A blacklist of actions disallowed
* from context menu of non-editable objects, when navigated object
* is being edited
* @constructor
*/
function EditContextualActionPolicy(navigationService, editModeBlacklist, nonEditContextBlacklist) {
this.navigationService = navigationService;
//The list of objects disallowed on target object when in edit mode
this.editModeBlacklist = editModeBlacklist;
//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.nonEditContextBlacklist = nonEditContextBlacklist;
}
function isParentEditable(object) {
var parent = object.hasCapability("context") && object.getCapability("context").getParent();
return !!parent && parent.hasCapability("editor");
}
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') || isParentEditable(selectedObject)){
return this.editModeBlacklist.indexOf(actionMetadata.key) === -1;
} else {
//Target is in the context menu
return this.nonEditContextBlacklist.indexOf(actionMetadata.key) === -1;
}
} else {
return true;
}
};
return EditContextualActionPolicy;
}
);

View File

@@ -19,47 +19,49 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define,moment*/
/*global define*/
/**
* Module defining DomainColumn. Created by vwoeltje on 11/18/14.
*/
define(
[],
function () {
"use strict";
/**
* A column which will report telemetry domain values
* (typically, timestamps.) Used by the ScrollingListController.
*
* @memberof platform/features/scrolling
* @implements {platform/features/scrolling.ScrollingColumn}
* Policy controlling whether navigation events should proceed
* when object is being edited.
* @memberof platform/commonUI/edit
* @constructor
* @param domainMetadata an object with the machine- and human-
* readable names for this domain (in `key` and `name`
* fields, respectively.)
* @param {TelemetryFormatter} telemetryFormatter the telemetry
* formatting service, for making values human-readable.
* @implements {Policy.<Action, ActionContext>}
*/
function DomainColumn(domainMetadata, telemetryFormatter) {
this.domainMetadata = domainMetadata;
this.telemetryFormatter = telemetryFormatter;
function EditNavigationPolicy(policyService) {
this.policyService = policyService;
}
DomainColumn.prototype.getTitle = function () {
return this.domainMetadata.name;
/**
* @private
*/
EditNavigationPolicy.prototype.isDirty = function(domainObject) {
var navigatedObject = domainObject,
editorCapability = navigatedObject &&
navigatedObject.getCapability("editor"),
statusCapability = navigatedObject &&
navigatedObject.getCapability("status");
return statusCapability && statusCapability.get('editing')
&& editorCapability && editorCapability.dirty();
};
DomainColumn.prototype.getValue = function (domainObject, datum) {
return {
text: this.telemetryFormatter.formatDomainValue(
datum[this.domainMetadata.key],
this.domainMetadata.format
)
};
/**
* Allow navigation if an object is not dirty, or if the user elects
* to proceed anyway.
* @param currentNavigation
* @returns {boolean|*} true if the object model is clean; or if
* it's dirty and the user wishes to proceed anyway.
*/
EditNavigationPolicy.prototype.allow = function (currentNavigation) {
return !this.isDirty(currentNavigation);
};
return DomainColumn;
return EditNavigationPolicy;
}
);

View File

@@ -0,0 +1,52 @@
/*****************************************************************************
* 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 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;
if (key === 'link') {
return !((context.selectedObject || context.domainObject)
.hasCapability('editor'));
}
// 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')) {
return !!selectedObject && selectedObject.hasCapability('editor');
}
// Like all policies, allow by default.
return true;
};
return EditableMovePolicy;
});

View File

@@ -49,6 +49,7 @@ define(
var self = this;
this.scope = scope;
this.listenHandle = undefined;
// Mutate and persist a new version of a domain object's model.
function doPersist(model) {
@@ -100,10 +101,18 @@ define(
// Place the "commit" method in the scope
scope.commit = commit;
scope.setEditable = setEditable;
// Clean up when the scope is destroyed
scope.$on("$destroy", function () {
self.destroy();
});
}
// Handle a specific representation of a specific domain object
EditRepresenter.prototype.represent = function represent(representation, representedObject) {
var scope = this.scope,
self = this;
// Track the key, to know which view configuration to save to.
this.key = (representation || {}).key;
// Track the represented object
@@ -111,11 +120,32 @@ define(
// Ensure existing watches are released
this.destroy();
function setEditing(){
scope.viewObjectTemplate = 'edit-object';
}
/**
* Listen for changes in object state. If the object becomes
* editable then change the view and inspector regions
* object representation accordingly
*/
this.listenHandle = this.domainObject.getCapability('status').listen(function(statuses){
if (statuses.indexOf('editing')!=-1){
setEditing();
} else {
delete scope.viewObjectTemplate;
}
});
if (representedObject.getCapability('status').get('editing')){
setEditing();
}
};
// Respond to the destruction of the current representation.
EditRepresenter.prototype.destroy = function destroy() {
// Nothing to clean up
return this.listenHandle && this.listenHandle();
};
return EditRepresenter;

View File

@@ -27,11 +27,11 @@ define(
"use strict";
describe("The Save action", function () {
var mockLocation,
mockDomainObject,
var mockDomainObject,
mockEditorCapability,
mockUrlService,
actionContext,
mockActionCapability,
capabilities = {},
action;
function mockPromise(value) {
@@ -43,65 +43,62 @@ define(
}
beforeEach(function () {
mockLocation = jasmine.createSpyObj(
"$location",
[ "path" ]
);
mockDomainObject = jasmine.createSpyObj(
"domainObject",
[ "getCapability", "hasCapability" ]
[
"getCapability",
"hasCapability",
"getModel",
"getOriginalObject"
]
);
mockEditorCapability = jasmine.createSpyObj(
"editor",
[ "save", "cancel" ]
);
mockUrlService = jasmine.createSpyObj(
"urlService",
["urlForLocation"]
mockActionCapability = jasmine.createSpyObj(
"actionCapability",
[ "perform"]
);
capabilities.editor = mockEditorCapability;
capabilities.action = mockActionCapability;
actionContext = {
domainObject: mockDomainObject
};
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andReturn(mockEditorCapability);
mockDomainObject.getCapability.andCallFake(function (capability) {
return capabilities[capability];
});
mockDomainObject.getModel.andReturn({persisted: 0});
mockEditorCapability.save.andReturn(mockPromise(true));
mockDomainObject.getOriginalObject.andReturn(mockDomainObject);
action = new SaveAction(mockLocation, mockUrlService, actionContext);
action = new SaveAction(actionContext);
});
it("only applies to domain object with an editor capability", function () {
expect(SaveAction.appliesTo(actionContext)).toBeTruthy();
expect(SaveAction.appliesTo(actionContext)).toBe(true);
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
mockDomainObject.hasCapability.andReturn(false);
mockDomainObject.getCapability.andReturn(undefined);
expect(SaveAction.appliesTo(actionContext)).toBeFalsy();
expect(SaveAction.appliesTo(actionContext)).toBe(false);
});
//TODO: Disabled for NEM Beta
xit("invokes the editor capability's save functionality when performed", function () {
// Verify precondition
expect(mockEditorCapability.save).not.toHaveBeenCalled();
action.perform();
// Should have called cancel
expect(mockEditorCapability.save).toHaveBeenCalled();
// Also shouldn't call cancel
expect(mockEditorCapability.cancel).not.toHaveBeenCalled();
it("only applies to domain object that has already been persisted",
function () {
mockDomainObject.getModel.andReturn({persisted: undefined});
expect(SaveAction.appliesTo(actionContext)).toBe(false);
});
//TODO: Disabled for NEM Beta
xit("returns to browse when performed", function () {
action.perform();
expect(mockLocation.path).toHaveBeenCalledWith(
mockUrlService.urlForLocation("browse", mockDomainObject)
);
});
it("uses the editor capability to save the object",
function () {
action.perform();
expect(mockEditorCapability.save).toHaveBeenCalled();
});
});
}
);

View File

@@ -0,0 +1,174 @@
/*****************************************************************************
* 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/actions/SaveAsAction"],
function (SaveAsAction) {
"use strict";
describe("The Save As action", function () {
var mockDomainObject,
mockEditorCapability,
mockActionCapability,
mockObjectService,
mockDialogService,
mockCopyService,
mockParent,
mockUrlService,
actionContext,
capabilities = {},
action;
function noop () {}
function mockPromise(value) {
return (value || {}).then ? value :
{
then: function (callback) {
return mockPromise(callback(value));
},
catch: function (callback) {
return mockPromise(callback(value));
}
} ;
}
beforeEach(function () {
mockDomainObject = jasmine.createSpyObj(
"domainObject",
[
"getCapability",
"hasCapability",
"getModel"
]
);
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andCallFake(function (capability) {
return capabilities[capability];
});
mockDomainObject.getModel.andReturn({location: 'a', persisted: undefined});
mockParent = jasmine.createSpyObj(
"parentObject",
[
"getCapability",
"hasCapability",
"getModel"
]
);
mockEditorCapability = jasmine.createSpyObj(
"editor",
[ "save", "cancel" ]
);
mockEditorCapability.cancel.andReturn(mockPromise(undefined));
mockEditorCapability.save.andReturn(mockPromise(true));
capabilities.editor = mockEditorCapability;
mockActionCapability = jasmine.createSpyObj(
"action",
["perform"]
);
capabilities.action = mockActionCapability;
mockObjectService = jasmine.createSpyObj(
"objectService",
["getObjects"]
);
mockObjectService.getObjects.andReturn(mockPromise({'a': mockParent}));
mockDialogService = jasmine.createSpyObj(
"dialogService",
[
"getUserInput"
]
);
mockDialogService.getUserInput.andReturn(mockPromise(undefined));
mockCopyService = jasmine.createSpyObj(
"copyService",
[
"perform"
]
);
mockUrlService = jasmine.createSpyObj(
"urlService",
["urlForLocation"]
);
actionContext = {
domainObject: mockDomainObject
};
action = new SaveAsAction(undefined, undefined, mockDialogService, undefined, mockCopyService, actionContext);
spyOn(action, "getObjectService");
action.getObjectService.andReturn(mockObjectService);
spyOn(action, "createWizard");
action.createWizard.andReturn({
getFormStructure: noop,
getInitialFormValue: noop,
populateObjectFromInput: function() {
return mockDomainObject;
}
});
});
it("only applies to domain object with an editor capability", function () {
expect(SaveAsAction.appliesTo(actionContext)).toBe(true);
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
mockDomainObject.hasCapability.andReturn(false);
mockDomainObject.getCapability.andReturn(undefined);
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
});
it("only applies to domain object that has not already been" +
" persisted", function () {
expect(SaveAsAction.appliesTo(actionContext)).toBe(true);
expect(mockDomainObject.hasCapability).toHaveBeenCalledWith("editor");
mockDomainObject.getModel.andReturn({persisted: 0});
expect(SaveAsAction.appliesTo(actionContext)).toBe(false);
});
it("returns to browse after save", function () {
spyOn(action, "save");
action.save.andReturn(mockPromise(mockDomainObject));
action.perform();
expect(mockActionCapability.perform).toHaveBeenCalledWith(
"navigate"
);
});
it("prompts the user for object details", function () {
action.perform();
expect(mockDialogService.getUserInput).toHaveBeenCalled();
});
});
}
);

View File

@@ -22,102 +22,110 @@
/*global define,describe,it,expect,beforeEach,jasmine*/
define(
["../../src/controllers/EditController"],
function (EditController) {
["../../src/controllers/EditObjectController"],
function (EditObjectController) {
"use strict";
describe("The Edit mode controller", function () {
var mockScope,
mockQ,
mockNavigationService,
mockObject,
mockType,
mockLocation,
mockStatusCapability,
mockCapabilities,
mockPolicyService,
controller;
// Utility function; look for a $watch on scope and fire it
function fireWatch(expr, value) {
mockScope.$watch.calls.forEach(function (call) {
if (call.args[0] === expr) {
call.args[1](value);
}
});
}
beforeEach(function () {
mockPolicyService = jasmine.createSpyObj(
"policyService",
[
"allow"
]
);
mockScope = jasmine.createSpyObj(
"$scope",
[ "$on" ]
);
mockQ = jasmine.createSpyObj('$q', ['when', 'all']);
mockNavigationService = jasmine.createSpyObj(
"navigationService",
[ "getNavigation", "addListener", "removeListener" ]
[ "$on", "$watch" ]
);
mockObject = jasmine.createSpyObj(
"domainObject",
[ "getId", "getModel", "getCapability", "hasCapability" ]
[ "getId", "getModel", "getCapability", "hasCapability", "useCapability" ]
);
mockType = jasmine.createSpyObj(
"type",
[ "hasFeature" ]
);
mockStatusCapability = jasmine.createSpyObj('statusCapability',
["get"]
);
mockCapabilities = {
"type" : mockType,
"status": mockStatusCapability
};
mockLocation = jasmine.createSpyObj('$location',
["search"]
);
mockLocation.search.andReturn({"view": "fixed"});
mockNavigationService.getNavigation.andReturn(mockObject);
mockObject.getId.andReturn("test");
mockObject.getModel.andReturn({ name: "Test object" });
mockObject.getCapability.andCallFake(function (key) {
return key === 'type' && mockType;
return mockCapabilities[key];
});
mockType.hasFeature.andReturn(true);
controller = new EditController(
mockScope.domainObject = mockObject;
controller = new EditObjectController(
mockScope,
mockQ,
mockNavigationService
mockLocation,
mockPolicyService
);
});
it("exposes the currently-navigated object", function () {
expect(controller.navigatedObject()).toBeDefined();
expect(controller.navigatedObject().getId()).toEqual("test");
});
it("adds an editor capability to the navigated object", function () {
// Should provide an editor capability...
expect(controller.navigatedObject().getCapability("editor"))
.toBeDefined();
// Shouldn't have been the mock capability we provided
expect(controller.navigatedObject().getCapability("editor"))
.not.toEqual(mockType);
});
it("detaches its navigation listener when destroyed", function () {
var navCallback = mockNavigationService
.addListener.mostRecentCall.args[0];
expect(mockScope.$on).toHaveBeenCalledWith(
"$destroy",
jasmine.any(Function)
);
// Verify precondition
expect(mockNavigationService.removeListener)
.not.toHaveBeenCalled();
// Trigger destroy
mockScope.$on.mostRecentCall.args[1]();
// Listener should have been removed
expect(mockNavigationService.removeListener)
.toHaveBeenCalledWith(navCallback);
});
it("exposes a warning message for unload", function () {
var obj = controller.navigatedObject(),
mockEditor = jasmine.createSpyObj('editor', ['dirty']);
var obj = mockObject,
errorMessage = "Unsaved changes";
// Normally, should be undefined
expect(controller.getUnloadWarning()).toBeUndefined();
// Override the object's editor capability, make it look
// like there are unsaved changes.
obj.getCapability = jasmine.createSpy();
obj.getCapability.andReturn(mockEditor);
mockEditor.dirty.andReturn(true);
// Override the policy service to prevent navigation
mockPolicyService.allow.andCallFake(function(category, object, context, callback){
callback(errorMessage);
});
// Should have some warning message here now
expect(controller.getUnloadWarning()).toEqual(jasmine.any(String));
expect(controller.getUnloadWarning()).toEqual(errorMessage);
});
it("sets the active view from query parameters", function () {
var testViews = [
{ key: 'abc' },
{ key: 'def', someKey: 'some value' },
{ key: 'xyz' }
];
mockObject.useCapability.andCallFake(function (c) {
return (c === 'view') && testViews;
});
mockLocation.search.andReturn({ view: 'def' });
fireWatch('domainObject', mockObject);
expect(mockScope.representation.selected)
.toEqual(testViews[1]);
});
});

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,109 @@
/*****************************************************************************
* 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,
editModeBlacklist = ["copy", "follow", "window", "link", "locate"],
nonEditContextBlacklist = ["copy", "follow", "properties", "move", "link", "remove", "locate"];
beforeEach(function () {
navigatedObject = jasmine.createSpyObj("navigatedObject", ["hasCapability"]);
navigatedObject.hasCapability.andReturn(false);
mockDomainObject = jasmine.createSpyObj("domainObject", ["hasCapability", "getCapability"]);
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, editModeBlacklist, nonEditContextBlacklist);
});
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('Allows "remove" action when navigated object in edit mode,' +
' and selected object not editable, but its parent is.',
function() {
var mockParent = jasmine.createSpyObj("parentObject", ["hasCapability"]),
mockContextCapability = jasmine.createSpyObj("contextCapability", ["getParent"]);
mockParent.hasCapability.andReturn(true);
mockContextCapability.getParent.andReturn(mockParent);
navigatedObject.hasCapability.andReturn(true);
mockDomainObject.getCapability.andReturn(mockContextCapability);
mockDomainObject.hasCapability.andCallFake(function (capability) {
switch (capability) {
case "editor": return false;
case "context": return true;
}
});
metadata.key = "remove";
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

@@ -33,6 +33,8 @@ define(
testRepresentation,
mockDomainObject,
mockPersistence,
mockStatusCapability,
mockCapabilities,
representer;
function mockPromise(value) {
@@ -46,7 +48,7 @@ define(
beforeEach(function () {
mockQ = { when: mockPromise };
mockLog = jasmine.createSpyObj("$log", ["info", "debug"]);
mockScope = jasmine.createSpyObj("$scope", ["$watch"]);
mockScope = jasmine.createSpyObj("$scope", ["$watch", "$on"]);
testRepresentation = { key: "test" };
mockDomainObject = jasmine.createSpyObj("domainObject", [
"getId",
@@ -57,11 +59,20 @@ define(
]);
mockPersistence =
jasmine.createSpyObj("persistence", ["persist"]);
mockStatusCapability =
jasmine.createSpyObj("statusCapability", ["get", "listen"]);
mockStatusCapability.get.andReturn(false);
mockCapabilities = {
'persistence': mockPersistence,
'status': mockStatusCapability
};
mockDomainObject.getModel.andReturn({});
mockDomainObject.hasCapability.andReturn(true);
mockDomainObject.useCapability.andReturn(true);
mockDomainObject.getCapability.andReturn(mockPersistence);
mockDomainObject.getCapability.andCallFake(function(capability){
return mockCapabilities[capability];
});
representer = new EditRepresenter(mockQ, mockLog, mockScope);
representer.represent(testRepresentation, mockDomainObject);
@@ -71,6 +82,17 @@ define(
expect(mockScope.commit).toEqual(jasmine.any(Function));
});
it("Sets edit view template on edit mode", function () {
mockStatusCapability.listen.mostRecentCall.args[0](['editing']);
expect(mockScope.viewObjectTemplate).toEqual('edit-object');
});
it("Cleans up listeners on scope destroy", function () {
representer.listenHandle = jasmine.createSpy('listen');
mockScope.$on.mostRecentCall.args[1]();
expect(representer.listenHandle).toHaveBeenCalled();
});
it("mutates and persists upon observed changes", function () {
mockScope.model = { someKey: "some value" };
mockScope.configuration = { someConfiguration: "something" };
@@ -101,4 +123,4 @@ define(
});
}
);
);

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

@@ -24,6 +24,7 @@
define([
"./src/services/UrlService",
"./src/services/PopupService",
"./src/SplashScreenManager",
"./src/StyleSheetLoader",
"./src/UnsupportedBrowserWarning",
"./src/controllers/TimeRangeController",
@@ -48,10 +49,31 @@ 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",
"text!./res/templates/indicator.html",
"text!./res/templates/message-banner.html",
"text!./res/templates/progress-bar.html",
"text!./res/templates/controls/time-controller.html",
"text!./res/templates/containers/accordion.html",
"text!./res/templates/subtree.html",
"text!./res/templates/tree.html",
"text!./res/templates/tree-node.html",
"text!./res/templates/label.html",
"text!./res/templates/controls/action-group.html",
"text!./res/templates/menu/context-menu.html",
"text!./res/templates/controls/switcher.html",
"text!./res/templates/object-inspector.html",
"text!./res/templates/controls/selector.html",
"text!./res/templates/controls/datetime-picker.html",
"text!./res/templates/controls/datetime-field.html",
'legacyRegistry'
], function (
UrlService,
PopupService,
SplashScreenManager,
StyleSheetLoader,
UnsupportedBrowserWarning,
TimeRangeController,
@@ -76,6 +98,26 @@ define([
MCTScroll,
MCTSplitPane,
MCTSplitter,
MCTTree,
bottombarTemplate,
actionButtonTemplate,
inputFilterTemplate,
indicatorTemplate,
messageBannerTemplate,
progressBarTemplate,
timeControllerTemplate,
accordionTemplate,
subtreeTemplate,
treeTemplate,
treeNodeTemplate,
labelTemplate,
actionGroupTemplate,
contextMenuTemplate,
switcherTemplate,
objectInspectorTemplate,
selectorTemplate,
datetimePickerTemplate,
datetimeFieldTemplate,
legacyRegistry
) {
"use strict";
@@ -117,6 +159,12 @@ define([
"notificationService",
"agentService"
]
},
{
"implementation": SplashScreenManager,
"depends": [
"$document"
]
}
],
"filters": [
@@ -134,31 +182,31 @@ define([
"templates": [
{
"key": "bottombar",
"templateUrl": "templates/bottombar.html"
"template": bottombarTemplate
},
{
"key": "action-button",
"templateUrl": "templates/controls/action-button.html"
"template": actionButtonTemplate
},
{
"key": "input-filter",
"templateUrl": "templates/controls/input-filter.html"
"template": inputFilterTemplate
},
{
"key": "indicator",
"templateUrl": "templates/indicator.html"
"template": indicatorTemplate
},
{
"key": "message-banner",
"templateUrl": "templates/message-banner.html"
"template": messageBannerTemplate
},
{
"key": "progress-bar",
"templateUrl": "templates/progress-bar.html"
"template": progressBarTemplate
},
{
"key": "time-controller",
"templateUrl": "templates/controls/time-controller.html"
"template": timeControllerTemplate
}
],
"controllers": [
@@ -339,6 +387,11 @@ define([
{
"key": "mctSplitter",
"implementation": MCTSplitter
},
{
"key": "mctTree",
"implementation": MCTTree,
"depends": [ '$parse', 'gestureService' ]
}
],
"constants": [
@@ -367,7 +420,7 @@ define([
"containers": [
{
"key": "accordion",
"templateUrl": "templates/containers/accordion.html",
"template": accordionTemplate,
"attributes": [
"label"
]
@@ -376,7 +429,7 @@ define([
"representations": [
{
"key": "tree",
"templateUrl": "templates/subtree.html",
"template": subtreeTemplate,
"uses": [
"composition"
],
@@ -385,25 +438,25 @@ define([
},
{
"key": "tree",
"templateUrl": "templates/tree.html"
"template": treeTemplate
},
{
"key": "subtree",
"templateUrl": "templates/subtree.html",
"template": subtreeTemplate,
"uses": [
"composition"
]
},
{
"key": "tree-node",
"templateUrl": "templates/tree-node.html",
"template": treeNodeTemplate,
"uses": [
"action"
]
},
{
"key": "label",
"templateUrl": "templates/label.html",
"template": labelTemplate,
"uses": [
"type",
"location"
@@ -416,7 +469,7 @@ define([
},
{
"key": "node",
"templateUrl": "templates/label.html",
"template": labelTemplate,
"uses": [
"type"
],
@@ -427,55 +480,45 @@ define([
},
{
"key": "action-group",
"templateUrl": "templates/controls/action-group.html",
"template": actionGroupTemplate,
"uses": [
"action"
]
},
{
"key": "context-menu",
"templateUrl": "templates/menu/context-menu.html",
"template": contextMenuTemplate,
"uses": [
"action"
]
},
{
"key": "switcher",
"templateUrl": "templates/controls/switcher.html",
"template": switcherTemplate,
"uses": [
"view"
]
},
{
"key": "object-inspector",
"templateUrl": "templates/object-inspector.html"
"template": objectInspectorTemplate
}
],
"controls": [
{
"key": "selector",
"templateUrl": "templates/controls/selector.html"
"template": selectorTemplate
},
{
"key": "datetime-picker",
"templateUrl": "templates/controls/datetime-picker.html"
"template": datetimePickerTemplate
},
{
"key": "datetime-field",
"templateUrl": "templates/controls/datetime-field.html"
"template": datetimeFieldTemplate
}
],
"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",
@@ -485,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"
}
]
}

View File

@@ -0,0 +1,48 @@
/* http://meyerweb.com/eric/tools/css/reset/
v2.0 | 20110126
License: none (public domain)
*/
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
margin: 0;
padding: 0;
border: 0;
font-size: 100%;
font: inherit;
vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
display: block;
}
body {
line-height: 1;
}
ol, ul {
list-style: none;
}
blockquote, q {
quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
content: '';
content: none;
}
table {
border-collapse: collapse;
border-spacing: 0;
}

File diff suppressed because one or more lines are too long

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