mirror of
https://github.com/nasa/openmct.git
synced 2025-01-29 15:43:52 +00:00
Merge remote-tracking branch 'github/master' into open245b
...in preparation to complete merge nasa/openmctweb#257 Conflicts: platform/entanglement/src/actions/CopyAction.js platform/entanglement/src/actions/LinkAction.js platform/entanglement/src/actions/MoveAction.js
This commit is contained in:
commit
7974ffdda2
@ -30,6 +30,7 @@
|
||||
"platform/policy",
|
||||
"platform/entanglement",
|
||||
"platform/search",
|
||||
"platform/status",
|
||||
|
||||
"example/imagery",
|
||||
"example/eventGenerator",
|
||||
|
@ -1288,6 +1288,22 @@ object, or the current view proxy.
|
||||
* `all()`: Get an array of all objects in the selection state. Will include
|
||||
either or both of the view proxy and selected object.
|
||||
|
||||
## Workers Category
|
||||
|
||||
The `workers` extension category allows scripts to be run as web workers
|
||||
using the `workerService`.
|
||||
|
||||
An extension of this category has no implementation. The following properties
|
||||
are supported:
|
||||
|
||||
* `key`: A symbolic string used to identify this worker.
|
||||
* `workerUrl`: The path, relative to this bundle's `src` folder, where
|
||||
this worker's source code resides.
|
||||
* `shared`: Optional; a boolean flag which, if true, indicates that this
|
||||
worker should be instantiated as a
|
||||
[`SharedWorker`](https://developer.mozilla.org/en-US/docs/Web/API/SharedWorker/SharedWorker).
|
||||
Default value is `false`.
|
||||
|
||||
# Directives
|
||||
|
||||
Open MCT Web defines several Angular directives that are intended for use both
|
||||
@ -1883,6 +1899,14 @@ the TelemetrySeries itself, in that order.
|
||||
* `getSeries(domainObject)`: Get the latest `TelemetrySeries` (as resulted from
|
||||
a previous `request(...)` call) available for this domain object.
|
||||
|
||||
### Worker Service
|
||||
|
||||
The `workerService` may be used to run web workers defined via the
|
||||
`workers` extension category. It has the following method:
|
||||
|
||||
* `run(key)`: Run the worker identified by the provided `key`. Returns
|
||||
a `Worker` (or `SharedWorker`, if the specified worker is defined
|
||||
as a shared worker); if the `key` is unknown, returns `undefined`.
|
||||
|
||||
# Models
|
||||
Domain object models in Open MCT Web are JavaScript objects describing the
|
||||
@ -2090,6 +2114,31 @@ objects which has a `relationships` property in their model, whose value is an
|
||||
object containing key-value pairs, where keys are strings identifying
|
||||
relationship types, and values are arrays of domain object identifiers.
|
||||
|
||||
## Status Capability
|
||||
|
||||
The `status` capability provides a way to flag domain objects as possessing
|
||||
certain states, represented as simple strings. These states, in turn, are
|
||||
reflected on `mct-representation` elements as classes (prefixed with
|
||||
`s-status-`.) The `status` capability has the following interface:
|
||||
|
||||
* `get()`: Returns an array of all status strings that currently apply
|
||||
to this object.
|
||||
* `set(status, state)`: Adds or removes a status flag to this domain object.
|
||||
The `status` argument is the string to set; `state` is a boolean
|
||||
indicating whether this status should be included (true) or removed (false).
|
||||
* `listen(callback)`: Listen for changes in status. The provided `callback`
|
||||
will be invoked with an array of all current status strings whenever status
|
||||
changes.
|
||||
|
||||
Plug-ins may add and/or recognize arbitrary status flags. Flags defined
|
||||
and/or supported by the platform are:
|
||||
|
||||
Status | CSS Class | Meaning
|
||||
-----------|--------------------|-----------------------------------
|
||||
`editing` | `s-status-editing` | Domain object is being edited.
|
||||
`pending` | `s-status-pending` | Domain object is partially loaded.
|
||||
|
||||
|
||||
## Telemetry Capability
|
||||
|
||||
The telemetry capability provides a means for accessing telemetry data
|
||||
|
@ -32,6 +32,7 @@
|
||||
<li><a href="architecture/">Architecture Overview</a></li>
|
||||
<li><a href="guide/">Developer Guide</a></li>
|
||||
<li><a href="tutorials/">Tutorials</a></li>
|
||||
<li><a href="process/">Development Process</a></li>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
156
docs/src/process/index.md
Normal file
156
docs/src/process/index.md
Normal file
@ -0,0 +1,156 @@
|
||||
# Development Cycle
|
||||
|
||||
Development of Open MCT Web occurs on an iterative cycle of
|
||||
sprints and releases.
|
||||
|
||||
* A _sprint_ is three weeks in duration, and represents a
|
||||
set of improvements that can be completed and tested by the
|
||||
development team. Software at the end of the sprint is
|
||||
"semi-stable"; it will have undergone reduced testing and may carry
|
||||
defects or usability issues of lower severity, particularly if
|
||||
there are workarounds.
|
||||
* A _release_ occurs every four sprints. Releases are stable, and
|
||||
will have undergone full acceptance testing to ensure that the
|
||||
software behaves correctly and usably.
|
||||
|
||||
## Roles
|
||||
|
||||
The sprint process assumes the presence of a __project manager.__
|
||||
The project manager is responsible for
|
||||
making tactical decisions about what development work will be
|
||||
performed, and for coordinating with stakeholders to arrive at
|
||||
higher-level strategic decisions about desired functionality
|
||||
and characteristics of the software, major external milestones,
|
||||
and so forth.
|
||||
|
||||
In the absence of a dedicated project manager, this role may be rotated
|
||||
among members of the development team on a per-sprint basis.
|
||||
|
||||
Responsibilities of the project manager including:
|
||||
|
||||
* Maintaining (with agreement of stakeholders) a "road map" of work
|
||||
planned for future releases/sprints; this should be higher-level,
|
||||
usually expressed as "themes",
|
||||
with just enough specificity to gauge feasibility of plans,
|
||||
relate work back to milestones, and identify longer-term
|
||||
dependencies.
|
||||
* Determining (with assistance from the rest of the team) which
|
||||
issues to work on in a given sprint and how they shall be
|
||||
assigned.
|
||||
* Pre-planning subsequent sprints to ensure that all members of the
|
||||
team always have a clear direction.
|
||||
* Scheduling and/or ensuring adherence to
|
||||
[process points](#process-points).
|
||||
* Responding to changes within the sprint (shifting priorities,
|
||||
new issues) and re-allocating work for the sprint as needed.
|
||||
|
||||
## Sprint Calendar
|
||||
|
||||
Certain [process points](#process-points) are regularly scheduled in
|
||||
the sprint cycle.
|
||||
|
||||
### Sprints by Release
|
||||
|
||||
Allocation of work among sprints should be planned relative to release
|
||||
goals and milestones. As a general guideline, higher-risk work (large
|
||||
new features which may carry new defects, major refactoring, design
|
||||
changes with uncertain effects on usability) should be allocated to
|
||||
earlier sprints, allowing for time in later sprints to ensure stability.
|
||||
|
||||
| Sprint | Focus |
|
||||
|:------:|:--------------------------------------------------------|
|
||||
| __1__ | Prototyping, design, experimentation. |
|
||||
| __2__ | New features, refinements, enhancements. |
|
||||
| __3__ | Feature completion, low-risk enhancements, bug fixing. |
|
||||
| __4__ | Stability & quality assurance. |
|
||||
|
||||
### Sprints 1-3
|
||||
|
||||
The first three sprints of a release are primarily centered around
|
||||
development work, with regular acceptance testing in the third
|
||||
week. During this third week, the top priority should be passing
|
||||
acceptance testing (e.g. by resolving any blockers found); any
|
||||
resources not needed for this effort should be used to begin work
|
||||
for the subsequent sprint.
|
||||
|
||||
| Week | Mon | Tue | Wed | Thu | Fri |
|
||||
|:-----:|:-------------------------:|:------:|:---:|:----------------------------:|:-----------:|
|
||||
| __1__ | Sprint plan | Tag-up | | | |
|
||||
| __2__ | | Tag-up | | | Code freeze |
|
||||
| __3__ | Sprint acceptance testing | Triage | | _Sprint acceptance testing*_ | Ship |
|
||||
|
||||
* If necessary.
|
||||
|
||||
### Sprint 4
|
||||
|
||||
The software must be stable at the end of the fourth sprint; because of
|
||||
this, the fourth sprint is scheduled differently, with a heightened
|
||||
emphasis on testing.
|
||||
|
||||
| Week | Mon | Tue | Wed | Thu | Fri |
|
||||
|-------:|:-------------------------:|:------:|:---:|:----------------------------:|:-----------:|
|
||||
| __1__ | Sprint plan | Tag-up | | | Code freeze |
|
||||
| __2__ | Acceptance testing | Triage | | | |
|
||||
| __3__ | _Acceptance testing*_ | Triage | | _Acceptance testing*_ | Ship |
|
||||
|
||||
* If necessary.
|
||||
|
||||
## Process Points
|
||||
|
||||
* __Sprint plan.__ Project manager allocates issues based on
|
||||
theme(s) for sprint, then reviews with team. Each team member
|
||||
should have roughly two weeks of work allocated (to allow time
|
||||
in the third week for testing of work completed.)
|
||||
* Project manager should also sketch out subsequent sprint so
|
||||
that team may begin work for that sprint during the
|
||||
third week, since testing and blocker resolution is unlikely
|
||||
to require all available resources.
|
||||
* __Tag-up.__ Check in and status update among development team.
|
||||
May amend plan for sprint as-needed.
|
||||
* __Code freeze.__ Any new work from this sprint
|
||||
(features, bug fixes, enhancements) must be integrated by the
|
||||
end of the second week of the sprint. After code freeze
|
||||
(and until the end of the sprint) the only changes that should be
|
||||
merged into the master branch should directly address issues
|
||||
needed to pass acceptance testing.
|
||||
* __Acceptance Testing.__ Structured testing with predefined
|
||||
success criteria. No release should ship without passing
|
||||
acceptance tests. Time is allocated in each sprint for subsequent
|
||||
rounds of acceptance testing if issues are identified during a
|
||||
prior round. Specific details of acceptance testing need to be
|
||||
agreed-upon with relevant stakeholders and delivery recipients,
|
||||
and should be flexible enough to allow changes to plans
|
||||
(e.g. deferring delivery of some feature in order to ensure
|
||||
stability of other features.) Baseline testing includes:
|
||||
* __Testathon.__ Multi-user testing, involving as many users as
|
||||
is feasible, plus development team. Open-ended; should verify
|
||||
completed work from this sprint, test exploratorily for
|
||||
regressions, et cetera.
|
||||
* __24-Hour Test.__ A test to verify that the software remains
|
||||
stable after running for longer durations. May include some
|
||||
combination of automated testing and user verification (e.g.
|
||||
checking to verify that software remains subjectively
|
||||
responsive at conclusion of test.)
|
||||
* __Automated Testing.__ Automated testing integrated into the
|
||||
build. (These tests are verified to pass more often than once
|
||||
per sprint, as they run before any merge to master, but still
|
||||
play an important role in acceptance testing.)
|
||||
* __Sprint Acceptance Testing.__ Subset of Acceptance Testing
|
||||
which should be performed before shipping at the end of any
|
||||
sprint. Time is allocated for a second round of
|
||||
Sprint Acceptance Testing if the first round is not passed.
|
||||
* __Triage.__ Team reviews issues from acceptance testing and uses
|
||||
success criteria to determine whether or not they should block
|
||||
release, then formulates a plan to address these issues before
|
||||
the next round of acceptance testing. Focus here should be on
|
||||
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
|
||||
been passed, will need to make ad hoc decisions with stakeholders,
|
||||
e.g. "extend the sprint" or "defer shipment until end of next
|
||||
sprint.")
|
||||
|
||||
|
@ -62,7 +62,7 @@ define(
|
||||
// so it's not checked for here, just formatted for display
|
||||
// differently.
|
||||
return (i + offset) * 1000 + firstTime * 1000 -
|
||||
(domain === 'yesterday' ? ONE_DAY : 0);
|
||||
(domain === 'yesterday' ? (ONE_DAY * 1000) : 0);
|
||||
};
|
||||
|
||||
generatorData.getRangeValue = function (i, range) {
|
||||
|
12
example/mobile/bundle.json
Normal file
12
example/mobile/bundle.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "Mobile",
|
||||
"description": "Allows elements with pertinence to mobile usage and development",
|
||||
"extensions": {
|
||||
"stylesheets": [
|
||||
{
|
||||
"stylesheetUrl": "css/mobile-example.css",
|
||||
"priority": "mandatory"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
26
example/mobile/res/config.rb
Executable file
26
example/mobile/res/config.rb
Executable file
@ -0,0 +1,26 @@
|
||||
# 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
|
103
example/mobile/res/css/mobile-example.css
Normal file
103
example/mobile/res/css/mobile-example.css
Normal file
@ -0,0 +1,103 @@
|
||||
/*****************************************************************************
|
||||
* 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; } }
|
31
example/mobile/res/sass/mobile-example.scss
Normal file
31
example/mobile/res/sass/mobile-example.scss
Normal file
@ -0,0 +1,31 @@
|
||||
/*****************************************************************************
|
||||
* 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.
|
||||
*****************************************************************************/
|
||||
@import "../../../../platform/commonUI/general/res/sass/constants";
|
||||
@import "../../../../platform/commonUI/general/res/sass/mobile/constants";
|
||||
@import "../../../../platform/commonUI/general/res/sass/mobile/mixins";
|
||||
|
||||
@include phoneandtablet {
|
||||
// Show the Create button
|
||||
.create-btn-holder {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
@ -20,15 +20,17 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<span ng-controller="BrowseObjectController">
|
||||
<div class="object-browse-bar bar l-flex">
|
||||
<div class="items-select left">
|
||||
<div class="object-browse-bar l-flex-row">
|
||||
<div class="items-select left flex-elem l-flex-row grows">
|
||||
<mct-representation key="'back-arrow'"
|
||||
mct-object="domainObject"
|
||||
class="l-back"></mct-representation>
|
||||
<mct-representation key="'object-header'" 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>
|
||||
<div class="btn-bar right">
|
||||
<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">
|
||||
|
@ -28,30 +28,23 @@
|
||||
<mct-split-pane class='abs contents'
|
||||
anchor='left'>
|
||||
<div class='split-pane-component treeview pane left'>
|
||||
<!--<a class="mini-tab-icon anchor-left toggle-pane toggle-search mobile-hide"
|
||||
title="Enable search"
|
||||
ng-click="modelPaneTree.toggle()"
|
||||
ng-class="{ collapsed : !modelPaneTree.visible() }"
|
||||
ng-style="{ opacity: modelPaneTree.visible()? 0:1 }"></a>-->
|
||||
<div class="holder holder-create-and-search abs l-mobile">
|
||||
<div class="abs holder l-flex-col holder-treeview-elements">
|
||||
<mct-representation key="'create-button'"
|
||||
mct-object="navigatedObject"
|
||||
mct-device="desktop">
|
||||
class="holder flex-elem create-btn-holder">
|
||||
</mct-representation>
|
||||
<mct-include key="'search'"
|
||||
ng-model="treeModel"
|
||||
class="holder l-flex-col flex-elem search-holder"
|
||||
ng-class="{ active: treeModel.search, grows: treeModel.search }">
|
||||
</mct-include>
|
||||
<mct-representation key="'tree'"
|
||||
mct-object="domainObject"
|
||||
parameters="tree"
|
||||
ng-model="treeModel"
|
||||
class="holder flex-elem grows vscroll tree-holder"
|
||||
ng-hide="treeModel.search">
|
||||
</mct-representation>
|
||||
<div class='holder search-holder abs'
|
||||
ng-class="{active: treeModel.search}">
|
||||
<mct-include key="'search'"
|
||||
ng-model="treeModel">
|
||||
</mct-include>
|
||||
</div>
|
||||
<div class='tree-holder abs mobile-tree-holder'
|
||||
ng-hide="treeModel.search">
|
||||
<mct-representation key="'tree'"
|
||||
mct-object="domainObject"
|
||||
parameters="tree"
|
||||
ng-model="treeModel">
|
||||
</mct-representation>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -63,7 +56,7 @@
|
||||
ng-click="modelPaneTree.toggle()"
|
||||
ng-class="{ collapsed : !modelPaneTree.visible() }"></a>
|
||||
|
||||
<div class='holder holder-object-and-inspector abs l-mobile' id='content-area'
|
||||
<div class='holder holder-object-and-inspector abs' id='content-area'
|
||||
ng-controller="PaneController as modelPaneInspect"
|
||||
ng-class="modelPaneInspect.visible() ? 'pane-inspect-showing' : 'pane-inspect-hidden'">
|
||||
|
||||
|
@ -19,12 +19,12 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class='object-header'>
|
||||
<span class='type-icon ui-symbol'>{{type.getGlyph()}}</span>
|
||||
<!--span class='type-name mobile-important-hide'>{{type.getName()}}</span-->
|
||||
<span class="l-elem-wrapper l-flex">
|
||||
<span ng-if="parameters.mode" class='action'>{{parameters.mode}}</span>
|
||||
<span class='title-label'>{{model.name}}</span>
|
||||
<mct-representation key="'menu-arrow'" mct-object='domainObject'></mct-representation>
|
||||
</span>
|
||||
</div>
|
||||
<span class='type-icon ui-symbol flex-elem'>{{type.getGlyph()}}</span>
|
||||
<span class="l-elem-wrapper l-flex-row flex-elem grows">
|
||||
<span ng-if="parameters.mode" class='action flex-elem'>{{parameters.mode}}</span>
|
||||
<span class='title-label flex-elem flex-can-shrink'>{{model.name}}</span>
|
||||
<mct-representation
|
||||
key="'menu-arrow'"
|
||||
mct-object='domainObject'
|
||||
class="flex-elem"></mct-representation>
|
||||
</span>
|
@ -22,7 +22,8 @@
|
||||
<div class='top-bar edit abs'>
|
||||
<mct-representation key="'object-header'"
|
||||
mct-object="domainObject"
|
||||
parameters="{ mode: 'Edit' }">
|
||||
parameters="{ mode: 'Edit' }"
|
||||
class="l-flex-row flex-elem grows object-header">
|
||||
</mct-representation>
|
||||
<div class='buttons-main btn-bar buttons abs'>
|
||||
<mct-representation key="'switcher'"
|
||||
|
@ -36,7 +36,6 @@
|
||||
.col {
|
||||
@include box-sizing(border-box);
|
||||
@include clearfix;
|
||||
// background: rgba(#ffcc00, 0.2);
|
||||
float: left;
|
||||
margin-left: $ueColMargin;
|
||||
padding-left: $interiorMargin;
|
||||
@ -98,22 +97,51 @@
|
||||
@include display-flex;
|
||||
@include flex-wrap(nowrap);
|
||||
.flex-elem {
|
||||
min-height: 0; // Needed to allow element to shrink within parent
|
||||
position: relative;
|
||||
&:not(.grows) {
|
||||
@include flex(0 1 auto);
|
||||
@include flex(0 0 auto);
|
||||
&.flex-can-shrink {
|
||||
@include flex(0 1 auto);
|
||||
}
|
||||
}
|
||||
&.grows {
|
||||
@include flex(1 1 auto);
|
||||
}
|
||||
}
|
||||
.flex-container {
|
||||
// Apply to wrapping elements, mct-includes, etc.
|
||||
@include display-flex;
|
||||
@include flex-wrap(nowrap);
|
||||
@include flex(1 1 auto);
|
||||
min-height:0;
|
||||
}
|
||||
}
|
||||
|
||||
.l-flex-row { @include flex-direction(row); }
|
||||
.l-flex-col { @include flex-direction(column); }
|
||||
|
||||
.l-flex {
|
||||
@extend .l-flex-row;
|
||||
.left {
|
||||
@include flex(1 1 0);
|
||||
padding-right: $interiorMarginLg;
|
||||
.l-flex-row {
|
||||
@include flex-direction(row);
|
||||
&.flex-elem { @include flex(1 1 auto); }
|
||||
.flex-elem {
|
||||
height: inherit;
|
||||
line-height: inherit;
|
||||
min-width: 0;
|
||||
}
|
||||
.flex-container { @include flex-direction(row); }
|
||||
}
|
||||
|
||||
.l-flex-col {
|
||||
@include flex-direction(column);
|
||||
.flex-elem {
|
||||
min-height: 0;
|
||||
&.holder:not(:last-child) { margin-bottom: $interiorMarginLg; }
|
||||
}
|
||||
.flex-container { @include flex-direction(column); }
|
||||
}
|
||||
|
||||
.flex-fixed {
|
||||
@include flex(0 0 auto);
|
||||
}
|
||||
|
||||
.flex-justify-end {
|
||||
@include justify-content(flex-end);
|
||||
}
|
@ -35,15 +35,13 @@ $ltGamma: 20%;
|
||||
$btnFontSizeToH: 0.45;
|
||||
|
||||
/************************** LAYOUT */
|
||||
$ueTopBarH: 24px; // Change when breadcrumb is enabled
|
||||
$ueTopBarH: 24px;
|
||||
$ueTopBarEditH: 30px;
|
||||
$ueTopBarBtnH: 35px;
|
||||
$ueFooterH: 25px;
|
||||
$ueColMargin: 1.5%;
|
||||
$ueAppLogoW: 105px;
|
||||
$ueEditToolBarH: 25px;
|
||||
$ueBrowseLeftPaneTreeW: 25%;
|
||||
$ueBrowseRightPaneInspectW: 20%;
|
||||
$ueCollapsedPaneEdgeM: 22px;
|
||||
$uePaneMiniTabH: $ueTopBarH;
|
||||
$uePaneMiniTabW: 9px;
|
||||
@ -51,6 +49,15 @@ $uePaneMiniTabCollapsedW: 11px;
|
||||
$ueEditLeftPaneW: 75%;
|
||||
$treeSearchInputBarH: 25px;
|
||||
$ueTimeControlH: (33px, 20px, 20px);
|
||||
// Panes
|
||||
$ueBrowseLeftPaneTreeMinW: 150px;
|
||||
$ueBrowseLeftPaneTreeMaxW: 35%;
|
||||
$ueBrowseLeftPaneTreeW: 25%;
|
||||
$ueBrowseRightPaneInspectMinW: 200px;
|
||||
$ueBrowseRightPaneInspectMaxW: 35%;
|
||||
$ueBrowseRightPaneInspectW: 20%;
|
||||
$ueDesktopMinW: 600px;
|
||||
|
||||
// Overlay
|
||||
$ovrTopBarH: 45px;
|
||||
$ovrFooterH: 24px;
|
||||
|
@ -142,6 +142,16 @@ mct-container {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.off {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.sep {
|
||||
color: rgba(#fff, 0.2);
|
||||
}
|
@ -127,7 +127,6 @@ label.checkbox.custom {
|
||||
&:before {
|
||||
@include border-radius($basicCr * .75);
|
||||
background: $bg;
|
||||
//border-bottom: 1px solid lighten($bg, 10%);
|
||||
@include box-shadow(inset rgba(black, 0.4) 0 1px 2px);
|
||||
box-sizing: border-box;
|
||||
content: " ";
|
||||
@ -202,7 +201,6 @@ label.checkbox.custom {
|
||||
|
||||
/******************************************************** OBJECT-HEADER */
|
||||
.object-header {
|
||||
//@include test();
|
||||
font-size: 1em;
|
||||
|
||||
> .type-icon {
|
||||
@ -213,8 +211,6 @@ label.checkbox.custom {
|
||||
}
|
||||
|
||||
.l-elem-wrapper {
|
||||
//@include test(#66f, 0.2);
|
||||
@include justify-content(flex-start);
|
||||
mct-representation {
|
||||
// Holds the context-available item
|
||||
// Must have min-width to make flex work properly
|
||||
@ -228,19 +224,15 @@ label.checkbox.custom {
|
||||
}
|
||||
|
||||
.title-label {
|
||||
//@include test(green, 0.9);
|
||||
color: $colorObjHdrTxt;
|
||||
@include ellipsize();
|
||||
//color: pushBack($colorBodyFg, 40%);
|
||||
@include webkitProp(flex, '0 1 auto');
|
||||
padding-right: 0.35em; // For context arrow. Done with em's so pad is relative to the scale of the text.
|
||||
//position: relative;
|
||||
}
|
||||
|
||||
.context-available {
|
||||
font-size: 0.7em;
|
||||
@include webkitProp(flex, '0 0 1');
|
||||
//margin-right: $interiorMargin;
|
||||
}
|
||||
|
||||
@include desktop {
|
||||
@ -303,7 +295,6 @@ label.checkbox.custom {
|
||||
@include border-radius($basicCr);
|
||||
@include boxIncised(0.3, 4px);
|
||||
background: $colorProgressBarOuter;
|
||||
//border:1px solid $colorProgressBarOuter;
|
||||
.progress-amt {
|
||||
@include border-radius($basicCr);
|
||||
@include boxShdw();
|
||||
@ -343,8 +334,6 @@ label.checkbox.custom {
|
||||
.slider {
|
||||
$knobH: 100%; //14px;
|
||||
.slot {
|
||||
// @include border-radius($basicCr * .75);
|
||||
//@include sliderTrack();
|
||||
width: auto;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
@ -400,14 +389,11 @@ label.checkbox.custom {
|
||||
width: 230px;
|
||||
.l-month-year-pager {
|
||||
$pagerW: 20px;
|
||||
//@include test();
|
||||
//font-size: 0.8rem;
|
||||
height: $r1H;
|
||||
margin-bottom: $interiorMargin;
|
||||
position: relative;
|
||||
.pager,
|
||||
.val {
|
||||
//@include test(red);
|
||||
@extend .abs;
|
||||
}
|
||||
.pager {
|
||||
@ -454,7 +440,6 @@ label.checkbox.custom {
|
||||
}
|
||||
li {
|
||||
@include flex(1 0);
|
||||
//@include test();
|
||||
margin-left: 1px;
|
||||
padding: $interiorMargin;
|
||||
text-align: center;
|
||||
@ -512,8 +497,6 @@ label.checkbox.custom {
|
||||
@include background-image(linear-gradient(lighten($bg, $gr), $bg 20px));
|
||||
@include border-radius(2px);
|
||||
@include box-sizing(border-box);
|
||||
//@include boxShdwSubtle();
|
||||
//border-top: 1px solid lighten($bg, 20%);
|
||||
&:hover {
|
||||
@include background-image(linear-gradient(lighten($hc, $gr), $hc 20px));
|
||||
}
|
||||
|
@ -25,7 +25,6 @@
|
||||
margin: 0 0 2px 0; // Needed to avoid dropshadow from being clipped by parent containers
|
||||
}
|
||||
padding: 0 $interiorMargin;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
line-height: $formInputH;
|
||||
select {
|
||||
|
@ -29,7 +29,7 @@
|
||||
//@include test(red);
|
||||
display: block;
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
z-index: 3;
|
||||
&:after {
|
||||
// The handle
|
||||
content:"";
|
||||
@ -43,7 +43,6 @@
|
||||
}
|
||||
}
|
||||
&:active {
|
||||
//@include test();
|
||||
&:after {
|
||||
background-color: $colorSplitterActive !important;
|
||||
}
|
||||
@ -122,11 +121,3 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*.browse-area .splitter {
|
||||
top: 0; //$ueTopBarH + $interiorMarginLg;
|
||||
}
|
||||
|
||||
.edit-area .splitter {
|
||||
top: 0;
|
||||
}*/
|
||||
|
@ -20,6 +20,8 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
/* REQUIRES /platform/commonUI/general/res/sass/_constants.scss */
|
||||
|
||||
/************************** MOBILE REPRESENTATION ITEMS DIMENSIONS */
|
||||
$mobileListIconSize: 30px;
|
||||
$mobileTitleDescH: 35px;
|
||||
@ -32,51 +34,31 @@ $mobileTreeItemH: 35px;
|
||||
$mobileTreeItemIndent: 20px;
|
||||
$mobileTreeRightArrowW: 30px;
|
||||
|
||||
/************************** WINDOW DIMENSIONS FOR RWD */
|
||||
/************************** DEVICE WIDTHS */
|
||||
// IMPORTANT! Usage assumes that ranges are mutually exclusive and have no gaps
|
||||
$phoMaxW: 514px;
|
||||
$phoMaxH: 740px;
|
||||
|
||||
$tabMinW: 515px;
|
||||
$tabMaxW: 799px;
|
||||
|
||||
$tabMinH: 741px;
|
||||
$tabMaxH: 1024px;
|
||||
|
||||
$compMinW: 800px;
|
||||
$compMinH: 1025px;
|
||||
$tabMaxW: 1280px;
|
||||
$desktopMinW: 1281px;
|
||||
|
||||
/************************** MEDIA QUERIES: WINDOW CHECKS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
|
||||
$screenPortrait: "screen and (orientation: portrait)";
|
||||
$screenLandscape: "screen and (orientation: landscape)";
|
||||
|
||||
$mobileDevice: "(max-device-width: #{$tabMaxW}) and (max-device-height: #{$tabMaxH})";
|
||||
$mobileDeviceEmu: "(max-device-width: #{$tabMaxH}) and (max-device-height: #{$tabMaxW})";
|
||||
$mobileDevice: "(max-device-width: #{$tabMaxW})";
|
||||
|
||||
$phonePortraitCheck: "(max-width: #{$phoMaxW}) and (max-height: #{$phoMaxH})";
|
||||
$phoneLandscapeCheck: "(max-height: #{$phoMaxW}) and (max-width: #{$phoMaxH})";
|
||||
|
||||
$tabWidPorCheck: "(min-width: #{$tabMinW}) and (max-width: #{$tabMaxW})";
|
||||
$tabHeiPorCheck: "(min-height: #{$tabMinH}) and (max-height: #{$tabMaxH})";
|
||||
$tabletPortraitCheck: "#{$tabWidPorCheck} and #{$tabHeiPorCheck}";
|
||||
|
||||
$tabWidLanCheck: "(min-height: #{$tabMinW}) and (max-height: #{$tabMaxW})";
|
||||
$tabHeiLanCheck: "(min-width: #{$tabMinH}) and (max-width: #{$tabMaxH})";
|
||||
$tabletLandscapeCheck: "#{$tabWidLanCheck} and #{$tabHeiLanCheck}";
|
||||
|
||||
$desktopPortraitCheck: "(min-device-width: #{$compMinW}) and (min-device-height: #{$compMinH})";
|
||||
$desktopLandscapeCheck: "(min-device-width: #{$compMinH}) and (min-device-height: #{$compMinW})";
|
||||
$phoneCheck: "(max-device-width: #{$phoMaxW})";
|
||||
$tabletCheck: $mobileDevice;
|
||||
$desktopCheck: "(min-device-width: #{$desktopMinW})";
|
||||
|
||||
/************************** MEDIA QUERIES: WINDOWS FOR SPECIFIC ORIENTATIONS FOR EACH DEVICE */
|
||||
$phonePortrait: "#{$screenPortrait} and #{$phonePortraitCheck} and #{$mobileDevice}";
|
||||
$phoneLandscape: "#{$screenLandscape} and #{$phoneLandscapeCheck} and #{$mobileDevice}";
|
||||
$phoneLandscapeEmu: "#{$screenLandscape} and #{$phoneLandscapeCheck} and #{$mobileDeviceEmu}";
|
||||
$phonePortrait: "#{$screenPortrait} and #{$phoneCheck} and #{$mobileDevice}";
|
||||
$phoneLandscape: "#{$screenLandscape} and #{$phoneCheck} and #{$mobileDevice}";
|
||||
|
||||
$tabletPortrait: "#{$screenPortrait} and #{$tabletPortraitCheck} and #{$mobileDevice}";
|
||||
$tabletLandscape: "#{$screenLandscape} and #{$tabletLandscapeCheck} and #{$mobileDevice}";
|
||||
$tabletLandscapeEmu: "#{$screenLandscape} and #{$tabletLandscapeCheck} and #{$mobileDeviceEmu}";
|
||||
$tabletPortrait: "#{$screenPortrait} and #{$tabletCheck} and #{$mobileDevice}";
|
||||
$tabletLandscape: "#{$screenLandscape} and #{$tabletCheck} and #{$mobileDevice}";
|
||||
|
||||
$desktopPortrait: "screen and #{$desktopPortraitCheck}";
|
||||
$desktopLandscape: "screen and #{$desktopLandscapeCheck}";
|
||||
$desktop: "screen and #{$desktopCheck}";
|
||||
|
||||
/************************** DEVICE PARAMETERS FOR MENUS/REPRESENTATIONS */
|
||||
$proporMenuOnly: 90%;
|
||||
|
@ -36,16 +36,23 @@
|
||||
//@include test();
|
||||
@include slMenuTransitions;
|
||||
margin-left: 0 !important;
|
||||
#content-area {
|
||||
.holder-object-and-inspector {
|
||||
@include slMenuTransitions;
|
||||
left: $bodyMargin;
|
||||
right: $bodyMargin;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.holder.holder-create-and-search {
|
||||
right: $bodyMargin !important;
|
||||
.create-btn-holder {
|
||||
// Hide the create button by default in mobile;
|
||||
// This can be overridden by the examples/mobile bundle
|
||||
display: none;
|
||||
}
|
||||
|
||||
.holder.holder-treeview-elements {
|
||||
right: $bodyMargin !important;
|
||||
}
|
||||
|
||||
// When the tree is hidden, these are the
|
||||
// classes used for the left menu and the
|
||||
@ -55,10 +62,6 @@
|
||||
// is hidden.
|
||||
.pane.left.treeview {
|
||||
@include trans-prop-nice(opacity, 150ms);
|
||||
//right: 100% !important;
|
||||
//width: auto !important;
|
||||
//overflow-y: hidden;
|
||||
//overflow-x: hidden;
|
||||
opacity: 0 !important;
|
||||
}
|
||||
.pane.right.items {
|
||||
@ -72,7 +75,6 @@
|
||||
// causing cut/copy/paste menu to
|
||||
// not appear. Should me moved in
|
||||
// future to properly work
|
||||
//@include user-select(none);
|
||||
|
||||
// Sets the left tree menu when the tree is shown.
|
||||
.pane.left.treeview {
|
||||
@ -100,7 +102,6 @@
|
||||
}
|
||||
|
||||
.object-browse-bar {
|
||||
//@include test();
|
||||
left: 45px !important;
|
||||
.context-available {
|
||||
opacity: 1 !important;
|
||||
@ -148,7 +149,7 @@
|
||||
.pane.right.items {
|
||||
left: 0 !important;
|
||||
@include transform(translateX($proporMenuOnly));
|
||||
#content-area {
|
||||
.holder-object-and-inspector {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@ -159,4 +160,4 @@
|
||||
.desktop-hide {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,11 +20,12 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
/* REQUIRES /platform/commonUI/general/res/sass/mobile/_constants.scss */
|
||||
|
||||
// Phones in any orientation
|
||||
@mixin phone {
|
||||
@media #{$phonePortrait},
|
||||
#{$phoneLandscape},
|
||||
#{$phoneLandscapeEmu} {
|
||||
#{$phoneLandscape} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
@ -38,8 +39,7 @@
|
||||
|
||||
// Phones in landscape orientation
|
||||
@mixin phoneLandscape {
|
||||
@media #{$phoneLandscape},
|
||||
#{$phoneLandscapeEmu} {
|
||||
@media #{$phoneLandscape} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
@ -47,8 +47,7 @@
|
||||
// Tablets in any orientation
|
||||
@mixin tablet {
|
||||
@media #{$tabletPortrait},
|
||||
#{$tabletLandscape},
|
||||
#{$tabletLandscapeEmu} {
|
||||
#{$tabletLandscape} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
@ -62,8 +61,7 @@
|
||||
|
||||
// Tablets in landscape orientation
|
||||
@mixin tabletLandscape {
|
||||
@media #{$tabletLandscape},
|
||||
#{$tabletLandscapeEmu} {
|
||||
@media #{$tabletLandscape} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
@ -72,10 +70,8 @@
|
||||
@mixin phoneandtablet {
|
||||
@media #{$phonePortrait},
|
||||
#{$phoneLandscape},
|
||||
#{$phoneLandscapeEmu},
|
||||
#{$tabletPortrait},
|
||||
#{$tabletLandscape},
|
||||
#{$tabletLandscapeEmu} {
|
||||
#{$tabletLandscape} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
@ -84,17 +80,14 @@
|
||||
@mixin desktopandtablet {
|
||||
@media #{$tabletPortrait},
|
||||
#{$tabletLandscape},
|
||||
#{$tabletLandscapeEmu},
|
||||
#{$desktopPortrait},
|
||||
#{$desktopLandscape} {
|
||||
#{$desktop} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
||||
// Desktop monitors in any orientation
|
||||
@mixin desktop {
|
||||
@media #{$desktopPortrait},
|
||||
#{$desktopLandscape} {
|
||||
@media #{$desktop} {
|
||||
@content
|
||||
}
|
||||
}
|
||||
|
@ -22,21 +22,19 @@
|
||||
|
||||
// Override the Create menu for mobile
|
||||
@include phoneandtablet {
|
||||
.menu-element {
|
||||
.super-menu {
|
||||
$d: 250px;
|
||||
width: $d;
|
||||
height: $d;
|
||||
.super-menu {
|
||||
$d: 250px;
|
||||
width: $d;
|
||||
height: $d;
|
||||
|
||||
.pane {
|
||||
&.left {
|
||||
border-right: none;
|
||||
padding-right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
&.right {
|
||||
display: none;
|
||||
}
|
||||
.pane {
|
||||
&.left {
|
||||
border-right: none;
|
||||
padding-right: 0;
|
||||
width: 100%;
|
||||
}
|
||||
&.right {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,11 +20,9 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
$yBarW: 60px;
|
||||
$yLabelW: auto;
|
||||
$yLabelW: 10px;
|
||||
$xBarH: 32px;
|
||||
$legendH: 20px;
|
||||
//$colorHash: rgba(white, 0.3); // MOVED INTO CONSTANTS
|
||||
//$styleHash: dashed; // MOVED INTO CONSTANTS
|
||||
$swatchD: 8px;
|
||||
$plotDisplayArea: ($legendH + $interiorMargin, 0, $xBarH + $interiorMargin, $yBarW); // Top, right, bottom, left
|
||||
|
||||
@ -36,7 +34,6 @@ $plotDisplayArea: ($legendH + $interiorMargin, 0, $xBarH + $interiorMargin, $yBa
|
||||
height: 100%;
|
||||
|
||||
.gl-plot-axis-area {
|
||||
// @include test(green);
|
||||
position: absolute;
|
||||
&.gl-plot-x {
|
||||
top: auto;
|
||||
@ -59,7 +56,7 @@ $plotDisplayArea: ($legendH + $interiorMargin, 0, $xBarH + $interiorMargin, $yBa
|
||||
.gl-plot-coords {
|
||||
@include box-sizing(border-box);
|
||||
@include border-radius($controlCr);
|
||||
background: black; //rgba($colorKey, 0.5);
|
||||
background: black;
|
||||
color: lighten($colorBodyFg, 30%);
|
||||
padding: 2px 5px;
|
||||
position: absolute;
|
||||
@ -88,11 +85,9 @@ $plotDisplayArea: ($legendH + $interiorMargin, 0, $xBarH + $interiorMargin, $yBa
|
||||
|
||||
.gl-plot-label,
|
||||
.l-plot-label {
|
||||
// @include test(yellow);
|
||||
color: $colorPlotLabelFg;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
// text-transform: uppercase;
|
||||
|
||||
&.gl-plot-x-label,
|
||||
&.l-plot-x-label {
|
||||
@ -117,20 +112,26 @@ $plotDisplayArea: ($legendH + $interiorMargin, 0, $xBarH + $interiorMargin, $yBa
|
||||
}
|
||||
}
|
||||
|
||||
.gl-plot-y-options {
|
||||
.gl-plot-x-options,
|
||||
.gl-plot-y-options {
|
||||
$h: 32px;
|
||||
// @include test();
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: auto;
|
||||
bottom: auto;
|
||||
left: $yLabelW + $interiorMargin;
|
||||
margin-top: $h / -2;
|
||||
height: auto;
|
||||
min-height: $h;
|
||||
width: $h;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.gl-plot-x-options {
|
||||
top: $interiorMargin;
|
||||
}
|
||||
|
||||
.gl-plot-y-options {
|
||||
@include transform(translateY(-50%));
|
||||
min-width: 150px; // Need this due to enclosure of .select
|
||||
top: 50%;
|
||||
left: $yLabelW + $interiorMargin * 2;
|
||||
}
|
||||
|
||||
.gl-plot-hash {
|
||||
position: absolute;
|
||||
border: 0 $colorPlotHash $stylePlotHash;
|
||||
@ -214,21 +215,13 @@ $plotDisplayArea: ($legendH + $interiorMargin, 0, $xBarH + $interiorMargin, $yBa
|
||||
display: inline-block;
|
||||
height: $swatchD;
|
||||
width: $swatchD;
|
||||
//margin-right: $interiorMarginSm;
|
||||
}
|
||||
&[class*='s-limit'] {
|
||||
.title-label {
|
||||
//color: #fff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.gl-plot-legend {
|
||||
.plot-legend-item {
|
||||
//@include test();
|
||||
@include border-radius($smallCr);
|
||||
//color: #fff;
|
||||
line-height: 1.5em;
|
||||
padding: 0px $itemPadLR;
|
||||
.plot-color-swatch {
|
||||
@ -250,7 +243,6 @@ $plotDisplayArea: ($legendH + $interiorMargin, 0, $xBarH + $interiorMargin, $yBa
|
||||
|
||||
.gl-plot-tick,
|
||||
.tick-label {
|
||||
// @include test(red);
|
||||
font-size: 0.7rem;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
@ -277,7 +269,6 @@ $plotDisplayArea: ($legendH + $interiorMargin, 0, $xBarH + $interiorMargin, $yBa
|
||||
}
|
||||
|
||||
.gl-plot-tick {
|
||||
// @include test(red);
|
||||
&.gl-plot-x-tick-label {
|
||||
top: $interiorMargin;
|
||||
}
|
||||
|
@ -20,30 +20,22 @@
|
||||
* at runtime from the About dialog for additional information.
|
||||
*****************************************************************************/
|
||||
|
||||
.abs.search-holder {
|
||||
//@include test(#990000);
|
||||
height: $treeSearchInputBarH;
|
||||
bottom: 0;
|
||||
&.active {
|
||||
height: auto;
|
||||
bottom: 0;
|
||||
}
|
||||
top: 23px;
|
||||
|
||||
// Align with the top of the divider bar, below create button
|
||||
//margin-top: 10px; // CH comment out
|
||||
z-index:5;
|
||||
.clear-icon,
|
||||
.menu-icon {
|
||||
cursor: pointer;
|
||||
font-family: symbolsfont;
|
||||
@include trans-prop-nice((opacity, color), 150ms);
|
||||
}
|
||||
|
||||
.search {
|
||||
.clear-icon {
|
||||
// 'x' in circle icon
|
||||
&:before {
|
||||
content: '\e607';
|
||||
}
|
||||
}
|
||||
|
||||
.holder-search {
|
||||
$iconWidth: 20px;
|
||||
$leftMargin: 6px;
|
||||
$rightPadding: 5px;
|
||||
@include webkitVal(display, flex);
|
||||
//display: flex;
|
||||
@include webkitProp(flex-direction, column);
|
||||
//flex-direction: column;
|
||||
height: 100%;
|
||||
|
||||
.search-bar {
|
||||
$textInputHeight: 19px; // This is equal to the default value, 19px
|
||||
@ -52,38 +44,25 @@
|
||||
font-size: 0.8em;
|
||||
max-width: 250px;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
.search-input,
|
||||
.search-icon {
|
||||
}
|
||||
|
||||
|
||||
.search-input {
|
||||
height: $treeSearchInputBarH;
|
||||
line-height: $treeSearchInputBarH;
|
||||
padding-top: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
|
||||
.search-icon,
|
||||
&:before,
|
||||
.clear-icon,
|
||||
.menu-icon {
|
||||
//@include test(#008800);
|
||||
@include box-sizing(border-box);
|
||||
color: $colorInputIcon;
|
||||
height: $iconD; width: $iconD;
|
||||
height: $iconD;
|
||||
width: $iconD;
|
||||
line-height: $iconD;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
top: $iconEdgeM;
|
||||
}
|
||||
|
||||
.clear-icon,
|
||||
.menu-icon {
|
||||
cursor: pointer;
|
||||
@include transition(color, .25s);
|
||||
}
|
||||
|
||||
|
||||
.search-input {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
@ -92,31 +71,21 @@
|
||||
|
||||
// Make work for mct-control textfield
|
||||
input {
|
||||
width: 100%;
|
||||
width: inherit; // was 100%
|
||||
}
|
||||
}
|
||||
|
||||
.search-icon {
|
||||
//color: $colorItemFg;
|
||||
left: $interiorMarginSm;
|
||||
transition: visibility .15s, opacity .15s, color .2s;
|
||||
pointer-events: none;
|
||||
|
||||
&.content {
|
||||
// Make icon invisible whenever there is text input
|
||||
//visibility: hidden;
|
||||
//opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Make icon invisible when the text input is focused
|
||||
.search-input:focus + div.search-icon {
|
||||
//visibility: hidden;
|
||||
//opacity: 0;
|
||||
}
|
||||
&:before {
|
||||
// Magnify glass icon
|
||||
content:'\4d';
|
||||
font-family: symbolsfont;
|
||||
left: $interiorMarginSm;
|
||||
@include trans-prop-nice(color, 250ms);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
// Make icon lighten when hovering over search bar
|
||||
.search-input:hover + div.search-icon {
|
||||
&:hover:before {
|
||||
color: pullForward($colorInputIcon, 10%);
|
||||
}
|
||||
|
||||
@ -124,13 +93,10 @@
|
||||
right: $iconD + $interiorMargin;
|
||||
|
||||
// Icon is visible only when there is text input
|
||||
visibility: hidden;
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
|
||||
transition: visibility .15s, opacity .15s, color .2s;
|
||||
|
||||
&.content {
|
||||
visibility: visible;
|
||||
&.show {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
@ -140,6 +106,8 @@
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
// 'v' invoke menu icon
|
||||
&:before { content: '\76'; }
|
||||
font-size: 0.8em;
|
||||
padding-right: $iconEdgeM;
|
||||
right: $iconEdgeM;
|
||||
@ -152,43 +120,19 @@
|
||||
|
||||
.search-menu-holder {
|
||||
float: right;
|
||||
//margin-top: $textInputHeight - 2px;
|
||||
//left: -50px;
|
||||
left: -20px;
|
||||
|
||||
z-index: 1;
|
||||
|
||||
z-index: 70;
|
||||
transition: visibility .05s, opacity .05s;
|
||||
|
||||
&.off {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Hovering reveals menu
|
||||
.menu-icon:hover + div.search-menu-holder {
|
||||
visibility: visible;
|
||||
}
|
||||
div.search-menu-holder:hover {
|
||||
visibility: visible;
|
||||
}
|
||||
}
|
||||
|
||||
.active-filter-display {
|
||||
//order: 2;
|
||||
$s: 0.65em;
|
||||
$p: $interiorMargin;
|
||||
@include border-radius($basicCr);
|
||||
@include box-sizing(border-box);
|
||||
line-height: 130%;
|
||||
padding: $p 0;
|
||||
padding-left: $s * 2.25;
|
||||
font-size: $s;
|
||||
//background-color: rgba(#000, 0.3);
|
||||
//border-radius: $basicCr;
|
||||
margin-top: $interiorMarginSm;
|
||||
|
||||
|
||||
.clear-filters-icon {
|
||||
color: $colorInputIcon;
|
||||
@ -198,43 +142,28 @@
|
||||
left: 1px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
// Transition looks weird when the results list has none
|
||||
//transition: visibility .2s, opacity .2s;
|
||||
|
||||
&.off {
|
||||
visibility: hidden;
|
||||
opacity: 0;
|
||||
height: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.search-scroll {
|
||||
order: 3;
|
||||
margin-top: 4px;
|
||||
|
||||
// Adjustable scrolling size
|
||||
overflow-y: auto;
|
||||
top: auto;
|
||||
height: auto;
|
||||
max-height: 100%;
|
||||
position: relative;
|
||||
|
||||
.load-icon {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.search-results {
|
||||
@include trans-prop-nice((opacity, visibility), 250ms);
|
||||
margin-top: $interiorMarginLg; // Always include margin here to fend off the search input
|
||||
padding-right: $interiorMargin;
|
||||
.hint {
|
||||
margin-bottom: $interiorMarginLg;
|
||||
font-size: 0.65em;
|
||||
opacity: 0.6;
|
||||
}
|
||||
&.active {
|
||||
visibility: visible;
|
||||
opacity: 1;
|
||||
}
|
||||
.load-more-button {
|
||||
margin-top: $interiorMargin 0;
|
||||
font-size: 0.8em;
|
||||
position: relative;
|
||||
left: 50%;
|
||||
margin-left: -45px;
|
||||
text-align: center;
|
||||
width: 90px;
|
||||
@include transform(translateX(-50%));
|
||||
display: inline-block;
|
||||
margin-top: $interiorMargin;
|
||||
padding: 0 $interiorMarginLg;
|
||||
font-size: 0.75em;
|
||||
margin-left: 50%;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
@ -29,11 +29,13 @@
|
||||
border-color: lighten($bc, 10%);
|
||||
}
|
||||
}
|
||||
>.object-header.abs {
|
||||
//@include test(red);
|
||||
.object-top-bar {
|
||||
font-size: 0.75em;
|
||||
height: $ohH;
|
||||
line-height: $ohH;
|
||||
.left {
|
||||
padding-right: $interiorMarginLg;
|
||||
}
|
||||
}
|
||||
>.object-holder.abs {
|
||||
top: $ohH + $interiorMargin;
|
||||
|
@ -31,7 +31,7 @@
|
||||
}
|
||||
|
||||
.contents {
|
||||
$myM: 0; //$interiorMargin;
|
||||
$myM: 0;
|
||||
box-sizing: border-box;
|
||||
position: absolute;
|
||||
top: $myM;
|
||||
@ -46,37 +46,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.bar {
|
||||
.icon.major {
|
||||
margin-right: $interiorMargin;
|
||||
}
|
||||
&.abs {
|
||||
text-wrap: none;
|
||||
white-space: nowrap;
|
||||
&.left,
|
||||
.left {
|
||||
width: 45%;
|
||||
right: auto;
|
||||
}
|
||||
&.right,
|
||||
.right {
|
||||
width: 45%;
|
||||
left: auto;
|
||||
text-align: right;
|
||||
.icon.major {
|
||||
margin-left: $interiorMargin * 3;
|
||||
}
|
||||
}
|
||||
.l-flex,
|
||||
&.l-flex {
|
||||
.left,
|
||||
.right {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.user-environ {
|
||||
.browse-area,
|
||||
.editor {
|
||||
@ -117,12 +86,10 @@
|
||||
background: $colorFooterBg;
|
||||
color: lighten($colorBodyBg, 30%);
|
||||
font-size: .7rem;
|
||||
|
||||
.status-holder {
|
||||
@include box-sizing(border-box);
|
||||
@include absPosDefault($interiorMargin);
|
||||
@include ellipsize();
|
||||
//line-height: $ueFooterH - ($interiorMargin * 2);
|
||||
right: 120px;
|
||||
text-transform: uppercase;
|
||||
z-index: 1;
|
||||
@ -141,25 +108,6 @@
|
||||
}
|
||||
}
|
||||
|
||||
.browse-mode {
|
||||
.split-layout {
|
||||
.split-pane-component.pane {
|
||||
//@include test(green);
|
||||
&.treeview.left {
|
||||
min-width: 150px;
|
||||
max-width: 800px;
|
||||
width: $ueBrowseLeftPaneTreeW;
|
||||
}
|
||||
&.t-inspect.right {
|
||||
min-width: 200px;
|
||||
max-width: 600px;
|
||||
//padding-left: $ueCollapsedPaneEdgeM; // Allow room for mini-tab element
|
||||
width: $ueBrowseRightPaneInspectW;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.edit-mode {
|
||||
.split-layout {
|
||||
.split-pane-component.pane.right {
|
||||
@ -180,7 +128,6 @@
|
||||
text-transform: uppercase;
|
||||
height: $ueTopBarH;
|
||||
line-height: $ueTopBarH;
|
||||
margin-bottom: $interiorMargin;
|
||||
}
|
||||
|
||||
.primary-pane {
|
||||
@ -188,30 +135,7 @@
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
&.treeview.left {
|
||||
//.create-btn-holder {
|
||||
// //bottom: auto;
|
||||
// //top: 0;
|
||||
// height: $ueTopBarH;
|
||||
// .wrapper.menu-element {
|
||||
// position: absolute;
|
||||
// bottom: $interiorMargin;
|
||||
// }
|
||||
//}
|
||||
.holder-create-and-search{
|
||||
|
||||
}
|
||||
.search-holder {
|
||||
top: $ueTopBarH + $interiorMarginLg;
|
||||
}
|
||||
.tree-holder {
|
||||
overflow: auto;
|
||||
top: $ueTopBarH + $interiorMarginLg + $treeSearchInputBarH + $interiorMargin;
|
||||
}
|
||||
}
|
||||
|
||||
.mini-tab-icon.toggle-pane {
|
||||
//@include test(blue, 0.3);
|
||||
z-index: 5;
|
||||
@include desktop {
|
||||
$d: $uePaneMiniTabH;
|
||||
@ -256,7 +180,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.items {
|
||||
.object-browse-bar {
|
||||
.left.abs,
|
||||
@ -268,32 +191,8 @@
|
||||
}
|
||||
|
||||
.split-layout {
|
||||
&.horizontal {
|
||||
// Slides up and down
|
||||
> .pane {
|
||||
// @include test();
|
||||
margin-top: $interiorMargin;
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* &.vertical {
|
||||
// Slides left and right
|
||||
> .pane.left {
|
||||
> .holder {
|
||||
left: $bodyMargin;
|
||||
}
|
||||
}
|
||||
> .pane.right {
|
||||
> .holder {
|
||||
right: $bodyMargin;
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// Specific elements margins
|
||||
.holder.holder-create-and-search {
|
||||
.holder.holder-treeview-elements {
|
||||
top: $bodyMargin;
|
||||
right: 0;
|
||||
bottom: $bodyMargin;
|
||||
@ -314,7 +213,6 @@
|
||||
bottom: $bodyMargin;
|
||||
left: $bodyMargin;
|
||||
right: $bodyMargin;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -347,19 +245,17 @@
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************** OBJECT BROWSE BAR */
|
||||
.object-browse-bar {
|
||||
//@include test(blue);
|
||||
@include absPosDefault(0, hidden);
|
||||
@include absPosDefault(0, visible); // Must use visible to avoid hiding view switcher menu
|
||||
@include box-sizing(border-box);
|
||||
height: $ueTopBarH;
|
||||
line-height: $ueTopBarH;
|
||||
white-space: nowrap;
|
||||
|
||||
.left {
|
||||
padding-right: $interiorMarginLg * 2;
|
||||
padding-right: $interiorMarginLg;
|
||||
.l-back {
|
||||
display: inline-block;
|
||||
float: left;
|
||||
margin-right: $interiorMarginLg;
|
||||
}
|
||||
}
|
||||
@ -370,24 +266,22 @@
|
||||
// right representation.
|
||||
.pane-tree-hidden {
|
||||
// Sets the left tree menu when the tree is hidden.
|
||||
//.pane.left.treeview,
|
||||
.tree-holder,
|
||||
.splitter-treeview,
|
||||
.holder-create-and-search {
|
||||
.holder-treeview-elements {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.pane-tree-showing {
|
||||
// Sets the left tree menu when the tree is shown.
|
||||
//.pane.left.treeview,
|
||||
.tree-holder,
|
||||
.splitter-treeview {
|
||||
@include trans-prop-nice(opacity, $dur: 250ms, $delay: 250ms);
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.holder-create-and-search {
|
||||
.holder-treeview-elements {
|
||||
@include trans-prop-nice(opacity, $dur: 250ms, $delay: 200ms);
|
||||
}
|
||||
}
|
||||
@ -401,8 +295,12 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pane-inspect-hidden {
|
||||
.l-object-and-inspector {
|
||||
.t-inspect {
|
||||
z-index: 1 !important; // Move down so that primary pane elements are clickable
|
||||
}
|
||||
.l-inspect,
|
||||
.splitter-inspect {
|
||||
opacity: 0;
|
||||
@ -411,6 +309,24 @@
|
||||
}
|
||||
|
||||
@include desktop {
|
||||
.holder-all {
|
||||
min-width: $ueDesktopMinW;
|
||||
}
|
||||
.split-layout {
|
||||
.split-pane-component.pane {
|
||||
&.treeview.left {
|
||||
min-width: $ueBrowseLeftPaneTreeMinW;
|
||||
max-width: $ueBrowseLeftPaneTreeMaxW;
|
||||
width: $ueBrowseLeftPaneTreeW;
|
||||
}
|
||||
&.t-inspect.right {
|
||||
min-width: $ueBrowseRightPaneInspectMinW;
|
||||
max-width: $ueBrowseRightPaneInspectMaxW;
|
||||
width: $ueBrowseRightPaneInspectW;
|
||||
z-index: 3; // Must lift up beyond primary pane to allow overflow to go underneath
|
||||
}
|
||||
}
|
||||
}
|
||||
.pane.treeview.left .tree-holder {
|
||||
padding-right: $interiorMargin;
|
||||
}
|
||||
@ -420,8 +336,10 @@
|
||||
.pane-inspect-hidden .l-object-and-inspector {
|
||||
.pane.left { right: $ueCollapsedPaneEdgeM !important; }
|
||||
}
|
||||
|
||||
.pane:not(.resizing) {
|
||||
@include trans-prop-nice-resize-w(250ms);
|
||||
}
|
||||
.pane.primary-pane .object-browse-bar {
|
||||
min-width: 200px; // Needed for nice display when primary pane is constrained severely via splitters
|
||||
}
|
||||
}
|
||||
|
@ -6,10 +6,10 @@
|
||||
</input>
|
||||
<a class="ui-symbol icon icon-calendar"
|
||||
ng-if="structure.format === 'utc' || !structure.format"
|
||||
ng-click="pickerActive = !pickerActive">
|
||||
ng-click="picker.active = !picker.active">
|
||||
</a>
|
||||
<mct-popup ng-if="pickerActive">
|
||||
<div mct-click-elsewhere="pickerActive = false">
|
||||
<mct-popup ng-if="picker.active">
|
||||
<div mct-click-elsewhere="picker.active = false">
|
||||
<mct-control key="'datetime-picker'"
|
||||
ng-model="ngModel"
|
||||
field="field"
|
||||
|
@ -69,9 +69,12 @@ define(
|
||||
updateFromModel($scope.ngModel[$scope.field]);
|
||||
}
|
||||
|
||||
$scope.picker = { active: false };
|
||||
|
||||
$scope.$watch('structure.format', setFormat);
|
||||
$scope.$watch('ngModel[field]', updateFromModel);
|
||||
$scope.$watch('textValue', updateFromView);
|
||||
|
||||
}
|
||||
|
||||
return DateTimeFieldController;
|
||||
|
@ -51,6 +51,10 @@ define(
|
||||
position = [ rect.left, rect.top ],
|
||||
popup = popupService.display(div, position);
|
||||
|
||||
// TODO: Handle in CSS;
|
||||
// https://github.com/nasa/openmctweb/issues/298
|
||||
div.css('z-index', 75);
|
||||
|
||||
transclude(function (clone) {
|
||||
div.append(clone);
|
||||
});
|
||||
|
@ -91,6 +91,10 @@ define(
|
||||
expect(mockScope.textValue).toEqual("1977-05-25 17:30:00");
|
||||
});
|
||||
|
||||
it("exposes toggle state for date-time picker", function () {
|
||||
expect(mockScope.picker.active).toBe(false);
|
||||
});
|
||||
|
||||
describe("when user input is invalid", function () {
|
||||
var newText, oldValue;
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -72,8 +72,6 @@ $colorInputBg: $colorGenBg;
|
||||
$colorInputFg: $colorBodyFg;
|
||||
$colorFormText: pushBack($colorBodyFg, 10%);
|
||||
$colorInputIcon: pushBack($colorBodyFg, 25%);
|
||||
$colorSelectBg: #ddd;
|
||||
$colorSelectFg: $colorBodyFg;
|
||||
|
||||
// Inspector
|
||||
$colorInspectorBg: pullForward($colorBodyBg, 5%);
|
||||
@ -83,6 +81,22 @@ $colorInspectorPropVal: pullForward($colorInspectorFg, 15%);
|
||||
$colorInspectorSectionHeaderBg: pullForward($colorInspectorBg, 5%);
|
||||
$colorInspectorSectionHeaderFg: pullForward($colorInspectorBg, 40%);
|
||||
|
||||
// Status colors, mainly used for messaging and item ancillary symbols
|
||||
$colorStatusFg: #fff;
|
||||
$colorStatusDefault: #ccc;
|
||||
$colorStatusInfo: #60ba7b;
|
||||
$colorStatusAlert: #ffb66c;
|
||||
$colorStatusError: #c96b68;
|
||||
$colorProgressBarOuter: rgba(#000, 0.1);
|
||||
$colorProgressBarAmt: #0a0;
|
||||
$progressBarHOverlay: 15px;
|
||||
$progressBarStripeW: 20px;
|
||||
$shdwStatusIc: rgba(white, 0.8) 0 0px 5px;
|
||||
|
||||
// Selects
|
||||
$colorSelectBg: #ddd;
|
||||
$colorSelectFg: $colorBodyFg;
|
||||
|
||||
// Limits and staleness colors//
|
||||
$colorTelemFresh: pullForward($colorBodyFg, 20%);
|
||||
$colorTelemStale: pushBack($colorBodyFg, 20%);
|
||||
|
@ -96,7 +96,7 @@
|
||||
"provides": "actionService",
|
||||
"type": "provider",
|
||||
"implementation": "actions/ActionProvider.js",
|
||||
"depends": [ "actions[]" ]
|
||||
"depends": [ "actions[]", "$log" ]
|
||||
},
|
||||
{
|
||||
"provides": "actionService",
|
||||
@ -222,7 +222,8 @@
|
||||
},
|
||||
{
|
||||
"key": "topic",
|
||||
"implementation": "services/Topic.js"
|
||||
"implementation": "services/Topic.js",
|
||||
"depends": [ "$log" ]
|
||||
},
|
||||
{
|
||||
"key": "contextualize",
|
||||
|
@ -39,9 +39,11 @@ define(
|
||||
* @imeplements {ActionService}
|
||||
* @constructor
|
||||
*/
|
||||
function ActionProvider(actions) {
|
||||
function ActionProvider(actions, $log) {
|
||||
var self = this;
|
||||
|
||||
this.$log = $log;
|
||||
|
||||
// Build up look-up tables
|
||||
this.actions = actions;
|
||||
this.actionsByKey = {};
|
||||
@ -74,6 +76,7 @@ define(
|
||||
var context = (actionContext || {}),
|
||||
category = context.category,
|
||||
key = context.key,
|
||||
$log = this.$log,
|
||||
candidates;
|
||||
|
||||
// Instantiate an action; invokes the constructor and
|
||||
@ -103,12 +106,31 @@ define(
|
||||
// appliesTo method of given actions (if defined), and
|
||||
// instantiate those applicable actions.
|
||||
function createIfApplicable(actions, context) {
|
||||
return (actions || []).filter(function (Action) {
|
||||
return Action.appliesTo ?
|
||||
Action.appliesTo(context) : true;
|
||||
}).map(function (Action) {
|
||||
return instantiateAction(Action, context);
|
||||
});
|
||||
function isApplicable(Action) {
|
||||
return Action.appliesTo ? Action.appliesTo(context) : true;
|
||||
}
|
||||
|
||||
function instantiate(Action) {
|
||||
try {
|
||||
return instantiateAction(Action, context);
|
||||
} catch (e) {
|
||||
$log.error([
|
||||
"Could not instantiate action",
|
||||
Action.key,
|
||||
"due to:",
|
||||
e.message
|
||||
].join(" "));
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
function isDefined(action) {
|
||||
return action !== undefined;
|
||||
}
|
||||
|
||||
return (actions || []).filter(isApplicable)
|
||||
.map(instantiate)
|
||||
.filter(isDefined);
|
||||
}
|
||||
|
||||
// Match actions to the provided context by comparing "key"
|
||||
|
@ -26,6 +26,8 @@ define(
|
||||
function () {
|
||||
"use strict";
|
||||
|
||||
var ERROR_PREFIX = "Error when notifying listener: ";
|
||||
|
||||
/**
|
||||
* The `topic` service provides a way to create both named,
|
||||
* shared listeners and anonymous, private listeners.
|
||||
@ -46,7 +48,7 @@ define(
|
||||
* @returns {Function}
|
||||
* @memberof platform/core
|
||||
*/
|
||||
function Topic() {
|
||||
function Topic($log) {
|
||||
var topics = {};
|
||||
|
||||
function createTopic() {
|
||||
@ -63,7 +65,11 @@ define(
|
||||
},
|
||||
notify: function (message) {
|
||||
listeners.forEach(function (listener) {
|
||||
listener(message);
|
||||
try {
|
||||
listener(message);
|
||||
} catch (e) {
|
||||
$log.error(ERROR_PREFIX + e.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -156,8 +156,15 @@ define(
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns the default model for an object of this type. Note that
|
||||
* this method returns a clone of the original model, so if using this
|
||||
* method heavily, consider caching the result to optimize performance.
|
||||
*
|
||||
* @return {object} The default model for an object of this type.
|
||||
*/
|
||||
TypeImpl.prototype.getInitialModel = function () {
|
||||
return this.typeDef.model || {};
|
||||
return JSON.parse(JSON.stringify(this.typeDef.model || {}));
|
||||
};
|
||||
|
||||
TypeImpl.prototype.getDefinition = function () {
|
||||
|
@ -30,7 +30,8 @@ define(
|
||||
"use strict";
|
||||
|
||||
describe("The action provider", function () {
|
||||
var actions,
|
||||
var mockLog,
|
||||
actions,
|
||||
actionProvider;
|
||||
|
||||
function SimpleAction() {
|
||||
@ -62,6 +63,10 @@ define(
|
||||
MetadataAction.key = "metadata";
|
||||
|
||||
beforeEach(function () {
|
||||
mockLog = jasmine.createSpyObj(
|
||||
'$log',
|
||||
['error', 'warn', 'info', 'debug']
|
||||
);
|
||||
actions = [
|
||||
SimpleAction,
|
||||
CategorizedAction,
|
||||
@ -137,6 +142,42 @@ define(
|
||||
expect(provided[0].getMetadata()).toEqual("custom metadata");
|
||||
});
|
||||
|
||||
describe("when actions throw errors during instantiation", function () {
|
||||
var errorText,
|
||||
provided;
|
||||
|
||||
beforeEach(function () {
|
||||
errorText = "some error text";
|
||||
|
||||
function BadAction() {
|
||||
throw new Error(errorText);
|
||||
}
|
||||
|
||||
provided = new ActionProvider(
|
||||
[ SimpleAction, BadAction ],
|
||||
mockLog
|
||||
).getActions();
|
||||
});
|
||||
|
||||
it("logs an error", function () {
|
||||
expect(mockLog.error)
|
||||
.toHaveBeenCalledWith(jasmine.any(String));
|
||||
});
|
||||
|
||||
it("reports the error's message", function () {
|
||||
expect(
|
||||
mockLog.error.mostRecentCall.args[0].indexOf(errorText)
|
||||
).not.toEqual(-1);
|
||||
});
|
||||
|
||||
it("still provides valid actions", function () {
|
||||
expect(provided.length).toEqual(1);
|
||||
expect(provided[0].perform()).toEqual("simple");
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
);
|
||||
|
@ -28,13 +28,18 @@ define(
|
||||
|
||||
describe("The 'topic' service", function () {
|
||||
var topic,
|
||||
mockLog,
|
||||
testMessage,
|
||||
mockCallback;
|
||||
|
||||
beforeEach(function () {
|
||||
testMessage = { someKey: "some value"};
|
||||
mockLog = jasmine.createSpyObj(
|
||||
'$log',
|
||||
[ 'error', 'warn', 'info', 'debug' ]
|
||||
);
|
||||
mockCallback = jasmine.createSpy('callback');
|
||||
topic = new Topic();
|
||||
topic = new Topic(mockLog);
|
||||
});
|
||||
|
||||
it("notifies listeners on a topic", function () {
|
||||
@ -65,6 +70,21 @@ define(
|
||||
expect(mockCallback).toHaveBeenCalledWith(testMessage);
|
||||
});
|
||||
|
||||
it("is robust against errors thrown by listeners", function () {
|
||||
var mockBadCallback = jasmine.createSpy("bad-callback"),
|
||||
t = topic();
|
||||
|
||||
mockBadCallback.andCallFake(function () {
|
||||
throw new Error("I'm afraid I can't do that.");
|
||||
});
|
||||
|
||||
t.listen(mockBadCallback);
|
||||
t.listen(mockCallback);
|
||||
|
||||
t.notify(testMessage);
|
||||
expect(mockCallback).toHaveBeenCalledWith(testMessage);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -101,6 +101,12 @@ define(
|
||||
expect(type.getInitialModel().someKey).toEqual("some value");
|
||||
});
|
||||
|
||||
it("provides a fresh initial model each time", function () {
|
||||
var model = type.getInitialModel();
|
||||
model.someKey = "some other value";
|
||||
expect(type.getInitialModel().someKey).toEqual("some value");
|
||||
});
|
||||
|
||||
it("provides type properties", function () {
|
||||
expect(type.getProperties().length).toEqual(1);
|
||||
});
|
||||
|
@ -146,6 +146,14 @@ define(
|
||||
});
|
||||
};
|
||||
|
||||
AbstractComposeAction.appliesTo = function (context) {
|
||||
var applicableObject =
|
||||
context.selectedObject || context.domainObject;
|
||||
|
||||
return !!(applicableObject &&
|
||||
applicableObject.hasCapability('context'));
|
||||
};
|
||||
|
||||
return AbstractComposeAction;
|
||||
}
|
||||
);
|
||||
|
@ -60,6 +60,8 @@ define(
|
||||
);
|
||||
}
|
||||
|
||||
CopyAction.prototype = Object.create(AbstractComposeAction.prototype);
|
||||
|
||||
/**
|
||||
* Updates user about progress of copy. Should not be invoked by
|
||||
* client code under any circumstances.
|
||||
@ -145,6 +147,9 @@ define(
|
||||
return AbstractComposeAction.prototype.perform.call(this)
|
||||
.then(success, error, notification);
|
||||
};
|
||||
|
||||
CopyAction.appliesTo = AbstractComposeAction.appliesTo;
|
||||
|
||||
return CopyAction;
|
||||
}
|
||||
);
|
||||
|
@ -35,15 +35,15 @@ define(
|
||||
* @memberof platform/entanglement
|
||||
*/
|
||||
function LinkAction(policyService, locationService, linkService, context) {
|
||||
return new AbstractComposeAction(
|
||||
policyService,
|
||||
locationService,
|
||||
linkService,
|
||||
context,
|
||||
"Link"
|
||||
AbstractComposeAction.apply(
|
||||
this,
|
||||
[policyService, locationService, linkService, context, "Link"]
|
||||
);
|
||||
}
|
||||
|
||||
LinkAction.prototype = Object.create(AbstractComposeAction.prototype);
|
||||
LinkAction.appliesTo = AbstractComposeAction.appliesTo;
|
||||
|
||||
return LinkAction;
|
||||
}
|
||||
);
|
||||
|
@ -35,15 +35,15 @@ define(
|
||||
* @memberof platform/entanglement
|
||||
*/
|
||||
function MoveAction(policyService, locationService, moveService, context) {
|
||||
return new AbstractComposeAction(
|
||||
policyService,
|
||||
locationService,
|
||||
moveService,
|
||||
context,
|
||||
"Move"
|
||||
AbstractComposeAction.apply(
|
||||
this,
|
||||
[policyService, locationService, moveService, context, "Move"]
|
||||
);
|
||||
}
|
||||
|
||||
MoveAction.prototype = Object.create(AbstractComposeAction.prototype);
|
||||
MoveAction.appliesTo = AbstractComposeAction.appliesTo;
|
||||
|
||||
return MoveAction;
|
||||
}
|
||||
);
|
||||
|
@ -102,6 +102,28 @@ define(
|
||||
composeService = new MockCopyService();
|
||||
});
|
||||
|
||||
it("are only applicable to domain objects with a context", function () {
|
||||
var noContextObject = domainObjectFactory({
|
||||
name: 'selectedObject',
|
||||
model: { name: 'selectedObject' },
|
||||
capabilities: {}
|
||||
});
|
||||
|
||||
expect(AbstractComposeAction.appliesTo({
|
||||
selectedObject: selectedObject
|
||||
})).toBe(true);
|
||||
expect(AbstractComposeAction.appliesTo({
|
||||
domainObject: selectedObject
|
||||
})).toBe(true);
|
||||
|
||||
expect(AbstractComposeAction.appliesTo({
|
||||
selectedObject: noContextObject
|
||||
})).toBe(false);
|
||||
expect(AbstractComposeAction.appliesTo({
|
||||
domainObject: noContextObject
|
||||
})).toBe(false);
|
||||
});
|
||||
|
||||
|
||||
describe("with context from context-action", function () {
|
||||
beforeEach(function () {
|
||||
|
@ -38,7 +38,8 @@ define(
|
||||
* @constructor
|
||||
*/
|
||||
function WorkerService($window, workers) {
|
||||
var workerUrls = {};
|
||||
var workerUrls = {},
|
||||
sharedWorkers = {};
|
||||
|
||||
function addWorker(worker) {
|
||||
var key = worker.key;
|
||||
@ -48,12 +49,15 @@ define(
|
||||
worker.bundle.sources,
|
||||
worker.scriptUrl
|
||||
].join("/");
|
||||
sharedWorkers[key] = worker.shared;
|
||||
}
|
||||
}
|
||||
|
||||
(workers || []).forEach(addWorker);
|
||||
this.workerUrls = workerUrls;
|
||||
this.sharedWorkers = sharedWorkers;
|
||||
this.Worker = $window.Worker;
|
||||
this.SharedWorker = $window.SharedWorker;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -61,12 +65,17 @@ define(
|
||||
* that has been registered under the `workers` category
|
||||
* of extension.
|
||||
*
|
||||
* This will return either a Worker or a SharedWorker,
|
||||
* depending on whether a `shared` flag has been specified
|
||||
* on the the extension definition for the referenced worker.
|
||||
*
|
||||
* @param {string} key symbolic identifier for the worker
|
||||
* @returns {Worker} the running Worker
|
||||
* @returns {Worker | SharedWorker} the running Worker
|
||||
*/
|
||||
WorkerService.prototype.run = function (key) {
|
||||
var scriptUrl = this.workerUrls[key],
|
||||
Worker = this.Worker;
|
||||
Worker = this.sharedWorkers[key] ?
|
||||
this.SharedWorker : this.Worker;
|
||||
return scriptUrl && Worker && new Worker(scriptUrl);
|
||||
};
|
||||
|
||||
|
@ -30,10 +30,14 @@ define(
|
||||
var mockWindow,
|
||||
testWorkers,
|
||||
mockWorker,
|
||||
mockSharedWorker,
|
||||
service;
|
||||
|
||||
beforeEach(function () {
|
||||
mockWindow = jasmine.createSpyObj('$window', ['Worker']);
|
||||
mockWindow = jasmine.createSpyObj(
|
||||
'$window',
|
||||
['Worker', 'SharedWorker']
|
||||
);
|
||||
testWorkers = [
|
||||
{
|
||||
key: 'abc',
|
||||
@ -49,11 +53,19 @@ define(
|
||||
key: 'xyz',
|
||||
scriptUrl: 'bad.js',
|
||||
bundle: { path: 'bad', sources: 'bad' }
|
||||
},
|
||||
{
|
||||
key: 'a-shared-worker',
|
||||
shared: true,
|
||||
scriptUrl: 'c.js',
|
||||
bundle: { path: 'a', sources: 'b' }
|
||||
}
|
||||
];
|
||||
mockWorker = {};
|
||||
mockSharedWorker = {};
|
||||
|
||||
mockWindow.Worker.andReturn(mockWorker);
|
||||
mockWindow.SharedWorker.andReturn(mockSharedWorker);
|
||||
|
||||
service = new WorkerService(mockWindow, testWorkers);
|
||||
});
|
||||
@ -68,6 +80,12 @@ define(
|
||||
expect(mockWindow.Worker).toHaveBeenCalledWith('x/y/z.js');
|
||||
});
|
||||
|
||||
it("allows workers to be shared", function () {
|
||||
expect(service.run('a-shared-worker')).toBe(mockSharedWorker);
|
||||
expect(mockWindow.SharedWorker)
|
||||
.toHaveBeenCalledWith('a/b/c.js');
|
||||
});
|
||||
|
||||
it("returns undefined for unknown workers", function () {
|
||||
expect(service.run('def')).toBeUndefined();
|
||||
});
|
||||
|
@ -1,5 +1,4 @@
|
||||
<div class="t-imagery" ng-controller="ImageryController as imagery">
|
||||
<!-- Main image -->
|
||||
<div
|
||||
class="l-image-main-wrapper"
|
||||
ng-mouseenter="showLocalControls = true;"
|
||||
@ -33,8 +32,8 @@
|
||||
>
|
||||
</div>
|
||||
|
||||
<div class="l-image-main-controlbar l-flex bar">
|
||||
<div class="left">
|
||||
<div class="l-image-main-controlbar l-flex-row">
|
||||
<div class="left flex-elem grows">
|
||||
<a
|
||||
class="s-btn show-thumbs sm hidden"
|
||||
ng-click="showThumbsBubble = (showThumbsBubble)? false:true"
|
||||
@ -43,7 +42,7 @@
|
||||
<span class="l-time">{{imagery.getTime()}}</span>
|
||||
<span class="l-date">{{imagery.getDate()}}</span>
|
||||
</div>
|
||||
<div class="right">
|
||||
<div class="right flex-elem">
|
||||
<a
|
||||
class="s-btn pause-play"
|
||||
ng-click="imagery.paused(!imagery.paused())"
|
||||
|
@ -20,12 +20,15 @@
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="frame frame-template abs">
|
||||
<div class="bar abs l-flex object-header object-top-bar">
|
||||
<div class="left">
|
||||
<mct-representation key="'object-header'" mct-object="domainObject">
|
||||
<div class="abs object-top-bar l-flex-row">
|
||||
<div class="left flex-elem l-flex-row grows">
|
||||
<mct-representation
|
||||
key="'object-header'"
|
||||
mct-object="domainObject"
|
||||
class="l-flex-row flex-elem object-header grows">
|
||||
</mct-representation>
|
||||
</div>
|
||||
<div class="btn-bar right">
|
||||
<div class="btn-bar right l-flex-row flex-elem flex-justify-end flex-fixed">
|
||||
<mct-representation key="'switcher'"
|
||||
ng-model="representation"
|
||||
mct-object="domainObject">
|
||||
|
@ -113,7 +113,7 @@ define(
|
||||
Math.floor(position.x / self.gridSize[0]),
|
||||
Math.floor(position.y / self.gridSize[1])
|
||||
],
|
||||
dimensions: DEFAULT_DIMENSIONS
|
||||
dimensions: self.defaultDimensions()
|
||||
};
|
||||
// Mark change as persistable
|
||||
if ($scope.commit) {
|
||||
|
@ -192,6 +192,29 @@ define(
|
||||
expect(parseInt(styleB.width, 10)).toBeGreaterThan(63);
|
||||
expect(parseInt(styleB.width, 10)).toBeGreaterThan(31);
|
||||
});
|
||||
|
||||
it("ensures a minimum frame size on drop", function () {
|
||||
var style;
|
||||
|
||||
// Start with a very small frame size
|
||||
testModel.layoutGrid = [ 1, 1 ];
|
||||
mockScope.$watch.calls[0].args[1](testModel.layoutGrid);
|
||||
|
||||
// Notify that a drop occurred
|
||||
testModel.composition.push('d');
|
||||
mockScope.$on.mostRecentCall.args[1](
|
||||
mockEvent,
|
||||
'd',
|
||||
{ x: 300, y: 100 }
|
||||
);
|
||||
mockScope.$watch.calls[0].args[1](['d']);
|
||||
|
||||
style = controller.getFrameStyle("d");
|
||||
|
||||
// Resulting size should still be reasonably large pixel-size
|
||||
expect(parseInt(style.width, 10)).toBeGreaterThan(63);
|
||||
expect(parseInt(style.height, 10)).toBeGreaterThan(31);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -62,7 +62,7 @@
|
||||
ng-show="representation.showControls"
|
||||
ng-if="axes[1].options.length > 0">
|
||||
<div class='form-control shell select'>
|
||||
<select class="form-control input shell select"
|
||||
<select class="form-control input shell"
|
||||
ng-model="axes[1].active"
|
||||
ng-options="option.name for option in axes[1].options">
|
||||
</select>
|
||||
@ -160,12 +160,11 @@
|
||||
{{axes[0].active.name}}
|
||||
</div>
|
||||
|
||||
|
||||
<div class="gl-plot-x-options gl-plot-local-controls"
|
||||
ng-show="representation.showControls"
|
||||
ng-if="axes[0].options.length > 0">
|
||||
<div class='form-control shell select'>
|
||||
<select class="form-control input shell select"
|
||||
<select class="form-control input shell"
|
||||
ng-model="axes[0].active"
|
||||
ng-options="option.name for option in axes[0].options">
|
||||
</select>
|
||||
|
@ -78,6 +78,8 @@ define(
|
||||
cachedObjects = [],
|
||||
updater,
|
||||
lastBounds,
|
||||
lastRange,
|
||||
lastDomain,
|
||||
handle;
|
||||
|
||||
// Populate the scope with axis information (specifically, options
|
||||
@ -120,16 +122,16 @@ define(
|
||||
// Reinstantiate the plot updater (e.g. because we have a
|
||||
// new subscription.) This will clear the plot.
|
||||
function recreateUpdater() {
|
||||
updater = new PlotUpdater(
|
||||
handle,
|
||||
($scope.axes[0].active || {}).key,
|
||||
($scope.axes[1].active || {}).key,
|
||||
PLOT_FIXED_DURATION
|
||||
);
|
||||
self.limitTracker = new PlotLimitTracker(
|
||||
handle,
|
||||
($scope.axes[1].active || {}).key
|
||||
);
|
||||
var domain = $scope.axes[0].active.key,
|
||||
range = $scope.axes[1].active.key,
|
||||
duration = PLOT_FIXED_DURATION;
|
||||
|
||||
updater = new PlotUpdater(handle, domain, range, duration);
|
||||
lastDomain = domain;
|
||||
lastRange = range;
|
||||
|
||||
self.limitTracker = new PlotLimitTracker(handle, range);
|
||||
|
||||
// Keep any externally-provided bounds
|
||||
if (lastBounds) {
|
||||
setBasePanZoom(lastBounds);
|
||||
@ -201,22 +203,39 @@ define(
|
||||
}
|
||||
}
|
||||
|
||||
function requery() {
|
||||
self.pending = true;
|
||||
releaseSubscription();
|
||||
subscribe($scope.domainObject);
|
||||
}
|
||||
|
||||
function updateDomainFormat() {
|
||||
var domainAxis = $scope.axes[0];
|
||||
plotTelemetryFormatter
|
||||
.setDomainFormat(domainAxis.active.format);
|
||||
}
|
||||
|
||||
function domainRequery(newDomain) {
|
||||
if (newDomain !== lastDomain) {
|
||||
updateDomainFormat();
|
||||
requery();
|
||||
}
|
||||
}
|
||||
|
||||
function rangeRequery(newRange) {
|
||||
if (newRange !== lastRange) {
|
||||
requery();
|
||||
}
|
||||
}
|
||||
|
||||
// Respond to a display bounds change (requery for data)
|
||||
function changeDisplayBounds(event, bounds) {
|
||||
var domainAxis = $scope.axes[0];
|
||||
|
||||
domainAxis.chooseOption(bounds.domain);
|
||||
plotTelemetryFormatter
|
||||
.setDomainFormat(domainAxis.active.format);
|
||||
|
||||
self.pending = true;
|
||||
releaseSubscription();
|
||||
subscribe($scope.domainObject);
|
||||
updateDomainFormat();
|
||||
setBasePanZoom(bounds);
|
||||
}
|
||||
|
||||
function updateDomainFormat(format) {
|
||||
plotTelemetryFormatter.setDomainFormat(format);
|
||||
requery();
|
||||
}
|
||||
|
||||
this.modeOptions = new PlotModeOptions([], subPlotFactory);
|
||||
@ -237,6 +256,10 @@ define(
|
||||
new PlotAxis("ranges", [], AXIS_DEFAULTS[1])
|
||||
];
|
||||
|
||||
// Watch for changes to the selected axis
|
||||
$scope.$watch("axes[0].active.key", domainRequery);
|
||||
$scope.$watch("axes[1].active.key", rangeRequery);
|
||||
|
||||
// Subscribe to telemetry when a domain object becomes available
|
||||
$scope.$watch('domainObject', subscribe);
|
||||
|
||||
|
@ -53,6 +53,14 @@ define(
|
||||
});
|
||||
}
|
||||
|
||||
function fireWatch(expr, value) {
|
||||
mockScope.$watch.calls.forEach(function (call) {
|
||||
if (call.args[0] === expr) {
|
||||
call.args[1].apply(null, [value]);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
beforeEach(function () {
|
||||
mockScope = jasmine.createSpyObj(
|
||||
@ -263,6 +271,20 @@ define(
|
||||
]);
|
||||
expect(mockHandle.request.calls.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("requeries when user changes domain selection", function () {
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
expect(mockHandle.request.calls.length).toEqual(1);
|
||||
fireWatch("axes[0].active.key", 'someNewKey');
|
||||
expect(mockHandle.request.calls.length).toEqual(2);
|
||||
});
|
||||
|
||||
it("requeries when user changes range selection", function () {
|
||||
mockScope.$watch.mostRecentCall.args[1](mockDomainObject);
|
||||
expect(mockHandle.request.calls.length).toEqual(1);
|
||||
fireWatch("axes[1].active.key", 'someNewKey');
|
||||
expect(mockHandle.request.calls.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
||||
|
@ -19,40 +19,17 @@
|
||||
this source code distribution or the Licensing information page available
|
||||
at runtime from the About dialog for additional information.
|
||||
-->
|
||||
<div class="search"
|
||||
ng-controller="SearchController as controller">
|
||||
|
||||
<!-- Search bar -->
|
||||
<div class="search-bar"
|
||||
ng-controller="ClickAwayController as toggle">
|
||||
|
||||
<!-- Input field -->
|
||||
<div class="l-flex-col flex-elem grows holder holder-search" ng-controller="SearchController as controller">
|
||||
<div class="search-bar flex-elem" ng-controller="ClickAwayController as toggle">
|
||||
<input class="search-input"
|
||||
type="text"
|
||||
ng-model="ngModel.input"
|
||||
ng-keyup="controller.search()" />
|
||||
|
||||
<!-- Search icon -->
|
||||
<!-- ui symbols for search are 'd' and 'M' -->
|
||||
<div class="ui-symbol search-icon"
|
||||
ng-class="{content: !(ngModel.input === '' || ngModel.input === undefined)}">
|
||||
M
|
||||
</div>
|
||||
|
||||
<!-- Clear icon/button 'x' -->
|
||||
<a class="ui-symbol clear-icon"
|
||||
ng-class="{content: !(ngModel.input === '' || ngModel.input === undefined)}"
|
||||
ng-click="ngModel.input = ''; controller.search()">
|
||||

|
||||
</a>
|
||||
|
||||
<!-- Menu icon/button 'v' -->
|
||||
<a class="ui-symbol menu-icon"
|
||||
ng-click="toggle.toggle()">
|
||||
v
|
||||
</a>
|
||||
|
||||
<!-- Menu -->
|
||||
<a class="clear-icon"
|
||||
ng-class="{show: !(ngModel.input === '' || ngModel.input === undefined)}"
|
||||
ng-click="ngModel.input = ''; controller.search()"></a>
|
||||
<a class="menu-icon"
|
||||
ng-click="toggle.toggle()"></a>
|
||||
<mct-include key="'search-menu'"
|
||||
class="menu-element search-menu-holder"
|
||||
ng-class="{off: !toggle.isActive()}"
|
||||
@ -60,49 +37,20 @@
|
||||
ng-click="toggle.setState(true)">
|
||||
</mct-include>
|
||||
</div>
|
||||
|
||||
<!-- Active filter display -->
|
||||
<div class="active-filter-display"
|
||||
<div class="active-filter-display flex-elem"
|
||||
ng-class="{off: ngModel.filtersString === '' || ngModel.filtersString === undefined || !ngModel.search}"
|
||||
ng-controller="SearchMenuController as menuController">
|
||||
|
||||
<a class="ui-symbol clear-filters-icon"
|
||||
ng-click="ngModel.checkAll = true; menuController.checkAll()">
|
||||

|
||||
</a>
|
||||
|
||||
Filtered by: {{ ngModel.filtersString }}
|
||||
|
||||
<a class="clear-icon clear-filters-icon"
|
||||
ng-click="ngModel.checkAll = true; menuController.checkAll()"></a>Filtered by: {{ ngModel.filtersString }}
|
||||
</div>
|
||||
|
||||
<!-- This div exists to determine scroll bar location -->
|
||||
<div class="search-scroll abs">
|
||||
|
||||
<!-- Results list -->
|
||||
<div class="results">
|
||||
<mct-representation key="'search-item'"
|
||||
ng-repeat="result in results"
|
||||
mct-object="result.object"
|
||||
ng-model="ngModel">
|
||||
</mct-representation>
|
||||
</div>
|
||||
|
||||
<!-- Loading icon -->
|
||||
<div class="load-icon"
|
||||
ng-class="{loading: loading}"
|
||||
ng-if="loading">
|
||||
<span class="icon wait-spinner"></span>
|
||||
<span class="title-label">Loading...</span>
|
||||
</div>
|
||||
|
||||
<!-- Load more button -->
|
||||
<div ng-if="controller.areMore()">
|
||||
<a class="load-more-button s-btn vsm"
|
||||
ng-click="controller.loadMore()">
|
||||
More Results
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<div class="search-results flex-elem grows vscroll"
|
||||
ng-class="{ off: !(loading || results.length > 0), loading: loading }">
|
||||
<mct-representation key="'search-item'"
|
||||
ng-repeat="result in results"
|
||||
mct-object="result.object"
|
||||
ng-model="ngModel">
|
||||
</mct-representation>
|
||||
<a class="load-more-button s-btn vsm" ng-if="controller.areMore()" ng-click="controller.loadMore()">More Results</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
2
platform/status/README.md
Normal file
2
platform/status/README.md
Normal file
@ -0,0 +1,2 @@
|
||||
Facilitates tracking states associated with specific domain
|
||||
objects.
|
23
platform/status/bundle.json
Normal file
23
platform/status/bundle.json
Normal file
@ -0,0 +1,23 @@
|
||||
{
|
||||
"extensions": {
|
||||
"representers": [
|
||||
{
|
||||
"implementation": "StatusRepresenter.js"
|
||||
}
|
||||
],
|
||||
"capabilities": [
|
||||
{
|
||||
"key": "status",
|
||||
"implementation": "StatusCapability.js",
|
||||
"depends": [ "statusService" ]
|
||||
}
|
||||
],
|
||||
"services": [
|
||||
{
|
||||
"key": "statusService",
|
||||
"implementation": "StatusService.js",
|
||||
"depends": [ "topic" ]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
100
platform/status/src/StatusCapability.js
Normal file
100
platform/status/src/StatusCapability.js
Normal file
@ -0,0 +1,100 @@
|
||||
/*****************************************************************************
|
||||
* 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';
|
||||
|
||||
/**
|
||||
* The `status` capability can be used to attach information
|
||||
* about the state of a domain object, expressed as simple
|
||||
* string flags.
|
||||
*
|
||||
* Representations of domain objects will also receive CSS
|
||||
* classes which reflect their current status.
|
||||
* (@see platform/status.StatusRepresenter)
|
||||
*
|
||||
* @param {platform/status.StatusService} statusService
|
||||
* the service which will track domain object status
|
||||
* within the application.
|
||||
* @param {DomainObject} the domain object whose status will
|
||||
* be tracked.
|
||||
* @constructor
|
||||
* @memberof platform/status
|
||||
*/
|
||||
function StatusCapability(statusService, domainObject) {
|
||||
this.statusService = statusService;
|
||||
this.domainObject = domainObject;
|
||||
}
|
||||
|
||||
/**
|
||||
* List all status flags currently set for this domain object.
|
||||
* @returns {string[]} all current status flags.
|
||||
*/
|
||||
StatusCapability.prototype.list = function () {
|
||||
return this.statusService.listStatuses(this.domainObject.getId());
|
||||
};
|
||||
|
||||
/**
|
||||
* Check if a status flag is currently set for this domain object.
|
||||
* @param {string} status the status to get
|
||||
* @returns {boolean} true if the flag is present, otherwise false
|
||||
*/
|
||||
StatusCapability.prototype.get = function (status) {
|
||||
return this.list().indexOf(status) !== -1;
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a status flag on this domain object.
|
||||
* @param {string} status the status to set
|
||||
* @param {boolean} state true if the domain object should
|
||||
* possess this status, false if it should not
|
||||
*/
|
||||
StatusCapability.prototype.set = function (status, state) {
|
||||
return this.statusService.setStatus(
|
||||
this.domainObject.getId(),
|
||||
status,
|
||||
state
|
||||
);
|
||||
};
|
||||
|
||||
/**
|
||||
* Listen for changes in this domain object's status.
|
||||
* @param {Function} callback function to invoke on changes;
|
||||
* called with the new status of the domain object, as an
|
||||
* array of strings
|
||||
* @returns {Function} a function which can be used to stop
|
||||
* listening to status changes for this domain object.
|
||||
*/
|
||||
StatusCapability.prototype.listen = function (callback) {
|
||||
return this.statusService.listen(
|
||||
this.domainObject.getId(),
|
||||
callback
|
||||
);
|
||||
};
|
||||
|
||||
return StatusCapability;
|
||||
|
||||
}
|
||||
);
|
26
platform/status/src/StatusConstants.js
Normal file
26
platform/status/src/StatusConstants.js
Normal file
@ -0,0 +1,26 @@
|
||||
/*****************************************************************************
|
||||
* 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({
|
||||
CSS_CLASS_PREFIX: 's-status-',
|
||||
TOPIC_PREFIX: 'status:'
|
||||
});
|
96
platform/status/src/StatusRepresenter.js
Normal file
96
platform/status/src/StatusRepresenter.js
Normal file
@ -0,0 +1,96 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
['./StatusConstants'],
|
||||
function (StatusConstants) {
|
||||
'use strict';
|
||||
|
||||
var STATUS_CLASS_PREFIX = StatusConstants.CSS_CLASS_PREFIX;
|
||||
|
||||
/**
|
||||
* Adds/removes CSS classes to `mct-representation`s to reflect the
|
||||
* current status of represented domain objects, as reported by
|
||||
* their `status` capability.
|
||||
*
|
||||
* Statuses are prefixed with `s-status-` to build CSS class names.
|
||||
* As such, when a domain object has the status "pending", its
|
||||
* representations will have the CSS class `s-status-pending`.
|
||||
*
|
||||
* @param {angular.Scope} scope the representation's scope object
|
||||
* @param element the representation's jqLite-wrapped DOM element
|
||||
* @implements {Representer}
|
||||
* @constructor
|
||||
* @memberof platform/status
|
||||
*/
|
||||
function StatusRepresenter(scope, element) {
|
||||
this.element = element;
|
||||
this.lastClasses = [];
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove any status-related classes from this representation.
|
||||
* @private
|
||||
*/
|
||||
StatusRepresenter.prototype.clearClasses = function () {
|
||||
var element = this.element;
|
||||
this.lastClasses.forEach(function (c) {
|
||||
element.removeClass(c);
|
||||
});
|
||||
};
|
||||
|
||||
StatusRepresenter.prototype.represent = function (representation, domainObject) {
|
||||
var self = this,
|
||||
statusCapability = domainObject.getCapability('status');
|
||||
|
||||
function updateStatus(flags) {
|
||||
var newClasses = flags.map(function (flag) {
|
||||
return STATUS_CLASS_PREFIX + flag;
|
||||
});
|
||||
|
||||
self.clearClasses();
|
||||
|
||||
newClasses.forEach(function (c) {
|
||||
self.element.addClass(c);
|
||||
});
|
||||
|
||||
self.lastClasses = newClasses;
|
||||
}
|
||||
|
||||
updateStatus(statusCapability.list());
|
||||
this.unlisten = statusCapability.listen(updateStatus);
|
||||
};
|
||||
|
||||
StatusRepresenter.prototype.destroy = function () {
|
||||
this.clearClasses();
|
||||
if (this.unlisten) {
|
||||
this.unlisten();
|
||||
this.unlisten = undefined;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
return StatusRepresenter;
|
||||
|
||||
}
|
||||
);
|
92
platform/status/src/StatusService.js
Normal file
92
platform/status/src/StatusService.js
Normal file
@ -0,0 +1,92 @@
|
||||
/*****************************************************************************
|
||||
* 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(
|
||||
['./StatusConstants'],
|
||||
function (StatusConstants) {
|
||||
'use strict';
|
||||
|
||||
var STATUS_PREFIX = StatusConstants.TOPIC_PREFIX;
|
||||
|
||||
/**
|
||||
* The `statusService` maintains information about the current
|
||||
* status of specific domain objects within the system. Status
|
||||
* is represented as string flags which are present when a
|
||||
* domain object possesses that status, and false when it does
|
||||
* not.
|
||||
*
|
||||
* @param {platform/core.Topic} topic the `topic` service, used
|
||||
* to create/use named listeners.
|
||||
* @constructor
|
||||
* @memberof platform/status
|
||||
*/
|
||||
function StatusService(topic) {
|
||||
this.statusTable = {};
|
||||
this.topic = topic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all status flags currently set for a domain object.
|
||||
* @param {string} id the identifier of the domain object
|
||||
* @returns {string[]} an array containing all status flags currently
|
||||
* applicable to the object with this identifier
|
||||
*/
|
||||
StatusService.prototype.listStatuses = function (id) {
|
||||
return this.statusTable[id] || [];
|
||||
};
|
||||
|
||||
/**
|
||||
* Set a status flag for a domain object.
|
||||
* @param {string} id the identifier of the domain object
|
||||
* @param {string} status the status to set
|
||||
* @param {boolean} state true if the domain object should
|
||||
* possess this status, false if it should not
|
||||
*/
|
||||
StatusService.prototype.setStatus = function (id, status, state) {
|
||||
this.statusTable[id] = this.statusTable[id] || [];
|
||||
this.statusTable[id] = this.statusTable[id].filter(function (s) {
|
||||
return s !== status;
|
||||
});
|
||||
if (state) {
|
||||
this.statusTable[id].push(status);
|
||||
}
|
||||
this.topic(STATUS_PREFIX + id).notify(this.statusTable[id]);
|
||||
};
|
||||
|
||||
/**
|
||||
* Listen for changes in a domain object's status.
|
||||
* @param {string} id the identifier of the domain object
|
||||
* @param {Function} callback function to invoke on changes;
|
||||
* called with the new status of the domain object, as an
|
||||
* array of strings
|
||||
* @returns {Function} a function which can be used to stop
|
||||
* listening to status changes for this domain object.
|
||||
*/
|
||||
StatusService.prototype.listen = function (id, callback) {
|
||||
return this.topic(STATUS_PREFIX + id).listen(callback);
|
||||
};
|
||||
|
||||
return StatusService;
|
||||
|
||||
}
|
||||
);
|
89
platform/status/test/StatusCapabilitySpec.js
Normal file
89
platform/status/test/StatusCapabilitySpec.js
Normal 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,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/StatusCapability"],
|
||||
function (StatusCapability) {
|
||||
"use strict";
|
||||
|
||||
describe("The status capability", function () {
|
||||
var mockStatusService,
|
||||
mockDomainObject,
|
||||
mockUnlisten,
|
||||
testId,
|
||||
testStatusFlags,
|
||||
capability;
|
||||
|
||||
beforeEach(function () {
|
||||
testId = "some-id";
|
||||
testStatusFlags = [ 'a', 'b', 'c' ];
|
||||
|
||||
mockStatusService = jasmine.createSpyObj(
|
||||
'statusService',
|
||||
[ 'listen', 'setStatus', 'listStatuses' ]
|
||||
);
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getId', 'getCapability', 'getModel' ]
|
||||
);
|
||||
mockUnlisten = jasmine.createSpy('unlisten');
|
||||
|
||||
mockStatusService.listen.andReturn(mockUnlisten);
|
||||
mockStatusService.listStatuses.andReturn(testStatusFlags);
|
||||
mockDomainObject.getId.andReturn(testId);
|
||||
|
||||
capability = new StatusCapability(
|
||||
mockStatusService,
|
||||
mockDomainObject
|
||||
);
|
||||
});
|
||||
|
||||
it("sets status with the statusService", function () {
|
||||
var testStatus = "some-test-status";
|
||||
capability.set(testStatus, true);
|
||||
expect(mockStatusService.setStatus)
|
||||
.toHaveBeenCalledWith(testId, testStatus, true);
|
||||
capability.set(testStatus, false);
|
||||
expect(mockStatusService.setStatus)
|
||||
.toHaveBeenCalledWith(testId, testStatus, false);
|
||||
});
|
||||
|
||||
it("gets status from the statusService", function () {
|
||||
expect(capability.list()).toBe(testStatusFlags);
|
||||
});
|
||||
|
||||
it("listens to changes from the statusService", function () {
|
||||
var mockCallback = jasmine.createSpy();
|
||||
expect(capability.listen(mockCallback))
|
||||
.toBe(mockUnlisten);
|
||||
expect(mockStatusService.listen)
|
||||
.toHaveBeenCalledWith(testId, mockCallback);
|
||||
});
|
||||
|
||||
it("allows statuses to be checked individually", function () {
|
||||
expect(capability.get('some-unset-status')).toBe(false);
|
||||
expect(capability.get(testStatusFlags[0])).toBe(true);
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
118
platform/status/test/StatusRepresenterSpec.js
Normal file
118
platform/status/test/StatusRepresenterSpec.js
Normal 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,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/
|
||||
|
||||
define(
|
||||
["../src/StatusRepresenter", "../src/StatusConstants"],
|
||||
function (StatusRepresenter, StatusConstants) {
|
||||
"use strict";
|
||||
|
||||
describe("The status representer", function () {
|
||||
var mockScope,
|
||||
mockElement,
|
||||
testRepresentation,
|
||||
mockDomainObject,
|
||||
mockStatusCapability,
|
||||
mockUnlisten,
|
||||
elementClasses,
|
||||
testStatusFlags,
|
||||
representer;
|
||||
|
||||
function verifyClasses() {
|
||||
expect(Object.keys(elementClasses).sort())
|
||||
.toEqual(testStatusFlags.map(function (s) {
|
||||
return StatusConstants.CSS_CLASS_PREFIX + s;
|
||||
}).sort());
|
||||
}
|
||||
|
||||
function updateStatus(newFlags) {
|
||||
testStatusFlags = newFlags;
|
||||
mockStatusCapability.get.andReturn(newFlags);
|
||||
mockStatusCapability.listen.mostRecentCall
|
||||
.args[0](newFlags);
|
||||
}
|
||||
|
||||
beforeEach(function () {
|
||||
testStatusFlags = [ 'x', 'y', 'z' ];
|
||||
|
||||
mockScope = {};
|
||||
mockElement = jasmine.createSpyObj('element', [
|
||||
'addClass',
|
||||
'removeClass'
|
||||
]);
|
||||
testRepresentation = { key: "someKey" };
|
||||
mockDomainObject = jasmine.createSpyObj(
|
||||
'domainObject',
|
||||
[ 'getModel', 'getId', 'getCapability' ]
|
||||
);
|
||||
mockStatusCapability = jasmine.createSpyObj(
|
||||
'status',
|
||||
[ 'list', 'get', 'set', 'listen' ]
|
||||
);
|
||||
mockUnlisten = jasmine.createSpy();
|
||||
|
||||
elementClasses = {};
|
||||
|
||||
mockElement.addClass.andCallFake(function (c) {
|
||||
elementClasses[c] = true;
|
||||
});
|
||||
mockElement.removeClass.andCallFake(function (c) {
|
||||
delete elementClasses[c];
|
||||
});
|
||||
|
||||
mockStatusCapability.list.andReturn(testStatusFlags);
|
||||
mockStatusCapability.listen.andReturn(mockUnlisten);
|
||||
|
||||
mockDomainObject.getCapability.andCallFake(function (c) {
|
||||
return c === 'status' && mockStatusCapability;
|
||||
});
|
||||
|
||||
representer = new StatusRepresenter(mockScope, mockElement);
|
||||
representer.represent(testRepresentation, mockDomainObject);
|
||||
});
|
||||
|
||||
it("listens for status changes", function () {
|
||||
expect(mockStatusCapability.listen)
|
||||
.toHaveBeenCalledWith(jasmine.any(Function));
|
||||
});
|
||||
|
||||
it("initially sets classes to reflect status", verifyClasses);
|
||||
|
||||
it("changes classes on status change callbacks", function () {
|
||||
updateStatus(['a', 'x', '123']);
|
||||
verifyClasses();
|
||||
});
|
||||
|
||||
it("stops listening when destroyed", function () {
|
||||
expect(mockUnlisten).not.toHaveBeenCalled();
|
||||
representer.destroy();
|
||||
expect(mockUnlisten).toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it("removes status classes when destroyed", function () {
|
||||
expect(elementClasses).not.toEqual({});
|
||||
representer.destroy();
|
||||
expect(elementClasses).toEqual({});
|
||||
});
|
||||
});
|
||||
}
|
||||
);
|
94
platform/status/test/StatusServiceSpec.js
Normal file
94
platform/status/test/StatusServiceSpec.js
Normal file
@ -0,0 +1,94 @@
|
||||
/*****************************************************************************
|
||||
* 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*/
|
||||
|
||||
define(
|
||||
["../src/StatusService"],
|
||||
function (StatusService) {
|
||||
"use strict";
|
||||
|
||||
describe("The status service", function () {
|
||||
var mockTopic,
|
||||
mockTopicInstance,
|
||||
mockUnlisten,
|
||||
mockCallback,
|
||||
testId,
|
||||
testStatus,
|
||||
statusService;
|
||||
|
||||
beforeEach(function () {
|
||||
testId = "some-domain-object-identifier";
|
||||
testStatus = "test-status";
|
||||
|
||||
mockTopic = jasmine.createSpy('topic');
|
||||
mockTopicInstance = jasmine.createSpyObj(
|
||||
'topicInstance',
|
||||
[ 'notify', 'listen' ]
|
||||
);
|
||||
mockUnlisten = jasmine.createSpy('unlisten');
|
||||
mockCallback = jasmine.createSpy('callback');
|
||||
|
||||
mockTopic.andReturn(mockTopicInstance);
|
||||
mockTopicInstance.listen.andReturn(mockUnlisten);
|
||||
|
||||
statusService = new StatusService(mockTopic);
|
||||
});
|
||||
|
||||
it("initially contains no flags for an object", function () {
|
||||
expect(statusService.listStatuses(testId)).toEqual([]);
|
||||
});
|
||||
|
||||
it("stores and clears status flags", function () {
|
||||
statusService.setStatus(testId, testStatus, true);
|
||||
expect(statusService.listStatuses(testId)).toEqual([testStatus]);
|
||||
statusService.setStatus(testId, testStatus, false);
|
||||
expect(statusService.listStatuses(testId)).toEqual([]);
|
||||
});
|
||||
|
||||
it("uses topic to listen for changes", function () {
|
||||
expect(statusService.listen(testId, mockCallback))
|
||||
.toEqual(mockUnlisten);
|
||||
expect(mockTopic)
|
||||
.toHaveBeenCalledWith(jasmine.any(String));
|
||||
// Just care that the topic was somehow unique to the object
|
||||
expect(mockTopic.mostRecentCall.args[0].indexOf(testId))
|
||||
.not.toEqual(-1);
|
||||
});
|
||||
|
||||
it("notifies listeners of changes", function () {
|
||||
statusService.setStatus(testId, testStatus, true);
|
||||
expect(mockTopicInstance.notify)
|
||||
.toHaveBeenCalledWith([ testStatus ]);
|
||||
statusService.setStatus(testId, testStatus, false);
|
||||
expect(mockTopicInstance.notify)
|
||||
.toHaveBeenCalledWith([ ]);
|
||||
|
||||
expect(mockTopic)
|
||||
.toHaveBeenCalledWith(jasmine.any(String));
|
||||
// Just care that the topic was somehow unique to the object
|
||||
expect(mockTopic.mostRecentCall.args[0].indexOf(testId))
|
||||
.not.toEqual(-1);
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
);
|
5
platform/status/test/suite.json
Normal file
5
platform/status/test/suite.json
Normal file
@ -0,0 +1,5 @@
|
||||
[
|
||||
"StatusCapability",
|
||||
"StatusRepresenter",
|
||||
"StatusService"
|
||||
]
|
@ -285,11 +285,17 @@ define(
|
||||
* domain objects returned by `getTelemetryObjects()`.
|
||||
*
|
||||
* @param {DomainObject} domainObject the object of interest
|
||||
* @param {string} [key] the symbolic identifier of the domain
|
||||
* to look up; if omitted, the value for this object's
|
||||
* default domain will be used
|
||||
* @returns the most recent domain value observed
|
||||
*/
|
||||
TelemetrySubscription.prototype.getDomainValue = function (domainObject) {
|
||||
var id = domainObject.getId();
|
||||
return (this.latestValues[id] || {}).domain;
|
||||
TelemetrySubscription.prototype.getDomainValue = function (domainObject, key) {
|
||||
var id = domainObject.getId(),
|
||||
latestValue = this.latestValues[id];
|
||||
return latestValue && (key ?
|
||||
latestValue.datum[key] :
|
||||
latestValue.domain);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -302,11 +308,17 @@ define(
|
||||
* domain objects returned by `getTelemetryObjects()`.
|
||||
*
|
||||
* @param {DomainObject} domainObject the object of interest
|
||||
* @param {string} [key] the symbolic identifier of the range
|
||||
* to look up; if omitted, the value for this object's
|
||||
* default range will be used
|
||||
* @returns the most recent range value observed
|
||||
*/
|
||||
TelemetrySubscription.prototype.getRangeValue = function (domainObject) {
|
||||
var id = domainObject.getId();
|
||||
return (this.latestValues[id] || {}).range;
|
||||
TelemetrySubscription.prototype.getRangeValue = function (domainObject, key) {
|
||||
var id = domainObject.getId(),
|
||||
latestValue = this.latestValues[id];
|
||||
return latestValue && (key ?
|
||||
latestValue.datum[key] :
|
||||
latestValue.range);
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
x
Reference in New Issue
Block a user