diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..5f2fb18d84
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,298 @@
+# Contributing to Open MCT Web
+
+This document describes the process of contributing to Open MCT Web as well
+as the standards that will be applied when evaluating contributions.
+
+Please be aware that additional agreements will be necessary before we can
+accept changes from external contributors.
+
+## Summary
+
+The short version:
+
+1. Write your contribution.
+2. Make sure your contribution meets code, test, and commit message
+ standards as described below.
+3. Submit a pull request from a topic branch back to `master`. Include a check
+ list, as described below. (Optionally, assign this to a specific member
+ for review.)
+4. Respond to any discussion. When the reviewer decides it's ready, they
+ will merge back `master` and fill out their own check list.
+
+## Contribution Process
+
+Open MCT Web uses git for software version control, and for branching and
+merging. The central repository is at
+https://github.com/nasa/openmctweb.git.
+
+### Roles
+
+References to roles are made throughout this document. These are not intended
+to reflect titles or long-term job assignments; rather, these are used as
+descriptors to refer to members of the development team performing tasks in
+the check-in process. These roles are:
+
+* _Author_: The individual who has made changes to files in the software
+ repository, and wishes to check these in.
+* _Reviewer_: The individual who reviews changes to files before they are
+ checked in.
+* _Integrator_: The individual who performs the task of merging these files.
+ Usually the reviewer.
+
+### Branching
+
+Three basic types of branches may be included in the above repository:
+
+1. Master branch.
+2. Topic branches.
+3. Developer branches.
+
+Branches which do not fit into the above categories may be created and used
+during the course of development for various reasons, such as large-scale
+refactoring of code or implementation of complex features which may cause
+instability. In these exceptional cases it is the responsibility of the
+developer who initiates the task which motivated this branching to
+communicate to the team the role of these branches and any associated
+procedures for the duration of their use.
+
+#### Master Branch
+
+The role of the `master` branches is to represent the latest
+"ready for test" version of the software. Source code on the master
+branch has undergone peer review, and will undergo regular automated
+testing with notification on failure. Master branches may be unstable
+(particularly for recent features), but the intent is for the stability of
+any features on master branches to be non-decreasing. It is the shared
+responsibility of authors, reviewers, and integrators to ensure this.
+
+#### Topic Branches
+
+Topic branches are used by developers to perform and record work on issues.
+
+Topic branches need not necessarily be stable, even when pushed to the
+central repository; in fact, the practice of making incremental commits
+while working on an issue and pushing these to the central repository is
+encouraged, to avoid lost work and to share work-in-progress. (Small commits
+also help isolate changes, which can help in identifying which change
+introduced a defect, particularly when that defect went unnoticed for some
+time, e.g. using `git bisect`.)
+
+Topic branches should be named according to their corresponding issue
+identifiers, all lower case, without hyphens. (e.g. branch mct9 would refer
+to issue #9.)
+
+In some cases, work on an issue may warrant the use of multiple divergent
+branches; for instance, when a developer wants to try more than one solution
+and compare them, or when a "dead end" is reached and an initial approach to
+resolving an issue needs to be abandoned. In these cases, a short suffix
+should be added to the additional branches; this may be simply a single
+character (e.g. wtd481b) or, where useful, a descriptive term for what
+distinguishes the branches (e.g. wtd481verbose). It is the responsibility of
+the author to communicate which branch is intended to be merged to both the
+reviewer and the integrator.
+
+#### Developer Branches
+
+Developer branches are any branches used for purposes outside of the scope
+of the above; e.g. to try things out, or maintain a "my latest stuff"
+branch that is not delayed by the review and integration process. These
+may be pushed to the central repository, and may follow any naming convention
+desired so long as the owner of the branch is identifiable, and so long as
+the name chosen could not be mistaken for a topic or master branch.
+
+### Merging
+
+When development is complete on an issue, the first step toward merging it
+back into the master branch is to file a Pull Request. The contributions
+should meet code, test, and commit message standards as described below,
+and the pull request should include a completed author checklist, also
+as described below. Pull requests may be assigned to specific team
+members when appropriate (e.g. to draw to a specific person's attention.)
+
+Code review should take place using discussion features within the pull
+request. When the reviewer is satisfied, they should add a comment to
+the pull request containing the reviewer checklist (from below) and complete
+the merge back to the master branch.
+
+## Standards
+
+Contributions to Open MCT Web are expected to meet the following standards.
+In addition, reviewers should use general discretion before accepting
+changes.
+
+### Code Standards
+
+JavaScript sources in Open MCT Web must satisfy JSLint under its default
+settings. This is verified by the command line build.
+
+#### Code Guidelines
+
+JavaScript sources in Open MCT Web should:
+
+* Use four spaces for indentation. Tabs should not be used.
+* Include JSDoc for any exposed API (e.g. public methods, constructors.)
+* Include non-JSDoc comments as-needed for explaining private variables,
+ methods, or algorithms when they are non-obvious.
+* Define one public class per script, expressed as a constructor function
+ returned from an AMD-style module.
+* Follow “Java-like” naming conventions. These includes:
+ * Classes should use camel case, first letter capitalized
+ (e.g. SomeClassName.)
+ * Methods, variables, fields, and function names should use camel case,
+ first letter lower-case (e.g. someVariableName.) Constants
+ (variables or fields which are meant to be declared and initialized
+ statically, and never changed) should use only capital letters, with
+ underscores between words (e.g. SOME_CONSTANT.)
+ * File name should be the name of the exported class, plus a .js extension
+ (e.g. SomeClassName.js)
+* Avoid anonymous functions, except when functions are short (a few lines)
+ and/or their inclusion makes sense within the flow of the code
+ (e.g. as arguments to a forEach call.)
+* Avoid deep nesting (especially of functions), except where necessary
+ (e.g. due to closure scope.)
+* End with a single new-line character.
+* Expose public methods by declaring them on the class's prototype.
+* Within a given function's scope, do not mix declarations and imperative
+ code, and present these in the following order:
+ * First, variable declarations and initialization.
+ * Second, function declarations.
+ * Third, imperative statements.
+ * Finally, the returned value.
+
+Deviations from Open MCT Web code style guidelines require two-party agreement,
+typically from the author of the change and its reviewer.
+
+#### Code Example
+
+```js
+/*global define*/
+
+/**
+ * Bundles should declare themselves as namespaces in whichever source
+ * file is most like the "main point of entry" to the bundle.
+ * @namespace some/bundle
+ */
+define(
+ ['./OtherClass'],
+ function (OtherClass) {
+ "use strict";
+
+ /**
+ * A summary of how to use this class goes here.
+ *
+ * @constructor
+ * @memberof some/bundle
+ */
+ function ExampleClass() {
+ }
+
+ // Methods which are not intended for external use should
+ // not have JSDoc (or should be marked @private)
+ ExampleClass.prototype.privateMethod = function () {
+ };
+
+ /**
+ * A summary of this method goes here.
+ * @param {number} n a parameter
+ * @returns {number} a return value
+ */
+ ExampleClass.prototype.publicMethod = function (n) {
+ return n * 2;
+ }
+
+ return ExampleClass;
+ }
+);
+```
+
+### Test Standards
+
+Automated testing shall occur whenever changes are merged into the main
+development branch and must be confirmed alongside any pull request.
+
+Automated tests are typically unit tests which exercise individual software
+components. Tests are subject to code review along with the actual
+implementation, to ensure that tests are applicable and useful.
+
+Examples of useful tests:
+* Tests which replicate bugs (or their root causes) to verify their
+ resolution.
+* Tests which reflect details from software specifications.
+* Tests which exercise edge or corner cases among inputs.
+* Tests which verify expected interactions with other components in the
+ system.
+
+During automated testing, code coverage metrics will be reported. Line
+coverage must remain at or above 80%.
+
+### Commit Message Standards
+
+Commit messages should:
+
+* Contain a one-line subject, followed by one line of white space,
+ followed by one or more descriptive paragraphs, each separated by one
+ line of white space.
+* Contain a short (usually one word) reference to the feature or subsystem
+ the commit effects, in square brackets, at the start of the subject line
+ (e.g. `[Documentation] Draft of check-in process`)
+* Contain a reference to a relevant issue number in the body of the commit.
+ * This is important for traceability; while branch names also provide this,
+ you cannot tell from looking at a commit what branch it was authored on.
+* Describe the change that was made, and any useful rationale therefore.
+ * Comments in code should explain what things do, commit messages describe
+ how they came to be done that way.
+* Provide sufficient information for a reviewer to understand the changes
+ made and their relationship to previous code.
+
+Commit messages should not:
+
+* Exceed 54 characters in length on the subject line.
+* Exceed 72 characters in length in the body of the commit.
+ * Except where necessary to maintain the structure of machine-readable or
+ machine-generated text (e.g. error messages)
+
+See [Contributing to a Project](http://git-scm.com/book/ch5-2.html) from
+Pro Git by Shawn Chacon and Ben Straub for a bit of the rationale behind
+these standards.
+
+## Issue Reporting
+
+Issues are tracked at https://github.com/nasa/openmctweb/issues
+
+Issues should include:
+
+* A short description of the issue encountered.
+* A longer-form description of the issue encountered. When possible, steps to
+ reproduce the issue.
+* When possible, a description of the impact of the issue. What use case does
+ it impede?
+* An assessment of the severity of the issue.
+
+Issue severity is categorized as follows (in ascending order):
+
+* _Trivial_: Minimal impact on the usefulness and functionality of the
+ software; a "nice-to-have."
+* _(Unspecified)_: Major loss of functionality or impairment of use.
+* _Critical_: Large-scale loss of functionality or impairment of use,
+ such that remaining utility becomes marginal.
+* _Blocker_: Harmful or otherwise unacceptable behavior. Must fix.
+
+## Check Lists
+
+The following check lists should be completed and attached to pull requests
+when they are filed (author checklist) and when they are merged (reviewer
+checklist.)
+
+### Author Checklist
+
+1. Changes address original issue?
+2. Unit tests included and/or updated with changes?
+3. Command line build passes?
+4. Expect to pass code review?
+
+### Reviewer Checklist
+
+1. Changes appear to address issue?
+2. Appropriate unit tests included?
+3. Code style and in-line documentation are appropriate?
+4. Commit messages meet standards?
diff --git a/jsdoc.json b/jsdoc.json
index ed0fddcf31..f913b650d1 100644
--- a/jsdoc.json
+++ b/jsdoc.json
@@ -1,10 +1,12 @@
{
"source": {
"include": [
- "example/",
"platform/"
],
- "includePattern": "(example|platform)/.+\\.js$",
+ "includePattern": "platform/.+\\.js$",
"excludePattern": ".+\\Spec\\.js$|lib/.+"
- }
-}
\ No newline at end of file
+ },
+ "plugins": [
+ "plugins/markdown"
+ ]
+}
diff --git a/package.json b/package.json
index d1d675df19..a1ac01f437 100644
--- a/package.json
+++ b/package.json
@@ -28,6 +28,7 @@
"start": "node app.js",
"test": "karma start --single-run",
"jshint": "jshint platform example || exit 0",
+ "watch": "karma start",
"jsdoc": "jsdoc -c jsdoc.json -r -d target/docs/api",
"otherdoc": "node docs/gendocs.js --in docs/src --out target/docs",
"docs": "npm run jsdoc ; npm run otherdoc"
diff --git a/platform/commonUI/about/src/AboutController.js b/platform/commonUI/about/src/AboutController.js
index 7fc61c8cc2..dffd9b9471 100644
--- a/platform/commonUI/about/src/AboutController.js
+++ b/platform/commonUI/about/src/AboutController.js
@@ -21,6 +21,11 @@
*****************************************************************************/
/*global define*/
+
+/**
+ * Implements Open MCT Web's About dialog.
+ * @namespace platform/commonUI/about
+ */
define(
[],
function () {
@@ -29,35 +34,36 @@ define(
/**
* The AboutController provides information to populate the
* About dialog.
+ * @memberof platform/commonUI/about
* @constructor
* @param {object[]} versions an array of version extensions;
* injected from `versions[]`
* @param $window Angular-injected window object
*/
function AboutController(versions, $window) {
- return {
- /**
- * Get version info. This is given as an array of
- * objects, where each object is intended to appear
- * as a line-item in the version information listing.
- * @memberof AboutController#
- * @returns {object[]} version information
- */
- versions: function () {
- return versions;
- },
- /**
- * Open a new window (or tab, depending on browser
- * configuration) containing open source licenses.
- * @memberof AboutController#
- */
- openLicenses: function () {
- // Open a new browser window at the licenses route
- $window.open("#/licenses");
- }
- };
+ this.versionDefinitions = versions;
+ this.$window = $window;
}
+ /**
+ * Get version info. This is given as an array of
+ * objects, where each object is intended to appear
+ * as a line-item in the version information listing.
+ * @returns {object[]} version information
+ */
+ AboutController.prototype.versions = function () {
+ return this.versionDefinitions;
+ };
+
+ /**
+ * Open a new window (or tab, depending on browser
+ * configuration) containing open source licenses.
+ */
+ AboutController.prototype.openLicenses = function () {
+ // Open a new browser window at the licenses route
+ this.$window.open("#/licenses");
+ };
+
return AboutController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/about/src/LicenseController.js b/platform/commonUI/about/src/LicenseController.js
index 1d996596aa..740124641f 100644
--- a/platform/commonUI/about/src/LicenseController.js
+++ b/platform/commonUI/about/src/LicenseController.js
@@ -29,20 +29,22 @@ define(
/**
* Provides extension-introduced licenses information to the
* licenses route.
+ * @memberof platform/commonUI/about
* @constructor
*/
function LicenseController(licenses) {
- return {
- /**
- * Get license information.
- * @returns {Array} license extensions
- */
- licenses: function () {
- return licenses;
- }
- };
+ this.licenseDefinitions = licenses;
}
+ /**
+ * Get license information.
+ * @returns {Array} license extensions
+ * @memberof platform/commonUI/about.LicenseController#
+ */
+ LicenseController.prototype.licenses = function () {
+ return this.licenseDefinitions;
+ };
+
return LicenseController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/about/src/LogoController.js b/platform/commonUI/about/src/LogoController.js
index a688e96acf..85909a0552 100644
--- a/platform/commonUI/about/src/LogoController.js
+++ b/platform/commonUI/about/src/LogoController.js
@@ -29,21 +29,23 @@ define(
/**
* The LogoController provides functionality to the application
* logo in the bottom-right of the user interface.
+ * @memberof platform/commonUI/about
* @constructor
* @param {OverlayService} overlayService the overlay service
*/
function LogoController(overlayService) {
- return {
- /**
- * Display the About dialog.
- * @memberof LogoController#
- */
- showAboutDialog: function () {
- overlayService.createOverlay("overlay-about");
- }
- };
+ this.overlayService = overlayService;
}
+ /**
+ * Display the About dialog.
+ * @memberof LogoController#
+ * @memberof platform/commonUI/about.LogoController#
+ */
+ LogoController.prototype.showAboutDialog = function () {
+ this.overlayService.createOverlay("overlay-about");
+ };
+
return LogoController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/bundle.json b/platform/commonUI/browse/bundle.json
index 6852c3e8e6..c5ee5e7198 100644
--- a/platform/commonUI/browse/bundle.json
+++ b/platform/commonUI/browse/bundle.json
@@ -69,8 +69,8 @@
{
"key": "grid-item",
"templateUrl": "templates/items/grid-item.html",
- "uses": [ "type", "action" ],
- "gestures": [ "info","menu" ]
+ "uses": [ "type", "action", "location" ],
+ "gestures": [ "info", "menu" ]
},
{
"key": "object-header",
@@ -93,12 +93,12 @@
{
"key": "navigationService",
"implementation": "navigation/NavigationService.js"
- },
+ },
{
"key": "creationService",
"implementation": "creation/CreationService.js",
"depends": [ "persistenceService", "$q", "$log" ]
- }
+ }
],
"actions": [
{
diff --git a/platform/commonUI/browse/res/templates/items/grid-item.html b/platform/commonUI/browse/res/templates/items/grid-item.html
index 175a47e055..d27d088ee1 100644
--- a/platform/commonUI/browse/res/templates/items/grid-item.html
+++ b/platform/commonUI/browse/res/templates/items/grid-item.html
@@ -32,7 +32,13 @@
-
{{type.getGlyph()}}
+
+ {{type.getGlyph()}}
+
+
}
diff --git a/platform/commonUI/browse/src/BrowseController.js b/platform/commonUI/browse/src/BrowseController.js
index 65ac4467b8..d1f89d43fb 100644
--- a/platform/commonUI/browse/src/BrowseController.js
+++ b/platform/commonUI/browse/src/BrowseController.js
@@ -22,7 +22,8 @@
/*global define,Promise*/
/**
- * Module defining BrowseController. Created by vwoeltje on 11/7/14.
+ * This bundle implements Browse mode.
+ * @namespace platform/commonUI/browse
*/
define(
[],
@@ -39,6 +40,7 @@ define(
* which Angular templates first have access to the domain object
* hierarchy.
*
+ * @memberof platform/commonUI/browse
* @constructor
*/
function BrowseController($scope, $route, $location, objectService, navigationService, urlService) {
@@ -202,3 +204,4 @@ define(
return BrowseController;
}
);
+
diff --git a/platform/commonUI/browse/src/BrowseObjectController.js b/platform/commonUI/browse/src/BrowseObjectController.js
index 1826120458..b1af9f29a7 100644
--- a/platform/commonUI/browse/src/BrowseObjectController.js
+++ b/platform/commonUI/browse/src/BrowseObjectController.js
@@ -29,6 +29,7 @@ define(
/**
* Controller for the `browse-object` representation of a domain
* object (the right-hand side of Browse mode.)
+ * @memberof platform/commonUI/browse
* @constructor
*/
function BrowseObjectController($scope, $location, $route) {
@@ -71,3 +72,4 @@ define(
return BrowseObjectController;
}
);
+
diff --git a/platform/commonUI/browse/src/MenuArrowController.js b/platform/commonUI/browse/src/MenuArrowController.js
index 86cad25c0e..5c4916e099 100644
--- a/platform/commonUI/browse/src/MenuArrowController.js
+++ b/platform/commonUI/browse/src/MenuArrowController.js
@@ -33,19 +33,29 @@ define(
* A left-click on the menu arrow should display a
* context menu. This controller launches the context
* menu.
+ * @memberof platform/commonUI/browse
* @constructor
*/
function MenuArrowController($scope) {
- function showMenu(event) {
- var actionContext = {key: 'menu', domainObject: $scope.domainObject, event: event};
- $scope.domainObject.getCapability('action').perform(actionContext);
- }
-
- return {
- showMenu: showMenu
- };
+ this.$scope = $scope;
}
+ /**
+ * Show a context menu for the domain object in this scope.
+ *
+ * @param event the browser event which caused this (used to
+ * position the menu)
+ */
+ MenuArrowController.prototype.showMenu = function (event) {
+ var actionContext = {
+ key: 'menu',
+ domainObject: this.$scope.domainObject,
+ event: event
+ };
+
+ this.$scope.domainObject.getCapability('action').perform(actionContext);
+ };
+
return MenuArrowController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/src/creation/CreateAction.js b/platform/commonUI/browse/src/creation/CreateAction.js
index ce0d6d5cd4..984b26cfe5 100644
--- a/platform/commonUI/browse/src/creation/CreateAction.js
+++ b/platform/commonUI/browse/src/creation/CreateAction.js
@@ -34,7 +34,10 @@ define(
* domain objects of a specific type. This is the action that
* is performed when a user uses the Create menu.
*
+ * @memberof platform/commonUI/browse
+ * @implements {Action}
* @constructor
+ *
* @param {Type} type the type of domain object to create
* @param {DomainObject} parent the domain object that should
* act as a container for the newly-created object
@@ -49,78 +52,84 @@ define(
* of the newly-created domain object
*/
function CreateAction(type, parent, context, dialogService, creationService, policyService) {
+ this.metadata = {
+ key: 'create',
+ glyph: type.getGlyph(),
+ name: type.getName(),
+ type: type.getKey(),
+ description: type.getDescription(),
+ context: context
+ };
+
+ this.type = type;
+ this.parent = parent;
+ this.policyService = policyService;
+ this.dialogService = dialogService;
+ this.creationService = creationService;
+ }
+
+ /**
+ * Create a new object of the given type.
+ * This will prompt for user input first.
+ */
+ CreateAction.prototype.perform = function () {
/*
Overview of steps in object creation:
1. Show dialog
- a. Prepare dialog contents
- b. Invoke dialogService
+ a. Prepare dialog contents
+ b. Invoke dialogService
2. Create new object in persistence service
- a. Generate UUID
- b. Store model
+ a. Generate UUID
+ b. Store model
3. Mutate destination container
- a. Get mutation capability
- b. Add new id to composition
+ a. Get mutation capability
+ b. Add new id to composition
4. Persist destination container
- a. ...use persistence capability.
+ a. ...use persistence capability.
*/
- function perform() {
- // The wizard will handle creating the form model based
- // on the type...
- var wizard = new CreateWizard(type, parent, policyService);
+ // The wizard will handle creating the form model based
+ // on the type...
+ var wizard =
+ new CreateWizard(this.type, this.parent, this.policyService),
+ self = this;
- // Create and persist the new object, based on user
- // input.
- function persistResult(formValue) {
- var parent = wizard.getLocation(formValue),
- newModel = wizard.createModel(formValue);
- return creationService.createObject(newModel, parent);
- }
-
- function doNothing() {
- // Create cancelled, do nothing
- return false;
- }
-
- return dialogService.getUserInput(
- wizard.getFormStructure(),
- wizard.getInitialFormValue()
- ).then(persistResult, doNothing);
+ // Create and persist the new object, based on user
+ // input.
+ function persistResult(formValue) {
+ var parent = wizard.getLocation(formValue),
+ newModel = wizard.createModel(formValue);
+ return self.creationService.createObject(newModel, parent);
}
- return {
- /**
- * Create a new object of the given type.
- * This will prompt for user input first.
- * @method
- * @memberof CreateAction
- */
- perform: perform,
+ function doNothing() {
+ // Create cancelled, do nothing
+ return false;
+ }
- /**
- * Get metadata about this action. This includes fields:
- * * `name`: Human-readable name
- * * `key`: Machine-readable identifier ("create")
- * * `glyph`: Glyph to use as an icon for this action
- * * `description`: Human-readable description
- * * `context`: The context in which this action will be performed.
- *
- * @return {object} metadata about the create action
- */
- getMetadata: function () {
- return {
- key: 'create',
- glyph: type.getGlyph(),
- name: type.getName(),
- type: type.getKey(),
- description: type.getDescription(),
- context: context
- };
- }
- };
- }
+ return this.dialogService.getUserInput(
+ wizard.getFormStructure(),
+ wizard.getInitialFormValue()
+ ).then(persistResult, doNothing);
+ };
+
+
+ /**
+ * Metadata associated with a Create action.
+ * @typedef {ActionMetadata} CreateActionMetadata
+ * @property {string} type the key for the type of domain object
+ * to be created
+ */
+
+ /**
+ * Get metadata about this action.
+ * @returns {CreateActionMetadata} metadata about this action
+ */
+ CreateAction.prototype.getMetadata = function () {
+ return this.metadata;
+ };
return CreateAction;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/src/creation/CreateActionProvider.js b/platform/commonUI/browse/src/creation/CreateActionProvider.js
index dcc98b8e95..4ca2bce59f 100644
--- a/platform/commonUI/browse/src/creation/CreateActionProvider.js
+++ b/platform/commonUI/browse/src/creation/CreateActionProvider.js
@@ -33,7 +33,10 @@ define(
* The CreateActionProvider is an ActionProvider which introduces
* a Create action for each creatable domain object type.
*
+ * @memberof platform/commonUI/browse
* @constructor
+ * @implements {ActionService}
+ *
* @param {TypeService} typeService the type service, used to discover
* available types
* @param {DialogService} dialogService the dialog service, used by
@@ -44,44 +47,41 @@ define(
* object creation.
*/
function CreateActionProvider(typeService, dialogService, creationService, policyService) {
- return {
- /**
- * Get all Create actions which are applicable in the provided
- * context.
- * @memberof CreateActionProvider
- * @method
- * @returns {CreateAction[]}
- */
- getActions: function (actionContext) {
- var context = actionContext || {},
- key = context.key,
- destination = context.domainObject;
-
- // We only provide Create actions, and we need a
- // domain object to serve as the container for the
- // newly-created object (although the user may later
- // make a different selection)
- if (key !== 'create' || !destination) {
- return [];
- }
-
- // Introduce one create action per type
- return typeService.listTypes().filter(function (type) {
- return type.hasFeature("creation");
- }).map(function (type) {
- return new CreateAction(
- type,
- destination,
- context,
- dialogService,
- creationService,
- policyService
- );
- });
- }
- };
+ this.typeService = typeService;
+ this.dialogService = dialogService;
+ this.creationService = creationService;
+ this.policyService = policyService;
}
+ CreateActionProvider.prototype.getActions = function (actionContext) {
+ var context = actionContext || {},
+ key = context.key,
+ destination = context.domainObject,
+ self = this;
+
+ // We only provide Create actions, and we need a
+ // domain object to serve as the container for the
+ // newly-created object (although the user may later
+ // make a different selection)
+ if (key !== 'create' || !destination) {
+ return [];
+ }
+
+ // Introduce one create action per type
+ return this.typeService.listTypes().filter(function (type) {
+ return type.hasFeature("creation");
+ }).map(function (type) {
+ return new CreateAction(
+ type,
+ destination,
+ context,
+ self.dialogService,
+ self.creationService,
+ self.policyService
+ );
+ });
+ };
+
return CreateActionProvider;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/src/creation/CreateMenuController.js b/platform/commonUI/browse/src/creation/CreateMenuController.js
index 2dace415df..624764c2e4 100644
--- a/platform/commonUI/browse/src/creation/CreateMenuController.js
+++ b/platform/commonUI/browse/src/creation/CreateMenuController.js
@@ -34,6 +34,7 @@ define(
* set of Create actions based on the currently-selected
* domain object.
*
+ * @memberof platform/commonUI/browse
* @constructor
*/
function CreateMenuController($scope) {
@@ -55,4 +56,4 @@ define(
return CreateMenuController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/src/creation/CreateWizard.js b/platform/commonUI/browse/src/creation/CreateWizard.js
index 29fe953e18..4073ed7e90 100644
--- a/platform/commonUI/browse/src/creation/CreateWizard.js
+++ b/platform/commonUI/browse/src/creation/CreateWizard.js
@@ -21,12 +21,6 @@
*****************************************************************************/
/*global define*/
-/**
- * Defines the CreateWizard, used by the CreateAction to
- * populate the form shown in dialog based on the created type.
- *
- * @module core/action/create-wizard
- */
define(
function () {
'use strict';
@@ -37,113 +31,118 @@ define(
* @param {TypeImpl} type the type of domain object to be created
* @param {DomainObject} parent the domain object to serve as
* the initial parent for the created object, in the dialog
+ * @memberof platform/commonUI/browse
* @constructor
- * @memberof module:core/action/create-wizard
*/
function CreateWizard(type, parent, policyService) {
- var model = type.getInitialModel(),
- properties = type.getProperties();
+ this.type = type;
+ this.model = type.getInitialModel();
+ this.properties = type.getProperties();
+ this.parent = parent;
+ this.policyService = policyService;
+ }
+
+ /**
+ * Get the form model for this wizard; this is a description
+ * that will be rendered to an HTML form. See the
+ * platform/forms bundle
+ *
+ * @return {FormModel} formModel the form model to
+ * show in the create dialog
+ */
+ CreateWizard.prototype.getFormStructure = function () {
+ var sections = [],
+ type = this.type,
+ policyService = this.policyService;
function validateLocation(locatingObject) {
var locatingType = locatingObject &&
- locatingObject.getCapability('type');
+ locatingObject.getCapability('type');
return locatingType && policyService.allow(
- "composition",
- locatingType,
- type
- );
+ "composition",
+ locatingType,
+ type
+ );
}
+ sections.push({
+ name: "Properties",
+ rows: this.properties.map(function (property, index) {
+ // Property definition is same as form row definition
+ var row = Object.create(property.getDefinition());
+
+ // Use index as the key into the formValue;
+ // this correlates to the indexing provided by
+ // getInitialFormValue
+ row.key = index;
+
+ return row;
+ })
+ });
+
+ // Ensure there is always a "save in" section
+ sections.push({ name: 'Location', rows: [{
+ name: "Save In",
+ control: "locator",
+ validate: validateLocation,
+ key: "createParent"
+ }]});
+
return {
- /**
- * Get the form model for this wizard; this is a description
- * that will be rendered to an HTML form. See the
- * platform/forms bundle
- *
- * @return {FormModel} formModel the form model to
- * show in the create dialog
- */
- getFormStructure: function () {
- var sections = [];
-
- sections.push({
- name: "Properties",
- rows: properties.map(function (property, index) {
- // Property definition is same as form row definition
- var row = Object.create(property.getDefinition());
-
- // Use index as the key into the formValue;
- // this correlates to the indexing provided by
- // getInitialFormValue
- row.key = index;
-
- return row;
- })
- });
-
- // Ensure there is always a "save in" section
- sections.push({ name: 'Location', rows: [{
- name: "Save In",
- control: "locator",
- validate: validateLocation,
- key: "createParent"
- }]});
-
- return {
- sections: sections,
- name: "Create a New " + type.getName()
- };
- },
- /**
- * Get the initial value for the form being described.
- * This will include the values for all properties described
- * in the structure.
- *
- * @returns {object} the initial value of the form
- */
- getInitialFormValue: function () {
- // Start with initial values for properties
- var formValue = properties.map(function (property) {
- return property.getValue(model);
- });
-
- // Include the createParent
- formValue.createParent = parent;
-
- return formValue;
- },
- /**
- * Based on a populated form, get the domain object which
- * should be used as a parent for the newly-created object.
- * @return {DomainObject}
- */
- getLocation: function (formValue) {
- return formValue.createParent || parent;
- },
- /**
- * Create the domain object model for a newly-created object,
- * based on user input read from a formModel.
- * @return {object} the domain object' model
- */
- createModel: function (formValue) {
- // Clone
- var newModel = JSON.parse(JSON.stringify(model));
-
- // Always use the type from the type definition
- newModel.type = type.getKey();
-
- // Update all properties
- properties.forEach(function (property, index) {
- property.setValue(newModel, formValue[index]);
- });
-
- return newModel;
- }
+ sections: sections,
+ name: "Create a New " + this.type.getName()
};
+ };
+ /**
+ * Get the initial value for the form being described.
+ * This will include the values for all properties described
+ * in the structure.
+ *
+ * @returns {object} the initial value of the form
+ */
+ CreateWizard.prototype.getInitialFormValue = function () {
+ // Start with initial values for properties
+ var model = this.model,
+ formValue = this.properties.map(function (property) {
+ return property.getValue(model);
+ });
- }
+ // Include the createParent
+ formValue.createParent = this.parent;
+
+ return formValue;
+ };
+
+ /**
+ * Based on a populated form, get the domain object which
+ * should be used as a parent for the newly-created object.
+ * @return {DomainObject}
+ */
+ CreateWizard.prototype.getLocation = function (formValue) {
+ return formValue.createParent || this.parent;
+ };
+
+ /**
+ * Create the domain object model for a newly-created object,
+ * based on user input read from a formModel.
+ * @return {object} the domain object model
+ */
+ CreateWizard.prototype.createModel = function (formValue) {
+ // Clone
+ var newModel = JSON.parse(JSON.stringify(this.model));
+
+ // Always use the type from the type definition
+ newModel.type = this.type.getKey();
+
+ // Update all properties
+ this.properties.forEach(function (property, index) {
+ property.setValue(newModel, formValue[index]);
+ });
+
+ return newModel;
+ };
return CreateWizard;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/src/creation/CreationService.js b/platform/commonUI/browse/src/creation/CreationService.js
index 015573c8bd..110a49c216 100644
--- a/platform/commonUI/browse/src/creation/CreationService.js
+++ b/platform/commonUI/browse/src/creation/CreationService.js
@@ -39,15 +39,45 @@ define(
* persisting new domain objects. Handles all actual object
* mutation and persistence associated with domain object
* creation.
+ * @memberof platform/commonUI/browse
* @constructor
*/
function CreationService(persistenceService, $q, $log) {
+ this.persistenceService = persistenceService;
+ this.$q = $q;
+ this.$log = $log;
+ }
+
+ /**
+ * Create a new domain object with the provided model, as
+ * a member of the provided parent domain object's composition.
+ * This parent will additionally determine which persistence
+ * space an object is created within (as it is possible to
+ * have multiple persistence spaces attached.)
+ *
+ * @param {object} model the model for the newly-created
+ * domain object
+ * @param {DomainObject} parent the domain object which
+ * should contain the newly-created domain object
+ * in its composition
+ * @return {Promise} a promise that will resolve when the domain
+ * object has been created
+ */
+ CreationService.prototype.createObject = function (model, parent) {
+ var persistence = parent.getCapability("persistence"),
+ self = this;
+
+ // Store the location of an object relative to it's parent.
+ function addLocationToModel(modelId, model, parent) {
+ model.location = parent.getId();
+ return model;
+ }
// Persist the new domain object's model; it will be fully
// constituted as a domain object when loaded back, as all
// domain object models are.
function doPersist(space, id, model) {
- return persistenceService.createObject(
+ return self.persistenceService.createObject(
space,
id,
model
@@ -66,14 +96,14 @@ define(
}
} else {
// This is abnormal; composition should be an array
- $log.warn(NO_COMPOSITION_WARNING + parent.getId());
+ self.$log.warn(NO_COMPOSITION_WARNING + parent.getId());
return false; // Cancel mutation
}
});
- return $q.when(mutatationResult).then(function (result) {
+ return self.$q.when(mutatationResult).then(function (result) {
if (!result) {
- $log.error("Could not mutate " + parent.getId());
+ self.$log.error("Could not mutate " + parent.getId());
return undefined;
}
@@ -93,49 +123,28 @@ define(
});
}
- // Create a new domain object with the provided model as a
- // member of the specified parent's composition
- function createObject(model, parent) {
- var persistence = parent.getCapability("persistence");
-
- // We need the parent's persistence capability to determine
- // what space to create the new object's model in.
- if (!persistence) {
- $log.warn(NON_PERSISTENT_WARNING);
- return $q.reject(new Error(NON_PERSISTENT_WARNING));
- }
-
- // We create a new domain object in three sequential steps:
- // 1. Get a new UUID for the object
- // 2. Create a model with that ID in the persistence space
- // 3. Add that ID to
- return $q.when(
- uuid()
- ).then(function (id) {
- return doPersist(persistence.getSpace(), id, model);
- }).then(function (id) {
- return addToComposition(id, parent, persistence);
- });
+ // We need the parent's persistence capability to determine
+ // what space to create the new object's model in.
+ if (!persistence) {
+ self.$log.warn(NON_PERSISTENT_WARNING);
+ return self.$q.reject(new Error(NON_PERSISTENT_WARNING));
}
- return {
- /**
- * Create a new domain object with the provided model, as
- * a member of the provided parent domain object's composition.
- * This parent will additionally determine which persistence
- * space an object is created within (as it is possible to
- * have multiple persistence spaces attached.)
- *
- * @param {object} model the model for the newly-created
- * domain object
- * @param {DomainObject} parent the domain object which
- * should contain the newly-created domain object
- * in its composition
- */
- createObject: createObject
- };
- }
+ // We create a new domain object in three sequential steps:
+ // 1. Get a new UUID for the object
+ // 2. Create a model with that ID in the persistence space
+ // 3. Add that ID to
+ return self.$q.when(uuid()).then(function (id) {
+ model = addLocationToModel(id, model, parent);
+ return doPersist(persistence.getSpace(), id, model);
+ }).then(function (id) {
+ return addToComposition(id, parent, persistence);
+ });
+ };
+
+
return CreationService;
}
);
+
diff --git a/platform/commonUI/browse/src/creation/LocatorController.js b/platform/commonUI/browse/src/creation/LocatorController.js
index c7104956ea..d6335f9bd1 100644
--- a/platform/commonUI/browse/src/creation/LocatorController.js
+++ b/platform/commonUI/browse/src/creation/LocatorController.js
@@ -30,6 +30,7 @@ define(
* Controller for the "locator" control, which provides the
* user with the ability to select a domain object as the
* destination for a newly-created object in the Create menu.
+ * @memberof platform/commonUI/browse
* @constructor
*/
function LocatorController($scope) {
@@ -79,3 +80,4 @@ define(
return LocatorController;
}
);
+
diff --git a/platform/commonUI/browse/src/navigation/NavigateAction.js b/platform/commonUI/browse/src/navigation/NavigateAction.js
index 779a83044a..7b258afafe 100644
--- a/platform/commonUI/browse/src/navigation/NavigateAction.js
+++ b/platform/commonUI/browse/src/navigation/NavigateAction.js
@@ -31,32 +31,34 @@ define(
/**
* The navigate action navigates to a specific domain object.
+ * @memberof platform/commonUI/browse
* @constructor
+ * @implements {Action}
*/
function NavigateAction(navigationService, $q, context) {
- var domainObject = context.domainObject;
-
- function perform() {
- // Set navigation, and wrap like a promise
- return $q.when(navigationService.setNavigation(domainObject));
- }
-
- return {
- /**
- * Navigate to the object described in the context.
- * @returns {Promise} a promise that is resolved once the
- * navigation has been updated
- */
- perform: perform
- };
+ this.domainObject = context.domainObject;
+ this.$q = $q;
+ this.navigationService = navigationService;
}
+ /**
+ * Navigate to the object described in the context.
+ * @returns {Promise} a promise that is resolved once the
+ * navigation has been updated
+ */
+ NavigateAction.prototype.perform = function () {
+ // Set navigation, and wrap like a promise
+ return this.$q.when(
+ this.navigationService.setNavigation(this.domainObject)
+ );
+ };
+
/**
* Navigate as an action is only applicable when a domain object
* is described in the action context.
* @param {ActionContext} context the context in which the action
* will be performed
- * @returns true if applicable
+ * @returns {boolean} true if applicable
*/
NavigateAction.appliesTo = function (context) {
return context.domainObject !== undefined;
@@ -64,4 +66,4 @@ define(
return NavigateAction;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/src/navigation/NavigationService.js b/platform/commonUI/browse/src/navigation/NavigationService.js
index c8c76857b8..87e5582ef7 100644
--- a/platform/commonUI/browse/src/navigation/NavigationService.js
+++ b/platform/commonUI/browse/src/navigation/NavigationService.js
@@ -32,68 +32,58 @@ define(
/**
* The navigation service maintains the application's current
* navigation state, and allows listening for changes thereto.
+ * @memberof platform/commonUI/browse
* @constructor
*/
function NavigationService() {
- var navigated,
- callbacks = [];
+ this.navigated = undefined;
+ this.callbacks = [];
+ }
- // Getter for current navigation
- function getNavigation() {
- return navigated;
- }
+ /**
+ * Get the current navigation state.
+ * @returns {DomainObject} the object that is navigated-to
+ */
+ NavigationService.prototype.getNavigation = function () {
+ return this.navigated;
+ };
- // Setter for navigation; invokes callbacks
- function setNavigation(value) {
- if (navigated !== value) {
- navigated = value;
- callbacks.forEach(function (callback) {
- callback(value);
- });
- }
- }
-
- // Adds a callback
- function addListener(callback) {
- callbacks.push(callback);
- }
-
- // Filters out a callback
- function removeListener(callback) {
- callbacks = callbacks.filter(function (cb) {
- return cb !== callback;
+ /**
+ * Set the current navigation state. This will invoke listeners.
+ * @param {DomainObject} domainObject the domain object to navigate to
+ */
+ NavigationService.prototype.setNavigation = function (value) {
+ if (this.navigated !== value) {
+ this.navigated = value;
+ this.callbacks.forEach(function (callback) {
+ callback(value);
});
}
+ };
- return {
- /**
- * Get the current navigation state.
- */
- getNavigation: getNavigation,
- /**
- * Set the current navigation state. Thiswill invoke listeners.
- * @param {DomainObject} value the domain object to navigate
- * to
- */
- setNavigation: setNavigation,
- /**
- * Listen for changes in navigation. The passed callback will
- * be invoked with the new domain object of navigation when
- * this changes.
- * @param {function} callback the callback to invoke when
- * navigation state changes
- */
- addListener: addListener,
- /**
- * Stop listening for changes in navigation state.
- * @param {function} callback the callback which should
- * no longer be invoked when navigation state
- * changes
- */
- removeListener: removeListener
- };
- }
+ /**
+ * Listen for changes in navigation. The passed callback will
+ * be invoked with the new domain object of navigation when
+ * this changes.
+ * @param {function} callback the callback to invoke when
+ * navigation state changes
+ */
+ NavigationService.prototype.addListener = function (callback) {
+ this.callbacks.push(callback);
+ };
+
+ /**
+ * Stop listening for changes in navigation state.
+ * @param {function} callback the callback which should
+ * no longer be invoked when navigation state
+ * changes
+ */
+ NavigationService.prototype.removeListener = function (callback) {
+ this.callbacks = this.callbacks.filter(function (cb) {
+ return cb !== callback;
+ });
+ };
return NavigationService;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/src/windowing/FullscreenAction.js b/platform/commonUI/browse/src/windowing/FullscreenAction.js
index efba99520b..82d92fbd40 100644
--- a/platform/commonUI/browse/src/windowing/FullscreenAction.js
+++ b/platform/commonUI/browse/src/windowing/FullscreenAction.js
@@ -35,36 +35,32 @@ define(
/**
* The fullscreen action toggles between fullscreen display
* and regular in-window display.
+ * @memberof platform/commonUI/browse
* @constructor
+ * @implements {Action}
*/
function FullscreenAction(context) {
- return {
- /**
- * Toggle full screen state
- */
- perform: function () {
- screenfull.toggle();
- },
- /**
- * Get metadata about this action, including the
- * applicable glyph to display.
- */
- getMetadata: function () {
- // We override getMetadata, because the glyph and
- // description need to be determined at run-time
- // based on whether or not we are currently
- // full screen.
- var metadata = Object.create(FullscreenAction);
- metadata.glyph = screenfull.isFullscreen ? "_" : "z";
- metadata.description = screenfull.isFullscreen ?
- EXIT_FULLSCREEN : ENTER_FULLSCREEN;
- metadata.group = "windowing";
- metadata.context = context;
- return metadata;
- }
- };
+ this.context = context;
}
+ FullscreenAction.prototype.perform = function () {
+ screenfull.toggle();
+ };
+
+ FullscreenAction.prototype.getMetadata = function () {
+ // We override getMetadata, because the glyph and
+ // description need to be determined at run-time
+ // based on whether or not we are currently
+ // full screen.
+ var metadata = Object.create(FullscreenAction);
+ metadata.glyph = screenfull.isFullscreen ? "_" : "z";
+ metadata.description = screenfull.isFullscreen ?
+ EXIT_FULLSCREEN : ENTER_FULLSCREEN;
+ metadata.group = "windowing";
+ metadata.context = this.context;
+ return metadata;
+ };
+
return FullscreenAction;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/src/windowing/NewTabAction.js b/platform/commonUI/browse/src/windowing/NewTabAction.js
index 8616a89711..301c204bbd 100644
--- a/platform/commonUI/browse/src/windowing/NewTabAction.js
+++ b/platform/commonUI/browse/src/windowing/NewTabAction.js
@@ -33,35 +33,29 @@ define(
/**
* The new tab action allows a domain object to be opened
* into a new browser tab.
+ * @memberof platform/commonUI/browse
* @constructor
+ * @implements {Action}
*/
function NewTabAction(urlService, $window, context) {
- // Returns the selected domain object
- // when using the context menu or the top right button
- // based on the context and the existance of the object
- // It is set to object an returned
- function getSelectedObject() {
- var object;
- if (context.selectedObject) {
- object = context.selectedObject;
- } else {
- object = context.domainObject;
- }
- return object;
- }
-
- return {
- // Performs the open in new tab function
- // By calling the url service, the mode needed
- // (browse) and the domainObject is passed in and
- // the path is returned and opened in a new tab
- perform: function () {
- $window.open(urlService.urlForNewTab("browse", getSelectedObject()),
- "_blank");
- }
+ context = context || {};
+
+ this.urlService = urlService;
+ this.open = function () {
+ $window.open.apply($window, arguments);
};
+
+ // Choose the object to be opened into a new tab
+ this.domainObject = context.selectedObject || context.domainObject;
}
+ NewTabAction.prototype.perform = function () {
+ this.open(
+ this.urlService.urlForNewTab("browse", this.domainObject),
+ "_blank"
+ );
+ };
+
return NewTabAction;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/src/windowing/WindowTitler.js b/platform/commonUI/browse/src/windowing/WindowTitler.js
index 9db65e5b0e..4ce448cb1e 100644
--- a/platform/commonUI/browse/src/windowing/WindowTitler.js
+++ b/platform/commonUI/browse/src/windowing/WindowTitler.js
@@ -29,6 +29,7 @@ define(
/**
* Updates the title of the current window to reflect the name
* of the currently navigated-to domain object.
+ * @memberof platform/commonUI/browse
* @constructor
*/
function WindowTitler(navigationService, $rootScope, $document) {
@@ -49,4 +50,4 @@ define(
return WindowTitler;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/browse/test/creation/CreationServiceSpec.js b/platform/commonUI/browse/test/creation/CreationServiceSpec.js
index 277b195eaf..7f15afe061 100644
--- a/platform/commonUI/browse/test/creation/CreationServiceSpec.js
+++ b/platform/commonUI/browse/test/creation/CreationServiceSpec.js
@@ -38,6 +38,7 @@ define(
mockMutationCapability,
mockPersistenceCapability,
mockCompositionCapability,
+ mockContextCapability,
mockCapabilities,
creationService;
@@ -87,10 +88,15 @@ define(
"composition",
["invoke"]
);
+ mockContextCapability = jasmine.createSpyObj(
+ "context",
+ ["getPath"]
+ );
mockCapabilities = {
mutation: mockMutationCapability,
persistence: mockPersistenceCapability,
- composition: mockCompositionCapability
+ composition: mockCompositionCapability,
+ context: mockContextCapability
};
mockPersistenceService.createObject.andReturn(
@@ -103,6 +109,7 @@ define(
mockParentObject.useCapability.andCallFake(function (key, value) {
return mockCapabilities[key].invoke(value);
});
+ mockParentObject.getId.andReturn('parentId');
mockPersistenceCapability.persist.andReturn(
mockPromise(true)
@@ -194,7 +201,16 @@ define(
expect(mockLog.error).toHaveBeenCalled();
});
+ it("stores location on new domainObjects", function () {
+ var model = { name: "my model" },
+ objectPromise = creationService.createObject(
+ model,
+ mockParentObject
+ );
+
+ expect(model.location).toBe('parentId');
+ });
});
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/dialog/src/DialogService.js b/platform/commonUI/dialog/src/DialogService.js
index d0c2c83f42..25e8943c06 100644
--- a/platform/commonUI/dialog/src/DialogService.js
+++ b/platform/commonUI/dialog/src/DialogService.js
@@ -22,7 +22,9 @@
/*global define*/
/**
- * Module defining DialogService. Created by vwoeltje on 11/10/14.
+ * This bundle implements the dialog service, which can be used to
+ * launch dialogs for user input & notifications.
+ * @namespace platform/commonUI/dialog
*/
define(
[],
@@ -32,128 +34,130 @@ define(
* The dialog service is responsible for handling window-modal
* communication with the user, such as displaying forms for user
* input.
+ * @memberof platform/commonUI/dialog
* @constructor
*/
function DialogService(overlayService, $q, $log) {
- var overlay,
- dialogVisible = false;
-
- // Stop showing whatever overlay is currently active
- // (e.g. because the user hit cancel)
- function dismiss() {
- if (overlay) {
- overlay.dismiss();
- }
- dialogVisible = false;
- }
-
- function getDialogResponse(key, model, resultGetter) {
- // We will return this result as a promise, because user
- // input is asynchronous.
- var deferred = $q.defer(),
- overlayModel;
-
- // Confirm function; this will be passed in to the
- // overlay-dialog template and associated with a
- // OK button click
- function confirm(value) {
- // Pass along the result
- deferred.resolve(resultGetter ? resultGetter() : value);
-
- // Stop showing the dialog
- dismiss();
- }
-
- // Cancel function; this will be passed in to the
- // overlay-dialog template and associated with a
- // Cancel or X button click
- function cancel() {
- deferred.reject();
- dismiss();
- }
-
- // Add confirm/cancel callbacks
- model.confirm = confirm;
- model.cancel = cancel;
-
- if (dialogVisible) {
- // Only one dialog should be shown at a time.
- // The application design should be such that
- // we never even try to do this.
- $log.warn([
- "Dialog already showing; ",
- "unable to show ",
- model.name
- ].join(""));
- deferred.reject();
- } else {
- // Add the overlay using the OverlayService, which
- // will handle actual insertion into the DOM
- overlay = overlayService.createOverlay(
- key,
- model
- );
-
- // Track that a dialog is already visible, to
- // avoid spawning multiple dialogs at once.
- dialogVisible = true;
- }
-
- return deferred.promise;
- }
-
- function getUserInput(formModel, value) {
- var overlayModel = {
- title: formModel.name,
- message: formModel.message,
- structure: formModel,
- value: value
- };
-
- // Provide result from the model
- function resultGetter() {
- return overlayModel.value;
- }
-
- // Show the overlay-dialog
- return getDialogResponse(
- "overlay-dialog",
- overlayModel,
- resultGetter
- );
- }
-
- function getUserChoice(dialogModel) {
- // Show the overlay-options dialog
- return getDialogResponse(
- "overlay-options",
- { dialog: dialogModel }
- );
- }
-
- return {
- /**
- * Request user input via a window-modal dialog.
- *
- * @param {FormModel} formModel a description of the form
- * to be shown (see platform/forms)
- * @param {object} value the initial state of the form
- * @returns {Promise} a promsie for the form value that the
- * user has supplied; this may be rejected if
- * user input cannot be obtained (for instance,
- * because the user cancelled the dialog)
- */
- getUserInput: getUserInput,
- /**
- * Request that the user chooses from a set of options,
- * which will be shown as buttons.
- *
- * @param dialogModel a description of the dialog to show
- */
- getUserChoice: getUserChoice
- };
+ this.overlayService = overlayService;
+ this.$q = $q;
+ this.$log = $log;
+ this.overlay = undefined;
+ this.dialogVisible = false;
}
+ // Stop showing whatever overlay is currently active
+ // (e.g. because the user hit cancel)
+ DialogService.prototype.dismiss = function () {
+ var overlay = this.overlay;
+ if (overlay) {
+ overlay.dismiss();
+ }
+ this.dialogVisible = false;
+ };
+
+ DialogService.prototype.getDialogResponse = function (key, model, resultGetter) {
+ // We will return this result as a promise, because user
+ // input is asynchronous.
+ var deferred = this.$q.defer(),
+ self = this;
+
+ // Confirm function; this will be passed in to the
+ // overlay-dialog template and associated with a
+ // OK button click
+ function confirm(value) {
+ // Pass along the result
+ deferred.resolve(resultGetter ? resultGetter() : value);
+
+ // Stop showing the dialog
+ self.dismiss();
+ }
+
+ // Cancel function; this will be passed in to the
+ // overlay-dialog template and associated with a
+ // Cancel or X button click
+ function cancel() {
+ deferred.reject();
+ self.dismiss();
+ }
+
+ // Add confirm/cancel callbacks
+ model.confirm = confirm;
+ model.cancel = cancel;
+
+ if (this.dialogVisible) {
+ // Only one dialog should be shown at a time.
+ // The application design should be such that
+ // we never even try to do this.
+ this.$log.warn([
+ "Dialog already showing; ",
+ "unable to show ",
+ model.name
+ ].join(""));
+ deferred.reject();
+ } else {
+ // Add the overlay using the OverlayService, which
+ // will handle actual insertion into the DOM
+ this.overlay = this.overlayService.createOverlay(
+ key,
+ model
+ );
+
+ // Track that a dialog is already visible, to
+ // avoid spawning multiple dialogs at once.
+ this.dialogVisible = true;
+ }
+
+ return deferred.promise;
+ };
+
+ /**
+ * Request user input via a window-modal dialog.
+ *
+ * @param {FormModel} formModel a description of the form
+ * to be shown (see platform/forms)
+ * @param {object} value the initial state of the form
+ * @returns {Promise} a promise for the form value that the
+ * user has supplied; this may be rejected if
+ * user input cannot be obtained (for instance,
+ * because the user cancelled the dialog)
+ */
+ DialogService.prototype.getUserInput = function (formModel, value) {
+ var overlayModel = {
+ title: formModel.name,
+ message: formModel.message,
+ structure: formModel,
+ value: value
+ };
+
+ // Provide result from the model
+ function resultGetter() {
+ return overlayModel.value;
+ }
+
+ // Show the overlay-dialog
+ return this.getDialogResponse(
+ "overlay-dialog",
+ overlayModel,
+ resultGetter
+ );
+ };
+
+ /**
+ * Request that the user chooses from a set of options,
+ * which will be shown as buttons.
+ *
+ * @param dialogModel a description of the dialog to show
+ * @return {Promise} a promise for the user's choice
+ */
+ DialogService.prototype.getUserChoice = function (dialogModel) {
+ // Show the overlay-options dialog
+ return this.getDialogResponse(
+ "overlay-options",
+ { dialog: dialogModel }
+ );
+ };
+
+
return DialogService;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/dialog/src/OverlayService.js b/platform/commonUI/dialog/src/OverlayService.js
index b66bffa7dc..5faba5dcf6 100644
--- a/platform/commonUI/dialog/src/OverlayService.js
+++ b/platform/commonUI/dialog/src/OverlayService.js
@@ -43,57 +43,63 @@ define(
* particularly where a multiple-overlay effect is not specifically
* desired).
*
+ * @memberof platform/commonUI/dialog
* @constructor
*/
function OverlayService($document, $compile, $rootScope) {
- function createOverlay(key, overlayModel) {
- // Create a new scope for this overlay
- var scope = $rootScope.$new(),
- element;
+ this.$compile = $compile;
- // Stop showing the overlay; additionally, release the scope
- // that it uses.
- function dismiss() {
- scope.$destroy();
- element.remove();
- }
-
- // If no model is supplied, just fill in a default "cancel"
- overlayModel = overlayModel || { cancel: dismiss };
-
- // Populate the scope; will be passed directly to the template
- scope.overlay = overlayModel;
- scope.key = key;
-
- // Create the overlay element and add it to the document's body
- element = $compile(TEMPLATE)(scope);
- $document.find('body').prepend(element);
-
-
-
- return {
- dismiss: dismiss
- };
- }
-
- return {
- /**
- * Add a new overlay to the document. This will be
- * prepended to the document body; the overlay's
- * template (as pointed to by the `key` argument) is
- * responsible for having a useful z-order, and for
- * blocking user interactions if appropriate.
- *
- * @param {string} key the symbolic key which identifies
- * the template of the overlay to be shown
- * @param {object} overlayModel the model to pass to the
- * included overlay template (this will be passed
- * in via ng-model)
- */
- createOverlay: createOverlay
+ // Don't include $document and $rootScope directly;
+ // avoids https://docs.angularjs.org/error/ng/cpws
+ this.findBody = function () {
+ return $document.find('body');
+ };
+ this.newScope = function () {
+ return $rootScope.$new();
};
}
+ /**
+ * Add a new overlay to the document. This will be
+ * prepended to the document body; the overlay's
+ * template (as pointed to by the `key` argument) is
+ * responsible for having a useful z-order, and for
+ * blocking user interactions if appropriate.
+ *
+ * @param {string} key the symbolic key which identifies
+ * the template of the overlay to be shown
+ * @param {object} overlayModel the model to pass to the
+ * included overlay template (this will be passed
+ * in via ng-model)
+ */
+ OverlayService.prototype.createOverlay = function (key, overlayModel) {
+ // Create a new scope for this overlay
+ var scope = this.newScope(),
+ element;
+
+ // Stop showing the overlay; additionally, release the scope
+ // that it uses.
+ function dismiss() {
+ scope.$destroy();
+ element.remove();
+ }
+
+ // If no model is supplied, just fill in a default "cancel"
+ overlayModel = overlayModel || { cancel: dismiss };
+
+ // Populate the scope; will be passed directly to the template
+ scope.overlay = overlayModel;
+ scope.key = key;
+
+ // Create the overlay element and add it to the document's body
+ element = this.$compile(TEMPLATE)(scope);
+ this.findBody().prepend(element);
+
+ return {
+ dismiss: dismiss
+ };
+ };
+
return OverlayService;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/actions/CancelAction.js b/platform/commonUI/edit/src/actions/CancelAction.js
index 725f6ee6a7..a9e6effe9f 100644
--- a/platform/commonUI/edit/src/actions/CancelAction.js
+++ b/platform/commonUI/edit/src/actions/CancelAction.js
@@ -29,9 +29,26 @@ define(
* The "Cancel" action; the action triggered by clicking Cancel from
* Edit Mode. Exits the editing user interface and invokes object
* capabilities to persist the changes that have been made.
+ * @constructor
+ * @memberof platform/commonUI/edit
+ * @implements {Action}
*/
function CancelAction($location, urlService, context) {
- var domainObject = context.domainObject;
+ this.domainObject = context.domainObject;
+ this.$location = $location;
+ this.urlService = urlService;
+ }
+
+ /**
+ * Cancel editing.
+ *
+ * @returns {Promise} a promise that will be fulfilled when
+ * cancellation has completed
+ */
+ CancelAction.prototype.perform = function () {
+ var domainObject = this.domainObject,
+ $location = this.$location,
+ urlService = this.urlService;
// Look up the object's "editor.completion" capability;
// this is introduced by EditableDomainObject which is
@@ -56,25 +73,15 @@ define(
)));
}
- return {
- /**
- * Cancel editing.
- *
- * @returns {Promise} a promise that will be fulfilled when
- * cancellation has completed
- */
- perform: function () {
- return doCancel(getEditorCapability())
- .then(returnToBrowse);
- }
- };
- }
+ return doCancel(getEditorCapability())
+ .then(returnToBrowse);
+ };
/**
* Check if this action is applicable in a given context.
* This will ensure that a domain object is present in the context,
* and that this domain object is in Edit mode.
- * @returns true if applicable
+ * @returns {boolean} true if applicable
*/
CancelAction.appliesTo = function (context) {
var domainObject = (context || {}).domainObject;
@@ -84,4 +91,4 @@ define(
return CancelAction;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/actions/EditAction.js b/platform/commonUI/edit/src/actions/EditAction.js
index 38260469ae..86a8a75540 100644
--- a/platform/commonUI/edit/src/actions/EditAction.js
+++ b/platform/commonUI/edit/src/actions/EditAction.js
@@ -42,7 +42,9 @@ define(
* mode (typically triggered by the Edit button.) This will
* show the user interface for editing (by way of a change in
* route)
+ * @memberof platform/commonUI/edit
* @constructor
+ * @implements {Action}
*/
function EditAction($location, navigationService, $log, context) {
var domainObject = (context || {}).domainObject;
@@ -60,17 +62,19 @@ define(
return NULL_ACTION;
}
- return {
- /**
- * Enter edit mode.
- */
- perform: function () {
- navigationService.setNavigation(domainObject);
- $location.path("/edit");
- }
- };
+ this.domainObject = domainObject;
+ this.$location = $location;
+ this.navigationService = navigationService;
}
+ /**
+ * Enter edit mode.
+ */
+ EditAction.prototype.perform = function () {
+ this.navigationService.setNavigation(this.domainObject);
+ this.$location.path("/edit");
+ };
+
/**
* Check for applicability; verify that a domain object is present
* for this action to be performed upon.
@@ -87,4 +91,4 @@ define(
return EditAction;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/actions/LinkAction.js b/platform/commonUI/edit/src/actions/LinkAction.js
index f7d0087646..74abd2a93c 100644
--- a/platform/commonUI/edit/src/actions/LinkAction.js
+++ b/platform/commonUI/edit/src/actions/LinkAction.js
@@ -29,42 +29,43 @@ define(
/**
* Add one domain object to another's composition.
+ * @constructor
+ * @memberof platform/commonUI/edit
+ * @implements {Action}
*/
function LinkAction(context) {
- var domainObject = (context || {}).domainObject,
- selectedObject = (context || {}).selectedObject,
- selectedId = selectedObject && selectedObject.getId();
+ this.domainObject = (context || {}).domainObject;
+ this.selectedObject = (context || {}).selectedObject;
+ this.selectedId = this.selectedObject && this.selectedObject.getId();
+ }
+
+ LinkAction.prototype.perform = function () {
+ var self = this;
// Add this domain object's identifier
function addId(model) {
if (Array.isArray(model.composition) &&
- model.composition.indexOf(selectedId) < 0) {
- model.composition.push(selectedId);
+ model.composition.indexOf(self.selectedId) < 0) {
+ model.composition.push(self.selectedId);
}
}
// Persist changes to the domain object
function doPersist() {
- var persistence = domainObject.getCapability('persistence');
+ var persistence =
+ self.domainObject.getCapability('persistence');
return persistence.persist();
}
// Link these objects
function doLink() {
- return domainObject.useCapability("mutation", addId)
+ return self.domainObject.useCapability("mutation", addId)
.then(doPersist);
}
- return {
- /**
- * Perform this action.
- */
- perform: function () {
- return selectedId && doLink();
- }
- };
- }
+ return this.selectedId && doLink();
+ };
return LinkAction;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/actions/PropertiesAction.js b/platform/commonUI/edit/src/actions/PropertiesAction.js
index bb37727c0e..1134c23190 100644
--- a/platform/commonUI/edit/src/actions/PropertiesAction.js
+++ b/platform/commonUI/edit/src/actions/PropertiesAction.js
@@ -32,58 +32,58 @@ define(
'use strict';
/**
- * Construct an action which will allow an object's metadata to be
- * edited.
+ * Implements the "Edit Properties" action, which prompts the user
+ * to modify a domain object's properties.
*
* @param {DialogService} dialogService a service which will show the dialog
* @param {DomainObject} object the object to be edited
* @param {ActionContext} context the context in which this action is performed
+ * @memberof platform/commonUI/edit
+ * @implements {Action}
* @constructor
*/
function PropertiesAction(dialogService, context) {
- var object = context.domainObject;
+ this.domainObject = (context || {}).domainObject;
+ this.dialogService = dialogService;
+ }
+
+ PropertiesAction.prototype.perform = function () {
+ var type = this.domainObject.getCapability('type'),
+ domainObject = this.domainObject,
+ dialogService = this.dialogService;
// Persist modifications to this domain object
function doPersist() {
- var persistence = object.getCapability('persistence');
+ var persistence = domainObject.getCapability('persistence');
return persistence && persistence.persist();
}
// Update the domain object model based on user input
function updateModel(userInput, dialog) {
- return object.useCapability('mutation', function (model) {
+ return domainObject.useCapability('mutation', function (model) {
dialog.updateModel(model, userInput);
});
}
function showDialog(type) {
// Create a dialog object to generate the form structure, etc.
- var dialog = new PropertiesDialog(type, object.getModel());
+ var dialog =
+ new PropertiesDialog(type, domainObject.getModel());
// Show the dialog
return dialogService.getUserInput(
dialog.getFormStructure(),
dialog.getInitialFormValue()
).then(function (userInput) {
- // Update the model, if user input was provided
- return userInput && updateModel(userInput, dialog);
- }).then(function (result) {
- return result && doPersist();
- });
+ // Update the model, if user input was provided
+ return userInput && updateModel(userInput, dialog);
+ }).then(function (result) {
+ return result && doPersist();
+ });
}
- return {
- /**
- * Perform this action.
- * @return {Promise} a promise which will be
- * fulfilled when the action has completed.
- */
- perform: function () {
- var type = object.getCapability('type');
- return type && showDialog(type);
- }
- };
- }
+ return type && showDialog(type);
+ };
/**
* Filter this action for applicability against a given context.
@@ -106,3 +106,4 @@ define(
);
+
diff --git a/platform/commonUI/edit/src/actions/PropertiesDialog.js b/platform/commonUI/edit/src/actions/PropertiesDialog.js
index 8319efc315..97ee1f5c0a 100644
--- a/platform/commonUI/edit/src/actions/PropertiesDialog.js
+++ b/platform/commonUI/edit/src/actions/PropertiesDialog.js
@@ -21,12 +21,6 @@
*****************************************************************************/
/*global define*/
-/**
- * Defines the PropertiesDialog, used by the PropertiesAction to
- * populate the form shown in dialog based on the created type.
- *
- * @module common/actions/properties-dialog
- */
define(
function () {
'use strict';
@@ -37,58 +31,60 @@ define(
* @param {TypeImpl} type the type of domain object for which properties
* will be specified
* @param {DomainObject} the object for which properties will be set
+ * @memberof platform/commonUI/edit
* @constructor
- * @memberof module:common/actions/properties-dialog
*/
function PropertiesDialog(type, model) {
- var properties = type.getProperties();
-
- return {
- /**
- * Get sections provided by this dialog.
- * @return {FormStructure} the structure of this form
- */
- getFormStructure: function () {
- return {
- name: "Edit " + model.name,
- sections: [{
- name: "Properties",
- rows: properties.map(function (property, index) {
- // Property definition is same as form row definition
- var row = Object.create(property.getDefinition());
- row.key = index;
- return row;
- })
- }]
- };
- },
- /**
- * Get the initial state of the form shown by this dialog
- * (based on the object model)
- * @returns {object} initial state of the form
- */
- getInitialFormValue: function () {
- // Start with initial values for properties
- // Note that index needs to correlate to row.key
- // from getFormStructure
- return properties.map(function (property) {
- return property.getValue(model);
- });
- },
- /**
- * Update a domain object model based on the value of a form.
- */
- updateModel: function (model, formValue) {
- // Update all properties
- properties.forEach(function (property, index) {
- property.setValue(model, formValue[index]);
- });
- }
- };
-
-
+ this.type = type;
+ this.model = model;
+ this.properties = type.getProperties();
}
+ /**
+ * Get sections provided by this dialog.
+ * @return {FormStructure} the structure of this form
+ */
+ PropertiesDialog.prototype.getFormStructure = function () {
+ return {
+ name: "Edit " + this.model.name,
+ sections: [{
+ name: "Properties",
+ rows: this.properties.map(function (property, index) {
+ // Property definition is same as form row definition
+ var row = Object.create(property.getDefinition());
+ row.key = index;
+ return row;
+ })
+ }]
+ };
+ };
+
+ /**
+ * Get the initial state of the form shown by this dialog
+ * (based on the object model)
+ * @returns {object} initial state of the form
+ */
+ PropertiesDialog.prototype.getInitialFormValue = function () {
+ var model = this.model;
+
+ // Start with initial values for properties
+ // Note that index needs to correlate to row.key
+ // from getFormStructure
+ return this.properties.map(function (property) {
+ return property.getValue(model);
+ });
+ };
+
+ /**
+ * Update a domain object model based on the value of a form.
+ */
+ PropertiesDialog.prototype.updateModel = function (model, formValue) {
+ // Update all properties
+ this.properties.forEach(function (property, index) {
+ property.setValue(model, formValue[index]);
+ });
+ };
+
return PropertiesDialog;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/actions/RemoveAction.js b/platform/commonUI/edit/src/actions/RemoveAction.js
index e89ad3ed2d..21c290cd08 100644
--- a/platform/commonUI/edit/src/actions/RemoveAction.js
+++ b/platform/commonUI/edit/src/actions/RemoveAction.js
@@ -37,23 +37,37 @@ define(
*
* @param {DomainObject} object the object to be removed
* @param {ActionContext} context the context in which this action is performed
+ * @memberof platform/commonUI/edit
* @constructor
- * @memberof module:editor/actions/remove-action
+ * @implements {Action}
*/
function RemoveAction($q, navigationService, context) {
- var object = (context || {}).domainObject,
+ this.domainObject = (context || {}).domainObject;
+ this.$q = $q;
+ this.navigationService = navigationService;
+ }
+
+ /**
+ * Perform this action.
+ * @return {Promise} a promise which will be
+ * fulfilled when the action has completed.
+ */
+ RemoveAction.prototype.perform = function () {
+ var $q = this.$q,
+ navigationService = this.navigationService,
+ domainObject = this.domainObject,
ROOT_ID = "ROOT";
- /**
+ /*
* Check whether an object ID matches the ID of the object being
* removed (used to filter a parent's composition to handle the
* removal.)
*/
function isNotObject(otherObjectId) {
- return otherObjectId !== object.getId();
+ return otherObjectId !== domainObject.getId();
}
- /**
+ /*
* Mutate a parent object such that it no longer contains the object
* which is being removed.
*/
@@ -61,7 +75,7 @@ define(
model.composition = model.composition.filter(isNotObject);
}
- /**
+ /*
* Invoke persistence on a domain object. This will be called upon
* the removed object's parent (as its composition will have changed.)
*/
@@ -76,10 +90,10 @@ define(
// navigate back to parent of removed object.
function checkObjectNavigation(object, parentObject) {
// Traverse object starts at current location
- var traverseObject = navigationService.getNavigation();
+ var traverseObject = (navigationService).getNavigation();
// Stop at ROOT of folder path
- while(traverseObject.getId() !== ROOT_ID) {
+ while (traverseObject.getId() !== ROOT_ID) {
// If traverse object is object being removed
// navigate to parent of removed object
if (traverseObject.getId() === object.getId()) {
@@ -90,37 +104,25 @@ define(
traverseObject = traverseObject.getCapability('context').getParent();
}
}
-
- /**
+
+ /*
* Remove the object from its parent, as identified by its context
* capability.
- * @param {object} domain object being removed contextCapability
- gotten from the "context" capability of this object
*/
function removeFromContext(object) {
var contextCapability = object.getCapability('context'),
parent = contextCapability.getParent();
- // Navigates through/ascendant if deleting current object
- checkObjectNavigation(object, parent)
- $q.when(
+ checkObjectNavigation(object, parent);
+ return $q.when(
parent.useCapability('mutation', doMutate)
).then(function () {
return doPersist(parent);
});
}
- return {
- /**
- * Perform this action.
- * @return {module:core/promises.Promise} a promise which will be
- * fulfilled when the action has completed.
- */
- perform: function () {
- return $q.when(object)
- .then(removeFromContext);
- }
- };
- }
+ return $q.when(domainObject)
+ .then(removeFromContext);
+ };
// Object needs to have a parent for Remove to be applicable
RemoveAction.appliesTo = function (context) {
@@ -138,4 +140,4 @@ define(
return RemoveAction;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/actions/SaveAction.js b/platform/commonUI/edit/src/actions/SaveAction.js
index d5db593742..fa276bba4b 100644
--- a/platform/commonUI/edit/src/actions/SaveAction.js
+++ b/platform/commonUI/edit/src/actions/SaveAction.js
@@ -30,9 +30,27 @@ define(
* The "Save" action; the action triggered by clicking Save from
* Edit Mode. Exits the editing user interface and invokes object
* capabilities to persist the changes that have been made.
+ * @constructor
+ * @implements {Action}
+ * @memberof platform/commonUI/edit
*/
function SaveAction($location, urlService, context) {
- var domainObject = context.domainObject;
+ this.domainObject = (context || {}).domainObject;
+ this.$location = $location;
+ this.urlService = urlService;
+ }
+
+ /**
+ * Save changes and conclude editing.
+ *
+ * @returns {Promise} a promise that will be fulfilled when
+ * cancellation has completed
+ * @memberof platform/commonUI/edit.SaveAction#
+ */
+ SaveAction.prototype.perform = function () {
+ var domainObject = this.domainObject,
+ $location = this.$location,
+ urlService = this.urlService;
// Invoke any save behavior introduced by the editor capability;
// this is introduced by EditableDomainObject which is
@@ -51,18 +69,8 @@ define(
));
}
- return {
- /**
- * Save changes and conclude editing.
- *
- * @returns {Promise} a promise that will be fulfilled when
- * cancellation has completed
- */
- perform: function () {
- return doSave().then(returnToBrowse);
- }
- };
- }
+ return doSave().then(returnToBrowse);
+ };
/**
* Check if this action is applicable in a given context.
@@ -78,4 +86,4 @@ define(
return SaveAction;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/capabilities/EditableCompositionCapability.js b/platform/commonUI/edit/src/capabilities/EditableCompositionCapability.js
index 02276639d2..17dff58c0d 100644
--- a/platform/commonUI/edit/src/capabilities/EditableCompositionCapability.js
+++ b/platform/commonUI/edit/src/capabilities/EditableCompositionCapability.js
@@ -35,6 +35,9 @@ define(
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
+ * @constructor
+ * @memberof platform/commonUI/edit
+ * @implements {CompositionCapability}
*/
return function EditableCompositionCapability(
contextCapability,
@@ -54,4 +57,4 @@ define(
);
};
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/capabilities/EditableContextCapability.js b/platform/commonUI/edit/src/capabilities/EditableContextCapability.js
index 34ea3ee465..d0df90afc4 100644
--- a/platform/commonUI/edit/src/capabilities/EditableContextCapability.js
+++ b/platform/commonUI/edit/src/capabilities/EditableContextCapability.js
@@ -35,6 +35,9 @@ define(
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
+ * @constructor
+ * @memberof platform/commonUI/edit
+ * @implements {ContextCapability}
*/
return function EditableContextCapability(
contextCapability,
@@ -72,4 +75,4 @@ define(
return capability;
};
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/capabilities/EditableLookupCapability.js b/platform/commonUI/edit/src/capabilities/EditableLookupCapability.js
index 5571072b25..c92495dc3f 100644
--- a/platform/commonUI/edit/src/capabilities/EditableLookupCapability.js
+++ b/platform/commonUI/edit/src/capabilities/EditableLookupCapability.js
@@ -35,6 +35,8 @@ define(
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
+ * @constructor
+ * @memberof platform/commonUI/edit
*/
return function EditableLookupCapability(
contextCapability,
@@ -76,7 +78,7 @@ define(
// Wrap a returned value (see above); if it's a promise, wrap
// the resolved value.
function wrapResult(result) {
- return result.then ? // promise-like
+ return (result && result.then) ? // promise-like
result.then(makeEditable) :
makeEditable(result);
}
@@ -105,8 +107,10 @@ define(
// Wrap a method of this capability
function wrapMethod(fn) {
- capability[fn] =
- (idempotent ? oneTimeFunction : wrapFunction)(fn);
+ if (typeof capability[fn] === 'function') {
+ capability[fn] =
+ (idempotent ? oneTimeFunction : wrapFunction)(fn);
+ }
}
// Wrap all methods; return only editable domain objects.
@@ -115,4 +119,4 @@ define(
return capability;
};
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/capabilities/EditablePersistenceCapability.js b/platform/commonUI/edit/src/capabilities/EditablePersistenceCapability.js
index 5252ef1d44..42b08c72b1 100644
--- a/platform/commonUI/edit/src/capabilities/EditablePersistenceCapability.js
+++ b/platform/commonUI/edit/src/capabilities/EditablePersistenceCapability.js
@@ -35,6 +35,9 @@ define(
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
+ * @constructor
+ * @memberof platform/commonUI/edit
+ * @implements {PersistenceCapability}
*/
function EditablePersistenceCapability(
persistenceCapability,
@@ -62,4 +65,4 @@ define(
return EditablePersistenceCapability;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/capabilities/EditableRelationshipCapability.js b/platform/commonUI/edit/src/capabilities/EditableRelationshipCapability.js
index f61a54176c..3034301502 100644
--- a/platform/commonUI/edit/src/capabilities/EditableRelationshipCapability.js
+++ b/platform/commonUI/edit/src/capabilities/EditableRelationshipCapability.js
@@ -35,6 +35,9 @@ define(
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
+ * @constructor
+ * @memberof platform/commonUI/edit
+ * @implements {RelationshipCapability}
*/
return function EditableRelationshipCapability(
relationshipCapability,
@@ -54,4 +57,4 @@ define(
);
};
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/capabilities/EditorCapability.js b/platform/commonUI/edit/src/capabilities/EditorCapability.js
index e59fbcae8c..7094d1142c 100644
--- a/platform/commonUI/edit/src/capabilities/EditorCapability.js
+++ b/platform/commonUI/edit/src/capabilities/EditorCapability.js
@@ -39,27 +39,48 @@ define(
* Meant specifically for use by EditableDomainObject and the
* associated cache; the constructor signature is particular
* to a pattern used there and may contain unused arguments.
+ * @constructor
+ * @memberof platform/commonUI/edit
*/
- return function EditorCapability(
+ function EditorCapability(
persistenceCapability,
editableObject,
domainObject,
cache
) {
+ this.editableObject = editableObject;
+ this.domainObject = domainObject;
+ this.cache = cache;
+ }
- // Simulate Promise.resolve (or $q.when); the former
- // causes a delayed reaction from Angular (since it
- // does not trigger a digest) and the latter is not
- // readily accessible, since we're a few classes
- // removed from the layer which gets dependency
- // injection.
- function resolvePromise(value) {
- return (value && value.then) ? value : {
- then: function (callback) {
- return resolvePromise(callback(value));
- }
- };
- }
+ // Simulate Promise.resolve (or $q.when); the former
+ // causes a delayed reaction from Angular (since it
+ // does not trigger a digest) and the latter is not
+ // readily accessible, since we're a few classes
+ // removed from the layer which gets dependency
+ // injection.
+ function resolvePromise(value) {
+ return (value && value.then) ? value : {
+ then: function (callback) {
+ return resolvePromise(callback(value));
+ }
+ };
+ }
+
+ /**
+ * Save any changes that have been made to this domain object
+ * (as well as to others that might have been retrieved and
+ * modified during the editing session)
+ * @param {boolean} nonrecursive if true, save only this
+ * object (and not other objects with associated changes)
+ * @returns {Promise} a promise that will be fulfilled after
+ * persistence has completed.
+ * @memberof platform/commonUI/edit.EditorCapability#
+ */
+ EditorCapability.prototype.save = function (nonrecursive) {
+ var domainObject = this.domainObject,
+ editableObject = this.editableObject,
+ cache = this.cache;
// Update the underlying, "real" domain object's model
// with changes made to the copy used for editing.
@@ -74,39 +95,32 @@ define(
return domainObject.getCapability('persistence').persist();
}
- return {
- /**
- * Save any changes that have been made to this domain object
- * (as well as to others that might have been retrieved and
- * modified during the editing session)
- * @param {boolean} nonrecursive if true, save only this
- * object (and not other objects with associated changes)
- * @returns {Promise} a promise that will be fulfilled after
- * persistence has completed.
- */
- save: function (nonrecursive) {
- return nonrecursive ?
- resolvePromise(doMutate()).then(doPersist) :
- resolvePromise(cache.saveAll());
- },
- /**
- * Cancel editing; Discard any changes that have been made to
- * this domain object (as well as to others that might have
- * been retrieved and modified during the editing session)
- * @returns {Promise} a promise that will be fulfilled after
- * cancellation has completed.
- */
- cancel: function () {
- return resolvePromise(undefined);
- },
- /**
- * Check if there are any unsaved changes.
- * @returns {boolean} true if there are unsaved changes
- */
- dirty: function () {
- return cache.dirty();
- }
- };
+ return nonrecursive ?
+ resolvePromise(doMutate()).then(doPersist) :
+ resolvePromise(cache.saveAll());
};
+
+ /**
+ * Cancel editing; Discard any changes that have been made to
+ * this domain object (as well as to others that might have
+ * been retrieved and modified during the editing session)
+ * @returns {Promise} a promise that will be fulfilled after
+ * cancellation has completed.
+ * @memberof platform/commonUI/edit.EditorCapability#
+ */
+ EditorCapability.prototype.cancel = function () {
+ return resolvePromise(undefined);
+ };
+
+ /**
+ * Check if there are any unsaved changes.
+ * @returns {boolean} true if there are unsaved changes
+ * @memberof platform/commonUI/edit.EditorCapability#
+ */
+ EditorCapability.prototype.dirty = function () {
+ return this.cache.dirty();
+ };
+
+ return EditorCapability;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/controllers/EditActionController.js b/platform/commonUI/edit/src/controllers/EditActionController.js
index 43c173b098..4ea38f9bb5 100644
--- a/platform/commonUI/edit/src/controllers/EditActionController.js
+++ b/platform/commonUI/edit/src/controllers/EditActionController.js
@@ -33,6 +33,7 @@ define(
/**
* Controller which supplies action instances for Save/Cancel.
+ * @memberof platform/commonUI/edit
* @constructor
*/
function EditActionController($scope) {
@@ -51,4 +52,4 @@ define(
return EditActionController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/controllers/EditController.js b/platform/commonUI/edit/src/controllers/EditController.js
index 34cabd0b0b..eaffe02186 100644
--- a/platform/commonUI/edit/src/controllers/EditController.js
+++ b/platform/commonUI/edit/src/controllers/EditController.js
@@ -22,7 +22,8 @@
/*global define,Promise*/
/**
- * Module defining EditController. Created by vwoeltje on 11/14/14.
+ * This bundle implements Edit mode.
+ * @namespace platform/commonUI/edit
*/
define(
["../objects/EditableDomainObject"],
@@ -33,15 +34,16 @@ define(
* Controller which is responsible for populating the scope for
* Edit mode; introduces an editable version of the currently
* navigated domain object into the scope.
+ * @memberof platform/commonUI/edit
* @constructor
*/
function EditController($scope, $q, navigationService) {
- var navigatedObject;
+ var self = this;
function setNavigation(domainObject) {
// Wrap the domain object such that all mutation is
// confined to edit mode (until Save)
- navigatedObject =
+ self.navigatedDomainObject =
domainObject && new EditableDomainObject(domainObject, $q);
}
@@ -50,33 +52,33 @@ define(
$scope.$on("$destroy", function () {
navigationService.removeListener(setNavigation);
});
-
- return {
- /**
- * Get the domain object which is navigated-to.
- * @returns {DomainObject} the domain object that is navigated-to
- */
- navigatedObject: function () {
- return navigatedObject;
- },
- /**
- * Get the warning to show if the user attempts to navigate
- * away from Edit mode while unsaved changes are present.
- * @returns {string} the warning to show, or undefined if
- * there are no unsaved changes
- */
- getUnloadWarning: function () {
- var editorCapability = navigatedObject &&
- navigatedObject.getCapability("editor"),
- hasChanges = editorCapability && editorCapability.dirty();
-
- return hasChanges ?
- "Unsaved changes will be lost if you leave this page." :
- undefined;
- }
- };
}
+ /**
+ * Get the domain object which is navigated-to.
+ * @returns {DomainObject} the domain object that is navigated-to
+ */
+ EditController.prototype.navigatedObject = function () {
+ return this.navigatedDomainObject;
+ };
+
+ /**
+ * Get the warning to show if the user attempts to navigate
+ * away from Edit mode while unsaved changes are present.
+ * @returns {string} the warning to show, or undefined if
+ * there are no unsaved changes
+ */
+ EditController.prototype.getUnloadWarning = function () {
+ var navigatedObject = this.navigatedDomainObject,
+ editorCapability = navigatedObject &&
+ navigatedObject.getCapability("editor"),
+ hasChanges = editorCapability && editorCapability.dirty();
+
+ return hasChanges ?
+ "Unsaved changes will be lost if you leave this page." :
+ undefined;
+ };
+
return EditController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/controllers/EditPanesController.js b/platform/commonUI/edit/src/controllers/EditPanesController.js
index 4bfc91002c..7dedc251ec 100644
--- a/platform/commonUI/edit/src/controllers/EditPanesController.js
+++ b/platform/commonUI/edit/src/controllers/EditPanesController.js
@@ -28,15 +28,17 @@ define(
/**
* Supports the Library and Elements panes in Edit mode.
+ * @memberof platform/commonUI/edit
* @constructor
*/
function EditPanesController($scope) {
- var root;
+ var self = this;
// Update root object based on represented object
function updateRoot(domainObject) {
- var context = domainObject &&
- domainObject.getCapability('context'),
+ var root = self.rootDomainObject,
+ context = domainObject &&
+ domainObject.getCapability('context'),
newRoot = context && context.getTrueRoot(),
oldId = root && root.getId(),
newId = newRoot && newRoot.getId();
@@ -44,25 +46,22 @@ define(
// Only update if this has actually changed,
// to avoid excessive refreshing.
if (oldId !== newId) {
- root = newRoot;
+ self.rootDomainObject = newRoot;
}
}
// Update root when represented object changes
$scope.$watch('domainObject', updateRoot);
-
- return {
- /**
- * Get the root-level domain object, as reported by the
- * represented domain object.
- * @returns {DomainObject} the root object
- */
- getRoot: function () {
- return root;
- }
- };
}
+ /**
+ * Get the root-level domain object, as reported by the
+ * represented domain object.
+ * @returns {DomainObject} the root object
+ */
+ EditPanesController.prototype.getRoot = function () {
+ return this.rootDomainObject;
+ };
return EditPanesController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/directives/MCTBeforeUnload.js b/platform/commonUI/edit/src/directives/MCTBeforeUnload.js
index 60e825d1b0..3e7501c788 100644
--- a/platform/commonUI/edit/src/directives/MCTBeforeUnload.js
+++ b/platform/commonUI/edit/src/directives/MCTBeforeUnload.js
@@ -31,6 +31,7 @@ define(
* to this attribute will be evaluated during page navigation events
* and, if it returns a truthy value, will be used to populate a
* prompt to the user to confirm this navigation.
+ * @memberof platform/commonUI/edit
* @constructor
* @param $window the window
*/
@@ -102,4 +103,4 @@ define(
return MCTBeforeUnload;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/objects/EditableDomainObject.js b/platform/commonUI/edit/src/objects/EditableDomainObject.js
index dce39bec87..bbbc0ae512 100644
--- a/platform/commonUI/edit/src/objects/EditableDomainObject.js
+++ b/platform/commonUI/edit/src/objects/EditableDomainObject.js
@@ -68,6 +68,9 @@ define(
* which need to behave differently in edit mode,
* and provides a "working copy" of the object's
* model to allow changes to be easily cancelled.
+ * @constructor
+ * @memberof platform/commonUI/edit
+ * @implements {DomainObject}
*/
function EditableDomainObject(domainObject, $q) {
// The cache will hold all domain objects reached from
@@ -92,10 +95,10 @@ define(
this,
delegateArguments
),
- factory = capabilityFactories[name];
+ Factory = capabilityFactories[name];
- return (factory && capability) ?
- factory(capability, editableObject, domainObject, cache) :
+ return (Factory && capability) ?
+ new Factory(capability, editableObject, domainObject, cache) :
capability;
};
@@ -109,4 +112,4 @@ define(
return EditableDomainObject;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/objects/EditableDomainObjectCache.js b/platform/commonUI/edit/src/objects/EditableDomainObjectCache.js
index a13a3e2360..88a154d79b 100644
--- a/platform/commonUI/edit/src/objects/EditableDomainObjectCache.js
+++ b/platform/commonUI/edit/src/objects/EditableDomainObjectCache.js
@@ -22,7 +22,7 @@
/*global define*/
-/**
+/*
* An editable domain object cache stores domain objects that have been
* made editable, in a group that can be saved all-at-once. This supports
* Edit mode, which is launched for a specific object but may contain
@@ -32,8 +32,6 @@
* to ensure that changes made while in edit mode do not propagate up
* to the objects used in browse mode (or to persistence) until the user
* initiates a Save.
- *
- * @module editor/object/editable-domain-object-cache
*/
define(
["./EditableModelCache"],
@@ -46,107 +44,118 @@ define(
* of objects retrieved via composition or context capabilities as
* editable domain objects.
*
- * @param {Constructor} EditableDomainObject a
+ * @param {Constructor} EditableDomainObject a
* constructor function which takes a regular domain object as
* an argument, and returns an editable domain object as its
* result.
* @param $q Angular's $q, for promise handling
+ * @memberof platform/commonUI/edit
* @constructor
- * @memberof module:editor/object/editable-domain-object-cache
*/
function EditableDomainObjectCache(EditableDomainObject, $q) {
- var cache = new EditableModelCache(),
- dirty = {},
- root;
-
- return {
- /**
- * Wrap this domain object in an editable form, or pull such
- * an object from the cache if one already exists.
- *
- * @param {DomainObject} domainObject the regular domain object
- * @returns {DomainObject} the domain object in an editable form
- */
- getEditableObject: function (domainObject) {
- var type = domainObject.getCapability('type');
-
- // Track the top-level domain object; this will have
- // some special behavior for its context capability.
- root = root || domainObject;
-
- // Avoid double-wrapping (WTD-1017)
- if (domainObject.hasCapability('editor')) {
- return domainObject;
- }
-
- // Don't bother wrapping non-editable objects
- if (!type || !type.hasFeature('creation')) {
- return domainObject;
- }
-
- // Provide an editable form of the object
- return new EditableDomainObject(
- domainObject,
- cache.getCachedModel(domainObject)
- );
- },
- /**
- * Check if a domain object is (effectively) the top-level
- * object in this editable subgraph.
- * @returns {boolean} true if it is the root
- */
- isRoot: function (domainObject) {
- return domainObject === root;
- },
- /**
- * Mark an editable domain object (presumably already cached)
- * as having received modifications during editing; it should be
- * included in the bulk save invoked when editing completes.
- *
- * @param {DomainObject} domainObject the domain object
- */
- markDirty: function (domainObject) {
- dirty[domainObject.getId()] = domainObject;
- },
- /**
- * Mark an object (presumably already cached) as having had its
- * changes saved (and thus no longer needing to be subject to a
- * save operation.)
- *
- * @param {DomainObject} domainObject the domain object
- */
- markClean: function (domainObject) {
- delete dirty[domainObject.getId()];
- },
- /**
- * Initiate a save on all objects that have been cached.
- */
- saveAll: function () {
- // Get a list of all dirty objects
- var objects = Object.keys(dirty).map(function (k) {
- return dirty[k];
- });
-
- // Clear dirty set, since we're about to save.
- dirty = {};
-
- // Most save logic is handled by the "editor.completion"
- // capability, so that is delegated here.
- return $q.all(objects.map(function (object) {
- // Save; pass a nonrecursive flag to avoid looping
- return object.getCapability('editor').save(true);
- }));
- },
- /**
- * Check if any objects have been marked dirty in this cache.
- * @returns {boolean} true if objects are dirty
- */
- dirty: function () {
- return Object.keys(dirty).length > 0;
- }
- };
+ this.cache = new EditableModelCache();
+ this.dirtyObjects = {};
+ this.root = undefined;
+ this.$q = $q;
+ this.EditableDomainObject = EditableDomainObject;
}
+ /**
+ * Wrap this domain object in an editable form, or pull such
+ * an object from the cache if one already exists.
+ *
+ * @param {DomainObject} domainObject the regular domain object
+ * @returns {DomainObject} the domain object in an editable form
+ */
+ EditableDomainObjectCache.prototype.getEditableObject = function (domainObject) {
+ var type = domainObject.getCapability('type'),
+ EditableDomainObject = this.EditableDomainObject;
+
+ // Track the top-level domain object; this will have
+ // some special behavior for its context capability.
+ this.root = this.root || domainObject;
+
+ // Avoid double-wrapping (WTD-1017)
+ if (domainObject.hasCapability('editor')) {
+ return domainObject;
+ }
+
+ // Don't bother wrapping non-editable objects
+ if (!type || !type.hasFeature('creation')) {
+ return domainObject;
+ }
+
+ // Provide an editable form of the object
+ return new EditableDomainObject(
+ domainObject,
+ this.cache.getCachedModel(domainObject)
+ );
+ };
+
+ /**
+ * Check if a domain object is (effectively) the top-level
+ * object in this editable subgraph.
+ * @returns {boolean} true if it is the root
+ */
+ EditableDomainObjectCache.prototype.isRoot = function (domainObject) {
+ return domainObject === this.root;
+ };
+
+ /**
+ * Mark an editable domain object (presumably already cached)
+ * as having received modifications during editing; it should be
+ * included in the bulk save invoked when editing completes.
+ *
+ * @param {DomainObject} domainObject the domain object
+ * @memberof platform/commonUI/edit.EditableDomainObjectCache#
+ */
+ EditableDomainObjectCache.prototype.markDirty = function (domainObject) {
+ this.dirtyObjects[domainObject.getId()] = domainObject;
+ };
+
+ /**
+ * Mark an object (presumably already cached) as having had its
+ * changes saved (and thus no longer needing to be subject to a
+ * save operation.)
+ *
+ * @param {DomainObject} domainObject the domain object
+ */
+ EditableDomainObjectCache.prototype.markClean = function (domainObject) {
+ delete this.dirtyObjects[domainObject.getId()];
+ };
+
+ /**
+ * Initiate a save on all objects that have been cached.
+ * @return {Promise} A promise which will resolve when all objects are
+ * persisted.
+ */
+ EditableDomainObjectCache.prototype.saveAll = function () {
+ // Get a list of all dirty objects
+ var dirty = this.dirtyObjects,
+ objects = Object.keys(dirty).map(function (k) {
+ return dirty[k];
+ });
+
+ // Clear dirty set, since we're about to save.
+ this.dirtyObjects = {};
+
+ // Most save logic is handled by the "editor.completion"
+ // capability, so that is delegated here.
+ return this.$q.all(objects.map(function (object) {
+ // Save; pass a nonrecursive flag to avoid looping
+ return object.getCapability('editor').save(true);
+ }));
+ };
+
+ /**
+ * Check if any objects have been marked dirty in this cache.
+ * @returns {boolean} true if objects are dirty
+ */
+ EditableDomainObjectCache.prototype.dirty = function () {
+ return Object.keys(this.dirtyObjects).length > 0;
+ };
+
return EditableDomainObjectCache;
}
);
+
diff --git a/platform/commonUI/edit/src/objects/EditableModelCache.js b/platform/commonUI/edit/src/objects/EditableModelCache.js
index 3652f679f7..30ca3d774a 100644
--- a/platform/commonUI/edit/src/objects/EditableModelCache.js
+++ b/platform/commonUI/edit/src/objects/EditableModelCache.js
@@ -31,33 +31,32 @@ define(
* made editable, to support a group that can be saved all-at-once.
* This is useful in Edit mode, which is launched for a specific
* object but may contain changes across many objects.
+ * @memberof platform/commonUI/edit
* @constructor
*/
function EditableModelCache() {
- var cache = {};
-
- // Deep-copy a model. Models are JSONifiable, so this can be
- // done by stringification then destringification
- function clone(model) {
- return JSON.parse(JSON.stringify(model));
- }
-
- return {
- /**
- * Get this domain object's model from the cache (or
- * place it in the cache if it isn't in the cache yet)
- * @returns a clone of the domain object's model
- */
- getCachedModel: function (domainObject) {
- var id = domainObject.getId();
-
- return (cache[id] =
- cache[id] || clone(domainObject.getModel()));
- }
- };
-
+ this.cache = {};
}
+ // Deep-copy a model. Models are JSONifiable, so this can be
+ // done by stringification then destringification
+ function clone(model) {
+ return JSON.parse(JSON.stringify(model));
+ }
+
+ /**
+ * Get this domain object's model from the cache (or
+ * place it in the cache if it isn't in the cache yet)
+ * @returns a clone of the domain object's model
+ */
+ EditableModelCache.prototype.getCachedModel = function (domainObject) {
+ var id = domainObject.getId(),
+ cache = this.cache;
+
+ return (cache[id] =
+ cache[id] || clone(domainObject.getModel()));
+ };
+
return EditableModelCache;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/policies/EditActionPolicy.js b/platform/commonUI/edit/src/policies/EditActionPolicy.js
index 3c47af43b8..bec2fc423d 100644
--- a/platform/commonUI/edit/src/policies/EditActionPolicy.js
+++ b/platform/commonUI/edit/src/policies/EditActionPolicy.js
@@ -30,53 +30,47 @@ define(
* Policy controlling when the `edit` and/or `properties` actions
* can appear as applicable actions of the `view-control` category
* (shown as buttons in the top-right of browse mode.)
+ * @memberof platform/commonUI/edit
* @constructor
+ * @implements {Policy.}
*/
function EditActionPolicy() {
- // Get a count of views which are not flagged as non-editable.
- function countEditableViews(context) {
- var domainObject = (context || {}).domainObject,
- views = domainObject && domainObject.useCapability('view'),
- count = 0;
+ }
- // A view is editable unless explicitly flagged as not
- (views || []).forEach(function (view) {
- count += (view.editable !== false) ? 1 : 0;
- });
+ // Get a count of views which are not flagged as non-editable.
+ function countEditableViews(context) {
+ var domainObject = (context || {}).domainObject,
+ views = domainObject && domainObject.useCapability('view'),
+ count = 0;
- return count;
+ // A view is editable unless explicitly flagged as not
+ (views || []).forEach(function (view) {
+ count += (view.editable !== false) ? 1 : 0;
+ });
+
+ return count;
+ }
+
+ EditActionPolicy.prototype.allow = function (action, context) {
+ var key = action.getMetadata().key,
+ category = (context || {}).category;
+
+ // Only worry about actions in the view-control category
+ if (category === 'view-control') {
+ // Restrict 'edit' to cases where there are editable
+ // views (similarly, restrict 'properties' to when
+ // the converse is true)
+ if (key === 'edit') {
+ return countEditableViews(context) > 0;
+ } else if (key === 'properties') {
+ return countEditableViews(context) < 1;
+ }
}
- return {
- /**
- * Check whether or not a given action is allowed by this
- * policy.
- * @param {Action} action the action
- * @param context the context
- * @returns {boolean} true if not disallowed
- */
- allow: function (action, context) {
- var key = action.getMetadata().key,
- category = (context || {}).category;
-
- // Only worry about actions in the view-control category
- if (category === 'view-control') {
- // Restrict 'edit' to cases where there are editable
- // views (similarly, restrict 'properties' to when
- // the converse is true)
- if (key === 'edit') {
- return countEditableViews(context) > 0;
- } else if (key === 'properties') {
- return countEditableViews(context) < 1;
- }
- }
-
- // Like all policies, allow by default.
- return true;
- }
- };
- }
+ // Like all policies, allow by default.
+ return true;
+ };
return EditActionPolicy;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/policies/EditableViewPolicy.js b/platform/commonUI/edit/src/policies/EditableViewPolicy.js
index c93072e861..17194064b0 100644
--- a/platform/commonUI/edit/src/policies/EditableViewPolicy.js
+++ b/platform/commonUI/edit/src/policies/EditableViewPolicy.js
@@ -28,30 +28,24 @@ define(
/**
* Policy controlling which views should be visible in Edit mode.
+ * @memberof platform/commonUI/edit
* @constructor
+ * @implements {Policy.}
*/
function EditableViewPolicy() {
- return {
- /**
- * Check whether or not a given action is allowed by this
- * policy.
- * @param {Action} action the action
- * @param domainObject the domain object which will be viewed
- * @returns {boolean} true if not disallowed
- */
- allow: function (view, domainObject) {
- // If a view is flagged as non-editable, only allow it
- // while we're not in Edit mode.
- if ((view || {}).editable === false) {
- return !domainObject.hasCapability('editor');
- }
-
- // Like all policies, allow by default.
- return true;
- }
- };
}
+ EditableViewPolicy.prototype.allow = function (view, domainObject) {
+ // If a view is flagged as non-editable, only allow it
+ // while we're not in Edit mode.
+ if ((view || {}).editable === false) {
+ return !domainObject.hasCapability('editor');
+ }
+
+ // Like all policies, allow by default.
+ return true;
+ };
+
return EditableViewPolicy;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/representers/EditRepresenter.js b/platform/commonUI/edit/src/representers/EditRepresenter.js
index 96f6da332b..17a0f634b2 100644
--- a/platform/commonUI/edit/src/representers/EditRepresenter.js
+++ b/platform/commonUI/edit/src/representers/EditRepresenter.js
@@ -41,14 +41,17 @@ define(
* and may be reused for different domain objects and/or
* representations resulting from changes there.
*
+ * @memberof platform/commonUI/edit
+ * @implements {Representer}
* @constructor
*/
function EditRepresenter($q, $log, scope) {
- var domainObject,
- key;
+ var self = this;
// Mutate and persist a new version of a domain object's model.
function doPersist(model) {
+ var domainObject = self.domainObject;
+
// First, mutate; then, persist.
return $q.when(domainObject.useCapability("mutation", function () {
return model;
@@ -64,7 +67,8 @@ define(
// Look up from scope; these will have been populated by
// mct-representation.
var model = scope.model,
- configuration = scope.configuration;
+ configuration = scope.configuration,
+ domainObject = self.domainObject;
// Log the commit message
$log.debug([
@@ -78,50 +82,33 @@ define(
if (domainObject && domainObject.hasCapability("persistence")) {
// Configurations for specific views are stored by
// key in the "configuration" field of the model.
- if (key && configuration) {
+ if (self.key && configuration) {
model.configuration = model.configuration || {};
- model.configuration[key] = configuration;
+ model.configuration[self.key] = configuration;
}
doPersist(model);
}
}
- // Respond to the destruction of the current representation.
- function destroy() {
- // Nothing to clean up
- }
-
- // Handle a specific representation of a specific domain object
- function represent(representation, representedObject) {
- // Track the key, to know which view configuration to save to.
- key = (representation || {}).key;
- // Track the represented object
- domainObject = representedObject;
- // Ensure existing watches are released
- destroy();
- }
-
// Place the "commit" method in the scope
scope.commit = commit;
-
- return {
- /**
- * Set the current representation in use, and the domain
- * object being represented.
- *
- * @param {RepresentationDefinition} representation the
- * definition of the representation in use
- * @param {DomainObject} domainObject the domain object
- * being represented
- */
- represent: represent,
- /**
- * Release any resources associated with this representer.
- */
- destroy: destroy
- };
}
+ // Handle a specific representation of a specific domain object
+ EditRepresenter.prototype.represent = function represent(representation, representedObject) {
+ // Track the key, to know which view configuration to save to.
+ this.key = (representation || {}).key;
+ // Track the represented object
+ this.domainObject = representedObject;
+ // Ensure existing watches are released
+ this.destroy();
+ };
+
+ // Respond to the destruction of the current representation.
+ EditRepresenter.prototype.destroy = function destroy() {
+ // Nothing to clean up
+ };
+
return EditRepresenter;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/representers/EditToolbar.js b/platform/commonUI/edit/src/representers/EditToolbar.js
index 58dab7497e..367eaf1705 100644
--- a/platform/commonUI/edit/src/representers/EditToolbar.js
+++ b/platform/commonUI/edit/src/representers/EditToolbar.js
@@ -38,125 +38,23 @@ define(
*
* @param structure toolbar structure, as provided by view definition
* @param {Function} commit callback to invoke after changes
+ * @memberof platform/commonUI/edit
* @constructor
*/
function EditToolbar(structure, commit) {
- var toolbarStructure = Object.create(structure || {}),
- toolbarState,
- selection,
- properties = [];
+ var self = this;
// Generate a new key for an item's property
function addKey(property) {
- properties.push(property);
- return properties.length - 1; // Return index of property
- }
-
- // Update value for this property in all elements of the
- // selection which have this property.
- function updateProperties(property, value) {
- var changed = false;
-
- // Update property in a selected element
- function updateProperty(selected) {
- // Ignore selected elements which don't have this property
- if (selected[property] !== undefined) {
- // Check if this is a setter, or just assignable
- if (typeof selected[property] === 'function') {
- changed =
- changed || (selected[property]() !== value);
- selected[property](value);
- } else {
- changed =
- changed || (selected[property] !== value);
- selected[property] = value;
- }
- }
- }
-
- // Update property in all selected elements
- selection.forEach(updateProperty);
-
- // Return whether or not anything changed
- return changed;
- }
-
- // Look up the current value associated with a property
- // in selection i
- function lookupState(property, selected) {
- var value = selected[property];
- return (typeof value === 'function') ? value() : value;
- }
-
- // Get initial value for a given property
- function initializeState(property) {
- var result;
- // Look through all selections for this property;
- // values should all match by the time we perform
- // this lookup anyway.
- selection.forEach(function (selected) {
- result = (selected[property] !== undefined) ?
- lookupState(property, selected) :
- result;
- });
- return result;
- }
-
- // Check if all elements of the selection which have this
- // property have the same value for this property.
- function isConsistent(property) {
- var consistent = true,
- observed = false,
- state;
-
- // Check if a given element of the selection is consistent
- // with previously-observed elements for this property.
- function checkConsistency(selected) {
- var next;
- // Ignore selections which don't have this property
- if (selected[property] !== undefined) {
- // Look up state of this element in the selection
- next = lookupState(property, selected);
- // Detect inconsistency
- if (observed) {
- consistent = consistent && (next === state);
- }
- // Track state for next iteration
- state = next;
- observed = true;
- }
- }
-
- // Iterate through selections
- selection.forEach(checkConsistency);
-
- return consistent;
- }
-
- // Used to filter out items which are applicable (or not)
- // to the current selection.
- function isApplicable(item) {
- var property = (item || {}).property,
- method = (item || {}).method,
- exclusive = !!(item || {}).exclusive;
-
- // Check if a selected item defines this property
- function hasProperty(selected) {
- return (property && (selected[property] !== undefined)) ||
- (method && (typeof selected[method] === 'function'));
- }
-
- return selection.map(hasProperty).reduce(
- exclusive ? and : or,
- exclusive
- ) && isConsistent(property);
+ self.properties.push(property);
+ return self.properties.length - 1; // Return index of property
}
// Invoke all functions in selections with the given name
function invoke(method, value) {
if (method) {
// Make the change in the selection
- selection.forEach(function (selected) {
+ self.selection.forEach(function (selected) {
if (typeof selected[method] === 'function') {
selected[method](value);
}
@@ -189,73 +87,172 @@ define(
return converted;
}
+ this.toolbarState = [];
+ this.selection = undefined;
+ this.properties = [];
+ this.toolbarStructure = Object.create(structure || {});
+ this.toolbarStructure.sections =
+ ((structure || {}).sections || []).map(convertSection);
+ }
+
+ // Check if all elements of the selection which have this
+ // property have the same value for this property.
+ EditToolbar.prototype.isConsistent = function (property) {
+ var self = this,
+ consistent = true,
+ observed = false,
+ state;
+
+ // Check if a given element of the selection is consistent
+ // with previously-observed elements for this property.
+ function checkConsistency(selected) {
+ var next;
+ // Ignore selections which don't have this property
+ if (selected[property] !== undefined) {
+ // Look up state of this element in the selection
+ next = self.lookupState(property, selected);
+ // Detect inconsistency
+ if (observed) {
+ consistent = consistent && (next === state);
+ }
+ // Track state for next iteration
+ state = next;
+ observed = true;
+ }
+ }
+
+ // Iterate through selections
+ self.selection.forEach(checkConsistency);
+
+ return consistent;
+ };
+
+ // Used to filter out items which are applicable (or not)
+ // to the current selection.
+ EditToolbar.prototype.isApplicable = function (item) {
+ var property = (item || {}).property,
+ method = (item || {}).method,
+ exclusive = !!(item || {}).exclusive;
+
+ // Check if a selected item defines this property
+ function hasProperty(selected) {
+ return (property && (selected[property] !== undefined)) ||
+ (method && (typeof selected[method] === 'function'));
+ }
+
+ return this.selection.map(hasProperty).reduce(
+ exclusive ? and : or,
+ exclusive
+ ) && this.isConsistent(property);
+ };
+
+
+ // Look up the current value associated with a property
+ EditToolbar.prototype.lookupState = function (property, selected) {
+ var value = selected[property];
+ return (typeof value === 'function') ? value() : value;
+ };
+
+ /**
+ * Set the current selection. Visibility of sections
+ * and items in the toolbar will be updated to match this.
+ * @param {Array} s the new selection
+ */
+ EditToolbar.prototype.setSelection = function (s) {
+ var self = this;
+
// Show/hide controls in this section per applicability
function refreshSectionApplicability(section) {
var count = 0;
// Show/hide each item
(section.items || []).forEach(function (item) {
- item.hidden = !isApplicable(item);
+ item.hidden = !self.isApplicable(item);
count += item.hidden ? 0 : 1;
});
// Hide this section if there are no applicable items
section.hidden = !count;
}
- // Show/hide controls if they are applicable
- function refreshApplicability() {
- toolbarStructure.sections.forEach(refreshSectionApplicability);
+ // Get initial value for a given property
+ function initializeState(property) {
+ var result;
+ // Look through all selections for this property;
+ // values should all match by the time we perform
+ // this lookup anyway.
+ self.selection.forEach(function (selected) {
+ result = (selected[property] !== undefined) ?
+ self.lookupState(property, selected) :
+ result;
+ });
+ return result;
}
- // Refresh toolbar state to match selection
- function refreshState() {
- toolbarState = properties.map(initializeState);
- }
+ this.selection = s;
+ this.toolbarStructure.sections.forEach(refreshSectionApplicability);
+ this.toolbarState = this.properties.map(initializeState);
+ };
- toolbarStructure.sections =
- ((structure || {}).sections || []).map(convertSection);
+ /**
+ * Get the structure of the toolbar, as appropriate to
+ * pass to `mct-toolbar`.
+ * @returns the toolbar structure
+ */
+ EditToolbar.prototype.getStructure = function () {
+ return this.toolbarStructure;
+ };
- toolbarState = [];
+ /**
+ * Get the current state of the toolbar, as appropriate
+ * to two-way bind to the state handled by `mct-toolbar`.
+ * @returns {Array} state of the toolbar
+ */
+ EditToolbar.prototype.getState = function () {
+ return this.toolbarState;
+ };
- return {
- /**
- * Set the current selection. Visisbility of sections
- * and items in the toolbar will be updated to match this.
- * @param {Array} s the new selection
- */
- setSelection: function (s) {
- selection = s;
- refreshApplicability();
- refreshState();
- },
- /**
- * Get the structure of the toolbar, as appropriate to
- * pass to `mct-toolbar`.
- * @returns the toolbar structure
- */
- getStructure: function () {
- return toolbarStructure;
- },
- /**
- * Get the current state of the toolbar, as appropriate
- * to two-way bind to the state handled by `mct-toolbar`.
- * @returns {Array} state of the toolbar
- */
- getState: function () {
- return toolbarState;
- },
- /**
- * Update state within the current selection.
- * @param {number} index the index of the corresponding
- * element in the state array
- * @param value the new value to convey to the selection
- */
- updateState: function (index, value) {
- return updateProperties(properties[index], value);
+ /**
+ * Update state within the current selection.
+ * @param {number} index the index of the corresponding
+ * element in the state array
+ * @param value the new value to convey to the selection
+ */
+ EditToolbar.prototype.updateState = function (index, value) {
+ var self = this;
+
+ // Update value for this property in all elements of the
+ // selection which have this property.
+ function updateProperties(property, value) {
+ var changed = false;
+
+ // Update property in a selected element
+ function updateProperty(selected) {
+ // Ignore selected elements which don't have this property
+ if (selected[property] !== undefined) {
+ // Check if this is a setter, or just assignable
+ if (typeof selected[property] === 'function') {
+ changed =
+ changed || (selected[property]() !== value);
+ selected[property](value);
+ } else {
+ changed =
+ changed || (selected[property] !== value);
+ selected[property] = value;
+ }
+ }
}
- };
- }
+
+ // Update property in all selected elements
+ self.selection.forEach(updateProperty);
+
+ // Return whether or not anything changed
+ return changed;
+ }
+
+ return updateProperties(this.properties[index], value);
+ };
return EditToolbar;
}
);
+
diff --git a/platform/commonUI/edit/src/representers/EditToolbarRepresenter.js b/platform/commonUI/edit/src/representers/EditToolbarRepresenter.js
index f94ddcd7a8..daf3645b69 100644
--- a/platform/commonUI/edit/src/representers/EditToolbarRepresenter.js
+++ b/platform/commonUI/edit/src/representers/EditToolbarRepresenter.js
@@ -27,17 +27,21 @@ define(
"use strict";
// No operation
- function noop() {}
+ var NOOP_REPRESENTER = {
+ represent: function () {},
+ destroy: function () {}
+ };
/**
* The EditToolbarRepresenter populates the toolbar in Edit mode
* based on a view's definition.
* @param {Scope} scope the Angular scope of the representation
+ * @memberof platform/commonUI/edit
* @constructor
+ * @implements {Representer}
*/
function EditToolbarRepresenter(scope, element, attrs) {
- var toolbar,
- toolbarObject = {};
+ var self = this;
// Mark changes as ready to persist
function commit(message) {
@@ -49,31 +53,33 @@ define(
// Handle changes to the current selection
function updateSelection(selection) {
// Only update if there is a toolbar to update
- if (toolbar) {
+ if (self.toolbar) {
// Make sure selection is array-like
selection = Array.isArray(selection) ?
selection :
(selection ? [selection] : []);
// Update the toolbar's selection
- toolbar.setSelection(selection);
+ self.toolbar.setSelection(selection);
// ...and expose its structure/state
- toolbarObject.structure = toolbar.getStructure();
- toolbarObject.state = toolbar.getState();
+ self.toolbarObject.structure =
+ self.toolbar.getStructure();
+ self.toolbarObject.state =
+ self.toolbar.getState();
}
}
// Get state (to watch it)
function getState() {
- return toolbarObject.state;
+ return self.toolbarObject.state;
}
// Update selection models to match changed toolbar state
function updateState(state) {
// Update underlying state based on toolbar changes
var changed = (state || []).map(function (value, index) {
- return toolbar.updateState(index, value);
+ return self.toolbar.updateState(index, value);
}).reduce(function (a, b) {
return a || b;
}, false);
@@ -85,66 +91,73 @@ define(
}
}
- // Initialize toolbar (expose object to parent scope)
- function initialize(definition) {
- // If we have been asked to expose toolbar state...
- if (attrs.toolbar) {
- // Initialize toolbar object
- toolbar = new EditToolbar(definition, commit);
- // Ensure toolbar state is exposed
- scope.$parent[attrs.toolbar] = toolbarObject;
- }
- }
-
- // Represent a domain object using this definition
- function represent(representation) {
- // Get the newest toolbar definition from the view
- var definition = (representation || {}).toolbar || {};
- // Expose the toolbar object to the parent scope
- initialize(definition);
- // Create a selection scope
- scope.selection = new EditToolbarSelection();
- // Initialize toolbar to an empty selection
- updateSelection([]);
- }
-
- // Destroy; remove toolbar object from parent scope
- function destroy() {
+ // Avoid attaching scope to this;
+ // http://errors.angularjs.org/1.2.26/ng/cpws
+ this.setSelection = function (s) {
+ scope.selection = s;
+ };
+ this.clearExposedToolbar = function () {
// Clear exposed toolbar state (if any)
if (attrs.toolbar) {
delete scope.$parent[attrs.toolbar];
}
- }
+ };
+ this.exposeToolbar = function () {
+ scope.$parent[self.attrs.toolbar] = self.toolbarObject;
+ };
+
+ this.commit = commit;
+ this.attrs = attrs;
+ this.updateSelection = updateSelection;
+ this.toolbar = undefined;
+ this.toolbarObject = {};
// If this representation exposes a toolbar, set up watches
// to synchronize with it.
- if (attrs.toolbar) {
+ if (attrs && attrs.toolbar) {
// Detect and handle changes to state from the toolbar
scope.$watchCollection(getState, updateState);
// Watch for changes in the current selection state
scope.$watchCollection("selection.all()", updateSelection);
// Expose toolbar state under that name
- scope.$parent[attrs.toolbar] = toolbarObject;
+ scope.$parent[attrs.toolbar] = this.toolbarObject;
+ } else {
+ // No toolbar declared, so do nothing.
+ return NOOP_REPRESENTER;
}
- return {
- /**
- * Set the current representation in use, and the domain
- * object being represented.
- *
- * @param {RepresentationDefinition} representation the
- * definition of the representation in use
- * @param {DomainObject} domainObject the domain object
- * being represented
- */
- represent: (attrs || {}).toolbar ? represent : noop,
- /**
- * Release any resources associated with this representer.
- */
- destroy: (attrs || {}).toolbar ? destroy : noop
- };
}
+ // Represent a domain object using this definition
+ EditToolbarRepresenter.prototype.represent = function (representation) {
+ // Get the newest toolbar definition from the view
+ var definition = (representation || {}).toolbar || {},
+ self = this;
+
+ // Initialize toolbar (expose object to parent scope)
+ function initialize(definition) {
+ // If we have been asked to expose toolbar state...
+ if (self.attrs.toolbar) {
+ // Initialize toolbar object
+ self.toolbar = new EditToolbar(definition, self.commit);
+ // Ensure toolbar state is exposed
+ self.exposeToolbar();
+ }
+ }
+
+ // Expose the toolbar object to the parent scope
+ initialize(definition);
+ // Create a selection scope
+ this.setSelection(new EditToolbarSelection());
+ // Initialize toolbar to an empty selection
+ this.updateSelection([]);
+ };
+
+ // Destroy; remove toolbar object from parent scope
+ EditToolbarRepresenter.prototype.destroy = function () {
+ this.clearExposedToolbar();
+ };
+
return EditToolbarRepresenter;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/src/representers/EditToolbarSelection.js b/platform/commonUI/edit/src/representers/EditToolbarSelection.js
index d88ad0da1a..318ae935b5 100644
--- a/platform/commonUI/edit/src/representers/EditToolbarSelection.js
+++ b/platform/commonUI/edit/src/representers/EditToolbarSelection.js
@@ -37,110 +37,96 @@ define(
* * The selection, for single selected elements within the
* view.
*
+ * @memberof platform/commonUI/edit
* @constructor
*/
function EditToolbarSelection() {
- var selection = [ {} ],
- selecting = false,
- selected;
+ this.selection = [{}];
+ this.selecting = false;
+ this.selectedObj = undefined;
+ }
- // Remove the currently-selected object
- function deselect() {
- // Nothing to do if we don't have a selected object
- if (selecting) {
- // Clear state tracking
- selecting = false;
- selected = undefined;
+ /**
+ * Check if an object is currently selected.
+ * @param {*} obj the object to check for selection
+ * @returns {boolean} true if selected, otherwise false
+ */
+ EditToolbarSelection.prototype.selected = function (obj) {
+ return (obj === this.selectedObj) || (obj === this.selection[0]);
+ };
- // Remove the selection
- selection.pop();
-
- return true;
- }
+ /**
+ * Select an object.
+ * @param obj the object to select
+ * @returns {boolean} true if selection changed
+ */
+ EditToolbarSelection.prototype.select = function (obj) {
+ // Proxy is always selected
+ if (obj === this.selection[0]) {
return false;
}
- // Select an object
- function select(obj) {
- // Proxy is always selected
- if (obj === selection[0]) {
- return false;
- }
+ // Clear any existing selection
+ this.deselect();
- // Clear any existing selection
- deselect();
+ // Note the current selection state
+ this.selectedObj = obj;
+ this.selecting = true;
- // Note the current selection state
- selected = obj;
- selecting = true;
+ // Add the selection
+ this.selection.push(obj);
+ };
- // Add the selection
- selection.push(obj);
+ /**
+ * Clear the current selection.
+ * @returns {boolean} true if selection changed
+ */
+ EditToolbarSelection.prototype.deselect = function () {
+ // Nothing to do if we don't have a selected object
+ if (this.selecting) {
+ // Clear state tracking
+ this.selecting = false;
+ this.selectedObj = undefined;
+
+ // Remove the selection
+ this.selection.pop();
+
+ return true;
}
+ return false;
+ };
+ /**
+ * Get the currently-selected object.
+ * @returns the currently selected object
+ */
+ EditToolbarSelection.prototype.get = function () {
+ return this.selectedObj;
+ };
- // Check if an object is selected
- function isSelected(obj) {
- return (obj === selected) || (obj === selection[0]);
+ /**
+ * Get/set the view proxy (for toolbar actions taken upon
+ * the view itself.)
+ * @param [proxy] the view proxy (if setting)
+ * @returns the current view proxy
+ */
+ EditToolbarSelection.prototype.proxy = function (p) {
+ if (arguments.length > 0) {
+ this.selection[0] = p;
}
+ return this.selection[0];
+ };
- // Getter for current selection
- function get() {
- return selected;
- }
-
- // Getter/setter for view proxy
- function proxy(p) {
- if (arguments.length > 0) {
- selection[0] = p;
- }
- return selection[0];
- }
-
- // Getter for the full array of selected objects (incl. view proxy)
- function all() {
- return selection;
- }
-
- return {
- /**
- * Check if an object is currently selected.
- * @returns true if selected, otherwise false
- */
- selected: isSelected,
- /**
- * Select an object.
- * @param obj the object to select
- * @returns {boolean} true if selection changed
- */
- select: select,
- /**
- * Clear the current selection.
- * @returns {boolean} true if selection changed
- */
- deselect: deselect,
- /**
- * Get the currently-selected object.
- * @returns the currently selected object
- */
- get: get,
- /**
- * Get/set the view proxy (for toolbar actions taken upon
- * the view itself.)
- * @param [proxy] the view proxy (if setting)
- * @returns the current view proxy
- */
- proxy: proxy,
- /**
- * Get an array containing all selections, including the
- * selection proxy. It is generally not advisable to
- * mutate this array directly.
- * @returns {Array} all selections
- */
- all: all
- };
- }
+ /**
+ * Get an array containing all selections, including the
+ * selection proxy. It is generally not advisable to
+ * mutate this array directly.
+ * @returns {Array} all selections
+ */
+ EditToolbarSelection.prototype.all = function () {
+ return this.selection;
+ };
return EditToolbarSelection;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/edit/test/objects/EditableDomainObjectCacheSpec.js b/platform/commonUI/edit/test/objects/EditableDomainObjectCacheSpec.js
index 39cac56d9f..4eea727e26 100644
--- a/platform/commonUI/edit/test/objects/EditableDomainObjectCacheSpec.js
+++ b/platform/commonUI/edit/test/objects/EditableDomainObjectCacheSpec.js
@@ -112,7 +112,9 @@ define(
});
it("saves objects that have been marked dirty", function () {
- var objects = ['a', 'b', 'c'].map(TestObject).map(cache.getEditableObject);
+ var objects = ['a', 'b', 'c'].map(TestObject).map(function (domainObject) {
+ return cache.getEditableObject(domainObject);
+ });
cache.markDirty(objects[0]);
cache.markDirty(objects[2]);
@@ -123,7 +125,9 @@ define(
});
it("does not save objects that have been marked clean", function () {
- var objects = ['a', 'b', 'c'].map(TestObject).map(cache.getEditableObject);
+ var objects = ['a', 'b', 'c'].map(TestObject).map(function (domainObject) {
+ return cache.getEditableObject(domainObject);
+ });
cache.markDirty(objects[0]);
cache.markDirty(objects[2]);
diff --git a/platform/commonUI/general/bundle.json b/platform/commonUI/general/bundle.json
index 7f5e2bfb86..2ab488ba12 100644
--- a/platform/commonUI/general/bundle.json
+++ b/platform/commonUI/general/bundle.json
@@ -200,7 +200,7 @@
{
"key": "label",
"templateUrl": "templates/label.html",
- "uses": [ "type" ],
+ "uses": [ "type", "location" ],
"gestures": [ "drag", "menu", "info" ]
},
{
diff --git a/platform/commonUI/general/res/css/forms.css b/platform/commonUI/general/res/css/forms.css
index 1550d1a6bb..7b9fa40b87 100644
--- a/platform/commonUI/general/res/css/forms.css
+++ b/platform/commonUI/general/res/css/forms.css
@@ -96,6 +96,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
+/*********************************************** FORM ELEMENTS */
/*
@mixin invokeMenu($baseColor: $colorBodyFg) {
$c: $baseColor;
@@ -230,27 +231,21 @@
line-height: 14px;
margin-right: 5px; }
/* line 89, ../sass/forms/_elems.scss */
- .form .form-row .controls input[type="text"] {
- height: 22px;
- line-height: 22px;
- margin-top: -4px;
- vertical-align: baseline; }
- /* line 96, ../sass/forms/_elems.scss */
.form .form-row .controls .l-med input[type="text"] {
width: 200px; }
- /* line 100, ../sass/forms/_elems.scss */
+ /* line 93, ../sass/forms/_elems.scss */
.form .form-row .controls .l-small input[type="text"] {
width: 50px; }
- /* line 104, ../sass/forms/_elems.scss */
+ /* line 97, ../sass/forms/_elems.scss */
.form .form-row .controls .l-numeric input[type="text"] {
text-align: right; }
- /* line 108, ../sass/forms/_elems.scss */
+ /* line 101, ../sass/forms/_elems.scss */
.form .form-row .controls .select {
margin-right: 5px; }
- /* line 113, ../sass/forms/_elems.scss */
+ /* line 106, ../sass/forms/_elems.scss */
.form .form-row .field-hints {
color: #666666; }
- /* line 117, ../sass/forms/_elems.scss */
+ /* line 110, ../sass/forms/_elems.scss */
.form .form-row .selector-list {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
@@ -263,7 +258,7 @@
position: relative;
height: 150px;
overflow: auto; }
- /* line 128, ../sass/forms/_elems.scss */
+ /* line 121, ../sass/forms/_elems.scss */
.form .form-row .selector-list .wrapper {
overflow-y: auto;
position: absolute;
@@ -272,24 +267,24 @@
bottom: 5px;
left: 5px; }
-/* line 142, ../sass/forms/_elems.scss */
+/* line 135, ../sass/forms/_elems.scss */
label.form-control.checkbox input {
margin-right: 5px;
vertical-align: top; }
-/* line 148, ../sass/forms/_elems.scss */
+/* line 141, ../sass/forms/_elems.scss */
.hint,
.s-hint {
font-size: 0.9em; }
-/* line 153, ../sass/forms/_elems.scss */
+/* line 146, ../sass/forms/_elems.scss */
.l-result {
display: inline-block;
min-width: 32px;
min-height: 32px;
position: relative;
vertical-align: top; }
- /* line 160, ../sass/forms/_elems.scss */
+ /* line 153, ../sass/forms/_elems.scss */
.l-result div.s-hint {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
@@ -324,18 +319,17 @@ label.form-control.checkbox input {
.edit-main textarea {
-moz-appearance: none;
-webkit-appearance: none;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
- -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
+ -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
background: rgba(255, 255, 255, 0.1);
border: none;
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
color: #cccccc;
outline: none;
padding: 5px;
@@ -371,18 +365,17 @@ label.form-control.checkbox input {
input[type="text"] {
-moz-appearance: none;
-webkit-appearance: none;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
- -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
+ -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
background: rgba(255, 255, 255, 0.1);
border: none;
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
color: #cccccc;
outline: none;
padding: 0 3px; }
@@ -422,9 +415,9 @@ input[type="text"] {
background-image: -moz-linear-gradient(#525252, #454545);
background-image: -webkit-linear-gradient(#525252, #454545);
background-image: linear-gradient(#525252, #454545);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -511,18 +504,17 @@ input[type="text"] {
.channel-selector .treeview {
-moz-appearance: none;
-webkit-appearance: none;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
- -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
+ -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
background: rgba(255, 255, 255, 0.1);
border: none;
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
color: #cccccc;
outline: none;
padding: 0 3px;
diff --git a/platform/commonUI/general/res/css/items.css b/platform/commonUI/general/res/css/items.css
index 3457e4f0b3..620ed931bc 100644
--- a/platform/commonUI/general/res/css/items.css
+++ b/platform/commonUI/general/res/css/items.css
@@ -96,6 +96,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
+/*********************************************** FORM ELEMENTS */
/*
@mixin invokeMenu($baseColor: $colorBodyFg) {
$c: $baseColor;
@@ -163,9 +164,9 @@
background-image: -moz-linear-gradient(#5e5e5e, #525252);
background-image: -webkit-linear-gradient(#5e5e5e, #525252);
background-image: linear-gradient(#5e5e5e, #525252);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -303,9 +304,9 @@
background-image: -moz-linear-gradient(#0ac2ff, #00b4f0);
background-image: -webkit-linear-gradient(#0ac2ff, #00b4f0);
background-image: linear-gradient(#0ac2ff, #00b4f0);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
diff --git a/platform/commonUI/general/res/css/theme-espresso.css b/platform/commonUI/general/res/css/theme-espresso.css
index a12100cc67..66e22fb008 100644
--- a/platform/commonUI/general/res/css/theme-espresso.css
+++ b/platform/commonUI/general/res/css/theme-espresso.css
@@ -119,7 +119,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
-/* line 5, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
+/* line 5, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
@@ -140,38 +140,38 @@ time, mark, audio, video {
font-size: 100%;
vertical-align: baseline; }
-/* line 22, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
+/* line 22, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
html {
line-height: 1; }
-/* line 24, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
+/* line 24, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
ol, ul {
list-style: none; }
-/* line 26, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
+/* line 26, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
table {
border-collapse: collapse;
border-spacing: 0; }
-/* line 28, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
+/* line 28, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
caption, th, td {
text-align: left;
font-weight: normal;
vertical-align: middle; }
-/* line 30, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
+/* line 30, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
q, blockquote {
quotes: none; }
- /* line 103, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
+ /* line 103, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
q:before, q:after, blockquote:before, blockquote:after {
content: "";
content: none; }
-/* line 32, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
+/* line 32, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
a img {
border: none; }
-/* line 116, ../../../../../../../../.gem/ruby/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
+/* line 116, ../../../../../../../../../../Library/Ruby/Gems/2.0.0/gems/compass-core-1.0.3/stylesheets/compass/reset/_utilities.scss */
article, aside, details, figcaption, figure, footer, header, hgroup, main, menu, nav, section, summary {
display: block; }
@@ -196,6 +196,7 @@ article, aside, details, figcaption, figure, footer, header, hgroup, main, menu,
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
+/*********************************************** FORM ELEMENTS */
/*
@mixin invokeMenu($baseColor: $colorBodyFg) {
$c: $baseColor;
@@ -364,10 +365,15 @@ input, textarea {
font-family: Helvetica, Arial, sans-serif; }
/* line 53, ../sass/_global.scss */
+input[type="text"] {
+ vertical-align: baseline;
+ padding: 3px 5px !important; }
+
+/* line 58, ../sass/_global.scss */
h1, h2, h3 {
margin: 0; }
-/* line 57, ../sass/_global.scss */
+/* line 62, ../sass/_global.scss */
h1 {
font-size: 1.7em;
font-weight: normal !important;
@@ -375,21 +381,21 @@ h1 {
margin-bottom: 20px;
margin-top: 0; }
-/* line 65, ../sass/_global.scss */
+/* line 70, ../sass/_global.scss */
p {
margin-bottom: 10px; }
-/* line 69, ../sass/_global.scss */
+/* line 74, ../sass/_global.scss */
span {
/* 618 DEBUG
box-sizing: border-box;
*/ }
-/* line 75, ../sass/_global.scss */
+/* line 80, ../sass/_global.scss */
mct-container {
display: block; }
-/* line 79, ../sass/_global.scss */
+/* line 84, ../sass/_global.scss */
.abs, .btn-menu span.l-click-area {
position: absolute;
top: 0;
@@ -399,51 +405,51 @@ mct-container {
height: auto;
width: auto; }
-/* line 89, ../sass/_global.scss */
+/* line 94, ../sass/_global.scss */
.code, .codehilite {
font-family: "Lucida Console", monospace;
font-size: 0.7em;
line-height: 150%;
white-space: pre; }
-/* line 96, ../sass/_global.scss */
+/* line 101, ../sass/_global.scss */
.codehilite {
background-color: rgba(255, 255, 255, 0.1);
padding: 1em; }
-/* line 102, ../sass/_global.scss */
+/* line 107, ../sass/_global.scss */
.align-right {
text-align: right; }
-/* line 106, ../sass/_global.scss */
+/* line 111, ../sass/_global.scss */
.centered {
text-align: center; }
-/* line 110, ../sass/_global.scss */
+/* line 115, ../sass/_global.scss */
.no-margin {
margin: 0; }
-/* line 114, ../sass/_global.scss */
+/* line 119, ../sass/_global.scss */
.colorKey {
color: #0099cc; }
-/* line 118, ../sass/_global.scss */
+/* line 123, ../sass/_global.scss */
.ds {
-moz-box-shadow: rgba(0, 0, 0, 0.7) 0 4px 10px 2px;
-webkit-box-shadow: rgba(0, 0, 0, 0.7) 0 4px 10px 2px;
box-shadow: rgba(0, 0, 0, 0.7) 0 4px 10px 2px; }
-/* line 122, ../sass/_global.scss */
+/* line 127, ../sass/_global.scss */
.hide,
.hidden {
display: none !important; }
-/* line 128, ../sass/_global.scss */
+/* line 133, ../sass/_global.scss */
.paused:not(.s-btn):not(.icon-btn) {
border-color: #c56f01 !important;
color: #c56f01 !important; }
-/* line 134, ../sass/_global.scss */
+/* line 139, ../sass/_global.scss */
.sep {
color: rgba(255, 255, 255, 0.2); }
@@ -1235,67 +1241,6 @@ mct-container {
.s-text h3 {
margin-top: 2em; }
-/*****************************************************************************
- * 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.
- *****************************************************************************/
-/* line 22, ../sass/_badges.scss */
-.badge {
- background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iI2ZmZDIzMyIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZmYzcwMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
- background-size: 100%;
- background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffd233), color-stop(100%, #ffc700));
- background-image: -moz-linear-gradient(#ffd233, #ffc700);
- background-image: -webkit-linear-gradient(#ffd233, #ffc700);
- background-image: linear-gradient(#ffd233, #ffc700);
- color: #333;
- display: inline-block;
- text-align: center; }
-
-/* line 29, ../sass/_badges.scss */
-.top-bar .badge {
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
- border-radius: 3px;
- font-size: 1.4em;
- height: 25px;
- line-height: 25px;
- margin-right: 5px;
- width: 35px;
- vertical-align: middle; }
-
-/* line 54, ../sass/_badges.scss */
-.super-menu .badge {
- background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwYmZmZiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwOTljYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA==');
- background-size: 100%;
- background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #00bfff), color-stop(100%, #0099cc));
- background-image: -moz-linear-gradient(#00bfff, #0099cc);
- background-image: -webkit-linear-gradient(#00bfff, #0099cc);
- background-image: linear-gradient(#00bfff, #0099cc);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
- -moz-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
- -webkit-box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
- box-shadow: rgba(0, 0, 0, 0.2) 0 1px 2px;
- padding: 2px 7px; }
-
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
@@ -1486,7 +1431,8 @@ mct-container {
height: 100%; }
/* line 27, ../sass/lists/_tabular.scss */
-.tabular {
+.tabular,
+table {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -1494,98 +1440,190 @@ mct-container {
border-collapse: collapse;
color: #fff;
display: table;
- font-size: 0.75em;
+ font-size: 0.75rem;
position: relative;
width: 100%; }
- /* line 37, ../sass/lists/_tabular.scss */
+ /* line 38, ../sass/lists/_tabular.scss */
.tabular thead, .tabular .thead,
- .tabular tbody tr, .tabular .tbody .tr {
+ .tabular tbody tr, .tabular .tbody .tr,
+ table thead,
+ table .thead,
+ table tbody tr,
+ table .tbody .tr {
width: 100%; }
- /* line 45, ../sass/lists/_tabular.scss */
- .tabular thead tr, .tabular thead .tr, .tabular .thead tr, .tabular .thead .tr {
- height: 18px; }
- /* line 48, ../sass/lists/_tabular.scss */
- .tabular thead:before, .tabular .thead:before {
- content: "";
- display: block;
- z-index: 0;
- position: absolute;
- width: 100%;
- height: 18px;
- background: rgba(255, 255, 255, 0.15); }
- /* line 58, ../sass/lists/_tabular.scss */
- .tabular tbody, .tabular .tbody {
+ /* line 44, ../sass/lists/_tabular.scss */
+ .tabular thead, .tabular .thead,
+ table thead,
+ table .thead {
+ border-bottom: 1px solid #333; }
+ /* line 47, ../sass/lists/_tabular.scss */
+ .tabular tbody, .tabular .tbody,
+ table tbody,
+ table .tbody {
display: table-row-group; }
- /* line 65, ../sass/lists/_tabular.scss */
- .tabular tbody tr:hover, .tabular tbody .tr:hover, .tabular .tbody tr:hover, .tabular .tbody .tr:hover {
+ /* line 54, ../sass/lists/_tabular.scss */
+ .tabular tbody tr:hover, .tabular tbody .tr:hover, .tabular .tbody tr:hover, .tabular .tbody .tr:hover,
+ table tbody tr:hover,
+ table tbody .tr:hover,
+ table .tbody tr:hover,
+ table .tbody .tr:hover {
background: rgba(255, 255, 255, 0.1); }
- /* line 70, ../sass/lists/_tabular.scss */
- .tabular tr, .tabular .tr {
+ /* line 59, ../sass/lists/_tabular.scss */
+ .tabular tr, .tabular .tr,
+ table tr,
+ table .tr {
display: table-row; }
- /* line 72, ../sass/lists/_tabular.scss */
- .tabular tr:first-child .td, .tabular .tr:first-child .td {
+ /* line 61, ../sass/lists/_tabular.scss */
+ .tabular tr:first-child .td, .tabular .tr:first-child .td,
+ table tr:first-child .td,
+ table .tr:first-child .td {
border-top: none; }
- /* line 75, ../sass/lists/_tabular.scss */
- .tabular tr th, .tabular tr .th, .tabular tr td, .tabular tr .td, .tabular .tr th, .tabular .tr .th, .tabular .tr td, .tabular .tr .td {
+ /* line 65, ../sass/lists/_tabular.scss */
+ .tabular tr.group-header td, .tabular tr.group-header .td, .tabular .tr.group-header td, .tabular .tr.group-header .td,
+ table tr.group-header td,
+ table tr.group-header .td,
+ table .tr.group-header td,
+ table .tr.group-header .td {
+ background-color: #404040;
+ color: #a6a6a6; }
+ /* line 71, ../sass/lists/_tabular.scss */
+ .tabular tr th, .tabular tr .th, .tabular tr td, .tabular tr .td, .tabular .tr th, .tabular .tr .th, .tabular .tr td, .tabular .tr .td,
+ table tr th,
+ table tr .th,
+ table tr td,
+ table tr .td,
+ table .tr th,
+ table .tr .th,
+ table .tr td,
+ table .tr .td {
display: table-cell; }
- /* line 78, ../sass/lists/_tabular.scss */
- .tabular tr th, .tabular tr .th, .tabular .tr th, .tabular .tr .th {
- border: none;
- border-left: 1px solid rgba(255, 255, 255, 0.1);
+ /* line 74, ../sass/lists/_tabular.scss */
+ .tabular tr th, .tabular tr .th, .tabular .tr th, .tabular .tr .th,
+ table tr th,
+ table tr .th,
+ table .tr th,
+ table .tr .th {
+ background-color: #4d4d4d;
+ border-left: 1px solid #333;
color: #b3b3b3;
- padding: 0 5px;
+ padding: 5px 5px;
white-space: nowrap;
vertical-align: middle; }
- /* line 85, ../sass/lists/_tabular.scss */
- .tabular tr th:first-child, .tabular tr .th:first-child, .tabular .tr th:first-child, .tabular .tr .th:first-child {
+ /* line 81, ../sass/lists/_tabular.scss */
+ .tabular tr th:first-child, .tabular tr .th:first-child, .tabular .tr th:first-child, .tabular .tr .th:first-child,
+ table tr th:first-child,
+ table tr .th:first-child,
+ table .tr th:first-child,
+ table .tr .th:first-child {
border-left: none; }
- /* line 89, ../sass/lists/_tabular.scss */
- .tabular tr th.sort .icon-sorting:before, .tabular tr .th.sort .icon-sorting:before, .tabular .tr th.sort .icon-sorting:before, .tabular .tr .th.sort .icon-sorting:before {
- display: inline-block;
+ /* line 85, ../sass/lists/_tabular.scss */
+ .tabular tr th.sort.sort:after, .tabular tr .th.sort.sort:after, .tabular .tr th.sort.sort:after, .tabular .tr .th.sort.sort:after,
+ table tr th.sort.sort:after,
+ table tr .th.sort.sort:after,
+ table .tr th.sort.sort:after,
+ table .tr .th.sort.sort:after {
+ color: #49dedb;
font-family: symbolsfont;
- margin-left: 5px; }
- /* line 94, ../sass/lists/_tabular.scss */
- .tabular tr th.sort.asc .icon-sorting:before, .tabular tr .th.sort.asc .icon-sorting:before, .tabular .tr th.sort.asc .icon-sorting:before, .tabular .tr .th.sort.asc .icon-sorting:before {
- content: '0'; }
+ font-size: 8px;
+ content: "\ed";
+ display: inline-block;
+ margin-left: 3px; }
+ /* line 93, ../sass/lists/_tabular.scss */
+ .tabular tr th.sort.sort.desc:after, .tabular tr .th.sort.sort.desc:after, .tabular .tr th.sort.sort.desc:after, .tabular .tr .th.sort.sort.desc:after,
+ table tr th.sort.sort.desc:after,
+ table tr .th.sort.sort.desc:after,
+ table .tr th.sort.sort.desc:after,
+ table .tr .th.sort.sort.desc:after {
+ content: "\ec"; }
/* line 97, ../sass/lists/_tabular.scss */
- .tabular tr th.sort.desc .icon-sorting:before, .tabular tr .th.sort.desc .icon-sorting:before, .tabular .tr th.sort.desc .icon-sorting:before, .tabular .tr .th.sort.desc .icon-sorting:before {
- content: '1'; }
- /* line 102, ../sass/lists/_tabular.scss */
- .tabular tr td, .tabular tr .td, .tabular .tr td, .tabular .tr .td {
- border-top: 1px solid rgba(255, 255, 255, 0.1);
- min-width: 110px;
+ .tabular tr th.sortable, .tabular tr .th.sortable, .tabular .tr th.sortable, .tabular .tr .th.sortable,
+ table tr th.sortable,
+ table tr .th.sortable,
+ table .tr th.sortable,
+ table .tr .th.sortable {
+ cursor: pointer; }
+ /* line 101, ../sass/lists/_tabular.scss */
+ .tabular tr td, .tabular tr .td, .tabular .tr td, .tabular .tr .td,
+ table tr td,
+ table tr .td,
+ table .tr td,
+ table .tr .td {
+ border-bottom: 1px solid rgba(255, 255, 255, 0.1);
+ min-width: 20px;
color: #fff;
- padding: 2px 5px;
+ padding: 3px 5px;
+ word-wrap: break-word;
vertical-align: top; }
/* line 108, ../sass/lists/_tabular.scss */
- .tabular tr td.numeric, .tabular tr .td.numeric, .tabular .tr td.numeric, .tabular .tr .td.numeric {
+ .tabular tr td.numeric, .tabular tr .td.numeric, .tabular .tr td.numeric, .tabular .tr .td.numeric,
+ table tr td.numeric,
+ table tr .td.numeric,
+ table .tr td.numeric,
+ table .tr .td.numeric {
text-align: right; }
/* line 111, ../sass/lists/_tabular.scss */
- .tabular tr td.s-cell-type-value, .tabular tr .td.s-cell-type-value, .tabular .tr td.s-cell-type-value, .tabular .tr .td.s-cell-type-value {
+ .tabular tr td.s-cell-type-value, .tabular tr .td.s-cell-type-value, .tabular .tr td.s-cell-type-value, .tabular .tr .td.s-cell-type-value,
+ table tr td.s-cell-type-value,
+ table tr .td.s-cell-type-value,
+ table .tr td.s-cell-type-value,
+ table .tr .td.s-cell-type-value {
text-align: right; }
/* line 113, ../sass/lists/_tabular.scss */
- .tabular tr td.s-cell-type-value .l-cell-contents, .tabular tr .td.s-cell-type-value .l-cell-contents, .tabular .tr td.s-cell-type-value .l-cell-contents, .tabular .tr .td.s-cell-type-value .l-cell-contents {
+ .tabular tr td.s-cell-type-value .l-cell-contents, .tabular tr .td.s-cell-type-value .l-cell-contents, .tabular .tr td.s-cell-type-value .l-cell-contents, .tabular .tr .td.s-cell-type-value .l-cell-contents,
+ table tr td.s-cell-type-value .l-cell-contents,
+ table tr .td.s-cell-type-value .l-cell-contents,
+ table .tr td.s-cell-type-value .l-cell-contents,
+ table .tr .td.s-cell-type-value .l-cell-contents {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
border-radius: 2px;
padding-left: 5px;
padding-right: 5px; }
- /* line 122, ../sass/lists/_tabular.scss */
- .tabular.filterable tbody, .tabular.filterable .tbody {
- top: 36px; }
- /* line 127, ../sass/lists/_tabular.scss */
- .tabular.fixed-header {
+ /* line 129, ../sass/lists/_tabular.scss */
+ .tabular.filterable tbody, .tabular.filterable .tbody,
+ table.filterable tbody,
+ table.filterable .tbody {
+ top: 44px; }
+ /* line 132, ../sass/lists/_tabular.scss */
+ .tabular.filterable input[type="text"],
+ table.filterable input[type="text"] {
+ -moz-box-sizing: border-box;
+ -webkit-box-sizing: border-box;
+ box-sizing: border-box;
+ width: 100%; }
+ /* line 138, ../sass/lists/_tabular.scss */
+ .tabular.fixed-header,
+ table.fixed-header {
height: 100%; }
- /* line 129, ../sass/lists/_tabular.scss */
+ /* line 140, ../sass/lists/_tabular.scss */
.tabular.fixed-header thead, .tabular.fixed-header .thead,
- .tabular.fixed-header tbody tr, .tabular.fixed-header .tbody .tr {
+ .tabular.fixed-header tbody tr, .tabular.fixed-header .tbody .tr,
+ table.fixed-header thead,
+ table.fixed-header .thead,
+ table.fixed-header tbody tr,
+ table.fixed-header .tbody .tr {
display: table;
table-layout: fixed; }
- /* line 134, ../sass/lists/_tabular.scss */
- .tabular.fixed-header thead, .tabular.fixed-header .thead {
+ /* line 145, ../sass/lists/_tabular.scss */
+ .tabular.fixed-header thead, .tabular.fixed-header .thead,
+ table.fixed-header thead,
+ table.fixed-header .thead {
width: calc(100% - 10px); }
- /* line 137, ../sass/lists/_tabular.scss */
- .tabular.fixed-header tbody, .tabular.fixed-header .tbody {
+ /* line 147, ../sass/lists/_tabular.scss */
+ .tabular.fixed-header thead:before, .tabular.fixed-header .thead:before,
+ table.fixed-header thead:before,
+ table.fixed-header .thead:before {
+ content: "";
+ display: block;
+ z-index: 0;
+ position: absolute;
+ width: 100%;
+ height: 22px;
+ background: rgba(255, 255, 255, 0.15); }
+ /* line 157, ../sass/lists/_tabular.scss */
+ .tabular.fixed-header tbody, .tabular.fixed-header .tbody,
+ table.fixed-header tbody,
+ table.fixed-header .tbody {
overflow: hidden;
position: absolute;
top: 0;
@@ -1594,11 +1632,13 @@ mct-container {
left: 0;
width: auto;
height: auto;
- top: 18px;
+ top: 22px;
display: block;
overflow-y: scroll; }
- /* line 145, ../sass/lists/_tabular.scss */
- .tabular.t-event-messages td, .tabular.t-event-messages .td {
+ /* line 165, ../sass/lists/_tabular.scss */
+ .tabular.t-event-messages td, .tabular.t-event-messages .td,
+ table.t-event-messages td,
+ table.t-event-messages .td {
min-width: 150px; }
/* line 1, ../sass/controls/_breadcrumb.scss */
@@ -1698,9 +1738,9 @@ mct-container {
.s-btn,
.icon-btn,
.s-icon-btn {
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -1718,9 +1758,9 @@ mct-container {
background-image: -moz-linear-gradient(#0ac2ff, #00b4f0);
background-image: -webkit-linear-gradient(#0ac2ff, #00b4f0);
background-image: linear-gradient(#0ac2ff, #00b4f0);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -1767,9 +1807,9 @@ mct-container {
background-image: -moz-linear-gradient(#24c8ff, #0ac2ff);
background-image: -webkit-linear-gradient(#24c8ff, #0ac2ff);
background-image: linear-gradient(#24c8ff, #0ac2ff);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -1821,9 +1861,9 @@ mct-container {
background-image: -moz-linear-gradient(#858585, #787878);
background-image: -webkit-linear-gradient(#858585, #787878);
background-image: linear-gradient(#858585, #787878);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -1872,9 +1912,9 @@ mct-container {
background-image: -moz-linear-gradient(#525252, #454545);
background-image: -webkit-linear-gradient(#525252, #454545);
background-image: linear-gradient(#525252, #454545);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -1932,9 +1972,9 @@ mct-container {
background-image: -moz-linear-gradient(#fe9105, #e98301);
background-image: -webkit-linear-gradient(#fe9105, #e98301);
background-image: linear-gradient(#fe9105, #e98301);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -2277,21 +2317,21 @@ a.l-btn span {
.btn-set .btn:first-child,
.btn-set .t-btn:first-child {
border-left: none;
- -moz-border-radius-topleft: 2px;
- -webkit-border-top-left-radius: 2px;
- border-top-left-radius: 2px;
- -moz-border-radius-bottomleft: 2px;
- -webkit-border-bottom-left-radius: 2px;
- border-bottom-left-radius: 2px; }
+ -moz-border-radius-topleft: 3px;
+ -webkit-border-top-left-radius: 3px;
+ border-top-left-radius: 3px;
+ -moz-border-radius-bottomleft: 3px;
+ -webkit-border-bottom-left-radius: 3px;
+ border-bottom-left-radius: 3px; }
/* line 169, ../sass/controls/_controls.scss */
.btn-set .btn:last-child,
.btn-set .t-btn:last-child {
- -moz-border-radius-topright: 2px;
- -webkit-border-top-right-radius: 2px;
- border-top-right-radius: 2px;
- -moz-border-radius-bottomright: 2px;
- -webkit-border-bottom-right-radius: 2px;
- border-bottom-right-radius: 2px; }
+ -moz-border-radius-topright: 3px;
+ -webkit-border-top-right-radius: 3px;
+ border-top-right-radius: 3px;
+ -moz-border-radius-bottomright: 3px;
+ -webkit-border-bottom-right-radius: 3px;
+ border-bottom-right-radius: 3px; }
/* line 175, ../sass/controls/_controls.scss */
.object-browse-bar .btn,
@@ -2391,9 +2431,9 @@ label.checkbox.custom {
background-image: -moz-linear-gradient(#525252, #454545);
background-image: -webkit-linear-gradient(#525252, #454545);
background-image: linear-gradient(#525252, #454545);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -2462,9 +2502,9 @@ label.checkbox.custom {
padding-left: 25px; }
/* line 335, ../sass/controls/_controls.scss */
.top-bar .btn-menu.browse-btn .badge {
- -moz-border-radius: 3px;
- -webkit-border-radius: 3px;
- border-radius: 3px;
+ -moz-border-radius: 4.5px;
+ -webkit-border-radius: 4.5px;
+ border-radius: 4.5px;
display: block;
font-size: 1em;
line-height: 15px;
@@ -2558,9 +2598,9 @@ label.checkbox.custom {
background-image: -moz-linear-gradient(#525252, #454545);
background-image: -webkit-linear-gradient(#525252, #454545);
background-image: linear-gradient(#525252, #454545);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -2772,9 +2812,9 @@ label.checkbox.custom {
background-image: -moz-linear-gradient(#5e5e5e, #525252);
background-image: -webkit-linear-gradient(#5e5e5e, #525252);
background-image: linear-gradient(#5e5e5e, #525252);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -2797,7 +2837,7 @@ label.checkbox.custom {
.menu-element .menu ul {
margin: 0;
padding: 0; }
- /* line 277, ../sass/_mixins.scss */
+ /* line 309, ../sass/_mixins.scss */
.menu-element .menu ul li {
list-style-type: none;
margin: 0;
@@ -2809,7 +2849,7 @@ label.checkbox.custom {
box-sizing: border-box;
border-top: 1px solid #737373;
color: #d9d9d9;
- line-height: 1.4rem;
+ line-height: 1.5rem;
padding: 3px 10px 3px 30px;
white-space: nowrap; }
/* line 46, ../sass/controls/_menus.scss */
@@ -2835,9 +2875,9 @@ label.checkbox.custom {
background-image: -moz-linear-gradient(#8c8c8c, #808080);
background-image: -webkit-linear-gradient(#8c8c8c, #808080);
background-image: linear-gradient(#8c8c8c, #808080);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -2903,9 +2943,9 @@ label.checkbox.custom {
overflow-y: auto; }
/* line 119, ../sass/controls/_menus.scss */
.menu-element .super-menu .pane.left ul li {
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
padding-left: 30px;
border-top: none; }
/* line 126, ../sass/controls/_menus.scss */
@@ -3430,27 +3470,6 @@ label.checkbox.custom {
font-size: 0.65em;
vertical-align: top; }
-/*****************************************************************************
- * 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
@@ -3534,27 +3553,21 @@ label.checkbox.custom {
line-height: 14px;
margin-right: 5px; }
/* line 89, ../sass/forms/_elems.scss */
- .form .form-row .controls input[type="text"] {
- height: 22px;
- line-height: 22px;
- margin-top: -4px;
- vertical-align: baseline; }
- /* line 96, ../sass/forms/_elems.scss */
.form .form-row .controls .l-med input[type="text"] {
width: 200px; }
- /* line 100, ../sass/forms/_elems.scss */
+ /* line 93, ../sass/forms/_elems.scss */
.form .form-row .controls .l-small input[type="text"] {
width: 50px; }
- /* line 104, ../sass/forms/_elems.scss */
+ /* line 97, ../sass/forms/_elems.scss */
.form .form-row .controls .l-numeric input[type="text"] {
text-align: right; }
- /* line 108, ../sass/forms/_elems.scss */
+ /* line 101, ../sass/forms/_elems.scss */
.form .form-row .controls .select {
margin-right: 5px; }
- /* line 113, ../sass/forms/_elems.scss */
+ /* line 106, ../sass/forms/_elems.scss */
.form .form-row .field-hints {
color: #666666; }
- /* line 117, ../sass/forms/_elems.scss */
+ /* line 110, ../sass/forms/_elems.scss */
.form .form-row .selector-list {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
@@ -3567,7 +3580,7 @@ label.checkbox.custom {
position: relative;
height: 150px;
overflow: auto; }
- /* line 128, ../sass/forms/_elems.scss */
+ /* line 121, ../sass/forms/_elems.scss */
.form .form-row .selector-list .wrapper {
overflow-y: auto;
position: absolute;
@@ -3576,24 +3589,24 @@ label.checkbox.custom {
bottom: 5px;
left: 5px; }
-/* line 142, ../sass/forms/_elems.scss */
+/* line 135, ../sass/forms/_elems.scss */
label.form-control.checkbox input {
margin-right: 5px;
vertical-align: top; }
-/* line 148, ../sass/forms/_elems.scss */
+/* line 141, ../sass/forms/_elems.scss */
.hint,
.s-hint {
font-size: 0.9em; }
-/* line 153, ../sass/forms/_elems.scss */
+/* line 146, ../sass/forms/_elems.scss */
.l-result {
display: inline-block;
min-width: 32px;
min-height: 32px;
position: relative;
vertical-align: top; }
- /* line 160, ../sass/forms/_elems.scss */
+ /* line 153, ../sass/forms/_elems.scss */
.l-result div.s-hint {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
@@ -3687,22 +3700,21 @@ span.req {
input[type="text"] {
-moz-appearance: none;
-webkit-appearance: none;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
- -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
+ -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
background: rgba(255, 255, 255, 0.1);
border: none;
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
color: #cccccc;
outline: none;
padding: 0 3px; }
- /* line 33, ../sass/forms/_mixins.scss */
+ /* line 275, ../sass/_mixins.scss */
input[type="text"].error {
background: rgba(255, 0, 0, 0.5); }
/* line 29, ../sass/forms/_text-input.scss */
@@ -3738,9 +3750,9 @@ input[type="text"] {
background-image: -moz-linear-gradient(#525252, #454545);
background-image: -webkit-linear-gradient(#525252, #454545);
background-image: linear-gradient(#525252, #454545);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -3827,18 +3839,17 @@ input[type="text"] {
.channel-selector .treeview {
-moz-appearance: none;
-webkit-appearance: none;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
- -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
+ -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
background: rgba(255, 255, 255, 0.1);
border: none;
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
color: #cccccc;
outline: none;
padding: 0 3px;
@@ -3848,7 +3859,7 @@ input[type="text"] {
max-height: 400px;
overflow: auto;
padding: 5px; }
- /* line 33, ../sass/forms/_mixins.scss */
+ /* line 275, ../sass/_mixins.scss */
.channel-selector .treeview.error {
background: rgba(255, 0, 0, 0.5); }
/* line 36, ../sass/forms/_channel-selector.scss */
@@ -3932,24 +3943,23 @@ input[type="text"] {
.t-filter input.t-filter-input {
-moz-appearance: none;
-webkit-appearance: none;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
- -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
- box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px;
+ -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
+ box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px;
background: rgba(255, 255, 255, 0.1);
border: none;
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
color: #cccccc;
outline: none;
padding: 0 3px;
background: #3b3b3b;
border-bottom: 1px solid #4d4d4d; }
- /* line 33, ../sass/forms/_mixins.scss */
+ /* line 275, ../sass/_mixins.scss */
.filter input.filter.error,
.filter input.t-filter-input.error,
.t-filter input.filter.error,
@@ -3967,9 +3977,9 @@ input[type="text"] {
/* line 42, ../sass/forms/_filter.scss */
.filter .icon.ui-symbol,
.t-filter .icon.ui-symbol {
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
display: inline-block;
font-size: 1.3em;
height: 22px;
@@ -3983,9 +3993,9 @@ input[type="text"] {
/* line 54, ../sass/forms/_filter.scss */
.filter .s-a-clear.ui-symbol,
.t-filter .s-a-clear.ui-symbol {
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -4083,9 +4093,9 @@ input[type="text"] {
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
background: black;
color: #e6e6e6;
padding: 2px 5px;
@@ -4365,9 +4375,9 @@ input[type="text"] {
background-image: -moz-linear-gradient(#525252, #454545);
background-image: -webkit-linear-gradient(#525252, #454545);
background-image: linear-gradient(#525252, #454545);
- -moz-border-radius: 2px;
- -webkit-border-radius: 2px;
- border-radius: 2px;
+ -moz-border-radius: 3px;
+ -webkit-border-radius: 3px;
+ border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
@@ -4747,30 +4757,30 @@ input[type="text"] {
.l-infobubble-wrapper .l-infobubble table tr td {
padding: 2px 0;
vertical-align: top; }
- /* line 57, ../sass/helpers/_bubbles.scss */
+ /* line 53, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper .l-infobubble table tr td.label {
padding-right: 10px;
white-space: nowrap; }
- /* line 61, ../sass/helpers/_bubbles.scss */
+ /* line 57, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper .l-infobubble table tr td.value {
- white-space: nowrap; }
- /* line 65, ../sass/helpers/_bubbles.scss */
+ word-break: break-all; }
+ /* line 61, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper .l-infobubble table tr td.align-wrap {
white-space: normal; }
- /* line 71, ../sass/helpers/_bubbles.scss */
+ /* line 67, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper .l-infobubble .title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
margin-bottom: 5px; }
- /* line 78, ../sass/helpers/_bubbles.scss */
+ /* line 74, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-left {
margin-left: 20px; }
- /* line 80, ../sass/helpers/_bubbles.scss */
+ /* line 76, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-left .l-infobubble::before {
right: 100%; }
@media 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), screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
- /* line 80, ../sass/helpers/_bubbles.scss */
+ /* line 76, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-left .l-infobubble::before {
width: 0;
height: 0;
@@ -4778,30 +4788,30 @@ input[type="text"] {
border-bottom: 6.66667px solid transparent;
border-right: 10px solid #ddd; } }
@media 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), screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
- /* line 92, ../sass/helpers/_bubbles.scss */
+ /* line 88, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-right {
margin-right: 20px; } }
- /* line 99, ../sass/helpers/_bubbles.scss */
+ /* line 95, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-right .l-infobubble::before {
left: 100%; }
@media 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), screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) {
- /* line 99, ../sass/helpers/_bubbles.scss */
+ /* line 95, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-right .l-infobubble::before {
width: 0;
height: 0;
border-top: 6.66667px solid transparent;
border-bottom: 6.66667px solid transparent;
border-left: 10px solid #ddd; } }
- /* line 112, ../sass/helpers/_bubbles.scss */
+ /* line 108, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-top .l-infobubble::before {
top: 20px; }
- /* line 118, ../sass/helpers/_bubbles.scss */
+ /* line 114, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-btm .l-infobubble::before {
bottom: 20px; }
- /* line 123, ../sass/helpers/_bubbles.scss */
+ /* line 119, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-down {
margin-bottom: 10px; }
- /* line 125, ../sass/helpers/_bubbles.scss */
+ /* line 121, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-down .l-infobubble::before {
left: 50%;
top: 100%;
@@ -4809,21 +4819,21 @@ input[type="text"] {
border-left: 5px solid transparent;
border-right: 5px solid transparent;
border-top: 7.5px solid #ddd; }
- /* line 134, ../sass/helpers/_bubbles.scss */
+ /* line 130, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper .arw {
z-index: 2; }
- /* line 137, ../sass/helpers/_bubbles.scss */
+ /* line 133, ../sass/helpers/_bubbles.scss */
.l-infobubble-wrapper.arw-up .arw.arw-down, .l-infobubble-wrapper.arw-down .arw.arw-up {
display: none; }
-/* line 144, ../sass/helpers/_bubbles.scss */
+/* line 142, ../sass/helpers/_bubbles.scss */
.l-thumbsbubble-wrapper .arw-up {
width: 0;
height: 0;
border-left: 6.66667px solid transparent;
border-right: 6.66667px solid transparent;
border-bottom: 10px solid #4d4d4d; }
-/* line 147, ../sass/helpers/_bubbles.scss */
+/* line 145, ../sass/helpers/_bubbles.scss */
.l-thumbsbubble-wrapper .arw-down {
width: 0;
height: 0;
@@ -4831,7 +4841,7 @@ input[type="text"] {
border-right: 6.66667px solid transparent;
border-top: 10px solid #4d4d4d; }
-/* line 151, ../sass/helpers/_bubbles.scss */
+/* line 150, ../sass/helpers/_bubbles.scss */
.s-infobubble {
-moz-border-radius: 2px;
-webkit-border-radius: 2px;
@@ -4842,22 +4852,29 @@ input[type="text"] {
background: #ddd;
color: #666;
font-size: 0.8rem; }
- /* line 158, ../sass/helpers/_bubbles.scss */
+ /* line 157, ../sass/helpers/_bubbles.scss */
.s-infobubble .title {
color: #333333;
font-weight: bold; }
/* line 163, ../sass/helpers/_bubbles.scss */
- .s-infobubble tr td {
- border-top: 1px solid #c4c4c4;
+ .s-infobubble table tr td {
+ border: none;
+ border-top: 1px solid #c4c4c4 !important;
font-size: 0.9em; }
- /* line 167, ../sass/helpers/_bubbles.scss */
- .s-infobubble tr:first-child td {
+ /* line 169, ../sass/helpers/_bubbles.scss */
+ .s-infobubble table tr:first-child td {
+ border-top: none !important; }
+ /* line 174, ../sass/helpers/_bubbles.scss */
+ .s-infobubble:first-child td {
border-top: none; }
- /* line 171, ../sass/helpers/_bubbles.scss */
+ /* line 178, ../sass/helpers/_bubbles.scss */
+ .s-infobubble .label {
+ color: gray; }
+ /* line 182, ../sass/helpers/_bubbles.scss */
.s-infobubble .value {
color: #333333; }
-/* line 176, ../sass/helpers/_bubbles.scss */
+/* line 188, ../sass/helpers/_bubbles.scss */
.s-thumbsbubble {
background: #4d4d4d;
color: #b3b3b3; }
@@ -5078,27 +5095,34 @@ input[type="text"] {
margin-top: -5%;
margin-left: -5%;
z-index: 2; }
+ /* line 53, ../sass/helpers/_wait-spinner.scss */
+ .t-wait-spinner.inline,
+ .wait-spinner.inline {
+ display: inline-block !important;
+ margin-right: 5px;
+ position: relative !important;
+ vertical-align: middle; }
-/* line 55, ../sass/helpers/_wait-spinner.scss */
+/* line 61, ../sass/helpers/_wait-spinner.scss */
.l-wait-spinner-holder {
pointer-events: none;
position: absolute; }
- /* line 59, ../sass/helpers/_wait-spinner.scss */
+ /* line 65, ../sass/helpers/_wait-spinner.scss */
.l-wait-spinner-holder.align-left .t-wait-spinner {
left: 0;
margin-left: 0; }
- /* line 64, ../sass/helpers/_wait-spinner.scss */
+ /* line 70, ../sass/helpers/_wait-spinner.scss */
.l-wait-spinner-holder.full-size {
display: inline-block;
height: 100%;
width: 100%; }
- /* line 67, ../sass/helpers/_wait-spinner.scss */
+ /* line 73, ../sass/helpers/_wait-spinner.scss */
.l-wait-spinner-holder.full-size .t-wait-spinner {
top: 0;
margin-top: 0;
padding: 30%; }
-/* line 76, ../sass/helpers/_wait-spinner.scss */
+/* line 82, ../sass/helpers/_wait-spinner.scss */
.treeview .wait-spinner {
display: block;
position: absolute;
@@ -5118,6 +5142,27 @@ input[type="text"] {
top: 2px;
left: 0; }
+/* line 91, ../sass/helpers/_wait-spinner.scss */
+.wait-spinner.sm {
+ display: block;
+ position: absolute;
+ -webkit-animation: rotation .6s infinite linear;
+ -moz-animation: rotation .6s infinite linear;
+ -o-animation: rotation .6s infinite linear;
+ animation: rotation .6s infinite linear;
+ border-color: rgba(0, 153, 204, 0.25);
+ border-top-color: #0099cc;
+ border-style: solid;
+ border-width: 0.25em;
+ border-radius: 100%;
+ height: 13px;
+ width: 13px;
+ margin-left: 0 !important;
+ margin-top: 0 !important;
+ padding: 0 !important;
+ top: 0;
+ left: 0; }
+
/*****************************************************************************
* Open MCT Web, Copyright (c) 2014-2015, United States Government
* as represented by the Administrator of the National Aeronautics and Space
@@ -5322,6 +5367,18 @@ input[type="text"] {
height: 100%;
width: 100%; }
+/* Styles for messages */
+/* line 4, ../sass/_messages.scss */
+.message.block {
+ -moz-border-radius: 2px;
+ -webkit-border-radius: 2px;
+ border-radius: 2px;
+ padding: 10px; }
+/* line 8, ../sass/_messages.scss */
+.message.error {
+ background-color: rgba(255, 60, 0, 0.3);
+ color: #ff8a66; }
+
/* line 5, ../sass/_initialization.scss */
.browse-mode .split-layout .split-pane-component.pane.left {
width: 15%; }
@@ -5361,3 +5418,31 @@ input[type="text"] {
/* line 32, ../sass/_hide-non-functional.scss */
.browse-mode .browse-area.holder {
top: 10px; }
+
+/* Styles for sub-dividing views generically */
+/* line 3, ../sass/_views.scss */
+.l-view-section {
+ overflow: hidden;
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ width: auto;
+ height: auto;
+ font-size: 0.8rem; }
+ /* line 6, ../sass/_views.scss */
+ .l-view-section h2 {
+ color: #fff;
+ margin-bottom: 5px; }
+ /* line 10, ../sass/_views.scss */
+ .l-view-section.fixed {
+ font-size: 0.8em; }
+ /* line 13, ../sass/_views.scss */
+ .l-view-section.scrolling {
+ overflow: auto; }
+ /* line 16, ../sass/_views.scss */
+ .l-view-section .controls,
+ .l-view-section label,
+ .l-view-section .inline-block {
+ display: inline-block; }
diff --git a/platform/commonUI/general/res/css/tree.css b/platform/commonUI/general/res/css/tree.css
index dec304455c..b80e1ff5f9 100644
--- a/platform/commonUI/general/res/css/tree.css
+++ b/platform/commonUI/general/res/css/tree.css
@@ -96,6 +96,7 @@
* this source code distribution or the Licensing information page available
* at runtime from the About dialog for additional information.
*****************************************************************************/
+/*********************************************** FORM ELEMENTS */
/*
@mixin invokeMenu($baseColor: $colorBodyFg) {
$c: $baseColor;
@@ -151,7 +152,7 @@
ul.tree {
margin: 0;
padding: 0; }
- /* line 277, ../sass/_mixins.scss */
+ /* line 309, ../sass/_mixins.scss */
ul.tree li {
list-style-type: none;
margin: 0;
@@ -171,8 +172,8 @@ ul.tree {
transition: background-color 0.25s;
display: block;
font-size: 0.8em;
- height: 1.4rem;
- line-height: 1.4rem;
+ height: 1.5rem;
+ line-height: 1.5rem;
margin-bottom: 3px;
position: relative; }
/* line 39, ../sass/tree/_tree.scss */
@@ -326,7 +327,7 @@ ul.tree {
ul.tree {
margin: 0;
padding: 0; }
- /* line 277, ../sass/_mixins.scss */
+ /* line 309, ../sass/_mixins.scss */
ul.tree li {
list-style-type: none;
margin: 0;
diff --git a/platform/commonUI/general/res/fonts/symbols/iconmoon.io-WTD-Symbols-v2.0.json b/platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json
similarity index 99%
rename from platform/commonUI/general/res/fonts/symbols/iconmoon.io-WTD-Symbols-v2.0.json
rename to platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json
index e2215bed12..502ce67f79 100644
--- a/platform/commonUI/general/res/fonts/symbols/iconmoon.io-WTD-Symbols-v2.0.json
+++ b/platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json
@@ -1,19 +1,59 @@
{
"metadata": {
- "name": "WTD Symbols v2.",
- "lastOpened": 1435765696898,
- "created": 1435764071891
+ "name": "WTD Symbols v2.1",
+ "lastOpened": 1439844340068,
+ "created": 1439844318831
},
"iconSets": [
{
"selection": [
+ {
+ "order": 77,
+ "id": 83,
+ "prevSize": 32,
+ "code": 58881,
+ "name": "icon-datatable",
+ "tempChar": ""
+ },
+ {
+ "order": 78,
+ "id": 82,
+ "prevSize": 32,
+ "code": 58882,
+ "name": "icon-tabular-scrolling",
+ "tempChar": ""
+ },
+ {
+ "order": 79,
+ "id": 81,
+ "prevSize": 32,
+ "code": 58884,
+ "name": "icon-tabular",
+ "tempChar": ""
+ },
+ {
+ "order": 80,
+ "id": 80,
+ "prevSize": 32,
+ "code": 58885,
+ "name": "icon-calendar",
+ "tempChar": ""
+ },
+ {
+ "order": 81,
+ "id": 78,
+ "prevSize": 32,
+ "code": 58886,
+ "name": "icon-paint-bucket",
+ "tempChar": ""
+ },
{
"order": 1,
"id": 75,
"prevSize": 32,
"code": 123,
"name": "icon-pointer-left",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 3,
@@ -21,7 +61,7 @@
"prevSize": 32,
"code": 125,
"name": "icon-pointer-right",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 4,
@@ -29,7 +69,7 @@
"prevSize": 32,
"code": 80,
"name": "icon-person",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 5,
@@ -37,7 +77,7 @@
"prevSize": 32,
"code": 232,
"name": "icon-chain-links",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 6,
@@ -45,7 +85,7 @@
"prevSize": 32,
"code": 115,
"name": "icon-database-in-brackets",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 7,
@@ -53,7 +93,7 @@
"prevSize": 32,
"code": 114,
"name": "icon-refresh",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 8,
@@ -61,7 +101,7 @@
"prevSize": 32,
"code": 108,
"name": "icon-lock",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 9,
@@ -69,7 +109,7 @@
"prevSize": 32,
"code": 51,
"name": "icon-box-with-dashed-lines",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 10,
@@ -77,7 +117,7 @@
"prevSize": 32,
"code": 58880,
"name": "icon-box-with-arrow-cursor",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 11,
@@ -85,7 +125,7 @@
"prevSize": 32,
"code": 65,
"name": "icon-activity-mode",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 12,
@@ -93,7 +133,7 @@
"prevSize": 32,
"code": 97,
"name": "icon-activity",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 13,
@@ -101,7 +141,7 @@
"prevSize": 32,
"code": 33,
"name": "icon-alert-rect",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 14,
@@ -109,7 +149,7 @@
"prevSize": 32,
"code": 58883,
"name": "icon-alert-triangle",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 15,
@@ -117,7 +157,7 @@
"prevSize": 32,
"code": 238,
"name": "icon-arrow-double-down",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 16,
@@ -125,7 +165,7 @@
"prevSize": 32,
"code": 235,
"name": "icon-arrow-double-up",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 2,
@@ -133,7 +173,7 @@
"prevSize": 32,
"code": 118,
"name": "icon-arrow-down",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 19,
@@ -141,7 +181,7 @@
"prevSize": 32,
"code": 60,
"name": "icon-arrow-left",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 20,
@@ -149,7 +189,7 @@
"prevSize": 32,
"code": 62,
"name": "icon-arrow-right",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 21,
@@ -157,7 +197,7 @@
"prevSize": 32,
"code": 236,
"name": "icon-arrow-tall-down",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 22,
@@ -165,7 +205,7 @@
"prevSize": 32,
"code": 237,
"name": "icon-arrow-tall-up",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 23,
@@ -173,7 +213,7 @@
"prevSize": 32,
"code": 94,
"name": "icon-arrow-up",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 24,
@@ -181,7 +221,7 @@
"prevSize": 32,
"code": 73,
"name": "icon-arrows-out",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 25,
@@ -189,7 +229,7 @@
"prevSize": 32,
"code": 58893,
"name": "icon-arrows-right-left",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 33,
@@ -197,7 +237,7 @@
"prevSize": 32,
"code": 53,
"name": "icon-arrows-up-down",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 26,
@@ -205,7 +245,7 @@
"prevSize": 32,
"code": 42,
"name": "icon-asterisk",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 27,
@@ -213,7 +253,7 @@
"prevSize": 32,
"code": 72,
"name": "icon-autoflow-tabular",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 28,
@@ -221,7 +261,7 @@
"prevSize": 32,
"code": 224,
"name": "icon-box-round-corners",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 29,
@@ -229,7 +269,7 @@
"prevSize": 32,
"code": 50,
"name": "icon-check",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 30,
@@ -237,7 +277,7 @@
"prevSize": 32,
"code": 67,
"name": "icon-clock",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 31,
@@ -245,7 +285,7 @@
"prevSize": 32,
"code": 46,
"name": "icon-connectivity",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 32,
@@ -253,7 +293,7 @@
"prevSize": 32,
"code": 100,
"name": "icon-database-query",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 17,
@@ -261,7 +301,7 @@
"prevSize": 32,
"code": 68,
"name": "icon-database",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 35,
@@ -269,7 +309,7 @@
"prevSize": 32,
"code": 81,
"name": "icon-dictionary",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 36,
@@ -277,7 +317,7 @@
"prevSize": 32,
"code": 242,
"name": "icon-duplicate",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 37,
@@ -285,7 +325,7 @@
"prevSize": 32,
"code": 102,
"name": "icon-folder-new",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 38,
@@ -293,7 +333,7 @@
"prevSize": 32,
"code": 70,
"name": "icon-folder",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 39,
@@ -301,7 +341,7 @@
"prevSize": 32,
"code": 95,
"name": "icon-fullscreen-collapse",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 40,
@@ -309,7 +349,7 @@
"prevSize": 32,
"code": 122,
"name": "icon-fullscreen-expand",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 41,
@@ -317,7 +357,7 @@
"prevSize": 32,
"code": 71,
"name": "icon-gear",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 49,
@@ -325,7 +365,7 @@
"prevSize": 32,
"code": 227,
"name": "icon-image",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 42,
@@ -333,7 +373,7 @@
"prevSize": 32,
"code": 225,
"name": "icon-layers",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 43,
@@ -341,7 +381,7 @@
"prevSize": 32,
"code": 76,
"name": "icon-layout",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 44,
@@ -349,7 +389,7 @@
"prevSize": 32,
"code": 226,
"name": "icon-line-horz",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 75,
@@ -357,7 +397,7 @@
"prevSize": 32,
"code": 244,
"name": "icon-link",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 46,
@@ -365,7 +405,7 @@
"prevSize": 32,
"code": 88,
"name": "icon-magnify-in",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 47,
@@ -373,7 +413,7 @@
"prevSize": 32,
"code": 89,
"name": "icon-magnify-out",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 48,
@@ -381,7 +421,7 @@
"prevSize": 32,
"code": 77,
"name": "icon-magnify",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 34,
@@ -389,7 +429,7 @@
"prevSize": 32,
"code": 109,
"name": "icon-menu",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 50,
@@ -397,7 +437,7 @@
"prevSize": 32,
"code": 243,
"name": "icon-move",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 51,
@@ -405,7 +445,7 @@
"prevSize": 32,
"code": 121,
"name": "icon-new-window",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 52,
@@ -413,7 +453,7 @@
"prevSize": 32,
"code": 111,
"name": "icon-object",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 73,
@@ -421,7 +461,7 @@
"prevSize": 32,
"code": 63,
"name": "icon-object-unknown",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 53,
@@ -429,7 +469,7 @@
"prevSize": 32,
"code": 86,
"name": "icon-packet",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 54,
@@ -437,7 +477,7 @@
"prevSize": 32,
"code": 234,
"name": "icon-page",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 55,
@@ -445,7 +485,7 @@
"prevSize": 32,
"code": 241,
"name": "icon-pause",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 56,
@@ -453,7 +493,7 @@
"prevSize": 32,
"code": 112,
"name": "icon-pencil",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 65,
@@ -461,7 +501,7 @@
"prevSize": 32,
"code": 79,
"name": "icon-people",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 57,
@@ -469,7 +509,7 @@
"prevSize": 32,
"code": 239,
"name": "icon-play",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 58,
@@ -477,7 +517,7 @@
"prevSize": 32,
"code": 233,
"name": "icon-plot-resource",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 59,
@@ -485,7 +525,7 @@
"prevSize": 32,
"code": 43,
"name": "icon-plus",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 60,
@@ -493,7 +533,7 @@
"prevSize": 32,
"code": 45,
"name": "icon-minus",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 61,
@@ -501,7 +541,7 @@
"prevSize": 32,
"code": 54,
"name": "icon-sine",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 62,
@@ -509,7 +549,7 @@
"prevSize": 32,
"code": 228,
"name": "icon-T",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 63,
@@ -517,7 +557,7 @@
"prevSize": 32,
"code": 116,
"name": "icon-telemetry-panel",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 64,
@@ -525,7 +565,7 @@
"prevSize": 32,
"code": 84,
"name": "icon-telemetry",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 18,
@@ -533,7 +573,7 @@
"prevSize": 32,
"code": 246,
"name": "icon-thumbs-strip",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 67,
@@ -541,7 +581,7 @@
"prevSize": 32,
"code": 83,
"name": "icon-timeline",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 68,
@@ -549,7 +589,7 @@
"prevSize": 32,
"code": 245,
"name": "icon-timer",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 69,
@@ -557,7 +597,7 @@
"prevSize": 32,
"code": 90,
"name": "icon-trash",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 70,
@@ -565,7 +605,7 @@
"prevSize": 32,
"code": 229,
"name": "icon-two-parts-both",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 71,
@@ -573,7 +613,7 @@
"prevSize": 32,
"code": 231,
"name": "icon-two-parts-one-only",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 72,
@@ -581,7 +621,7 @@
"prevSize": 32,
"code": 120,
"name": "icon-x-heavy",
- "tempChar": ""
+ "tempChar": ""
},
{
"order": 66,
@@ -589,7 +629,7 @@
"prevSize": 32,
"code": 58946,
"name": "icon-x",
- "tempChar": ""
+ "tempChar": ""
}
],
"id": 2,
@@ -604,6 +644,182 @@
"height": 1024,
"prevSize": 32,
"icons": [
+ {
+ "id": 83,
+ "paths": [
+ "M1024 192c0 106.039-229.23 192-512 192s-512-85.961-512-192c0-106.039 229.23-192 512-192s512 85.961 512 192z",
+ "M512 512c-282.8 0-512-86-512-192v512c0 106 229.2 192 512 192s512-86 512-192v-512c0 106-229.2 192-512 192zM896 575v256c-36.6 15.6-79.8 28.8-128 39.4v-256c48.2-10.6 91.4-23.8 128-39.4zM256 614.4v256c-48.2-10.4-91.4-23.8-128-39.4v-256c36.6 15.6 79.8 28.8 128 39.4zM384 890v-256c41 4 83.8 6 128 6s87-2.2 128-6v256c-41 4-83.8 6-128 6s-87-2.2-128-6z"
+ ],
+ "attrs": [
+ {
+ "fill": "rgb(6,161,75)",
+ "opacity": 1
+ },
+ {
+ "fill": "rgb(6,161,75)",
+ "opacity": 1
+ }
+ ],
+ "isMulticolor": false,
+ "grid": 0,
+ "tags": [
+ "icon-datatable"
+ ],
+ "colorPermutations": {
+ "125525525516161751": [
+ 1,
+ 1
+ ]
+ }
+ },
+ {
+ "id": 82,
+ "paths": [
+ "M64 0c-35.2 0-64 28.8-64 64v192h448v-256h-384z",
+ "M1024 256v-192c0-35.2-28.8-64-64-64h-384v256h448z",
+ "M0 384v192c0 35.2 28.8 64 64 64h384v-256h-448z",
+ "M960 640c35.2 0 64-28.8 64-64v-192h-448v256h384z",
+ "M512 1024l-256-256h512z"
+ ],
+ "attrs": [
+ {
+ "fill": "rgb(6,161,75)",
+ "opacity": 1
+ },
+ {
+ "fill": "rgb(6,161,75)",
+ "opacity": 1
+ },
+ {
+ "fill": "rgb(6,161,75)",
+ "opacity": 1
+ },
+ {
+ "fill": "rgb(6,161,75)",
+ "opacity": 1
+ },
+ {
+ "fill": "rgb(6,161,75)",
+ "opacity": 1
+ }
+ ],
+ "isMulticolor": false,
+ "grid": 0,
+ "tags": [
+ "icon-tabular-scrolling"
+ ],
+ "colorPermutations": {
+ "125525525516161751": [
+ 1,
+ 1,
+ 1,
+ 1,
+ 1
+ ]
+ }
+ },
+ {
+ "id": 81,
+ "paths": [
+ "M0 64v192h448v-256h-384c-35.2 0-64 28.8-64 64z",
+ "M960 0h-384v256h448v-192c0-35.2-28.8-64-64-64z",
+ "M576 384h448v256h-448v-256z",
+ "M0 384h448v256h-448v-256z",
+ "M0 960c0 35.2 28.8 64 64 64h384v-256h-448v192z",
+ "M576 1024h384c35.2 0 64-28.8 64-64v-192h-448v256z"
+ ],
+ "attrs": [
+ {
+ "fill": "#000",
+ "opacity": 1
+ },
+ {
+ "fill": "#000",
+ "opacity": 1
+ },
+ {
+ "fill": "#000",
+ "opacity": 1
+ },
+ {
+ "fill": "#000",
+ "opacity": 1
+ },
+ {
+ "fill": "#000",
+ "opacity": 1
+ },
+ {
+ "fill": "#000",
+ "opacity": 1
+ }
+ ],
+ "isMulticolor": false,
+ "grid": 0,
+ "tags": [
+ "icon-tabular"
+ ],
+ "colorPermutations": {
+ "125525525516161751": [
+ 0,
+ 0,
+ 0,
+ 0,
+ 0,
+ 0
+ ]
+ }
+ },
+ {
+ "id": 80,
+ "paths": [
+ "M896 0h-768c-70.4 0-128 57.6-128 128v768c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v-768c0-70.4-57.6-128-128-128zM640 448h-256v-192h256v192zM384 512h256v192h-256v-192zM320 704h-256v-192h256v192zM320 256v192h-256v-192h256zM128 960c-17 0-33-6.6-45.2-18.8s-18.8-28.2-18.8-45.2v-128h256v192h-192zM384 960v-192h256v192h-256zM960 896c0 17-6.6 33-18.8 45.2s-28.2 18.8-45.2 18.8h-192v-192h256v128zM960 704h-256v-192h256v192zM960 448h-256v-192h256v192z"
+ ],
+ "attrs": [
+ {
+ "fill": "rgb(6,161,75)",
+ "opacity": 1
+ }
+ ],
+ "isMulticolor": false,
+ "grid": 0,
+ "tags": [
+ "icon-calendar"
+ ],
+ "colorPermutations": {
+ "125525525516161751": [
+ 1
+ ]
+ }
+ },
+ {
+ "id": 78,
+ "paths": [
+ "M896 640c0 0-130 188-128 256 2 70.6 57.4 128 128 128s126-57.4 128-128c2-68-128-256-128-256z",
+ "M449 129l0.2-64.8c0-35.4-28.4-64-63.8-64.2 0 0-0.2 0-0.2 0-35.2 0-63.8 28.6-64 63.8l-0.6 190.8-294 292.6c-50 50-12.4 215.2 112.4 340s290 162.4 340 112.4l417-423.6-447-447zM384 640c-70.6 0-128-57.4-128-128 0-47.4 25.8-89 64.4-111l-0.4 110.8c0 35.4 28.4 64 63.8 64.2 0 0 0.2 0 0.2 0 35.2 0 63.8-28.6 64-63.8l0.4-110.8c38 22.2 63.6 63.4 63.6 110.6 0 70.6-57.4 128-128 128z"
+ ],
+ "attrs": [
+ {
+ "fill": "rgb(6,161,75)",
+ "opacity": 1
+ },
+ {
+ "fill": "rgb(6,161,75)",
+ "opacity": 1
+ }
+ ],
+ "isMulticolor": false,
+ "grid": 0,
+ "tags": [
+ "icon-paint-bucket"
+ ],
+ "colorPermutations": {
+ "125525525516161751": [
+ 1,
+ 1
+ ]
+ }
+ },
{
"id": 75,
"paths": [
@@ -1767,7 +1983,24 @@
]
}
],
- "invisible": false
+ "invisible": false,
+ "colorThemes": [
+ [
+ [
+ 0,
+ 0,
+ 0,
+ 1
+ ],
+ [
+ 6,
+ 161,
+ 75,
+ 1
+ ]
+ ]
+ ],
+ "colorThemeIdx": 0
},
{
"selection": [
@@ -14510,7 +14743,8 @@
"selector": "class",
"classSelector": ".ui-symbol",
"showMetrics": true,
- "showMetadata": true
+ "showMetadata": true,
+ "embed": false
},
"imagePref": {
"prefix": "icon-",
diff --git a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.eot b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.eot
index 278460b5a8..2f4f938076 100755
Binary files a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.eot and b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.eot differ
diff --git a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.svg b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.svg
index 9c9d712d2d..d31a879fc3 100755
--- a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.svg
+++ b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.svg
@@ -6,78 +6,83 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.ttf b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.ttf
index b113a531a4..37af03fa79 100755
Binary files a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.ttf and b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.ttf differ
diff --git a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.woff b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.woff
index 5989698d98..c93e44215c 100755
Binary files a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.woff and b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.woff differ
diff --git a/platform/commonUI/general/res/sass/_constants.scss b/platform/commonUI/general/res/sass/_constants.scss
index 714338637f..22518172da 100644
--- a/platform/commonUI/general/res/sass/_constants.scss
+++ b/platform/commonUI/general/res/sass/_constants.scss
@@ -29,7 +29,7 @@ $interiorMargin: 5px;
$interiorMarginLg: $interiorMargin * 2;
$interiorMarginSm: 3px;
$basicCr: 2px;
-$controlCr: 2px;
+$controlCr: 3px;
$smallCr: 2px;
$badgeW: 35px;
@@ -84,6 +84,7 @@ $tabularColorBodyBg: darken($colorBodyBg, 10%);
$tabularColorBodyFg: lighten($tabularColorBodyBg, 40%);
$tabularColorHeaderBg: lighten($colorBodyBg, 10%);
$tabularColorHeaderFg: lighten($tabularColorHeaderBg, 40%);
+$tabularColorHeaderBorder: $colorBodyBg;
/************************** RATIOS */
$ltGamma: 20%;
@@ -115,9 +116,9 @@ $colorItemTreeIcon: $colorKey;
$colorItemTreeIconHover: lighten($colorItemTreeIcon, 20%);
$colorItemTreeVCHover: $colorAlt1;
// Tabular
-$tabularHeaderH: 18px;
+$tabularHeaderH: 22px; //18px
$tabularTdPadLR: $itemPadLR;
-$tabularTdPadTB: 2px;
+$tabularTdPadTB: 3px;
// Imagery
$imageMainControlBarH: 22px;
$imageThumbsD: 120px;
@@ -141,12 +142,11 @@ $reqSymbolM: $interiorMargin * 2;
$reqSymbolFontSize: 0.7em;
/************************** CONTROLS */
-$controlCr: $basicCr;
$controlDisabledOpacity: 0.3;
$formLabelW: 20%;
$formInputH: 22px;
$formRowCtrlsH: 14px;
-$menuLineH: 1.4rem;
+$menuLineH: 1.5rem;
$scrollbarTrackSize: 10px;
$scrollbarTrackColorBg: rgba(#000, 0.4);
$btnStdH: 25px;
diff --git a/platform/commonUI/general/res/sass/_global.scss b/platform/commonUI/general/res/sass/_global.scss
index 3c28d54c7d..94fe8e151c 100644
--- a/platform/commonUI/general/res/sass/_global.scss
+++ b/platform/commonUI/general/res/sass/_global.scss
@@ -50,6 +50,11 @@ input, textarea {
font-family: Helvetica, Arial, sans-serif;
}
+input[type="text"] {
+ vertical-align: baseline;
+ padding: 3px 5px !important;
+}
+
h1, h2, h3 {
margin: 0;
}
diff --git a/platform/commonUI/general/res/sass/_main.scss b/platform/commonUI/general/res/sass/_main.scss
index fd641fac09..8803074f63 100644
--- a/platform/commonUI/general/res/sass/_main.scss
+++ b/platform/commonUI/general/res/sass/_main.scss
@@ -38,7 +38,6 @@
@import "fixed-position";
@import "about";
@import "text";
-@import "badges";
@import "icons";
@import "limits";
@import "data-status";
@@ -54,7 +53,6 @@
@import "edit/editor";
@import "features/imagery";
@import "features/time-display";
-@import "forms/mixins";
@import "forms/elems";
@import "forms/validation";
@import "forms/text-input";
@@ -76,5 +74,7 @@
@import "properties";
@import "autoflow";
@import "iframe";
+@import "messages";
@import "initialization";
@import "hide-non-functional";
+@import "views";
diff --git a/platform/commonUI/general/res/sass/_messages.scss b/platform/commonUI/general/res/sass/_messages.scss
new file mode 100644
index 0000000000..db4de4c946
--- /dev/null
+++ b/platform/commonUI/general/res/sass/_messages.scss
@@ -0,0 +1,12 @@
+/* Styles for messages */
+
+.message {
+ &.block {
+ @include border-radius($basicCr);
+ padding: $interiorMarginLg;
+ }
+ &.error {
+ background-color: rgba($colorAlert,0.3);
+ color: lighten($colorAlert, 20%);
+ }
+}
\ No newline at end of file
diff --git a/platform/commonUI/general/res/sass/_mixins.scss b/platform/commonUI/general/res/sass/_mixins.scss
index cca5f30e16..4f2c1901af 100644
--- a/platform/commonUI/general/res/sass/_mixins.scss
+++ b/platform/commonUI/general/res/sass/_mixins.scss
@@ -260,6 +260,38 @@
@include text-shadow(rgba(black, $sVal) 0 3px 7px);
}
+/*********************************************** FORM ELEMENTS */
+@mixin input-base($bg: $colorBodyBg, $fg: $colorBodyFg) {
+ @include appearance(none);
+ @include border-radius($controlCr);
+ @include box-sizing(border-box);
+ @include box-shadow(inset rgba(black, 0.65) 0 1px 4px);
+ // background: lighten($bg, 20%);
+ background: rgba(#fff, 0.1);
+ border: none;
+ //border-bottom: 1px solid rgba(#fff, 0.1);
+ color: lighten($fg, 20%);
+ outline: none;
+ &.error {
+ background: rgba(red, 0.5);
+ }
+}
+
+@mixin nice-input($bg: $colorBodyBg, $fg: $colorBodyFg) {
+ @include input-base($bg, $fg);
+ padding: 0 $interiorMarginSm;
+}
+
+@mixin nice-textarea($bg: $colorBodyBg, $fg: $colorBodyFg) {
+ @include input-base($bg, $fg);
+ padding: $interiorMargin;
+}
+
+@mixin subdued-input($bg: $colorBodyBg, $fg: $colorBodyFg) {
+ @include nice-input($bg, $fg);
+ background: lighten($bg, 3%);
+ border-bottom: 1px solid lighten($bg, 10%);
+}
/*
@mixin invokeMenu($baseColor: $colorBodyFg) {
diff --git a/platform/commonUI/general/res/sass/_views.scss b/platform/commonUI/general/res/sass/_views.scss
new file mode 100644
index 0000000000..ef83e3c29b
--- /dev/null
+++ b/platform/commonUI/general/res/sass/_views.scss
@@ -0,0 +1,21 @@
+/* Styles for sub-dividing views generically */
+
+.l-view-section {
+ @include absPosDefault(0);
+ font-size: 0.8rem;
+ h2 {
+ color: #fff;
+ margin-bottom: $interiorMargin;
+ }
+ &.fixed {
+ font-size: 0.8em;
+ }
+ &.scrolling {
+ overflow: auto;
+ }
+ .controls,
+ label,
+ .inline-block {
+ display: inline-block;
+ }
+}
\ No newline at end of file
diff --git a/platform/commonUI/general/res/sass/forms/_elems.scss b/platform/commonUI/general/res/sass/forms/_elems.scss
index a47cdc2484..9a2adab2e3 100644
--- a/platform/commonUI/general/res/sass/forms/_elems.scss
+++ b/platform/commonUI/general/res/sass/forms/_elems.scss
@@ -86,13 +86,6 @@
}
}
- input[type="text"] {
- height: $formInputH;
- line-height: $formInputH;
- margin-top: -4px;
- vertical-align: baseline;
- }
-
.l-med input[type="text"] {
width: 200px;
}
diff --git a/platform/commonUI/general/res/sass/forms/_mixins.scss b/platform/commonUI/general/res/sass/forms/_mixins.scss
index fae98a588f..e80999174c 100644
--- a/platform/commonUI/general/res/sass/forms/_mixins.scss
+++ b/platform/commonUI/general/res/sass/forms/_mixins.scss
@@ -23,11 +23,11 @@
@include appearance(none);
@include border-radius($controlCr);
@include box-sizing(border-box);
- @include box-shadow(inset rgba(black, 0.5) 0 1px 5px);
+ @include box-shadow(inset rgba(black, 0.65) 0 1px 4px);
// background: lighten($bg, 20%);
background: rgba(#fff, 0.1);
border: none;
- border-bottom: 1px solid rgba(#fff, 0.1);
+ //border-bottom: 1px solid rgba(#fff, 0.1);
color: lighten($fg, 20%);
outline: none;
&.error {
diff --git a/platform/commonUI/general/res/sass/helpers/_bubbles.scss b/platform/commonUI/general/res/sass/helpers/_bubbles.scss
index ef580f853a..166f92a883 100644
--- a/platform/commonUI/general/res/sass/helpers/_bubbles.scss
+++ b/platform/commonUI/general/res/sass/helpers/_bubbles.scss
@@ -48,19 +48,15 @@
width: 100%;
tr {
td {
- //max-width: 150px;
padding: 2px 0;
vertical-align: top;
- //white-space: nowrap;
- //overflow: hidden;
- //text-overflow: ellipsis;
&.label {
padding-right: $interiorMargin * 2;
white-space: nowrap;
}
&.value {
- white-space: nowrap;
- //width: 90%;
+ //word-wrap: break-word; // Doesn't work in
?
+ word-break: break-all;
}
&.align-wrap {
white-space: normal;
@@ -135,7 +131,9 @@
z-index: 2;
}
&.arw-up .arw.arw-down,
- &.arw-down .arw.arw-up { display: none; }
+ &.arw-down .arw.arw-up {
+ display: none;
+ }
}
//************************************************* LOOK AND FEEL
@@ -148,6 +146,7 @@
@include triangle('down', $bubbleArwSize, 1.5, $colorThumbsBubbleBg);
}
}
+
.s-infobubble {
$emFg: darken($colorInfoBubbleFg, 20%);
@include border-radius($basicCr);
@@ -159,18 +158,31 @@
color: $emFg;
font-weight: bold;
}
- tr {
- td {
- border-top: 1px solid darken($colorInfoBubbleBg, 10%);
- font-size: 0.9em;
- }
- &:first-child td {
- border-top: none;
+ table {
+ tr {
+ td {
+ border: none;
+ border-top: 1px solid darken($colorInfoBubbleBg, 10%) !important;
+ font-size: 0.9em;
+ }
+
+ &:first-child td {
+ border-top: none !important;
+ }
}
}
+ &:first-child td {
+ border-top: none;
+ }
+
+ .label {
+ color: lighten($emFg, 30%);
+ }
+
.value {
color: $emFg;
}
+
}
.s-thumbsbubble {
diff --git a/platform/commonUI/general/res/sass/helpers/_wait-spinner.scss b/platform/commonUI/general/res/sass/helpers/_wait-spinner.scss
index fafae5e9ea..f80c1f1971 100644
--- a/platform/commonUI/general/res/sass/helpers/_wait-spinner.scss
+++ b/platform/commonUI/general/res/sass/helpers/_wait-spinner.scss
@@ -50,6 +50,12 @@
margin-top: $d / -1;
margin-left: $d / -1;
z-index: 2;
+ &.inline {
+ display: inline-block !important;
+ margin-right: $interiorMargin;
+ position: relative !important;
+ vertical-align: middle;
+ }
}
.l-wait-spinner-holder {
@@ -80,4 +86,14 @@
margin: 0 !important;
padding: 0 !important;
top: 2px; left: 0;
+}
+
+.wait-spinner.sm {
+ $d: 13px;
+ @include wait-spinner(0.25em, $colorKey);
+ height: $d; width: $d;
+ margin-left: 0 !important;
+ margin-top: 0 !important;
+ padding: 0 !important;
+ top: 0; left: 0;
}
\ No newline at end of file
diff --git a/platform/commonUI/general/res/sass/lists/_tabular.scss b/platform/commonUI/general/res/sass/lists/_tabular.scss
index 0b449baccf..0621cad46b 100644
--- a/platform/commonUI/general/res/sass/lists/_tabular.scss
+++ b/platform/commonUI/general/res/sass/lists/_tabular.scss
@@ -24,13 +24,14 @@
height: 100%;
}
-.tabular {
+.tabular,
+table {
@include box-sizing(border-box);
border-spacing: 0;
border-collapse: collapse;
color: #fff;
display: table;
- font-size: 0.75em;
+ font-size: 0.75rem;
position: relative;
//height: 100%; MOVED
width: 100%;
@@ -41,19 +42,7 @@
//table-layout: fixed; MOVED
}
thead, .thead {
- //width: calc(100% - 10px); MOVED
- tr, .tr {
- height: $tabularHeaderH;
- }
- &:before {
- content: "";
- display: block;
- z-index: 0;
- position: absolute;
- width: 100%;
- height: $tabularHeaderH;
- background: rgba(#fff, 0.15);
- }
+ border-bottom: 1px solid $tabularColorHeaderBorder;
}
tbody, .tbody {
//@include absPosDefault(0); MOVED
@@ -72,38 +61,49 @@
&:first-child .td {
border-top: none;
}
+ &.group-header {
+ td, .td {
+ $d: 5%;
+ background-color: darken($tabularColorHeaderBg, $d);
+ color: darken($tabularColorHeaderFg, $d);
+ }
+ }
th, .th, td, .td {
display: table-cell;
}
th, .th {
- border: none;
- border-left: 1px solid $tabularColorBorder;
+ background-color: $tabularColorHeaderBg;
+ border-left: 1px solid $tabularColorHeaderBorder;
color: $tabularColorHeaderFg;
- padding: 0 $tabularTdPadLR;
+ padding: $tabularTdPadLR $tabularTdPadLR;
white-space: nowrap;
vertical-align: middle; // This is crucial to hiding f**king 4px height injected by browser by default
&:first-child {
border-left: none;
}
&.sort {
- .icon-sorting:before {
- display: inline-block;
+ &.sort:after {
+ color: $colorIconLink;
font-family: symbolsfont;
- margin-left: 5px;
+ font-size: 8px;
+ content: "\ed";
+ display: inline-block;
+ margin-left: $interiorMarginSm;
}
- &.asc .icon-sorting:before {
- content: '0';
- }
- &.desc .icon-sorting:before {
- content: '1';
+ &.sort.desc:after {
+ content: "\ec";
}
}
+ &.sortable {
+ cursor: pointer;
+ }
}
td, .td {
- border-top: 1px solid $tabularColorBorder;
- min-width: 110px;
+ border-bottom: 1px solid $tabularColorBorder;
+ min-width: 20px;
color: $colorTelemFresh;
padding: $tabularTdPadTB $tabularTdPadLR;
+ word-wrap: break-word;
vertical-align: top;
&.numeric {
text-align: right;
@@ -119,9 +119,20 @@
}
}
&.filterable {
+ thead, .thead {
+ tr.s-filters, .tr.s-filters {
+ th, .th {
+ //border-left: none;
+ }
+ }
+ }
tbody, .tbody {
top: $tabularHeaderH * 2;
}
+ input[type="text"] {
+ @include box-sizing(border-box);
+ width: 100%; //50px;
+ }
}
&.fixed-header {
@@ -133,6 +144,15 @@
}
thead, .thead {
width: calc(100% - 10px);
+ &:before {
+ content: "";
+ display: block;
+ z-index: 0;
+ position: absolute;
+ width: 100%;
+ height: $tabularHeaderH;
+ background: rgba(#fff, 0.15);
+ }
}
tbody, .tbody {
@include absPosDefault(0);
diff --git a/platform/commonUI/general/res/templates/label.html b/platform/commonUI/general/res/templates/label.html
index bfa7bd56ff..7ca73bb026 100644
--- a/platform/commonUI/general/res/templates/label.html
+++ b/platform/commonUI/general/res/templates/label.html
@@ -22,7 +22,13 @@
{{type.getGlyph()}}
- !
+
+
+
+
+ {{model.name}}
- {{model.name}}
diff --git a/platform/commonUI/general/res/templates/tree-node.html b/platform/commonUI/general/res/templates/tree-node.html
index 9b094fe81d..54aef8edbc 100644
--- a/platform/commonUI/general/res/templates/tree-node.html
+++ b/platform/commonUI/general/res/templates/tree-node.html
@@ -21,8 +21,7 @@
-->
-
+ class="tree-item-subtree"
+ ng-show="toggle.isActive()"
+ ng-if="model.composition !== undefined"
+ >
0 && !assigned) {
- current = defaultState;
- assigned = true;
- }
- return current;
- },
- /**
- * Begin moving the splitter; this will note the splitter's
- * current position, which is necessary for correct
- * interpretation of deltas provided by mct-drag.
- */
- startMove: function () {
- start = current;
- },
- /**
- * Move the splitter a number of pixels to the right
- * (negative numbers move the splitter to the left.)
- * This movement is relative to the position of the
- * splitter when startMove was last invoked.
- * @param {number} delta number of pixels to move
- */
- move: function (delta, minimum, maximum) {
- // Ensure defaults for minimum/maximum
- maximum = isNaN(maximum) ? DEFAULT_MAXIMUM : maximum;
- minimum = isNaN(minimum) ? DEFAULT_MINIMUM : minimum;
-
- // Update current splitter state
- current = Math.min(
- maximum,
- Math.max(minimum, start + delta)
- );
-
- //console.log(current + "; minimum: " + minimum + "; max: " + maximum);
- }
- };
+ this.current = 200;
+ this.start = 200;
+ this.assigned = false;
}
+ /**
+ * Get the current position of the splitter, in pixels
+ * from the left edge.
+ * @returns {number} position of the splitter, in pixels
+ */
+ SplitPaneController.prototype.state = function (defaultState) {
+ // Set the state to the desired default, if we don't have a
+ // "real" current state yet.
+ if (arguments.length > 0 && !this.assigned) {
+ this.current = defaultState;
+ this.assigned = true;
+ }
+ return this.current;
+ };
+
+ /**
+ * Begin moving the splitter; this will note the splitter's
+ * current position, which is necessary for correct
+ * interpretation of deltas provided by mct-drag.
+ */
+ SplitPaneController.prototype.startMove = function () {
+ this.start = this.current;
+ };
+
+ /**
+ * Move the splitter a number of pixels to the right
+ * (negative numbers move the splitter to the left.)
+ * This movement is relative to the position of the
+ * splitter when startMove was last invoked.
+ * @param {number} delta number of pixels to move
+ */
+ SplitPaneController.prototype.move = function (delta, minimum, maximum) {
+ // Ensure defaults for minimum/maximum
+ maximum = isNaN(maximum) ? DEFAULT_MAXIMUM : maximum;
+ minimum = isNaN(minimum) ? DEFAULT_MINIMUM : minimum;
+
+ // Update current splitter state
+ this.current = Math.min(
+ maximum,
+ Math.max(minimum, this.start + delta)
+ );
+ };
+
return SplitPaneController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/general/src/controllers/ToggleController.js b/platform/commonUI/general/src/controllers/ToggleController.js
index 0d3bd664ca..9d7d493f15 100644
--- a/platform/commonUI/general/src/controllers/ToggleController.js
+++ b/platform/commonUI/general/src/controllers/ToggleController.js
@@ -30,37 +30,37 @@ define(
* A ToggleController is used to activate/deactivate things.
* A common usage is for "twistie"
*
+ * @memberof platform/commonUI/general
* @constructor
*/
function ToggleController() {
- var state = false;
-
- return {
- /**
- * Get the current state of the toggle.
- * @return {boolean} true if active
- */
- isActive: function () {
- return state;
- },
- /**
- * Set a new state for the toggle.
- * @return {boolean} true to activate
- */
- setState: function (newState) {
- state = newState;
- },
- /**
- * Toggle the current state; activate if it is inactive,
- * deactivate if it is active.
- */
- toggle: function () {
- state = !state;
- }
- };
-
+ this.state = false;
}
+ /**
+ * Get the current state of the toggle.
+ * @return {boolean} true if active
+ */
+ ToggleController.prototype.isActive = function () {
+ return this.state;
+ };
+
+ /**
+ * Set a new state for the toggle.
+ * @return {boolean} true to activate
+ */
+ ToggleController.prototype.setState = function (newState) {
+ this.state = newState;
+ };
+
+ /**
+ * Toggle the current state; activate if it is inactive,
+ * deactivate if it is active.
+ */
+ ToggleController.prototype.toggle = function () {
+ this.state = !this.state;
+ };
+
return ToggleController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/general/src/controllers/TreeNodeController.js b/platform/commonUI/general/src/controllers/TreeNodeController.js
index 8d6becdfad..96f89ee2e0 100644
--- a/platform/commonUI/general/src/controllers/TreeNodeController.js
+++ b/platform/commonUI/general/src/controllers/TreeNodeController.js
@@ -48,10 +48,12 @@ define(
* node expansion when this tree node's _subtree_ will contain
* the navigated object (recursively, this becomes an
* expand-to-show-navigated-object behavior.)
+ * @memberof platform/commonUI/general
* @constructor
*/
function TreeNodeController($scope, $timeout, agentService) {
- var selectedObject = ($scope.ngModel || {}).selectedObject,
+ var self = this,
+ selectedObject = ($scope.ngModel || {}).selectedObject,
isSelected = false,
hasBeenExpanded = false;
@@ -75,32 +77,6 @@ define(
((navPath[index] === nodePath[index]) &&
checkPath(nodePath, navPath, index + 1));
}
-
- // Track that a node has been expanded, either by the
- // user or automatically to show a selection.
- function trackExpansion() {
- if (!hasBeenExpanded) {
- // Run on a timeout; if a lot of expansion needs to
- // occur (e.g. if the selection is several nodes deep) we
- // want this to be spread across multiple digest cycles.
- $timeout(function () { hasBeenExpanded = true; }, 0);
- }
- }
-
- // Sets the selected object in the tree, to be the
- // currently represented object. If the user is on phone
- // and in portrait mode, than, hide the tree menu
- function setObject(ngModel, domainObject) {
- ngModel.selectedObject = domainObject;
- if (agentService.getOrientation() === "portrait" &&
- agentService.isPhone(navigator.userAgent)) {
- $scope.$emit('select-obj');
- }
- }
-
- function checkMobile() {
- return agentService.isMobile(navigator.userAgent);
- }
// Consider the currently-navigated object and update
// parameters which support display.
@@ -116,7 +92,7 @@ define(
// Deselect; we will reselect below, iff we are
// exactly at the end of the path.
- isSelected = false;
+ self.isSelectedFlag = false;
// Expand if necessary (if the navigated object will
// be in this node's subtree)
@@ -135,12 +111,12 @@ define(
// at the end of the path, highlight;
// otherwise, expand.
if (nodePath.length === navPath.length) {
- isSelected = true;
+ self.isSelectedFlag = true;
} else { // node path is shorter: Expand!
if ($scope.toggle) {
$scope.toggle.setState(true);
}
- trackExpansion();
+ self.trackExpansion();
}
}
@@ -153,43 +129,69 @@ define(
selectedObject = object;
checkSelection();
}
-
+
+ this.isSelectedFlag = false;
+ this.hasBeenExpandedFlag = false;
+ this.$timeout = $timeout;
+ this.agentService = agentService;
+ this.$scope = $scope;
+
// Listen for changes which will effect display parameters
$scope.$watch("ngModel.selectedObject", setSelection);
$scope.$watch("domainObject", checkSelection);
-
- return {
- /**
- * This method should be called when a node is expanded
- * to record that this has occurred, to support one-time
- * lazy loading of the node's subtree.
- */
- trackExpansion: trackExpansion,
-
- checkMobile: checkMobile,
-
- setObject: setObject,
-
- /**
- * Check if this not has ever been expanded.
- * @returns true if it has been expanded
- */
- hasBeenExpanded: function () {
- return hasBeenExpanded;
- },
- /**
- * Check whether or not the domain object represented by
- * this tree node should be highlighted.
- * An object will be highlighted if it matches
- * ngModel.selectedObject
- * @returns true if this should be highlighted
- */
- isSelected: function () {
- return isSelected;
- }
- };
}
+ /**
+ * This method should be called when a node is expanded
+ * to record that this has occurred, to support one-time
+ * lazy loading of the node's subtree.
+ */
+ TreeNodeController.prototype.trackExpansion = function () {
+ var self = this;
+ if (!self.hasBeenExpanded()) {
+ // Run on a timeout; if a lot of expansion needs to
+ // occur (e.g. if the selection is several nodes deep) we
+ // want this to be spread across multiple digest cycles.
+ self.$timeout(function () {
+ self.hasBeenExpandedFlag = true;
+ }, 0);
+ }
+ };
+
+ /**
+ * Check if this not has ever been expanded.
+ * @returns true if it has been expanded
+ */
+ TreeNodeController.prototype.hasBeenExpanded = function () {
+ return this.hasBeenExpandedFlag;
+ };
+
+ /**
+ * Check whether or not the domain object represented by
+ * this tree node should be highlighted.
+ * An object will be highlighted if it matches
+ * ngModel.selectedObject
+ * @returns true if this should be highlighted
+ */
+ TreeNodeController.prototype.isSelected = function () {
+ return this.isSelectedFlag;
+ };
+
+ // Sets the selected object in the tree, to be the
+ // currently represented object. If the user is on phone
+ // and in portrait mode, than, hide the tree menu
+ TreeNodeController.prototype.setObject = function (ngModel, domainObject) {
+ ngModel.selectedObject = domainObject;
+ if (this.agentService.getOrientation() === "portrait" &&
+ this.agentService.isPhone(navigator.userAgent)) {
+ this.$scope.$emit('select-obj');
+ }
+ };
+
+ TreeNodeController.prototype.checkMobile = function () {
+ return this.agentService.isMobile(navigator.userAgent);
+ };
+
return TreeNodeController;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/general/src/controllers/ViewSwitcherController.js b/platform/commonUI/general/src/controllers/ViewSwitcherController.js
index 69674013d5..a3ab2e7bc4 100644
--- a/platform/commonUI/general/src/controllers/ViewSwitcherController.js
+++ b/platform/commonUI/general/src/controllers/ViewSwitcherController.js
@@ -32,6 +32,7 @@ define(
/**
* Controller for the view switcher; populates and maintains a list
* of applicable views for a represented domain object.
+ * @memberof platform/commonUI/general
* @constructor
*/
function ViewSwitcherController($scope, $timeout) {
@@ -71,3 +72,4 @@ define(
return ViewSwitcherController;
}
);
+
diff --git a/platform/commonUI/general/src/directives/MCTContainer.js b/platform/commonUI/general/src/directives/MCTContainer.js
index 00b7b2b21a..f65cf0803d 100644
--- a/platform/commonUI/general/src/directives/MCTContainer.js
+++ b/platform/commonUI/general/src/directives/MCTContainer.js
@@ -39,6 +39,7 @@ define(
* plain string attribute, instead of as an Angular
* expression.
*
+ * @memberof platform/commonUI/general
* @constructor
*/
function MCTContainer(containers) {
@@ -96,4 +97,4 @@ define(
return MCTContainer;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/general/src/directives/MCTDrag.js b/platform/commonUI/general/src/directives/MCTDrag.js
index f12aae5c5f..7bccccdf28 100644
--- a/platform/commonUI/general/src/directives/MCTDrag.js
+++ b/platform/commonUI/general/src/directives/MCTDrag.js
@@ -44,6 +44,7 @@ define(
* and vertical pixel offset of the current mouse position
* relative to the mouse position where dragging began.
*
+ * @memberof platform/commonUI/general
* @constructor
*
*/
@@ -157,3 +158,4 @@ define(
return MCTDrag;
}
);
+
diff --git a/platform/commonUI/general/src/directives/MCTResize.js b/platform/commonUI/general/src/directives/MCTResize.js
index 62ae977271..c78039627a 100644
--- a/platform/commonUI/general/src/directives/MCTResize.js
+++ b/platform/commonUI/general/src/directives/MCTResize.js
@@ -49,6 +49,7 @@ define(
* This is an Angular expression, and it will be re-evaluated after
* each interval.
*
+ * @memberof platform/commonUI/general
* @constructor
*
*/
@@ -111,4 +112,4 @@ define(
return MCTResize;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/general/src/directives/MCTScroll.js b/platform/commonUI/general/src/directives/MCTScroll.js
index 3df79f23b2..6b9d480c66 100644
--- a/platform/commonUI/general/src/directives/MCTScroll.js
+++ b/platform/commonUI/general/src/directives/MCTScroll.js
@@ -37,6 +37,7 @@ define(
* This is exposed as two directives in `bundle.json`; the difference
* is handled purely by parameterization.
*
+ * @memberof platform/commonUI/general
* @constructor
* @param $parse Angular's $parse
* @param {string} property property to manage within the HTML element
@@ -80,4 +81,4 @@ define(
return MCTScroll;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/general/src/directives/MCTSplitPane.js b/platform/commonUI/general/src/directives/MCTSplitPane.js
index 8d95ff2b69..688689d79f 100644
--- a/platform/commonUI/general/src/directives/MCTSplitPane.js
+++ b/platform/commonUI/general/src/directives/MCTSplitPane.js
@@ -91,6 +91,7 @@ define(
* etc. can be set on that element to control the splitter's
* allowable positions.
*
+ * @memberof platform/commonUI/general
* @constructor
*/
function MCTSplitPane($parse, $log) {
@@ -213,3 +214,4 @@ define(
}
);
+
diff --git a/platform/commonUI/general/src/directives/MCTSplitter.js b/platform/commonUI/general/src/directives/MCTSplitter.js
index 0494830057..5216c69358 100644
--- a/platform/commonUI/general/src/directives/MCTSplitter.js
+++ b/platform/commonUI/general/src/directives/MCTSplitter.js
@@ -39,6 +39,7 @@ define(
/**
* Implements `mct-splitter` directive.
+ * @memberof platform/commonUI/general
* @constructor
*/
function MCTSplitter() {
@@ -88,3 +89,4 @@ define(
}
);
+
diff --git a/platform/commonUI/general/src/services/UrlService.js b/platform/commonUI/general/src/services/UrlService.js
index edb5f6235b..5d57b03ca0 100644
--- a/platform/commonUI/general/src/services/UrlService.js
+++ b/platform/commonUI/general/src/services/UrlService.js
@@ -32,62 +32,56 @@ define(
/**
* The url service handles calls for url paths
* using domain objects.
+ * @constructor
+ * @memberof platform/commonUI/general
*/
function UrlService($location) {
- // Returns the url for the mode wanted
- // and the domainObject passed in. A path
- // is returned. The view is defaulted to
- // the current location's (current object's)
- // view set.
- function urlForLocation(mode, domainObject) {
- var context = domainObject &&
- domainObject.getCapability('context'),
- objectPath = context ? context.getPath() : [],
- ids = objectPath.map(function (domainObject) {
- return domainObject.getId();
- }),
- // Parses the path together. Starts with the
- // default index.html file, then the mode passed
- // into the service, followed by ids in the url
- // joined by '/', and lastly the view path from
- // the current location
- path = mode + "/" + ids.slice(1).join("/");
- return path;
- }
-
- // Uses the Url for the current location
- // from the urlForLocation function and
- // includes the view and the index path
- function urlForNewTab(mode, domainObject) {
- var viewPath = "?view=" + $location.search().view,
- newTabPath =
- "index.html#" + urlForLocation(mode, domainObject) + viewPath;
- return newTabPath;
- }
-
- return {
- /**
- * Returns the Url path for a specific domain object
- * without the index.html path and the view path
- * @param {value} value of the browse or edit mode
- * for the path
- * @param {DomainObject} value of the domain object
- * to get the path of
- */
- urlForNewTab: urlForNewTab,
- /**
- * Returns the Url path for a specific domain object
- * including the index.html path and the view path
- * allowing a new tab to hold the correct characteristics
- * @param {value} value of the browse or edit mode
- * for the path
- * @param {DomainObject} value of the domain object
- * to get the path of
- */
- urlForLocation: urlForLocation
- };
+ this.$location = $location;
}
+ /**
+ * Returns the Url path for a specific domain object
+ * without the index.html path and the view path
+ * @param {string} mode value of browse or edit mode
+ * for the path
+ * @param {DomainObject} value of the domain object
+ * to get the path of
+ * @returns {string} URL for the domain object
+ */
+ UrlService.prototype.urlForLocation = function (mode, domainObject) {
+ var context = domainObject &&
+ domainObject.getCapability('context'),
+ objectPath = context ? context.getPath() : [],
+ ids = objectPath.map(function (domainObject) {
+ return domainObject.getId();
+ });
+
+ // Parses the path together. Starts with the
+ // default index.html file, then the mode passed
+ // into the service, followed by ids in the url
+ // joined by '/', and lastly the view path from
+ // the current location
+ return mode + "/" + ids.slice(1).join("/");
+ };
+
+ /**
+ * Returns the Url path for a specific domain object
+ * including the index.html path and the view path
+ * allowing a new tab to hold the correct characteristics
+ * @param {string} mode value of browse or edit mode
+ * for the path
+ * @param {DomainObject} value of the domain object
+ * to get the path of
+ * @returns {string} URL for the domain object
+ */
+ UrlService.prototype.urlForNewTab = function (mode, domainObject) {
+ var viewPath = "?view=" + this.$location.search().view,
+ newTabPath =
+ "index.html#" + this.urlForLocation(mode, domainObject) +
+ viewPath;
+ return newTabPath;
+ };
+
return UrlService;
}
-);
\ No newline at end of file
+);
diff --git a/platform/commonUI/inspect/src/InfoConstants.js b/platform/commonUI/inspect/src/InfoConstants.js
index 5e43a1b618..4927de870f 100644
--- a/platform/commonUI/inspect/src/InfoConstants.js
+++ b/platform/commonUI/inspect/src/InfoConstants.js
@@ -20,6 +20,13 @@
* at runtime from the About dialog for additional information.
*****************************************************************************/
/*global define*/
+
+/**
+ * This bundle provides support for object inspection (specifically, metadata
+ * show in bubbles on hover.)
+ * @namespace platform/commonUI/inspect
+ */
+
define({
BUBBLE_TEMPLATE: " (winDim[0] - bubbleSpaceLR),
- goUp = position[1] > (winDim[1] / 2),
- bubble;
+ /**
+ * Display an info bubble at the specified location.
+ * @param {string} templateKey template to place in bubble
+ * @param {string} title title for the bubble
+ * @param {*} content content to pass to the template, via
+ * `ng-model`
+ * @param {number[]} x,y position of the info bubble, in
+ * pixel coordinates.
+ * @returns {Function} a function that may be invoked to
+ * dismiss the info bubble
+ */
+ InfoService.prototype.display = function (templateKey, title, content, position) {
+ var $compile = this.$compile,
+ $document = this.$document,
+ $window = this.$window,
+ $rootScope = this.$rootScope,
+ body = $document.find('body'),
+ scope = $rootScope.$new(),
+ winDim = [$window.innerWidth, $window.innerHeight],
+ bubbleSpaceLR = InfoConstants.BUBBLE_MARGIN_LR + InfoConstants.BUBBLE_MAX_WIDTH,
+ goLeft = position[0] > (winDim[0] - bubbleSpaceLR),
+ goUp = position[1] > (winDim[1] / 2),
+ bubble;
+
+ // Pass model & container parameters into the scope
+ scope.bubbleModel = content;
+ scope.bubbleTemplate = templateKey;
+ scope.bubbleLayout = (goUp ? 'arw-btm' : 'arw-top') + ' ' +
+ (goLeft ? 'arw-right' : 'arw-left');
+ scope.bubbleTitle = title;
- // Pass model & container parameters into the scope
- scope.bubbleModel = content;
- scope.bubbleTemplate = templateKey;
- scope.bubbleLayout = (goUp ? 'arw-btm' : 'arw-top') + ' ' +
- (goLeft ? 'arw-right' : 'arw-left');
- scope.bubbleTitle = title;
+ // Create the context menu
+ bubble = $compile(BUBBLE_TEMPLATE)(scope);
- // Create the context menu
- bubble = $compile(BUBBLE_TEMPLATE)(scope);
-
- // Position the bubble:
- // Phone: On a phone the bubble is specifically positioned
- // so that it takes up the width of the screen.
- // Tablet/Desktop: On other devices with larger screens, the
- // info bubble positioned as normal (with triangle pointing
- // to where clicked or pressed)
- bubble.css('position', 'absolute');
- if (agentService.isPhone(navigator.userAgent)) {
- bubble.css('right', '0px');
- bubble.css('left', '0px');
- bubble.css('top', 'auto');
- bubble.css('bottom', '25px');
+ // Position the bubble
+ bubble.css('position', 'absolute');
+ if (this.agentService.isPhone(navigator.userAgent)) {
+ bubble.css('right', '0px');
+ bubble.css('left', '0px');
+ bubble.css('top', 'auto');
+ bubble.css('bottom', '25px');
+ } else {
+ if (goLeft) {
+ bubble.css('right', (winDim[0] - position[0] + OFFSET[0]) + 'px');
} else {
- if (goLeft) {
- bubble.css('right', (winDim[0] - position[0] + OFFSET[0]) + 'px');
- } else {
- bubble.css('left', position[0] + OFFSET[0] + 'px');
- }
- if (goUp) {
- bubble.css('bottom', (winDim[1] - position[1] + OFFSET[1]) + 'px');
- } else {
- bubble.css('top', position[1] + OFFSET[1] + 'px');
- }
+ bubble.css('left', position[0] + OFFSET[0] + 'px');
+ }
+ if (goUp) {
+ bubble.css('bottom', (winDim[1] - position[1] + OFFSET[1]) + 'px');
+ } else {
+ bubble.css('top', position[1] + OFFSET[1] + 'px');
}
- // Add the menu to the body
- body.append(bubble);
-
- // Return a function to dismiss the bubble
- return function () { bubble.remove(); };
}
- return {
- /**
- * Display an info bubble at the specified location.
- * @param {string} templateKey template to place in bubble
- * @param {string} title title for the bubble
- * @param {*} content content to pass to the template, via
- * `ng-model`
- * @param {number[]} x,y position of the info bubble, in
- * pixel coordinates.
- * @returns {Function} a function that may be invoked to
- * dismiss the info bubble
- */
- display: display
- };
- }
+ // Add the menu to the body
+ body.append(bubble);
+
+ // Return a function to dismiss the bubble
+ return function () { bubble.remove(); };
+ };
return InfoService;
}
);
+
diff --git a/platform/containment/src/CapabilityTable.js b/platform/containment/src/CapabilityTable.js
index db14c0f20f..db89f9e68f 100644
--- a/platform/containment/src/CapabilityTable.js
+++ b/platform/containment/src/CapabilityTable.js
@@ -32,9 +32,11 @@ define(
* which capabilities. This supports composition policy (rules
* for which objects can contain which other objects) which
* sometimes is determined based on the presence of capabilities.
+ * @constructor
+ * @memberof platform/containment
*/
function CapabilityTable(typeService, capabilityService) {
- var table = {};
+ var self = this;
// Build an initial model for a type
function buildModel(type) {
@@ -52,25 +54,26 @@ define(
function addToTable(type) {
var typeKey = type.getKey();
Object.keys(getCapabilities(type)).forEach(function (key) {
- table[key] = table[key] || {};
- table[key][typeKey] = true;
+ self.table[key] = self.table[key] || {};
+ self.table[key][typeKey] = true;
});
}
// Build the table
+ this.table = {};
(typeService.listTypes() || []).forEach(addToTable);
-
- return {
- /**
- * Check if a type is expected to expose a specific
- * capability.
- */
- hasCapability: function (typeKey, capabilityKey) {
- return (table[capabilityKey] || {})[typeKey];
- }
- };
}
+ /**
+ * Check if a type is expected to expose a specific capability.
+ * @param {string} typeKey the type identifier
+ * @param {string} capabilityKey the capability identifier
+ * @returns {boolean} true if expected to be exposed
+ */
+ CapabilityTable.prototype.hasCapability = function (typeKey, capabilityKey) {
+ return (this.table[capabilityKey] || {})[typeKey];
+ };
+
return CapabilityTable;
}
-);
\ No newline at end of file
+);
diff --git a/platform/containment/src/ComposeActionPolicy.js b/platform/containment/src/ComposeActionPolicy.js
index 6d3952b763..3468cd3107 100644
--- a/platform/containment/src/ComposeActionPolicy.js
+++ b/platform/containment/src/ComposeActionPolicy.js
@@ -34,47 +34,51 @@ define(
* since it's delegated to a different policy category.
* To avoid a circular dependency, the service is obtained via
* Angular's `$injector`.
+ * @constructor
+ * @memberof platform/containment
+ * @implements {Policy.}
*/
function ComposeActionPolicy($injector) {
- var policyService;
-
- function allowComposition(containerObject, selectedObject) {
- // Get the object types involved in the compose action
- var containerType = containerObject &&
- containerObject.getCapability('type'),
- selectedType = selectedObject &&
- selectedObject.getCapability('type');
-
- // Get a reference to the policy service if needed...
- policyService = policyService || $injector.get('policyService');
-
- // ...and delegate to the composition policy
- return policyService.allow(
- 'composition',
- containerType,
- selectedType
- );
- }
-
- return {
- /**
- * Check whether or not a compose action should be allowed
- * in this context.
- * @returns {boolean} true if it may be allowed
- */
- allow: function (candidate, context) {
- if (candidate.getMetadata().key === 'compose') {
- return allowComposition(
- (context || {}).domainObject,
- (context || {}).selectedObject
- );
- }
- return true;
- }
+ this.getPolicyService = function () {
+ return $injector.get('policyService');
};
}
+ ComposeActionPolicy.prototype.allowComposition = function (containerObject, selectedObject) {
+ // Get the object types involved in the compose action
+ var containerType = containerObject &&
+ containerObject.getCapability('type'),
+ selectedType = selectedObject &&
+ selectedObject.getCapability('type');
+
+ // Get a reference to the policy service if needed...
+ this.policyService = this.policyService || this.getPolicyService();
+
+ // ...and delegate to the composition policy
+ return this.policyService.allow(
+ 'composition',
+ containerType,
+ selectedType
+ );
+ };
+
+ /**
+ * Check whether or not a compose action should be allowed
+ * in this context.
+ * @returns {boolean} true if it may be allowed
+ * @memberof platform/containment.ComposeActionPolicy#
+ */
+ ComposeActionPolicy.prototype.allow = function (candidate, context) {
+ if (candidate.getMetadata().key === 'compose') {
+ return this.allowComposition(
+ (context || {}).domainObject,
+ (context || {}).selectedObject
+ );
+ }
+ return true;
+ };
+
return ComposeActionPolicy;
}
-);
\ No newline at end of file
+);
diff --git a/platform/containment/src/CompositionModelPolicy.js b/platform/containment/src/CompositionModelPolicy.js
index 74f1200530..d5e5cb5f72 100644
--- a/platform/containment/src/CompositionModelPolicy.js
+++ b/platform/containment/src/CompositionModelPolicy.js
@@ -8,21 +8,19 @@ define(
/**
* Policy allowing composition only for domain object types which
* have a composition property.
+ * @constructor
+ * @memberof platform/containment
+ * @implements {Policy.}
*/
function CompositionModelPolicy() {
- return {
- /**
- * Is the type identified by the candidate allowed to
- * contain the type described by the context?
- */
- allow: function (candidate, context) {
- return Array.isArray(
- (candidate.getInitialModel() || {}).composition
- );
- }
- };
}
+ CompositionModelPolicy.prototype.allow = function (candidate, context) {
+ return Array.isArray(
+ (candidate.getInitialModel() || {}).composition
+ );
+ };
+
return CompositionModelPolicy;
}
-);
\ No newline at end of file
+);
diff --git a/platform/containment/src/CompositionMutabilityPolicy.js b/platform/containment/src/CompositionMutabilityPolicy.js
index 9b3e12eb95..8c5ef6a765 100644
--- a/platform/containment/src/CompositionMutabilityPolicy.js
+++ b/platform/containment/src/CompositionMutabilityPolicy.js
@@ -28,24 +28,20 @@ define(
/**
* Disallow composition changes to objects which are not mutable.
+ * @memberof platform/containment
* @constructor
+ * @implements {Policy.}
*/
function CompositionMutabilityPolicy() {
- return {
- /**
- * Is the type identified by the candidate allowed to
- * contain the type described by the context?
- * @param {Type} candidate the type of domain object
- */
- allow: function (candidate) {
- // Equate creatability with mutability; that is, users
- // can only modify objects of types they can create, and
- // vice versa.
- return candidate.hasFeature('creation');
- }
- };
}
+ CompositionMutabilityPolicy.prototype.allow = function (candidate) {
+ // Equate creatability with mutability; that is, users
+ // can only modify objects of types they can create, and
+ // vice versa.
+ return candidate.hasFeature('creation');
+ };
+
return CompositionMutabilityPolicy;
}
-);
\ No newline at end of file
+);
diff --git a/platform/containment/src/CompositionPolicy.js b/platform/containment/src/CompositionPolicy.js
index 992fced49f..1f5239ec59 100644
--- a/platform/containment/src/CompositionPolicy.js
+++ b/platform/containment/src/CompositionPolicy.js
@@ -21,6 +21,11 @@
*****************************************************************************/
/*global define*/
+/**
+ * This bundle implements "containment" rules, which determine which objects
+ * can be contained within which other objects.
+ * @namespace platform/containment
+ */
define(
['./ContainmentTable'],
function (ContainmentTable) {
@@ -28,30 +33,27 @@ define(
/**
* Defines composition policy as driven by type metadata.
+ * @constructor
+ * @memberof platform/containment
+ * @implements {Policy.}
*/
function CompositionPolicy($injector) {
// We're really just wrapping the containment table and rephrasing
// it as a policy decision.
var table;
- function getTable() {
+ this.getTable = function () {
return (table = table || new ContainmentTable(
$injector.get('typeService'),
$injector.get('capabilityService')
));
- }
-
- return {
- /**
- * Is the type identified by the candidate allowed to
- * contain the type described by the context?
- */
- allow: function (candidate, context) {
- return getTable().canContain(candidate, context);
- }
};
}
+ CompositionPolicy.prototype.allow = function (candidate, context) {
+ return this.getTable().canContain(candidate, context);
+ };
+
return CompositionPolicy;
}
-);
\ No newline at end of file
+);
diff --git a/platform/containment/src/ContainmentTable.js b/platform/containment/src/ContainmentTable.js
index a3d7ab6ed4..823c782faf 100644
--- a/platform/containment/src/ContainmentTable.js
+++ b/platform/containment/src/ContainmentTable.js
@@ -37,15 +37,13 @@ define(
* start time (plug-in support means this cannot be determined
* prior to that, but we don't want to redo these calculations
* every time policy is checked.)
+ * @constructor
+ * @memberof platform/containment
*/
function ContainmentTable(typeService, capabilityService) {
- var types = typeService.listTypes(),
- capabilityTable = new CapabilityTable(typeService, capabilityService),
- table = {};
-
- // Check if one type can contain another
- function canContain(containerType, containedType) {
- }
+ var self = this,
+ types = typeService.listTypes(),
+ capabilityTable = new CapabilityTable(typeService, capabilityService);
// Add types which have all these capabilities to the set
// of allowed types
@@ -82,38 +80,39 @@ define(
// Check for defined containment restrictions
if (contains === undefined) {
// If not, accept anything
- table[key] = ANY;
+ self.table[key] = ANY;
} else {
// Start with an empty set...
- table[key] = {};
+ self.table[key] = {};
// ...cast accepted types to array if necessary...
contains = Array.isArray(contains) ? contains : [contains];
// ...and add all containment rules to that set
contains.forEach(function (c) {
- addToSet(table[key], c);
+ addToSet(self.table[key], c);
});
}
}
// Build the table
+ this.table = {};
types.forEach(addToTable);
-
- return {
- /**
- * Check if domain objects of one type can contain domain
- * objects of another type.
- * @returns {boolean} true if allowable
- */
- canContain: function (containerType, containedType) {
- var set = table[containerType.getKey()] || {};
- // Recognize either the symbolic value for "can contain
- // anything", or lookup the specific type from the set.
- return (set === ANY) || set[containedType.getKey()];
- }
- };
-
}
+ /**
+ * Check if domain objects of one type can contain domain
+ * objects of another type.
+ * @param {Type} containerType type of the containing domain object
+ * @param {Type} containedType type of the domain object
+ * to be contained
+ * @returns {boolean} true if allowable
+ */
+ ContainmentTable.prototype.canContain = function (containerType, containedType) {
+ var set = this.table[containerType.getKey()] || {};
+ // Recognize either the symbolic value for "can contain
+ // anything", or lookup the specific type from the set.
+ return (set === ANY) || set[containedType.getKey()];
+ };
+
return ContainmentTable;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/actions/ActionAggregator.js b/platform/core/src/actions/ActionAggregator.js
index 4a9288a612..3056ab04e8 100644
--- a/platform/core/src/actions/ActionAggregator.js
+++ b/platform/core/src/actions/ActionAggregator.js
@@ -25,51 +25,102 @@ define(
function () {
"use strict";
+ /**
+ * Actions are reusable processes/behaviors performed by users within
+ * the system, typically upon domain objects. Actions are commonly
+ * exposed to users as menu items or buttons.
+ *
+ * Actions are usually registered via the `actions` extension
+ * category, or (in advanced cases) via an `actionService`
+ * implementation.
+ *
+ * @interface Action
+ */
+
+ /**
+ * Perform the behavior associated with this action. The return type
+ * may vary depending on which action has been performed; in general,
+ * no return value should be expected.
+ *
+ * @method Action#perform
+ */
+
+ /**
+ * Get metadata associated with this action.
+ *
+ * @method Action#getMetadata
+ * @returns {ActionMetadata}
+ */
+
+ /**
+ * Metadata associated with an Action. Actions of specific types may
+ * extend this with additional properties.
+ *
+ * @typedef {Object} ActionMetadata
+ * @property {string} key machine-readable identifier for this action
+ * @property {string} name human-readable name for this action
+ * @property {string} description human-readable description
+ * @property {string} glyph character to display as icon
+ * @property {ActionContext} context the context in which the action
+ * will be performed.
+ */
+
+ /**
+ * Provides actions that can be performed within specific contexts.
+ *
+ * @interface ActionService
+ */
+
+ /**
+ * Get actions which can be performed within a certain context.
+ *
+ * @method ActionService#getActions
+ * @param {ActionContext} context the context in which the action will
+ * be performed
+ * @return {Action[]} relevant actions
+ */
+
+ /**
+ * A description of the context in which an action may occur.
+ *
+ * @typedef ActionContext
+ * @property {DomainObject} [domainObject] the domain object being
+ * acted upon.
+ * @property {DomainObject} [selectedObject] the selection at the
+ * time of action (e.g. the dragged object in a
+ * drag-and-drop operation.)
+ * @property {string} [key] the machine-readable identifier of
+ * the relevant action
+ * @property {string} [category] a string identifying the category
+ * of action being performed
+ */
+
/**
* The ActionAggregator makes several actionService
* instances act as those they were one. When requesting
* actions for a given context, results from all
* services will be assembled and concatenated.
*
+ * @memberof platform/core
* @constructor
- * @param {ActionProvider[]} actionProviders an array
+ * @implements {ActionService}
+ * @param {ActionService[]} actionProviders an array
* of action services
*/
function ActionAggregator(actionProviders) {
-
- function getActions(context) {
- // Get all actions from all providers, reduce down
- // to one array by concatenation
- return actionProviders.map(function (provider) {
- return provider.getActions(context);
- }).reduce(function (a, b) {
- return a.concat(b);
- }, []);
- }
-
- return {
- /**
- * Get a list of actions which are valid in a given
- * context.
- *
- * @param {ActionContext} the context in which
- * the action will occur; this is a
- * JavaScript object containing key-value
- * pairs. Typically, this will contain a
- * field "domainObject" which refers to
- * the domain object that will be acted
- * upon, but may contain arbitrary information
- * recognized by specific providers.
- * @return {Action[]} an array of actions which
- * may be performed in the provided context.
- *
- * @method
- * @memberof ActionAggregator
- */
- getActions: getActions
- };
+ this.actionProviders = actionProviders;
}
+ ActionAggregator.prototype.getActions = function (context) {
+ // Get all actions from all providers, reduce down
+ // to one array by concatenation
+ return this.actionProviders.map(function (provider) {
+ return provider.getActions(context);
+ }).reduce(function (a, b) {
+ return a.concat(b);
+ }, []);
+ };
+
return ActionAggregator;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/actions/ActionCapability.js b/platform/core/src/actions/ActionCapability.js
index 94b0706a0d..2164969a05 100644
--- a/platform/core/src/actions/ActionCapability.js
+++ b/platform/core/src/actions/ActionCapability.js
@@ -45,73 +45,74 @@ define(
* which the action will be performed (also, the
* action which exposes the capability.)
*
+ * @memberof platform/core
* @constructor
*/
function ActionCapability($q, actionService, domainObject) {
+ this.$q = $q;
+ this.actionService = actionService;
+ this.domainObject = domainObject;
+ }
+ /**
+ * Perform an action. This will find and perform the
+ * first matching action available for the specified
+ * context or key.
+ *
+ * @param {ActionContext|string} context the context in which
+ * to perform the action; this is passed along to
+ * the action service to match against available
+ * actions. The "domainObject" field will automatically
+ * be populated with the domain object that exposed
+ * this capability. If given as a string, this will
+ * be taken as the "key" field to match against
+ * specific actions.
+ * @returns {Promise} the result of the action that was
+ * performed, or undefined if no matching action
+ * was found.
+ * @memberof platform/core.ActionCapability#
+ */
+ ActionCapability.prototype.getActions = function (context) {
// Get all actions which are valid in this context;
// this simply redirects to the action service,
// but additionally adds a domainObject field.
- function getActions(context) {
- var baseContext = typeof context === 'string' ?
- { key: context } :
- (context || {}),
- actionContext = Object.create(baseContext);
+ var baseContext = typeof context === 'string' ?
+ { key: context } : (context || {}),
+ actionContext = Object.create(baseContext);
- actionContext.domainObject = domainObject;
+ actionContext.domainObject = this.domainObject;
- return actionService.getActions(actionContext);
- }
+ return this.actionService.getActions(actionContext);
+ };
+ /**
+ * Get actions which are available for this domain object,
+ * in this context.
+ *
+ * @param {ActionContext|string} context the context in which
+ * to perform the action; this is passed along to
+ * the action service to match against available
+ * actions. The "domainObject" field will automatically
+ * be populated with the domain object that exposed
+ * this capability. If given as a string, this will
+ * be taken as the "key" field to match against
+ * specific actions.
+ * @returns {Action[]} an array of matching actions
+ * @memberof platform/core.ActionCapability#
+ */
+ ActionCapability.prototype.perform = function (context) {
// Alias to getActions(context)[0].perform, with a
// check for empty arrays.
- function performAction(context) {
- var actions = getActions(context);
+ var actions = this.getActions(context);
- return $q.when(
- (actions && actions.length > 0) ?
- actions[0].perform() :
- undefined
- );
- }
+ return this.$q.when(
+ (actions && actions.length > 0) ?
+ actions[0].perform() :
+ undefined
+ );
+ };
- return {
- /**
- * Perform an action. This will find and perform the
- * first matching action available for the specified
- * context or key.
- *
- * @param {ActionContext|string} context the context in which
- * to perform the action; this is passed along to
- * the action service to match against available
- * actions. The "domainObject" field will automatically
- * be populated with the domain object that exposed
- * this capability. If given as a string, this will
- * be taken as the "key" field to match against
- * specific actions.
- * @returns {Promise} the result of the action that was
- * performed, or undefined if no matching action
- * was found.
- */
- perform: performAction,
- /**
- * Get actions which are available for this domain object,
- * in this context.
- *
- * @param {ActionContext|string} context the context in which
- * to perform the action; this is passed along to
- * the action service to match against available
- * actions. The "domainObject" field will automatically
- * be populated with the domain object that exposed
- * this capability. If given as a string, this will
- * be taken as the "key" field to match against
- * specific actions.
- * @returns {Action[]} an array of matching actions
- */
- getActions: getActions
- };
- }
return ActionCapability;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/actions/ActionProvider.js b/platform/core/src/actions/ActionProvider.js
index 5937f00fc2..dcb17eb6ce 100644
--- a/platform/core/src/actions/ActionProvider.js
+++ b/platform/core/src/actions/ActionProvider.js
@@ -35,11 +35,46 @@ define(
* of actions exposed via extension (specifically, the "actions"
* category of extension.)
*
+ * @memberof platform/core
+ * @imeplements {ActionService}
* @constructor
*/
function ActionProvider(actions) {
- var actionsByKey = {},
- actionsByCategory = {};
+ var self = this;
+
+ // Build up look-up tables
+ this.actions = actions;
+ this.actionsByKey = {};
+ this.actionsByCategory = {};
+ actions.forEach(function (Action) {
+ // Get an action's category or categories
+ var categories = Action.category || [];
+
+ // Convert to an array if necessary
+ categories = Array.isArray(categories) ?
+ categories : [categories];
+
+ // Store action under all relevant categories
+ categories.forEach(function (category) {
+ self.actionsByCategory[category] =
+ self.actionsByCategory[category] || [];
+ self.actionsByCategory[category].push(Action);
+ });
+
+ // Store action by ekey as well
+ if (Action.key) {
+ self.actionsByKey[Action.key] =
+ self.actionsByKey[Action.key] || [];
+ self.actionsByKey[Action.key].push(Action);
+ }
+ });
+ }
+
+ ActionProvider.prototype.getActions = function (actionContext) {
+ var context = (actionContext || {}),
+ category = context.category,
+ key = context.key,
+ candidates;
// Instantiate an action; invokes the constructor and
// additionally fills in the action's getMetadata method
@@ -70,86 +105,32 @@ define(
function createIfApplicable(actions, context) {
return (actions || []).filter(function (Action) {
return Action.appliesTo ?
- Action.appliesTo(context) : true;
+ Action.appliesTo(context) : true;
}).map(function (Action) {
return instantiateAction(Action, context);
});
}
- // Get an array of actions that are valid in the supplied context.
- function getActions(actionContext) {
- var context = (actionContext || {}),
- category = context.category,
- key = context.key,
- candidates;
-
- // Match actions to the provided context by comparing "key"
- // and/or "category" parameters, if specified.
- candidates = actions;
- if (key) {
- candidates = actionsByKey[key];
- if (category) {
- candidates = candidates.filter(function (Action) {
- return Action.category === category;
- });
- }
- } else if (category) {
- candidates = actionsByCategory[category];
+ // Match actions to the provided context by comparing "key"
+ // and/or "category" parameters, if specified.
+ candidates = this.actions;
+ if (key) {
+ candidates = this.actionsByKey[key];
+ if (category) {
+ candidates = candidates.filter(function (Action) {
+ return Action.category === category;
+ });
}
-
- // Instantiate those remaining actions, with additional
- // filtering per any appliesTo methods defined on those
- // actions.
- return createIfApplicable(candidates, context);
+ } else if (category) {
+ candidates = this.actionsByCategory[category];
}
- // Build up look-up tables
- actions.forEach(function (Action) {
- // Get an action's category or categories
- var categories = Action.category || [];
-
- // Convert to an array if necessary
- categories = Array.isArray(categories) ?
- categories : [categories];
-
- // Store action under all relevant categories
- categories.forEach(function (category) {
- actionsByCategory[category] =
- actionsByCategory[category] || [];
- actionsByCategory[category].push(Action);
- });
-
- // Store action by ekey as well
- if (Action.key) {
- actionsByKey[Action.key] =
- actionsByKey[Action.key] || [];
- actionsByKey[Action.key].push(Action);
- }
- });
-
- return {
- /**
- * Get a list of actions which are valid in a given
- * context.
- *
- * @param {ActionContext} the context in which
- * the action will occur; this is a
- * JavaScript object containing key-value
- * pairs. Typically, this will contain a
- * field "domainObject" which refers to
- * the domain object that will be acted
- * upon, but may contain arbitrary information
- * recognized by specific providers.
- * @return {Action[]} an array of actions which
- * may be performed in the provided context.
- *
- * @method
- * @memberof ActionProvider
- */
- getActions: getActions
- };
- }
+ // Instantiate those remaining actions, with additional
+ // filtering per any appliesTo methods defined on those
+ // actions.
+ return createIfApplicable(candidates, context);
+ };
return ActionProvider;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/actions/LoggingActionDecorator.js b/platform/core/src/actions/LoggingActionDecorator.js
index 3e9652d229..0d6f170261 100644
--- a/platform/core/src/actions/LoggingActionDecorator.js
+++ b/platform/core/src/actions/LoggingActionDecorator.js
@@ -34,9 +34,21 @@ define(
* the actions it exposes always emit a log message when they are
* performed.
*
+ * @memberof platform/core
* @constructor
+ * @implements {ActionService}
+ * @param $log Angular's logging service
+ * @param {ActionService} actionService the decorated action service
*/
function LoggingActionDecorator($log, actionService) {
+ this.$log = $log;
+ this.actionService = actionService;
+ }
+
+ LoggingActionDecorator.prototype.getActions = function () {
+ var actionService = this.actionService,
+ $log = this.$log;
+
// Decorate the perform method of the specified action, such that
// it emits a log message whenever performed.
function addLogging(action) {
@@ -58,35 +70,12 @@ define(
return logAction;
}
- return {
- /**
- * Get a list of actions which are valid in a given
- * context. These actions will additionally log
- * themselves when performed.
- *
- * @param {ActionContext} the context in which
- * the action will occur; this is a
- * JavaScript object containing key-value
- * pairs. Typically, this will contain a
- * field "domainObject" which refers to
- * the domain object that will be acted
- * upon, but may contain arbitrary information
- * recognized by specific providers.
- * @return {Action[]} an array of actions which
- * may be performed in the provided context.
- *
- * @method
- * @memberof LoggingActionDecorator
- */
- getActions: function () {
- return actionService.getActions.apply(
- actionService,
- arguments
- ).map(addLogging);
- }
- };
- }
+ return actionService.getActions.apply(
+ actionService,
+ arguments
+ ).map(addLogging);
+ };
return LoggingActionDecorator;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/capabilities/CompositionCapability.js b/platform/core/src/capabilities/CompositionCapability.js
index 8049d5b3c4..f1b2532040 100644
--- a/platform/core/src/capabilities/CompositionCapability.js
+++ b/platform/core/src/capabilities/CompositionCapability.js
@@ -37,68 +37,61 @@ define(
* require consulting the object service (e.g. to trigger a database
* query to retrieve the nested object models.)
*
+ * @memberof platform/core
* @constructor
+ * @implements {Capability}
*/
function CompositionCapability($injector, domainObject) {
- var objectService,
- lastPromise,
- lastModified;
-
// Get a reference to the object service from $injector
- function injectObjectService() {
- objectService = $injector.get("objectService");
- return objectService;
- }
-
- // Get a reference to the object service (either cached or
- // from the injector)
- function getObjectService() {
- return objectService || injectObjectService();
- }
-
- // Promise this domain object's composition (an array of domain
- // object instances corresponding to ids in its model.)
- function promiseComposition() {
- var model = domainObject.getModel(),
- ids;
-
- // Then filter out non-existent objects,
- // and wrap others (such that they expose a
- // "context" capability)
- function contextualize(objects) {
- return ids.filter(function (id) {
- return objects[id];
- }).map(function (id) {
- return new ContextualDomainObject(
- objects[id],
- domainObject
- );
- });
- }
-
- // Make a new request if we haven't made one, or if the
- // object has been modified.
- if (!lastPromise || lastModified !== model.modified) {
- ids = model.composition || [];
- lastModified = model.modified;
- // Load from the underlying object service
- lastPromise = getObjectService().getObjects(ids)
- .then(contextualize);
- }
-
- return lastPromise;
- }
-
- return {
- /**
- * Request the composition of this object.
- * @returns {Promise.} a list of all domain
- * objects which compose this domain object.
- */
- invoke: promiseComposition
+ this.injectObjectService = function () {
+ this.objectService = $injector.get("objectService");
};
+
+ this.domainObject = domainObject;
}
+ /**
+ * Request the composition of this object.
+ * @returns {Promise.} a list of all domain
+ * objects which compose this domain object.
+ */
+ CompositionCapability.prototype.invoke = function () {
+ var domainObject = this.domainObject,
+ model = domainObject.getModel(),
+ ids;
+
+ // Then filter out non-existent objects,
+ // and wrap others (such that they expose a
+ // "context" capability)
+ function contextualize(objects) {
+ return ids.filter(function (id) {
+ return objects[id];
+ }).map(function (id) {
+ return new ContextualDomainObject(
+ objects[id],
+ domainObject
+ );
+ });
+ }
+
+ // Lazily acquire object service (avoids cyclical dependency)
+ if (!this.objectService) {
+ this.injectObjectService();
+ }
+
+ // Make a new request if we haven't made one, or if the
+ // object has been modified.
+ if (!this.lastPromise || this.lastModified !== model.modified) {
+ ids = model.composition || [];
+ this.lastModified = model.modified;
+ // Load from the underlying object service
+ this.lastPromise = this.objectService.getObjects(ids)
+ .then(contextualize);
+ }
+
+ return this.lastPromise;
+ };
+
/**
* Test to determine whether or not this capability should be exposed
* by a domain object based on its model. Checks for the presence of
@@ -112,4 +105,4 @@ define(
return CompositionCapability;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/capabilities/ContextCapability.js b/platform/core/src/capabilities/ContextCapability.js
index 9eeb00823b..9ffaf4a5bb 100644
--- a/platform/core/src/capabilities/ContextCapability.js
+++ b/platform/core/src/capabilities/ContextCapability.js
@@ -36,77 +36,78 @@ define(
* those whose `composition` capability was used to access this
* object.)
*
+ * @memberof platform/core
* @constructor
+ * @implements {Capability}
*/
function ContextCapability(parentObject, domainObject) {
- return {
- /**
- * Get the immediate parent of a domain object.
- *
- * A domain object may be contained in multiple places; its
- * parent (as exposed by this capability) is the domain
- * object from which this object was accessed, usually
- * by way of a `composition` capability.
- *
- * @returns {DomainObject} the immediate parent of this
- * domain object.
- */
- getParent: function () {
- return parentObject;
- },
- /**
- * Get an array containing the complete direct ancestry
- * of this domain object, including the domain object
- * itself.
- *
- * A domain object may be contained in multiple places; its
- * parent and all ancestors (as exposed by this capability)
- * serve as a record of how this specific domain object
- * instance was reached.
- *
- * The first element in the returned array is the deepest
- * ancestor; subsequent elements are progressively more
- * recent ancestors, with the domain object which exposed
- * the capability occupying the last element of the array.
- *
- * @returns {DomainObject[]} the full composition ancestry
- * of the domain object which exposed this
- * capability.
- */
- getPath: function () {
- var parentPath = [],
- parentContext;
-
- if (parentObject) {
- parentContext = parentObject.getCapability("context");
- parentPath = parentContext ?
- parentContext.getPath() :
- [parentObject];
- }
-
- return parentPath.concat([domainObject]);
- },
- /**
- * Get the deepest ancestor available for this domain object;
- * equivalent to `getPath()[0]`.
- *
- * See notes on `getPath()` for how ancestry is defined in
- * the context of this capability.
- *
- * @returns {DomainObject} the deepest ancestor of the domain
- * object which exposed this capability.
- */
- getRoot: function () {
- var parentContext = parentObject &&
- parentObject.getCapability('context');
-
- return parentContext ?
- parentContext.getRoot() :
- (parentObject || domainObject);
- }
- };
+ this.parentObject = parentObject;
+ this.domainObject = domainObject;
}
+ /**
+ * Get the immediate parent of a domain object.
+ *
+ * A domain object may be contained in multiple places; its
+ * parent (as exposed by this capability) is the domain
+ * object from which this object was accessed, usually
+ * by way of a `composition` capability.
+ *
+ * @returns {DomainObject} the immediate parent of this
+ * domain object.
+ */
+ ContextCapability.prototype.getParent = function () {
+ return this.parentObject;
+ };
+
+ /**
+ * Get an array containing the complete direct ancestry
+ * of this domain object, including the domain object
+ * itself.
+ *
+ * A domain object may be contained in multiple places; its
+ * parent and all ancestors (as exposed by this capability)
+ * serve as a record of how this specific domain object
+ * instance was reached.
+ *
+ * The first element in the returned array is the deepest
+ * ancestor; subsequent elements are progressively more
+ * recent ancestors, with the domain object which exposed
+ * the capability occupying the last element of the array.
+ *
+ * @returns {DomainObject[]} the full composition ancestry
+ * of the domain object which exposed this
+ * capability.
+ */
+ ContextCapability.prototype.getPath = function () {
+ var parentObject = this.parentObject,
+ parentContext =
+ parentObject && parentObject.getCapability('context'),
+ parentPath = parentContext ?
+ parentContext.getPath() : [ this.parentObject ];
+
+ return parentPath.concat([this.domainObject]);
+ };
+
+ /**
+ * Get the deepest ancestor available for this domain object;
+ * equivalent to `getPath()[0]`.
+ *
+ * See notes on `getPath()` for how ancestry is defined in
+ * the context of this capability.
+ *
+ * @returns {DomainObject} the deepest ancestor of the domain
+ * object which exposed this capability.
+ */
+ ContextCapability.prototype.getRoot = function () {
+ var parentContext = this.parentObject &&
+ this.parentObject.getCapability('context');
+
+ return parentContext ?
+ parentContext.getRoot() :
+ (this.parentObject || this.domainObject);
+ };
+
return ContextCapability;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/capabilities/ContextualDomainObject.js b/platform/core/src/capabilities/ContextualDomainObject.js
index 0d042923a0..2955515ead 100644
--- a/platform/core/src/capabilities/ContextualDomainObject.js
+++ b/platform/core/src/capabilities/ContextualDomainObject.js
@@ -42,7 +42,9 @@ define(
* @param {DomainObject} parentObject the domain object from which
* the wrapped object was retrieved
*
+ * @memberof platform/core
* @constructor
+ * @implements {DomainObject}
*/
function ContextualDomainObject(domainObject, parentObject) {
// Prototypally inherit from the domain object, and
@@ -63,4 +65,4 @@ define(
return ContextualDomainObject;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/capabilities/CoreCapabilityProvider.js b/platform/core/src/capabilities/CoreCapabilityProvider.js
index 89660b72ee..7b1ba070d7 100644
--- a/platform/core/src/capabilities/CoreCapabilityProvider.js
+++ b/platform/core/src/capabilities/CoreCapabilityProvider.js
@@ -29,6 +29,19 @@ define(
function () {
"use strict";
+ /**
+ * A capability provides an interface with dealing with some
+ * dynamic behavior associated with a domain object.
+ * @interface Capability
+ */
+
+ /**
+ * Optional; if present, will be used by `DomainObject#useCapability`
+ * to simplify interaction with a specific capability. Parameters
+ * and return values vary depending on capability type.
+ * @method Capability#invoke
+ */
+
/**
* Provides capabilities based on extension definitions,
* matched to domain object models.
@@ -37,6 +50,7 @@ define(
* of constructor functions for capabilities, as
* exposed by extensions defined at the bundle level.
*
+ * @memberof platform/core
* @constructor
*/
function CoreCapabilityProvider(capabilities, $log) {
@@ -84,6 +98,7 @@ define(
* @returns {Object.} all
* capabilities known to be valid for this model, as
* key-value pairs
+ * @memberof platform/core.CoreCapabilityProvider#
*/
getCapabilities: getCapabilities
};
@@ -92,3 +107,4 @@ define(
return CoreCapabilityProvider;
}
);
+
diff --git a/platform/core/src/capabilities/DelegationCapability.js b/platform/core/src/capabilities/DelegationCapability.js
index 452b842452..0c62c05f00 100644
--- a/platform/core/src/capabilities/DelegationCapability.js
+++ b/platform/core/src/capabilities/DelegationCapability.js
@@ -45,12 +45,40 @@ define(
* in the type's definition, which contains an array of names of
* capabilities to be delegated.
*
- * @param domainObject
+ * @param $q Angular's $q, for promises
+ * @param {DomainObject} domainObject the delegating domain object
+ * @memberof platform/core
* @constructor
+ * @implements {Capability}
*/
function DelegationCapability($q, domainObject) {
- var delegateCapabilities = {},
- type = domainObject.getCapability("type");
+ var type = domainObject.getCapability("type"),
+ self = this;
+
+ this.$q = $q;
+ this.delegateCapabilities = {};
+ this.domainObject = domainObject;
+
+ // Generate set for easy lookup of capability delegation
+ if (type && type.getDefinition) {
+ (type.getDefinition().delegates || []).forEach(function (key) {
+ self.delegateCapabilities[key] = true;
+ });
+ }
+ }
+
+
+ /**
+ * Get the domain objects which are intended to be delegated
+ * responsibility for some specific capability.
+ *
+ * @param {string} key the name of the delegated capability
+ * @returns {DomainObject[]} the domain objects to which
+ * responsibility for this capability is delegated.
+ * @memberof platform/core.DelegationCapability#
+ */
+ DelegationCapability.prototype.getDelegates = function (key) {
+ var domainObject = this.domainObject;
function filterObjectsWithCapability(capability) {
return function (objects) {
@@ -64,55 +92,42 @@ define(
return domainObject.useCapability('composition');
}
- function doesDelegate(key) {
- return delegateCapabilities[key] || false;
- }
+ return this.doesDelegateCapability(key) ?
+ promiseChildren().then(
+ filterObjectsWithCapability(key)
+ ) :
+ this.$q.when([]);
+ };
- function getDelegates(capability) {
- return doesDelegate(capability) ?
- promiseChildren().then(
- filterObjectsWithCapability(capability)
- ) :
- $q.when([]);
- }
-
- // Generate set for easy lookup of capability delegation
- if (type && type.getDefinition) {
- (type.getDefinition().delegates || []).forEach(function (key) {
- delegateCapabilities[key] = true;
- });
- }
-
- return {
- /**
- * Invoke this capability; alias of `getDelegates`, used to
- * simplify usage, e.g.:
- *
- * `domainObject.useCapability("delegation", "telemetry")`
- *
- * ...will retrieve all members of a domain object's
- * composition which have a "telemetry" capability.
- *
- * @param {string} the name of the delegated capability
- * @returns {DomainObject[]} the domain objects to which
- * responsibility for this capability is delegated.
- */
- invoke: getDelegates,
- /**
- * Get the domain objects which are intended to be delegated
- * responsibility for some specific capability.
- *
- * @param {string} the name of the delegated capability
- * @returns {DomainObject[]} the domain objects to which
- * responsibility for this capability is delegated.
- */
- getDelegates: getDelegates,
- doesDelegateCapability: doesDelegate
- };
- }
+ /**
+ * Check if the domain object which exposed this capability
+ * wishes to delegate another capability.
+ *
+ * @param {string} key the capability to check for
+ * @returns {boolean} true if the capability is delegated
+ */
+ DelegationCapability.prototype.doesDelegateCapability = function (key) {
+ return !!(this.delegateCapabilities[key]);
+ };
+ /**
+ * Invoke this capability; alias of `getDelegates`, used to
+ * simplify usage, e.g.:
+ *
+ * `domainObject.useCapability("delegation", "telemetry")`
+ *
+ * ...will retrieve all members of a domain object's
+ * composition which have a "telemetry" capability.
+ *
+ * @param {string} the name of the delegated capability
+ * @returns {DomainObject[]} the domain objects to which
+ * responsibility for this capability is delegated.
+ * @memberof platform/core.DelegationCapability#
+ */
+ DelegationCapability.prototype.invoke =
+ DelegationCapability.prototype.getDelegates;
return DelegationCapability;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/capabilities/MetadataCapability.js b/platform/core/src/capabilities/MetadataCapability.js
index 677dab0008..242b35b6dc 100644
--- a/platform/core/src/capabilities/MetadataCapability.js
+++ b/platform/core/src/capabilities/MetadataCapability.js
@@ -25,10 +25,23 @@ define(
* `value` properties describing that domain object (suitable for
* display.)
*
+ * @param {DomainObject} domainObject the domain object whose
+ * metadata is to be exposed
+ * @implements {Capability}
* @constructor
+ * @memberof platform/core
*/
function MetadataCapability(domainObject) {
- var model = domainObject.getModel();
+ this.domainObject = domainObject;
+ }
+
+ /**
+ * Get metadata about this object.
+ * @returns {MetadataProperty[]} metadata about this object
+ */
+ MetadataCapability.prototype.invoke = function () {
+ var domainObject = this.domainObject,
+ model = domainObject.getModel();
function hasDisplayableValue(metadataProperty) {
var t = typeof metadataProperty.value;
@@ -37,8 +50,8 @@ define(
function formatTimestamp(timestamp) {
return typeof timestamp === 'number' ?
- (moment.utc(timestamp).format(TIME_FORMAT) + " UTC") :
- undefined;
+ (moment.utc(timestamp).format(TIME_FORMAT) + " UTC") :
+ undefined;
}
function getProperties() {
@@ -73,20 +86,11 @@ define(
];
}
- function getMetadata() {
- return getProperties().concat(getCommonMetadata())
- .filter(hasDisplayableValue);
- }
-
- return {
- /**
- * Get metadata about this object.
- * @returns {MetadataProperty[]} metadata about this object
- */
- invoke: getMetadata
- };
- }
+ return getProperties().concat(getCommonMetadata())
+ .filter(hasDisplayableValue);
+ };
return MetadataCapability;
}
);
+
diff --git a/platform/core/src/capabilities/MutationCapability.js b/platform/core/src/capabilities/MutationCapability.js
index 4268f7c323..b9f49ca969 100644
--- a/platform/core/src/capabilities/MutationCapability.js
+++ b/platform/core/src/capabilities/MutationCapability.js
@@ -69,97 +69,105 @@ define(
* });
* ```
*
+ * @param {Function} topic a service for creating listeners
+ * @param {Function} now a service to get the current time
* @param {DomainObject} domainObject the domain object
* which will expose this capability
+ * @memberof platform/core
* @constructor
+ * @implements {Capability}
*/
function MutationCapability(topic, now, domainObject) {
- var t = topic(TOPIC_PREFIX + domainObject.getId());
+ this.mutationTopic = topic(TOPIC_PREFIX + domainObject.getId());
+ this.now = now;
+ this.domainObject = domainObject;
+ }
- function mutate(mutator, timestamp) {
- // Get the object's model and clone it, so the
- // mutator function has a temporary copy to work with.
- var model = domainObject.getModel(),
- clone = JSON.parse(JSON.stringify(model)),
- useTimestamp = arguments.length > 1;
+ /**
+ * Modify the domain object's model, using a provided
+ * function. This function will receive a copy of the
+ * domain object's model as an argument; behavior
+ * varies depending on that function's return value:
+ *
+ * * If no value (or undefined) is returned by the mutator,
+ * the state of the model object delivered as the mutator's
+ * argument will become the domain object's new model.
+ * This is useful for writing code that modifies the model
+ * directly.
+ * * If a plain object is returned, that object will be used
+ * as the domain object's new model.
+ * * If boolean `false` is returned, the mutation will be
+ * cancelled.
+ * * If a promise is returned, its resolved value will be
+ * handled as one of the above.
+ *
+ *
+ * @param {Function} mutator the function which will make
+ * changes to the domain object's model.
+ * @param {number} [timestamp] timestamp to record for
+ * this mutation (otherwise, system time will be
+ * used)
+ * @returns {Promise.} a promise for the result
+ * of the mutation; true if changes were made.
+ */
+ MutationCapability.prototype.mutate = function (mutator, timestamp) {
+ // Get the object's model and clone it, so the
+ // mutator function has a temporary copy to work with.
+ var domainObject = this.domainObject,
+ now = this.now,
+ t = this.mutationTopic,
+ model = domainObject.getModel(),
+ clone = JSON.parse(JSON.stringify(model)),
+ useTimestamp = arguments.length > 1;
- // Function to handle copying values to the actual
- function handleMutation(mutationResult) {
- // If mutation result was undefined, just use
- // the clone; this allows the mutator to omit return
- // values and just change the model directly.
- var result = mutationResult || clone;
+ // Function to handle copying values to the actual
+ function handleMutation(mutationResult) {
+ // If mutation result was undefined, just use
+ // the clone; this allows the mutator to omit return
+ // values and just change the model directly.
+ var result = mutationResult || clone;
- // Allow mutators to change their mind by
- // returning false.
- if (mutationResult !== false) {
- // Copy values if result was a different object
- // (either our clone or some other new thing)
- if (model !== result) {
- copyValues(model, result);
- }
- model.modified = useTimestamp ? timestamp : now();
- t.notify(model);
+ // Allow mutators to change their mind by
+ // returning false.
+ if (mutationResult !== false) {
+ // Copy values if result was a different object
+ // (either our clone or some other new thing)
+ if (model !== result) {
+ copyValues(model, result);
}
-
- // Report the result of the mutation
- return mutationResult !== false;
+ model.modified = useTimestamp ? timestamp : now();
+ t.notify(model);
}
- // Invoke the provided mutator, then make changes to
- // the underlying model (if applicable.)
- return fastPromise(mutator(clone)).then(handleMutation);
+ // Report the result of the mutation
+ return mutationResult !== false;
}
- function listen(listener) {
- return t.listen(listener);
- }
+ // Invoke the provided mutator, then make changes to
+ // the underlying model (if applicable.)
+ return fastPromise(mutator(clone)).then(handleMutation);
+ };
- return {
- /**
- * Alias of `mutate`, used to support useCapability.
- */
- invoke: mutate,
- /**
- * Modify the domain object's model, using a provided
- * function. This function will receive a copy of the
- * domain object's model as an argument; behavior
- * varies depending on that function's return value:
- *
- * * If no value (or undefined) is returned by the mutator,
- * the state of the model object delivered as the mutator's
- * argument will become the domain object's new model.
- * This is useful for writing code that modifies the model
- * directly.
- * * If a plain object is returned, that object will be used
- * as the domain object's new model.
- * * If boolean `false` is returned, the mutation will be
- * cancelled.
- * * If a promise is returned, its resolved value will be
- * handled as one of the above.
- *
- *
- * @param {function} mutator the function which will make
- * changes to the domain object's model.
- * @param {number} [timestamp] timestamp to record for
- * this mutation (otherwise, system time will be
- * used)
- * @returns {Promise.} a promise for the result
- * of the mutation; true if changes were made.
- */
- mutate: mutate,
- /**
- * Listen for mutations of this domain object's model.
- * The provided listener will be invoked with the domain
- * object's new model after any changes. To stop listening,
- * invoke the function returned by this method.
- * @param {Function} listener function to call on mutation
- * @returns {Function} a function to stop listening
- */
- listen: listen
- };
- }
+ /**
+ * Listen for mutations of this domain object's model.
+ * The provided listener will be invoked with the domain
+ * object's new model after any changes. To stop listening,
+ * invoke the function returned by this method.
+ * @param {Function} listener function to call on mutation
+ * @returns {Function} a function to stop listening
+ * @memberof platform/core.MutationCapability#
+ */
+ MutationCapability.prototype.listen = function (listener) {
+ return this.mutationTopic.listen(listener);
+ };
+
+ /**
+ * Alias of `mutate`, used to support useCapability.
+ */
+ MutationCapability.prototype.invoke =
+ MutationCapability.prototype.mutate;
return MutationCapability;
}
);
+
diff --git a/platform/core/src/capabilities/PersistenceCapability.js b/platform/core/src/capabilities/PersistenceCapability.js
index 68c3255412..8c7e08e17d 100644
--- a/platform/core/src/capabilities/PersistenceCapability.js
+++ b/platform/core/src/capabilities/PersistenceCapability.js
@@ -33,18 +33,69 @@ define(
*
* @param {PersistenceService} persistenceService the underlying
* provider of persistence capabilities.
- * @param {string} SPACE the name of the persistence space to
+ * @param {string} space the name of the persistence space to
* use (this is an arbitrary string, useful in principle
* for distinguishing different persistence stores from
* one another.)
* @param {DomainObject} the domain object which shall expose
* this capability
*
+ * @memberof platform/core
* @constructor
+ * @implements {Capability}
*/
- function PersistenceCapability(persistenceService, SPACE, domainObject) {
+ function PersistenceCapability(persistenceService, space, domainObject) {
// Cache modified timestamp
- var modified = domainObject.getModel().modified;
+ this.modified = domainObject.getModel().modified;
+
+ this.domainObject = domainObject;
+ this.space = space;
+ this.persistenceService = persistenceService;
+ }
+
+ // Utility function for creating promise-like objects which
+ // resolve synchronously when possible
+ function fastPromise(value) {
+ return (value || {}).then ? value : {
+ then: function (callback) {
+ return fastPromise(callback(value));
+ }
+ };
+ }
+
+ /**
+ * Persist any changes which have been made to this
+ * domain object's model.
+ * @returns {Promise} a promise which will be resolved
+ * if persistence is successful, and rejected
+ * if not.
+ */
+ PersistenceCapability.prototype.persist = function () {
+ var domainObject = this.domainObject,
+ modified = domainObject.getModel().modified;
+
+ // Update persistence timestamp...
+ domainObject.useCapability("mutation", function (model) {
+ model.persisted = modified;
+ }, modified);
+
+ // ...and persist
+ return this.persistenceService.updateObject(
+ this.getSpace(),
+ domainObject.getId(),
+ domainObject.getModel()
+ );
+ };
+
+ /**
+ * Update this domain object to match the latest from
+ * persistence.
+ * @returns {Promise} a promise which will be resolved
+ * when the update is complete
+ */
+ PersistenceCapability.prototype.refresh = function () {
+ var domainObject = this.domainObject,
+ model = domainObject.getModel();
// Update a domain object's model upon refresh
function updateModel(model) {
@@ -54,73 +105,29 @@ define(
}, modified);
}
- // For refresh; update a domain object model, only if there
- // are no unsaved changes.
- function updatePersistenceTimestamp() {
- var modified = domainObject.getModel().modified;
- domainObject.useCapability("mutation", function (model) {
- model.persisted = modified;
- }, modified);
- }
+ // Only update if we don't have unsaved changes
+ return (model.modified === model.persisted) ?
+ this.persistenceService.readObject(
+ this.getSpace(),
+ this.domainObject.getId()
+ ).then(updateModel) :
+ fastPromise(false);
+ };
- // Utility function for creating promise-like objects which
- // resolve synchronously when possible
- function fastPromise(value) {
- return (value || {}).then ? value : {
- then: function (callback) {
- return fastPromise(callback(value));
- }
- };
- }
-
- return {
- /**
- * Persist any changes which have been made to this
- * domain object's model.
- * @returns {Promise} a promise which will be resolved
- * if persistence is successful, and rejected
- * if not.
- */
- persist: function () {
- updatePersistenceTimestamp();
- return persistenceService.updateObject(
- SPACE,
- domainObject.getId(),
- domainObject.getModel()
- );
- },
- /**
- * Update this domain object to match the latest from
- * persistence.
- * @returns {Promise} a promise which will be resolved
- * when the update is complete
- */
- refresh: function () {
- var model = domainObject.getModel();
- // Only update if we don't have unsaved changes
- return (model.modified === model.persisted) ?
- persistenceService.readObject(
- SPACE,
- domainObject.getId()
- ).then(updateModel) :
- fastPromise(false);
- },
- /**
- * Get the space in which this domain object is persisted;
- * this is useful when, for example, decided which space a
- * newly-created domain object should be persisted to (by
- * default, this should be the space of its containing
- * object.)
- *
- * @returns {string} the name of the space which should
- * be used to persist this object
- */
- getSpace: function () {
- return SPACE;
- }
- };
- }
+ /**
+ * Get the space in which this domain object is persisted;
+ * this is useful when, for example, decided which space a
+ * newly-created domain object should be persisted to (by
+ * default, this should be the space of its containing
+ * object.)
+ *
+ * @returns {string} the name of the space which should
+ * be used to persist this object
+ */
+ PersistenceCapability.prototype.getSpace = function () {
+ return this.space;
+ };
return PersistenceCapability;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/capabilities/RelationshipCapability.js b/platform/core/src/capabilities/RelationshipCapability.js
index fc8729a9a1..7eb6d01bb9 100644
--- a/platform/core/src/capabilities/RelationshipCapability.js
+++ b/platform/core/src/capabilities/RelationshipCapability.js
@@ -38,91 +38,82 @@ define(
* which are not intended to appear in the tree, but are instead
* intended only for special, limited usage.
*
+ * @memberof platform/core
* @constructor
+ * @implements {Capability}
*/
function RelationshipCapability($injector, domainObject) {
- var objectService,
- lastPromise = {},
- lastModified;
-
// Get a reference to the object service from $injector
- function injectObjectService() {
- objectService = $injector.get("objectService");
- return objectService;
- }
-
- // Get a reference to the object service (either cached or
- // from the injector)
- function getObjectService() {
- return objectService || injectObjectService();
- }
-
- // Promise this domain object's composition (an array of domain
- // object instances corresponding to ids in its model.)
- function promiseRelationships(key) {
- var model = domainObject.getModel(),
- ids;
-
- // Package objects as an array
- function packageObject(objects) {
- return ids.map(function (id) {
- return objects[id];
- }).filter(function (obj) {
- return obj;
- });
- }
-
- // Clear cached promises if modification has occurred
- if (lastModified !== model.modified) {
- lastPromise = {};
- lastModified = model.modified;
- }
-
- // Make a new request if needed
- if (!lastPromise[key]) {
- ids = (model.relationships || {})[key] || [];
- lastModified = model.modified;
- // Load from the underlying object service
- lastPromise[key] = getObjectService().getObjects(ids)
- .then(packageObject);
- }
-
- return lastPromise[key];
- }
-
- // List types of relationships which this object has
- function listRelationships() {
- var relationships =
- (domainObject.getModel() || {}).relationships || {};
-
- // Check if this key really does expose an array of ids
- // (to filter out malformed relationships)
- function isArray(key) {
- return Array.isArray(relationships[key]);
- }
-
- return Object.keys(relationships).filter(isArray).sort();
- }
-
- return {
- /**
- * List all types of relationships exposed by this
- * object.
- * @returns {string[]} a list of all relationship types
- */
- listRelationships: listRelationships,
- /**
- * Request related objects, with a given relationship type.
- * This will typically require asynchronous lookup, so this
- * returns a promise.
- * @param {string} key the type of relationship
- * @returns {Promise.} a promise for related
- * domain objects
- */
- getRelatedObjects: promiseRelationships
+ this.injectObjectService = function () {
+ this.objectService = $injector.get("objectService");
};
+
+ this.lastPromise = {};
+ this.domainObject = domainObject;
}
+ /**
+ * List all types of relationships exposed by this
+ * object.
+ * @returns {string[]} a list of all relationship types
+ */
+ RelationshipCapability.prototype.listRelationships = function listRelationships() {
+ var relationships =
+ (this.domainObject.getModel() || {}).relationships || {};
+
+ // Check if this key really does expose an array of ids
+ // (to filter out malformed relationships)
+ function isArray(key) {
+ return Array.isArray(relationships[key]);
+ }
+
+ return Object.keys(relationships).filter(isArray).sort();
+ };
+
+ /**
+ * Request related objects, with a given relationship type.
+ * This will typically require asynchronous lookup, so this
+ * returns a promise.
+ * @param {string} key the type of relationship
+ * @returns {Promise.} a promise for related
+ * domain objects
+ */
+ RelationshipCapability.prototype.getRelatedObjects = function (key) {
+ var model = this.domainObject.getModel(),
+ ids;
+
+ // Package objects as an array
+ function packageObject(objects) {
+ return ids.map(function (id) {
+ return objects[id];
+ }).filter(function (obj) {
+ return obj;
+ });
+ }
+
+ // Clear cached promises if modification has occurred
+ if (this.lastModified !== model.modified) {
+ this.lastPromise = {};
+ this.lastModified = model.modified;
+ }
+
+ // Make a new request if needed
+ if (!this.lastPromise[key]) {
+ ids = (model.relationships || {})[key] || [];
+ this.lastModified = model.modified;
+ // Lazily initialize object service now that we need it
+ if (!this.objectService) {
+ this.injectObjectService();
+ }
+ // Load from the underlying object service
+ this.lastPromise[key] = this.objectService.getObjects(ids)
+ .then(packageObject);
+ }
+
+ return this.lastPromise[key];
+ };
+
+
/**
* Test to determine whether or not this capability should be exposed
* by a domain object based on its model. Checks for the presence of
@@ -136,4 +127,4 @@ define(
return RelationshipCapability;
}
-);
\ No newline at end of file
+);
diff --git a/platform/core/src/models/CachingModelDecorator.js b/platform/core/src/models/CachingModelDecorator.js
index d9d4ef6775..a338d6770f 100644
--- a/platform/core/src/models/CachingModelDecorator.js
+++ b/platform/core/src/models/CachingModelDecorator.js
@@ -30,11 +30,32 @@ define(
* The caching model decorator maintains a cache of loaded domain
* object models, and ensures that duplicate models for the same
* object are not provided.
+ * @memberof platform/core
* @constructor
+ * @param {ModelService} modelService this service to decorate
+ * @implements {ModelService}
*/
function CachingModelDecorator(modelService) {
- var cache = {},
- cached = {};
+ this.cache = {};
+ this.cached = {};
+ this.modelService = modelService;
+ }
+
+ // Fast-resolving promise
+ function fastPromise(value) {
+ return (value || {}).then ? value : {
+ then: function (callback) {
+ return fastPromise(callback(value));
+ }
+ };
+ }
+
+ CachingModelDecorator.prototype.getModels = function (ids) {
+ var cache = this.cache,
+ cached = this.cached,
+ neededIds = ids.filter(function notCached(id) {
+ return !cached[id];
+ });
// Update the cached instance of a model to a new value.
// We update in-place to ensure there is only ever one instance
@@ -67,30 +88,12 @@ define(
return oldModel;
}
- // Fast-resolving promise
- function fastPromise(value) {
- return (value || {}).then ? value : {
- then: function (callback) {
- return fastPromise(callback(value));
- }
- };
- }
-
- // Store this model in the cache
- function cacheModel(id, model) {
- cache[id] = cached[id] ? updateModel(id, model) : model;
- cached[id] = true;
- }
-
- // Check if an id is not in cache, for lookup filtering
- function notCached(id) {
- return !cached[id];
- }
-
// Store the provided models in our cache
function cacheAll(models) {
Object.keys(models).forEach(function (id) {
- cacheModel(id, models[id]);
+ cache[id] = cached[id] ?
+ updateModel(id, models[id]) : models[id];
+ cached[id] = true;
});
}
@@ -99,38 +102,17 @@ define(
return cache;
}
- return {
- /**
- * Get models for these specified string identifiers.
- * These will be given as an object containing keys
- * and values, where keys are object identifiers and
- * values are models.
- * This result may contain either a subset or a
- * superset of the total objects.
- *
- * @param {Array} ids the string identifiers for
- * models of interest.
- * @returns {Promise