diff --git a/docs/src/guide/index.md b/docs/src/guide/index.md index 239235a279..01896ecfc5 100644 --- a/docs/src/guide/index.md +++ b/docs/src/guide/index.md @@ -3,8 +3,8 @@ Victor Woeltjen [victor.woeltjen@nasa.gov](mailto:victor.woeltjen@nasa.gov) -September 23, 2015 -Document Version 1.1 +September 23, 2015 +Document Version 1.1 Date | Version | Summary of Changes | Author ------------------- | --------- | ----------------------- | --------------- @@ -20,9 +20,9 @@ MCT Web platform. ## What is Open MCT Web Open MCT Web is a platform for building user interface and display tools, developed at the NASA Ames Research Center in collaboration with teams at the -Jet Propulsion Laboratory. It is written in HTML5, CSS3, and JavaScript, using -[AngularJS](http://www.angularjs.org) as a framework. Its intended use is to -create single-page web applications which integrate data and behavior from a +Jet Propulsion Laboratory. It is written in HTML5, CSS3, and JavaScript, using +[AngularJS](http://www.angularjs.org) as a framework. Its intended use is to +create single-page web applications which integrate data and behavior from a variety of sources and domains. Open MCT Web has been developed to support the remote operation of space @@ -36,9 +36,9 @@ Open MCT Web provides: * A common user interface paradigm which can be applied to a variety of domains and tasks. Open MCT Web is more than a widget toolkit - it provides a standard tree-on-the-left, view-on-the-right browsing environment which you customize by -adding new browsable object types, visualizations, and back-end adapters. +adding new browsable object types, visualizations, and back-end adapters. * A plugin framework and an extensible API for introducing new application -features of a variety of types. +features of a variety of types. * A set of general-purpose object types and visualizations, as well as some visualizations and infrastructure specific to telemetry display. @@ -70,7 +70,7 @@ Web should behave. ### Technologies Open MCT Web sources are written in JavaScript, with a number of configuration -files written in JSON. Displayable components are written in HTML5 and CSS3. +files written in JSON. Displayable components are written in HTML5 and CSS3. Open MCT Web is built using [AngularJS](http://www.angularjs.org) from Google. A good understanding of Angular is recommended for developers working with Open MCT Web. @@ -90,9 +90,9 @@ chapter) within that directory. To initially clone the Open MCT Web repository: `git clone <repository URL> <local repo directory> -b open-master` -To create a fork to begin working on a new application using Open MCT Web: +To create a fork to begin working on a new application using Open MCT Web: - cd <local repo directory> + cd <local repo directory> git checkout open-master git checkout -b <new branch name> @@ -120,7 +120,7 @@ plugins) but to collaborate at run-time. Open MCT Web's framework layer is implemented on top of AngularJS's [dependency injection mechanism](https://docs.angularjs.org/guide/di) and is modelled after -[OSGi](hhttp://www.osgi.org/) and its [Declarative Services component model](http://wiki.osgi.org/wiki/Declarative_Services). +[OSGi](hhttp://www.osgi.org/) and its [Declarative Services component model](http://wiki.osgi.org/wiki/Declarative_Services). In particular, this is where the term _bundle_ comes from. ## Framework Overview @@ -129,7 +129,7 @@ The framework's role in the application is to manage connections between bundles. All application-specific behavior is provided by individual bundles, or as the result of their collaboration. -The framework is described in more detail in the [Framework Overview](../architecture/Framework.md#Overview) of the +The framework is described in more detail in the [Framework Overview](../architecture/Framework.md#Overview) of the architecture guide. ### Tiers @@ -186,16 +186,16 @@ as well as the framework layer's role in mediating between these components. Once the framework layer has wired these software components together, however, the application's logical architecture emerges. -An overview of the logical architecture of the platform is given in the [Platform Architecture](../architecture/Platform.md#PlatformArchitecture) +An overview of the logical architecture of the platform is given in the [Platform Architecture](../architecture/Platform.md#PlatformArchitecture) section of the Platform guide ### Web Services -As mentioned in the Introduction, Open MCT Web is a platform single-page -applications which runs entirely in the browser. Most applications will want to -additionally interact with server-side resources, to (for example) read -telemetry data or store user-created objects. This interaction is handled by -individual bundles using APIs which are supported in browser (such as +As mentioned in the Introduction, Open MCT Web is a platform single-page +applications which runs entirely in the browser. Most applications will want to +additionally interact with server-side resources, to (for example) read +telemetry data or store user-created objects. This interaction is handled by +individual bundles using APIs which are supported in browser (such as `XMLHttpRequest`, typically wrapped by Angular's `$http`.) ```nomnoml @@ -218,213 +218,213 @@ individual bundles using APIs which are supported in browser (such as ] ``` -This architectural approach ensures a loose coupling between applications built -using Open MCT Web and the backends which support them. - -### Glossary - -Certain terms are used throughout Open MCT Web with consistent meanings or -conventions. Other developer documentation, particularly in-line documentation, +This architectural approach ensures a loose coupling between applications built +using Open MCT Web and the backends which support them. + +### Glossary + +Certain terms are used throughout Open MCT Web with consistent meanings or +conventions. Other developer documentation, particularly in-line documentation, may presume an understanding of these terms. -* __bundle__: A bundle is a removable, reusable grouping of software elements. +* __bundle__: A bundle is a removable, reusable grouping of software elements. The application is composed of bundles. Plug-ins are bundles. -* __capability__: A JavaScript object which exposes dynamic behavior or +* __capability__: A JavaScript object which exposes dynamic behavior or non-persistent state associated with a domain object. -* __category__: A machine-readable identifier for a group that something may +* __category__: A machine-readable identifier for a group that something may belong to. -* __composition __: In the context of a domain object, this refers to the set of -other domain objects that compose or are contained by that object. A domain +* __composition __: In the context of a domain object, this refers to the set of +other domain objects that compose or are contained by that object. A domain object's composition is the set of domain objects that should appear immediately - beneath it in a tree hierarchy. A domain object's composition is described in -its model as an array of identifiers; its composition capability provides a -means to retrieve the actual domain object instances associated with these -identifiers asynchronously. + beneath it in a tree hierarchy. A domain object's composition is described in +its model as an array of identifiers; its composition capability provides a +means to retrieve the actual domain object instances associated with these +identifiers asynchronously. * __description__: When used as an object property, this refers to the human- -readable description of a thing; usually a single sentence or short paragraph. -(Most often used in the context of extensions, domain object models, or other -similar application-specific objects.) -* __domain object __: A meaningful object to the user; a distinct thing in the -work support by Open MCT Web. Anything that appears in the left-hand tree is a -domain object. -* __extension __: An extension is a unit of functionality exposed to the platform -in a declarative fashion by a bundle. The term 'extension category' is used to -distinguish types of extensions from specific extension instances. -* __id__: A string which uniquely identifies a domain object. -* __key__: When used as an object property, this refers to the machine-readable -identifier for a specific thing in a set of things. (Most often used in the -context of extensions or other similar application-specific object sets.) This -term is chosen to avoid attaching ambiguous meanings to 'id'. -* __model__: The persistent state associated with a domain object. A domain -object's model is a JavaScript object which can be converted to JSON without -losing information (that is, it contains no methods.) -* __name__: When used as an object property, this refers to the human-readable -name for a thing. (Most often used in the context of extensions, domain object -models, or other similar application-specific objects.) -* __navigation__: Refers to the current state of the application with respect to -the user's expressed interest in a specific domain object; e.g. when a user -clicks on a domain object in the tree, they are navigating to it, and it is -thereafter considered the navigated object (until the user makes another such -choice.) This term is used to distinguish navigation from selection, which -occurs in an editing context. -* __space__: A machine-readable name used to identify a persistence store. -Interactions with persistence with generally involve a space parameter in some -form, to distinguish multiple persistence stores from one another (for cases -where there are multiple valid persistence locations available.) -* __source__: A machine-readable name used to identify a source of telemetry -data. Similar to "space", this allows multiple telemetry sources to operate -side-by-side without conflicting. +readable description of a thing; usually a single sentence or short paragraph. +(Most often used in the context of extensions, domain object models, or other +similar application-specific objects.) +* __domain object __: A meaningful object to the user; a distinct thing in the +work support by Open MCT Web. Anything that appears in the left-hand tree is a +domain object. +* __extension __: An extension is a unit of functionality exposed to the platform +in a declarative fashion by a bundle. The term 'extension category' is used to +distinguish types of extensions from specific extension instances. +* __id__: A string which uniquely identifies a domain object. +* __key__: When used as an object property, this refers to the machine-readable +identifier for a specific thing in a set of things. (Most often used in the +context of extensions or other similar application-specific object sets.) This +term is chosen to avoid attaching ambiguous meanings to 'id'. +* __model__: The persistent state associated with a domain object. A domain +object's model is a JavaScript object which can be converted to JSON without +losing information (that is, it contains no methods.) +* __name__: When used as an object property, this refers to the human-readable +name for a thing. (Most often used in the context of extensions, domain object +models, or other similar application-specific objects.) +* __navigation__: Refers to the current state of the application with respect to +the user's expressed interest in a specific domain object; e.g. when a user +clicks on a domain object in the tree, they are navigating to it, and it is +thereafter considered the navigated object (until the user makes another such +choice.) This term is used to distinguish navigation from selection, which +occurs in an editing context. +* __space__: A machine-readable name used to identify a persistence store. +Interactions with persistence with generally involve a space parameter in some +form, to distinguish multiple persistence stores from one another (for cases +where there are multiple valid persistence locations available.) +* __source__: A machine-readable name used to identify a source of telemetry +data. Similar to "space", this allows multiple telemetry sources to operate +side-by-side without conflicting. # Framework - -Open MCT Web is built on the [AngularJS framework]( http://www.angularjs.org ). A -good understanding of that framework is recommended. -Open MCT Web adds an extra layer on top of AngularJS to (a) generalize its -dependency injection mechanism slightly, particularly to handle many-to-one -relationships; and (b) handle script loading. Combined, these features become a -plugin mechanism. - -This framework layer operates on two key concepts: +Open MCT Web is built on the [AngularJS framework]( http://www.angularjs.org ). A +good understanding of that framework is recommended. -* __Bundle:__ A bundle is a collection of related functionality that can be -added to the application as a group. More concretely, a bundle is a directory -containing a JSON file declaring its contents, as well as JavaScript sources, -HTML templates, and other resources used to support that functionality. (The -term bundle is borrowed from [OSGi](http://www.osgi.org/) - which has also -inspired many of the concepts used in the framework layer. A familiarity with -OSGi, particularly Declarative Services, may be useful when working with Open +Open MCT Web adds an extra layer on top of AngularJS to (a) generalize its +dependency injection mechanism slightly, particularly to handle many-to-one +relationships; and (b) handle script loading. Combined, these features become a +plugin mechanism. + +This framework layer operates on two key concepts: + +* __Bundle:__ A bundle is a collection of related functionality that can be +added to the application as a group. More concretely, a bundle is a directory +containing a JSON file declaring its contents, as well as JavaScript sources, +HTML templates, and other resources used to support that functionality. (The +term bundle is borrowed from [OSGi](http://www.osgi.org/) - which has also +inspired many of the concepts used in the framework layer. A familiarity with +OSGi, particularly Declarative Services, may be useful when working with Open MCT Web.) -* __Extension:__ An extension is an individual unit of functionality. Extensions -are collected together in bundles, and may interact with other extensions. +* __Extension:__ An extension is an individual unit of functionality. Extensions +are collected together in bundles, and may interact with other extensions. -The framework layer, loaded and initiated from `index.html`, is the main point -of entry for an application built on Open MCT Web. It is responsible for wiring -together the application at run time (much of this responsibility is actually -delegated to Angular); at a high-level, the framework does this by proceeding +The framework layer, loaded and initiated from `index.html`, is the main point +of entry for an application built on Open MCT Web. It is responsible for wiring +together the application at run time (much of this responsibility is actually +delegated to Angular); at a high-level, the framework does this by proceeding through four stages: -1. __Loading definitions:__ JSON declarations are loaded for all bundles which -will constitute the application, and wrapped in a useful API for subsequent -stages. -2. __Resolving extensions:__ Any scripts which provide implementations for -extensions exposed by bundles are loaded, using Require. -3. __Registering extensions__ Resolved extensions are registered with Angular, -such that they can be used by the application at run-time. This stage includes -both registration of Angular built-ins (directives, controllers, routes, -constants, and services) as well as registration of non-Angular extensions. -4. __Bootstrapping__ The Angular application is bootstrapped; at that point, -Angular takes over and populates the body of the page using the extensions that -have been registered. +1. __Loading definitions:__ JSON declarations are loaded for all bundles which +will constitute the application, and wrapped in a useful API for subsequent +stages. +2. __Resolving extensions:__ Any scripts which provide implementations for +extensions exposed by bundles are loaded, using Require. +3. __Registering extensions__ Resolved extensions are registered with Angular, +such that they can be used by the application at run-time. This stage includes +both registration of Angular built-ins (directives, controllers, routes, +constants, and services) as well as registration of non-Angular extensions. +4. __Bootstrapping__ The Angular application is bootstrapped; at that point, +Angular takes over and populates the body of the page using the extensions that +have been registered. -## Bundles +## Bundles -The basic configurable unit of Open MCT Web is the _bundle_. This term has been -used a bit already; now we'll get to a more formal definition. +The basic configurable unit of Open MCT Web is the _bundle_. This term has been +used a bit already; now we'll get to a more formal definition. A bundle is a directory which contains: * A bundle definition; a file named `bundle.json`. -* Subdirectories for sources, resources, and tests. -* Optionally, a `README.md` Markdown file describing its contents (this is not +* Subdirectories for sources, resources, and tests. +* Optionally, a `README.md` Markdown file describing its contents (this is not used by Open MCT Web in any way, but it's a helpful convention to follow.) -The bundle definition is the main point of entry for the bundle. The framework -looks at this to determine which components need to be loaded and how they +The bundle definition is the main point of entry for the bundle. The framework +looks at this to determine which components need to be loaded and how they interact. -A plugin in Open MCT Web is a bundle. The platform itself is also decomposed -into bundles, each of which provides some category of functionality. The -difference between a _bundle_ and a _plugin_ is purely a matter of the intended -use; a plugin is just a bundle that is meant to be easily added or removed. When -developing, it is typically more useful to think in terms of bundles. - -### Configuring Active Bundles - -To decide which bundles should be loaded, the framework loads a file named -`bundles.json` (peer to the `index.html` file which serves the application) to -determine which bundles should be loaded. This file should contain a single JSON -array of strings, where each is the path to a bundle. These paths should not -include bundle.json (this is implicit) or a trailing slash. +A plugin in Open MCT Web is a bundle. The platform itself is also decomposed +into bundles, each of which provides some category of functionality. The +difference between a _bundle_ and a _plugin_ is purely a matter of the intended +use; a plugin is just a bundle that is meant to be easily added or removed. When +developing, it is typically more useful to think in terms of bundles. -For instance, if `bundles.json` contained: +### Configuring Active Bundles - [ - "example/builtins", - "example/extensions" - ] - -...then the Open MCT Web framework would look for bundle definitions at -`example/builtins/bundle.json` and `example/extensions/bundle.json`, relative -to the path of `index.html`. No other bundles would be loaded. +To decide which bundles should be loaded, the framework loads a file named +`bundles.json` (peer to the `index.html` file which serves the application) to +determine which bundles should be loaded. This file should contain a single JSON +array of strings, where each is the path to a bundle. These paths should not +include bundle.json (this is implicit) or a trailing slash. -### Bundle Definition - -A bundle definition (the `bundle.json` file located within a bundle) contains a -description of the bundle itself, as well as the information exposed by the -bundle. - -This definition is expressed as a single JSON object with the following +For instance, if `bundles.json` contained: + + [ + "example/builtins", + "example/extensions" + ] + +...then the Open MCT Web framework would look for bundle definitions at +`example/builtins/bundle.json` and `example/extensions/bundle.json`, relative +to the path of `index.html`. No other bundles would be loaded. + +### Bundle Definition + +A bundle definition (the `bundle.json` file located within a bundle) contains a +description of the bundle itself, as well as the information exposed by the +bundle. + +This definition is expressed as a single JSON object with the following properties (all of which are optional, falling back to reasonable defaults): -* `key`: A machine-readable name for the bundle. (Currently used only in -logging.) -* `name`: A human-readable name for the bundle. (Also only used in logging.) -* `sources`: Names a directory in which source scripts (which will implement -extensions) are located. Defaults to 'src' -* `resources`: Names a directory in which resource files (such as HTML templates, -images, CS files, and other non-JavaScript files needed by this bundle) are -located. Defaults to 'res' -* `libraries`: Names a directory in which third-party libraries are located. -Defaults to 'lib' -* `configuration`: A bundle's configuration object, which should be formatted as -would be passed to require.config (see [RequireJS documentation](http://requirejs.org/docs/api.html ) ); -note that only paths and shim have been tested. -* `extensions`: An object containing key-value pairs, where keys are extension -categories, and values are extension definitions. See the section on Extensions -for more information. +* `key`: A machine-readable name for the bundle. (Currently used only in +logging.) +* `name`: A human-readable name for the bundle. (Also only used in logging.) +* `sources`: Names a directory in which source scripts (which will implement +extensions) are located. Defaults to 'src' +* `resources`: Names a directory in which resource files (such as HTML templates, +images, CS files, and other non-JavaScript files needed by this bundle) are +located. Defaults to 'res' +* `libraries`: Names a directory in which third-party libraries are located. +Defaults to 'lib' +* `configuration`: A bundle's configuration object, which should be formatted as +would be passed to require.config (see [RequireJS documentation](http://requirejs.org/docs/api.html ) ); +note that only paths and shim have been tested. +* `extensions`: An object containing key-value pairs, where keys are extension +categories, and values are extension definitions. See the section on Extensions +for more information. -For example, the bundle definition for example/policy looks like: +For example, the bundle definition for example/policy looks like: { - "name": "Example Policy", - "description": "Provides an example of using policies.", - "sources": "src", - "extensions": { - "policies": [ - { - "implementation": "ExamplePolicy.js", - "category": "action" + "name": "Example Policy", + "description": "Provides an example of using policies.", + "sources": "src", + "extensions": { + "policies": [ + { + "implementation": "ExamplePolicy.js", + "category": "action" } - ] - } + ] + } } -### Bundle Directory Structure - -In addition to the directories defined in the bundle definition, a bundle will -typically contain other directories not used at run-time. Additionally, some -useful development scripts (such as the command line build and the test suite) -expect this directory structure to be in use, and may ignore options chosen by -`b undle.json`. It is recommended that the directory structure described below be +### Bundle Directory Structure + +In addition to the directories defined in the bundle definition, a bundle will +typically contain other directories not used at run-time. Additionally, some +useful development scripts (such as the command line build and the test suite) +expect this directory structure to be in use, and may ignore options chosen by +`b undle.json`. It is recommended that the directory structure described below be used for new bundles. -* `src`: Contains JavaScript sources for this bundle. May contain additional -subdirectories to organize these sources; typically, these subdirectories are -named to correspond to the extension categories they contain and/or support, but -this is only a convention. -* `res`: Contains other files needed by this bundle, such as HTML templates. May -contain additional subdirectories to organize these sources. -* `lib`: Contains JavaScript sources from third-party libraries. These are -separated from bundle sources in order to ignore them during code style checking +* `src`: Contains JavaScript sources for this bundle. May contain additional +subdirectories to organize these sources; typically, these subdirectories are +named to correspond to the extension categories they contain and/or support, but +this is only a convention. +* `res`: Contains other files needed by this bundle, such as HTML templates. May +contain additional subdirectories to organize these sources. +* `lib`: Contains JavaScript sources from third-party libraries. These are +separated from bundle sources in order to ignore them during code style checking from the command line build. -* `test`: Contains JavaScript sources implementing [Jasmine](http://jasmine.github.io/) -tests, as well as a file named `suite.json` describing which files to test. -Should have the same folder structure as the `src` directory; see the section on -automated testing for more information. - -For example, the directory structure for bundle `platform/commonUI/about` looks -like: +* `test`: Contains JavaScript sources implementing [Jasmine](http://jasmine.github.io/) +tests, as well as a file named `suite.json` describing which files to test. +Should have the same folder structure as the `src` directory; see the section on +automated testing for more information. + +For example, the directory structure for bundle `platform/commonUI/about` looks +like: Platform | @@ -442,238 +442,238 @@ like: | +-README.md -## Extensions +## Extensions -While bundles provide groupings of related behaviors, the individual units of -behavior are called extensions. +While bundles provide groupings of related behaviors, the individual units of +behavior are called extensions. -Extensions belong to categories; an extension category is the machine-readable -identifier used to identify groups of extensions. In the `extensions` property -of a bundle definition, the keys are extension categories and the values are -arrays of extension definitions. - -### General Extensions +Extensions belong to categories; an extension category is the machine-readable +identifier used to identify groups of extensions. In the `extensions` property +of a bundle definition, the keys are extension categories and the values are +arrays of extension definitions. -Extensions are intended as a general-purpose mechanism for adding new types of -functionality to Open MCT Web. +### General Extensions -An extension category is registered with Angular under the name of the -extension, plus a suffix of two square brackets; so, an Angular service (or, -generally, any other extension) can access the full set of registered -extensions, from all bundles, by including this string (e.g. `types[]` to get -all type definitions) in a dependency declaration. +Extensions are intended as a general-purpose mechanism for adding new types of +functionality to Open MCT Web. -As a convention, extension categories are given single-word, plural nouns for -names within Open MCT Web (e.g. `types`.) This convention is not enforced by the -platform in any way. For extension categories introduced by external plugins, it -is recommended to prefix the extension category with a vendor identifier (or -similar) followed by a dot, to avoid collisions. - -### Extension Definitions +An extension category is registered with Angular under the name of the +extension, plus a suffix of two square brackets; so, an Angular service (or, +generally, any other extension) can access the full set of registered +extensions, from all bundles, by including this string (e.g. `types[]` to get +all type definitions) in a dependency declaration. -The properties used in extension definitions are typically unique to each -category of extension; a few properties have standard interpretations by the -platform. +As a convention, extension categories are given single-word, plural nouns for +names within Open MCT Web (e.g. `types`.) This convention is not enforced by the +platform in any way. For extension categories introduced by external plugins, it +is recommended to prefix the extension category with a vendor identifier (or +similar) followed by a dot, to avoid collisions. -* `implementation`: Identifies a JavaScript source file (in the sources -folder) which implements this extension. This JavaScript file is expected to -contain an AMD module (see http://requirejs.org/docs/whyamd.html#amd ) which -gives as its result a single constructor function. -* `depends`: An array of dependencies needed by this extension; these will be -passed on to Angular's [dependency injector](https://docs.angularjs.org/guide/di ) . -By default, this is treated as an empty array. Note that depends does not make -sense without `implementation` (since these dependencies will be passed to the -implementation when it is instantiated.) -* `priority`: A number or string indicating the priority order (see below) of -this extension instance. Before an extension category is registered with -AngularJS, the extensions of this category from all bundles will be concatenated -into a single array, and then sorted by priority. +### Extension Definitions -Extensions do not need to have an implementation. If no implementation is -provided, consumers of the extension category will receive the extension -definition as a plain JavaScript object. Otherwise, they will receive the -partialized (see below) constructor for that implementation, which will -additionally have all properties from the extension definition attached. +The properties used in extension definitions are typically unique to each +category of extension; a few properties have standard interpretations by the +platform. -#### Partial Construction +* `implementation`: Identifies a JavaScript source file (in the sources +folder) which implements this extension. This JavaScript file is expected to +contain an AMD module (see http://requirejs.org/docs/whyamd.html#amd ) which +gives as its result a single constructor function. +* `depends`: An array of dependencies needed by this extension; these will be +passed on to Angular's [dependency injector](https://docs.angularjs.org/guide/di ) . +By default, this is treated as an empty array. Note that depends does not make +sense without `implementation` (since these dependencies will be passed to the +implementation when it is instantiated.) +* `priority`: A number or string indicating the priority order (see below) of +this extension instance. Before an extension category is registered with +AngularJS, the extensions of this category from all bundles will be concatenated +into a single array, and then sorted by priority. -In general, extensions are intended to be implemented as constructor functions, -which will be used elsewhere to instantiate new objects of that type. However, -the Angular-supported method for dependency injection is (effectively) -constructor-style injection; so, both declared dependencies and run-time -arguments are competing for space in a constructor's arguments. +Extensions do not need to have an implementation. If no implementation is +provided, consumers of the extension category will receive the extension +definition as a plain JavaScript object. Otherwise, they will receive the +partialized (see below) constructor for that implementation, which will +additionally have all properties from the extension definition attached. -To resolve this, the Open MCT Web framework registers extension instances in a -partially constructed form. That is, the constructor exposed by the extension's -implementation is effectively decomposed into two calls; the first takes the -dependencies, and returns the constructor in its second form, which takes the -remaining arguments. +#### Partial Construction -This means that, when writing implementations, the constructor function should -be written to include all declared dependencies, followed by all run-time -arguments. When using extensions, only the run-time arguments need to be -provided. - -#### Priority +In general, extensions are intended to be implemented as constructor functions, +which will be used elsewhere to instantiate new objects of that type. However, +the Angular-supported method for dependency injection is (effectively) +constructor-style injection; so, both declared dependencies and run-time +arguments are competing for space in a constructor's arguments. -Within each extension category, registration occurs in priority order. An -extension's priority may be specified as a `priority` property in its extension -definition; this may be a number, or a symbolic string. Extensions are -registered in reverse order (highest-priority first), and symbolic strings are -mapped to the numeric values as follows: +To resolve this, the Open MCT Web framework registers extension instances in a +partially constructed form. That is, the constructor exposed by the extension's +implementation is effectively decomposed into two calls; the first takes the +dependencies, and returns the constructor in its second form, which takes the +remaining arguments. -* `fallback`: Negative infinity. Used for extensions that are not intended for -use (that is, they are meant to be overridden) but are present as an option of -last resort. -* `default`: `-100`. Used for extensions that are expected to be overridden, but -need a useful default. -* `none`: `0`. Also used if no priority is specified, or if an unknown or -malformed priority is specified. -* `optional`: `100`. Used for extensions that are meant to be used, but may be -overridden. -* `preferred`: `1000`. Used for extensions that are specifically intended to be -used, but still may be overridden in principle. -* `mandatory`: Positive infinity. Used when an extension should definitely not -be overridden. +This means that, when writing implementations, the constructor function should +be written to include all declared dependencies, followed by all run-time +arguments. When using extensions, only the run-time arguments need to be +provided. -These symbolic names are chosen to support usage where many extensions may -satisfy a given need, but only one may be used; in this case, as a convention it -should be the lowest-ordered (highest-priority) extensions available. In other -cases, a full set (or multi-element subset) of extensions may be desired, with a -specific ordering; in these cases, it is preferable to specify priority -numerically when declaring extensions, and to understand that extensions will be -sorted according to these conventions when using them. - -### Angular Built-ins +#### Priority + +Within each extension category, registration occurs in priority order. An +extension's priority may be specified as a `priority` property in its extension +definition; this may be a number, or a symbolic string. Extensions are +registered in reverse order (highest-priority first), and symbolic strings are +mapped to the numeric values as follows: + +* `fallback`: Negative infinity. Used for extensions that are not intended for +use (that is, they are meant to be overridden) but are present as an option of +last resort. +* `default`: `-100`. Used for extensions that are expected to be overridden, but +need a useful default. +* `none`: `0`. Also used if no priority is specified, or if an unknown or +malformed priority is specified. +* `optional`: `100`. Used for extensions that are meant to be used, but may be +overridden. +* `preferred`: `1000`. Used for extensions that are specifically intended to be +used, but still may be overridden in principle. +* `mandatory`: Positive infinity. Used when an extension should definitely not +be overridden. + +These symbolic names are chosen to support usage where many extensions may +satisfy a given need, but only one may be used; in this case, as a convention it +should be the lowest-ordered (highest-priority) extensions available. In other +cases, a full set (or multi-element subset) of extensions may be desired, with a +specific ordering; in these cases, it is preferable to specify priority +numerically when declaring extensions, and to understand that extensions will be +sorted according to these conventions when using them. + +### Angular Built-ins + +Several entities supported Angular are expressed and managed as extensions in +Open MCT Web. Specifically, these extension categories are _directives_, +_controllers_, _services_, _constants_, _runs_, and _routes_. -Several entities supported Angular are expressed and managed as extensions in -Open MCT Web. Specifically, these extension categories are _directives_, -_controllers_, _services_, _constants_, _runs_, and _routes_. - #### Angular Directives -New [directives]( https://docs.angularjs.org/guide/directive ) may be -registered as extensions of the directives category. Implementations of -directives in this category should take only dependencies as arguments, and -should return a directive definition object. +New [directives]( https://docs.angularjs.org/guide/directive ) may be +registered as extensions of the directives category. Implementations of +directives in this category should take only dependencies as arguments, and +should return a directive definition object. + +The directive's name should be provided as a key property of its extension +definition, in camel-case format. -The directive's name should be provided as a key property of its extension -definition, in camel-case format. - #### Angular Controllers -New [controllers]( https://docs.angularjs.org/guide/controller ) may be registered -as extensions of the controllers category. The implementation is registered -directly as the controller; its only constructor arguments are its declared -dependencies. +New [controllers]( https://docs.angularjs.org/guide/controller ) may be registered +as extensions of the controllers category. The implementation is registered +directly as the controller; its only constructor arguments are its declared +dependencies. + +The directive's identifier should be provided as a key property of its extension +definition. + -The directive's identifier should be provided as a key property of its extension -definition. - - #### Angular Services -New [services](https://docs.angularjs.org/guide/services ) may be registered as -extensions of the services category. The implementation is registered via a -[service call]( https://docs.angularjs.org/api/auto/service/$provide#service ), so -it will be instantiated with the new operator. +New [services](https://docs.angularjs.org/guide/services ) may be registered as +extensions of the services category. The implementation is registered via a +[service call]( https://docs.angularjs.org/api/auto/service/$provide#service ), so +it will be instantiated with the new operator. -#### Angular Constants +#### Angular Constants -Constant values may be registered as extensions of the [ constants category](https://docs.angularjs.org/api/ng/type/angular.Module#constant ). -These extensions have no implementation; instead, they should contain a property - key , which is the name under which the constant will be registered, and a +Constant values may be registered as extensions of the [ constants category](https://docs.angularjs.org/api/ng/type/angular.Module#constant ). +These extensions have no implementation; instead, they should contain a property + key , which is the name under which the constant will be registered, and a property value , which is the constant value that will be registered. -#### Angular Runs +#### Angular Runs -In some cases, you want to register code to run as soon as the application -starts; these can be registered as extensions of the [ runs category](https://docs.angularjs.org/api/ng/type/angular.Module#run ). -Implementations registered in this category will be invoked (with their declared -dependencies) when the Open MCT Web application first starts. (Note that, in -this case, the implementation is better thought of as just a function, as +In some cases, you want to register code to run as soon as the application +starts; these can be registered as extensions of the [ runs category](https://docs.angularjs.org/api/ng/type/angular.Module#run ). +Implementations registered in this category will be invoked (with their declared +dependencies) when the Open MCT Web application first starts. (Note that, in +this case, the implementation is better thought of as just a function, as opposed to a constructor function.) #### Angular Routes -Extensions of category `routes` will be registered with Angular's [route provider](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider ). -Extensions of this category have no implementations, and need only two -properties in their definition: +Extensions of category `routes` will be registered with Angular's [route provider](https://docs.angularjs.org/api/ngRoute/provider/$routeProvider ). +Extensions of this category have no implementations, and need only two +properties in their definition: -* `when`: The value that will be passed as the path argument to `$routeProvider.when`; -specifically, the string that will appear in the trailing -part of the URL corresponding to this route. This property may be omitted, in -which case this extension instance will be treated as the default route. -* `templateUrl`: A path to the template to render for this route. Specified as a -path relative to the bundle's resource directory (`res` by default.) +* `when`: The value that will be passed as the path argument to `$routeProvider.when`; +specifically, the string that will appear in the trailing +part of the URL corresponding to this route. This property may be omitted, in +which case this extension instance will be treated as the default route. +* `templateUrl`: A path to the template to render for this route. Specified as a +path relative to the bundle's resource directory (`res` by default.) ### Composite Services -Composite services are described in the [relevant section](../architecture/Framework.md#Composite-Services) +Composite services are described in the [relevant section](../architecture/Framework.md#Composite-Services) of the framework guide. A component should include the following properties in its extension definition: -* `provides`: The symbolic identifier for the service that will be composed. The +* `provides`: The symbolic identifier for the service that will be composed. The fully-composed service will be registered with Angular under this name. -* `type`: One of `provider`, `aggregator` or `decorator` (as above) +* `type`: One of `provider`, `aggregator` or `decorator` (as above) -In addition to any declared dependencies, _aggregators_ and _decorators_ both -receive one more argument (immediately following declared dependencies) that is -provided by the framework. For an aggregator, this will be an array of all -providers of the same service (that is, with matching `provides` properties); -for a decorator, this will be whichever provider, decorator, or aggregator is -next in the sequence of decorators. +In addition to any declared dependencies, _aggregators_ and _decorators_ both +receive one more argument (immediately following declared dependencies) that is +provided by the framework. For an aggregator, this will be an array of all +providers of the same service (that is, with matching `provides` properties); +for a decorator, this will be whichever provider, decorator, or aggregator is +next in the sequence of decorators. -Services exposed by the Open MCT Web platform are often declared as composite -services, as this form is open for a variety of common modifications. +Services exposed by the Open MCT Web platform are often declared as composite +services, as this form is open for a variety of common modifications. -# Core API +# Core API -Most of Open MCT Web's relevant API is provided and/or mediated by the -framework; that is, much of developing for Open MCT Web is a matter of adding -extensions which access other parts of the platform by means of dependency -injection. +Most of Open MCT Web's relevant API is provided and/or mediated by the +framework; that is, much of developing for Open MCT Web is a matter of adding +extensions which access other parts of the platform by means of dependency +injection. -The core bundle (`platform/core`) introduces a few additional object types meant -to be passed along by other services. +The core bundle (`platform/core`) introduces a few additional object types meant +to be passed along by other services. -## Domain Objects +## Domain Objects -Domain objects are the most fundamental component of Open MCT Web's information -model. A domain object is some distinct thing relevant to a user's work flow, -such as a telemetry channel, display, or similar. Open MCT Web is a tool for -viewing, browsing, manipulating, and otherwise interacting with a graph of -domain objects. +Domain objects are the most fundamental component of Open MCT Web's information +model. A domain object is some distinct thing relevant to a user's work flow, +such as a telemetry channel, display, or similar. Open MCT Web is a tool for +viewing, browsing, manipulating, and otherwise interacting with a graph of +domain objects. A domain object should be conceived of as the union of the following: -* __Identifier__: A machine-readable string that uniquely identifies the domain -object within this application instance. -* __Model__: The persistent state of the domain object. A domain object's model -is a JavaScript object that can be losslessly converted to JSON. -* __Capabilities__: Dynamic behavior associated with the domain object. -Capabilities are JavaScript objects which provide additional methods for -interacting with the domain objects which expose those capabilities. Not all -domain objects expose all capabilities. +* __Identifier__: A machine-readable string that uniquely identifies the domain +object within this application instance. +* __Model__: The persistent state of the domain object. A domain object's model +is a JavaScript object that can be losslessly converted to JSON. +* __Capabilities__: Dynamic behavior associated with the domain object. +Capabilities are JavaScript objects which provide additional methods for +interacting with the domain objects which expose those capabilities. Not all +domain objects expose all capabilities. At run-time, a domain object has the following interface: -* `getId()`: Get the identifier for this domain object. -* `getModel()`: Get the plain state associated with this domain object. This -will return a JavaScript object that can be losslessly converted to JSON. Note -that the model returned here can be modified directly but should not be; -instead, use the mutation capability. -* `getCapability(key)`: Get the specified capability associated with this domain -object. This will return a JavaScript object whose interface is specific to the -type of capability being requested. If the requested capability is not exposed +* `getId()`: Get the identifier for this domain object. +* `getModel()`: Get the plain state associated with this domain object. This +will return a JavaScript object that can be losslessly converted to JSON. Note +that the model returned here can be modified directly but should not be; +instead, use the mutation capability. +* `getCapability(key)`: Get the specified capability associated with this domain +object. This will return a JavaScript object whose interface is specific to the +type of capability being requested. If the requested capability is not exposed by this domain object, this will return undefined . -* `hasCapability(key)`: Shorthand for checking if a domain object exposes the +* `hasCapability(key)`: Shorthand for checking if a domain object exposes the requested capability. -* `useCapability(key, arguments )`: Shorthand for -`getCapability(key).invoke(arguments)`, with additional checking between calls. -If the provided capability has no invoke method, the return value here functions -as `getCapability` including returning `undefined` if the capability is not +* `useCapability(key, arguments )`: Shorthand for +`getCapability(key).invoke(arguments)`, with additional checking between calls. +If the provided capability has no invoke method, the return value here functions +as `getCapability` including returning `undefined` if the capability is not exposed. ### Identifier Syntax @@ -700,208 +700,208 @@ A domain object identifier has one or two parts, separated by a colon. ## Domain Object Actions -An `Action` is behavior that can be performed upon/using a `DomainObject`. An +An `Action` is behavior that can be performed upon/using a `DomainObject`. An Action has the following interface: -* `perform()`: Do this action. For example, if one had an instance of a -`RemoveAction` invoking its perform method would cause the domain object which +* `perform()`: Do this action. For example, if one had an instance of a +`RemoveAction` invoking its perform method would cause the domain object which exposed it to be removed from its container. -* `getMetadata()`: Get metadata associated with this action. Returns an object -containing: +* `getMetadata()`: Get metadata associated with this action. Returns an object +containing: * `name`: Human-readable name. - * `description`: Human-readable summary of this action. - * `glyph`: Single character to be displayed in Open MCT Web's icon font set. + * `description`: Human-readable summary of this action. + * `glyph`: Single character to be displayed in Open MCT Web's icon font set. * `context`: The context in which this action is being performed (see below) -Action instances are typically obtained via a domain object's `action` -capability. - -### Action Contexts +Action instances are typically obtained via a domain object's `action` +capability. -An action context is a JavaScript object with the following properties: +### Action Contexts -* `domainObject`: The domain object being acted upon. -* `selectedObject`: Optional; the selection at the time of action (e.g. the +An action context is a JavaScript object with the following properties: + +* `domainObject`: The domain object being acted upon. +* `selectedObject`: Optional; the selection at the time of action (e.g. the dragged object in a drag-and-drop operation.) -## Telemetry +## Telemetry -Telemetry series data in Open MCT Web is represented by a common interface, and -packaged in a consistent manner to facilitate passing telemetry updates around -multiple visualizations. - -### Telemetry Requests +Telemetry series data in Open MCT Web is represented by a common interface, and +packaged in a consistent manner to facilitate passing telemetry updates around +multiple visualizations. -A telemetry request is a JavaScript object containing the following properties: +### Telemetry Requests -* `source`: A machine-readable identifier for the source of this telemetry. This -is useful when multiple distinct data sources are in use side-by-side. -* `key`: A machine-readable identifier for a unique series of telemetry within -that source. -* _Note: This API is still under development; additional properties, such as -start and end time, should be present in future versions of Open MCT Web._ +A telemetry request is a JavaScript object containing the following properties: -Additional properties may be included in telemetry requests which have specific +* `source`: A machine-readable identifier for the source of this telemetry. This +is useful when multiple distinct data sources are in use side-by-side. +* `key`: A machine-readable identifier for a unique series of telemetry within +that source. +* _Note: This API is still under development; additional properties, such as +start and end time, should be present in future versions of Open MCT Web._ + +Additional properties may be included in telemetry requests which have specific interpretations for specific sources. ### Telemetry Responses -When returned from the `telemetryService` (see [Services](#Services) section), -telemetry series data will be packaged in a `source -> key -> TelemetrySeries` -fashion. That is, telemetry is passed in an object containing key-value pairs. -Keys identify telemetry sources; values are objects containing additional -key-value pairs. In this object, keys identify individual telemetry series (and -match they `key` property from corresponding requests) and values are -`TelemetrySeries` objects (see below.) +When returned from the `telemetryService` (see [Services](#Services) section), +telemetry series data will be packaged in a `source -> key -> TelemetrySeries` +fashion. That is, telemetry is passed in an object containing key-value pairs. +Keys identify telemetry sources; values are objects containing additional +key-value pairs. In this object, keys identify individual telemetry series (and +match they `key` property from corresponding requests) and values are +`TelemetrySeries` objects (see below.) ### Telemetry Series -A telemetry series is a specific sequence of data, typically associated with a -specific instrument. Telemetry is modeled as an ordered sequence of domain and -range values, where domain values must be non-decreasing but range values do -not. (Typically, domain values are interpreted as UTC timestamps in milliseconds -relative to the UNIX epoch.) A series must have at least one domain and one +A telemetry series is a specific sequence of data, typically associated with a +specific instrument. Telemetry is modeled as an ordered sequence of domain and +range values, where domain values must be non-decreasing but range values do +not. (Typically, domain values are interpreted as UTC timestamps in milliseconds +relative to the UNIX epoch.) A series must have at least one domain and one range, and may have more than one. -Telemetry series data in Open MCT Web is expressed via the following -`TelemetrySeries` interface: +Telemetry series data in Open MCT Web is expressed via the following +`TelemetrySeries` interface: -* `getPointCount()`: Returns the number of unique points/samples in this series. -* `getDomainValue(index, [domain])`: Get the domain value at the specified index . -If a second domain argument is provided, this is taken as a string identifier -indicating which domain option (of, presumably, multiple) should be returned. -* `getRangeValue(index, [range])`: Get the domain value at the specified index . -If a second range argument is provided, this is taken as a string identifier -indicating which range option (of, presumably, multiple) should be returned. - -### Telemetry Metadata +* `getPointCount()`: Returns the number of unique points/samples in this series. +* `getDomainValue(index, [domain])`: Get the domain value at the specified index . +If a second domain argument is provided, this is taken as a string identifier +indicating which domain option (of, presumably, multiple) should be returned. +* `getRangeValue(index, [range])`: Get the domain value at the specified index . +If a second range argument is provided, this is taken as a string identifier +indicating which range option (of, presumably, multiple) should be returned. -Domain objects which have associated telemetry also expose metadata about that -telemetry; this is retrievable via the `getMetadata()` of the telemetry -capability. This will return a single JavaScript object containing the following -properties: +### Telemetry Metadata -* `source`: The machine-readable identifier for the source of telemetry data for -this object. -* `key`: The machine-readable identifier for the individual telemetry series. -* `domains`: An array of supported domains (see TelemetrySeries above.) Each -domain should be expressed as an object which includes: - * `key`: Machine-readable identifier for this domain, as will be passed into - a getDomainValue(index, domain) call. - * `name`: Human-readable name for this domain. -* `ranges`: An array of supported ranges; same format as domains . +Domain objects which have associated telemetry also expose metadata about that +telemetry; this is retrievable via the `getMetadata()` of the telemetry +capability. This will return a single JavaScript object containing the following +properties: -Note that this metadata is also used as the prototype for telemetry requests -made using this capability. +* `source`: The machine-readable identifier for the source of telemetry data for +this object. +* `key`: The machine-readable identifier for the individual telemetry series. +* `domains`: An array of supported domains (see TelemetrySeries above.) Each +domain should be expressed as an object which includes: + * `key`: Machine-readable identifier for this domain, as will be passed into + a getDomainValue(index, domain) call. + * `name`: Human-readable name for this domain. +* `ranges`: An array of supported ranges; same format as domains . -## Types -A domain object's type is represented as a Type object, which has the following +Note that this metadata is also used as the prototype for telemetry requests +made using this capability. + +## Types +A domain object's type is represented as a Type object, which has the following interface: -* `getKey()`: Get the machine-readable identifier for this type. -* `getName()`: Get the human-readable name for this type. -* `getDescription()`: Get a human-readable summary of this type. -* `getGlyph()`: Get the single character to be rendered as an icon for this type -in Open MCT Web's custom font set. -* `getInitialModel()`: Get a domain object model that represents the initial -state (before user specification of properties) for domain objects of this type. -* `getDefinition()`: Get the extension definition for this type, as a JavaScript -object. -* `instanceOf(type)`: Check if this type is (or inherits from) a specified type . -This type can be either a string, in which case it is taken to be that type's - key , or it may be a `Type` instance. -* `hasFeature(feature)`: Returns a boolean value indicating whether or not this -type supports the specified feature, which is a symbolic string. -* `getProperties()`: Get all properties associated with this type, expressed as -an array of `TypeProperty` instances. - -### Type Features +* `getKey()`: Get the machine-readable identifier for this type. +* `getName()`: Get the human-readable name for this type. +* `getDescription()`: Get a human-readable summary of this type. +* `getGlyph()`: Get the single character to be rendered as an icon for this type +in Open MCT Web's custom font set. +* `getInitialModel()`: Get a domain object model that represents the initial +state (before user specification of properties) for domain objects of this type. +* `getDefinition()`: Get the extension definition for this type, as a JavaScript +object. +* `instanceOf(type)`: Check if this type is (or inherits from) a specified type . +This type can be either a string, in which case it is taken to be that type's + key , or it may be a `Type` instance. +* `hasFeature(feature)`: Returns a boolean value indicating whether or not this +type supports the specified feature, which is a symbolic string. +* `getProperties()`: Get all properties associated with this type, expressed as +an array of `TypeProperty` instances. -Features of a domain object type are expressed as symbolic string identifiers. -They are defined in practice by usage; currently, the Open MCT Web platform only -uses the creation feature to determine which domain object types should appear -in the Create menu. - -### Type Properties +### Type Features -Types declare the user-editable properties of their domain object instances in -order to allow the forms which appear in the __Create__ and __Edit Properties__ +Features of a domain object type are expressed as symbolic string identifiers. +They are defined in practice by usage; currently, the Open MCT Web platform only +uses the creation feature to determine which domain object types should appear +in the Create menu. + +### Type Properties + +Types declare the user-editable properties of their domain object instances in +order to allow the forms which appear in the __Create__ and __Edit Properties__ dialogs to be generated by the platform. A `TypeProperty` has the following interface: -* `getValue(model)`: Get the current value for this property, as it appears in -the provided domain object model. -* `setValue(model, value)`: Set a new value for this property in the provided -domain object model . -* `getDefinition()`: Get the raw definition for this property as a JavaScript -object (as it was declared in this type's extension definition.) +* `getValue(model)`: Get the current value for this property, as it appears in +the provided domain object model. +* `setValue(model, value)`: Set a new value for this property in the provided +domain object model . +* `getDefinition()`: Get the raw definition for this property as a JavaScript +object (as it was declared in this type's extension definition.) -# Extension Categories +# Extension Categories -The information in this section is focused on registering new extensions of -specific types; it does not contain a catalog of the extension instances of -these categories provided by the platform. Relevant summaries there are provided +The information in this section is focused on registering new extensions of +specific types; it does not contain a catalog of the extension instances of +these categories provided by the platform. Relevant summaries there are provided in subsequent sections. - + ## Actions Category -An action is a thing that can be done to or using a domain object, typically as -initiated by the user. +An action is a thing that can be done to or using a domain object, typically as +initiated by the user. An action's implementation: -* Should take a single `context` argument in its constructor. (See Action +* Should take a single `context` argument in its constructor. (See Action Contexts, under Core API.) -* Should provide a method `perform` which causes the behavior associated with +* Should provide a method `perform` which causes the behavior associated with the action to occur. -* May provide a method `getMetadata` which provides metadata associated with -the action. If omitted, one will be provided by the platform which includes +* May provide a method `getMetadata` which provides metadata associated with +the action. If omitted, one will be provided by the platform which includes metadata from the action's extension definition. -* May provide a static method `appliesTo(context)` (that is, a function -available as a property of the implementation's constructor itself), which will -be used by the platform to filter out actions from contexts in which they are +* May provide a static method `appliesTo(context)` (that is, a function +available as a property of the implementation's constructor itself), which will +be used by the platform to filter out actions from contexts in which they are inherently inapplicable. An action's bundle definition (and/or `getMetadata()` return value) may include: -* `category`: A string or array of strings identifying which category or -categories an action falls into; used to determine when an action is displayed. -Categories supported by the platform include: - * `contextual`: Actions in a context menu. - * `view-control`: Actions triggered by buttons in the top-right of Browse - view. -* `key`: A machine-readable identifier for this action. -* `name`: A human-readable name for this action (e.g. to show in a menu) -* `description`: A human-readable summary of the behavior of this action. -* `glyph`: A single character which will be rendered in Open MCT Web's custom +* `category`: A string or array of strings identifying which category or +categories an action falls into; used to determine when an action is displayed. +Categories supported by the platform include: + * `contextual`: Actions in a context menu. + * `view-control`: Actions triggered by buttons in the top-right of Browse + view. +* `key`: A machine-readable identifier for this action. +* `name`: A human-readable name for this action (e.g. to show in a menu) +* `description`: A human-readable summary of the behavior of this action. +* `glyph`: A single character which will be rendered in Open MCT Web's custom font set as an icon for this action. ## Capabilities Category -Capabilities are exposed by domain objects (e.g. via the `getCapability` method) +Capabilities are exposed by domain objects (e.g. via the `getCapability` method) but most commonly originate as extensions of this category. -Extension definitions for capabilities should include both an implementation, -and a property named key whose value should be a string used as a -machine-readable identifier for that capability, e.g. when passed as the +Extension definitions for capabilities should include both an implementation, +and a property named key whose value should be a string used as a +machine-readable identifier for that capability, e.g. when passed as the argument to a domain object's `getCapability(key)` call. - -A capability's implementation should have methods specific to that capability; -that is, there is no common format for capability implementations, aside from + +A capability's implementation should have methods specific to that capability; +that is, there is no common format for capability implementations, aside from support for invocation via the `useCapability` shorthand. -A capability's implementation will take a single argument (in addition to any -declared dependencies), which is the domain object that will expose that +A capability's implementation will take a single argument (in addition to any +declared dependencies), which is the domain object that will expose that capability. -A capability's implementation may also expose a static method `appliesTo(model)` -which should return a boolean value, and will be used by the platform to filter -down capabilities to those which should be exposed by specific domain objects, -based on their domain object models. - +A capability's implementation may also expose a static method `appliesTo(model)` +which should return a boolean value, and will be used by the platform to filter +down capabilities to those which should be exposed by specific domain objects, +based on their domain object models. + ## Controls Category -Controls provide options for the `mct-control` directive. - +Controls provide options for the `mct-control` directive. + Six standard control types are included in the forms bundle: * `textfield`: An area to enter plain text. @@ -909,94 +909,94 @@ Six standard control types are included in the forms bundle: * `checkbox`: A box which may be checked/unchecked. * `color`: A color picker. * `button`: A button. -* `datetime`: An input for UTC date/time entry; gives result as a UNIX -timestamp, in milliseconds since start of 1970, UTC. +* `datetime`: An input for UTC date/time entry; gives result as a UNIX +timestamp, in milliseconds since start of 1970, UTC. -New controls may be added as extensions of the controls category. Extensions of -this category have two properties: +New controls may be added as extensions of the controls category. Extensions of +this category have two properties: -* `key`: The symbolic name for this control (matched against the control field +* `key`: The symbolic name for this control (matched against the control field in rows of the form structure). -* `templateUrl`: The URL to the control's Angular template, relative to the -resources directory of the bundle which exposes the extension. +* `templateUrl`: The URL to the control's Angular template, relative to the +resources directory of the bundle which exposes the extension. -Within the template for a control, the following variables will be included in +Within the template for a control, the following variables will be included in scope: -* `ngModel`: The model where form input will be stored. Notably we also need to -look at field (see below) to determine which field in the model should be -modified. +* `ngModel`: The model where form input will be stored. Notably we also need to +look at field (see below) to determine which field in the model should be +modified. * `ngRequired`: True if input is required. * `ngPattern`: The pattern to match against (for text entry) -* `options`: The options for this control, as passed from the `options` property -of an individual row definition. -* `field`: Name of the field in `ngModel` which will hold the value for this -control. +* `options`: The options for this control, as passed from the `options` property +of an individual row definition. +* `field`: Name of the field in `ngModel` which will hold the value for this +control. ## Gestures Category -A _gesture_ is a user action which can be taken upon a representation of a -domain object. +A _gesture_ is a user action which can be taken upon a representation of a +domain object. Examples of gestures included in the platform are: -* `drag`: For representations that can be used to initiate drag-and-drop +* `drag`: For representations that can be used to initiate drag-and-drop composition. -* `drop`: For representations that can be drop targets for drag-and-drop -composition. -* `menu`: For representations that can be used to pop up a context menu. - -Gesture definitions have a property `key` which is used as a machine-readable -identifier for the gesture (e.g. `drag`, `drop`, `menu` above.) - -A gesture's implementation is instantiated once per representation that uses the -gesture. This class will receive the jqLite-wrapped `mct-representation` element -and the domain object being represented as arguments, and should do any -necessary "wiring" (e.g. listening for events) during its constructor call. The -gesture's implementation may also expose an optional `destroy()` method which -will be called when the gesture should be removed, to avoid memory leaks by way +* `drop`: For representations that can be drop targets for drag-and-drop +composition. +* `menu`: For representations that can be used to pop up a context menu. + +Gesture definitions have a property `key` which is used as a machine-readable +identifier for the gesture (e.g. `drag`, `drop`, `menu` above.) + +A gesture's implementation is instantiated once per representation that uses the +gesture. This class will receive the jqLite-wrapped `mct-representation` element +and the domain object being represented as arguments, and should do any +necessary "wiring" (e.g. listening for events) during its constructor call. The +gesture's implementation may also expose an optional `destroy()` method which +will be called when the gesture should be removed, to avoid memory leaks by way of unremoved listeners. ## Indicators Category -An indicator is an element that should appear in the status area at the bottom -of a running Open MCT Web client instance. +An indicator is an element that should appear in the status area at the bottom +of a running Open MCT Web client instance. -### Standard Indicators - -Indicators which wish to appear in the common form of an icon-text pair should +### Standard Indicators + +Indicators which wish to appear in the common form of an icon-text pair should provide implementations with the following methods: -* `getText()`: Provides the human-readable text that will be displayed for this -indicator. -* `getGlyph()`: Provides a single-character string that will be displayed as an -icon in Open MCT Web's custom font set. -* `getDescription()`: Provides a human-readable summary of the current state of -this indicator; will be displayed in a tooltip on hover. -* `getClass()`: Get a CSS class that will be applied to this indicator. -* `getTextClass()`: Get a CSS class that will be applied to this indicator's -text portion. -* `getGlyphClass()`: Get a CSS class that will be applied to this indicator's -icon portion. -* `configure()`: If present, a configuration icon will appear to the right of -this indicator, and clicking it will invoke this method. - -Note that all methods are optional, and are called directly from an Angular -template, so they should be appropriate to run during digest cycles. +* `getText()`: Provides the human-readable text that will be displayed for this +indicator. +* `getGlyph()`: Provides a single-character string that will be displayed as an +icon in Open MCT Web's custom font set. +* `getDescription()`: Provides a human-readable summary of the current state of +this indicator; will be displayed in a tooltip on hover. +* `getClass()`: Get a CSS class that will be applied to this indicator. +* `getTextClass()`: Get a CSS class that will be applied to this indicator's +text portion. +* `getGlyphClass()`: Get a CSS class that will be applied to this indicator's +icon portion. +* `configure()`: If present, a configuration icon will appear to the right of +this indicator, and clicking it will invoke this method. -### Custom Indicators +Note that all methods are optional, and are called directly from an Angular +template, so they should be appropriate to run during digest cycles. -Indicators which wish to have an arbitrary appearance (instead of following the -icon-text convention commonly used) may specify a `template` property in their -extension definition. The value of this property will be used as the `key` for -an `mct-include` directive (so should refer to an extension of category - templates .) This template will be rendered to the status area. Indicators of -this variety do not need to provide an implementation. +### Custom Indicators + +Indicators which wish to have an arbitrary appearance (instead of following the +icon-text convention commonly used) may specify a `template` property in their +extension definition. The value of this property will be used as the `key` for +an `mct-include` directive (so should refer to an extension of category + templates .) This template will be rendered to the status area. Indicators of +this variety do not need to provide an implementation. ## Licenses Category -The extension category `licenses` can be used to add entries into the 'Licensing -information' page, reachable from Open MCT Web's About dialog. +The extension category `licenses` can be used to add entries into the 'Licensing +information' page, reachable from Open MCT Web's About dialog. Licenses may have the following properties, all of which are strings: @@ -1005,1177 +1005,1179 @@ Licenses may have the following properties, all of which are strings: * `description`: Human-readable summary of the component. * `author`: Name or names of entities to which authorship should be attributed. * `copyright`: Copyright text to display for this component. -* `link`: URL to full license text. +* `link`: URL to full license text. ## Policies Category -Policies are used to handle decisions made using Open MCT Web's `policyService`; -examples of these decisions are determining the applicability of certain -actions, or checking whether or not a domain object of one type can contain a -domain object of a different type. See the section on the Policies for an +Policies are used to handle decisions made using Open MCT Web's `policyService`; +examples of these decisions are determining the applicability of certain +actions, or checking whether or not a domain object of one type can contain a +domain object of a different type. See the section on the Policies for an overview of Open MCT Web's policy model. A policy's extension definition should include: -* `category`: The machine-readable identifier for the type of policy decision -being supported here. For a list of categories supported by the platform, see -the section on Policies. Plugins may introduce and utilize additional policy -categories not in that list. -* `message`: Optional; a human-readable message describing the policy, intended -for display in situations where this specific policy has disallowed something. - -A policy's implementation should include a single method, `allow(candidate, -context)`. The specific types used for `candidate` and `context` vary by policy -category; in general, what is being asked is 'is this candidate allowed in this -context?' This method should return a boolean value. +* `category`: The machine-readable identifier for the type of policy decision +being supported here. For a list of categories supported by the platform, see +the section on Policies. Plugins may introduce and utilize additional policy +categories not in that list. +* `message`: Optional; a human-readable message describing the policy, intended +for display in situations where this specific policy has disallowed something. + +A policy's implementation should include a single method, `allow(candidate, +context)`. The specific types used for `candidate` and `context` vary by policy +category; in general, what is being asked is 'is this candidate allowed in this +context?' This method should return a boolean value. + +Open MCT Web's policy model requires consensus; a policy decision is allowed +when and only when all policies choose to allow it. As such, policies should +generally be written to reject a certain case, and allow (by returning `true`) +anything else. -Open MCT Web's policy model requires consensus; a policy decision is allowed -when and only when all policies choose to allow it. As such, policies should -generally be written to reject a certain case, and allow (by returning `true`) -anything else. - ## Representations Category -A representation is an Angular template used to display a domain object. The -`representations` extension category is used to add options for the -`mct-representation` directive. - +A representation is an Angular template used to display a domain object. The +`representations` extension category is used to add options for the +`mct-representation` directive. + A representation definition should include the following properties: -* `key`: The machine-readable name which identifies the representation. -* `templateUrl`: The path to the representation's Angular template. This path is -relative to the bundle's resources directory. -* `uses`: Optional; an array of capability names. Indicates that this -representation intends to use those capabilities of a domain object (via a -`useCapability` call), and expects to find the latest results of that -`useCapability` call in the scope of the presented template (under the same name -as the capability itself.) Note that, if `useCapability` returns a promise, this -will be resolved before being placed in the representation's scope. -* `gestures`: An array of keys identifying gestures (see the `gestures` -extension category) which should be available upon this representation. Examples -of gestures include `drag` (for representations that should act as draggable -sources for drag-drop operations) and `menu` (for representations which should -show a domain-object-specific context menu on right-click.) +* `key`: The machine-readable name which identifies the representation. +* `templateUrl`: The path to the representation's Angular template. This path is +relative to the bundle's resources directory. +* `uses`: Optional; an array of capability names. Indicates that this +representation intends to use those capabilities of a domain object (via a +`useCapability` call), and expects to find the latest results of that +`useCapability` call in the scope of the presented template (under the same name +as the capability itself.) Note that, if `useCapability` returns a promise, this +will be resolved before being placed in the representation's scope. +* `gestures`: An array of keys identifying gestures (see the `gestures` +extension category) which should be available upon this representation. Examples +of gestures include `drag` (for representations that should act as draggable +sources for drag-drop operations) and `menu` (for representations which should +show a domain-object-specific context menu on right-click.) ### Representation Scope -While _representations_ do not have implementations, per se, they do refer to -Angular templates which need to interact with information (e.g. the domain -object being represented) provided by the platform. This information is passed -in through the template's scope, such that simple representations may be created -by providing only templates. (More complex representations will need controllers +While _representations_ do not have implementations, per se, they do refer to +Angular templates which need to interact with information (e.g. the domain +object being represented) provided by the platform. This information is passed +in through the template's scope, such that simple representations may be created +by providing only templates. (More complex representations will need controllers which are referenced from templates. See [https://docs.angularjs.org/guide/controller ]() -for more information on controllers in Angular.) - +for more information on controllers in Angular.) + A representation's scope will contain: * `domainObject`: The represented domain object. * `model`: The domain object's model. -* `configuration`: An object containing configuration information for this -representation (an empty object if there is no saved configuration.) The -contents of this object are managed entirely by the view/representation which -receives it. -* `representation`: An empty object, useful as a 'scratch pad' for -representation state. -* `ngModel`: An object passed through the ng-model attribute of the -`mct-representation` , if any. -* `parameters`: An object passed through the parameters attribute of the -`mct-representation`, if any. -* Any capabilities requested by the uses property of the representation +* `configuration`: An object containing configuration information for this +representation (an empty object if there is no saved configuration.) The +contents of this object are managed entirely by the view/representation which +receives it. +* `representation`: An empty object, useful as a 'scratch pad' for +representation state. +* `ngModel`: An object passed through the ng-model attribute of the +`mct-representation` , if any. +* `parameters`: An object passed through the parameters attribute of the +`mct-representation`, if any. +* Any capabilities requested by the uses property of the representation definition. - + ## Representers Category -The `representers` extension category is used to add additional behavior to the -`mct-representation` directive. This extension category is intended primarily -for use internal to the platform. +The `representers` extension category is used to add additional behavior to the +`mct-representation` directive. This extension category is intended primarily +for use internal to the platform. -Unlike _representations_, which describe specific ways to represent domain -objects, _representers_ are used to modify or augment the process of -representing domain objects in general. For example, support for the _gestures_ +Unlike _representations_, which describe specific ways to represent domain +objects, _representers_ are used to modify or augment the process of +representing domain objects in general. For example, support for the _gestures_ extension category is added by a _representer_. -A representer needs only provide an implementation. When an `mct-representation` -is linked (see [https://docs.angularjs.org/guide/directive ]() or when the -domain object being represented changes, a new _representer_ of each declared -type is instantiated. The constructor arguments for a _representer_ are the same -as the arguments to the link function in an Angular directive: `scope` the -Angular scope for this representation; `element` the jqLite-wrapped -`mct-representation` element, and `attrs` a set of key-value pairs of that -element's attributes. _Representers_ may wish to populate the scope, attach +A representer needs only provide an implementation. When an `mct-representation` +is linked (see [https://docs.angularjs.org/guide/directive ]() or when the +domain object being represented changes, a new _representer_ of each declared +type is instantiated. The constructor arguments for a _representer_ are the same +as the arguments to the link function in an Angular directive: `scope` the +Angular scope for this representation; `element` the jqLite-wrapped +`mct-representation` element, and `attrs` a set of key-value pairs of that +element's attributes. _Representers_ may wish to populate the scope, attach event listeners to the element, etc. -This implementation must provide a single method, `destroy()`, which will be -invoked when the representer is no longer needed. +This implementation must provide a single method, `destroy()`, which will be +invoked when the representer is no longer needed. ## Roots Category -The extension category `roots` is used to provide root-level domain object -models. Root-level domain objects appear at the top-level of the tree hierarchy. -For example, the _My Items_ folder is added as an extension of this category. +The extension category `roots` is used to provide root-level domain object +models. Root-level domain objects appear at the top-level of the tree hierarchy. +For example, the _My Items_ folder is added as an extension of this category. Extensions of this category should have the following properties: * `id`: The machine-readable identifier for the domaiwn object being exposed. -* `model`: The model, as a JSON object, for the domain object being exposed. +* `model`: The model, as a JSON object, for the domain object being exposed. ## Stylesheets Category -The stylesheets extension category is used to add CSS files to style the -application. Extension definitions for this category should include one +The stylesheets extension category is used to add CSS files to style the +application. Extension definitions for this category should include one property: -* `stylesheetUrl`: Path and filename, including extension, for the stylesheet to -include. This path is relative to the bundle's resources folder (by default, -`res`) - -To control the order of CSS files, use priority (see the section on Extension -Definitions above.) +* `stylesheetUrl`: Path and filename, including extension, for the stylesheet to +include. This path is relative to the bundle's resources folder (by default, +`res`) +* `theme`: Optional; if present, this stylesheet will only be included if this +value matches the `THEME` constant. + +To control the order of CSS files, use priority (see the section on Extension +Definitions above.) ## Templates Category -The `templates` extension category is used to expose Angular templates under -symbolic identifiers. These can then be utilized using the `mct-include` -directive, which behaves similarly to `ng-include` except that it uses these +The `templates` extension category is used to expose Angular templates under +symbolic identifiers. These can then be utilized using the `mct-include` +directive, which behaves similarly to `ng-include` except that it uses these symbolic identifiers instead of paths. A template's extension definition should include the following properties: -* `key`: The machine-readable name which identifies this template, matched +* `key`: The machine-readable name which identifies this template, matched against the value given to the key attribute of the `mct-include` directive. -* `templateUrl`: The path to the relevant Angular template. This path is -relative to the bundle's resources directory. +* `templateUrl`: The path to the relevant Angular template. This path is +relative to the bundle's resources directory. -Note that, when multiple templates are present with the same key , the one with -the highest priority will be used from `mct-include`. This behavior can be used -to override templates exposed by the platform (to change the logo which appears +Note that, when multiple templates are present with the same key , the one with +the highest priority will be used from `mct-include`. This behavior can be used +to override templates exposed by the platform (to change the logo which appears in the bottom right, for instance.) -Templates do not have implementations. +Templates do not have implementations. ## Types Category -The types extension category describes types of domain objects which may +The types extension category describes types of domain objects which may appear within Open MCT Web. A type's extension definition should have the following properties: -* `key`: The machine-readable identifier for this domain object type. Will be +* `key`: The machine-readable identifier for this domain object type. Will be stored to and matched against the type property of domain object models. * `name`: The human-readable name for this domain object type. * `description`: A human-readable summary of this domain object type. -* `glyph`: A single character to be rendered as an icon in Open MCT Web's custom -font set. -* `model`: A domain object model, used as the initial state for created domain +* `glyph`: A single character to be rendered as an icon in Open MCT Web's custom +font set. +* `model`: A domain object model, used as the initial state for created domain objects of this type (before any properties are specified.) -* `features`: Optional; an array of strings describing features of this domain -object type. Currently, only creation is recognized by the platform; this is -used to determine that this type should appear in the Create menu. More -generally, this is used to support the `hasFeature(...)` method of the type -capability. +* `features`: Optional; an array of strings describing features of this domain +object type. Currently, only creation is recognized by the platform; this is +used to determine that this type should appear in the Create menu. More +generally, this is used to support the `hasFeature(...)` method of the type +capability. * `properties`: An array describing individual properties of this domain object -(as should appear in the _Create_ or the _Edit Properties_ dialog.) Each +(as should appear in the _Create_ or the _Edit Properties_ dialog.) Each property is described by an object containing the following properties: - * `control`: The key of the control (see `mct-control` and the `controls` - [extension category](#Controls)) to use for editing this property. - * `property`: A string which will be used as the name of the property in the - domain object's model that the value for this property should be stored - under. If this value should be stored in an object nested within the domain - object model, then property should be specified as an array of strings - identifying these nested objects and, finally, the property itself. - * other properties as appropriate for a control of this type (each - property's definition will also be passed in as the structure for its - control.) See documentation of mct-form for more detail on these + * `control`: The key of the control (see `mct-control` and the `controls` + [extension category](#Controls)) to use for editing this property. + * `property`: A string which will be used as the name of the property in the + domain object's model that the value for this property should be stored + under. If this value should be stored in an object nested within the domain + object model, then property should be specified as an array of strings + identifying these nested objects and, finally, the property itself. + * other properties as appropriate for a control of this type (each + property's definition will also be passed in as the structure for its + control.) See documentation of mct-form for more detail on these properties. - -Types do not have implementations. - -## Versions Category -The versions extension category is used to introduce line items in Open MCT -Web's About dialog. These should have the following properties: -* `name`: The name of this line item, as should appear in the left-hand side of +Types do not have implementations. + +## Versions Category +The versions extension category is used to introduce line items in Open MCT +Web's About dialog. These should have the following properties: + +* `name`: The name of this line item, as should appear in the left-hand side of the list of version information in the About dialog. -* `value`: The value which should appear to the right of the name in the About +* `value`: The value which should appear to the right of the name in the About dialog. -To control the ordering of line items within the About dialog, use `priority`. -(See section on [Extension Definitions](#ExtensionDefinitions) above.) +To control the ordering of line items within the About dialog, use `priority`. +(See section on [Extension Definitions](#ExtensionDefinitions) above.) + +This extension category does not have implementations. -This extension category does not have implementations. - ## Views Category -The views extension category is used to determine which options appear to the -user as available views of domain objects of specific types. A view's extension -definition has the same properties as a representation (and views can be +The views extension category is used to determine which options appear to the +user as available views of domain objects of specific types. A view's extension +definition has the same properties as a representation (and views can be utilized via `mct-representation`); additionally: * `name`: The human-readable name for this view type. * description : A human-readable summary of this view type. -* `glyph`: A single character to be rendered as an icon in Open MCT Web's custom +* `glyph`: A single character to be rendered as an icon in Open MCT Web's custom font set. -* `type`: Optional; if present, this representation is only applicable for +* `type`: Optional; if present, this representation is only applicable for domain object's of this type. -* `needs`: Optional array of strings; if present, this representation is only -applicable for domain objects which have the capabilities identified by these -strings. -* `delegation`: Optional boolean, intended to be used in conjunction with -`needs`; if present, allow required capabilities to be satisfied by means of +* `needs`: Optional array of strings; if present, this representation is only +applicable for domain objects which have the capabilities identified by these +strings. +* `delegation`: Optional boolean, intended to be used in conjunction with +`needs`; if present, allow required capabilities to be satisfied by means of capability delegation. (See [Delegation](#Delegation)) -* `toolbar`: Optional; a definition for the toolbar which may appear in a -toolbar when using this view in Edit mode. This should be specified as a -structure for mct-toolbar , with additional properties available for each item in -that toolbar: - * `property`: A property name. This will refer to a property in the view's - current selection; that property on the selected object will be modifiable - as the `ng-model` of the displayed control in the toolbar. If the value of - the property is a function, it will be used as a getter-setter (called with - no arguments to use as a getter, called with a value to use as a setter.) - * `method`: A method to invoke (again, on the selected object) from the - toolbar control. Useful particularly for buttons (which don't edit a single +* `toolbar`: Optional; a definition for the toolbar which may appear in a +toolbar when using this view in Edit mode. This should be specified as a +structure for mct-toolbar , with additional properties available for each item in +that toolbar: + * `property`: A property name. This will refer to a property in the view's + current selection; that property on the selected object will be modifiable + as the `ng-model` of the displayed control in the toolbar. If the value of + the property is a function, it will be used as a getter-setter (called with + no arguments to use as a getter, called with a value to use as a setter.) + * `method`: A method to invoke (again, on the selected object) from the + toolbar control. Useful particularly for buttons (which don't edit a single property, necessarily.) -### View Scope +### View Scope -Views do not have implementations, but do get the same properties in scope that -are provided for `representations`. +Views do not have implementations, but do get the same properties in scope that +are provided for `representations`. When a view is in Edit mode, this scope will additionally contain: -* `commit()`: A function which can be invoked to mark any changes to the view's +* `commit()`: A function which can be invoked to mark any changes to the view's configuration as ready to persist. -* `selection`: An object representing the current selection state. +* `selection`: An object representing the current selection state. -#### Selection State +#### Selection State -A view's selection state is, conceptually, a set of JavaScript objects. The -presence of methods/properties on these objects determine which toolbar controls -are visible, and what state they manage and/or behavior they invoke. +A view's selection state is, conceptually, a set of JavaScript objects. The +presence of methods/properties on these objects determine which toolbar controls +are visible, and what state they manage and/or behavior they invoke. -This set may contain up to two different objects: The _view proxy _, which is -used to make changes to the view as a whole, and the _ selected object _, which is -used to represent some state within the view. (Future versions of Open MCT Web -may support multiple selected objects.) +This set may contain up to two different objects: The _view proxy _, which is +used to make changes to the view as a whole, and the _ selected object _, which is +used to represent some state within the view. (Future versions of Open MCT Web +may support multiple selected objects.) -The `selection` object made available during Edit mode has the following -methods: +The `selection` object made available during Edit mode has the following +methods: -* `proxy([object])`: Get (or set, if called with an argument) the current view -proxy. -* `select(object)`: Make this object the selected object. -* `deselect()`: Clear the currently selected object. -* `get()`: Get the currently selected object. Returns undefined if there is no +* `proxy([object])`: Get (or set, if called with an argument) the current view +proxy. +* `select(object)`: Make this object the selected object. +* `deselect()`: Clear the currently selected object. +* `get()`: Get the currently selected object. Returns undefined if there is no currently selected object. -* `selected(object)`: Check if the JavaScript object is currently in the -selection set. Returns true if the object is either the currently selected -object, or the current view proxy. -* `all()`: Get an array of all objects in the selection state. Will include -either or both of the view proxy and selected object. +* `selected(object)`: Check if the JavaScript object is currently in the +selection set. Returns true if the object is either the currently selected +object, or the current view proxy. +* `all()`: Get an array of all objects in the selection state. Will include +either or both of the view proxy and selected object. # Directives -Open MCT Web defines several Angular directives that are intended for use both -internally within the platform, and by plugins. +Open MCT Web defines several Angular directives that are intended for use both +internally within the platform, and by plugins. -## Before Unload +## Before Unload -The `mct-before-unload` directive is used to listen for (and prompt for user -confirmation) of navigation changes in the browser. This includes reloading, -following links out of Open MCT Web, or changing routes. It is used to hook into -both `onbeforeunload` event handling as well as route changes from within +The `mct-before-unload` directive is used to listen for (and prompt for user +confirmation) of navigation changes in the browser. This includes reloading, +following links out of Open MCT Web, or changing routes. It is used to hook into +both `onbeforeunload` event handling as well as route changes from within Angular. -This directive is useable as an attribute. Its value should be an Angular -expression. When an action that would trigger an unload and/or route change -occurs, this Angular expression is evaluated. Its result should be a message to -display to the user to confirm their navigation change; if this expression -evaluates to a falsy value, no message will be displayed. - -## Chart +This directive is useable as an attribute. Its value should be an Angular +expression. When an action that would trigger an unload and/or route change +occurs, this Angular expression is evaluated. Its result should be a message to +display to the user to confirm their navigation change; if this expression +evaluates to a falsy value, no message will be displayed. -The `mct-chart` directive is used to support drawing of simple charts. It is -present to support the Plot view, and its functionality is limited to the +## Chart + +The `mct-chart` directive is used to support drawing of simple charts. It is +present to support the Plot view, and its functionality is limited to the functionality that is relevant for that view. -This directive is used at the element level and takes one attribute, `draw` -which is an Angular expression which will should evaluate to a drawing object. +This directive is used at the element level and takes one attribute, `draw` +which is an Angular expression which will should evaluate to a drawing object. This drawing object should contain the following properties: -* `dimensions`: The size, in logical coordinates, of the chart area. A -two-element array or numbers. -* `origin`: The position, in logical coordinates, of the lower-left corner of -the chart area. A two-element array or numbers. -* `lines`: An array of lines (e.g. as a plot line) to draw, where each line is -expressed as an object containing: - * `buffer`: A Float32Array containing points in the line, in logical - coordinates, in sequential x,y pairs. - * `color`: The color of the line, as a four-element RGBA array, where - each element is a number in the range of 0.0-1.0. - * `points`: The number of points in the line. -* `boxes`: An array of rectangles to draw in the chart area. Each is an object -containing: - * `start`: The first corner of the rectangle, as a two-element array of - numbers, in logical coordinates. - * `end`: The opposite corner of the rectangle, as a two-element array of - numbers, in logical coordinates. color : The color of the line, as a - four-element RGBA array, where each element is a number in the range of - 0.0-1.0. +* `dimensions`: The size, in logical coordinates, of the chart area. A +two-element array or numbers. +* `origin`: The position, in logical coordinates, of the lower-left corner of +the chart area. A two-element array or numbers. +* `lines`: An array of lines (e.g. as a plot line) to draw, where each line is +expressed as an object containing: + * `buffer`: A Float32Array containing points in the line, in logical + coordinates, in sequential x,y pairs. + * `color`: The color of the line, as a four-element RGBA array, where + each element is a number in the range of 0.0-1.0. + * `points`: The number of points in the line. +* `boxes`: An array of rectangles to draw in the chart area. Each is an object +containing: + * `start`: The first corner of the rectangle, as a two-element array of + numbers, in logical coordinates. + * `end`: The opposite corner of the rectangle, as a two-element array of + numbers, in logical coordinates. color : The color of the line, as a + four-element RGBA array, where each element is a number in the range of + 0.0-1.0. -While `mct-chart` is intended to support plots specifically, it does perform -some useful management of canvas objects (e.g. choosing between WebGL and Canvas -2D APIs for drawing based on browser support) so its usage is recommended when -its supported drawing primitives are sufficient for other charting tasks. - -## Container +While `mct-chart` is intended to support plots specifically, it does perform +some useful management of canvas objects (e.g. choosing between WebGL and Canvas +2D APIs for drawing based on browser support) so its usage is recommended when +its supported drawing primitives are sufficient for other charting tasks. -The `mct-container` is similar to the `mct-include` directive insofar as it allows -templates to be referenced by symbolic keys instead of by URL. Unlike +## Container + +The `mct-container` is similar to the `mct-include` directive insofar as it allows +templates to be referenced by symbolic keys instead of by URL. Unlike `mct-include` it supports transclusion. -Unlike `mct-include` `mct-container` accepts a key as a plain string attribute, +Unlike `mct-include` `mct-container` accepts a key as a plain string attribute, instead of as an Angular expression. ## Control -The `mct-control` directive is used to display user input elements. Several -controls are included with the platform to wrap default input types. This -directive is primarily intended for internal use by the `mct-form` and -`mct-toolbar` directives. +The `mct-control` directive is used to display user input elements. Several +controls are included with the platform to wrap default input types. This +directive is primarily intended for internal use by the `mct-form` and +`mct-toolbar` directives. -When using `mct-control` the attributes `ng-model` `ng-disabled` -`ng-required` and `ng-pattern` may also be used. These have the usual meaning -(as they would for an input element) except for `ng-model`; when used, it will -actually be `ngModel[field]` (see below) that is two-way bound by this control. -This allows `mct-control` elements to more easily delegate to other -`mct-control` instances, and also facilitates usage for generated forms. +When using `mct-control` the attributes `ng-model` `ng-disabled` +`ng-required` and `ng-pattern` may also be used. These have the usual meaning +(as they would for an input element) except for `ng-model`; when used, it will +actually be `ngModel[field]` (see below) that is two-way bound by this control. +This allows `mct-control` elements to more easily delegate to other +`mct-control` instances, and also facilitates usage for generated forms. -This directive supports the following additional attributes, all specified as +This directive supports the following additional attributes, all specified as Angular expressions: -* `key`: A machine-readable identifier for the specific type of control to +* `key`: A machine-readable identifier for the specific type of control to display. * `options`: A set of options to display in this control. -* `structure`: In practice, contains the definition object which describes this -form row or toolbar item. Used to pass additional control-specific parameters. -* `field`: The field in the `ngModel` under which to read/store the property -associated with this control. +* `structure`: In practice, contains the definition object which describes this +form row or toolbar item. Used to pass additional control-specific parameters. +* `field`: The field in the `ngModel` under which to read/store the property +associated with this control. ## Drag -The `mct-drag` directive is used to support drag-based gestures on HTML -elements. Note that this is not 'drag' in the 'drag-and-drop' sense, but 'drag' -in the more general 'mouse down, mouse move, mouse up' sense. +The `mct-drag` directive is used to support drag-based gestures on HTML +elements. Note that this is not 'drag' in the 'drag-and-drop' sense, but 'drag' +in the more general 'mouse down, mouse move, mouse up' sense. -This takes the form of three attributes: +This takes the form of three attributes: * `mct-drag`: An Angular expression to evaluate during drag movement. * `mct-drag-down`: An Angular expression to evaluate when the drag starts. * `mct-drag-up`: An Angular expression to evaluate when the drag ends. -In each case, a variable `delta` will be provided to the expression; this is a -two-element array or the horizontal and vertical pixel offset of the current -mouse position relative to the mouse position where dragging began. +In each case, a variable `delta` will be provided to the expression; this is a +two-element array or the horizontal and vertical pixel offset of the current +mouse position relative to the mouse position where dragging began. -## Form +## Form -The `mct-form` directive is used to generate forms using a declarative structure, -and to gather back user input. It is applicable at the element level and -supports the following attributes: +The `mct-form` directive is used to generate forms using a declarative structure, +and to gather back user input. It is applicable at the element level and +supports the following attributes: -* `ng-model`: The object which should contain the full form input. Individual -fields in this model are bound to individual controls; the names used for these +* `ng-model`: The object which should contain the full form input. Individual +fields in this model are bound to individual controls; the names used for these fields are provided in the form structure (see below). -* `structure`: The structure of the form; e.g. sections, rows, their names, and -so forth. The value of this attribute should be an Angular expression. -* `name`: The name in the containing scope under which to publish form -"meta-state", e.g. `$valid` `$dirty` etc. This is as the behavior of `ng-form`. -Passed as plain text in the attribute. +* `structure`: The structure of the form; e.g. sections, rows, their names, and +so forth. The value of this attribute should be an Angular expression. +* `name`: The name in the containing scope under which to publish form +"meta-state", e.g. `$valid` `$dirty` etc. This is as the behavior of `ng-form`. +Passed as plain text in the attribute. -### Form Structure +### Form Structure -Forms in Open MCT Web have a common structure to permit consistent display. A -form is broken down into sections, which will be displayed in groups; each -section is broken down into rows, each of which provides a control for a single -property. Input from this form is two-way bound to the object passed via -`ng-model`. +Forms in Open MCT Web have a common structure to permit consistent display. A +form is broken down into sections, which will be displayed in groups; each +section is broken down into rows, each of which provides a control for a single +property. Input from this form is two-way bound to the object passed via +`ng-model`. A form's structure is represented by a JavaScript object in the following form: - - { - "name": ... title to display for the form, as a string ..., + + { + "name": ... title to display for the form, as a string ..., "sections": [ - { - "name": ... title to display for the section ..., - "rows": [ - { + { + "name": ... title to display for the section ..., + "rows": [ + { "name": ... title to display for this row ..., - "control": ... symbolic key for the control ..., - "key": ... field name in ng-model ... - "pattern": ... optional, reg exp to match against ... - "required": ... optional boolean ... - "options": [ - "name": ... name to display (e.g. in a select) ..., - "value": ... value to store in the model ... - ] - }, - ... and other rows ... - ] - }, - ... and other sections ... - ] - } + "control": ... symbolic key for the control ..., + "key": ... field name in ng-model ... + "pattern": ... optional, reg exp to match against ... + "required": ... optional boolean ... + "options": [ + "name": ... name to display (e.g. in a select) ..., + "value": ... value to store in the model ... + ] + }, + ... and other rows ... + ] + }, + ... and other sections ... + ] + } -Note that `pattern` may be specified as a string, to simplify storing for -structures as JSON when necessary. The string should be given in a form -appropriate to pass to a `RegExp` constructor. +Note that `pattern` may be specified as a string, to simplify storing for +structures as JSON when necessary. The string should be given in a form +appropriate to pass to a `RegExp` constructor. -### Form Controls +### Form Controls -A few standard control types are included in the platform/forms bundle: +A few standard control types are included in the platform/forms bundle: -* `textfield`: An area to enter plain text. -* `select`: A drop-down list of options. -* `checkbox`: A box which may be checked/unchecked. -* `color`: A color picker. -* `button`: A button. -* `datetime`: An input for UTC date/time entry; gives result as a UNIX -timestamp, in milliseconds since start of 1970, UTC. +* `textfield`: An area to enter plain text. +* `select`: A drop-down list of options. +* `checkbox`: A box which may be checked/unchecked. +* `color`: A color picker. +* `button`: A button. +* `datetime`: An input for UTC date/time entry; gives result as a UNIX +timestamp, in milliseconds since start of 1970, UTC. -## Include +## Include -The `mct-include` directive is similar to ng-include , except that it takes a -symbolic identifier for a template instead of a URL. Additionally, templates -included via mct-include will have an isolated scope. +The `mct-include` directive is similar to ng-include , except that it takes a +symbolic identifier for a template instead of a URL. Additionally, templates +included via mct-include will have an isolated scope. -The directive should be used at the element level and supports the following -attributes, all of which are specified as Angular expressions: - -* `key`: Machine-readable identifier for the template (of extension category -templates ) to be displayed. -* `ng-model`: _Optional_; will be passed into the template's scope as `ngModel`. -Intended usage is for two-way bound user input. -* `parameters`: _Optional_; will be passed into the template's scope as -parameters. Intended usage is for template-specific display parameters. - -## Representation - -The `mct-representation` directive is used to include templates which -specifically represent domain objects. Usage is similar to `mct-include`. - -The directive should be used at the element level and supports the following +The directive should be used at the element level and supports the following attributes, all of which are specified as Angular expressions: -* `key`: Machine-readable identifier for the representation (of extension -category _representations_ or _views_ ) to be displayed. -* `mct-object`: The domain object being represented. -* `ng-model`: Optional; will be passed into the template's scope as `ngModel`. -Intended usage is for two-way bound user input. -* `parameters`: Optional; will be passed into the template's scope as -parameters . Intended usage is for template-specific display parameters. +* `key`: Machine-readable identifier for the template (of extension category +templates ) to be displayed. +* `ng-model`: _Optional_; will be passed into the template's scope as `ngModel`. +Intended usage is for two-way bound user input. +* `parameters`: _Optional_; will be passed into the template's scope as +parameters. Intended usage is for template-specific display parameters. -## Resize +## Representation -The `mct-resize` directive is used to monitor the size of an HTML element. It is -specified as an attribute whose value is an Angular expression that will be -evaluated when the size of the HTML element changes. This expression will be -provided a single variable, `bounds` which is an object containing two +The `mct-representation` directive is used to include templates which +specifically represent domain objects. Usage is similar to `mct-include`. + +The directive should be used at the element level and supports the following +attributes, all of which are specified as Angular expressions: + +* `key`: Machine-readable identifier for the representation (of extension +category _representations_ or _views_ ) to be displayed. +* `mct-object`: The domain object being represented. +* `ng-model`: Optional; will be passed into the template's scope as `ngModel`. +Intended usage is for two-way bound user input. +* `parameters`: Optional; will be passed into the template's scope as +parameters . Intended usage is for template-specific display parameters. + +## Resize + +The `mct-resize` directive is used to monitor the size of an HTML element. It is +specified as an attribute whose value is an Angular expression that will be +evaluated when the size of the HTML element changes. This expression will be +provided a single variable, `bounds` which is an object containing two properties, `width` and `height` describing the size in pixels of the element. -When using this directive, an attribute `mct-resize-interval` may optionally be -provided. Its value is an Angular expression describing the number of -milliseconds to wait before next checking the size of the HTML element; this -expression is evaluated when the directive is linked and reevaluated whenever +When using this directive, an attribute `mct-resize-interval` may optionally be +provided. Its value is an Angular expression describing the number of +milliseconds to wait before next checking the size of the HTML element; this +expression is evaluated when the directive is linked and reevaluated whenever the size is checked. -## Scroll +## Scroll -The `mct-scroll-x` and `mct-scroll-y` directives are used to both monitor and -control the horizontal and vertical scroll bar state of an element, -respectively. They are intended to be used as attributes whose values are +The `mct-scroll-x` and `mct-scroll-y` directives are used to both monitor and +control the horizontal and vertical scroll bar state of an element, +respectively. They are intended to be used as attributes whose values are assignable Angular expressions which two-way bind to the scroll bar state. ## Toolbar -The `mct-toolbar` directive is used to generate toolbars using a declarative -structure, and to gather back user input. It is applicable at the element level -and supports the following attributes: +The `mct-toolbar` directive is used to generate toolbars using a declarative +structure, and to gather back user input. It is applicable at the element level +and supports the following attributes: -* `ng-model`: The object which should contain the full toolbar input. Individual -fields in this model are bound to individual controls; the names used for these -fields are provided in the form structure (see below). -* `structure`: The structure of the toolbar; e.g. sections, rows, their names, and +* `ng-model`: The object which should contain the full toolbar input. Individual +fields in this model are bound to individual controls; the names used for these +fields are provided in the form structure (see below). +* `structure`: The structure of the toolbar; e.g. sections, rows, their names, and so forth. The value of this attribute should be an Angular expression. -* `name`: The name in the containing scope under which to publish form -"meta-state", e.g. `$valid`, `$dirty` etc. This is as the behavior of -`ng-form`. Passed as plain text in the attribute. +* `name`: The name in the containing scope under which to publish form +"meta-state", e.g. `$valid`, `$dirty` etc. This is as the behavior of +`ng-form`. Passed as plain text in the attribute. -Toolbars support the same control options as forms. +Toolbars support the same control options as forms. -### Toolbar Structure +### Toolbar Structure -A toolbar's structure is defined similarly to forms, except instead of rows -there are items . +A toolbar's structure is defined similarly to forms, except instead of rows +there are items . - { - "name": ... title to display for the form, as a string ..., - "sections": [ - { - "name": ... title to display for the section ..., - "items": [ - { - "name": ... title to display for this row ..., - "control": ... symbolic key for the control ..., - "key": ... field name in ng-model ... - "pattern": ... optional, reg exp to match against ... - "required": ... optional boolean ... - "options": [ - "name": ... name to display (e.g. in a select) ..., - "value": ... value to store in the model ... - ], - "disabled": ... true if control should be disabled ... - "size": ... size of the control (for textfields) ... - "click": ... function to invoke (for buttons) ... - "glyph": ... glyph to display (for buttons) ... - "text": ... text within control (for buttons) ... - }, - ... and other rows ... - ] - }, - ... and other sections ... - ] + { + "name": ... title to display for the form, as a string ..., + "sections": [ + { + "name": ... title to display for the section ..., + "items": [ + { + "name": ... title to display for this row ..., + "control": ... symbolic key for the control ..., + "key": ... field name in ng-model ... + "pattern": ... optional, reg exp to match against ... + "required": ... optional boolean ... + "options": [ + "name": ... name to display (e.g. in a select) ..., + "value": ... value to store in the model ... + ], + "disabled": ... true if control should be disabled ... + "size": ... size of the control (for textfields) ... + "click": ... function to invoke (for buttons) ... + "glyph": ... glyph to display (for buttons) ... + "text": ... text within control (for buttons) ... + }, + ... and other rows ... + ] + }, + ... and other sections ... + ] } -# Services +# Services -The Open MCT Web platform provides a variety of services which can be retrieved -and utilized via dependency injection. These services fall into two categories: +The Open MCT Web platform provides a variety of services which can be retrieved +and utilized via dependency injection. These services fall into two categories: -* _Composite Services_ are defined by a set of components extensions; plugins may -introduce additional components with matching interfaces to extend or augment -the functionality of the composed service. (See the Framework section on -Composite Services.) -* _Other services_ which are defined as standalone service objects; these can be -utilized by plugins but are not intended to be modified or augmented. +* _Composite Services_ are defined by a set of components extensions; plugins may +introduce additional components with matching interfaces to extend or augment +the functionality of the composed service. (See the Framework section on +Composite Services.) +* _Other services_ which are defined as standalone service objects; these can be +utilized by plugins but are not intended to be modified or augmented. ## Composite Type Services -This section describes the composite services exposed by Open MCT Web, -specifically focusing on their interface and contract. - -In many cases, the platform will include a provider for a service which consumes -a specific extension category; for instance, the `actionService` depends on -`actions[]` and will expose available actions based on the rules defined for -that extension category. +This section describes the composite services exposed by Open MCT Web, +specifically focusing on their interface and contract. -In these cases, it will usually be simpler to add a new extension of a given -category (e.g. of category `actions`) even when the same behavior could be -introduced by a service component (e.g. an extension of category `components` -where `provides` is `actionService` and `type` is `provider`.) +In many cases, the platform will include a provider for a service which consumes +a specific extension category; for instance, the `actionService` depends on +`actions[]` and will expose available actions based on the rules defined for +that extension category. + +In these cases, it will usually be simpler to add a new extension of a given +category (e.g. of category `actions`) even when the same behavior could be +introduced by a service component (e.g. an extension of category `components` +where `provides` is `actionService` and `type` is `provider`.) + +Occasionally, the extension category does not provide enough expressive power to +achieve a desired result. For instance, the Create menu is populated with +`create` actions, where one such action exists for each creatable type. Since +the framework does not provide a declarative means to introduce a new action per +type declaratively, the platform implements this explicitly in an `actionService` +component of type `provider`. Plugins may use a similar approach when the normal +extension mechanism is insufficient to achieve a desired result. -Occasionally, the extension category does not provide enough expressive power to -achieve a desired result. For instance, the Create menu is populated with -`create` actions, where one such action exists for each creatable type. Since -the framework does not provide a declarative means to introduce a new action per -type declaratively, the platform implements this explicitly in an `actionService` -component of type `provider`. Plugins may use a similar approach when the normal -extension mechanism is insufficient to achieve a desired result. - ### Action Service -The [Action Service](../architecture/platform#action-service) (`actionService`) -provides `Action` instances which are applicable in specific contexts. See Core -API for additional notes on the interface for actions. The `actionService` has -the following interface: +The [Action Service](../architecture/platform#action-service) (`actionService`) +provides `Action` instances which are applicable in specific contexts. See Core +API for additional notes on the interface for actions. The `actionService` has +the following interface: -* `getActions(context)`: Returns an array of Action objects which are applicable -in the specified action context. +* `getActions(context)`: Returns an array of Action objects which are applicable +in the specified action context. -### Capability Service +### Capability Service -The [Capability Service](../architecture/platform#capability-service) (`capabilityService`) -provides constructors for capabilities which will be exposed for a given domain -object. +The [Capability Service](../architecture/platform#capability-service) (`capabilityService`) +provides constructors for capabilities which will be exposed for a given domain +object. -The capabilityService has the following interface: +The capabilityService has the following interface: -* `getCapabilities(model)`: Returns a an object containing key-value pairs, -representing capabilities which should be exposed by the domain object with this -model. Keys in this object are the capability keys (as used in a -`getCapability(...)` call) and values are either: - * Functions, in which case they will be used as constructors, which will - receive the domain object instance to which the capability applies as their - sole argument.The resulting object will be provided as the result of a - domain object's `getCapability(...)` call. Note that these instances are cached - by each object, but may be recreated when an object is mutated. - * Other objects, which will be used directly as the result of a domain - object's `getCapability(...)` call. +* `getCapabilities(model)`: Returns a an object containing key-value pairs, +representing capabilities which should be exposed by the domain object with this +model. Keys in this object are the capability keys (as used in a +`getCapability(...)` call) and values are either: + * Functions, in which case they will be used as constructors, which will + receive the domain object instance to which the capability applies as their + sole argument.The resulting object will be provided as the result of a + domain object's `getCapability(...)` call. Note that these instances are cached + by each object, but may be recreated when an object is mutated. + * Other objects, which will be used directly as the result of a domain + object's `getCapability(...)` call. -### Dialog Service +### Dialog Service -The `dialogService` provides a means for requesting user input via a modal -dialog. It has the following interface: +The `dialogService` provides a means for requesting user input via a modal +dialog. It has the following interface: -* `getUserInput(formStructure, formState)`: Prompt the user to fill out a form. -The first argument describes the form's structure (as will be passed to - mct-form ) while the second argument contains the initial state of that form. -This returns a Promise for the state of the form after the user has filled it -in; this promise will be rejected if the user cancels input. -* `getUserChoice(dialogStructure)`: Prompt the user to make a single choice from -a set of options, which (in the platform implementation) will be expressed as -buttons in the displayed dialog. Returns a Promise for the user's choice, which -will be rejected if the user cancels input. +* `getUserInput(formStructure, formState)`: Prompt the user to fill out a form. +The first argument describes the form's structure (as will be passed to + mct-form ) while the second argument contains the initial state of that form. +This returns a Promise for the state of the form after the user has filled it +in; this promise will be rejected if the user cancels input. +* `getUserChoice(dialogStructure)`: Prompt the user to make a single choice from +a set of options, which (in the platform implementation) will be expressed as +buttons in the displayed dialog. Returns a Promise for the user's choice, which +will be rejected if the user cancels input. -### Dialog Structure +### Dialog Structure -The object passed as the `dialogStructure` to `getUserChoice` should have the +The object passed as the `dialogStructure` to `getUserChoice` should have the following properties: -* `title`: The title to display at the top of the dialog. -* `hint`: Short message to display below the title. -* `template`: Identifying key (as will be passed to mct-include ) for the -template which will be used to populate the inner area of the dialog. -* `model`: Model to pass in the ng-model attribute of mct-include . -* `parameters`: Parameters to pass in the parameters attribute of mct-include . -* `options`: An array of options describing each button at the bottom. Each +* `title`: The title to display at the top of the dialog. +* `hint`: Short message to display below the title. +* `template`: Identifying key (as will be passed to mct-include ) for the +template which will be used to populate the inner area of the dialog. +* `model`: Model to pass in the ng-model attribute of mct-include . +* `parameters`: Parameters to pass in the parameters attribute of mct-include . +* `options`: An array of options describing each button at the bottom. Each option may have the following properties: - * `name`: Human-readable name to display in the button. - * `key`: Machine-readable key, to pass as the result of the resolved promise - when clicked. + * `name`: Human-readable name to display in the button. + * `key`: Machine-readable key, to pass as the result of the resolved promise + when clicked. * `description`: Description to show in tooltip on hover. -### Domain Object Service +### Domain Object Service The [Object Service](../architecture/platform.md#object-service) (`objectService`) provides domain object instances. It has the following interface: -* `getObjects(ids)`: For the provided array of domain object identifiers, -returns a Promise for an object containing key-value pairs, where keys are -domain object identifiers and values are corresponding DomainObject instances. -Note that the result may contain a superset or subset of the objects requested. +* `getObjects(ids)`: For the provided array of domain object identifiers, +returns a Promise for an object containing key-value pairs, where keys are +domain object identifiers and values are corresponding DomainObject instances. +Note that the result may contain a superset or subset of the objects requested. -### Gesture Service +### Gesture Service -The `gestureService` is used to attach gestures (see extension category gestures) +The `gestureService` is used to attach gestures (see extension category gestures) to representations. It has the following interface: -* `attachGestures(element, domainObject, keys)`: Attach gestures specified by -the provided gesture keys (an array of strings) to this jqLite-wrapped HTML -element , which represents the specified domainObject . Returns an object with a -single method `destroy()`, to be invoked when it is time to detach these -gestures. +* `attachGestures(element, domainObject, keys)`: Attach gestures specified by +the provided gesture keys (an array of strings) to this jqLite-wrapped HTML +element , which represents the specified domainObject . Returns an object with a +single method `destroy()`, to be invoked when it is time to detach these +gestures. -### Model Service +### Model Service -The [Model Service](../architecture/platform.md#model-service) (`modelService`) -provides domain object models. It has the following interface: +The [Model Service](../architecture/platform.md#model-service) (`modelService`) +provides domain object models. It has the following interface: -* `getModels(ids)`: For the provided array of domain object identifiers, returns -a Promise for an object containing key-value pairs, where keys are domain object -identifiers and values are corresponding domain object models. Note that the -result may contain a superset or subset of the models requested. +* `getModels(ids)`: For the provided array of domain object identifiers, returns +a Promise for an object containing key-value pairs, where keys are domain object +identifiers and values are corresponding domain object models. Note that the +result may contain a superset or subset of the models requested. -### Persistence Service +### Persistence Service The [Persistence Service](../architecture/platform.md#persistence-service) (`persistenceService`) -provides the ability to load/store JavaScript objects -(presumably serializing/deserializing to JSON in the process.) This is used -primarily to store domain object models. It has the following interface: +provides the ability to load/store JavaScript objects +(presumably serializing/deserializing to JSON in the process.) This is used +primarily to store domain object models. It has the following interface: -* `listSpaces()`: Returns a Promise for an array of strings identifying the -different persistence spaces this service supports. Spaces are intended to be -used to distinguish between different underlying persistence stores, to allow -these to live side by side. -* `listObjects()`: Returns a Promise for an array of strings identifying all -documents stored in this persistence service. -* `createObject(space, key, value)`: Create a new document in the specified -persistence space , identified by the specified key , the contents of which shall -match the specified value . Returns a promise that will be rejected if creation -fails. -* `readObject(space, key)`: Read an existing document in the specified -persistence space , identified by the specified key . Returns a promise for the -specified document; this promise will resolve to undefined if the document does -not exist. -* `updateObject(space, key, value)`: Update an existing document in the -specified persistence space , identified by the specified key , such that its -contents match the specified value . Returns a promise that will be rejected if -the update fails. -* `deleteObject(space, key)`: Delete an existing document from the specified -persistence space , identified by the specified key . Returns a promise which will -be rejected if deletion fails. +* `listSpaces()`: Returns a Promise for an array of strings identifying the +different persistence spaces this service supports. Spaces are intended to be +used to distinguish between different underlying persistence stores, to allow +these to live side by side. +* `listObjects()`: Returns a Promise for an array of strings identifying all +documents stored in this persistence service. +* `createObject(space, key, value)`: Create a new document in the specified +persistence space , identified by the specified key , the contents of which shall +match the specified value . Returns a promise that will be rejected if creation +fails. +* `readObject(space, key)`: Read an existing document in the specified +persistence space , identified by the specified key . Returns a promise for the +specified document; this promise will resolve to undefined if the document does +not exist. +* `updateObject(space, key, value)`: Update an existing document in the +specified persistence space , identified by the specified key , such that its +contents match the specified value . Returns a promise that will be rejected if +the update fails. +* `deleteObject(space, key)`: Delete an existing document from the specified +persistence space , identified by the specified key . Returns a promise which will +be rejected if deletion fails. -### Policy Service +### Policy Service -The [Policy Service](../architecture/platform.md#policy-service) (`policyService`) -may be used to determine whether or not certain behaviors are -allowed within the application. It has the following interface: - -* `allow(category, candidate, context, [callback])`: Check if this decision -should be allowed. Returns a boolean. Its arguments are interpreted as: - * `category`: A string identifying which kind of decision is being made. See - the [section on Categories](#PolicyCategories) for categories supported by - the platform; plugins may define and utilize policies of additional - categories, as well. - * `candidate`: An object representing the thing which shall or shall not be - allowed. Usually, this will be an instance of an extension of the category - defined above. This does need to be the case; additional policies which are - not specific to any extension may also be defined and consulted using unique - category identifiers. In this case, the type of the object delivered for the - candidate may be unique to the policy type. - * `context`: An object representing the context in which the decision is - occurring. Its contents are specific to each policy category. - * `callback`: Optional; a function to call if the policy decision is rejected. - This function will be called with the message string (which may be - undefined) of whichever individual policy caused the operation to fail. +The [Policy Service](../architecture/platform.md#policy-service) (`policyService`) +may be used to determine whether or not certain behaviors are +allowed within the application. It has the following interface: -### Telemetry Service +* `allow(category, candidate, context, [callback])`: Check if this decision +should be allowed. Returns a boolean. Its arguments are interpreted as: + * `category`: A string identifying which kind of decision is being made. See + the [section on Categories](#PolicyCategories) for categories supported by + the platform; plugins may define and utilize policies of additional + categories, as well. + * `candidate`: An object representing the thing which shall or shall not be + allowed. Usually, this will be an instance of an extension of the category + defined above. This does need to be the case; additional policies which are + not specific to any extension may also be defined and consulted using unique + category identifiers. In this case, the type of the object delivered for the + candidate may be unique to the policy type. + * `context`: An object representing the context in which the decision is + occurring. Its contents are specific to each policy category. + * `callback`: Optional; a function to call if the policy decision is rejected. + This function will be called with the message string (which may be + undefined) of whichever individual policy caused the operation to fail. + +### Telemetry Service The [Telemetry Service](../architecture/platform.md#telemetry-service) (`telemetryService`) -is used to acquire telemetry data. See the section on -Telemetry in Core API for more information on how both the arguments and -responses of this service are structured. +is used to acquire telemetry data. See the section on +Telemetry in Core API for more information on how both the arguments and +responses of this service are structured. -When acquiring telemetry for display, it is recommended that the -`telemetryHandler` service be used instead of this service. The -`telemetryHandler` has additional support for subscribing to and requesting -telemetry data associated with domain objects or groups of domain objects. See -the [Other Services](#Other-Services) section for more information. +When acquiring telemetry for display, it is recommended that the +`telemetryHandler` service be used instead of this service. The +`telemetryHandler` has additional support for subscribing to and requesting +telemetry data associated with domain objects or groups of domain objects. See +the [Other Services](#Other-Services) section for more information. The `telemetryService` has the following interface: -* `requestTelemetry(requests)`: Issue a request for telemetry, matching the -specified telemetry requests . Returns a _ Promise _ for a telemetry response +* `requestTelemetry(requests)`: Issue a request for telemetry, matching the +specified telemetry requests . Returns a _ Promise _ for a telemetry response object. -* `subscribe(callback, requests)`: Subscribe to real-time updates for telemetry, -matching the specified `requests`. The specified `callback` will be invoked with -telemetry response objects as they become available. This method returns a -function which can be invoked to terminate the subscription. +* `subscribe(callback, requests)`: Subscribe to real-time updates for telemetry, +matching the specified `requests`. The specified `callback` will be invoked with +telemetry response objects as they become available. This method returns a +function which can be invoked to terminate the subscription. -### Type Service +### Type Service -The [Type Service](../architecture/platform.md#type-service) (`typeService`) exposes +The [Type Service](../architecture/platform.md#type-service) (`typeService`) exposes domain object types. It has the following interface: -* `listTypes()`: Returns all domain object types supported in the application, +* `listTypes()`: Returns all domain object types supported in the application, as an array of `Type` instances. -* `getType(key)`: Returns the `Type` instance identified by the provided key, or -undefined if no such type exists. +* `getType(key)`: Returns the `Type` instance identified by the provided key, or +undefined if no such type exists. -### View Service +### View Service -The [View Service](../architecture/platform.md#view-service) (`viewService`) exposes +The [View Service](../architecture/platform.md#view-service) (`viewService`) exposes definitions for views of domain objects. It has the following interface: - -* `getViews(domainObject)`: Get an array of extension definitions of category -`views` which are valid and applicable to the specified `domainObject`. - + +* `getViews(domainObject)`: Get an array of extension definitions of category +`views` which are valid and applicable to the specified `domainObject`. + ## Other Services -### Drag and Drop +### Drag and Drop -The `dndService` provides information about the content of an active -drag-and-drop gesture within the application. It is intended to complement the -`DataTransfer` API of HTML5 drag-and-drop, by providing access to non-serialized -JavaScript objects being dragged, as well as by permitting inspection during -drag (which is normally prohibited by browsers for security reasons.) +The `dndService` provides information about the content of an active +drag-and-drop gesture within the application. It is intended to complement the +`DataTransfer` API of HTML5 drag-and-drop, by providing access to non-serialized +JavaScript objects being dragged, as well as by permitting inspection during +drag (which is normally prohibited by browsers for security reasons.) -The `dndService` has the following methods: +The `dndService` has the following methods: -* `setData(key, value)`: Set drag data associated with a given type, specified -by the `key` argument. -* `getData(key)`: Get drag data associated with a given type, specified by the -`key` argument. -* `removeData(key)`: Clear drag data associated with a given type, specified by -the `key` argument. +* `setData(key, value)`: Set drag data associated with a given type, specified +by the `key` argument. +* `getData(key)`: Get drag data associated with a given type, specified by the +`key` argument. +* `removeData(key)`: Clear drag data associated with a given type, specified by +the `key` argument. -### Navigation - -The _Navigation_ service provides information about the current navigation state -of the application; that is, which object is the user currently viewing? This -service merely tracks this state and notifies listeners; it does not take -immediate action when navigation changes, although its listeners might. +### Navigation + +The _Navigation_ service provides information about the current navigation state +of the application; that is, which object is the user currently viewing? This +service merely tracks this state and notifies listeners; it does not take +immediate action when navigation changes, although its listeners might. The `navigationService` has the following methods: -* `getNavigation()`: Get the current navigation state. Returns a `DomainObject`. -* `setNavigation(domainObject)`: Set the current navigation state. Returns a -`DomainObject`. -* `addListener(callback)`: Listen for changes in navigation state. The provided -`callback` should be a `Function` which takes a single `DomainObject` as an -argument. -* `removeListener(callback)`: Stop listening for changes in navigation state. -The provided `callback` should be a `Function` which has previously been passed +* `getNavigation()`: Get the current navigation state. Returns a `DomainObject`. +* `setNavigation(domainObject)`: Set the current navigation state. Returns a +`DomainObject`. +* `addListener(callback)`: Listen for changes in navigation state. The provided +`callback` should be a `Function` which takes a single `DomainObject` as an +argument. +* `removeListener(callback)`: Stop listening for changes in navigation state. +The provided `callback` should be a `Function` which has previously been passed to addListener . -### Now +### Now -The service now is a function which acts as a simple wrapper for `Date.now()`. -It is present mainly so that this functionality may be more easily mocked in -tests for scripts which use the current time. +The service now is a function which acts as a simple wrapper for `Date.now()`. +It is present mainly so that this functionality may be more easily mocked in +tests for scripts which use the current time. -### Telemetry Formatter +### Telemetry Formatter -The _Telemetry Formatter_ is a utility for formatting domain and range values -read from a telemetry series. +The _Telemetry Formatter_ is a utility for formatting domain and range values +read from a telemetry series. -`telemetryFormatter` has the following methods: +`telemetryFormatter` has the following methods: -* `formatDomainValue(value)`: Format the provided domain value (which will be -assumed to be a timestamp) for display; returns a string. -* `formatRangeValue(value)`: Format the provided range value (a number) for +* `formatDomainValue(value)`: Format the provided domain value (which will be +assumed to be a timestamp) for display; returns a string. +* `formatRangeValue(value)`: Format the provided range value (a number) for display; returns a string. -### Telemetry Handler +### Telemetry Handler -The _Telemetry Handler_ is a utility for retrieving telemetry data associated -with domain objects; it is particularly useful for dealing with cases where the -telemetry capability is delegated to contained objects (as occurs -in _Telemetry Panels_.) +The _Telemetry Handler_ is a utility for retrieving telemetry data associated +with domain objects; it is particularly useful for dealing with cases where the +telemetry capability is delegated to contained objects (as occurs +in _Telemetry Panels_.) -The `telemetryHandler` has the following methods: +The `telemetryHandler` has the following methods: -* `handle(domainObject, callback, [lossless])`: Subscribe to and issue future -requests for telemetry associated with the provided `domainObject`, invoking the -provided callback function when streaming data becomes available. Returns a -`TelemetryHandle` (see below.) +* `handle(domainObject, callback, [lossless])`: Subscribe to and issue future +requests for telemetry associated with the provided `domainObject`, invoking the +provided callback function when streaming data becomes available. Returns a +`TelemetryHandle` (see below.) -#### Telemetry Handle +#### Telemetry Handle -A TelemetryHandle has the following methods: +A TelemetryHandle has the following methods: -* `getTelemetryObjects()`: Get the domain objects (as a `DomainObject[]`) that -have a telemetry capability and are being handled here. Note that these are -looked up asynchronously, so this method may return an empty array if the -initial lookup is not yet completed. -* `promiseTelemetryObjects()`: As `getTelemetryObjects()`, but returns a Promise -that will be fulfilled when the lookup is complete. -* `unsubscribe()`: Unsubscribe to streaming telemetry updates associated with -this handle. -* `getDomainValue(domainObject)`: Get the most recent domain value received via -a streaming update for the specified `domainObject`. -* `getRangeValue(domainObject)`: Get the most recent range value received via a -streaming update for the specified `domainObject`. -* `getMetadata()`: Get metadata (as reported by the `getMetadata()` method of a -telemetry capability) associated with telemetry-providing domain objects. -Returns an array, which is in the same order as getTelemetryObjects() . -* `request(request, callback)`: Issue a new request for historical telemetry -data. The provided callback will be invoked when new data becomes available, -which may occur multiple times (e.g. if there are multiple domain objects.) It -will be invoked with the DomainObject for which a new series is available, and -the TelemetrySeries itself, in that order. -* `getSeries(domainObject)`: Get the latest `TelemetrySeries` (as resulted from +* `getTelemetryObjects()`: Get the domain objects (as a `DomainObject[]`) that +have a telemetry capability and are being handled here. Note that these are +looked up asynchronously, so this method may return an empty array if the +initial lookup is not yet completed. +* `promiseTelemetryObjects()`: As `getTelemetryObjects()`, but returns a Promise +that will be fulfilled when the lookup is complete. +* `unsubscribe()`: Unsubscribe to streaming telemetry updates associated with +this handle. +* `getDomainValue(domainObject)`: Get the most recent domain value received via +a streaming update for the specified `domainObject`. +* `getRangeValue(domainObject)`: Get the most recent range value received via a +streaming update for the specified `domainObject`. +* `getMetadata()`: Get metadata (as reported by the `getMetadata()` method of a +telemetry capability) associated with telemetry-providing domain objects. +Returns an array, which is in the same order as getTelemetryObjects() . +* `request(request, callback)`: Issue a new request for historical telemetry +data. The provided callback will be invoked when new data becomes available, +which may occur multiple times (e.g. if there are multiple domain objects.) It +will be invoked with the DomainObject for which a new series is available, and +the TelemetrySeries itself, in that order. +* `getSeries(domainObject)`: Get the latest `TelemetrySeries` (as resulted from a previous `request(...)` call) available for this domain object. # Models -Domain object models in Open MCT Web are JavaScript objects describing the -persistent state of the domain objects they describe. Their contents include a -mix of commonly understood metadata attributes; attributes which are recognized -by and/or determine the applicability of specific extensions; and properties -specific to given types. +Domain object models in Open MCT Web are JavaScript objects describing the +persistent state of the domain objects they describe. Their contents include a +mix of commonly understood metadata attributes; attributes which are recognized +by and/or determine the applicability of specific extensions; and properties +specific to given types. -## General Metadata +## General Metadata -Some properties of domain object models have a ubiquitous meaning through Open -MCT Web and can be utilized directly: +Some properties of domain object models have a ubiquitous meaning through Open +MCT Web and can be utilized directly: * `name`: The human-readable name of the domain object. -## Extension-specific Properties +## Extension-specific Properties -Other properties of domain object models have specific meaning imposed by other -extensions within the Open MCT Web platform. +Other properties of domain object models have specific meaning imposed by other +extensions within the Open MCT Web platform. -### Capability-specific Properties +### Capability-specific Properties -Some properties either trigger the presence/absence of certain capabilities, or +Some properties either trigger the presence/absence of certain capabilities, or are managed by specific capabilities: -* `composition`: An array of domain object identifiers that represents the -contents of this domain object (e.g. as will appear in the tree hierarchy.) -Understood by the composition capability; the presence or absence of this -property determines the presence or absence of that capability. -* `modified`: The timestamp (in milliseconds since the UNIX epoch) of the last -modification made to this domain object. Managed by the mutation capability. -* `persisted`: The timestamp (in milliseconds since the UNIX epoch) of the last -time when changes to this domain object were persisted. Managed by the - persistence capability. -* `relationships`: An object containing key-value pairs, where keys are symbolic -identifiers for relationship types, and values are arrays of domain object -identifiers. Used by the relationship capability; the presence or absence of -this property determines the presence or absence of that capability. -* `telemetry`: An object which serves as a template for telemetry requests -associated with this domain object (e.g. specifying `source` and `key`; see -Telemetry Requests under Core API.) Used by the telemetry capability; the -presence or absence of this property determines the presence or absence of that +* `composition`: An array of domain object identifiers that represents the +contents of this domain object (e.g. as will appear in the tree hierarchy.) +Understood by the composition capability; the presence or absence of this +property determines the presence or absence of that capability. +* `modified`: The timestamp (in milliseconds since the UNIX epoch) of the last +modification made to this domain object. Managed by the mutation capability. +* `persisted`: The timestamp (in milliseconds since the UNIX epoch) of the last +time when changes to this domain object were persisted. Managed by the + persistence capability. +* `relationships`: An object containing key-value pairs, where keys are symbolic +identifiers for relationship types, and values are arrays of domain object +identifiers. Used by the relationship capability; the presence or absence of +this property determines the presence or absence of that capability. +* `telemetry`: An object which serves as a template for telemetry requests +associated with this domain object (e.g. specifying `source` and `key`; see +Telemetry Requests under Core API.) Used by the telemetry capability; the +presence or absence of this property determines the presence or absence of that +capability. +* `type`: A string identifying the type of this domain object. Used by the `type` capability. -* `type`: A string identifying the type of this domain object. Used by the `type` -capability. - -### View Configurations -Persistent configurations for specific views of domain objects are stored in the -domain object model under the property configurations . This is an object -containing key-value pairs, where keys identify the view, and values are objects -containing view-specific (and view-managed) configuration properties. - -## Modifying Models -When interacting with a domain object's model, it is possible to make -modifications to it directly. __Don't!__ These changes may not be properly detected -by the platform, meaning that other representations of the domain object may not -be updated, changes may not be saved at the expected times, and generally, that -unexpected behavior may occur. Instead, use the `mutation` capability. +### View Configurations -# Capabilities +Persistent configurations for specific views of domain objects are stored in the +domain object model under the property configurations . This is an object +containing key-value pairs, where keys identify the view, and values are objects +containing view-specific (and view-managed) configuration properties. -Dynamic behavior associated with a domain object is expressed as capabilities. A -capability is a JavaScript object with an interface that is specific to the type -of capability in use. +## Modifying Models +When interacting with a domain object's model, it is possible to make +modifications to it directly. __Don't!__ These changes may not be properly detected +by the platform, meaning that other representations of the domain object may not +be updated, changes may not be saved at the expected times, and generally, that +unexpected behavior may occur. Instead, use the `mutation` capability. -Often, there is a relationship between capabilities and services. For instance, -there is an action capability and an actionService , and there is a telemetry -capability as well as a `telemetryService`. Typically, the pattern here is that -the capability will utilize the service for the specific domain object. +# Capabilities + +Dynamic behavior associated with a domain object is expressed as capabilities. A +capability is a JavaScript object with an interface that is specific to the type +of capability in use. + +Often, there is a relationship between capabilities and services. For instance, +there is an action capability and an actionService , and there is a telemetry +capability as well as a `telemetryService`. Typically, the pattern here is that +the capability will utilize the service for the specific domain object. + +When interacting with domain objects, it is generally preferable to use a +capability instead of a service when the option is available. Capability +interfaces are typically easier to use and/or more powerful in these situations. +Additionally, this usage provides a more robust substitutability mechanism; for +instance, one could configure a plugin such that it provided a totally new +implementation of a given capability which might not invoke the underlying +service, while user code which interacts with capabilities remains indifferent +to this detail. -When interacting with domain objects, it is generally preferable to use a -capability instead of a service when the option is available. Capability -interfaces are typically easier to use and/or more powerful in these situations. -Additionally, this usage provides a more robust substitutability mechanism; for -instance, one could configure a plugin such that it provided a totally new -implementation of a given capability which might not invoke the underlying -service, while user code which interacts with capabilities remains indifferent -to this detail. - ## Action Capability -The `action` capability is present for all domain objects. It allows applicable -`Action` instances to be retrieved and performed for specific domain objects. +The `action` capability is present for all domain objects. It allows applicable +`Action` instances to be retrieved and performed for specific domain objects. -For example: +For example: `domainObject.getCapability("action").perform("navigate"); ` - ...will initiate a navigate action upon the domain object, if an action with - key "navigate" is defined. - -This capability has the following interface: -* `getActions(context)`: Get the actions that are applicable in the specified -action `context`; the capability will fill in the `domainObject` field of this -context if necessary. If context is specified as a string, they will instead be + ...will initiate a navigate action upon the domain object, if an action with + key "navigate" is defined. + +This capability has the following interface: +* `getActions(context)`: Get the actions that are applicable in the specified +action `context`; the capability will fill in the `domainObject` field of this +context if necessary. If context is specified as a string, they will instead be used as the `key` of the action context. Returns an array of `Action` instances. -* `perform(context)`: Perform an action. This will find and perform the first -matching action available for the specified action context , filling in the -`domainObject` field as necessary. If `context` is specified as a string, they -will instead be used as the `key` of the action context. Returns a `Promise` for -the result of the action that was performed, or `undefined` if no matching action -was found. +* `perform(context)`: Perform an action. This will find and perform the first +matching action available for the specified action context , filling in the +`domainObject` field as necessary. If `context` is specified as a string, they +will instead be used as the `key` of the action context. Returns a `Promise` for +the result of the action that was performed, or `undefined` if no matching action +was found. ## Composition Capability -The `composition` capability provides access to domain objects that are -contained by this domain object. While the `composition` property of a domain -object's model describes these contents (by their identifiers), the -`composition` capability provides a means to load the corresponding -`DomainObject` instances in the same order. The absence of this property in the -model will result in the absence of this capability in the domain object. +The `composition` capability provides access to domain objects that are +contained by this domain object. While the `composition` property of a domain +object's model describes these contents (by their identifiers), the +`composition` capability provides a means to load the corresponding +`DomainObject` instances in the same order. The absence of this property in the +model will result in the absence of this capability in the domain object. -This capability has the following interface: +This capability has the following interface: * `invoke()`: Returns a `Promise` for an array of `DomainObject` instances. ## Delegation Capability -The delegation capability is used to communicate the intent of a domain object -to delegate responsibilities, which would normally handled by other -capabilities, to the domain objects in its composition. +The delegation capability is used to communicate the intent of a domain object +to delegate responsibilities, which would normally handled by other +capabilities, to the domain objects in its composition. -This capability has the following interface: +This capability has the following interface: -* `getDelegates(key)`: Returns a Promise for an array of DomainObject instances, -to which this domain object wishes to delegate the capability with the specified -key . -* `invoke(key)`: Alias of getDelegates(key) . -* `doesDelegate(key)`: Returns true if the domain object does delegate the -capability with the specified key . +* `getDelegates(key)`: Returns a Promise for an array of DomainObject instances, +to which this domain object wishes to delegate the capability with the specified +key . +* `invoke(key)`: Alias of getDelegates(key) . +* `doesDelegate(key)`: Returns true if the domain object does delegate the +capability with the specified key . -The platform implementation of the delegation capability inspects the domain -object's type definition for a property delegates , whose value is an array of -strings describing which capabilities domain objects of that type wish to -delegate. If this property is not present, the delegation capability will not be -present in domain objects of that type. +The platform implementation of the delegation capability inspects the domain +object's type definition for a property delegates , whose value is an array of +strings describing which capabilities domain objects of that type wish to +delegate. If this property is not present, the delegation capability will not be +present in domain objects of that type. ## Editor Capability -The editor capability is meant primarily for internal use by Edit mode, and -helps to manage the behavior associated with exiting _Edit_ mode via _Save_ or -_Cancel_. Its interface is not intended for general use. However, -`domainObject.hasCapability(editor)` is a useful way of determining whether or +The editor capability is meant primarily for internal use by Edit mode, and +helps to manage the behavior associated with exiting _Edit_ mode via _Save_ or +_Cancel_. Its interface is not intended for general use. However, +`domainObject.hasCapability(editor)` is a useful way of determining whether or not we are looking at an object in _Edit_ mode. - + ## Mutation Capability -The `mutation` capability provides a means by which the contents of a domain -object's model can be modified. This capability is provided by the platform for +The `mutation` capability provides a means by which the contents of a domain +object's model can be modified. This capability is provided by the platform for all domain objects, and has the following interface: -* `mutate(mutator, [timestamp])`: Modify the domain object's model using the -specified `mutator` function. After changes are made, the `modified` property of -the model will be updated with the specified `timestamp` if one was provided, -or with the current system time. +* `mutate(mutator, [timestamp])`: Modify the domain object's model using the +specified `mutator` function. After changes are made, the `modified` property of +the model will be updated with the specified `timestamp` if one was provided, +or with the current system time. * `invoke(...)`: Alias of `mutate`. -Changes to domain object models should only be made via the `mutation` -capability; other platform behavior is likely to break (either by exhibiting -undesired behavior, or failing to exhibit desired behavior) if models are +Changes to domain object models should only be made via the `mutation` +capability; other platform behavior is likely to break (either by exhibiting +undesired behavior, or failing to exhibit desired behavior) if models are modified by other means. - + ### Mutator Function -The mutator argument above is a function which will receive a cloned copy of the -domain object's model as a single argument. It may return: +The mutator argument above is a function which will receive a cloned copy of the +domain object's model as a single argument. It may return: -* A `Promise` in which case the resolved value of the promise will be used to -determine which of the following forms is used. -* Boolean `false` in which case the mutation is cancelled. -* A JavaScript object, in which case this object will be used as the new model +* A `Promise` in which case the resolved value of the promise will be used to +determine which of the following forms is used. +* Boolean `false` in which case the mutation is cancelled. +* A JavaScript object, in which case this object will be used as the new model for this domain object. -* No value (or, equivalently, `undefined`), in which case the cloned copy -(including any changes made in place by the mutator function) will be used as -the new domain object model. +* No value (or, equivalently, `undefined`), in which case the cloned copy +(including any changes made in place by the mutator function) will be used as +the new domain object model. ## Persistence Capability -The persistence capability provides a mean for interacting with the underlying -persistence service which stores this domain object's model. It has the +The persistence capability provides a mean for interacting with the underlying +persistence service which stores this domain object's model. It has the following interface: -* `persist()`: Store the local version of this domain object, including any -changes, to the persistence store. Returns a Promise for a boolean value, which +* `persist()`: Store the local version of this domain object, including any +changes, to the persistence store. Returns a Promise for a boolean value, which will be true when the object was successfully persisted. -* `refresh()`: Replace this domain object's model with the most recent version -from persistence. Returns a Promise which will resolve when the change has +* `refresh()`: Replace this domain object's model with the most recent version +from persistence. Returns a Promise which will resolve when the change has completed. -* `getSpace()`: Return the string which identifies the persistence space which +* `getSpace()`: Return the string which identifies the persistence space which stores this domain object. ## Relationship Capability -The relationship capability provides a means for accessing other domain objects -with which this domain object has some typed relationship. It has the following +The relationship capability provides a means for accessing other domain objects +with which this domain object has some typed relationship. It has the following interface: -* `listRelationships()`: List all types of relationships exposed by this object. +* `listRelationships()`: List all types of relationships exposed by this object. Returns an array of strings identifying the types of relationships. -* `getRelatedObjects(relationship)`: Get all domain objects to which this domain -object has the specified type of relationship, which is a string identifier +* `getRelatedObjects(relationship)`: Get all domain objects to which this domain +object has the specified type of relationship, which is a string identifier (as above.) Returns a `Promise` for an array of `DomainObject` instances. -The platform implementation of the `relationship` capability is present for domain -objects which has a `relationships` property in their model, whose value is an -object containing key-value pairs, where keys are strings identifying +The platform implementation of the `relationship` capability is present for domain +objects which has a `relationships` property in their model, whose value is an +object containing key-value pairs, where keys are strings identifying relationship types, and values are arrays of domain object identifiers. ## Telemetry Capability -The telemetry capability provides a means for accessing telemetry data +The telemetry capability provides a means for accessing telemetry data associated with a domain object. It has the following interface: -* `requestData([request])`: Request telemetry data for this specific domain -object, using telemetry request parameters from the specified request if -provided. This capability will fill in telemetry request properties as-needed +* `requestData([request])`: Request telemetry data for this specific domain +object, using telemetry request parameters from the specified request if +provided. This capability will fill in telemetry request properties as-needed for this domain object. Returns a `Promise` for a `TelemetrySeries`. -* `subscribe(callback, [request])`: Subscribe to telemetry data updates for -this specific domain object, using telemetry request parameters from the -specified request if provided. This capability will fill in telemetry request -properties as-needed for this domain object. The specified callback will be -invoked with TelemetrySeries instances as they arrive. Returns a function which -can be invoked to terminate the subscription, or undefined if no subscription +* `subscribe(callback, [request])`: Subscribe to telemetry data updates for +this specific domain object, using telemetry request parameters from the +specified request if provided. This capability will fill in telemetry request +properties as-needed for this domain object. The specified callback will be +invoked with TelemetrySeries instances as they arrive. Returns a function which +can be invoked to terminate the subscription, or undefined if no subscription could be obtained. * `getMetadata()`: Get metadata associated with this domain object's telemetry. -The platform implementation of the `telemetry` capability is present for domain -objects which has a `telemetry` property in their model and/or type definition; -this object will serve as a template for telemetry requests made using this +The platform implementation of the `telemetry` capability is present for domain +objects which has a `telemetry` property in their model and/or type definition; +this object will serve as a template for telemetry requests made using this object, and will also be returned by `getMetadata()` above. ## Type Capability -The `type` capability exposes information about the domain object's type. It has +The `type` capability exposes information about the domain object's type. It has the same interface as `Type`; see Core API. ## View Capability -The `view` capability exposes views which are applicable to a given domain +The `view` capability exposes views which are applicable to a given domain object. It has the following interface: -* `invoke()`: Returns an array of extension definitions for views which are +* `invoke()`: Returns an array of extension definitions for views which are applicable for this domain object. # Actions -Actions are reusable processes/behaviors performed by users within the system, +Actions are reusable processes/behaviors performed by users within the system, typically upon domain objects. ## Action Categories -The platform understands the following action categories (specifiable as the +The platform understands the following action categories (specifiable as the `category` parameter of an action's extension definition.) * `contextual`: Appears in context menus. * `view-control`: Appears in top-right area of view (as buttons) in Browse mode ## Platform Actions -The platform defines certain actions which can be utilized by way of a domain -object's `action` capability. Unless otherwise specified, these act upon (and -modify) the object described by the `domainObject` property of the action's +The platform defines certain actions which can be utilized by way of a domain +object's `action` capability. Unless otherwise specified, these act upon (and +modify) the object described by the `domainObject` property of the action's context. * `cancel`: Cancel the current editing action (invoked from Edit mode.) -* `compose`: Place an object in another object's composition. The object to be +* `compose`: Place an object in another object's composition. The object to be added should be provided as the `selectedObject` of the action context. * `edit`: Start editing an object (enter Edit mode.) * `fullscreen`: Enter full screen mode. -* `navigate`: Make this object the focus of navigation (e.g. highlight it within +* `navigate`: Make this object the focus of navigation (e.g. highlight it within the tree, display a view of it to the right.) * `properties`: Show the 'Edit Properties' dialog. -* `remove`: Remove this domain object from its parent's composition. (The -parent, in this case, is whichever other domain object exposed this object by +* `remove`: Remove this domain object from its parent's composition. (The +parent, in this case, is whichever other domain object exposed this object by way of its `composition` capability.) * `save`: Save changes (invoked from Edit mode.) * `window`: Open this object in a new window. # Policies -Policies are consulted to determine when certain behavior in Open MCT Web is -allowed. Policy questions are assigned to certain categories, which broadly -describe the type of decision being made; within each category, policies have a -candidate (the thing which may or may not be allowed) and, optionally, a context +Policies are consulted to determine when certain behavior in Open MCT Web is +allowed. Policy questions are assigned to certain categories, which broadly +describe the type of decision being made; within each category, policies have a +candidate (the thing which may or may not be allowed) and, optionally, a context (describing, generally, the context in which the decision is occurring.) -The types of objects passed for 'candidate' and 'context' vary by category; +The types of objects passed for 'candidate' and 'context' vary by category; these types are documented below. ## Policy Categories -The platform understands the following policy categories (specifiable as the +The platform understands the following policy categories (specifiable as the `category` parameter of an policy's extension definition.) -* `action`: Determines whether or not a given action is allowable. The candidate +* `action`: Determines whether or not a given action is allowable. The candidate argument here is an Action; the context is its action context object. -* `composition`: Determines whether or not domain objects of a given type are -allowed to contain domain objects of another type. The candidate argument here -is the container's `Type`; the context argument is the `Type` of the object to be +* `composition`: Determines whether or not domain objects of a given type are +allowed to contain domain objects of another type. The candidate argument here +is the container's `Type`; the context argument is the `Type` of the object to be contained. -* `view`: Determines whether or not a view is applicable for a domain object. -The candidate argument is the view's extension definition; the context argument +* `view`: Determines whether or not a view is applicable for a domain object. +The candidate argument is the view's extension definition; the context argument is the `DomainObject` to be viewed. # Build-Test-Deploy -Open MCT Web is designed to support a broad variety of build and deployment -options. The sources can be deployed in the same directory structure used during +Open MCT Web is designed to support a broad variety of build and deployment +options. The sources can be deployed in the same directory structure used during development. A few utilities are included to support development processes. ## Command-line Build -Open MCT Web includes a script for building via command line using Maven 3.0.4 +Open MCT Web includes a script for building via command line using Maven 3.0.4 [https://maven.apache.org/](). - + Invoking mvn clean install will: * Check code style using JSLint. The build will fail if JSLint raises any warnings. @@ -2183,44 +2185,44 @@ Invoking mvn clean install will: * Populate version info (e.g. commit hash, build time.) * Produce a web archive (`.war`) artifact in the `target` directory. -The produced artifact contains a subset of the repository's own folder -hierarchy, omitting tests and example bundles. +The produced artifact contains a subset of the repository's own folder +hierarchy, omitting tests and example bundles. -Note that an internet connection is required to run this build, in order to +Note that an internet connection is required to run this build, in order to download build dependencies. ## Test Suite -Open MCT Web uses Jasmine [http://jasmine.github.io/]() for automated testing. -The file `test.html` included at the top level of the source repository, can be -run from the browser to perform tests for all active bundles, as defined in +Open MCT Web uses Jasmine [http://jasmine.github.io/]() for automated testing. +The file `test.html` included at the top level of the source repository, can be +run from the browser to perform tests for all active bundles, as defined in `bundle.json`. To define tests for a bundle: * Include a directory named `test` within that bundle. -* In the `test` directory, include a file named `suite.json`. This will identify +* In the `test` directory, include a file named `suite.json`. This will identify which scripts will be tested. -* The file `suite.json` must contain a JSON array of strings, where each string -is the name of a script to be tested. These names should include any directory -paths to the script after (but not including) the `src` folder, and should not -include the file's `.js` extension. (Note that while Open MCT Web's framework -allows a different name to be chosen for the src directory, the test runner +* The file `suite.json` must contain a JSON array of strings, where each string +is the name of a script to be tested. These names should include any directory +paths to the script after (but not including) the `src` folder, and should not +include the file's `.js` extension. (Note that while Open MCT Web's framework +allows a different name to be chosen for the src directory, the test runner does not: This directory must be named `src` for the test runner to find it.) -* For each script to be tested, a corresponding test script should be located in -the bundle's `test` directory. This should include the suffix Spec at the end of -the filename (but before the `.js` extension.) This test script should be an AMD -module which uses the Jasmine API to declare its test behavior. It should +* For each script to be tested, a corresponding test script should be located in +the bundle's `test` directory. This should include the suffix Spec at the end of +the filename (but before the `.js` extension.) This test script should be an AMD +module which uses the Jasmine API to declare its test behavior. It should declare an AMD dependency on the script to be tested, using a relative path. For example, if writing tests for a bundle at example/foo with two scripts: * `example/foo/src/controllers/FooController.js` * `example/foo/src/directives/FooDirective.js` -First, these scripts should be identified in `example/foo/test/suite.json` e.g. +First, these scripts should be identified in `example/foo/test/suite.json` e.g. with contents:`[ "controllers/FooController", "directives/FooDirective" ]` -Then, scripts which describe these tests should be written. For example, test +Then, scripts which describe these tests should be written. For example, test `example/foo/test/controllers/FooControllerSpec.js` could look like: /*global define,Promise,describe,it,expect,beforeEach*/ @@ -2229,8 +2231,8 @@ Then, scripts which describe these tests should be written. For example, test ["../../src/controllers/FooController"], function (FooController) { "use strict"; - - + + describe("The foo controller", function () { it("does something", function () { var controller = new FooController(); @@ -2243,104 +2245,104 @@ Then, scripts which describe these tests should be written. For example, test ## Code Coverage -In addition to running tests, the test runner will also capture code coverage -information using [Blanket.JS](http://blanketjs.org/) and display this at the +In addition to running tests, the test runner will also capture code coverage +information using [Blanket.JS](http://blanketjs.org/) and display this at the bottom of the screen. Currently, only statement coverage is displayed. ## Deployment -Open MCT Web is built to be flexible in terms of the deployment strategies it +Open MCT Web is built to be flexible in terms of the deployment strategies it supports. In order to run in the browser, Open MCT Web needs: -1. HTTP access to sources/resources for the framework, platform, and all active +1. HTTP access to sources/resources for the framework, platform, and all active bundles. -2. Access to any external services utilized by active bundles. (This means that -external services need to support HTTP or some other web-accessible interface, +2. Access to any external services utilized by active bundles. (This means that +external services need to support HTTP or some other web-accessible interface, like WebSockets.) -Any HTTP server capable of serving flat files is sufficient for the first point. -The command-line build also packages Open MCT Web into a `.war` file for easier +Any HTTP server capable of serving flat files is sufficient for the first point. +The command-line build also packages Open MCT Web into a `.war` file for easier deployment on containers such as Apache Tomcat. -The second point may be less flexible, as it depends upon the specific services -to be utilized by Open MCT Web. Because of this, it is often the set of external -services (and the manner in which they are exposed) that determine how to deploy +The second point may be less flexible, as it depends upon the specific services +to be utilized by Open MCT Web. Because of this, it is often the set of external +services (and the manner in which they are exposed) that determine how to deploy Open MCT Web. -One important constraint to consider in this context is the browser's same -origin policy. If external services are not on the same apparent host and port -as the client (from the perspective of the browser) then access may be +One important constraint to consider in this context is the browser's same +origin policy. If external services are not on the same apparent host and port +as the client (from the perspective of the browser) then access may be disallowed. There are two workarounds if this occurs: -* Make the external service appear to be on the same host/port, either by +* Make the external service appear to be on the same host/port, either by actually deploying it there, or by proxying requests to it. -* Enable CORS (cross-origin resource sharing) on the external service. This is -only possible if the external service can be configured to support CORS. Care -should be exercised if choosing this option to ensure that the chosen +* Enable CORS (cross-origin resource sharing) on the external service. This is +only possible if the external service can be configured to support CORS. Care +should be exercised if choosing this option to ensure that the chosen configuration does not create a security vulnerability. -Examples of deployment strategies (and the conditions under which they make the +Examples of deployment strategies (and the conditions under which they make the most sense) include: -* If the external services that Open MCT Web will utilize are all running on -Apache Tomcat [https://tomcat.apache.org/](), then it makes sense to run Open -MCT Web from the same Tomcat instance as a separate web application. The -`.war` artifact produced by the command line build facilitates this deployment -option. (See [https://tomcat.apache.org/tomcat-8.0-doc/deployer-howto.html() for +* If the external services that Open MCT Web will utilize are all running on +Apache Tomcat [https://tomcat.apache.org/](), then it makes sense to run Open +MCT Web from the same Tomcat instance as a separate web application. The +`.war` artifact produced by the command line build facilitates this deployment +option. (See [https://tomcat.apache.org/tomcat-8.0-doc/deployer-howto.html() for general information on deploying in Tomcat.) -* If a variety of external services will be running from a variety of -hosts/ports, then it may make sense to use a web server that supports proxying, -such as the Apache HTTP Server [http://httpd.apache.org/](). In this -configuration, the HTTP server would be configured to proxy (or reverse proxy) -requests at specific paths to the various external services, while providing +* If a variety of external services will be running from a variety of +hosts/ports, then it may make sense to use a web server that supports proxying, +such as the Apache HTTP Server [http://httpd.apache.org/](). In this +configuration, the HTTP server would be configured to proxy (or reverse proxy) +requests at specific paths to the various external services, while providing Open MCT Web as flat files from a different path. -* If a single server component is being developed to handle all server-side -needs of an Open MCT Web instance, it can make sense to serve Open MCT Web (as -flat files) from the same component using an embedded HTTP server such as Nancy +* If a single server component is being developed to handle all server-side +needs of an Open MCT Web instance, it can make sense to serve Open MCT Web (as +flat files) from the same component using an embedded HTTP server such as Nancy [http://nancyfx.org/](). -* If no external services are needed (or if the 'external services' will just -be generating flat files to read) it makes sense to utilize a lightweight flat -file HTTP server such as Lighttpd [http://www.lighttpd.net/](). In this -configuration, Open MCT Web sources/resources would be placed at one path, while +* If no external services are needed (or if the 'external services' will just +be generating flat files to read) it makes sense to utilize a lightweight flat +file HTTP server such as Lighttpd [http://www.lighttpd.net/](). In this +configuration, Open MCT Web sources/resources would be placed at one path, while the files generated by the external service are placed at another path. -* If all external services support CORS, it may make sense to have an HTTP -server that is solely responsible for making Open MCT Web sources/resources -available, and to have Open MCT Web contact these external services directly. -Again, lightweight HTTP servers such as Lighttpd [http://www.lighttpd.net/]() -are useful in this circumstance. The downside of this option is that additional -configuration effort is required, both to enable CORS on the external services, +* If all external services support CORS, it may make sense to have an HTTP +server that is solely responsible for making Open MCT Web sources/resources +available, and to have Open MCT Web contact these external services directly. +Again, lightweight HTTP servers such as Lighttpd [http://www.lighttpd.net/]() +are useful in this circumstance. The downside of this option is that additional +configuration effort is required, both to enable CORS on the external services, and to ensure that Open MCT Web can correctly locate these services. -Another important consideration is authentication. By design, Open MCT Web does -not handle user authentication. Instead, this should typically be treated as a -deployment-time concern, where authentication is handled by the HTTP server +Another important consideration is authentication. By design, Open MCT Web does +not handle user authentication. Instead, this should typically be treated as a +deployment-time concern, where authentication is handled by the HTTP server which provides Open MCT Web, or an external access management system. ### Configuration -In most of the deployment options above, some level of configuration is likely -to be needed or desirable to make sure that bundles can reach the external -services they need to reach. Most commonly this means providing the path or URL +In most of the deployment options above, some level of configuration is likely +to be needed or desirable to make sure that bundles can reach the external +services they need to reach. Most commonly this means providing the path or URL to an external service. -Configurable parameters within Open MCT Web are specified via constants -(literally, as extensions of the `constants` category) and accessed via -dependency injection by the scripts which need them. Reasonable defaults for -these constants are provided in the bundle where they are used. Plugins are +Configurable parameters within Open MCT Web are specified via constants +(literally, as extensions of the `constants` category) and accessed via +dependency injection by the scripts which need them. Reasonable defaults for +these constants are provided in the bundle where they are used. Plugins are encouraged to follow the same pattern. -Constants may be specified in any bundle; if multiple constants are specified -with the same `key` the highest-priority one will be used. This allows default +Constants may be specified in any bundle; if multiple constants are specified +with the same `key` the highest-priority one will be used. This allows default values to be overridden by specifying constants with higher priority. This permits at least three configuration approaches: -* Modify the constants defined in their original bundles when deploying. This is -generally undesirable due to the amount of manual work required and potential +* Modify the constants defined in their original bundles when deploying. This is +generally undesirable due to the amount of manual work required and potential for error, but is viable if there are a small number of constants to change. -* Add a separate configuration bundle which overrides the values of these -constants. This is particularly appropriate when multiple configurations (e.g. -development, test, production) need to be managed easily; these can be swapped +* Add a separate configuration bundle which overrides the values of these +constants. This is particularly appropriate when multiple configurations (e.g. +development, test, production) need to be managed easily; these can be swapped quickly by changing the set of active bundles in bundles.json. -* Deploy Open MCT Web and its external services in such a fashion that the +* Deploy Open MCT Web and its external services in such a fashion that the default paths to reach external services are all correct. ### Configuration Constants @@ -2352,11 +2354,15 @@ The following constants have global significance: consume this constant in order to provide persistence for that space. The following configuration constants are recognized by Open MCT Web bundles: +* Common UI elements - `platform/commonUI/general` + * `THEME`: A string identifying the current theme symbolically. Individual + stylesheets (the `stylesheets` extension category) may specify an optional + `theme` property which will be matched against this before inclusion. * CouchDB adapter - `platform/persistence/couch` - * `COUCHDB_PATH`: URL or path to the CouchDB database to be used for domain + * `COUCHDB_PATH`: URL or path to the CouchDB database to be used for domain object persistence. Should not include a trailing slash. * ElasticSearch adapter - `platform/persistence/elastic` - * `ELASTIC_ROOT`: URL or path to the ElasticSearch instance to be used for + * `ELASTIC_ROOT`: URL or path to the ElasticSearch instance to be used for domain object persistence. Should not include a trailing slash. - * `ELASTIC_PATH`: Path relative to the ElasticSearch instance where domain - object models should be persisted. Should take the form `<index>/<type>`. \ No newline at end of file + * `ELASTIC_PATH`: Path relative to the ElasticSearch instance where domain + object models should be persisted. Should take the form `<index>/<type>`. diff --git a/platform/commonUI/browse/src/creation/CreationService.js b/platform/commonUI/browse/src/creation/CreationService.js index bfd8a0c403..4b7c0119c9 100644 --- a/platform/commonUI/browse/src/creation/CreationService.js +++ b/platform/commonUI/browse/src/creation/CreationService.js @@ -68,7 +68,7 @@ define( */ CreationService.prototype.createObject = function (model, parent) { var persistence = parent.getCapability("persistence"), - newObject = parent.useCapability("creation", model), + newObject = parent.useCapability("instantiation", model), newObjectPersistence = newObject.getCapability("persistence"), self = this; diff --git a/platform/commonUI/browse/test/creation/CreationServiceSpec.js b/platform/commonUI/browse/test/creation/CreationServiceSpec.js index a35bf39f97..e0704ba702 100644 --- a/platform/commonUI/browse/test/creation/CreationServiceSpec.js +++ b/platform/commonUI/browse/test/creation/CreationServiceSpec.js @@ -91,14 +91,14 @@ define( ); mockCreationCapability = jasmine.createSpyObj( "creation", - ["create", "invoke"] + ["instantiate", "invoke"] ); mockCapabilities = { mutation: mockMutationCapability, persistence: mockPersistenceCapability, composition: mockCompositionCapability, context: mockContextCapability, - creation: mockCreationCapability + instantiation: mockCreationCapability }; mockNewPersistenceCapability = jasmine.createSpyObj( "new-persistence", @@ -130,9 +130,9 @@ define( mockPromise([mockNewObject]) ); mockCompositionCapability.add.andReturn(mockPromise(true)); - mockCreationCapability.create.andReturn(mockNewObject); + mockCreationCapability.instantiate.andReturn(mockNewObject); mockCreationCapability.invoke.andCallFake(function (model) { - return mockCreationCapability.create(model); + return mockCreationCapability.instantiate(model); }); creationService = new CreationService( @@ -144,7 +144,7 @@ define( it("allows new objects to be created", function () { var model = { someKey: "some value" }; creationService.createObject(model, mockParentObject); - expect(mockCreationCapability.create) + expect(mockCreationCapability.instantiate) .toHaveBeenCalledWith(model); }); diff --git a/platform/commonUI/dialog/src/DialogService.js b/platform/commonUI/dialog/src/DialogService.js index 27ffa9ae8b..0d480f3455 100644 --- a/platform/commonUI/dialog/src/DialogService.js +++ b/platform/commonUI/dialog/src/DialogService.js @@ -181,7 +181,7 @@ define( * @typedef DialogOption * @property {string} label a label to be displayed as the button * text for this action - * @property {function} action a function to be called when the + * @property {function} callback a function to be called when the * button is clicked */ diff --git a/platform/commonUI/general/bundle.json b/platform/commonUI/general/bundle.json index edaa8ec103..5976b912cc 100644 --- a/platform/commonUI/general/bundle.json +++ b/platform/commonUI/general/bundle.json @@ -18,7 +18,7 @@ "runs": [ { "implementation": "StyleSheetLoader.js", - "depends": [ "stylesheets[]", "$document" ] + "depends": [ "stylesheets[]", "$document", "THEME" ] } ], "stylesheets": [ @@ -194,6 +194,11 @@ { "key": "MCT_SCROLL_Y_ATTRIBUTE", "value": "mctScrollY" + }, + { + "key": "THEME", + "value": "unspecified", + "priority": "fallback" } ], "containers": [ diff --git a/platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json b/platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json index 489d491fd2..fee491e4b3 100644 --- a/platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json +++ b/platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json @@ -1,19 +1,27 @@ { "metadata": { "name": "WTD Symbols", - "lastOpened": 1446490786311, - "created": 1446489891263 + "lastOpened": 1446670352108, + "created": 1446670349721 }, "iconSets": [ { "selection": [ { - "order": 113, + "order": 116, + "id": 93, + "prevSize": 32, + "code": 58902, + "name": "icon-eye-open-no-gleam", + "tempChar": "" + }, + { + "order": 115, "id": 92, "prevSize": 32, "code": 58901, - "name": "icon-crosshair", - "tempChar": "" + "name": "icon-eye-open", + "tempChar": "" }, { "order": 110, @@ -21,7 +29,7 @@ "prevSize": 32, "code": 58899, "name": "icon-collapse-pane-left", - "tempChar": "" + "tempChar": "" }, { "order": 111, @@ -29,7 +37,7 @@ "prevSize": 32, "code": 58900, "name": "icon-collapse-pane-right", - "tempChar": "" + "tempChar": "" }, { "order": 109, @@ -37,7 +45,7 @@ "prevSize": 32, "code": 58898, "name": "icon-save", - "tempChar": "" + "tempChar": "" }, { "order": 108, @@ -45,7 +53,7 @@ "prevSize": 32, "code": 58897, "name": "icon-dataset", - "tempChar": "" + "tempChar": "" }, { "order": 90, @@ -53,7 +61,7 @@ "prevSize": 32, "code": 58896, "name": "icon-bell", - "tempChar": "" + "tempChar": "" }, { "order": 91, @@ -61,7 +69,7 @@ "prevSize": 32, "code": 58889, "name": "icon-hourglass", - "tempChar": "" + "tempChar": "" }, { "order": 92, @@ -74,7 +82,7 @@ 58890 ], "name": "icon-info-v15", - "tempChar": "" + "tempChar": "" }, { "order": 93, @@ -82,7 +90,7 @@ "prevSize": 32, "code": 58887, "name": "icon-x-in-circle", - "tempChar": "" + "tempChar": "" }, { "order": 94, @@ -90,7 +98,7 @@ "prevSize": 32, "code": 58881, "name": "icon-datatable", - "tempChar": "" + "tempChar": "" }, { "order": 95, @@ -98,7 +106,7 @@ "prevSize": 32, "code": 58882, "name": "icon-tabular-scrolling", - "tempChar": "" + "tempChar": "" }, { "order": 96, @@ -106,7 +114,7 @@ "prevSize": 32, "code": 58884, "name": "icon-tabular", - "tempChar": "" + "tempChar": "" }, { "order": 97, @@ -114,7 +122,7 @@ "prevSize": 32, "code": 58885, "name": "icon-calendar", - "tempChar": "" + "tempChar": "" }, { "order": 98, @@ -122,7 +130,7 @@ "prevSize": 32, "code": 58886, "name": "icon-paint-bucket", - "tempChar": "" + "tempChar": "" }, { "order": 99, @@ -130,7 +138,7 @@ "prevSize": 32, "code": 123, "name": "icon-pointer-left", - "tempChar": "" + "tempChar": "" }, { "order": 100, @@ -138,7 +146,7 @@ "prevSize": 32, "code": 125, "name": "icon-pointer-right", - "tempChar": "" + "tempChar": "" }, { "order": 101, @@ -146,7 +154,7 @@ "prevSize": 32, "code": 80, "name": "icon-person", - "tempChar": "" + "tempChar": "" }, { "order": 102, @@ -154,7 +162,7 @@ "prevSize": 32, "code": 232, "name": "icon-chain-links", - "tempChar": "" + "tempChar": "" }, { "order": 103, @@ -162,7 +170,7 @@ "prevSize": 32, "code": 115, "name": "icon-database-in-brackets", - "tempChar": "" + "tempChar": "" }, { "order": 104, @@ -170,7 +178,7 @@ "prevSize": 32, "code": 114, "name": "icon-refresh", - "tempChar": "" + "tempChar": "" }, { "order": 105, @@ -178,7 +186,7 @@ "prevSize": 32, "code": 108, "name": "icon-lock", - "tempChar": "" + "tempChar": "" }, { "order": 106, @@ -186,7 +194,7 @@ "prevSize": 32, "code": 51, "name": "icon-box-with-dashed-lines", - "tempChar": "" + "tempChar": "" }, { "order": 10, @@ -194,7 +202,7 @@ "prevSize": 32, "code": 58880, "name": "icon-box-with-arrow-cursor", - "tempChar": "" + "tempChar": "" }, { "order": 11, @@ -202,7 +210,7 @@ "prevSize": 32, "code": 65, "name": "icon-activity-mode", - "tempChar": "" + "tempChar": "" }, { "order": 12, @@ -210,7 +218,7 @@ "prevSize": 32, "code": 97, "name": "icon-activity", - "tempChar": "" + "tempChar": "" }, { "order": 87, @@ -218,7 +226,7 @@ "prevSize": 32, "code": 33, "name": "icon-alert-rect", - "tempChar": "" + "tempChar": "" }, { "order": 14, @@ -226,7 +234,7 @@ "prevSize": 32, "code": 58883, "name": "icon-alert-triangle", - "tempChar": "" + "tempChar": "" }, { "order": 15, @@ -234,7 +242,7 @@ "prevSize": 32, "code": 238, "name": "icon-arrow-double-down", - "tempChar": "" + "tempChar": "" }, { "order": 16, @@ -242,7 +250,7 @@ "prevSize": 32, "code": 235, "name": "icon-arrow-double-up", - "tempChar": "" + "tempChar": "" }, { "order": 2, @@ -250,7 +258,7 @@ "prevSize": 32, "code": 118, "name": "icon-arrow-down", - "tempChar": "" + "tempChar": "" }, { "order": 19, @@ -258,7 +266,7 @@ "prevSize": 32, "code": 60, "name": "icon-arrow-left", - "tempChar": "" + "tempChar": "" }, { "order": 20, @@ -266,7 +274,7 @@ "prevSize": 32, "code": 62, "name": "icon-arrow-right", - "tempChar": "" + "tempChar": "" }, { "order": 21, @@ -274,7 +282,7 @@ "prevSize": 32, "code": 236, "name": "icon-arrow-tall-down", - "tempChar": "" + "tempChar": "" }, { "order": 22, @@ -282,7 +290,7 @@ "prevSize": 32, "code": 237, "name": "icon-arrow-tall-up", - "tempChar": "" + "tempChar": "" }, { "order": 23, @@ -290,7 +298,7 @@ "prevSize": 32, "code": 94, "name": "icon-arrow-up", - "tempChar": "" + "tempChar": "" }, { "order": 24, @@ -298,7 +306,7 @@ "prevSize": 32, "code": 73, "name": "icon-arrows-out", - "tempChar": "" + "tempChar": "" }, { "order": 25, @@ -306,7 +314,7 @@ "prevSize": 32, "code": 58893, "name": "icon-arrows-right-left", - "tempChar": "" + "tempChar": "" }, { "order": 33, @@ -314,7 +322,7 @@ "prevSize": 32, "code": 53, "name": "icon-arrows-up-down", - "tempChar": "" + "tempChar": "" }, { "order": 26, @@ -322,7 +330,7 @@ "prevSize": 32, "code": 42, "name": "icon-asterisk", - "tempChar": "" + "tempChar": "" }, { "order": 27, @@ -330,7 +338,7 @@ "prevSize": 32, "code": 72, "name": "icon-autoflow-tabular", - "tempChar": "" + "tempChar": "" }, { "order": 28, @@ -338,7 +346,7 @@ "prevSize": 32, "code": 224, "name": "icon-box", - "tempChar": "" + "tempChar": "" }, { "order": 29, @@ -346,7 +354,7 @@ "prevSize": 32, "code": 50, "name": "icon-check", - "tempChar": "" + "tempChar": "" }, { "order": 30, @@ -354,7 +362,7 @@ "prevSize": 32, "code": 67, "name": "icon-clock", - "tempChar": "" + "tempChar": "" }, { "order": 31, @@ -362,7 +370,7 @@ "prevSize": 32, "code": 46, "name": "icon-connectivity", - "tempChar": "" + "tempChar": "" }, { "order": 32, @@ -370,7 +378,7 @@ "prevSize": 32, "code": 100, "name": "icon-database-query", - "tempChar": "" + "tempChar": "" }, { "order": 17, @@ -378,7 +386,7 @@ "prevSize": 32, "code": 68, "name": "icon-database", - "tempChar": "" + "tempChar": "" }, { "order": 35, @@ -386,7 +394,7 @@ "prevSize": 32, "code": 81, "name": "icon-dictionary", - "tempChar": "" + "tempChar": "" }, { "order": 36, @@ -394,7 +402,7 @@ "prevSize": 32, "code": 242, "name": "icon-duplicate", - "tempChar": "" + "tempChar": "" }, { "order": 37, @@ -402,7 +410,7 @@ "prevSize": 32, "code": 102, "name": "icon-folder-new", - "tempChar": "" + "tempChar": "" }, { "order": 38, @@ -410,7 +418,7 @@ "prevSize": 32, "code": 70, "name": "icon-folder", - "tempChar": "" + "tempChar": "" }, { "order": 39, @@ -418,7 +426,7 @@ "prevSize": 32, "code": 95, "name": "icon-fullscreen-collapse", - "tempChar": "" + "tempChar": "" }, { "order": 40, @@ -426,7 +434,7 @@ "prevSize": 32, "code": 122, "name": "icon-fullscreen-expand", - "tempChar": "" + "tempChar": "" }, { "order": 41, @@ -434,7 +442,7 @@ "prevSize": 32, "code": 71, "name": "icon-gear", - "tempChar": "" + "tempChar": "" }, { "order": 49, @@ -442,7 +450,7 @@ "prevSize": 32, "code": 227, "name": "icon-image", - "tempChar": "" + "tempChar": "" }, { "order": 42, @@ -450,7 +458,7 @@ "prevSize": 32, "code": 225, "name": "icon-layers", - "tempChar": "" + "tempChar": "" }, { "order": 43, @@ -458,7 +466,7 @@ "prevSize": 32, "code": 76, "name": "icon-layout", - "tempChar": "" + "tempChar": "" }, { "order": 44, @@ -466,7 +474,7 @@ "prevSize": 32, "code": 226, "name": "icon-line-horz", - "tempChar": "" + "tempChar": "" }, { "order": 75, @@ -474,7 +482,7 @@ "prevSize": 32, "code": 244, "name": "icon-link", - "tempChar": "" + "tempChar": "" }, { "order": 46, @@ -482,7 +490,7 @@ "prevSize": 32, "code": 88, "name": "icon-magnify-in", - "tempChar": "" + "tempChar": "" }, { "order": 47, @@ -490,7 +498,7 @@ "prevSize": 32, "code": 89, "name": "icon-magnify-out", - "tempChar": "" + "tempChar": "" }, { "order": 48, @@ -498,7 +506,7 @@ "prevSize": 32, "code": 77, "name": "icon-magnify", - "tempChar": "" + "tempChar": "" }, { "order": 34, @@ -506,7 +514,7 @@ "prevSize": 32, "code": 109, "name": "icon-menu", - "tempChar": "" + "tempChar": "" }, { "order": 50, @@ -514,7 +522,7 @@ "prevSize": 32, "code": 243, "name": "icon-move", - "tempChar": "" + "tempChar": "" }, { "order": 51, @@ -522,7 +530,7 @@ "prevSize": 32, "code": 121, "name": "icon-new-window", - "tempChar": "" + "tempChar": "" }, { "order": 52, @@ -530,7 +538,7 @@ "prevSize": 32, "code": 111, "name": "icon-object", - "tempChar": "" + "tempChar": "" }, { "order": 73, @@ -538,7 +546,7 @@ "prevSize": 32, "code": 63, "name": "icon-object-unknown", - "tempChar": "" + "tempChar": "" }, { "order": 53, @@ -546,7 +554,7 @@ "prevSize": 32, "code": 86, "name": "icon-packet", - "tempChar": "" + "tempChar": "" }, { "order": 54, @@ -554,7 +562,7 @@ "prevSize": 32, "code": 234, "name": "icon-page", - "tempChar": "" + "tempChar": "" }, { "order": 55, @@ -562,7 +570,7 @@ "prevSize": 32, "code": 241, "name": "icon-pause", - "tempChar": "" + "tempChar": "" }, { "order": 56, @@ -570,7 +578,7 @@ "prevSize": 32, "code": 112, "name": "icon-pencil", - "tempChar": "" + "tempChar": "" }, { "order": 65, @@ -578,7 +586,7 @@ "prevSize": 32, "code": 79, "name": "icon-people", - "tempChar": "" + "tempChar": "" }, { "order": 57, @@ -586,7 +594,7 @@ "prevSize": 32, "code": 239, "name": "icon-play", - "tempChar": "" + "tempChar": "" }, { "order": 58, @@ -594,7 +602,7 @@ "prevSize": 32, "code": 233, "name": "icon-plot-resource", - "tempChar": "" + "tempChar": "" }, { "order": 59, @@ -602,7 +610,7 @@ "prevSize": 32, "code": 43, "name": "icon-plus", - "tempChar": "" + "tempChar": "" }, { "order": 60, @@ -610,7 +618,7 @@ "prevSize": 32, "code": 45, "name": "icon-minus", - "tempChar": "" + "tempChar": "" }, { "order": 61, @@ -618,7 +626,7 @@ "prevSize": 32, "code": 54, "name": "icon-sine", - "tempChar": "" + "tempChar": "" }, { "order": 62, @@ -626,7 +634,7 @@ "prevSize": 32, "code": 228, "name": "icon-T", - "tempChar": "" + "tempChar": "" }, { "order": 63, @@ -634,7 +642,7 @@ "prevSize": 32, "code": 116, "name": "icon-telemetry-panel", - "tempChar": "" + "tempChar": "" }, { "order": 64, @@ -642,7 +650,7 @@ "prevSize": 32, "code": 84, "name": "icon-telemetry", - "tempChar": "" + "tempChar": "" }, { "order": 18, @@ -650,7 +658,7 @@ "prevSize": 32, "code": 246, "name": "icon-thumbs-strip", - "tempChar": "" + "tempChar": "" }, { "order": 67, @@ -658,7 +666,7 @@ "prevSize": 32, "code": 83, "name": "icon-timeline", - "tempChar": "" + "tempChar": "" }, { "order": 68, @@ -666,7 +674,7 @@ "prevSize": 32, "code": 245, "name": "icon-timer", - "tempChar": "" + "tempChar": "" }, { "order": 69, @@ -674,7 +682,7 @@ "prevSize": 32, "code": 90, "name": "icon-trash", - "tempChar": "" + "tempChar": "" }, { "order": 70, @@ -682,7 +690,7 @@ "prevSize": 32, "code": 229, "name": "icon-two-parts-both", - "tempChar": "" + "tempChar": "" }, { "order": 71, @@ -690,7 +698,7 @@ "prevSize": 32, "code": 231, "name": "icon-two-parts-one-only", - "tempChar": "" + "tempChar": "" }, { "order": 72, @@ -698,7 +706,7 @@ "prevSize": 32, "code": 120, "name": "icon-x-heavy", - "tempChar": "" + "tempChar": "" }, { "order": 66, @@ -706,7 +714,7 @@ "prevSize": 32, "code": 58946, "name": "icon-x", - "tempChar": "" + "tempChar": "" } ], "id": 2, @@ -722,13 +730,43 @@ "prevSize": 32, "icons": [ { - "id": 92, + "id": 93, "paths": [ - "M514 2c-282.8 0-512 229.2-512 512s229.2 512 512 512 512-229.2 512-512-229.2-512-512-512zM860.2 450h-282.2v-282.2c69.6 12.8 133.8 46.2 185 97.4 51 51 84.4 115.2 97.2 184.8zM450 167.8v282.2h-282.2c12.8-69.6 46.2-133.8 97.4-185 51-51 115.2-84.4 184.8-97.2zM167.8 578h282.2v282.2c-69.6-12.8-133.8-46.2-185-97.4-51-51-84.4-115.2-97.2-184.8zM578 860.2v-282.2h282.2c-12.8 69.6-46.2 133.8-97.4 185-51 51-115.2 84.4-184.8 97.2z" + "M512 64c-261 0-480.6 195.4-512 448 31.4 252.6 251 448 512 448s480.6-195.4 512-448c-31.4-252.6-251-448-512-448zM768.2 734.6c-71.4 62.8-162.8 97.4-257.6 97.4s-186.2-34.6-257.6-97.4c-66.6-58.6-110.6-137.2-125-222.6 0 0 0-0.2 0-0.2 76.8-154 220.8-257.6 384-257.6s307.2 103.8 384 257.6c0 0 0 0.2 0 0.2-14.4 85.4-61.2 164-127.8 222.6z", + "M512 288c-123.8 0-224 100.2-224 224s100.2 224 224 224 224-100.2 224-224-100.2-224-224-224zM576 544c-53 0-96-43-96-96s43-96 96-96 96 43 96 96c0 53-43 96-96 96z" ], "attrs": [ { - "fill": "rgb(0, 0, 0)" + "fill": "rgb(6, 161, 75)" + }, + { + "fill": "rgb(6, 161, 75)" + } + ], + "isMulticolor": false, + "grid": 0, + "tags": [ + "icon-eye-open-no-gleam" + ], + "colorPermutations": { + "125525525516161751": [ + 1, + 1 + ] + } + }, + { + "id": 92, + "paths": [ + "M512 64c-261 0-480.6 195.4-512 448 31.4 252.6 251 448 512 448s480.6-195.4 512-448c-31.4-252.6-251-448-512-448zM768.2 734.6c-71.4 62.8-162.8 97.4-257.6 97.4s-186.2-34.6-257.6-97.4c-66.6-58.6-110.6-137.2-125-222.6 0 0 0-0.2 0-0.2 76.8-154 220.8-257.6 384-257.6s307.2 103.8 384 257.6c0 0 0 0.2 0 0.2-14.4 85.4-61.2 164-127.8 222.6z", + "M512 288c-123.8 0-224 100.2-224 224s100.2 224 224 224 224-100.2 224-224-100.2-224-224-224z" + ], + "attrs": [ + { + "fill": "rgb(6, 161, 75)" + }, + { + "fill": "rgb(6, 161, 75)" } ], "isMulticolor": false, @@ -738,7 +776,8 @@ ], "colorPermutations": { "125525525516161751": [ - 0 + 1, + 1 ] } }, diff --git a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.eot b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.eot index 43192b87f7..6e1b7e80f7 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 455f2db341..7636991183 100755 --- a/platform/commonUI/general/res/fonts/symbols/wtdsymbols.svg +++ b/platform/commonUI/general/res/fonts/symbols/wtdsymbols.svg @@ -92,6 +92,7 @@ <glyph unicode="" glyph-name="icon-save" d="M192.2 384c-0.2 0-0.2 0 0 0l-0.2-448h640v447.8c0 0 0 0-0.2 0.2h-639.6zM978.8 749.2l-165.4 165.4c-25 25-74.2 45.4-109.4 45.4h-576c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128v448c0 35.2 28.8 64 64 64h640c35.2 0 64-28.8 64-64v-448c70.4 0 128 57.6 128 128v576c0 35.2-20.4 84.4-45.2 109.2zM704 704c0-35.2-28.8-64-64-64h-448c-35.2 0-64 28.8-64 64v192h320v-192h128v192h128v-192z" /> <glyph unicode="" glyph-name="icon-collapse-pane-left" d="M256 960h-256v-1024h256c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM512 640l512-320v640z" /> <glyph unicode="" glyph-name="icon-collapse-pane-right" d="M768 960h256v-1024h-256c-105.6 0-192 86.4-192 192v640c0 105.6 86.4 192 192 192zM512 640l-512-320v640z" /> -<glyph unicode="" glyph-name="icon-crosshair" d="M514 958c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM860.2 510h-282.2v282.2c69.6-12.8 133.8-46.2 185-97.4 51-51 84.4-115.2 97.2-184.8zM450 792.2v-282.2h-282.2c12.8 69.6 46.2 133.8 97.4 185 51 51 115.2 84.4 184.8 97.2zM167.8 382h282.2v-282.2c-69.6 12.8-133.8 46.2-185 97.4-51 51-84.4 115.2-97.2 184.8zM578 99.8v282.2h282.2c-12.8-69.6-46.2-133.8-97.4-185-51-51-115.2-84.4-184.8-97.2z" /> +<glyph unicode="" glyph-name="icon-eye-open" d="M512 896c-261 0-480.6-195.4-512-448 31.4-252.6 251-448 512-448s480.6 195.4 512 448c-31.4 252.6-251 448-512 448zM768.2 225.4c-71.4-62.8-162.8-97.4-257.6-97.4s-186.2 34.6-257.6 97.4c-66.6 58.6-110.6 137.2-125 222.6 0 0 0 0.2 0 0.2 76.8 154 220.8 257.6 384 257.6s307.2-103.8 384-257.6c0 0 0-0.2 0-0.2-14.4-85.4-61.2-164-127.8-222.6zM512 672c-123.8 0-224-100.2-224-224s100.2-224 224-224 224 100.2 224 224-100.2 224-224 224z" /> +<glyph unicode="" glyph-name="icon-eye-open-no-gleam" d="M512 896c-261 0-480.6-195.4-512-448 31.4-252.6 251-448 512-448s480.6 195.4 512 448c-31.4 252.6-251 448-512 448zM768.2 225.4c-71.4-62.8-162.8-97.4-257.6-97.4s-186.2 34.6-257.6 97.4c-66.6 58.6-110.6 137.2-125 222.6 0 0 0 0.2 0 0.2 76.8 154 220.8 257.6 384 257.6s307.2-103.8 384-257.6c0 0 0-0.2 0-0.2-14.4-85.4-61.2-164-127.8-222.6zM512 672c-123.8 0-224-100.2-224-224s100.2-224 224-224 224 100.2 224 224-100.2 224-224 224zM576 416c-53 0-96 43-96 96s43 96 96 96 96-43 96-96c0-53-43-96-96-96z" /> <glyph unicode="" glyph-name="icon-x" d="M384 448l-365.332-365.332c-24.89-24.89-24.89-65.62 0-90.51l37.49-37.49c24.89-24.89 65.62-24.89 90.51 0 0 0 365.332 365.332 365.332 365.332l365.332-365.332c24.89-24.89 65.62-24.89 90.51 0l37.49 37.49c24.89 24.89 24.89 65.62 0 90.51l-365.332 365.332c0 0 365.332 365.332 365.332 365.332 24.89 24.89 24.89 65.62 0 90.51l-37.49 37.49c-24.89 24.89-65.62 24.89-90.51 0 0 0-365.332-365.332-365.332-365.332l-365.332 365.332c-24.89 24.89-65.62 24.89-90.51 0l-37.49-37.49c-24.89-24.89-24.89-65.62 0-90.51 0 0 365.332-365.332 365.332-365.332z" /> </font></defs></svg> \ 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 0bb5126e8a..a514b65eb1 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 0b1935282d..eb524a6291 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/_archetypes.scss b/platform/commonUI/general/res/sass/_archetypes.scss new file mode 100644 index 0000000000..88c34ad3bd --- /dev/null +++ b/platform/commonUI/general/res/sass/_archetypes.scss @@ -0,0 +1,119 @@ +/***************************************************************************** + * 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. + *****************************************************************************/ + +/********************************************* COLUMN LAYOUTS STYLES */ +@mixin cols($totalCols, $span) { + $cw: 100% / $totalCols; + min-width: (500px / $totalCols) * $span; + @if ($totalCols != $span) { + width: ($cw * $span) - $ueColMargin; + } @else { + width: $cw; + } +} + +.cols { + @include clearfix; + .col { + @include box-sizing(border-box); + @include clearfix; + // background: rgba(#ffcc00, 0.2); + float: left; + margin-left: $ueColMargin; + padding-left: $interiorMargin; + position: relative; + &:first-child { + margin-left: 0; + padding-left: 0; + } + } + &.cols-2 { + $nc: 2; + .col-1 { + @include cols($nc, 1); + } + } + &.cols-2-ff { + // 2 columns, first column is fixed, second is fluid + .col-100px { + width: 100px; + } + } + + &.cols-6 { + $nc: 6; + .col-1 { + @include cols($nc, 1); + } + } + &.cols-16 { + $nc: 16; + .col-1 { + @include cols($nc, 1); + } + .col-2 { + @include cols($nc, 2); + } + .col-7 { + @include cols($nc, 7); + } + } + &.cols-32 { + $nc: 32; + .col-2 { + @include cols($nc, 2); + } + .col-15 { + @include cols($nc, 15); + } + } + .l-row { + @include clearfix; + padding: $interiorMargin 0; + } +} + +/********************************************* FLEX STYLES */ +.l-flex-row, +.l-flex-col { + @include display-flex; + @include flex-wrap(nowrap); + .flex-elem { + &:not(.grows) { + @include flex(0 1 auto); + } + &.grows { + @include flex(1 1 auto); + } + } +} + +.l-flex-row { @include flex-direction(row); } +.l-flex-col { @include flex-direction(column); } + +.l-flex { + @extend .l-flex-row; + .left { + @include flex(1 1 0); + padding-right: $interiorMarginLg; + } +} \ No newline at end of file diff --git a/platform/commonUI/general/res/sass/_constants.scss b/platform/commonUI/general/res/sass/_constants.scss index a3305cf0a4..e0d9f34bd6 100644 --- a/platform/commonUI/general/res/sass/_constants.scss +++ b/platform/commonUI/general/res/sass/_constants.scss @@ -44,9 +44,10 @@ $ueAppLogoW: 105px; $ueEditToolBarH: 25px; $ueBrowseLeftPaneTreeW: 25%; $ueBrowseRightPaneInspectW: 20%; -$ueCollapsedPaneEdgeM: 20px; +$ueCollapsedPaneEdgeM: 22px; $uePaneMiniTabH: $ueTopBarH; $uePaneMiniTabW: 9px; +$uePaneMiniTabCollapsedW: 11px; $ueEditLeftPaneW: 75%; $treeSearchInputBarH: 25px; $ueTimeControlH: (33px, 20px, 20px); diff --git a/platform/commonUI/general/res/sass/_inspector.scss b/platform/commonUI/general/res/sass/_inspector.scss index 9f67ff3b73..62917017a4 100644 --- a/platform/commonUI/general/res/sass/_inspector.scss +++ b/platform/commonUI/general/res/sass/_inspector.scss @@ -43,6 +43,11 @@ vertical-align: bottom; } } + + ul { + @include box-sizing(border-box); + padding-right: $interiorMargin; + } ul li, em { diff --git a/platform/commonUI/general/res/sass/_main.scss b/platform/commonUI/general/res/sass/_main.scss index 0dab445e84..f7f2489dc7 100644 --- a/platform/commonUI/general/res/sass/_main.scss +++ b/platform/commonUI/general/res/sass/_main.scss @@ -21,6 +21,7 @@ *****************************************************************************/ @import "effects"; @import "global"; +@import "archetypes"; @import "about"; @import "text"; @import "icons"; diff --git a/platform/commonUI/general/res/sass/controls/_buttons.scss b/platform/commonUI/general/res/sass/controls/_buttons.scss index 956e144899..5431b0f563 100644 --- a/platform/commonUI/general/res/sass/controls/_buttons.scss +++ b/platform/commonUI/general/res/sass/controls/_buttons.scss @@ -225,6 +225,11 @@ $pad: $interiorMargin * $baseRatio; overflow: hidden; word-break: break-all; + &.collapsed { + $d: $uePaneMiniTabCollapsedW; + width: $d; font-size: $d; + } + &:before, &:after { position: absolute; diff --git a/platform/commonUI/general/res/sass/user-environ/_layout.scss b/platform/commonUI/general/res/sass/user-environ/_layout.scss index 4800cdeb6d..e6e6ba5f93 100644 --- a/platform/commonUI/general/res/sass/user-environ/_layout.scss +++ b/platform/commonUI/general/res/sass/user-environ/_layout.scss @@ -19,23 +19,6 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -@mixin cols($totalCols, $span) { - $cw: 100% / $totalCols; - min-width: (500px / $totalCols) * $span; - @if ($totalCols != $span) { - width: ($cw * $span) - $ueColMargin; - } @else { - width: $cw; - } -} - -/*.holder-all { - $myM: 0; // $interiorMarginSm; - top: $myM; - right: $myM; - bottom: $myM; - left: $myM; -}*/ .browse-area, .edit-area, @@ -158,67 +141,6 @@ } } -.cols { - @include clearfix; - .col { - @include box-sizing(border-box); - @include clearfix; - // background: rgba(#ffcc00, 0.2); - float: left; - margin-left: $ueColMargin; - padding-left: $interiorMargin; - position: relative; - &:first-child { - margin-left: 0; - padding-left: 0; - } - } - &.cols-2 { - $nc: 2; - .col-1 { - @include cols($nc, 1); - } - } - &.cols-2-ff { - // 2 columns, first column is fixed, second is fluid - .col-100px { - width: 100px; - } - } - - &.cols-6 { - $nc: 6; - .col-1 { - @include cols($nc, 1); - } - } - &.cols-16 { - $nc: 16; - .col-1 { - @include cols($nc, 1); - } - .col-2 { - @include cols($nc, 2); - } - .col-7 { - @include cols($nc, 7); - } - } - &.cols-32 { - $nc: 32; - .col-2 { - @include cols($nc, 2); - } - .col-15 { - @include cols($nc, 15); - } - } - .l-row { - @include clearfix; - padding: $interiorMargin 0; - } -} - .browse-mode { .split-layout { .split-pane-component.pane { @@ -427,7 +349,7 @@ .object-browse-bar { //@include test(blue); - @include absPosDefault(0, visible); + @include absPosDefault(0, hidden); @include box-sizing(border-box); height: $ueTopBarH; line-height: $ueTopBarH; @@ -443,16 +365,6 @@ } } -.l-flex { - @include webkitVal('display', 'flex'); - @include webkitProp('flex-flow', 'row nowrap'); - .left { - //@include test(red); - @include webkitProp(flex, '1 1 0'); - padding-right: $interiorMarginLg; - } -} - // When the tree is hidden, these are the // classes used for the left menu and the // right representation. @@ -464,25 +376,6 @@ .holder-create-and-search { opacity: 0; } - /*.holder-create-and-search { - @include trans-prop-nice((top, left), 250ms); - top: $ueTopBarH + $interiorMargin; - left: -1 * $bodyMargin !important; - .create-btn { - @include border-left-radius(0); - @include trans-prop-nice((width), 250ms); - width: $uePaneMiniTabW !important; - text-align: center !important; - padding: 0; - .title-label, - &:after { - display: none; - } - &:before { - font-size: 9px; - } - } - }*/ } .pane-tree-showing { diff --git a/platform/commonUI/general/res/templates/object-inspector.html b/platform/commonUI/general/res/templates/object-inspector.html index 83ed591ff7..cf111a3695 100644 --- a/platform/commonUI/general/res/templates/object-inspector.html +++ b/platform/commonUI/general/res/templates/object-inspector.html @@ -20,9 +20,9 @@ at runtime from the About dialog for additional information. --> <span class="l-inspect" ng-controller="ObjectInspectorController as controller"> - <div class="abs holder holder-inspector-elements"> - <div class="pane-header">Inspection</div> - <ul> + <div class="abs holder holder-inspector-elements l-flex-col"> + <div class="pane-header flex-elem">Inspection</div> + <ul class="flex-elem grows vscroll"> <li> <em>Properties</em> <div class="inspector-properties" diff --git a/platform/commonUI/general/src/StyleSheetLoader.js b/platform/commonUI/general/src/StyleSheetLoader.js index 19c0ffc291..9b64303df1 100644 --- a/platform/commonUI/general/src/StyleSheetLoader.js +++ b/platform/commonUI/general/src/StyleSheetLoader.js @@ -38,8 +38,9 @@ define( * @constructor * @param {object[]} stylesheets stylesheet extension definitions * @param $document Angular's jqLite-wrapped document element + * @param {string} activeTheme the theme in use */ - function StyleSheetLoader(stylesheets, $document) { + function StyleSheetLoader(stylesheets, $document, activeTheme) { var head = $document.find('head'), document = $document[0]; @@ -62,8 +63,15 @@ define( head.append(link); } + // Stylesheets which specify themes should only be applied + // when that theme has been declared. + function matchesTheme(stylesheet) { + return stylesheet.theme === undefined || + stylesheet.theme === activeTheme; + } + // Add all stylesheets from extensions - stylesheets.forEach(addStyleSheet); + stylesheets.filter(matchesTheme).forEach(addStyleSheet); } return StyleSheetLoader; diff --git a/platform/commonUI/general/test/StyleSheetLoaderSpec.js b/platform/commonUI/general/test/StyleSheetLoaderSpec.js index b2c1a7da93..c1db25fb0a 100644 --- a/platform/commonUI/general/test/StyleSheetLoaderSpec.js +++ b/platform/commonUI/general/test/StyleSheetLoaderSpec.js @@ -32,10 +32,11 @@ define( mockPlainDocument, mockHead, mockElement, + testBundle, loader; beforeEach(function () { - var testBundle = { + testBundle = { path: "a/b", resources: "c" }; @@ -72,6 +73,40 @@ define( expect(mockElement.setAttribute) .toHaveBeenCalledWith('href', "a/b/c/d.css"); }); + + describe("for themed stylesheets", function () { + var testTheme = "test-theme"; + + beforeEach(function () { + testStyleSheets = [{ + stylesheetUrl: "themed.css", + bundle: testBundle, + theme: testTheme + }, { + stylesheetUrl: "bad-theme.css", + bundle: testBundle, + theme: 'bad-theme' + }]; + + loader = new StyleSheetLoader( + testStyleSheets, + mockDocument, + testTheme + ); + }); + + it("includes matching themes", function () { + expect(mockElement.setAttribute) + .toHaveBeenCalledWith('href', "a/b/c/themed.css"); + }); + + it("excludes mismatching themes", function () { + expect(mockElement.setAttribute) + .not.toHaveBeenCalledWith('href', "a/b/c/bad-theme.css"); + }); + }); + + }); } ); diff --git a/platform/commonUI/themes/espresso/bundle.json b/platform/commonUI/themes/espresso/bundle.json index 37cab3e412..94c7259027 100644 --- a/platform/commonUI/themes/espresso/bundle.json +++ b/platform/commonUI/themes/espresso/bundle.json @@ -1,12 +1,18 @@ { - "name": "Espresso", - "description": "Espresso theme: dark and rich", - "extensions": { - "stylesheets": [ - { - "stylesheetUrl": "css/theme-espresso.css", - "priority": 1000 - } - ] - } -} \ No newline at end of file + "name": "Espresso", + "description": "Espresso theme: dark and rich", + "extensions": { + "stylesheets": [ + { + "stylesheetUrl": "css/theme-espresso.css", + "priority": 1000 + } + ], + "constants": [ + { + "key": "THEME", + "value": "espresso" + } + ] + } +} diff --git a/platform/commonUI/themes/espresso/res/css/theme-espresso.css b/platform/commonUI/themes/espresso/res/css/theme-espresso.css index f60ef90791..506a023511 100644 --- a/platform/commonUI/themes/espresso/res/css/theme-espresso.css +++ b/platform/commonUI/themes/espresso/res/css/theme-espresso.css @@ -20,7 +20,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/* line 5, ../../../../../../../../../../../Library/Ruby/Gems/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, @@ -41,38 +41,38 @@ time, mark, audio, video { font-size: 100%; vertical-align: baseline; } -/* line 22, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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; } @@ -306,7 +306,7 @@ a.disabled { *****************************************************************************/ /************************** FONTS */ @font-face { - /* + /* * Use https://icomoon.io/app with /platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json */ font-family: 'symbolsfont'; @@ -428,6 +428,119 @@ mct-container { .sep { color: rgba(255, 255, 255, 0.2); } +/***************************************************************************** + * 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. + *****************************************************************************/ +/********************************************* COLUMN LAYOUTS STYLES */ +/* line 34, ../../../../general/res/sass/_archetypes.scss */ +.cols { + overflow: hidden; + *zoom: 1; } + /* line 36, ../../../../general/res/sass/_archetypes.scss */ + .cols .col { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + overflow: hidden; + *zoom: 1; + float: left; + margin-left: 1.5%; + padding-left: 5px; + position: relative; } + /* line 44, ../../../../general/res/sass/_archetypes.scss */ + .cols .col:first-child { + margin-left: 0; + padding-left: 0; } + /* line 51, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-2 .col-1 { + min-width: 250px; + width: 48.5%; } + /* line 57, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-2-ff .col-100px { + width: 100px; } + /* line 64, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-6 .col-1 { + min-width: 83.33333px; + width: 15.16667%; } + /* line 70, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-16 .col-1 { + min-width: 31.25px; + width: 4.75%; } + /* line 73, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-16 .col-2 { + min-width: 62.5px; + width: 11%; } + /* line 76, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-16 .col-7 { + min-width: 218.75px; + width: 42.25%; } + /* line 82, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-32 .col-2 { + min-width: 31.25px; + width: 4.75%; } + /* line 85, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-32 .col-15 { + min-width: 234.375px; + width: 45.375%; } + /* line 89, ../../../../general/res/sass/_archetypes.scss */ + .cols .l-row { + overflow: hidden; + *zoom: 1; + padding: 5px 0; } + +/********************************************* FLEX STYLES */ +/* line 96, ../../../../general/res/sass/_archetypes.scss */ +.l-flex-row, .l-flex, +.l-flex-col { + display: -webkit-flex; + display: flex; + -webkit-flex-wrap: nowrap; + flex-wrap: nowrap; } + /* line 101, ../../../../general/res/sass/_archetypes.scss */ + .l-flex-row .flex-elem:not(.grows), .l-flex .flex-elem:not(.grows), + .l-flex-col .flex-elem:not(.grows) { + -webkit-flex: 0 1 auto; + flex: 0 1 auto; } + /* line 104, ../../../../general/res/sass/_archetypes.scss */ + .l-flex-row .flex-elem.grows, .l-flex .flex-elem.grows, + .l-flex-col .flex-elem.grows { + -webkit-flex: 1 1 auto; + flex: 1 1 auto; } + +/* line 110, ../../../../general/res/sass/_archetypes.scss */ +.l-flex-row, .l-flex { + -webkit-flex-direction: row; + flex-direction: row; } + +/* line 111, ../../../../general/res/sass/_archetypes.scss */ +.l-flex-col { + -webkit-flex-direction: column; + flex-direction: column; } + +/* line 115, ../../../../general/res/sass/_archetypes.scss */ +.l-flex .left { + -webkit-flex: 1 1 0; + flex: 1 1 0; + padding-right: 10px; } + /***************************************************************************** * Open MCT Web, Copyright (c) 2014-2015, United States Government * as represented by the Administrator of the National Aeronautics and Space @@ -1044,11 +1157,11 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { background-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0.05) 70%, rgba(0, 0, 0, 0.2) 100%); } /*.browse-area .splitter { - top: 0; //$ueTopBarH + $interiorMarginLg; + top: 0; //$ueTopBarH + $interiorMarginLg; } .edit-area .splitter { - top: 0; + top: 0; }*/ /***************************************************************************** * Open MCT Web, Copyright (c) 2014-2015, United States Government @@ -1299,14 +1412,20 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { margin-right: 5px; vertical-align: bottom; } /* line 47, ../../../../general/res/sass/_inspector.scss */ + .l-inspect ul { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + padding-right: 5px; } + /* line 52, ../../../../general/res/sass/_inspector.scss */ .l-inspect ul li, .l-inspect em { display: block; position: relative; } - /* line 53, ../../../../general/res/sass/_inspector.scss */ + /* line 58, ../../../../general/res/sass/_inspector.scss */ .l-inspect ul li { margin-bottom: 10px; } - /* line 57, ../../../../general/res/sass/_inspector.scss */ + /* line 62, ../../../../general/res/sass/_inspector.scss */ .l-inspect em { -moz-border-radius: 3px; -webkit-border-radius: 3px; @@ -1316,34 +1435,34 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { margin-bottom: 5px; padding: 5px 5px; text-transform: uppercase; } - /* line 66, ../../../../general/res/sass/_inspector.scss */ + /* line 71, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-properties { padding: 3px 0; } - /* line 67, ../../../../general/res/sass/_inspector.scss */ + /* line 72, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-properties:not(.first) { border-top: 1px solid #474747; } - /* line 71, ../../../../general/res/sass/_inspector.scss */ + /* line 76, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-properties .label { color: #737373; text-transform: uppercase; } - /* line 75, ../../../../general/res/sass/_inspector.scss */ + /* line 80, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-properties .value { color: #bfbfbf; word-break: break-all; } - /* line 83, ../../../../general/res/sass/_inspector.scss */ + /* line 88, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-location .location-item { cursor: pointer; display: inline-block; position: relative; padding: 2px 4px; } - /* line 88, ../../../../general/res/sass/_inspector.scss */ + /* line 93, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-location .location-item:hover { background: rgba(153, 153, 153, 0.1); color: #cccccc; } - /* line 91, ../../../../general/res/sass/_inspector.scss */ + /* line 96, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-location .location-item:hover .icon, .l-inspect .inspector-location .location-item:hover .t-item-icon { color: #33ccff; } - /* line 96, ../../../../general/res/sass/_inspector.scss */ + /* line 101, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-location:not(.last) .t-object-label .t-title-label:after { color: #737373; content: '\3e'; @@ -1776,26 +1895,30 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { overflow: hidden; word-break: break-all; } /* line 228, ../../../../general/res/sass/controls/_buttons.scss */ + .mini-tab-icon.collapsed { + width: 11px; + font-size: 11px; } + /* line 233, ../../../../general/res/sass/controls/_buttons.scss */ .mini-tab-icon:before, .mini-tab-icon:after { position: absolute; display: inherit; } - /* line 234, ../../../../general/res/sass/controls/_buttons.scss */ + /* line 239, ../../../../general/res/sass/controls/_buttons.scss */ .mini-tab-icon:before { content: '\78'; } - /* line 238, ../../../../general/res/sass/controls/_buttons.scss */ + /* line 243, ../../../../general/res/sass/controls/_buttons.scss */ .mini-tab-icon:hover { color: #0099cc; } } -/* line 245, ../../../../general/res/sass/controls/_buttons.scss */ +/* line 250, ../../../../general/res/sass/controls/_buttons.scss */ .l-btn-set { font-size: 0; } - /* line 251, ../../../../general/res/sass/controls/_buttons.scss */ + /* line 256, ../../../../general/res/sass/controls/_buttons.scss */ .l-btn-set .s-btn, .l-btn-set .s-menu-btn { -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; margin-left: 1px; } - /* line 257, ../../../../general/res/sass/controls/_buttons.scss */ + /* line 262, ../../../../general/res/sass/controls/_buttons.scss */ .l-btn-set .first .s-btn, .l-btn-set .first .s-menu-btn { -moz-border-radius-topleft: 3px; -webkit-border-top-left-radius: 3px; @@ -1804,7 +1927,7 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { -webkit-border-bottom-left-radius: 3px; border-bottom-left-radius: 3px; margin-left: 0; } - /* line 264, ../../../../general/res/sass/controls/_buttons.scss */ + /* line 269, ../../../../general/res/sass/controls/_buttons.scss */ .l-btn-set .last .s-btn, .l-btn-set .last .s-menu-btn { -moz-border-radius-topright: 3px; -webkit-border-top-right-radius: 3px; @@ -1813,7 +1936,7 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { -webkit-border-bottom-right-radius: 3px; border-bottom-right-radius: 3px; } -/* line 271, ../../../../general/res/sass/controls/_buttons.scss */ +/* line 276, ../../../../general/res/sass/controls/_buttons.scss */ .paused:not(.s-btn):not(.s-menu-btn) { border-color: #c56f01 !important; color: #c56f01 !important; } @@ -2118,23 +2241,23 @@ label.checkbox.custom { /* line 204, ../../../../general/res/sass/controls/_controls.scss */ .object-header { font-size: 1em; } - /* line 236, ../../../../general/res/sass/controls/_controls.scss */ + /* line 208, ../../../../general/res/sass/controls/_controls.scss */ .object-header > .type-icon { color: #cccccc; font-size: 120%; float: left; margin-right: 5px; } - /* line 222, ../../../../general/res/sass/controls/_controls.scss */ + /* line 215, ../../../../general/res/sass/controls/_controls.scss */ .object-header .l-elem-wrapper { -webkit-justify-content: flex-start; justify-content: flex-start; } - /* line 225, ../../../../general/res/sass/controls/_controls.scss */ + /* line 218, ../../../../general/res/sass/controls/_controls.scss */ .object-header .l-elem-wrapper mct-representation { min-width: 0.7em; } - /* line 233, ../../../../general/res/sass/controls/_controls.scss */ + /* line 226, ../../../../general/res/sass/controls/_controls.scss */ .object-header .action { margin-right: 5px; } - /* line 237, ../../../../general/res/sass/controls/_controls.scss */ + /* line 230, ../../../../general/res/sass/controls/_controls.scss */ .object-header .title-label { color: #999; overflow: hidden; @@ -2143,13 +2266,13 @@ label.checkbox.custom { flex: 0 1 auto; -webkit-flex: 0 1 auto; padding-right: 0.35em; } - /* line 269, ../../../../general/res/sass/controls/_controls.scss */ + /* line 240, ../../../../general/res/sass/controls/_controls.scss */ .object-header .context-available { font-size: 0.7em; flex: 0 0 1; -webkit-flex: 0 0 1; } @media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) { - /* line 276, ../../../../general/res/sass/controls/_controls.scss */ + /* line 247, ../../../../general/res/sass/controls/_controls.scss */ .object-header .context-available { -moz-transition-property: opacity; -o-transition-property: opacity; @@ -2168,7 +2291,7 @@ label.checkbox.custom { -webkit-transition-delay: 0; transition-delay: 0; opacity: 0; } - /* line 259, ../../../../general/res/sass/controls/_controls.scss */ + /* line 252, ../../../../general/res/sass/controls/_controls.scss */ .object-header:hover .context-available { opacity: 1; } } @@ -2182,12 +2305,12 @@ label.checkbox.custom { @keyframes progress { 100% { background-position: 20px center; } } -/* line 281, ../../../../general/res/sass/controls/_controls.scss */ +/* line 274, ../../../../general/res/sass/controls/_controls.scss */ .l-progress-bar { display: inline-block; overflow: hidden; position: relative; } - /* line 287, ../../../../general/res/sass/controls/_controls.scss */ + /* line 280, ../../../../general/res/sass/controls/_controls.scss */ .l-progress-bar .progress-amt-holder { overflow: hidden; position: absolute; @@ -2197,7 +2320,7 @@ label.checkbox.custom { left: 1px; width: auto; height: auto; } - /* line 290, ../../../../general/res/sass/controls/_controls.scss */ + /* line 283, ../../../../general/res/sass/controls/_controls.scss */ .l-progress-bar .progress-amt, .l-progress-bar .progress-amt:before, .l-progress-bar .progress-amt:after { @@ -2211,14 +2334,14 @@ label.checkbox.custom { height: auto; display: block; content: ''; } - /* line 298, ../../../../general/res/sass/controls/_controls.scss */ + /* line 291, ../../../../general/res/sass/controls/_controls.scss */ .l-progress-bar .progress-amt { right: auto; } - /* line 303, ../../../../general/res/sass/controls/_controls.scss */ + /* line 296, ../../../../general/res/sass/controls/_controls.scss */ .l-progress-bar.indeterminate .progress-amt { width: 100% !important; } -/* line 309, ../../../../general/res/sass/controls/_controls.scss */ +/* line 302, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar { -moz-border-radius: 3px; -webkit-border-radius: 3px; @@ -2227,7 +2350,7 @@ label.checkbox.custom { -webkit-box-shadow: inset rgba(0, 0, 0, 0.3) 0 1px 4px; box-shadow: inset rgba(0, 0, 0, 0.3) 0 1px 4px; background: rgba(0, 0, 0, 0.1); } - /* line 314, ../../../../general/res/sass/controls/_controls.scss */ + /* line 307, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar .progress-amt { -moz-border-radius: 3px; -webkit-border-radius: 3px; @@ -2254,10 +2377,10 @@ label.checkbox.custom { -o-transition-delay: 0; -webkit-transition-delay: 0; transition-delay: 0; } - /* line 319, ../../../../general/res/sass/controls/_controls.scss */ + /* line 312, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar .progress-amt:before { background-color: #0099cc; } - /* line 322, ../../../../general/res/sass/controls/_controls.scss */ + /* line 315, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar .progress-amt:after { background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjMwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background-size: 100%; @@ -2265,7 +2388,7 @@ label.checkbox.custom { background-image: -moz-linear-gradient(rgba(0, 0, 0, 0) 5%, rgba(255, 255, 255, 0.25) 30%, rgba(0, 0, 0, 0) 100%); background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0) 5%, rgba(255, 255, 255, 0.25) 30%, rgba(0, 0, 0, 0) 100%); background-image: linear-gradient(rgba(0, 0, 0, 0) 5%, rgba(255, 255, 255, 0.25) 30%, rgba(0, 0, 0, 0) 100%); } - /* line 331, ../../../../general/res/sass/controls/_controls.scss */ + /* line 324, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar:not(.indeterminate) .progress-amt:before { -moz-animation: progress 0.4s linear infinite; -webkit-animation: progress 0.4s linear infinite; @@ -2278,7 +2401,7 @@ label.checkbox.custom { background-position: 0 center; background-repeat: repeat-x; background-size: 20px 40%; } - /* line 339, ../../../../general/res/sass/controls/_controls.scss */ + /* line 332, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar.indeterminate .progress-amt:before { -moz-animation: progress 0.6s linear infinite; -webkit-animation: progress 0.6s linear infinite; @@ -2290,12 +2413,12 @@ label.checkbox.custom { background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.2) 25%, rgba(0, 0, 0, 0) 25%, rgba(0, 0, 0, 0) 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, rgba(0, 0, 0, 0) 75%, rgba(0, 0, 0, 0) 100%); background-repeat: repeat; background-size: 20px 20px; } - /* line 344, ../../../../general/res/sass/controls/_controls.scss */ + /* line 337, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar.indeterminate .progress-amt:after { display: none; } /******************************************************** SLIDERS */ -/* line 352, ../../../../general/res/sass/controls/_controls.scss */ +/* line 345, ../../../../general/res/sass/controls/_controls.scss */ .slider .slot { width: auto; position: absolute; @@ -2303,7 +2426,7 @@ label.checkbox.custom { right: 0; bottom: 0; left: 0; } -/* line 362, ../../../../general/res/sass/controls/_controls.scss */ +/* line 355, ../../../../general/res/sass/controls/_controls.scss */ .slider .knob { -moz-transition-property: opacity, background-color, border-color, color; -o-transition-property: opacity, background-color, border-color, color; @@ -2329,10 +2452,10 @@ label.checkbox.custom { auto: 0; bottom: auto; left: auto; } - /* line 307, ../../../../general/res/sass/controls/_controls.scss */ + /* line 358, ../../../../general/res/sass/controls/_controls.scss */ .slider .knob:hover { background-color: #0099cc; } -/* line 318, ../../../../general/res/sass/controls/_controls.scss */ +/* line 369, ../../../../general/res/sass/controls/_controls.scss */ .slider .knob-l { -moz-border-radius-topleft: 10px; -webkit-border-top-left-radius: 10px; @@ -2341,7 +2464,7 @@ label.checkbox.custom { -webkit-border-bottom-left-radius: 10px; border-bottom-left-radius: 10px; cursor: w-resize; } -/* line 322, ../../../../general/res/sass/controls/_controls.scss */ +/* line 373, ../../../../general/res/sass/controls/_controls.scss */ .slider .knob-r { -moz-border-radius-topright: 10px; -webkit-border-top-right-radius: 10px; @@ -2350,7 +2473,7 @@ label.checkbox.custom { -webkit-border-bottom-right-radius: 10px; border-bottom-right-radius: 10px; cursor: e-resize; } -/* line 326, ../../../../general/res/sass/controls/_controls.scss */ +/* line 377, ../../../../general/res/sass/controls/_controls.scss */ .slider .range { -moz-transition-property: opacity, background-color, border-color, color; -o-transition-property: opacity, background-color, border-color, color; @@ -2377,12 +2500,12 @@ label.checkbox.custom { left: auto; height: auto; width: auto; } - /* line 337, ../../../../general/res/sass/controls/_controls.scss */ + /* line 388, ../../../../general/res/sass/controls/_controls.scss */ .slider .range:hover { background-color: rgba(0, 153, 204, 0.5); } /******************************************************** DATETIME PICKER */ -/* line 344, ../../../../general/res/sass/controls/_controls.scss */ +/* line 395, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker { -moz-user-select: -moz-none; -ms-user-select: none; @@ -2391,65 +2514,65 @@ label.checkbox.custom { font-size: 0.8rem; padding: 10px !important; width: 230px; } - /* line 350, ../../../../general/res/sass/controls/_controls.scss */ + /* line 401, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager { height: 15px; margin-bottom: 5px; position: relative; } - /* line 420, ../../../../general/res/sass/controls/_controls.scss */ + /* line 413, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .pager { width: 20px; } - /* line 423, ../../../../general/res/sass/controls/_controls.scss */ + /* line 416, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .pager.prev { right: auto; } - /* line 425, ../../../../general/res/sass/controls/_controls.scss */ + /* line 418, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .pager.prev:before { content: "\3c"; } - /* line 429, ../../../../general/res/sass/controls/_controls.scss */ + /* line 422, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .pager.next { left: auto; text-align: right; } - /* line 432, ../../../../general/res/sass/controls/_controls.scss */ + /* line 425, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .pager.next:before { content: "\3e"; } - /* line 437, ../../../../general/res/sass/controls/_controls.scss */ + /* line 430, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .val { text-align: center; left: 25px; right: 25px; } - /* line 443, ../../../../general/res/sass/controls/_controls.scss */ + /* line 436, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-calendar, .l-datetime-picker .l-time-selects { border-top: 1px solid rgba(153, 153, 153, 0.1); } - /* line 447, ../../../../general/res/sass/controls/_controls.scss */ + /* line 440, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-time-selects { line-height: 22px; } /******************************************************** CALENDAR */ -/* line 397, ../../../../general/res/sass/controls/_controls.scss */ +/* line 448, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row { display: -webkit-flex; display: flex; -webkit-flex-flow: row nowrap; flex-flow: row nowrap; margin-top: 1px; } - /* line 459, ../../../../general/res/sass/controls/_controls.scss */ + /* line 452, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row:first-child { margin-top: 0; } - /* line 462, ../../../../general/res/sass/controls/_controls.scss */ + /* line 455, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row li { -webkit-flex: 1 0; flex: 1 0; margin-left: 1px; padding: 5px; text-align: center; } - /* line 468, ../../../../general/res/sass/controls/_controls.scss */ + /* line 461, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row li:first-child { margin-left: 0; } - /* line 472, ../../../../general/res/sass/controls/_controls.scss */ + /* line 465, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-header li { color: #b3b3b3; } - /* line 475, ../../../../general/res/sass/controls/_controls.scss */ + /* line 468, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li { -moz-transition-property: background-color; -o-transition-property: background-color; @@ -2468,31 +2591,31 @@ label.checkbox.custom { -webkit-transition-delay: 0; transition-delay: 0; cursor: pointer; } - /* line 478, ../../../../general/res/sass/controls/_controls.scss */ + /* line 471, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li.in-month { background-color: #616161; } - /* line 481, ../../../../general/res/sass/controls/_controls.scss */ + /* line 474, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li .sub { color: #b3b3b3; font-size: 0.8em; } - /* line 485, ../../../../general/res/sass/controls/_controls.scss */ + /* line 478, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li.selected { background: #006080; color: #cccccc; } - /* line 488, ../../../../general/res/sass/controls/_controls.scss */ + /* line 481, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li.selected .sub { color: inherit; } - /* line 492, ../../../../general/res/sass/controls/_controls.scss */ + /* line 485, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li:hover { background-color: #0099cc; color: #fff; } - /* line 495, ../../../../general/res/sass/controls/_controls.scss */ + /* line 488, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li:hover .sub { color: inherit; } /******************************************************** BROWSER ELEMENTS */ @media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) { - /* line 448, ../../../../general/res/sass/controls/_controls.scss */ + /* line 499, ../../../../general/res/sass/controls/_controls.scss */ ::-webkit-scrollbar { -moz-border-radius: 2px; -webkit-border-radius: 2px; @@ -2507,7 +2630,7 @@ label.checkbox.custom { height: 10px; width: 10px; } - /* line 457, ../../../../general/res/sass/controls/_controls.scss */ + /* line 508, ../../../../general/res/sass/controls/_controls.scss */ ::-webkit-scrollbar-thumb { background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzU5NTk1OSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzRkNGQ0ZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background-size: 100%; @@ -2521,7 +2644,7 @@ label.checkbox.custom { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - /* line 466, ../../../../general/res/sass/controls/_controls.scss */ + /* line 517, ../../../../general/res/sass/controls/_controls.scss */ ::-webkit-scrollbar-thumb:hover { background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzVlNWU1ZSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzUyNTI1MiIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background-size: 100%; @@ -2530,7 +2653,7 @@ label.checkbox.custom { background-image: -webkit-linear-gradient(#5e5e5e, #525252 20px); background-image: linear-gradient(#5e5e5e, #525252 20px); } - /* line 471, ../../../../general/res/sass/controls/_controls.scss */ + /* line 522, ../../../../general/res/sass/controls/_controls.scss */ ::-webkit-scrollbar-corner { background: rgba(0, 0, 0, 0.4); } } /***************************************************************************** @@ -3918,15 +4041,15 @@ textarea { /* line 29, ../../../../general/res/sass/forms/_datetime.scss */ .complex.datetime { /* - .field-hints, - .fields { - } - - - .field-hints { - - } - */ } + .field-hints, + .fields { + } + + + .field-hints { + + } + */ } /* line 30, ../../../../general/res/sass/forms/_datetime.scss */ .complex.datetime span { display: inline-block; @@ -4173,26 +4296,19 @@ span.req { * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/*.holder-all { - $myM: 0; // $interiorMarginSm; - top: $myM; - right: $myM; - bottom: $myM; - left: $myM; -}*/ -/* line 40, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 23, ../../../../general/res/sass/user-environ/_layout.scss */ .browse-area, .edit-area, .editor { position: absolute; } -/* line 46, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 29, ../../../../general/res/sass/user-environ/_layout.scss */ .editor { -moz-border-radius: 4.5px; -webkit-border-radius: 4.5px; border-radius: 4.5px; } -/* line 50, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 33, ../../../../general/res/sass/user-environ/_layout.scss */ .contents { box-sizing: border-box; position: absolute; @@ -4200,21 +4316,21 @@ span.req { right: 0; bottom: 0; left: 0; } - /* line 58, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 41, ../../../../general/res/sass/user-environ/_layout.scss */ .contents.nomargin { right: 0px; bottom: 0px; left: 0px; } -/* line 67, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 50, ../../../../general/res/sass/user-environ/_layout.scss */ .bar .icon.major, .bar .major.t-item-icon { margin-right: 5px; } -/* line 70, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 53, ../../../../general/res/sass/user-environ/_layout.scss */ .bar.abs, .bar.l-inspect, .l-datetime-picker .l-month-year-pager .bar.pager, .l-datetime-picker .l-month-year-pager .bar.val, .s-menu-btn span.bar.l-click-area { text-wrap: none; white-space: nowrap; } - /* line 73, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 56, ../../../../general/res/sass/user-environ/_layout.scss */ .bar.abs.left, .bar.left.l-inspect, .l-datetime-picker .l-month-year-pager .bar.left.pager, .l-datetime-picker .l-month-year-pager .bar.left.val, .s-menu-btn span.bar.left.l-click-area, .bar.abs .left, @@ -4224,7 +4340,7 @@ span.req { .s-menu-btn span.bar.l-click-area .left { width: 45%; right: auto; } - /* line 78, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 61, ../../../../general/res/sass/user-environ/_layout.scss */ .bar.abs.right, .bar.right.l-inspect, .l-datetime-picker .l-month-year-pager .bar.right.pager, .l-datetime-picker .l-month-year-pager .bar.right.val, .s-menu-btn span.bar.right.l-click-area, .bar.abs .right, @@ -4235,7 +4351,7 @@ span.req { width: 45%; left: auto; text-align: right; } - /* line 83, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 66, ../../../../general/res/sass/user-environ/_layout.scss */ .bar.abs.right .icon.major, .bar.right.l-inspect .icon.major, .l-datetime-picker .l-month-year-pager .bar.right.pager .icon.major, .l-datetime-picker .l-month-year-pager .bar.right.val .icon.major, .s-menu-btn span.bar.right.l-click-area .icon.major, .bar.abs.right .major.t-item-icon, .bar.right.l-inspect .major.t-item-icon, .l-datetime-picker .l-month-year-pager .bar.right.pager .major.t-item-icon, .l-datetime-picker .l-month-year-pager .bar.right.val .major.t-item-icon, .s-menu-btn span.bar.right.l-click-area .major.t-item-icon, @@ -4250,7 +4366,7 @@ span.req { .l-datetime-picker .l-month-year-pager .bar.val .right .major.t-item-icon, .s-menu-btn span.bar.l-click-area .right .major.t-item-icon { margin-left: 15px; } - /* line 89, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 72, ../../../../general/res/sass/user-environ/_layout.scss */ .bar.abs .l-flex .left, .bar.l-inspect .l-flex .left, .l-datetime-picker .l-month-year-pager .bar.pager .l-flex .left, .l-datetime-picker .l-month-year-pager .bar.val .l-flex .left, .s-menu-btn span.bar.l-click-area .l-flex .left, .bar.abs .l-flex .right, @@ -4266,34 +4382,34 @@ span.req { .s-menu-btn span.bar.l-flex.l-click-area .right { width: auto; } -/* line 98, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 81, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .browse-area, .user-environ .editor { top: 0; left: 0; right: 0; bottom: 25px; } -/* line 105, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 88, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .browse-area > .contents, .user-environ .edit-area > .contents { left: 0; right: 0; } -/* line 111, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 94, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .edit-area { top: 45px; left: 10px; right: 10px; bottom: 35px; } - /* line 117, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 100, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .edit-area .tool-bar { bottom: auto; height: 30px; line-height: 25px; } - /* line 122, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 105, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .edit-area .object-holder.work-area { top: 40px; overflow: auto; } -/* line 129, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 112, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .ue-bottom-bar { overflow: hidden; position: absolute; @@ -4309,7 +4425,7 @@ span.req { background: #000; color: gray; font-size: .7rem; } - /* line 138, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 121, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .ue-bottom-bar .status-holder { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; @@ -4328,7 +4444,7 @@ span.req { right: 120px; text-transform: uppercase; z-index: 1; } - /* line 147, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 130, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .ue-bottom-bar .app-logo { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; @@ -4345,143 +4461,87 @@ span.req { left: auto; width: 105px; z-index: 2; } - /* line 154, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 137, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .ue-bottom-bar .app-logo.logo-openmctweb { background: url("../../../../general/res/images/logo-openmctweb.svg") no-repeat center center; } -/* line 161, ../../../../general/res/sass/user-environ/_layout.scss */ -.cols { - overflow: hidden; - *zoom: 1; } - /* line 163, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols .col { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - overflow: hidden; - *zoom: 1; - float: left; - margin-left: 1.5%; - padding-left: 5px; - position: relative; } - /* line 171, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols .col:first-child { - margin-left: 0; - padding-left: 0; } - /* line 178, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-2 .col-1 { - min-width: 250px; - width: 48.5%; } - /* line 184, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-2-ff .col-100px { - width: 100px; } - /* line 191, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-6 .col-1 { - min-width: 83.33333px; - width: 15.16667%; } - /* line 197, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-16 .col-1 { - min-width: 31.25px; - width: 4.75%; } - /* line 200, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-16 .col-2 { - min-width: 62.5px; - width: 11%; } - /* line 203, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-16 .col-7 { - min-width: 218.75px; - width: 42.25%; } - /* line 209, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-32 .col-2 { - min-width: 31.25px; - width: 4.75%; } - /* line 212, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-32 .col-15 { - min-width: 234.375px; - width: 45.375%; } - /* line 216, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols .l-row { - overflow: hidden; - *zoom: 1; - padding: 5px 0; } - -/* line 226, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 148, ../../../../general/res/sass/user-environ/_layout.scss */ .browse-mode .split-layout .split-pane-component.pane.treeview.left { min-width: 150px; max-width: 800px; width: 25%; } -/* line 231, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 153, ../../../../general/res/sass/user-environ/_layout.scss */ .browse-mode .split-layout .split-pane-component.pane.t-inspect.right { min-width: 200px; max-width: 600px; width: 20%; } -/* line 243, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 165, ../../../../general/res/sass/user-environ/_layout.scss */ .edit-mode .split-layout .split-pane-component.pane.right { width: 15%; } - /* line 245, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 167, ../../../../general/res/sass/user-environ/_layout.scss */ .edit-mode .split-layout .split-pane-component.pane.right .pane.bottom { min-height: 50px; height: 30%; } -/* line 253, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 175, ../../../../general/res/sass/user-environ/_layout.scss */ .pane { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; position: absolute; } - /* line 257, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 179, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .pane-header { text-transform: uppercase; height: 24px; line-height: 24px; margin-bottom: 5px; } - /* line 264, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 186, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .primary-pane { z-index: 2; } - /* line 282, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 204, ../../../../general/res/sass/user-environ/_layout.scss */ .pane.treeview.left .search-holder { top: 34px; } - /* line 285, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 207, ../../../../general/res/sass/user-environ/_layout.scss */ .pane.treeview.left .tree-holder { overflow: auto; top: 64px; } - /* line 291, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 213, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane { z-index: 5; } @media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) { - /* line 291, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 213, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane { top: 10px; height: 24px; line-height: 24px; } - /* line 300, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 222, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane:after { opacity: 0; } - /* line 305, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 227, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.collapsed:before { opacity: 0; } - /* line 308, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 230, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.collapsed:after { opacity: 1; } - /* line 312, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 234, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-tree.anchor-left { left: 0; -moz-transform: translateX(-34px); -ms-transform: translateX(-34px); -webkit-transform: translateX(-34px); transform: translateX(-34px); } - /* line 315, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 237, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-tree.anchor-left:after { content: '\6d'; } - /* line 318, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 240, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-tree.anchor-left.collapsed { left: 0; - -moz-transform: translateX(-15px); - -ms-transform: translateX(-15px); - -webkit-transform: translateX(-15px); - transform: translateX(-15px); } - /* line 322, ../../../../general/res/sass/user-environ/_layout.scss */ + -moz-transform: translateX(-17px); + -ms-transform: translateX(-17px); + -webkit-transform: translateX(-17px); + transform: translateX(-17px); } + /* line 244, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-tree.anchor-left:not(.collapsed):before { -moz-transition-property: opacity; -o-transition-property: opacity; @@ -4499,16 +4559,16 @@ span.req { -o-transition-delay: 200ms; -webkit-transition-delay: 200ms; transition-delay: 200ms; } - /* line 326, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 248, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-inspect.anchor-right { right: 10px; } - /* line 328, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 250, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-inspect.anchor-right:after { content: '\e615'; } - /* line 331, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 253, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-inspect.anchor-right.collapsed { right: 5px; } } - /* line 340, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 262, ../../../../general/res/sass/user-environ/_layout.scss */ .pane.items .object-browse-bar .left.abs, .pane.items .object-browse-bar .left.l-inspect, .pane.items .object-browse-bar .l-datetime-picker .l-month-year-pager .left.pager, .l-datetime-picker .l-month-year-pager .pane.items .object-browse-bar .left.pager, .pane.items .object-browse-bar .l-datetime-picker .l-month-year-pager .left.val, .l-datetime-picker .l-month-year-pager .pane.items .object-browse-bar .left.val, .pane.items .object-browse-bar .s-menu-btn span.left.l-click-area, .s-menu-btn .pane.items .object-browse-bar span.left.l-click-area, @@ -4522,7 +4582,7 @@ span.req { .s-menu-btn .pane.items .object-browse-bar span.right.l-click-area { top: auto; } -/* line 348, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 270, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout { /* &.vertical { // Slides left and right @@ -4537,36 +4597,36 @@ span.req { } } }*/ } - /* line 351, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 273, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout.horizontal > .pane { margin-top: 5px; } - /* line 354, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 276, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout.horizontal > .pane:first-child { margin-top: 0; } - /* line 374, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 296, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout .holder.holder-create-and-search { top: 10px; right: 0; bottom: 10px; left: 10px; } - /* line 381, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 303, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout .holder.holder-object-and-inspector { top: 0; right: 0; bottom: 0; left: 0; } - /* line 386, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 308, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout .holder.holder-object-and-inspector .holder-object { top: 10px; bottom: 10px; } - /* line 390, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 312, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout .holder.holder-object-and-inspector .holder-inspector-elements { top: 10px; bottom: 10px; left: 10px; right: 10px; } -/* line 400, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 322, ../../../../general/res/sass/user-environ/_layout.scss */ .object-holder { overflow: auto; position: absolute; @@ -4577,11 +4637,11 @@ span.req { width: auto; height: auto; top: 34px; } - /* line 293, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 326, ../../../../general/res/sass/user-environ/_layout.scss */ .object-holder.l-controls-visible.l-time-controller-visible { bottom: 88px; } -/* line 299, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 332, ../../../../general/res/sass/user-environ/_layout.scss */ .object-browse-bar .s-btn, .object-browse-bar .s-menu-btn, .top-bar .buttons-main .s-btn, .top-bar .buttons-main .s-menu-btn, @@ -4593,14 +4653,14 @@ span.req { line-height: 25px; vertical-align: top; } -/* line 426, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 345, ../../../../general/res/sass/user-environ/_layout.scss */ .object-browse-bar .view-switcher, .top-bar .view-switcher { margin-right: 20px; } -/* line 431, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 350, ../../../../general/res/sass/user-environ/_layout.scss */ .object-browse-bar { - overflow: visible; + overflow: hidden; position: absolute; top: 0; right: 0; @@ -4614,55 +4674,22 @@ span.req { height: 24px; line-height: 24px; white-space: nowrap; } - /* line 439, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 358, ../../../../general/res/sass/user-environ/_layout.scss */ .object-browse-bar .left { padding-right: 20px; } - /* line 441, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 360, ../../../../general/res/sass/user-environ/_layout.scss */ .object-browse-bar .left .l-back { display: inline-block; float: left; margin-right: 10px; } -/* line 449, ../../../../general/res/sass/user-environ/_layout.scss */ -.l-flex { - display: flex; - display: -webkit-flex; - flex-flow: row nowrap; - -webkit-flex-flow: row nowrap; } - /* line 452, ../../../../general/res/sass/user-environ/_layout.scss */ - .l-flex .left { - flex: 1 1 0; - -webkit-flex: 1 1 0; - padding-right: 10px; } +/* line 374, ../../../../general/res/sass/user-environ/_layout.scss */ +.pane-tree-hidden .tree-holder, +.pane-tree-hidden .splitter-treeview, +.pane-tree-hidden .holder-create-and-search { + opacity: 0; } -/* line 462, ../../../../general/res/sass/user-environ/_layout.scss */ -.pane-tree-hidden { - /*.holder-create-and-search { - @include trans-prop-nice((top, left), 250ms); - top: $ueTopBarH + $interiorMargin; - left: -1 * $bodyMargin !important; - .create-btn { - @include border-left-radius(0); - @include trans-prop-nice((width), 250ms); - width: $uePaneMiniTabW !important; - text-align: center !important; - padding: 0; - .title-label, - &:after { - display: none; - } - &:before { - font-size: 9px; - } - } - }*/ } - /* line 465, ../../../../general/res/sass/user-environ/_layout.scss */ - .pane-tree-hidden .tree-holder, - .pane-tree-hidden .splitter-treeview, - .pane-tree-hidden .holder-create-and-search { - opacity: 0; } - -/* line 494, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 384, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-tree-showing .tree-holder, .pane-tree-showing .splitter-treeview { -moz-transition-property: opacity; @@ -4682,7 +4709,7 @@ span.req { -webkit-transition-delay: 250ms; transition-delay: 250ms; opacity: 1; } -/* line 500, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 390, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-tree-showing .holder-create-and-search { -moz-transition-property: opacity; -o-transition-property: opacity; @@ -4701,7 +4728,7 @@ span.req { -webkit-transition-delay: 200ms; transition-delay: 200ms; } -/* line 507, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 397, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-inspect-showing .l-object-and-inspector .l-inspect, .pane-inspect-showing .l-object-and-inspector .splitter-inspect { -moz-transition-property: opacity; @@ -4722,25 +4749,25 @@ span.req { transition-delay: 250ms; opacity: 1; } -/* line 516, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 406, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-inspect-hidden .l-object-and-inspector .l-inspect, .pane-inspect-hidden .l-object-and-inspector .splitter-inspect { opacity: 0; } @media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) { - /* line 524, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 414, ../../../../general/res/sass/user-environ/_layout.scss */ .pane.treeview.left .tree-holder { padding-right: 5px; } - /* line 528, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 418, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-tree-hidden .pane.right.primary-pane { - left: 20px !important; } + left: 22px !important; } - /* line 531, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 421, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-inspect-hidden .l-object-and-inspector .pane.left { - right: 20px !important; } + right: 22px !important; } - /* line 534, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 424, ../../../../general/res/sass/user-environ/_layout.scss */ .pane:not(.resizing) { -moz-transition-property: width, left, right; -o-transition-property: width, left, right; @@ -5948,9 +5975,9 @@ ul.tree { *****************************************************************************/ /* line 22, ../../../../general/res/sass/user-environ/_top-bar.scss */ .top-bar { - /* .title { - color: #fff; - }*/ } + /* .title { + color: #fff; + }*/ } /* line 23, ../../../../general/res/sass/user-environ/_top-bar.scss */ .top-bar.browse, .top-bar.edit { border-bottom: 1px solid rgba(153, 153, 153, 0.1); diff --git a/platform/commonUI/themes/snow/bundle.json b/platform/commonUI/themes/snow/bundle.json index 6db1ba21c1..6780df8e33 100644 --- a/platform/commonUI/themes/snow/bundle.json +++ b/platform/commonUI/themes/snow/bundle.json @@ -1,12 +1,18 @@ { - "name": "Sonw", - "description": "Snow theme: light and cool", - "extensions": { - "stylesheets": [ - { - "stylesheetUrl": "css/theme-snow.css", - "priority": 1000 - } - ] - } -} \ No newline at end of file + "name": "Snow", + "description": "Snow theme: light and cool", + "extensions": { + "stylesheets": [ + { + "stylesheetUrl": "css/theme-snow.css", + "priority": 1000 + } + ], + "constants": [ + { + "key": "THEME", + "value": "snow" + } + ] + } +} diff --git a/platform/commonUI/themes/snow/res/css/theme-snow.css b/platform/commonUI/themes/snow/res/css/theme-snow.css index 6ec5b55434..3aaf090ae9 100644 --- a/platform/commonUI/themes/snow/res/css/theme-snow.css +++ b/platform/commonUI/themes/snow/res/css/theme-snow.css @@ -20,7 +20,7 @@ * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/* line 5, ../../../../../../../../../../../Library/Ruby/Gems/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, @@ -41,38 +41,38 @@ time, mark, audio, video { font-size: 100%; vertical-align: baseline; } -/* line 22, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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, ../../../../../../../../../../../Library/Ruby/Gems/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; } @@ -306,7 +306,7 @@ a.disabled { *****************************************************************************/ /************************** FONTS */ @font-face { - /* + /* * Use https://icomoon.io/app with /platform/commonUI/general/res/fonts/symbols/icomoon.io-WTD-symbols-project.json */ font-family: 'symbolsfont'; @@ -428,6 +428,119 @@ mct-container { .sep { color: rgba(255, 255, 255, 0.2); } +/***************************************************************************** + * 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. + *****************************************************************************/ +/********************************************* COLUMN LAYOUTS STYLES */ +/* line 34, ../../../../general/res/sass/_archetypes.scss */ +.cols { + overflow: hidden; + *zoom: 1; } + /* line 36, ../../../../general/res/sass/_archetypes.scss */ + .cols .col { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + overflow: hidden; + *zoom: 1; + float: left; + margin-left: 1.5%; + padding-left: 5px; + position: relative; } + /* line 44, ../../../../general/res/sass/_archetypes.scss */ + .cols .col:first-child { + margin-left: 0; + padding-left: 0; } + /* line 51, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-2 .col-1 { + min-width: 250px; + width: 48.5%; } + /* line 57, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-2-ff .col-100px { + width: 100px; } + /* line 64, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-6 .col-1 { + min-width: 83.33333px; + width: 15.16667%; } + /* line 70, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-16 .col-1 { + min-width: 31.25px; + width: 4.75%; } + /* line 73, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-16 .col-2 { + min-width: 62.5px; + width: 11%; } + /* line 76, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-16 .col-7 { + min-width: 218.75px; + width: 42.25%; } + /* line 82, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-32 .col-2 { + min-width: 31.25px; + width: 4.75%; } + /* line 85, ../../../../general/res/sass/_archetypes.scss */ + .cols.cols-32 .col-15 { + min-width: 234.375px; + width: 45.375%; } + /* line 89, ../../../../general/res/sass/_archetypes.scss */ + .cols .l-row { + overflow: hidden; + *zoom: 1; + padding: 5px 0; } + +/********************************************* FLEX STYLES */ +/* line 96, ../../../../general/res/sass/_archetypes.scss */ +.l-flex-row, .l-flex, +.l-flex-col { + display: -webkit-flex; + display: flex; + -webkit-flex-wrap: nowrap; + flex-wrap: nowrap; } + /* line 101, ../../../../general/res/sass/_archetypes.scss */ + .l-flex-row .flex-elem:not(.grows), .l-flex .flex-elem:not(.grows), + .l-flex-col .flex-elem:not(.grows) { + -webkit-flex: 0 1 auto; + flex: 0 1 auto; } + /* line 104, ../../../../general/res/sass/_archetypes.scss */ + .l-flex-row .flex-elem.grows, .l-flex .flex-elem.grows, + .l-flex-col .flex-elem.grows { + -webkit-flex: 1 1 auto; + flex: 1 1 auto; } + +/* line 110, ../../../../general/res/sass/_archetypes.scss */ +.l-flex-row, .l-flex { + -webkit-flex-direction: row; + flex-direction: row; } + +/* line 111, ../../../../general/res/sass/_archetypes.scss */ +.l-flex-col { + -webkit-flex-direction: column; + flex-direction: column; } + +/* line 115, ../../../../general/res/sass/_archetypes.scss */ +.l-flex .left { + -webkit-flex: 1 1 0; + flex: 1 1 0; + padding-right: 10px; } + /***************************************************************************** * Open MCT Web, Copyright (c) 2014-2015, United States Government * as represented by the Administrator of the National Aeronautics and Space @@ -1025,11 +1138,11 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { background-image: linear-gradient(90deg, rgba(0, 0, 0, 0) 40%, rgba(0, 0, 0, 0.05) 70%, rgba(0, 0, 0, 0.2) 100%); } /*.browse-area .splitter { - top: 0; //$ueTopBarH + $interiorMarginLg; + top: 0; //$ueTopBarH + $interiorMarginLg; } .edit-area .splitter { - top: 0; + top: 0; }*/ /***************************************************************************** * Open MCT Web, Copyright (c) 2014-2015, United States Government @@ -1280,14 +1393,20 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { margin-right: 5px; vertical-align: bottom; } /* line 47, ../../../../general/res/sass/_inspector.scss */ + .l-inspect ul { + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + box-sizing: border-box; + padding-right: 5px; } + /* line 52, ../../../../general/res/sass/_inspector.scss */ .l-inspect ul li, .l-inspect em { display: block; position: relative; } - /* line 53, ../../../../general/res/sass/_inspector.scss */ + /* line 58, ../../../../general/res/sass/_inspector.scss */ .l-inspect ul li { margin-bottom: 10px; } - /* line 57, ../../../../general/res/sass/_inspector.scss */ + /* line 62, ../../../../general/res/sass/_inspector.scss */ .l-inspect em { -moz-border-radius: 4px; -webkit-border-radius: 4px; @@ -1297,34 +1416,34 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { margin-bottom: 5px; padding: 5px 5px; text-transform: uppercase; } - /* line 66, ../../../../general/res/sass/_inspector.scss */ + /* line 71, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-properties { padding: 3px 0; } - /* line 67, ../../../../general/res/sass/_inspector.scss */ + /* line 72, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-properties:not(.first) { border-top: 1px solid #e3e3e3; } - /* line 71, ../../../../general/res/sass/_inspector.scss */ + /* line 76, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-properties .label { color: #999999; text-transform: uppercase; } - /* line 75, ../../../../general/res/sass/_inspector.scss */ + /* line 80, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-properties .value { color: #404040; word-break: break-all; } - /* line 83, ../../../../general/res/sass/_inspector.scss */ + /* line 88, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-location .location-item { cursor: pointer; display: inline-block; position: relative; padding: 2px 4px; } - /* line 88, ../../../../general/res/sass/_inspector.scss */ + /* line 93, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-location .location-item:hover { background: rgba(102, 102, 102, 0.1); color: #333333; } - /* line 91, ../../../../general/res/sass/_inspector.scss */ + /* line 96, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-location .location-item:hover .icon, .l-inspect .inspector-location .location-item:hover .t-item-icon { color: #0099cc; } - /* line 96, ../../../../general/res/sass/_inspector.scss */ + /* line 101, ../../../../general/res/sass/_inspector.scss */ .l-inspect .inspector-location:not(.last) .t-object-label .t-title-label:after { color: #8c8c8c; content: '\3e'; @@ -1721,26 +1840,30 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { overflow: hidden; word-break: break-all; } /* line 228, ../../../../general/res/sass/controls/_buttons.scss */ + .mini-tab-icon.collapsed { + width: 11px; + font-size: 11px; } + /* line 233, ../../../../general/res/sass/controls/_buttons.scss */ .mini-tab-icon:before, .mini-tab-icon:after { position: absolute; display: inherit; } - /* line 234, ../../../../general/res/sass/controls/_buttons.scss */ + /* line 239, ../../../../general/res/sass/controls/_buttons.scss */ .mini-tab-icon:before { content: '\78'; } - /* line 238, ../../../../general/res/sass/controls/_buttons.scss */ + /* line 243, ../../../../general/res/sass/controls/_buttons.scss */ .mini-tab-icon:hover { color: #0099cc; } } -/* line 245, ../../../../general/res/sass/controls/_buttons.scss */ +/* line 250, ../../../../general/res/sass/controls/_buttons.scss */ .l-btn-set { font-size: 0; } - /* line 251, ../../../../general/res/sass/controls/_buttons.scss */ + /* line 256, ../../../../general/res/sass/controls/_buttons.scss */ .l-btn-set .s-btn, .l-btn-set .s-menu-btn { -moz-border-radius: 0; -webkit-border-radius: 0; border-radius: 0; margin-left: 1px; } - /* line 257, ../../../../general/res/sass/controls/_buttons.scss */ + /* line 262, ../../../../general/res/sass/controls/_buttons.scss */ .l-btn-set .first .s-btn, .l-btn-set .first .s-menu-btn { -moz-border-radius-topleft: 4px; -webkit-border-top-left-radius: 4px; @@ -1749,7 +1872,7 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { -webkit-border-bottom-left-radius: 4px; border-bottom-left-radius: 4px; margin-left: 0; } - /* line 264, ../../../../general/res/sass/controls/_buttons.scss */ + /* line 269, ../../../../general/res/sass/controls/_buttons.scss */ .l-btn-set .last .s-btn, .l-btn-set .last .s-menu-btn { -moz-border-radius-topright: 4px; -webkit-border-top-right-radius: 4px; @@ -1758,7 +1881,7 @@ tr[class*="s-limit"].s-limit-lwr td:first-child:before { -webkit-border-bottom-right-radius: 4px; border-bottom-right-radius: 4px; } -/* line 271, ../../../../general/res/sass/controls/_buttons.scss */ +/* line 276, ../../../../general/res/sass/controls/_buttons.scss */ .paused:not(.s-btn):not(.s-menu-btn) { border-color: #ff9900 !important; color: #ff9900 !important; } @@ -2063,23 +2186,23 @@ label.checkbox.custom { /* line 204, ../../../../general/res/sass/controls/_controls.scss */ .object-header { font-size: 1em; } - /* line 236, ../../../../general/res/sass/controls/_controls.scss */ + /* line 208, ../../../../general/res/sass/controls/_controls.scss */ .object-header > .type-icon { color: #b3b3b3; font-size: 120%; float: left; margin-right: 5px; } - /* line 243, ../../../../general/res/sass/controls/_controls.scss */ + /* line 215, ../../../../general/res/sass/controls/_controls.scss */ .object-header .l-elem-wrapper { -webkit-justify-content: flex-start; justify-content: flex-start; } - /* line 247, ../../../../general/res/sass/controls/_controls.scss */ + /* line 218, ../../../../general/res/sass/controls/_controls.scss */ .object-header .l-elem-wrapper mct-representation { min-width: 0.7em; } - /* line 255, ../../../../general/res/sass/controls/_controls.scss */ + /* line 226, ../../../../general/res/sass/controls/_controls.scss */ .object-header .action { margin-right: 5px; } - /* line 259, ../../../../general/res/sass/controls/_controls.scss */ + /* line 230, ../../../../general/res/sass/controls/_controls.scss */ .object-header .title-label { color: #666; overflow: hidden; @@ -2088,13 +2211,13 @@ label.checkbox.custom { flex: 0 1 auto; -webkit-flex: 0 1 auto; padding-right: 0.35em; } - /* line 269, ../../../../general/res/sass/controls/_controls.scss */ + /* line 240, ../../../../general/res/sass/controls/_controls.scss */ .object-header .context-available { font-size: 0.7em; flex: 0 0 1; -webkit-flex: 0 0 1; } @media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) { - /* line 276, ../../../../general/res/sass/controls/_controls.scss */ + /* line 247, ../../../../general/res/sass/controls/_controls.scss */ .object-header .context-available { -moz-transition-property: opacity; -o-transition-property: opacity; @@ -2113,7 +2236,7 @@ label.checkbox.custom { -webkit-transition-delay: 0; transition-delay: 0; opacity: 0; } - /* line 259, ../../../../general/res/sass/controls/_controls.scss */ + /* line 252, ../../../../general/res/sass/controls/_controls.scss */ .object-header:hover .context-available { opacity: 1; } } @@ -2127,12 +2250,12 @@ label.checkbox.custom { @keyframes progress { 100% { background-position: 20px center; } } -/* line 281, ../../../../general/res/sass/controls/_controls.scss */ +/* line 274, ../../../../general/res/sass/controls/_controls.scss */ .l-progress-bar { display: inline-block; overflow: hidden; position: relative; } - /* line 287, ../../../../general/res/sass/controls/_controls.scss */ + /* line 280, ../../../../general/res/sass/controls/_controls.scss */ .l-progress-bar .progress-amt-holder { overflow: hidden; position: absolute; @@ -2142,7 +2265,7 @@ label.checkbox.custom { left: 1px; width: auto; height: auto; } - /* line 290, ../../../../general/res/sass/controls/_controls.scss */ + /* line 283, ../../../../general/res/sass/controls/_controls.scss */ .l-progress-bar .progress-amt, .l-progress-bar .progress-amt:before, .l-progress-bar .progress-amt:after { @@ -2156,14 +2279,14 @@ label.checkbox.custom { height: auto; display: block; content: ''; } - /* line 298, ../../../../general/res/sass/controls/_controls.scss */ + /* line 291, ../../../../general/res/sass/controls/_controls.scss */ .l-progress-bar .progress-amt { right: auto; } - /* line 303, ../../../../general/res/sass/controls/_controls.scss */ + /* line 296, ../../../../general/res/sass/controls/_controls.scss */ .l-progress-bar.indeterminate .progress-amt { width: 100% !important; } -/* line 309, ../../../../general/res/sass/controls/_controls.scss */ +/* line 302, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar { -moz-border-radius: 4px; -webkit-border-radius: 4px; @@ -2172,7 +2295,7 @@ label.checkbox.custom { -webkit-box-shadow: inset rgba(0, 0, 0, 0.3) 0 1px 4px; box-shadow: inset rgba(0, 0, 0, 0.3) 0 1px 4px; background: rgba(0, 0, 0, 0.1); } - /* line 314, ../../../../general/res/sass/controls/_controls.scss */ + /* line 307, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar .progress-amt { -moz-border-radius: 4px; -webkit-border-radius: 4px; @@ -2199,10 +2322,10 @@ label.checkbox.custom { -o-transition-delay: 0; -webkit-transition-delay: 0; transition-delay: 0; } - /* line 319, ../../../../general/res/sass/controls/_controls.scss */ + /* line 312, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar .progress-amt:before { background-color: #0a0; } - /* line 322, ../../../../general/res/sass/controls/_controls.scss */ + /* line 315, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar .progress-amt:after { background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSI1JSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIgc3RvcC1vcGFjaXR5PSIwLjAiLz48c3RvcCBvZmZzZXQ9IjMwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIgc3RvcC1vcGFjaXR5PSIwLjI1Ii8+PHN0b3Agb2Zmc2V0PSIxMDAlIiBzdG9wLWNvbG9yPSIjMDAwMDAwIiBzdG9wLW9wYWNpdHk9IjAuMCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background-size: 100%; @@ -2210,7 +2333,7 @@ label.checkbox.custom { background-image: -moz-linear-gradient(rgba(0, 0, 0, 0) 5%, rgba(255, 255, 255, 0.25) 30%, rgba(0, 0, 0, 0) 100%); background-image: -webkit-linear-gradient(rgba(0, 0, 0, 0) 5%, rgba(255, 255, 255, 0.25) 30%, rgba(0, 0, 0, 0) 100%); background-image: linear-gradient(rgba(0, 0, 0, 0) 5%, rgba(255, 255, 255, 0.25) 30%, rgba(0, 0, 0, 0) 100%); } - /* line 331, ../../../../general/res/sass/controls/_controls.scss */ + /* line 324, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar:not(.indeterminate) .progress-amt:before { -moz-animation: progress 0.4s linear infinite; -webkit-animation: progress 0.4s linear infinite; @@ -2223,7 +2346,7 @@ label.checkbox.custom { background-position: 0 center; background-repeat: repeat-x; background-size: 20px 40%; } - /* line 339, ../../../../general/res/sass/controls/_controls.scss */ + /* line 332, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar.indeterminate .progress-amt:before { -moz-animation: progress 0.6s linear infinite; -webkit-animation: progress 0.6s linear infinite; @@ -2235,12 +2358,12 @@ label.checkbox.custom { background-image: linear-gradient(-45deg, rgba(255, 255, 255, 0.2) 25%, rgba(0, 0, 0, 0) 25%, rgba(0, 0, 0, 0) 50%, rgba(255, 255, 255, 0.2) 50%, rgba(255, 255, 255, 0.2) 75%, rgba(0, 0, 0, 0) 75%, rgba(0, 0, 0, 0) 100%); background-repeat: repeat; background-size: 20px 20px; } - /* line 344, ../../../../general/res/sass/controls/_controls.scss */ + /* line 337, ../../../../general/res/sass/controls/_controls.scss */ .s-progress-bar.indeterminate .progress-amt:after { display: none; } /******************************************************** SLIDERS */ -/* line 352, ../../../../general/res/sass/controls/_controls.scss */ +/* line 345, ../../../../general/res/sass/controls/_controls.scss */ .slider .slot { width: auto; position: absolute; @@ -2248,7 +2371,7 @@ label.checkbox.custom { right: 0; bottom: 0; left: 0; } -/* line 362, ../../../../general/res/sass/controls/_controls.scss */ +/* line 355, ../../../../general/res/sass/controls/_controls.scss */ .slider .knob { -moz-transition-property: opacity, background-color, border-color, color; -o-transition-property: opacity, background-color, border-color, color; @@ -2274,10 +2397,10 @@ label.checkbox.custom { auto: 0; bottom: auto; left: auto; } - /* line 365, ../../../../general/res/sass/controls/_controls.scss */ + /* line 358, ../../../../general/res/sass/controls/_controls.scss */ .slider .knob:hover { background-color: rgba(0, 153, 204, 0.7); } -/* line 376, ../../../../general/res/sass/controls/_controls.scss */ +/* line 369, ../../../../general/res/sass/controls/_controls.scss */ .slider .knob-l { -moz-border-radius-topleft: 10px; -webkit-border-top-left-radius: 10px; @@ -2286,7 +2409,7 @@ label.checkbox.custom { -webkit-border-bottom-left-radius: 10px; border-bottom-left-radius: 10px; cursor: w-resize; } -/* line 322, ../../../../general/res/sass/controls/_controls.scss */ +/* line 373, ../../../../general/res/sass/controls/_controls.scss */ .slider .knob-r { -moz-border-radius-topright: 10px; -webkit-border-top-right-radius: 10px; @@ -2295,7 +2418,7 @@ label.checkbox.custom { -webkit-border-bottom-right-radius: 10px; border-bottom-right-radius: 10px; cursor: e-resize; } -/* line 326, ../../../../general/res/sass/controls/_controls.scss */ +/* line 377, ../../../../general/res/sass/controls/_controls.scss */ .slider .range { -moz-transition-property: opacity, background-color, border-color, color; -o-transition-property: opacity, background-color, border-color, color; @@ -2322,12 +2445,12 @@ label.checkbox.custom { left: auto; height: auto; width: auto; } - /* line 337, ../../../../general/res/sass/controls/_controls.scss */ + /* line 388, ../../../../general/res/sass/controls/_controls.scss */ .slider .range:hover { background-color: rgba(0, 153, 204, 0.4); } /******************************************************** DATETIME PICKER */ -/* line 344, ../../../../general/res/sass/controls/_controls.scss */ +/* line 395, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker { -moz-user-select: -moz-none; -ms-user-select: none; @@ -2336,65 +2459,65 @@ label.checkbox.custom { font-size: 0.8rem; padding: 10px !important; width: 230px; } - /* line 350, ../../../../general/res/sass/controls/_controls.scss */ + /* line 401, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager { height: 15px; margin-bottom: 5px; position: relative; } - /* line 420, ../../../../general/res/sass/controls/_controls.scss */ + /* line 413, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .pager { width: 20px; } - /* line 423, ../../../../general/res/sass/controls/_controls.scss */ + /* line 416, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .pager.prev { right: auto; } - /* line 425, ../../../../general/res/sass/controls/_controls.scss */ + /* line 418, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .pager.prev:before { content: "\3c"; } - /* line 429, ../../../../general/res/sass/controls/_controls.scss */ + /* line 422, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .pager.next { left: auto; text-align: right; } - /* line 432, ../../../../general/res/sass/controls/_controls.scss */ + /* line 425, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .pager.next:before { content: "\3e"; } - /* line 437, ../../../../general/res/sass/controls/_controls.scss */ + /* line 430, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-month-year-pager .val { text-align: center; left: 25px; right: 25px; } - /* line 443, ../../../../general/res/sass/controls/_controls.scss */ + /* line 436, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-calendar, .l-datetime-picker .l-time-selects { border-top: 1px solid rgba(102, 102, 102, 0.2); } - /* line 447, ../../../../general/res/sass/controls/_controls.scss */ + /* line 440, ../../../../general/res/sass/controls/_controls.scss */ .l-datetime-picker .l-time-selects { line-height: 22px; } /******************************************************** CALENDAR */ -/* line 397, ../../../../general/res/sass/controls/_controls.scss */ +/* line 448, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row { display: -webkit-flex; display: flex; -webkit-flex-flow: row nowrap; flex-flow: row nowrap; margin-top: 1px; } - /* line 459, ../../../../general/res/sass/controls/_controls.scss */ + /* line 452, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row:first-child { margin-top: 0; } - /* line 462, ../../../../general/res/sass/controls/_controls.scss */ + /* line 455, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row li { -webkit-flex: 1 0; flex: 1 0; margin-left: 1px; padding: 5px; text-align: center; } - /* line 468, ../../../../general/res/sass/controls/_controls.scss */ + /* line 461, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row li:first-child { margin-left: 0; } - /* line 472, ../../../../general/res/sass/controls/_controls.scss */ + /* line 465, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-header li { color: #999999; } - /* line 475, ../../../../general/res/sass/controls/_controls.scss */ + /* line 468, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li { -moz-transition-property: background-color; -o-transition-property: background-color; @@ -2413,31 +2536,31 @@ label.checkbox.custom { -webkit-transition-delay: 0; transition-delay: 0; cursor: pointer; } - /* line 478, ../../../../general/res/sass/controls/_controls.scss */ + /* line 471, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li.in-month { background-color: #f2f2f2; } - /* line 481, ../../../../general/res/sass/controls/_controls.scss */ + /* line 474, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li .sub { color: #999999; font-size: 0.8em; } - /* line 485, ../../../../general/res/sass/controls/_controls.scss */ + /* line 478, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li.selected { background: #1ac6ff; color: #fcfcfc; } - /* line 488, ../../../../general/res/sass/controls/_controls.scss */ + /* line 481, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li.selected .sub { color: inherit; } - /* line 492, ../../../../general/res/sass/controls/_controls.scss */ + /* line 485, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li:hover { background-color: #0099cc; color: #fff; } - /* line 495, ../../../../general/res/sass/controls/_controls.scss */ + /* line 488, ../../../../general/res/sass/controls/_controls.scss */ .l-calendar ul.l-cal-row.l-body li:hover .sub { color: inherit; } /******************************************************** BROWSER ELEMENTS */ @media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) { - /* line 448, ../../../../general/res/sass/controls/_controls.scss */ + /* line 499, ../../../../general/res/sass/controls/_controls.scss */ ::-webkit-scrollbar { -moz-border-radius: 2px; -webkit-border-radius: 2px; @@ -2452,7 +2575,7 @@ label.checkbox.custom { height: 10px; width: 10px; } - /* line 457, ../../../../general/res/sass/controls/_controls.scss */ + /* line 508, ../../../../general/res/sass/controls/_controls.scss */ ::-webkit-scrollbar-thumb { background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzg5ODk4OSIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzdkN2Q3ZCIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background-size: 100%; @@ -2466,7 +2589,7 @@ label.checkbox.custom { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; } - /* line 466, ../../../../general/res/sass/controls/_controls.scss */ + /* line 517, ../../../../general/res/sass/controls/_controls.scss */ ::-webkit-scrollbar-thumb:hover { background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4gPHN2ZyB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PGRlZnM+PGxpbmVhckdyYWRpZW50IGlkPSJncmFkIiBncmFkaWVudFVuaXRzPSJvYmplY3RCb3VuZGluZ0JveCIgeDE9IjAuNSIgeTE9IjAuMCIgeDI9IjAuNSIgeTI9IjEuMCI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwYWNlNiIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iIzAwOTljYyIvPjwvbGluZWFyR3JhZGllbnQ+PC9kZWZzPjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIGZpbGw9InVybCgjZ3JhZCkiIC8+PC9zdmc+IA=='); background-size: 100%; @@ -2475,7 +2598,7 @@ label.checkbox.custom { background-image: -webkit-linear-gradient(#00ace6, #0099cc 20px); background-image: linear-gradient(#00ace6, #0099cc 20px); } - /* line 471, ../../../../general/res/sass/controls/_controls.scss */ + /* line 522, ../../../../general/res/sass/controls/_controls.scss */ ::-webkit-scrollbar-corner { background: rgba(0, 0, 0, 0.1); } } /***************************************************************************** @@ -3840,15 +3963,15 @@ textarea { /* line 29, ../../../../general/res/sass/forms/_datetime.scss */ .complex.datetime { /* - .field-hints, - .fields { - } - - - .field-hints { - - } - */ } + .field-hints, + .fields { + } + + + .field-hints { + + } + */ } /* line 30, ../../../../general/res/sass/forms/_datetime.scss */ .complex.datetime span { display: inline-block; @@ -4095,26 +4218,19 @@ span.req { * this source code distribution or the Licensing information page available * at runtime from the About dialog for additional information. *****************************************************************************/ -/*.holder-all { - $myM: 0; // $interiorMarginSm; - top: $myM; - right: $myM; - bottom: $myM; - left: $myM; -}*/ -/* line 40, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 23, ../../../../general/res/sass/user-environ/_layout.scss */ .browse-area, .edit-area, .editor { position: absolute; } -/* line 46, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 29, ../../../../general/res/sass/user-environ/_layout.scss */ .editor { -moz-border-radius: 6px; -webkit-border-radius: 6px; border-radius: 6px; } -/* line 50, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 33, ../../../../general/res/sass/user-environ/_layout.scss */ .contents { box-sizing: border-box; position: absolute; @@ -4122,21 +4238,21 @@ span.req { right: 0; bottom: 0; left: 0; } - /* line 58, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 41, ../../../../general/res/sass/user-environ/_layout.scss */ .contents.nomargin { right: 0px; bottom: 0px; left: 0px; } -/* line 67, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 50, ../../../../general/res/sass/user-environ/_layout.scss */ .bar .icon.major, .bar .major.t-item-icon { margin-right: 5px; } -/* line 70, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 53, ../../../../general/res/sass/user-environ/_layout.scss */ .bar.abs, .bar.l-inspect, .l-datetime-picker .l-month-year-pager .bar.pager, .l-datetime-picker .l-month-year-pager .bar.val, .s-menu-btn span.bar.l-click-area { text-wrap: none; white-space: nowrap; } - /* line 73, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 56, ../../../../general/res/sass/user-environ/_layout.scss */ .bar.abs.left, .bar.left.l-inspect, .l-datetime-picker .l-month-year-pager .bar.left.pager, .l-datetime-picker .l-month-year-pager .bar.left.val, .s-menu-btn span.bar.left.l-click-area, .bar.abs .left, @@ -4146,7 +4262,7 @@ span.req { .s-menu-btn span.bar.l-click-area .left { width: 45%; right: auto; } - /* line 78, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 61, ../../../../general/res/sass/user-environ/_layout.scss */ .bar.abs.right, .bar.right.l-inspect, .l-datetime-picker .l-month-year-pager .bar.right.pager, .l-datetime-picker .l-month-year-pager .bar.right.val, .s-menu-btn span.bar.right.l-click-area, .bar.abs .right, @@ -4157,7 +4273,7 @@ span.req { width: 45%; left: auto; text-align: right; } - /* line 83, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 66, ../../../../general/res/sass/user-environ/_layout.scss */ .bar.abs.right .icon.major, .bar.right.l-inspect .icon.major, .l-datetime-picker .l-month-year-pager .bar.right.pager .icon.major, .l-datetime-picker .l-month-year-pager .bar.right.val .icon.major, .s-menu-btn span.bar.right.l-click-area .icon.major, .bar.abs.right .major.t-item-icon, .bar.right.l-inspect .major.t-item-icon, .l-datetime-picker .l-month-year-pager .bar.right.pager .major.t-item-icon, .l-datetime-picker .l-month-year-pager .bar.right.val .major.t-item-icon, .s-menu-btn span.bar.right.l-click-area .major.t-item-icon, @@ -4172,7 +4288,7 @@ span.req { .l-datetime-picker .l-month-year-pager .bar.val .right .major.t-item-icon, .s-menu-btn span.bar.l-click-area .right .major.t-item-icon { margin-left: 15px; } - /* line 89, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 72, ../../../../general/res/sass/user-environ/_layout.scss */ .bar.abs .l-flex .left, .bar.l-inspect .l-flex .left, .l-datetime-picker .l-month-year-pager .bar.pager .l-flex .left, .l-datetime-picker .l-month-year-pager .bar.val .l-flex .left, .s-menu-btn span.bar.l-click-area .l-flex .left, .bar.abs .l-flex .right, @@ -4188,34 +4304,34 @@ span.req { .s-menu-btn span.bar.l-flex.l-click-area .right { width: auto; } -/* line 98, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 81, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .browse-area, .user-environ .editor { top: 0; left: 0; right: 0; bottom: 25px; } -/* line 105, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 88, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .browse-area > .contents, .user-environ .edit-area > .contents { left: 0; right: 0; } -/* line 111, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 94, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .edit-area { top: 45px; left: 10px; right: 10px; bottom: 35px; } - /* line 117, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 100, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .edit-area .tool-bar { bottom: auto; height: 30px; line-height: 25px; } - /* line 122, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 105, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .edit-area .object-holder.work-area { top: 40px; overflow: auto; } -/* line 129, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 112, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .ue-bottom-bar { overflow: hidden; position: absolute; @@ -4231,7 +4347,7 @@ span.req { background: #000; color: white; font-size: .7rem; } - /* line 138, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 121, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .ue-bottom-bar .status-holder { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; @@ -4250,7 +4366,7 @@ span.req { right: 120px; text-transform: uppercase; z-index: 1; } - /* line 147, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 130, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .ue-bottom-bar .app-logo { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; @@ -4267,143 +4383,87 @@ span.req { left: auto; width: 105px; z-index: 2; } - /* line 154, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 137, ../../../../general/res/sass/user-environ/_layout.scss */ .user-environ .ue-bottom-bar .app-logo.logo-openmctweb { background: url("../../../../general/res/images/logo-openmctweb.svg") no-repeat center center; } -/* line 161, ../../../../general/res/sass/user-environ/_layout.scss */ -.cols { - overflow: hidden; - *zoom: 1; } - /* line 163, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols .col { - -moz-box-sizing: border-box; - -webkit-box-sizing: border-box; - box-sizing: border-box; - overflow: hidden; - *zoom: 1; - float: left; - margin-left: 1.5%; - padding-left: 5px; - position: relative; } - /* line 171, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols .col:first-child { - margin-left: 0; - padding-left: 0; } - /* line 178, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-2 .col-1 { - min-width: 250px; - width: 48.5%; } - /* line 184, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-2-ff .col-100px { - width: 100px; } - /* line 191, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-6 .col-1 { - min-width: 83.33333px; - width: 15.16667%; } - /* line 197, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-16 .col-1 { - min-width: 31.25px; - width: 4.75%; } - /* line 200, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-16 .col-2 { - min-width: 62.5px; - width: 11%; } - /* line 203, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-16 .col-7 { - min-width: 218.75px; - width: 42.25%; } - /* line 209, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-32 .col-2 { - min-width: 31.25px; - width: 4.75%; } - /* line 212, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols.cols-32 .col-15 { - min-width: 234.375px; - width: 45.375%; } - /* line 216, ../../../../general/res/sass/user-environ/_layout.scss */ - .cols .l-row { - overflow: hidden; - *zoom: 1; - padding: 5px 0; } - -/* line 226, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 148, ../../../../general/res/sass/user-environ/_layout.scss */ .browse-mode .split-layout .split-pane-component.pane.treeview.left { min-width: 150px; max-width: 800px; width: 25%; } -/* line 231, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 153, ../../../../general/res/sass/user-environ/_layout.scss */ .browse-mode .split-layout .split-pane-component.pane.t-inspect.right { min-width: 200px; max-width: 600px; width: 20%; } -/* line 243, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 165, ../../../../general/res/sass/user-environ/_layout.scss */ .edit-mode .split-layout .split-pane-component.pane.right { width: 15%; } - /* line 245, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 167, ../../../../general/res/sass/user-environ/_layout.scss */ .edit-mode .split-layout .split-pane-component.pane.right .pane.bottom { min-height: 50px; height: 30%; } -/* line 253, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 175, ../../../../general/res/sass/user-environ/_layout.scss */ .pane { -moz-box-sizing: border-box; -webkit-box-sizing: border-box; box-sizing: border-box; position: absolute; } - /* line 257, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 179, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .pane-header { text-transform: uppercase; height: 24px; line-height: 24px; margin-bottom: 5px; } - /* line 264, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 186, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .primary-pane { z-index: 2; } - /* line 282, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 204, ../../../../general/res/sass/user-environ/_layout.scss */ .pane.treeview.left .search-holder { top: 34px; } - /* line 285, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 207, ../../../../general/res/sass/user-environ/_layout.scss */ .pane.treeview.left .tree-holder { overflow: auto; top: 64px; } - /* line 291, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 213, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane { z-index: 5; } @media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) { - /* line 291, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 213, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane { top: 10px; height: 24px; line-height: 24px; } - /* line 300, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 222, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane:after { opacity: 0; } - /* line 305, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 227, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.collapsed:before { opacity: 0; } - /* line 308, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 230, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.collapsed:after { opacity: 1; } - /* line 312, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 234, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-tree.anchor-left { left: 0; -moz-transform: translateX(-33px); -ms-transform: translateX(-33px); -webkit-transform: translateX(-33px); transform: translateX(-33px); } - /* line 315, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 237, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-tree.anchor-left:after { content: '\6d'; } - /* line 318, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 240, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-tree.anchor-left.collapsed { left: 0; - -moz-transform: translateX(-15px); - -ms-transform: translateX(-15px); - -webkit-transform: translateX(-15px); - transform: translateX(-15px); } - /* line 322, ../../../../general/res/sass/user-environ/_layout.scss */ + -moz-transform: translateX(-17px); + -ms-transform: translateX(-17px); + -webkit-transform: translateX(-17px); + transform: translateX(-17px); } + /* line 244, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-tree.anchor-left:not(.collapsed):before { -moz-transition-property: opacity; -o-transition-property: opacity; @@ -4421,16 +4481,16 @@ span.req { -o-transition-delay: 200ms; -webkit-transition-delay: 200ms; transition-delay: 200ms; } - /* line 326, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 248, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-inspect.anchor-right { right: 10px; } - /* line 328, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 250, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-inspect.anchor-right:after { content: '\e615'; } - /* line 331, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 253, ../../../../general/res/sass/user-environ/_layout.scss */ .pane .mini-tab-icon.toggle-pane.toggle-inspect.anchor-right.collapsed { right: 5px; } } - /* line 340, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 262, ../../../../general/res/sass/user-environ/_layout.scss */ .pane.items .object-browse-bar .left.abs, .pane.items .object-browse-bar .left.l-inspect, .pane.items .object-browse-bar .l-datetime-picker .l-month-year-pager .left.pager, .l-datetime-picker .l-month-year-pager .pane.items .object-browse-bar .left.pager, .pane.items .object-browse-bar .l-datetime-picker .l-month-year-pager .left.val, .l-datetime-picker .l-month-year-pager .pane.items .object-browse-bar .left.val, .pane.items .object-browse-bar .s-menu-btn span.left.l-click-area, .s-menu-btn .pane.items .object-browse-bar span.left.l-click-area, @@ -4444,7 +4504,7 @@ span.req { .s-menu-btn .pane.items .object-browse-bar span.right.l-click-area { top: auto; } -/* line 348, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 270, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout { /* &.vertical { // Slides left and right @@ -4459,36 +4519,36 @@ span.req { } } }*/ } - /* line 351, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 273, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout.horizontal > .pane { margin-top: 5px; } - /* line 354, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 276, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout.horizontal > .pane:first-child { margin-top: 0; } - /* line 374, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 296, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout .holder.holder-create-and-search { top: 10px; right: 0; bottom: 10px; left: 10px; } - /* line 381, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 303, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout .holder.holder-object-and-inspector { top: 0; right: 0; bottom: 0; left: 0; } - /* line 386, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 308, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout .holder.holder-object-and-inspector .holder-object { top: 10px; bottom: 10px; } - /* line 390, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 312, ../../../../general/res/sass/user-environ/_layout.scss */ .split-layout .holder.holder-object-and-inspector .holder-inspector-elements { top: 10px; bottom: 10px; left: 10px; right: 10px; } -/* line 400, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 322, ../../../../general/res/sass/user-environ/_layout.scss */ .object-holder { overflow: auto; position: absolute; @@ -4499,11 +4559,11 @@ span.req { width: auto; height: auto; top: 34px; } - /* line 293, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 326, ../../../../general/res/sass/user-environ/_layout.scss */ .object-holder.l-controls-visible.l-time-controller-visible { bottom: 88px; } -/* line 299, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 332, ../../../../general/res/sass/user-environ/_layout.scss */ .object-browse-bar .s-btn, .object-browse-bar .s-menu-btn, .top-bar .buttons-main .s-btn, .top-bar .buttons-main .s-menu-btn, @@ -4515,14 +4575,14 @@ span.req { line-height: 25px; vertical-align: top; } -/* line 426, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 345, ../../../../general/res/sass/user-environ/_layout.scss */ .object-browse-bar .view-switcher, .top-bar .view-switcher { margin-right: 20px; } -/* line 431, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 350, ../../../../general/res/sass/user-environ/_layout.scss */ .object-browse-bar { - overflow: visible; + overflow: hidden; position: absolute; top: 0; right: 0; @@ -4536,55 +4596,22 @@ span.req { height: 24px; line-height: 24px; white-space: nowrap; } - /* line 439, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 358, ../../../../general/res/sass/user-environ/_layout.scss */ .object-browse-bar .left { padding-right: 20px; } - /* line 441, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 360, ../../../../general/res/sass/user-environ/_layout.scss */ .object-browse-bar .left .l-back { display: inline-block; float: left; margin-right: 10px; } -/* line 335, ../../../../general/res/sass/user-environ/_layout.scss */ -.l-flex { - display: flex; - display: -webkit-flex; - flex-flow: row nowrap; - -webkit-flex-flow: row nowrap; } - /* line 452, ../../../../general/res/sass/user-environ/_layout.scss */ - .l-flex .left { - flex: 1 1 0; - -webkit-flex: 1 1 0; - padding-right: 10px; } +/* line 374, ../../../../general/res/sass/user-environ/_layout.scss */ +.pane-tree-hidden .tree-holder, +.pane-tree-hidden .splitter-treeview, +.pane-tree-hidden .holder-create-and-search { + opacity: 0; } -/* line 462, ../../../../general/res/sass/user-environ/_layout.scss */ -.pane-tree-hidden { - /*.holder-create-and-search { - @include trans-prop-nice((top, left), 250ms); - top: $ueTopBarH + $interiorMargin; - left: -1 * $bodyMargin !important; - .create-btn { - @include border-left-radius(0); - @include trans-prop-nice((width), 250ms); - width: $uePaneMiniTabW !important; - text-align: center !important; - padding: 0; - .title-label, - &:after { - display: none; - } - &:before { - font-size: 9px; - } - } - }*/ } - /* line 465, ../../../../general/res/sass/user-environ/_layout.scss */ - .pane-tree-hidden .tree-holder, - .pane-tree-hidden .splitter-treeview, - .pane-tree-hidden .holder-create-and-search { - opacity: 0; } - -/* line 494, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 384, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-tree-showing .tree-holder, .pane-tree-showing .splitter-treeview { -moz-transition-property: opacity; @@ -4604,7 +4631,7 @@ span.req { -webkit-transition-delay: 250ms; transition-delay: 250ms; opacity: 1; } -/* line 500, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 390, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-tree-showing .holder-create-and-search { -moz-transition-property: opacity; -o-transition-property: opacity; @@ -4623,7 +4650,7 @@ span.req { -webkit-transition-delay: 200ms; transition-delay: 200ms; } -/* line 507, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 397, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-inspect-showing .l-object-and-inspector .l-inspect, .pane-inspect-showing .l-object-and-inspector .splitter-inspect { -moz-transition-property: opacity; @@ -4644,25 +4671,25 @@ span.req { transition-delay: 250ms; opacity: 1; } -/* line 516, ../../../../general/res/sass/user-environ/_layout.scss */ +/* line 406, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-inspect-hidden .l-object-and-inspector .l-inspect, .pane-inspect-hidden .l-object-and-inspector .splitter-inspect { opacity: 0; } @media screen and (min-device-width: 800px) and (min-device-height: 1025px), screen and (min-device-width: 1025px) and (min-device-height: 800px) { - /* line 524, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 414, ../../../../general/res/sass/user-environ/_layout.scss */ .pane.treeview.left .tree-holder { padding-right: 5px; } - /* line 528, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 418, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-tree-hidden .pane.right.primary-pane { - left: 20px !important; } + left: 22px !important; } - /* line 531, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 421, ../../../../general/res/sass/user-environ/_layout.scss */ .pane-inspect-hidden .l-object-and-inspector .pane.left { - right: 20px !important; } + right: 22px !important; } - /* line 534, ../../../../general/res/sass/user-environ/_layout.scss */ + /* line 424, ../../../../general/res/sass/user-environ/_layout.scss */ .pane:not(.resizing) { -moz-transition-property: width, left, right; -o-transition-property: width, left, right; @@ -5850,9 +5877,9 @@ ul.tree { *****************************************************************************/ /* line 22, ../../../../general/res/sass/user-environ/_top-bar.scss */ .top-bar { - /* .title { - color: #fff; - }*/ } + /* .title { + color: #fff; + }*/ } /* line 23, ../../../../general/res/sass/user-environ/_top-bar.scss */ .top-bar.browse, .top-bar.edit { border-bottom: 1px solid rgba(102, 102, 102, 0.2); diff --git a/platform/commonUI/themes/snow/res/sass/_constants.scss b/platform/commonUI/themes/snow/res/sass/_constants.scss index 1338b2c335..8963c30b8b 100644 --- a/platform/commonUI/themes/snow/res/sass/_constants.scss +++ b/platform/commonUI/themes/snow/res/sass/_constants.scss @@ -72,20 +72,6 @@ $colorInputBg: $colorGenBg; $colorInputFg: $colorBodyFg; $colorFormText: pushBack($colorBodyFg, 10%); $colorInputIcon: pushBack($colorBodyFg, 25%); - -// Status colors, mainly used for messaging and item ancillary symbols -$colorStatusFg: #fff; -$colorStatusDefault: #ccc; -$colorStatusInfo: #60ba7b; -$colorStatusAlert: #ffb66c; -$colorStatusError: #c96b68; -$colorProgressBarOuter: rgba(#000, 0.1); -$colorProgressBarAmt: #0a0; -$progressBarHOverlay: 15px; -$progressBarStripeW: 20px; -$shdwStatusIc: rgba(white, 0.8) 0 0px 5px; - -// Selects $colorSelectBg: #ddd; $colorSelectFg: $colorBodyFg; diff --git a/platform/core/bundle.json b/platform/core/bundle.json index 5b107843f1..25ca81f5f6 100644 --- a/platform/core/bundle.json +++ b/platform/core/bundle.json @@ -38,7 +38,7 @@ "provides": "objectService", "type": "provider", "implementation": "objects/DomainObjectProvider.js", - "depends": [ "modelService", "capabilityService", "$q" ] + "depends": [ "modelService", "instantiate" ] }, { "provides": "capabilityService", @@ -205,8 +205,8 @@ "depends": [ "$q" ] }, { - "key": "creation", - "implementation": "capabilities/CreationCapability.js", + "key": "instantiation", + "implementation": "capabilities/InstantiationCapability.js", "depends": [ "$injector" ] } ], @@ -228,6 +228,11 @@ "key": "contextualize", "implementation": "services/Contextualize.js", "depends": [ "$log" ] + }, + { + "key": "instantiate", + "implementation": "services/Instantiate.js", + "depends": [ "capabilityService" ] } ], "roots": [ diff --git a/platform/core/src/capabilities/CreationCapability.js b/platform/core/src/capabilities/InstantiationCapability.js similarity index 65% rename from platform/core/src/capabilities/CreationCapability.js rename to platform/core/src/capabilities/InstantiationCapability.js index 680f3f2805..84807294ca 100644 --- a/platform/core/src/capabilities/CreationCapability.js +++ b/platform/core/src/capabilities/InstantiationCapability.js @@ -27,33 +27,19 @@ define( 'use strict'; /** - * Implements the `creation` capability. This allows new domain + * Implements the `instantiation` capability. This allows new domain * objects to be instantiated. * * @constructor * @memberof platform/core * @param $injector Angular's `$injector` */ - function CreationCapability($injector, identifierService, domainObject) { + function InstantiationCapability($injector, identifierService, domainObject) { this.$injector = $injector; this.identifierService = identifierService; this.domainObject = domainObject; } - /** - * Alias of `capabilityService.getCapabilities`; handles lazy loading - * of `capabilityService`, since it cannot be declared as a - * dependency directly without creating a cycle. - * @private - */ - CreationCapability.prototype.getCapabilities = function (model) { - if (!this.capabilityService) { - this.capabilityService = - this.$injector.get('capabilityService'); - } - return this.capabilityService.getCapabilities(model); - }; - /** * Instantiate a new domain object with the provided model. * @@ -63,23 +49,27 @@ define( * * @returns {DomainObject} the new domain object */ - CreationCapability.prototype.create = function (model) { + InstantiationCapability.prototype.instantiate = function (model) { var parsedId = this.identifierService.parse(this.domainObject.getId()), space = parsedId.getDefinedSpace(), - id = this.identifierService.generate(space), - capabilities = this.getCapabilities(model); + id = this.identifierService.generate(space); - return new DomainObjectImpl(id, model, capabilities); + // Lazily initialize; instantiate depends on capabilityService, + // which depends on all capabilities, including this one. + this.instantiateFn = this.instantiateFn || + this.$injector.get("instantiate"); + + return this.instantiateFn(model, id); }; /** - * Alias of `create`. - * @see {platform/core.CreationCapability#create} + * Alias of `instantiate`. + * @see {platform/core.CreationCapability#instantiate} */ - CreationCapability.prototype.invoke = - CreationCapability.prototype.create; + InstantiationCapability.prototype.invoke = + InstantiationCapability.prototype.instantiate; - return CreationCapability; + return InstantiationCapability; } ); diff --git a/platform/core/src/objects/DomainObjectProvider.js b/platform/core/src/objects/DomainObjectProvider.js index c846cbf665..800d31f5d5 100644 --- a/platform/core/src/objects/DomainObjectProvider.js +++ b/platform/core/src/objects/DomainObjectProvider.js @@ -27,8 +27,8 @@ * @namespace platform/core */ define( - ["./DomainObjectImpl"], - function (DomainObjectImpl) { + [], + function () { "use strict"; /** @@ -57,62 +57,36 @@ define( * * @param {ModelService} modelService the service which shall * provide models (persistent state) for domain objects - * @param {CapabilityService} capabilityService the service - * which provides capabilities (dynamic behavior) - * for domain objects. + * @param {Function} instantiate a service to instantiate new + * domain object instances * @param $q Angular's $q, for promise consolidation * @memberof platform/core * @constructor */ - function DomainObjectProvider(modelService, capabilityService, $q) { + function DomainObjectProvider(modelService, instantiate, $q) { this.modelService = modelService; - this.capabilityService = capabilityService; - this.$q = $q; + this.instantiate = instantiate; } DomainObjectProvider.prototype.getObjects = function getObjects(ids) { var modelService = this.modelService, - capabilityService = this.capabilityService, - $q = this.$q; - - // Given a models object (containing key-value id-model pairs) - // create a function that will look up from the capability - // service based on id; for handy mapping below. - function capabilityResolver(models) { - return function (id) { - var model = models[id]; - return model ? - capabilityService.getCapabilities(model) : - undefined; - }; - } + instantiate = this.instantiate; // Assemble the results from the model service and the // capability service into one value, suitable to return - // from this service. Note that ids are matched to capabilities - // by index. - function assembleResult(ids, models, capabilities) { + // from this service. + function assembleResult(models) { var result = {}; ids.forEach(function (id, index) { if (models[id]) { // Create the domain object - result[id] = new DomainObjectImpl( - id, - models[id], - capabilities[index] - ); + result[id] = instantiate(models[id], id); } }); return result; } - return modelService.getModels(ids).then(function (models) { - return $q.all( - ids.map(capabilityResolver(models)) - ).then(function (capabilities) { - return assembleResult(ids, models, capabilities); - }); - }); + return modelService.getModels(ids).then(assembleResult); }; return DomainObjectProvider; diff --git a/platform/core/src/services/Instantiate.js b/platform/core/src/services/Instantiate.js new file mode 100644 index 0000000000..f59916c938 --- /dev/null +++ b/platform/core/src/services/Instantiate.js @@ -0,0 +1,54 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise*/ + +define( + ['../objects/DomainObjectImpl', 'uuid'], + function (DomainObjectImpl, uuid) { + 'use strict'; + + /** + * The `instantiate` service allows new domain object instances to be + * created. These objects are not persisted to any back-end or + * placed anywhere in the object hierarchy by default. + * + * Usage: `instantiate(model, [id])` + * + * ...returns a new instance of a domain object with the specified + * model. An identifier may be provided; if omitted, one will be + * generated instead. + * + * @constructor + * @memberof platform/core + * @param $injector Angular's `$injector` + */ + function Instantiate(capabilityService) { + return function (model, id) { + var capabilities = capabilityService.getCapabilities(model); + id = id || uuid(); + return new DomainObjectImpl(id, model, capabilities); + }; + } + + return Instantiate; + } +); diff --git a/platform/core/test/capabilities/CreationCapabilitySpec.js b/platform/core/test/capabilities/CreationCapabilitySpec.js deleted file mode 100644 index bfc847fcc7..0000000000 --- a/platform/core/test/capabilities/CreationCapabilitySpec.js +++ /dev/null @@ -1,102 +0,0 @@ -/***************************************************************************** - * Open MCT Web, Copyright (c) 2014-2015, United States Government - * as represented by the Administrator of the National Aeronautics and Space - * Administration. All rights reserved. - * - * Open MCT Web is licensed under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0. - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - * - * Open MCT Web includes source code licensed under additional open source - * licenses. See the Open Source Licenses file (LICENSES.md) included with - * this source code distribution or the Licensing information page available - * at runtime from the About dialog for additional information. - *****************************************************************************/ -/*global define,Promise,describe,it,expect,beforeEach,waitsFor,jasmine*/ - -/** - * ContextCapability. Created by vwoeltje on 11/6/14. - */ -define( - ["../../src/capabilities/CreationCapability"], - function (CreationCapability) { - 'use strict'; - - describe("The 'creation' capability", function () { - var mockInjector, - mockCapabilityService, - creation; - - beforeEach(function () { - mockInjector = jasmine.createSpyObj("$injector", ["get"]); - mockCapabilityService = jasmine.createSpyObj( - "capabilityService", - [ "getCapabilities" ] - ); - - mockInjector.get.andCallFake(function (key) { - return key === 'capabilityService' ? - mockCapabilityService : undefined; - }); - - creation = new CreationCapability(mockInjector); - }); - - - it("aliases 'create' as 'invoke'", function () { - expect(creation.invoke).toBe(creation.create); - }); - - describe("when creating an object", function () { - var mockCapabilityConstructor, - mockCapabilityInstance, - mockCapabilities, - testModel, - domainObject; - - beforeEach(function () { - mockCapabilityConstructor = jasmine.createSpy('capability'); - mockCapabilityInstance = {}; - mockCapabilityService.getCapabilities.andReturn({ - something: mockCapabilityConstructor - }); - mockCapabilityConstructor.andReturn(mockCapabilityInstance); - - testModel = { someKey: "some value" }; - - domainObject = creation.create(testModel); - }); - - it("loads capabilities from the capability service", function () { - expect(mockCapabilityService.getCapabilities) - .toHaveBeenCalledWith(testModel); - }); - - it("exposes loaded capabilities from the created object", function () { - expect(domainObject.getCapability('something')) - .toBe(mockCapabilityInstance); - expect(mockCapabilityConstructor) - .toHaveBeenCalledWith(domainObject); - }); - - it("exposes the provided model", function () { - expect(domainObject.getModel()).toEqual(testModel); - }); - - it("provides unique identifiers", function () { - expect(domainObject.getId()).toEqual(jasmine.any(String)); - expect(creation.create(testModel).getId()) - .not.toEqual(domainObject.getId()); - }); - }); - - }); - } -); diff --git a/platform/core/test/capabilities/InstantiationCapabilitySpec.js b/platform/core/test/capabilities/InstantiationCapabilitySpec.js new file mode 100644 index 0000000000..0798a68f0c --- /dev/null +++ b/platform/core/test/capabilities/InstantiationCapabilitySpec.js @@ -0,0 +1,67 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise,describe,it,xdescribe,expect,beforeEach,waitsFor,jasmine*/ + +define( + ["../../src/capabilities/InstantiationCapability"], + function (InstantiationCapability) { + 'use strict'; + + describe("The 'instantiation' capability", function () { + var mockInjector, + mockInstantiate, + instantiation; + + beforeEach(function () { + mockInjector = jasmine.createSpyObj("$injector", ["get"]); + mockInstantiate = jasmine.createSpy("instantiate"); + + mockInjector.get.andCallFake(function (key) { + return key === 'instantiate' ? + mockInstantiate : undefined; + }); + + instantiation = new InstantiationCapability(mockInjector); + }); + + + it("aliases 'instantiate' as 'invoke'", function () { + expect(instantiation.invoke).toBe(instantiation.instantiate); + }); + + it("uses the instantiate service to create domain objects", function () { + var mockDomainObject = jasmine.createSpyObj('domainObject', [ + 'getId', + 'getModel', + 'getCapability', + 'useCapability', + 'hasCapability' + ]), testModel = { someKey: "some value" }; + mockInstantiate.andReturn(mockDomainObject); + expect(instantiation.instantiate(testModel)) + .toBe(mockDomainObject); + expect(mockInstantiate).toHaveBeenCalledWith(testModel); + }); + + }); + } +); diff --git a/platform/core/test/objects/DomainObjectProviderSpec.js b/platform/core/test/objects/DomainObjectProviderSpec.js index 3aca982260..438c91f103 100644 --- a/platform/core/test/objects/DomainObjectProviderSpec.js +++ b/platform/core/test/objects/DomainObjectProviderSpec.js @@ -25,14 +25,16 @@ * DomainObjectProviderSpec. Created by vwoeltje on 11/6/14. */ define( - ["../../src/objects/DomainObjectProvider"], - function (DomainObjectProvider) { + [ + "../../src/objects/DomainObjectProvider", + "../../src/objects/DomainObjectImpl" + ], + function (DomainObjectProvider, DomainObjectImpl) { "use strict"; describe("The domain object provider", function () { var mockModelService, - mockCapabilityService, - mockQ, + mockInstantiate, provider; function mockPromise(value) { @@ -57,18 +59,15 @@ define( "modelService", [ "getModels" ] ); - mockCapabilityService = jasmine.createSpyObj( - "capabilityService", - [ "getCapabilities" ] - ); - mockQ = { - when: mockPromise, - all: mockAll - }; + mockInstantiate = jasmine.createSpy("instantiate"); + + mockInstantiate.andCallFake(function (model, id) { + return new DomainObjectImpl(id, model, {}); + }); + provider = new DomainObjectProvider( mockModelService, - mockCapabilityService, - mockQ + mockInstantiate ); }); @@ -86,10 +85,11 @@ define( result; mockModelService.getModels.andReturn(mockPromise({ a: model })); result = provider.getObjects(ids).testValue; + expect(mockInstantiate).toHaveBeenCalledWith(model, 'a'); expect(result.a.getId()).toEqual("a"); expect(result.a.getModel()).toEqual(model); }); }); } -); \ No newline at end of file +); diff --git a/platform/core/test/services/InstantiateSpec.js b/platform/core/test/services/InstantiateSpec.js new file mode 100644 index 0000000000..31a5731dd3 --- /dev/null +++ b/platform/core/test/services/InstantiateSpec.js @@ -0,0 +1,81 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ +/*global define,Promise,describe,it,xdescribe,expect,beforeEach,waitsFor,jasmine*/ + +define( + ["../../src/services/Instantiate"], + function (Instantiate) { + 'use strict'; + + describe("The 'instantiate' service", function () { + + var mockCapabilityService, + mockCapabilityConstructor, + mockCapabilityInstance, + mockCapabilities, + testModel, + instantiate, + domainObject; + + beforeEach(function () { + mockCapabilityService = jasmine.createSpyObj( + 'capabilityService', + ['getCapabilities'] + ); + mockCapabilityConstructor = jasmine.createSpy('capability'); + mockCapabilityInstance = {}; + mockCapabilityService.getCapabilities.andReturn({ + something: mockCapabilityConstructor + }); + mockCapabilityConstructor.andReturn(mockCapabilityInstance); + + testModel = { someKey: "some value" }; + + instantiate = new Instantiate(mockCapabilityService); + domainObject = instantiate(testModel); + }); + + it("loads capabilities from the capability service", function () { + expect(mockCapabilityService.getCapabilities) + .toHaveBeenCalledWith(testModel); + }); + + it("exposes loaded capabilities from the created object", function () { + expect(domainObject.getCapability('something')) + .toBe(mockCapabilityInstance); + expect(mockCapabilityConstructor) + .toHaveBeenCalledWith(domainObject); + }); + + it("exposes the provided model", function () { + expect(domainObject.getModel()).toEqual(testModel); + }); + + it("provides unique identifiers", function () { + expect(domainObject.getId()).toEqual(jasmine.any(String)); + expect(instantiate(testModel).getId()) + .not.toEqual(domainObject.getId()); + }); + }); + + } +); diff --git a/platform/core/test/suite.json b/platform/core/test/suite.json index 3b0613629d..d6afc373ef 100644 --- a/platform/core/test/suite.json +++ b/platform/core/test/suite.json @@ -8,8 +8,8 @@ "capabilities/ContextCapability", "capabilities/ContextualDomainObject", "capabilities/CoreCapabilityProvider", - "capabilities/CreationCapability", "capabilities/DelegationCapability", + "capabilities/InstantiationCapability", "capabilities/MetadataCapability", "capabilities/MutationCapability", "capabilities/PersistenceCapability", @@ -26,6 +26,7 @@ "objects/DomainObjectProvider", "services/Contextualize", + "services/Instantiate", "services/Now", "services/Throttle", "services/Topic", diff --git a/platform/entanglement/bundle.json b/platform/entanglement/bundle.json index d8cde0ada6..714d9f7f79 100644 --- a/platform/entanglement/bundle.json +++ b/platform/entanglement/bundle.json @@ -20,7 +20,8 @@ "glyph": "+", "category": "contextual", "implementation": "actions/CopyAction.js", - "depends": ["locationService", "copyService"] + "depends": ["$log", "locationService", "copyService", + "dialogService", "notificationService"] }, { "key": "link", @@ -84,7 +85,8 @@ "name": "Copy Service", "description": "Provides a service for copying objects", "implementation": "services/CopyService.js", - "depends": ["$q", "creationService", "policyService"] + "depends": ["$q", "creationService", "policyService", + "persistenceService", "now"] }, { "key": "locationService", diff --git a/platform/entanglement/src/actions/CopyAction.js b/platform/entanglement/src/actions/CopyAction.js index 3411fdba85..cdcefeb935 100644 --- a/platform/entanglement/src/actions/CopyAction.js +++ b/platform/entanglement/src/actions/CopyAction.js @@ -34,16 +34,103 @@ define( * @constructor * @memberof platform/entanglement */ - function CopyAction(locationService, copyService, context) { - return new AbstractComposeAction( - locationService, - copyService, - context, - "Duplicate", - "to a location" - ); + function CopyAction($log, locationService, copyService, dialogService, + notificationService, context) { + this.dialog = undefined; + this.notification = undefined; + this.dialogService = dialogService; + this.notificationService = notificationService; + this.$log = $log; + //Extend the behaviour of the Abstract Compose Action + AbstractComposeAction.call(this, locationService, copyService, + context, "Duplicate", "to a location"); } + /** + * Updates user about progress of copy. Should not be invoked by + * client code under any circumstances. + * + * @private + * @param phase + * @param totalObjects + * @param processed + */ + CopyAction.prototype.progress = function(phase, totalObjects, processed){ + /* + Copy has two distinct phases. In the first phase a copy plan is + made in memory. During this phase of execution, the user is + shown a blocking 'modal' dialog. + + In the second phase, the copying is taking place, and the user + is shown non-invasive banner notifications at the bottom of the screen. + */ + if (phase.toLowerCase() === 'preparing' && !this.dialog){ + this.dialog = this.dialogService.showBlockingMessage({ + title: "Preparing to copy objects", + unknownProgress: true, + severity: "info" + }); + } else if (phase.toLowerCase() === "copying") { + this.dialogService.dismiss(); + if (!this.notification) { + this.notification = this.notificationService + .notify({ + title: "Copying objects", + unknownProgress: false, + severity: "info" + }); + } + this.notification.model.progress = (processed / totalObjects) * 100; + this.notification.model.title = ["Copied ", processed, "of ", + totalObjects, "objects"].join(" "); + } + }; + + /** + * Executes the CopyAction. The CopyAction uses the default behaviour of + * the AbstractComposeAction, but extends it to support notification + * updates of progress on copy. + */ + CopyAction.prototype.perform = function() { + var self = this; + + function success(){ + self.notification.dismiss(); + self.notificationService.info("Copying complete."); + } + + function error(errorDetails){ + var errorMessage = { + title: "Error copying objects.", + severity: "error", + hint: errorDetails.message, + minimized: true, // want the notification to be minimized initially (don't show banner) + options: [{ + label: "OK", + callback: function() { + self.dialogService.dismiss(); + } + }] + }; + + self.dialogService.dismiss(); + if (self.notification) { + self.notification.dismiss(); // Clear the progress notification + } + self.$log.error("Error copying objects. ", errorDetails); + //Show a minimized notification of error for posterity + self.notificationService.notify(errorMessage); + //Display a blocking message + self.dialogService.showBlockingMessage(errorMessage); + + } + function notification(details){ + self.progress(details.phase, details.totalObjects, details.processed); + } + + return AbstractComposeAction.prototype.perform.call(this) + .then(success, error, notification); + }; return CopyAction; } ); diff --git a/platform/entanglement/src/services/CopyService.js b/platform/entanglement/src/services/CopyService.js index 48ba3e7ce5..29c6be4d10 100644 --- a/platform/entanglement/src/services/CopyService.js +++ b/platform/entanglement/src/services/CopyService.js @@ -23,7 +23,11 @@ /*global define */ define( - function () { + [ + "uuid", + "./CopyTask" + ], + function (uuid, CopyTask) { "use strict"; /** @@ -34,10 +38,12 @@ define( * @memberof platform/entanglement * @implements {platform/entanglement.AbstractComposeService} */ - function CopyService($q, creationService, policyService) { + function CopyService($q, creationService, policyService, persistenceService, now) { this.$q = $q; this.creationService = creationService; this.policyService = policyService; + this.persistenceService = persistenceService; + this.now = now; } CopyService.prototype.validate = function (object, parentCandidate) { @@ -54,45 +60,25 @@ define( ); }; + /** + * Creates a duplicate of the object tree starting at domainObject to + * the new parent specified. + * @param domainObject + * @param parent + * @param progress + * @returns a promise that will be completed with the clone of + * domainObject when the duplication is successful. + */ CopyService.prototype.perform = function (domainObject, parent) { - var model = JSON.parse(JSON.stringify(domainObject.getModel())), - $q = this.$q, - self = this; - - // Wrapper for the recursive step - function duplicateObject(domainObject, parent) { - return self.perform(domainObject, parent); - } - - if (!this.validate(domainObject, parent)) { + var $q = this.$q, + copyTask = new CopyTask(domainObject, parent, this.persistenceService, this.$q, this.now); + if (this.validate(domainObject, parent)) { + return copyTask.perform(); + } else { throw new Error( "Tried to copy objects without validating first." ); } - - if (domainObject.hasCapability('composition')) { - model.composition = []; - } - - return this.creationService - .createObject(model, parent) - .then(function (newObject) { - if (!domainObject.hasCapability('composition')) { - return; - } - - return domainObject - .useCapability('composition') - .then(function (composees) { - // Duplicate composition serially to prevent - // write conflicts. - return composees.reduce(function (promise, composee) { - return promise.then(function () { - return duplicateObject(composee, newObject); - }); - }, $q.when(undefined)); - }); - }); }; return CopyService; diff --git a/platform/entanglement/src/services/CopyTask.js b/platform/entanglement/src/services/CopyTask.js new file mode 100644 index 0000000000..f484856448 --- /dev/null +++ b/platform/entanglement/src/services/CopyTask.js @@ -0,0 +1,198 @@ +/***************************************************************************** + * Open MCT Web, Copyright (c) 2014-2015, United States Government + * as represented by the Administrator of the National Aeronautics and Space + * Administration. All rights reserved. + * + * Open MCT Web is licensed under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0. + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + * + * Open MCT Web includes source code licensed under additional open source + * licenses. See the Open Source Licenses file (LICENSES.md) included with + * this source code distribution or the Licensing information page available + * at runtime from the About dialog for additional information. + *****************************************************************************/ + +/*global define */ + +define( + ["uuid"], + function (uuid) { + "use strict"; + + /** + * This class encapsulates the process of copying a domain object + * and all of its children. + * + * @param domainObject The object to copy + * @param parent The new location of the cloned object tree + * @param persistenceService + * @param $q + * @param now + * @constructor + */ + function CopyTask (domainObject, parent, persistenceService, $q, now){ + this.domainObject = domainObject; + this.parent = parent; + this.$q = $q; + this.deferred = undefined; + this.persistenceService = persistenceService; + this.persisted = 0; + this.now = now; + this.clones = []; + } + + function composeChild(child, parent) { + //Once copied, associate each cloned + // composee with its parent clone + child.model.location = parent.id; + parent.model.composition = parent.model.composition || []; + return parent.model.composition.push(child.id); + } + + function cloneObjectModel(objectModel) { + var clone = JSON.parse(JSON.stringify(objectModel)); + + delete clone.composition; + delete clone.persisted; + delete clone.modified; + + return clone; + } + + /** + * Will persist a list of {@link objectClones}. It will persist all + * simultaneously, irrespective of order in the list. This may + * result in automatic request batching by the browser. + */ + function persistObjects(self) { + + return self.$q.all(self.clones.map(function(clone){ + clone.model.persisted = self.now(); + return self.persistenceService.createObject(clone.persistenceSpace, clone.id, clone.model) + .then(function(){ + self.deferred.notify({phase: "copying", totalObjects: self.clones.length, processed: ++self.persisted}); + }); + })).then(function(){ + return self; + }); + } + + /** + * Will add a list of clones to the specified parent's composition + */ + function addClonesToParent(self) { + var parentClone = self.clones[self.clones.length-1]; + + if (!self.parent.hasCapability('composition')){ + return self.$q.reject(); + } + + return self.persistenceService + .updateObject(parentClone.persistenceSpace, parentClone.id, parentClone.model) + .then(function(){return self.parent.getCapability("composition").add(parentClone.id);}) + .then(function(){return self.parent.getCapability("persistence").persist();}) + .then(function(){return parentClone;}); + // Ensure the clone of the original domainObject is returned + } + + /** + * Given an array of objects composed by a parent, clone them, then + * add them to the parent. + * @private + * @returns {*} + */ + CopyTask.prototype.copyComposees = function(composees, clonedParent, originalParent){ + var self = this; + + return (composees || []).reduce(function(promise, composee){ + //If the composee is composed of other + // objects, chain a promise.. + return promise.then(function(){ + // ...to recursively copy it (and its children) + return self.copy(composee, originalParent).then(function(composee){ + composeChild(composee, clonedParent); + }); + });}, self.$q.when(undefined) + ); + }; + + /** + * A recursive function that will perform a bottom-up copy of + * the object tree with originalObject at the root. Recurses to + * the farthest leaf, then works its way back up again, + * cloning objects, and composing them with their child clones + * as it goes + * @private + * @param originalObject + * @param originalParent + * @returns {*} + */ + CopyTask.prototype.copy = function(originalObject, originalParent) { + var self = this, + modelClone = { + id: uuid(), + model: cloneObjectModel(originalObject.getModel()), + persistenceSpace: originalParent.hasCapability('persistence') && originalParent.getCapability('persistence').getSpace() + }; + + return this.$q.when(originalObject.useCapability('composition')).then(function(composees){ + self.deferred.notify({phase: "preparing"}); + //Duplicate the object's children, and their children, and + // so on down to the leaf nodes of the tree. + return self.copyComposees(composees, modelClone, originalObject).then(function (){ + //Add the clone to the list of clones that will + //be returned by this function + self.clones.push(modelClone); + return modelClone; + }); + }); + }; + + /** + * Will build a graph of an object and all of its child objects in + * memory + * @private + * @param domainObject The original object to be copied + * @param parent The parent of the original object to be copied + * @returns {Promise} resolved with an array of clones of the models + * of the object tree being copied. Copying is done in a bottom-up + * fashion, so that the last member in the array is a clone of the model + * object being copied. The clones are all full composed with + * references to their own children. + */ + CopyTask.prototype.buildCopyPlan = function() { + var self = this; + + return this.copy(self.domainObject, self.parent).then(function(domainObjectClone){ + domainObjectClone.model.location = self.parent.getId(); + return self; + }); + }; + + /** + * Execute the copy task with the objects provided in the constructor. + * @returns {promise} Which will resolve with a clone of the object + * once complete. + */ + CopyTask.prototype.perform = function(){ + this.deferred = this.$q.defer(); + + this.buildCopyPlan() + .then(persistObjects) + .then(addClonesToParent) + .then(this.deferred.resolve, this.deferred.reject); + + return this.deferred.promise; + }; + + return CopyTask; + } +); \ No newline at end of file diff --git a/platform/entanglement/test/actions/CopyActionSpec.js b/platform/entanglement/test/actions/CopyActionSpec.js index 4284a22e59..fc8e615960 100644 --- a/platform/entanglement/test/actions/CopyActionSpec.js +++ b/platform/entanglement/test/actions/CopyActionSpec.js @@ -20,7 +20,7 @@ * at runtime from the About dialog for additional information. *****************************************************************************/ -/*global define,describe,beforeEach,it,jasmine,expect */ +/*global define,describe,beforeEach,it,jasmine,expect,spyOn */ define( [ @@ -41,7 +41,13 @@ define( selectedObject, selectedObjectContextCapability, currentParent, - newParent; + newParent, + notificationService, + notification, + dialogService, + mockLog, + abstractComposePromise, + progress = {phase: "copying", totalObjects: 10, processed: 1}; beforeEach(function () { selectedObjectContextCapability = jasmine.createSpyObj( @@ -87,10 +93,43 @@ define( ] ); + abstractComposePromise = jasmine.createSpyObj( + 'abstractComposePromise', + [ + 'then' + ] + ); + + abstractComposePromise.then.andCallFake(function(success, error, notify){ + notify(progress); + success(); + }); + + locationServicePromise.then.andCallFake(function(callback){ + callback(newParent); + return abstractComposePromise; + }); + locationService .getLocationFromUser .andReturn(locationServicePromise); + dialogService = jasmine.createSpyObj('dialogService', + ['showBlockingMessage', 'dismiss'] + ); + + notification = jasmine.createSpyObj('notification', + ['dismiss', 'model'] + ); + + notificationService = jasmine.createSpyObj('notificationService', + ['notify', 'info'] + ); + + notificationService.notify.andReturn(notification); + + mockLog = jasmine.createSpyObj('log', ['error']); + copyService = new MockCopyService(); }); @@ -102,8 +141,11 @@ define( }; copyAction = new CopyAction( + mockLog, locationService, copyService, + dialogService, + notificationService, context ); }); @@ -114,6 +156,7 @@ define( describe("when performed it", function () { beforeEach(function () { + spyOn(copyAction, 'progress').andCallThrough(); copyAction.perform(); }); @@ -132,7 +175,7 @@ define( .toHaveBeenCalledWith(jasmine.any(Function)); }); - it("copys object to selected location", function () { + it("copies object to selected location", function () { locationServicePromise .then .mostRecentCall @@ -141,6 +184,11 @@ define( expect(copyService.perform) .toHaveBeenCalledWith(selectedObject, newParent); }); + + it("notifies the user of progress", function(){ + expect(notificationService.info).toHaveBeenCalled(); + }); + }); }); @@ -152,8 +200,11 @@ define( }; copyAction = new CopyAction( + mockLog, locationService, copyService, + dialogService, + notificationService, context ); }); diff --git a/platform/entanglement/test/services/CopyServiceSpec.js b/platform/entanglement/test/services/CopyServiceSpec.js index 2788fcefa8..391d90913c 100644 --- a/platform/entanglement/test/services/CopyServiceSpec.js +++ b/platform/entanglement/test/services/CopyServiceSpec.js @@ -31,6 +31,10 @@ define( "use strict"; function synchronousPromise(value) { + if (value && value.then) { + return value; + } + var promise = { then: function (callback) { return synchronousPromise(callback(value)); @@ -122,13 +126,19 @@ define( describe("perform", function () { var mockQ, + mockDeferred, creationService, createObjectPromise, copyService, + mockPersistenceService, + mockNow, object, newParent, copyResult, - copyFinished; + copyFinished, + persistObjectPromise, + parentPersistenceCapability, + resolvedValue; beforeEach(function () { creationService = jasmine.createSpyObj( @@ -138,44 +148,93 @@ define( createObjectPromise = synchronousPromise(undefined); creationService.createObject.andReturn(createObjectPromise); policyService.allow.andReturn(true); + + mockPersistenceService = jasmine.createSpyObj( + 'persistenceService', + ['createObject', 'updateObject'] + ); + persistObjectPromise = synchronousPromise(undefined); + mockPersistenceService.createObject.andReturn(persistObjectPromise); + mockPersistenceService.updateObject.andReturn(persistObjectPromise); + + parentPersistenceCapability = jasmine.createSpyObj( + "persistence", + [ "persist", "getSpace" ] + ); + + parentPersistenceCapability.persist.andReturn(persistObjectPromise); + parentPersistenceCapability.getSpace.andReturn("testSpace"); + + mockNow = jasmine.createSpyObj("mockNow", ["now"]); + mockNow.now.andCallFake(function(){ + return 1234; + }); + + mockDeferred = jasmine.createSpyObj('mockDeferred', ['notify', 'resolve']); + mockDeferred.notify.andCallFake(function(notification){}); + mockDeferred.resolve.andCallFake(function(value){resolvedValue = value;}); + mockDeferred.promise = { + then: function(callback){ + return synchronousPromise(callback(resolvedValue)); + } + }; + + mockQ = jasmine.createSpyObj('mockQ', ['when', 'all', 'reject', 'defer']); + mockQ.when.andCallFake(synchronousPromise); + mockQ.all.andCallFake(function (promises) { + var result = {}; + Object.keys(promises).forEach(function (k) { + promises[k].then(function (v) { result[k] = v; }); + }); + return synchronousPromise(result); + }); + mockQ.defer.andReturn(mockDeferred); + }); describe("on domain object without composition", function () { beforeEach(function () { - object = domainObjectFactory({ - name: 'object', - id: 'abc', - model: { - name: 'some object' - } - }); newParent = domainObjectFactory({ name: 'newParent', id: '456', model: { composition: [] + }, + capabilities: { + persistence: parentPersistenceCapability } }); - copyService = new CopyService(null, creationService, policyService); + + object = domainObjectFactory({ + name: 'object', + id: 'abc', + model: { + name: 'some object', + location: newParent.id, + persisted: mockNow.now() + } + }); + + copyService = new CopyService(mockQ, creationService, policyService, mockPersistenceService, mockNow.now); copyResult = copyService.perform(object, newParent); copyFinished = jasmine.createSpy('copyFinished'); copyResult.then(copyFinished); }); - it("uses creation service", function () { - expect(creationService.createObject) - .toHaveBeenCalledWith(jasmine.any(Object), newParent); - - expect(createObjectPromise.then) - .toHaveBeenCalledWith(jasmine.any(Function)); - }); + it("uses persistence service", function () { + expect(mockPersistenceService.createObject) + .toHaveBeenCalledWith(parentPersistenceCapability.getSpace(), jasmine.any(String), object.getModel()); + expect(persistObjectPromise.then) + .toHaveBeenCalledWith(jasmine.any(Function)); + }); + it("deep clones object model", function () { - var newModel = creationService + //var newModel = creationService + var newModel = mockPersistenceService .createObject .mostRecentCall - .args[0]; - + .args[2]; expect(newModel).toEqual(object.model); expect(newModel).not.toBe(object.model); }); @@ -191,11 +250,15 @@ define( var newObject, childObject, compositionCapability, + locationCapability, compositionPromise; beforeEach(function () { - mockQ = jasmine.createSpyObj('mockQ', ['when']); - mockQ.when.andCallFake(synchronousPromise); + + + locationCapability = jasmine.createSpyObj('locationCapability', ['isLink']); + locationCapability.isLink.andReturn(true); + childObject = domainObjectFactory({ name: 'childObject', id: 'def', @@ -205,24 +268,28 @@ define( }); compositionCapability = jasmine.createSpyObj( 'compositionCapability', - ['invoke'] + ['invoke', 'add'] ); compositionPromise = jasmine.createSpyObj( 'compositionPromise', ['then'] ); + compositionCapability .invoke - .andReturn(compositionPromise); + .andReturn(synchronousPromise([childObject])); + object = domainObjectFactory({ name: 'object', id: 'abc', model: { name: 'some object', - composition: ['def'] + composition: ['def'], + location: 'testLocation' }, capabilities: { - composition: compositionCapability + composition: compositionCapability, + location: locationCapability } }); newObject = domainObjectFactory({ @@ -241,45 +308,45 @@ define( id: '456', model: { composition: [] + }, + capabilities: { + composition: compositionCapability, + persistence: parentPersistenceCapability } }); createObjectPromise = synchronousPromise(newObject); creationService.createObject.andReturn(createObjectPromise); - copyService = new CopyService(mockQ, creationService, policyService); - copyResult = copyService.perform(object, newParent); - copyFinished = jasmine.createSpy('copyFinished'); - copyResult.then(copyFinished); + copyService = new CopyService(mockQ, creationService, policyService, mockPersistenceService, mockNow.now); }); - it("uses creation service", function () { - expect(creationService.createObject) - .toHaveBeenCalledWith(jasmine.any(Object), newParent); + describe("the cloning process", function(){ + beforeEach(function() { + copyResult = copyService.perform(object, newParent); + copyFinished = jasmine.createSpy('copyFinished'); + copyResult.then(copyFinished); + }); - expect(createObjectPromise.then) - .toHaveBeenCalledWith(jasmine.any(Function)); - }); + it("copies object and children in a bottom-up" + + " fashion", function () { + expect(mockPersistenceService.createObject.calls[0].args[2].name).toEqual(childObject.model.name); + expect(mockPersistenceService.createObject.calls[1].args[2].name).toEqual(object.model.name); + }); - it("clears model composition", function () { - var newModel = creationService - .createObject - .mostRecentCall - .args[0]; + it("returns a promise", function () { + expect(copyResult.then).toBeDefined(); + expect(copyFinished).toHaveBeenCalled(); + }); - expect(newModel.composition.length).toBe(0); - expect(newModel.name).toBe('some object'); - }); + it("clears modified and sets persisted", function () { + expect(copyFinished.mostRecentCall.args[0].model.modified).toBeUndefined(); + expect(copyFinished.mostRecentCall.args[0].model.persisted).toBe(mockNow.now()); + }); - it("recursively clones it's children", function () { - expect(creationService.createObject.calls.length).toBe(1); - expect(compositionCapability.invoke).toHaveBeenCalled(); - compositionPromise.then.mostRecentCall.args[0]([childObject]); - expect(creationService.createObject.calls.length).toBe(2); - }); + it ("correctly locates cloned objects", function() { + expect(mockPersistenceService.createObject.calls[0].args[2].location).toEqual(mockPersistenceService.createObject.calls[1].args[1]); + }); - it("returns a promise", function () { - expect(copyResult.then).toBeDefined(); - expect(copyFinished).toHaveBeenCalled(); }); }); @@ -301,7 +368,7 @@ define( it("throws an error", function () { var copyService = - new CopyService(mockQ, creationService, policyService); + new CopyService(mockQ, creationService, policyService, mockPersistenceService, mockNow.now); function perform() { copyService.perform(object, newParent); diff --git a/platform/features/conductor/src/ConductorRepresenter.js b/platform/features/conductor/src/ConductorRepresenter.js index 3b9cb58be4..957e6af9ba 100644 --- a/platform/features/conductor/src/ConductorRepresenter.js +++ b/platform/features/conductor/src/ConductorRepresenter.js @@ -102,7 +102,7 @@ define( function updateDomain(value) { var newDomain = conductor.domain(value); conductorScope.parameters.format = newDomain.format; - repScope.$broadcast('telemetry:display:bounds', bounds()); + broadcastBounds(); } // telemetry domain metadata -> option for a select control @@ -139,8 +139,6 @@ define( .$watch('ngModel.conductor.inner.end', updateConductorInner); conductorScope .$watch('ngModel.domain', updateDomain); - - repScope.$on('telemetry:view', updateConductorInner); }; ConductorRepresenter.prototype.conductorScope = function (s) { diff --git a/platform/features/plot/src/PlotController.js b/platform/features/plot/src/PlotController.js index d6acdb6a5c..cf6bfcf581 100644 --- a/platform/features/plot/src/PlotController.js +++ b/platform/features/plot/src/PlotController.js @@ -245,9 +245,6 @@ define( // Unsubscribe when the plot is destroyed $scope.$on("$destroy", releaseSubscription); - - // Notify any external observers that a new telemetry view is here - $scope.$emit("telemetry:view"); } /** diff --git a/platform/telemetry/src/TelemetryHandle.js b/platform/telemetry/src/TelemetryHandle.js index ff77d7b9e0..11fd05bb90 100644 --- a/platform/telemetry/src/TelemetryHandle.js +++ b/platform/telemetry/src/TelemetryHandle.js @@ -39,6 +39,7 @@ define( */ function TelemetryHandle($q, subscription) { var seriesMap = {}, + active = true, self = Object.create(subscription); // Request a telemetry series for this specific object @@ -50,7 +51,7 @@ define( // Store it for subsequent lookup seriesMap[id] = series; // Notify callback of new series data, if there is one - if (callback) { + if (callback && active) { callback(telemetryObject, series); } // Pass it along for promise-chaining @@ -61,6 +62,10 @@ define( return telemetry.requestData(request).then(receiveSeries); } + self.unsubscribe = function () { + active = false; + return subscription.unsubscribe(); + }; /** * Get the most recently obtained telemetry data series associated diff --git a/platform/telemetry/test/TelemetryHandleSpec.js b/platform/telemetry/test/TelemetryHandleSpec.js index 2e34b8dcd3..8e543d21dd 100644 --- a/platform/telemetry/test/TelemetryHandleSpec.js +++ b/platform/telemetry/test/TelemetryHandleSpec.js @@ -85,10 +85,18 @@ define( it("exposes subscription API", function () { // Should still expose methods from the provided subscription - expect(handle.unsubscribe) - .toBe(mockSubscription.unsubscribe); - expect(handle.getTelemetryObjects) - .toBe(mockSubscription.getTelemetryObjects); + // (though these may have been wrapped) + expect(mockSubscription.getTelemetryObjects) + .not.toHaveBeenCalled(); + handle.getTelemetryObjects(); + expect(mockSubscription.getTelemetryObjects) + .toHaveBeenCalled(); + + expect(mockSubscription.unsubscribe) + .not.toHaveBeenCalled(); + handle.unsubscribe(); + expect(mockSubscription.unsubscribe) + .toHaveBeenCalled(); }); it("provides an interface for historical requests", function () {