Compare commits
	
		
			278 Commits
		
	
	
		
			open-maste
			...
			inspector
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | cebdf24666 | ||
|   | 15152d26f8 | ||
|   | 50c08a15d6 | ||
|   | 8f40d7d9ee | ||
|   | 38b09fbeb1 | ||
|   | 455f4b6bdb | ||
|   | b0b87d7fd9 | ||
|   | 8c811c4a22 | ||
|   | f1bf88fac4 | ||
|   | cf421f8b9a | ||
|   | 953bd9d8fc | ||
|   | 95791d5c3a | ||
|   | 30cd3d0074 | ||
|   | cd4bc6c3b4 | ||
|   | 4de8d91890 | ||
|   | 1dd3d5214d | ||
|   | bcf6bbf627 | ||
|   | 01f5a4886b | ||
|   | 815b8e040e | ||
|   | a957f87f61 | ||
|   | 5230bdfc6b | ||
|   | 97acf2012a | ||
|   | 687d86790e | ||
|   | 3ec4cc099b | ||
|   | dadbf3f6dc | ||
|   | c4c4c42415 | ||
|   | 7b9a886beb | ||
|   | 2cd1907b71 | ||
|   | 7a69bffb4a | ||
|   | 05fb7173aa | ||
|   | 57d1876dd8 | ||
|   | 7119f6f3a1 | ||
|   | e7563ff4e9 | ||
|   | a507557cec | ||
|   | 86d398d8ff | ||
|   | 5cc634e946 | ||
|   | 7e837c266d | ||
|   | cd204af71c | ||
|   | 4e9348cb28 | ||
|   | 509badb225 | ||
|   | c4de3505b9 | ||
|   | c3e5fbf713 | ||
|   | 5080b5296e | ||
|   | 7a7cabedcc | ||
|   | 6571da922d | ||
|   | 33d88ecce0 | ||
|   | 70324a2198 | ||
|   | c81e2dbb4a | ||
|   | 41198627c3 | ||
|   | 454b96c3c9 | ||
|   | b8eaea5624 | ||
|   | d5062c74a2 | ||
|   | d877ee3ce3 | ||
|   | f1ca9ff15e | ||
|   | 57e3c2554d | ||
|   | 67e57081f4 | ||
|   | 9eb23a62bc | ||
|   | 9b6a839c06 | ||
|   | 7715acd4d4 | ||
|   | 6aaa887e65 | ||
|   | e53c419e87 | ||
|   | 6e8dcc6ab8 | ||
|   | 1e332da11b | ||
|   | 3a050cc5b8 | ||
|   | bbcb0e15c9 | ||
|   | d0183d44c9 | ||
|   | a7cc06a28b | ||
|   | 7b5f07ae45 | ||
|   | 3343475973 | ||
|   | 71207d643a | ||
|   | d9a65a1844 | ||
|   | 32c7cc2424 | ||
|   | dcfcfa74bb | ||
|   | 79529e4879 | ||
|   | 503c8e2f03 | ||
|   | 570e0f31b2 | ||
|   | 83c86c748c | ||
|   | 4b3ca316e1 | ||
|   | 3f7b874b38 | ||
|   | ed96889fce | ||
|   | d2bc8227c7 | ||
|   | 81ece1190e | ||
|   | 249a9b2eb2 | ||
|   | 62f7ca5a0a | ||
|   | 29b1cfa890 | ||
|   | e44e50823e | ||
|   | 4a730f875f | ||
|   | 02abbdf4fe | ||
|   | 08d68f99a5 | ||
|   | 8108a3b81c | ||
|   | b8958edf72 | ||
|   | 2b00b71da9 | ||
|   | 9c912b62d3 | ||
|   | f27e4d6e06 | ||
|   | 9c578c53db | ||
|   | a4a9acd2ea | ||
|   | c118234bbf | ||
|   | a94763041e | ||
|   | ffd80ed42b | ||
|   | 8dad6a3fd5 | ||
|   | 26892e7104 | ||
|   | 5c74365f4b | ||
|   | 94854e5965 | ||
|   | 9cf30f4213 | ||
|   | eb776e69c0 | ||
|   | 33a63947e5 | ||
|   | 432ec519b6 | ||
|   | 7f65ba236c | ||
|   | 3a86f5e746 | ||
|   | 4e3e3653a3 | ||
|   | d3ea67fbd9 | ||
|   | 9ebc04ef14 | ||
|   | e426e0e5ec | ||
|   | 3d1e1659c2 | ||
|   | 17f2bb966b | ||
|   | 158f549df2 | ||
|   | a98b65286f | ||
|   | 17aa666519 | ||
|   | f6cf4c3215 | ||
|   | 86f0a9100f | ||
|   | f4b87cf70d | ||
|   | 841273edf6 | ||
|   | 366ec3d516 | ||
|   | a4e2aba6dc | ||
|   | f4ae86eb53 | ||
|   | 3a932f5443 | ||
|   | ce58aff18a | ||
|   | 24ee8ec063 | ||
|   | eee8790682 | ||
|   | 083932e902 | ||
|   | e159b7a15d | ||
|   | 4481c44c4b | ||
|   | 6d660d48ca | ||
|   | bf417a14e0 | ||
|   | 0cee5ad380 | ||
|   | 7b4934ec55 | ||
|   | 2ef0c2a8cb | ||
|   | 80c99d2eb6 | ||
|   | 2ccca016a5 | ||
|   | cb0f72052f | ||
|   | 1030eff943 | ||
|   | 5e3caf6252 | ||
|   | aa67489404 | ||
|   | 1ea6f7620e | ||
|   | 365134b085 | ||
|   | 07a2065c11 | ||
|   | f8cb3f464c | ||
|   | 31337eaf4f | ||
|   | 3e8ea972c2 | ||
|   | 0f6287e715 | ||
|   | 0cfd881510 | ||
|   | edca2a9f03 | ||
|   | cc05c50769 | ||
|   | adbb3486c5 | ||
|   | ced1609e51 | ||
|   | 7fe866060b | ||
|   | 7bc9b83aac | ||
|   | d6d16f8f1c | ||
|   | bcea3832ed | ||
|   | 94662cb904 | ||
|   | 26ab9af911 | ||
|   | f38b89a582 | ||
|   | c17ec19f97 | ||
|   | 2ca7a175bd | ||
|   | 371b690072 | ||
|   | c62e73f863 | ||
|   | 5726dd0e0c | ||
|   | 1c187c3914 | ||
|   | 74cf4d73d5 | ||
|   | c8694f182a | ||
|   | 2e767c94c4 | ||
|   | 6302eee17e | ||
|   | 820c15d74c | ||
|   | b26aa3cab7 | ||
|   | c51856522c | ||
|   | aefad6fdd3 | ||
|   | a9c85d5241 | ||
|   | edf52f32ad | ||
|   | 18bc7d3637 | ||
|   | 175490e1f7 | ||
|   | 3492cd3942 | ||
|   | ed53808556 | ||
|   | 41ddb76385 | ||
|   | 55dd8cb1a8 | ||
|   | eefc746567 | ||
|   | 0218bad9e8 | ||
|   | dd993c81a7 | ||
|   | a76e54483a | ||
|   | 515470fa6a | ||
|   | 3555f41f3e | ||
|   | 9dd520f17b | ||
|   | a9e2d48036 | ||
|   | d701567b70 | ||
|   | 7911909c5f | ||
|   | b93d752c88 | ||
|   | 5e4dcc1e35 | ||
|   | 9939c809be | ||
|   | 89cb6867bd | ||
|   | 98801cb5d6 | ||
|   | 23bc246a48 | ||
|   | 11a45e4db0 | ||
|   | c450c22ddd | ||
|   | c19b3384ca | ||
|   | b7765ff388 | ||
|   | f377c7cb71 | ||
|   | aa08db1050 | ||
|   | a48a0820ad | ||
|   | 109d933945 | ||
|   | 7b471e5379 | ||
|   | de291ad3b1 | ||
|   | 140d767026 | ||
|   | be5cad212a | ||
|   | efc42aa8f2 | ||
|   | f8a0ddb484 | ||
|   | 3a0ba4f5a6 | ||
|   | a77920bd18 | ||
|   | 78146d97f8 | ||
|   | 0b9b936368 | ||
|   | 23f18c799d | ||
|   | a7a1ac70e5 | ||
|   | 31eb366e7f | ||
|   | eaaa1a19ca | ||
|   | c08a460d30 | ||
|   | 14f97eae9c | ||
|   | 2f79323264 | ||
|   | 1558c9d1bd | ||
|   | 7141c2818a | ||
|   | 058a0d393d | ||
|   | b0a23590d4 | ||
|   | 48a9eef924 | ||
|   | 62f335573a | ||
|   | c80e9bfa26 | ||
|   | ec62c27f36 | ||
|   | 19b80ded16 | ||
|   | f72f88adfa | ||
|   | f083d019a3 | ||
|   | 10ec30ba76 | ||
|   | 3fb4296d23 | ||
|   | 197ec0eb2c | ||
|   | 1d162888dd | ||
|   | 5ab26df4c9 | ||
|   | 3783ed69d7 | ||
|   | 1d2cd4745c | ||
|   | ee2d7efae2 | ||
|   | 4a755e259f | ||
|   | 4c56e4ffdc | ||
|   | 449db4f3a9 | ||
|   | 6802484ad8 | ||
|   | e0a0d293fa | ||
|   | 1a4d7618c1 | ||
|   | 44dce05ec5 | ||
|   | e729a966c7 | ||
|   | 8923f23f70 | ||
|   | 6407a66d30 | ||
|   | 7f486f739d | ||
|   | 5fa6db72d2 | ||
|   | e43e14ec00 | ||
|   | c9acfc9f89 | ||
|   | d82be0deef | ||
|   | eab140df48 | ||
|   | 15e39e00c2 | ||
|   | 077a0ce3e3 | ||
|   | 5711b2b241 | ||
|   | d9a1b9d530 | ||
|   | 9ea1d24121 | ||
|   | 40e85b718d | ||
|   | a9418fd2c7 | ||
|   | 50ce800c2a | ||
|   | 1a1eecb4c3 | ||
|   | 07c907b315 | ||
|   | d343d38037 | ||
|   | 7e89c13839 | ||
|   | 2a032bf66d | ||
|   | e0727e8485 | ||
|   | d5d7ac90ac | ||
|   | 3e5fa30d9d | ||
|   | 73241efdc8 | ||
|   | cc470f671a | 
							
								
								
									
										298
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										298
									
								
								CONTRIBUTING.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,298 @@ | ||||
| # Contributing to Open MCT Web | ||||
|  | ||||
| This document describes the process of contributing to Open MCT Web as well | ||||
| as the standards that will be applied when evaluating contributions. | ||||
|  | ||||
| Please be aware that additional agreements will be necessary before we can | ||||
| accept changes from external contributors. | ||||
|  | ||||
| ## Summary | ||||
|  | ||||
| The short version: | ||||
|  | ||||
| 1. Write your contribution. | ||||
| 2. Make sure your contribution meets code, test, and commit message | ||||
|    standards as described below. | ||||
| 3. Submit a pull request from a topic branch back to `master`. Include a check | ||||
|    list, as described below. (Optionally, assign this to a specific member | ||||
|    for review.) | ||||
| 4. Respond to any discussion. When the reviewer decides it's ready, they | ||||
|    will merge back `master` and fill out their own check list. | ||||
|  | ||||
| ## Contribution Process | ||||
|  | ||||
| Open MCT Web uses git for software version control, and for branching and | ||||
| merging. The central repository is at | ||||
| https://github.com/nasa/openmctweb.git. | ||||
|  | ||||
| ### Roles | ||||
|  | ||||
| References to roles are made throughout this document. These are not intended | ||||
| to reflect titles or long-term job assignments; rather, these are used as | ||||
| descriptors to refer to members of the development team performing tasks in | ||||
| the check-in process. These roles are: | ||||
|  | ||||
| * _Author_: The individual who has made changes to files in the software | ||||
|   repository, and wishes to check these in. | ||||
| * _Reviewer_: The individual who reviews changes to files before they are | ||||
|   checked in. | ||||
| * _Integrator_: The individual who performs the task of merging these files. | ||||
|   Usually the reviewer. | ||||
|  | ||||
| ### Branching | ||||
|  | ||||
| Three basic types of branches may be included in the above repository: | ||||
|  | ||||
| 1. Master branch. | ||||
| 2. Topic branches. | ||||
| 3. Developer branches. | ||||
|  | ||||
| Branches which do not fit into the above categories may be created and used | ||||
| during the course of development for various reasons, such as large-scale | ||||
| refactoring of code or implementation of complex features which may cause | ||||
| instability. In these exceptional cases it is the responsibility of the | ||||
| developer who initiates the task which motivated this branching to | ||||
| communicate to the team the role of these branches and any associated | ||||
| procedures for the duration of their use. | ||||
|  | ||||
| #### Master Branch | ||||
|  | ||||
| The role of the `master` branches is to represent the latest | ||||
| "ready for test" version of the software. Source code on the master | ||||
| branch has undergone peer review, and will undergo regular automated | ||||
| testing with notification on failure. Master branches may be unstable | ||||
| (particularly for recent features), but the intent is for the stability of | ||||
| any features on master branches to be non-decreasing. It is the shared | ||||
| responsibility of authors, reviewers, and integrators to ensure this. | ||||
|  | ||||
| #### Topic Branches | ||||
|  | ||||
| Topic branches are used by developers to perform and record work on issues. | ||||
|  | ||||
| Topic branches need not necessarily be stable, even when pushed to the | ||||
| central repository; in fact, the practice of making incremental commits | ||||
| while working on an issue and pushing these to the central repository is | ||||
| encouraged, to avoid lost work and to share work-in-progress. (Small commits | ||||
| also help isolate changes, which can help in identifying which change | ||||
| introduced a defect, particularly when that defect went unnoticed for some | ||||
| time, e.g. using `git bisect`.) | ||||
|  | ||||
| Topic branches should be named according to their corresponding issue | ||||
| identifiers, all lower case, without hyphens. (e.g. branch mct9 would refer | ||||
| to issue #9.) | ||||
|  | ||||
| In some cases, work on an issue may warrant the use of multiple divergent | ||||
| branches; for instance, when a developer wants to try more than one solution | ||||
| and compare them, or when a "dead end" is reached and an initial approach to | ||||
| resolving an issue needs to be abandoned. In these cases, a short suffix | ||||
| should be added to the additional branches; this may be simply a single | ||||
| character (e.g. wtd481b) or, where useful, a descriptive term for what | ||||
| distinguishes the branches (e.g. wtd481verbose). It is the responsibility of | ||||
| the author to communicate which branch is intended to be merged to both the | ||||
| reviewer and the integrator. | ||||
|  | ||||
| #### Developer Branches | ||||
|  | ||||
| Developer branches are any branches used for purposes outside of the scope | ||||
| of the above; e.g. to try things out, or maintain a "my latest stuff" | ||||
| branch that is not delayed by the review and integration process. These | ||||
| may be pushed to the central repository, and may follow any naming convention | ||||
| desired so long as the owner of the branch is identifiable, and so long as | ||||
| the name chosen could not be mistaken for a topic or master branch. | ||||
|  | ||||
| ### Merging | ||||
|  | ||||
| When development is complete on an issue, the first step toward merging it | ||||
| back into the master branch is to file a Pull Request. The contributions | ||||
| should meet code, test, and commit message standards as described below, | ||||
| and the pull request should include a completed author checklist, also | ||||
| as described below. Pull requests may be assigned to specific team | ||||
| members when appropriate (e.g. to draw to a specific person's attention.) | ||||
|  | ||||
| Code review should take place using discussion features within the pull | ||||
| request. When the reviewer is satisfied, they should add a comment to | ||||
| the pull request containing the reviewer checklist (from below) and complete | ||||
| the merge back to the master branch. | ||||
|  | ||||
| ## Standards | ||||
|  | ||||
| Contributions to Open MCT Web are expected to meet the following standards. | ||||
| In addition, reviewers should use general discretion before accepting | ||||
| changes. | ||||
|  | ||||
| ### Code Standards | ||||
|  | ||||
| JavaScript sources in Open MCT Web must satisfy JSLint under its default | ||||
| settings. This is verified by the command line build. | ||||
|  | ||||
| #### Code Guidelines | ||||
|  | ||||
| JavaScript sources in Open MCT Web should: | ||||
|  | ||||
| * Use four spaces for indentation. Tabs should not be used. | ||||
| * Include JSDoc for any exposed API (e.g. public methods, constructors.) | ||||
| * Include non-JSDoc comments as-needed for explaining private variables, | ||||
|   methods, or algorithms when they are non-obvious. | ||||
| * Define one public class per script, expressed as a constructor function | ||||
|   returned from an AMD-style module. | ||||
| * Follow “Java-like” naming conventions. These includes: | ||||
|   * Classes should use camel case, first letter capitalized | ||||
|     (e.g. SomeClassName.) | ||||
|   * Methods, variables, fields, and function names should use camel case, | ||||
|     first letter lower-case (e.g. someVariableName.) Constants | ||||
|     (variables or fields which are meant to be declared and initialized | ||||
|     statically, and never changed) should use only capital letters, with | ||||
|     underscores between words (e.g. SOME_CONSTANT.) | ||||
|   * File name should be the name of the exported class, plus a .js extension | ||||
|     (e.g. SomeClassName.js) | ||||
| * Avoid anonymous functions, except when functions are short (a few lines) | ||||
|   and/or their inclusion makes sense within the flow of the code | ||||
|   (e.g. as arguments to a forEach call.) | ||||
| * Avoid deep nesting (especially of functions), except where necessary | ||||
|   (e.g. due to closure scope.) | ||||
| * End with a single new-line character. | ||||
| * Expose public methods by declaring them on the class's prototype. | ||||
| * Within a given function's scope, do not mix declarations and imperative | ||||
|   code, and  present these in the following order: | ||||
|   * First, variable declarations and initialization. | ||||
|   * Second, function declarations. | ||||
|   * Third, imperative statements. | ||||
|   * Finally, the returned value. | ||||
|  | ||||
| Deviations from Open MCT Web code style guidelines require two-party agreement, | ||||
| typically from the author of the change and its reviewer. | ||||
|  | ||||
| #### Code Example | ||||
|  | ||||
| ```js | ||||
| /*global define*/ | ||||
|  | ||||
| /** | ||||
|  * Bundles should declare themselves as namespaces in whichever source | ||||
|  * file is most like the "main point of entry" to the bundle. | ||||
|  * @namespace some/bundle | ||||
|  */ | ||||
| define( | ||||
|     ['./OtherClass'], | ||||
|     function (OtherClass) { | ||||
|         "use strict"; | ||||
|  | ||||
|         /** | ||||
|          * A summary of how to use this class goes here. | ||||
|          * | ||||
|          * @constructor | ||||
|          * @memberof some/bundle | ||||
|          */ | ||||
|         function ExampleClass() { | ||||
|         } | ||||
|  | ||||
|         // Methods which are not intended for external use should | ||||
|         // not have JSDoc (or should be marked @private) | ||||
|         ExampleClass.prototype.privateMethod = function () { | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * A summary of this method goes here. | ||||
|          * @param {number} n a parameter | ||||
|          * @returns {number} a return value | ||||
|          */ | ||||
|         ExampleClass.prototype.publicMethod = function (n) { | ||||
|             return n * 2; | ||||
|         } | ||||
|  | ||||
|         return ExampleClass; | ||||
|     } | ||||
| ); | ||||
| ``` | ||||
|  | ||||
| ### Test Standards | ||||
|  | ||||
| Automated testing shall occur whenever changes are merged into the main | ||||
| development branch and must be confirmed alongside any pull request. | ||||
|  | ||||
| Automated tests are typically unit tests which exercise individual software | ||||
| components. Tests are subject to code review along with the actual | ||||
| implementation, to ensure that tests are applicable and useful. | ||||
|  | ||||
| Examples of useful tests: | ||||
| * Tests which replicate bugs (or their root causes) to verify their | ||||
|   resolution. | ||||
| * Tests which reflect details from software specifications. | ||||
| * Tests which exercise edge or corner cases among inputs. | ||||
| * Tests which verify expected interactions with other components in the | ||||
|   system. | ||||
|  | ||||
| During automated testing, code coverage metrics will be reported. Line | ||||
| coverage must remain at or above 80%. | ||||
|  | ||||
| ### Commit Message Standards | ||||
|  | ||||
| Commit messages should: | ||||
|  | ||||
| * Contain a one-line subject, followed by one line of white space, | ||||
|   followed by one or more descriptive paragraphs, each separated by one | ||||
|   line of white space. | ||||
| * Contain a short (usually one word) reference to the feature or subsystem | ||||
|   the commit effects, in square brackets, at the start of the subject line | ||||
|   (e.g. `[Documentation] Draft of check-in process`) | ||||
| * Contain a reference to a relevant issue number in the body of the commit. | ||||
|   * This is important for traceability; while branch names also provide this, | ||||
|     you cannot tell from looking at a commit what branch it was authored on. | ||||
| * Describe the change that was made, and any useful rationale therefore. | ||||
|   * Comments in code should explain what things do, commit messages describe | ||||
|     how they came to be done that way. | ||||
| * Provide sufficient information for a reviewer to understand the changes | ||||
|   made and their relationship to previous code. | ||||
|  | ||||
| Commit messages should not: | ||||
|  | ||||
| * Exceed 54 characters in length on the subject line. | ||||
| * Exceed 72 characters in length in the body of the commit. | ||||
|   * Except where necessary to maintain the structure of machine-readable or | ||||
|     machine-generated text (e.g. error messages) | ||||
|  | ||||
| See [Contributing to a Project](http://git-scm.com/book/ch5-2.html) from | ||||
| Pro Git by Shawn Chacon and Ben Straub for a bit of the rationale behind | ||||
| these standards. | ||||
|  | ||||
| ## Issue Reporting | ||||
|  | ||||
| Issues are tracked at https://github.com/nasa/openmctweb/issues | ||||
|  | ||||
| Issues should include: | ||||
|  | ||||
| * A short description of the issue encountered. | ||||
| * A longer-form description of the issue encountered. When possible, steps to | ||||
|   reproduce the issue. | ||||
| * When possible, a description of the impact of the issue. What use case does | ||||
|   it impede? | ||||
| * An assessment of the severity of the issue. | ||||
|  | ||||
| Issue severity is categorized as follows (in ascending order): | ||||
|  | ||||
| * _Trivial_: Minimal impact on the usefulness and functionality of the | ||||
|   software; a "nice-to-have." | ||||
| * _(Unspecified)_: Major loss of functionality or impairment of use. | ||||
| * _Critical_: Large-scale loss of functionality or impairment of use, | ||||
|   such that remaining utility becomes marginal. | ||||
| * _Blocker_: Harmful or otherwise unacceptable behavior. Must fix. | ||||
|  | ||||
| ## Check Lists | ||||
|  | ||||
| The following check lists should be completed and attached to pull requests | ||||
| when they are filed (author checklist) and when they are merged (reviewer | ||||
| checklist.) | ||||
|  | ||||
| ### Author Checklist | ||||
|  | ||||
| 1. Changes address original issue? | ||||
| 2. Unit tests included and/or updated with changes? | ||||
| 3. Command line build passes? | ||||
| 4. Expect to pass code review? | ||||
|  | ||||
| ### Reviewer Checklist | ||||
|  | ||||
| 1. Changes appear to address issue? | ||||
| 2. Appropriate unit tests included? | ||||
| 3. Code style and in-line documentation are appropriate? | ||||
| 4. Commit messages meet standards? | ||||
							
								
								
									
										10
									
								
								jsdoc.json
									
									
									
									
									
								
							
							
						
						
									
										10
									
								
								jsdoc.json
									
									
									
									
									
								
							| @@ -1,10 +1,12 @@ | ||||
| { | ||||
|     "source": { | ||||
|         "include": [ | ||||
|             "example/", | ||||
|             "platform/" | ||||
|         ], | ||||
|         "includePattern": "(example|platform)/.+\\.js$", | ||||
|         "includePattern": "platform/.+\\.js$", | ||||
|         "excludePattern": ".+\\Spec\\.js$|lib/.+" | ||||
|     } | ||||
| } | ||||
|     }, | ||||
|     "plugins": [ | ||||
|         "plugins/markdown" | ||||
|     ] | ||||
| } | ||||
|   | ||||
| @@ -28,6 +28,7 @@ | ||||
|     "start": "node app.js", | ||||
|     "test": "karma start --single-run", | ||||
|     "jshint": "jshint platform example || exit 0", | ||||
|     "watch": "karma start", | ||||
|     "jsdoc": "jsdoc -c jsdoc.json -r -d target/docs/api", | ||||
|     "otherdoc": "node docs/gendocs.js --in docs/src --out target/docs", | ||||
|     "docs": "npm run jsdoc ; npm run otherdoc" | ||||
|   | ||||
| @@ -21,6 +21,11 @@ | ||||
|  *****************************************************************************/ | ||||
| /*global define*/ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Implements Open MCT Web's About dialog. | ||||
|  * @namespace platform/commonUI/about | ||||
|  */ | ||||
| define( | ||||
|     [], | ||||
|     function () { | ||||
| @@ -29,35 +34,36 @@ define( | ||||
|         /** | ||||
|          * The AboutController provides information to populate the | ||||
|          * About dialog. | ||||
|          * @memberof platform/commonUI/about | ||||
|          * @constructor | ||||
|          * @param {object[]} versions an array of version extensions; | ||||
|          *        injected from `versions[]` | ||||
|          * @param $window Angular-injected window object | ||||
|          */ | ||||
|         function AboutController(versions, $window) { | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get version info. This is given as an array of | ||||
|                  * objects, where each object is intended to appear | ||||
|                  * as a line-item in the version information listing. | ||||
|                  * @memberof AboutController# | ||||
|                  * @returns {object[]} version information | ||||
|                  */ | ||||
|                 versions: function () { | ||||
|                     return versions; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Open a new window (or tab, depending on browser | ||||
|                  * configuration) containing open source licenses. | ||||
|                  * @memberof AboutController# | ||||
|                  */ | ||||
|                 openLicenses: function () { | ||||
|                     // Open a new browser window at the licenses route | ||||
|                     $window.open("#/licenses"); | ||||
|                 } | ||||
|             }; | ||||
|             this.versionDefinitions = versions; | ||||
|             this.$window = $window; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get version info. This is given as an array of | ||||
|          * objects, where each object is intended to appear | ||||
|          * as a line-item in the version information listing. | ||||
|          * @returns {object[]} version information | ||||
|          */ | ||||
|         AboutController.prototype.versions = function () { | ||||
|             return this.versionDefinitions; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Open a new window (or tab, depending on browser | ||||
|          * configuration) containing open source licenses. | ||||
|          */ | ||||
|         AboutController.prototype.openLicenses = function () { | ||||
|             // Open a new browser window at the licenses route | ||||
|             this.$window.open("#/licenses"); | ||||
|         }; | ||||
|  | ||||
|         return AboutController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -29,20 +29,22 @@ define( | ||||
|         /** | ||||
|          * Provides extension-introduced licenses information to the | ||||
|          * licenses route. | ||||
|          * @memberof platform/commonUI/about | ||||
|          * @constructor | ||||
|          */ | ||||
|         function LicenseController(licenses) { | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get license information. | ||||
|                  * @returns {Array} license extensions | ||||
|                  */ | ||||
|                 licenses: function () { | ||||
|                     return licenses; | ||||
|                 } | ||||
|             }; | ||||
|             this.licenseDefinitions = licenses; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get license information. | ||||
|          * @returns {Array} license extensions | ||||
|          * @memberof platform/commonUI/about.LicenseController# | ||||
|          */ | ||||
|         LicenseController.prototype.licenses = function () { | ||||
|             return this.licenseDefinitions; | ||||
|         }; | ||||
|  | ||||
|         return LicenseController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -29,21 +29,23 @@ define( | ||||
|         /** | ||||
|          * The LogoController provides functionality to the application | ||||
|          * logo in the bottom-right of the user interface. | ||||
|          * @memberof platform/commonUI/about | ||||
|          * @constructor | ||||
|          * @param {OverlayService} overlayService the overlay service | ||||
|          */ | ||||
|         function LogoController(overlayService) { | ||||
|             return { | ||||
|                 /** | ||||
|                  * Display the About dialog. | ||||
|                  * @memberof LogoController# | ||||
|                  */ | ||||
|                 showAboutDialog: function () { | ||||
|                     overlayService.createOverlay("overlay-about"); | ||||
|                 } | ||||
|             }; | ||||
|             this.overlayService = overlayService; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Display the About dialog. | ||||
|          * @memberof LogoController# | ||||
|          * @memberof platform/commonUI/about.LogoController# | ||||
|          */ | ||||
|         LogoController.prototype.showAboutDialog = function () { | ||||
|             this.overlayService.createOverlay("overlay-about"); | ||||
|         }; | ||||
|  | ||||
|         return LogoController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -21,7 +21,7 @@ | ||||
|             { | ||||
|                 "key": "BrowseObjectController", | ||||
|                 "implementation": "BrowseObjectController.js", | ||||
|                 "depends": [ "$scope", "$location", "$route" ] | ||||
|                 "depends": [ "$scope", "$location", "$route", "$window" ] | ||||
|             }, | ||||
|             { | ||||
|                 "key": "CreateMenuController", | ||||
| @@ -69,8 +69,8 @@ | ||||
|             { | ||||
|                 "key": "grid-item", | ||||
|                 "templateUrl": "templates/items/grid-item.html", | ||||
|                 "uses": [ "type", "action" ], | ||||
|                 "gestures": [ "info","menu" ] | ||||
|                 "uses": [ "type", "action", "location" ], | ||||
|                 "gestures": [ "info", "menu" ] | ||||
|             }, | ||||
|             { | ||||
|                 "key": "object-header", | ||||
| @@ -88,12 +88,12 @@ | ||||
|             { | ||||
|                 "key": "navigationService", | ||||
|                 "implementation": "navigation/NavigationService.js" | ||||
|             },         | ||||
|             }, | ||||
|             { | ||||
|                 "key": "creationService", | ||||
|                 "implementation": "creation/CreationService.js", | ||||
|                 "depends": [ "persistenceService", "$q", "$log" ] | ||||
|             }         | ||||
|             } | ||||
|         ], | ||||
|         "actions": [ | ||||
|             { | ||||
|   | ||||
| @@ -20,7 +20,15 @@ | ||||
|  at runtime from the About dialog for additional information. | ||||
| --> | ||||
| <span ng-controller="BrowseObjectController"> | ||||
|     <div class="object-browse-bar bar abs"> | ||||
|      | ||||
|     <div class="object-browse-bar bar abs" | ||||
|          ng-click="ngModel.inspectionObjects = [domainObject]"> | ||||
|          | ||||
|         <div class="pane-tabs left" | ||||
|              ng-class="{inactivePane: !ngModel.leftPane, activePane: ngModel.leftPane}" | ||||
|              ng-click="ngModel.leftPane = !ngModel.leftPane"> | ||||
|         </div> | ||||
|          | ||||
|         <div class="items-select left abs"> | ||||
|             <mct-representation key="'object-header'" mct-object="domainObject"> | ||||
|             </mct-representation> | ||||
| @@ -37,11 +45,19 @@ | ||||
|                                 ng-model="representation"> | ||||
|             </mct-representation> | ||||
|         </div> | ||||
|          | ||||
|         <div class="pane-tabs right" | ||||
|              ng-class="{inactivePane: !ngModel.rightPane, activePane: ngModel.rightPane}" | ||||
|              ng-click="ngModel.rightPane = !ngModel.rightPane"> | ||||
|         </div> | ||||
|          | ||||
|     </div> | ||||
|  | ||||
|     <div class='object-holder abs vscroll'> | ||||
|         <mct-representation key="representation.selected.key" | ||||
|                             mct-object="representation.selected.key && domainObject"> | ||||
|                             mct-object="representation.selected.key && domainObject" | ||||
|                             ng-model="ngModel"> | ||||
|         </mct-representation> | ||||
|     </div> | ||||
|      | ||||
| </span> | ||||
|   | ||||
| @@ -19,30 +19,84 @@ | ||||
|  this source code distribution or the Licensing information page available | ||||
|  at runtime from the About dialog for additional information. | ||||
| --> | ||||
| <div content="jquery-wrapper" class="abs holder-all browse-mode"> | ||||
|     <mct-include key="'topbar-browse'"></mct-include> | ||||
|     <div class="holder browse-area s-browse-area abs" ng-controller="BrowseController"> | ||||
|         <mct-split-pane class='contents abs' anchor='left'> | ||||
|             <div | ||||
|                 class='split-pane-component treeview pane left' | ||||
|                 > | ||||
|                 <mct-representation key="'create-button'" mct-object="navigatedObject"> | ||||
|  | ||||
| <div content="jquery-wrapper" | ||||
|      class="abs holder-all browse-mode"> | ||||
|      | ||||
|     <mct-include key="'topbar-browse'"> | ||||
|     </mct-include> | ||||
|      | ||||
|     <div class="holder browse-area s-browse-area abs" | ||||
|          ng-controller="BrowseController"> | ||||
|          | ||||
|         <mct-split-pane class='contents abs' | ||||
|                         anchor='left'> | ||||
|             <div class='split-pane-component treeview pane left' | ||||
|                  ng-class='{inactive: !treeModel.leftPane}'> | ||||
|                  | ||||
|                 <mct-representation key="'create-button'" | ||||
|                                     mct-object="navigatedObject" | ||||
|                                     ng-model="treeModel"> | ||||
|                 </mct-representation> | ||||
|                 <div class='holder tree-holder abs'> | ||||
|                  | ||||
|                 <div class='holder search-holder abs' | ||||
|                      ng-class="{active: treeModel.search}"> | ||||
|                     <mct-representation key="'search'" | ||||
|                                  mct-object="domainObject" | ||||
|                                  ng-model="treeModel"> | ||||
|                     </mct-representation> | ||||
|                 </div> | ||||
|                  | ||||
|                 <div class='holder tree-holder abs' | ||||
|                      ng-hide="treeModel.search"> | ||||
|                     <mct-representation key="'tree'" | ||||
|                                         mct-object="domainObject" | ||||
|                                         ng-model="treeModel"> | ||||
|                     </mct-representation> | ||||
|                 </div> | ||||
|             </div> | ||||
|             <mct-splitter></mct-splitter> | ||||
|             <div class='split-pane-component items pane'> | ||||
|                 <div class='holder abs' id='content-area'> | ||||
|                     <mct-representation mct-object="navigatedObject" key="'browse-object'"> | ||||
|                     </mct-representation> | ||||
|                 </div> | ||||
|              | ||||
|             <mct-splitter class="splitter-bar left" | ||||
|                           ng-class="{inactive: !treeModel.leftPane}"> | ||||
|             </mct-splitter> | ||||
|              | ||||
|             <div class='split-pane-component secondary-split pane right slide' | ||||
|                  ng-class='{leftInactive: !treeModel.leftPane}'> | ||||
|                 <mct-split-pane class='contents abs' | ||||
|                                 anchor='right'> | ||||
|                      | ||||
|                     <div class='split-pane-component items pane slide' | ||||
|                          ng-class='{rightInactive: !treeModel.rightPane}'> | ||||
|                         <div class='holder abs' | ||||
|                              id='content-area'> | ||||
|                             <mct-representation key="'browse-object'" | ||||
|                                                 mct-object="navigatedObject" | ||||
|                                                 ng-model="treeModel"> | ||||
|                             </mct-representation> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                      | ||||
|                     <mct-splitter class="splitter-bar right" | ||||
|                                   ng-class="{inactive: !treeModel.rightPane}"> | ||||
|                     </mct-splitter> | ||||
|                      | ||||
|                     <div class='split-pane-component object-inspector pane right' | ||||
|                          ng-class='{inactive: !treeModel.rightPane}'> | ||||
|                         <div class='holder inspector-holder abs'> | ||||
|                             <mct-representation key="'object-inspector'" | ||||
|                                                 mct-object="domainObject" | ||||
|                                                 ng-model="treeModel"> | ||||
|                             </mct-representation> | ||||
|                         </div> | ||||
|                     </div> | ||||
|                      | ||||
|                 </mct-split-pane> | ||||
|             </div> | ||||
|              | ||||
|         </mct-split-pane> | ||||
|          | ||||
|     </div> | ||||
|     <mct-include key="'bottombar'"></mct-include> | ||||
|      | ||||
|     <mct-include key="'bottombar'"> | ||||
|     </mct-include> | ||||
| </div> | ||||
|   | ||||
| @@ -20,8 +20,10 @@ | ||||
|  at runtime from the About dialog for additional information. | ||||
| --> | ||||
| <div class="menu-element wrapper" ng-controller="ClickAwayController as createController"> | ||||
|     <div class="btn btn-menu create-btn major" ng-click="createController.toggle()"> | ||||
| 	    Create | ||||
|     <div class="btn btn-menu create-btn major" | ||||
|          ng-class="{inactivePane: !ngModel.leftPane}" | ||||
|          ng-click="createController.toggle()"> | ||||
| 	    <span>Create</span> | ||||
|     </div> | ||||
|     <div class="menu dropdown super-menu" ng-show="createController.isActive()"> | ||||
|         <mct-representation mct-object="domainObject" key="'create-menu'"> | ||||
|   | ||||
| @@ -27,12 +27,18 @@ | ||||
|                 <mct-include key="_checkbox"></mct-include> | ||||
|             </div> | ||||
|             <div class='right abs'> | ||||
|                 <div class='ui-symbol icon alert hidden' onclick="alert('Not yet functional. When this is visible, it means that this object needs to be updated. Clicking will allow that action via a dialog.');">!</div> | ||||
|                 <div class='ui-symbol icon l-icon-alert'></div> | ||||
|                 <div class='ui-symbol icon profile' title="Shared">P</div> | ||||
|             </div> | ||||
|         </div> | ||||
|         <div class='item-main abs'> | ||||
|             <div class='ui-symbol icon lg abs item-type'>{{type.getGlyph()}}</div> | ||||
|             <div class='ui-symbol icon lg item-type'> | ||||
|                 {{type.getGlyph()}} | ||||
|                 <span | ||||
|                     class="ui-symbol icon l-icon-link" title="This object is a link" | ||||
|                     ng-show="location.isLink()" | ||||
|                     ></span> | ||||
|             </div> | ||||
|             <div class='ui-symbol icon abs item-open'>}</div> | ||||
|         </div> | ||||
|         <div class='bottom-bar bar abs'> | ||||
| @@ -44,4 +50,4 @@ | ||||
|             </div> | ||||
|         </div> | ||||
|     </div> | ||||
| </div> | ||||
| </div> | ||||
|   | ||||
| @@ -22,7 +22,8 @@ | ||||
| /*global define,Promise*/ | ||||
|  | ||||
| /** | ||||
|  * Module defining BrowseController. Created by vwoeltje on 11/7/14. | ||||
|  * This bundle implements Browse mode. | ||||
|  * @namespace platform/commonUI/browse | ||||
|  */ | ||||
| define( | ||||
|     [], | ||||
| @@ -39,6 +40,7 @@ define( | ||||
|          * which Angular templates first have access to the domain object | ||||
|          * hierarchy. | ||||
|          * | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          */ | ||||
|         function BrowseController($scope, $route, $location, objectService, navigationService, urlService) { | ||||
| @@ -137,10 +139,14 @@ define( | ||||
|             }); | ||||
|  | ||||
|             // Provide a model for the tree to modify | ||||
|             // Also use this model for the left and right pane controlling | ||||
|             $scope.treeModel = { | ||||
|                 selectedObject: navigationService.getNavigation() | ||||
|             }; | ||||
|  | ||||
|             // Create an array of objects which will allow for multiple selection | ||||
|             // for the object inspector.  | ||||
|             $scope.inspectionObjects = [$scope.domainObject]; | ||||
|              | ||||
|             // Listen for changes in navigation state. | ||||
|             navigationService.addListener(setNavigation); | ||||
|  | ||||
| @@ -151,9 +157,9 @@ define( | ||||
|             $scope.$on("$destroy", function () { | ||||
|                 navigationService.removeListener(setNavigation); | ||||
|             }); | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return BrowseController; | ||||
|     } | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -29,12 +29,16 @@ define( | ||||
|         /** | ||||
|          * Controller for the `browse-object` representation of a domain | ||||
|          * object (the right-hand side of Browse mode.) | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          */ | ||||
|         function BrowseObjectController($scope, $location, $route) { | ||||
|         function BrowseObjectController($scope, $location, $route, $window) { | ||||
|             function setViewForDomainObject(domainObject) { | ||||
|                 var locationViewKey = $location.search().view; | ||||
|  | ||||
|                  | ||||
|                 // Reset the inspection objects when we switch the view  | ||||
|                 $scope.ngModel.inspectionObjects = [$scope.domainObject]; | ||||
|                  | ||||
|                 function selectViewIfMatching(view) { | ||||
|                     if (view.key === locationViewKey) { | ||||
|                         $scope.representation = $scope.representation || {}; | ||||
| @@ -64,6 +68,19 @@ define( | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // If there is a defined opener, assume that the window was opened  | ||||
|             //   by choosing 'Open in a new tab' | ||||
|             if ($window.opener) { | ||||
|                 // The desired default for this is to have a closed left pane | ||||
|                 $scope.ngModel.leftPane = false; | ||||
|             } else { | ||||
|                 // Otherwise, start the application with an open left pane  | ||||
|                 $scope.ngModel.leftPane = true; | ||||
|             } | ||||
|              | ||||
|             // The object inspector by default always starts closed | ||||
|             $scope.ngModel.rightPane = false; | ||||
|              | ||||
|             $scope.$watch('domainObject', setViewForDomainObject); | ||||
|             $scope.$watch('representation.selected.key', updateQueryParam); | ||||
|         } | ||||
| @@ -71,3 +88,4 @@ define( | ||||
|         return BrowseObjectController; | ||||
|     } | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -33,19 +33,29 @@ define( | ||||
|          * A left-click on the menu arrow should display a  | ||||
|          * context menu. This controller launches the context  | ||||
|          * menu.  | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          */ | ||||
|         function MenuArrowController($scope) { | ||||
|             function showMenu(event) { | ||||
|                 var actionContext = {key: 'menu', domainObject: $scope.domainObject, event: event}; | ||||
|                 $scope.domainObject.getCapability('action').perform(actionContext); | ||||
|             } | ||||
|              | ||||
|             return { | ||||
|                 showMenu: showMenu | ||||
|             }; | ||||
|             this.$scope = $scope; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Show a context menu for the domain object in this scope. | ||||
|          * | ||||
|          * @param event the browser event which caused this (used to | ||||
|          *        position the menu) | ||||
|          */ | ||||
|         MenuArrowController.prototype.showMenu = function (event) { | ||||
|             var actionContext = { | ||||
|                 key: 'menu', | ||||
|                 domainObject: this.$scope.domainObject, | ||||
|                 event: event | ||||
|             }; | ||||
|  | ||||
|             this.$scope.domainObject.getCapability('action').perform(actionContext); | ||||
|         }; | ||||
|  | ||||
|         return MenuArrowController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -34,7 +34,10 @@ define( | ||||
|          * domain objects of a specific type. This is the action that | ||||
|          * is performed when a user uses the Create menu. | ||||
|          * | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @implements {Action} | ||||
|          * @constructor | ||||
|          * | ||||
|          * @param {Type} type the type of domain object to create | ||||
|          * @param {DomainObject} parent the domain object that should | ||||
|          *        act as a container for the newly-created object | ||||
| @@ -49,78 +52,84 @@ define( | ||||
|          *        of the newly-created domain object | ||||
|          */ | ||||
|         function CreateAction(type, parent, context, dialogService, creationService, policyService) { | ||||
|             this.metadata = { | ||||
|                 key: 'create', | ||||
|                 glyph: type.getGlyph(), | ||||
|                 name: type.getName(), | ||||
|                 type: type.getKey(), | ||||
|                 description: type.getDescription(), | ||||
|                 context: context | ||||
|             }; | ||||
|  | ||||
|             this.type = type; | ||||
|             this.parent = parent; | ||||
|             this.policyService = policyService; | ||||
|             this.dialogService = dialogService; | ||||
|             this.creationService = creationService; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Create a new object of the given type. | ||||
|          * This will prompt for user input first. | ||||
|          */ | ||||
|         CreateAction.prototype.perform = function () { | ||||
|             /* | ||||
|              Overview of steps in object creation: | ||||
|  | ||||
|              1. Show dialog | ||||
|                a. Prepare dialog contents | ||||
|                b. Invoke dialogService | ||||
|              a. Prepare dialog contents | ||||
|              b. Invoke dialogService | ||||
|              2. Create new object in persistence service | ||||
|                a. Generate UUID | ||||
|                b. Store model | ||||
|              a. Generate UUID | ||||
|              b. Store model | ||||
|              3. Mutate destination container | ||||
|                a. Get mutation capability | ||||
|                b. Add new id to composition | ||||
|              a. Get mutation capability | ||||
|              b. Add new id to composition | ||||
|              4. Persist destination container | ||||
|                a. ...use persistence capability. | ||||
|              a. ...use persistence capability. | ||||
|              */ | ||||
|  | ||||
|             function perform() { | ||||
|                 // The wizard will handle creating the form model based | ||||
|                 // on the type... | ||||
|                 var wizard = new CreateWizard(type, parent, policyService); | ||||
|             // The wizard will handle creating the form model based | ||||
|             // on the type... | ||||
|             var wizard = | ||||
|                 new CreateWizard(this.type, this.parent, this.policyService), | ||||
|                 self = this; | ||||
|  | ||||
|                 // Create and persist the new object, based on user | ||||
|                 // input. | ||||
|                 function persistResult(formValue) { | ||||
|                     var parent = wizard.getLocation(formValue), | ||||
|                         newModel = wizard.createModel(formValue); | ||||
|                     return creationService.createObject(newModel, parent); | ||||
|                 } | ||||
|  | ||||
|                 function doNothing() { | ||||
|                     // Create cancelled, do nothing | ||||
|                     return false; | ||||
|                 } | ||||
|  | ||||
|                 return dialogService.getUserInput( | ||||
|                     wizard.getFormStructure(), | ||||
|                     wizard.getInitialFormValue() | ||||
|                 ).then(persistResult, doNothing); | ||||
|             // Create and persist the new object, based on user | ||||
|             // input. | ||||
|             function persistResult(formValue) { | ||||
|                 var parent = wizard.getLocation(formValue), | ||||
|                     newModel = wizard.createModel(formValue); | ||||
|                 return self.creationService.createObject(newModel, parent); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Create a new object of the given type. | ||||
|                  * This will prompt for user input first. | ||||
|                  * @method | ||||
|                  * @memberof CreateAction | ||||
|                  */ | ||||
|                 perform: perform, | ||||
|             function doNothing() { | ||||
|                 // Create cancelled, do nothing | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|                 /** | ||||
|                  * Get metadata about this action. This includes fields: | ||||
|                  * * `name`: Human-readable name | ||||
|                  * * `key`: Machine-readable identifier ("create") | ||||
|                  * * `glyph`: Glyph to use as an icon for this action | ||||
|                  * * `description`: Human-readable description | ||||
|                  * * `context`: The context in which this action will be performed. | ||||
|                  * | ||||
|                  * @return {object} metadata about the create action | ||||
|                  */ | ||||
|                 getMetadata: function () { | ||||
|                     return { | ||||
|                         key: 'create', | ||||
|                         glyph: type.getGlyph(), | ||||
|                         name: type.getName(), | ||||
|                         type: type.getKey(), | ||||
|                         description: type.getDescription(), | ||||
|                         context: context | ||||
|                     }; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|             return this.dialogService.getUserInput( | ||||
|                 wizard.getFormStructure(), | ||||
|                 wizard.getInitialFormValue() | ||||
|             ).then(persistResult, doNothing); | ||||
|         }; | ||||
|  | ||||
|  | ||||
|         /** | ||||
|          * Metadata associated with a Create action. | ||||
|          * @typedef {ActionMetadata} CreateActionMetadata | ||||
|          * @property {string} type the key for the type of domain object | ||||
|          *           to be created | ||||
|          */ | ||||
|  | ||||
|         /** | ||||
|          * Get metadata about this action. | ||||
|          * @returns {CreateActionMetadata} metadata about this action | ||||
|          */ | ||||
|         CreateAction.prototype.getMetadata = function () { | ||||
|            return this.metadata; | ||||
|         }; | ||||
|  | ||||
|         return CreateAction; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -33,7 +33,10 @@ define( | ||||
|          * The CreateActionProvider is an ActionProvider which introduces | ||||
|          * a Create action for each creatable domain object type. | ||||
|          * | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          * @implements {ActionService} | ||||
|          * | ||||
|          * @param {TypeService} typeService the type service, used to discover | ||||
|          *        available types | ||||
|          * @param {DialogService} dialogService the dialog service, used by | ||||
| @@ -44,44 +47,41 @@ define( | ||||
|          *        object creation. | ||||
|          */ | ||||
|         function CreateActionProvider(typeService, dialogService, creationService, policyService) { | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get all Create actions which are applicable in the provided | ||||
|                  * context. | ||||
|                  * @memberof CreateActionProvider | ||||
|                  * @method | ||||
|                  * @returns {CreateAction[]} | ||||
|                  */ | ||||
|                 getActions: function (actionContext) { | ||||
|                     var context = actionContext || {}, | ||||
|                         key = context.key, | ||||
|                         destination = context.domainObject; | ||||
|  | ||||
|                     // We only provide Create actions, and we need a | ||||
|                     // domain object to serve as the container for the | ||||
|                     // newly-created object (although the user may later | ||||
|                     // make a different selection) | ||||
|                     if (key !== 'create' || !destination) { | ||||
|                         return []; | ||||
|                     } | ||||
|  | ||||
|                     // Introduce one create action per type | ||||
|                     return typeService.listTypes().filter(function (type) { | ||||
|                         return type.hasFeature("creation"); | ||||
|                     }).map(function (type) { | ||||
|                         return new CreateAction( | ||||
|                             type, | ||||
|                             destination, | ||||
|                             context, | ||||
|                             dialogService, | ||||
|                             creationService, | ||||
|                             policyService | ||||
|                         ); | ||||
|                     }); | ||||
|                 } | ||||
|             }; | ||||
|             this.typeService = typeService; | ||||
|             this.dialogService = dialogService; | ||||
|             this.creationService = creationService; | ||||
|             this.policyService = policyService; | ||||
|         } | ||||
|  | ||||
|         CreateActionProvider.prototype.getActions = function (actionContext) { | ||||
|             var context = actionContext || {}, | ||||
|                 key = context.key, | ||||
|                 destination = context.domainObject, | ||||
|                 self = this; | ||||
|  | ||||
|             // We only provide Create actions, and we need a | ||||
|             // domain object to serve as the container for the | ||||
|             // newly-created object (although the user may later | ||||
|             // make a different selection) | ||||
|             if (key !== 'create' || !destination) { | ||||
|                 return []; | ||||
|             } | ||||
|  | ||||
|             // Introduce one create action per type | ||||
|             return this.typeService.listTypes().filter(function (type) { | ||||
|                 return type.hasFeature("creation"); | ||||
|             }).map(function (type) { | ||||
|                 return new CreateAction( | ||||
|                     type, | ||||
|                     destination, | ||||
|                     context, | ||||
|                     self.dialogService, | ||||
|                     self.creationService, | ||||
|                     self.policyService | ||||
|                 ); | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         return CreateActionProvider; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -34,6 +34,7 @@ define( | ||||
|          * set of Create actions based on the currently-selected | ||||
|          * domain object. | ||||
|          * | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          */ | ||||
|         function CreateMenuController($scope) { | ||||
| @@ -55,4 +56,4 @@ define( | ||||
|  | ||||
|         return CreateMenuController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -21,12 +21,6 @@ | ||||
|  *****************************************************************************/ | ||||
| /*global define*/ | ||||
|  | ||||
| /** | ||||
|  * Defines the CreateWizard, used by the CreateAction to | ||||
|  * populate the form shown in dialog based on the created type. | ||||
|  * | ||||
|  * @module core/action/create-wizard | ||||
|  */ | ||||
| define( | ||||
|     function () { | ||||
|         'use strict'; | ||||
| @@ -37,113 +31,118 @@ define( | ||||
|          * @param {TypeImpl} type the type of domain object to be created | ||||
|          * @param {DomainObject} parent the domain object to serve as | ||||
|          *        the initial parent for the created object, in the dialog | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          * @memberof module:core/action/create-wizard | ||||
|          */ | ||||
|         function CreateWizard(type, parent, policyService) { | ||||
|             var model = type.getInitialModel(), | ||||
|                 properties = type.getProperties(); | ||||
|             this.type = type; | ||||
|             this.model = type.getInitialModel(); | ||||
|             this.properties = type.getProperties(); | ||||
|             this.parent = parent; | ||||
|             this.policyService = policyService; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get the form model for this wizard; this is a description | ||||
|          * that will be rendered to an HTML form. See the | ||||
|          * platform/forms bundle | ||||
|          * | ||||
|          * @return {FormModel} formModel the form model to | ||||
|          *         show in the create dialog | ||||
|          */ | ||||
|         CreateWizard.prototype.getFormStructure = function () { | ||||
|             var sections = [], | ||||
|                 type = this.type, | ||||
|                 policyService = this.policyService; | ||||
|  | ||||
|             function validateLocation(locatingObject) { | ||||
|                 var locatingType = locatingObject && | ||||
|                         locatingObject.getCapability('type'); | ||||
|                     locatingObject.getCapability('type'); | ||||
|                 return locatingType && policyService.allow( | ||||
|                     "composition", | ||||
|                     locatingType, | ||||
|                     type | ||||
|                 ); | ||||
|                         "composition", | ||||
|                         locatingType, | ||||
|                         type | ||||
|                     ); | ||||
|             } | ||||
|  | ||||
|             sections.push({ | ||||
|                 name: "Properties", | ||||
|                 rows: this.properties.map(function (property, index) { | ||||
|                     // Property definition is same as form row definition | ||||
|                     var row = Object.create(property.getDefinition()); | ||||
|  | ||||
|                     // Use index as the key into the formValue; | ||||
|                     // this correlates to the indexing provided by | ||||
|                     // getInitialFormValue | ||||
|                     row.key = index; | ||||
|  | ||||
|                     return row; | ||||
|                 }) | ||||
|             }); | ||||
|  | ||||
|             // Ensure there is always a "save in" section | ||||
|             sections.push({ name: 'Location', rows: [{ | ||||
|                 name: "Save In", | ||||
|                 control: "locator", | ||||
|                 validate: validateLocation, | ||||
|                 key: "createParent" | ||||
|             }]}); | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get the form model for this wizard; this is a description | ||||
|                  * that will be rendered to an HTML form. See the | ||||
|                  * platform/forms bundle | ||||
|                  * | ||||
|                  * @return {FormModel} formModel the form model to | ||||
|                  *         show in the create dialog | ||||
|                  */ | ||||
|                 getFormStructure: function () { | ||||
|                     var sections = []; | ||||
|  | ||||
|                     sections.push({ | ||||
|                         name: "Properties", | ||||
|                         rows: properties.map(function (property, index) { | ||||
|                             // Property definition is same as form row definition | ||||
|                             var row = Object.create(property.getDefinition()); | ||||
|  | ||||
|                             // Use index as the key into the formValue; | ||||
|                             // this correlates to the indexing provided by | ||||
|                             // getInitialFormValue | ||||
|                             row.key = index; | ||||
|  | ||||
|                             return row; | ||||
|                         }) | ||||
|                     }); | ||||
|  | ||||
|                     // Ensure there is always a "save in" section | ||||
|                     sections.push({ name: 'Location', rows: [{ | ||||
|                         name: "Save In", | ||||
|                         control: "locator", | ||||
|                         validate: validateLocation, | ||||
|                         key: "createParent" | ||||
|                     }]}); | ||||
|  | ||||
|                     return { | ||||
|                         sections: sections, | ||||
|                         name: "Create a New " + type.getName() | ||||
|                     }; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Get the initial value for the form being described. | ||||
|                  * This will include the values for all properties described | ||||
|                  * in the structure. | ||||
|                  * | ||||
|                  * @returns {object} the initial value of the form | ||||
|                  */ | ||||
|                 getInitialFormValue: function () { | ||||
|                     // Start with initial values for properties | ||||
|                     var formValue = properties.map(function (property) { | ||||
|                         return property.getValue(model); | ||||
|                     }); | ||||
|  | ||||
|                     // Include the createParent | ||||
|                     formValue.createParent = parent; | ||||
|  | ||||
|                     return formValue; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Based on a populated form, get the domain object which | ||||
|                  * should be used as a parent for the newly-created object. | ||||
|                  * @return {DomainObject} | ||||
|                  */ | ||||
|                 getLocation: function (formValue) { | ||||
|                     return formValue.createParent || parent; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Create the domain object model for a newly-created object, | ||||
|                  * based on user input read from a formModel. | ||||
|                  * @return {object} the domain object' model | ||||
|                  */ | ||||
|                 createModel: function (formValue) { | ||||
|                     // Clone | ||||
|                     var newModel = JSON.parse(JSON.stringify(model)); | ||||
|  | ||||
|                     // Always use the type from the type definition | ||||
|                     newModel.type = type.getKey(); | ||||
|  | ||||
|                     // Update all properties | ||||
|                     properties.forEach(function (property, index) { | ||||
|                         property.setValue(newModel, formValue[index]); | ||||
|                     }); | ||||
|  | ||||
|                     return newModel; | ||||
|                 } | ||||
|                 sections: sections, | ||||
|                 name: "Create a New " + this.type.getName() | ||||
|             }; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Get the initial value for the form being described. | ||||
|          * This will include the values for all properties described | ||||
|          * in the structure. | ||||
|          * | ||||
|          * @returns {object} the initial value of the form | ||||
|          */ | ||||
|         CreateWizard.prototype.getInitialFormValue = function () { | ||||
|             // Start with initial values for properties | ||||
|             var model = this.model, | ||||
|                 formValue = this.properties.map(function (property) { | ||||
|                     return property.getValue(model); | ||||
|                 }); | ||||
|  | ||||
|         } | ||||
|             // Include the createParent | ||||
|             formValue.createParent = this.parent; | ||||
|  | ||||
|             return formValue; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Based on a populated form, get the domain object which | ||||
|          * should be used as a parent for the newly-created object. | ||||
|          * @return {DomainObject} | ||||
|          */ | ||||
|         CreateWizard.prototype.getLocation = function (formValue) { | ||||
|             return formValue.createParent || this.parent; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Create the domain object model for a newly-created object, | ||||
|          * based on user input read from a formModel. | ||||
|          * @return {object} the domain object model | ||||
|          */ | ||||
|         CreateWizard.prototype.createModel = function (formValue) { | ||||
|             // Clone | ||||
|             var newModel = JSON.parse(JSON.stringify(this.model)); | ||||
|  | ||||
|             // Always use the type from the type definition | ||||
|             newModel.type = this.type.getKey(); | ||||
|  | ||||
|             // Update all properties | ||||
|             this.properties.forEach(function (property, index) { | ||||
|                 property.setValue(newModel, formValue[index]); | ||||
|             }); | ||||
|  | ||||
|             return newModel; | ||||
|         }; | ||||
|  | ||||
|         return CreateWizard; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -39,15 +39,45 @@ define( | ||||
|          * persisting new domain objects. Handles all actual object | ||||
|          * mutation and persistence associated with domain object | ||||
|          * creation. | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          */ | ||||
|         function CreationService(persistenceService, $q, $log) { | ||||
|             this.persistenceService = persistenceService; | ||||
|             this.$q = $q; | ||||
|             this.$log = $log; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Create a new domain object with the provided model, as | ||||
|          * a member of the provided parent domain object's composition. | ||||
|          * This parent will additionally determine which persistence | ||||
|          * space an object is created within (as it is possible to | ||||
|          * have multiple persistence spaces attached.) | ||||
|          * | ||||
|          * @param {object} model the model for the newly-created | ||||
|          *        domain object | ||||
|          * @param {DomainObject} parent the domain object which | ||||
|          *        should contain the newly-created domain object | ||||
|          *        in its composition | ||||
|          * @return {Promise} a promise that will resolve when the domain | ||||
|          *         object has been created | ||||
|          */ | ||||
|         CreationService.prototype.createObject = function (model, parent) { | ||||
|             var persistence = parent.getCapability("persistence"), | ||||
|                 self = this; | ||||
|  | ||||
|             // Store the location of an object relative to it's parent. | ||||
|             function addLocationToModel(modelId, model, parent) { | ||||
|                 model.location = parent.getId(); | ||||
|                 return model; | ||||
|             } | ||||
|  | ||||
|             // Persist the new domain object's model; it will be fully | ||||
|             // constituted as a domain object when loaded back, as all | ||||
|             // domain object models are. | ||||
|             function doPersist(space, id, model) { | ||||
|                 return persistenceService.createObject( | ||||
|                 return self.persistenceService.createObject( | ||||
|                     space, | ||||
|                     id, | ||||
|                     model | ||||
| @@ -66,14 +96,14 @@ define( | ||||
|                         } | ||||
|                     } else { | ||||
|                         // This is abnormal; composition should be an array | ||||
|                         $log.warn(NO_COMPOSITION_WARNING + parent.getId()); | ||||
|                         self.$log.warn(NO_COMPOSITION_WARNING + parent.getId()); | ||||
|                         return false; // Cancel mutation | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|                 return $q.when(mutatationResult).then(function (result) { | ||||
|                 return self.$q.when(mutatationResult).then(function (result) { | ||||
|                     if (!result) { | ||||
|                         $log.error("Could not mutate " + parent.getId()); | ||||
|                         self.$log.error("Could not mutate " + parent.getId()); | ||||
|                         return undefined; | ||||
|                     } | ||||
|  | ||||
| @@ -93,49 +123,28 @@ define( | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             // Create a new domain object with the provided model as a | ||||
|             // member of the specified parent's composition | ||||
|             function createObject(model, parent) { | ||||
|                 var persistence = parent.getCapability("persistence"); | ||||
|  | ||||
|                 // We need the parent's persistence capability to determine | ||||
|                 // what space to create the new object's model in. | ||||
|                 if (!persistence) { | ||||
|                     $log.warn(NON_PERSISTENT_WARNING); | ||||
|                     return $q.reject(new Error(NON_PERSISTENT_WARNING)); | ||||
|                 } | ||||
|  | ||||
|                 // We create a new domain object in three sequential steps: | ||||
|                 // 1. Get a new UUID for the object | ||||
|                 // 2. Create a model with that ID in the persistence space | ||||
|                 // 3. Add that ID to | ||||
|                 return $q.when( | ||||
|                     uuid() | ||||
|                 ).then(function (id) { | ||||
|                     return doPersist(persistence.getSpace(), id, model); | ||||
|                 }).then(function (id) { | ||||
|                     return addToComposition(id, parent, persistence); | ||||
|                 }); | ||||
|             // We need the parent's persistence capability to determine | ||||
|             // what space to create the new object's model in. | ||||
|             if (!persistence) { | ||||
|                 self.$log.warn(NON_PERSISTENT_WARNING); | ||||
|                 return self.$q.reject(new Error(NON_PERSISTENT_WARNING)); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Create a new domain object with the provided model, as | ||||
|                  * a member of the provided parent domain object's composition. | ||||
|                  * This parent will additionally determine which persistence | ||||
|                  * space an object is created within (as it is possible to | ||||
|                  * have multiple persistence spaces attached.) | ||||
|                  * | ||||
|                  * @param {object} model the model for the newly-created | ||||
|                  *        domain object | ||||
|                  * @param {DomainObject} parent the domain object which | ||||
|                  *        should contain the newly-created domain object | ||||
|                  *        in its composition | ||||
|                  */ | ||||
|                 createObject: createObject | ||||
|             }; | ||||
|         } | ||||
|             // We create a new domain object in three sequential steps: | ||||
|             // 1. Get a new UUID for the object | ||||
|             // 2. Create a model with that ID in the persistence space | ||||
|             // 3. Add that ID to | ||||
|             return self.$q.when(uuid()).then(function (id) { | ||||
|                 model = addLocationToModel(id, model, parent); | ||||
|                 return doPersist(persistence.getSpace(), id, model); | ||||
|             }).then(function (id) { | ||||
|                 return addToComposition(id, parent, persistence); | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|  | ||||
|  | ||||
|         return CreationService; | ||||
|     } | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -30,6 +30,7 @@ define( | ||||
|          * Controller for the "locator" control, which provides the | ||||
|          * user with the ability to select a domain object as the | ||||
|          * destination for a newly-created object in the Create menu. | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          */ | ||||
|         function LocatorController($scope) { | ||||
| @@ -79,3 +80,4 @@ define( | ||||
|         return LocatorController; | ||||
|     } | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -31,32 +31,34 @@ define( | ||||
|  | ||||
|         /** | ||||
|          * The navigate action navigates to a specific domain object. | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          * @implements {Action} | ||||
|          */ | ||||
|         function NavigateAction(navigationService, $q, context) { | ||||
|             var domainObject = context.domainObject; | ||||
|  | ||||
|             function perform() { | ||||
|                 // Set navigation, and wrap like a promise | ||||
|                 return $q.when(navigationService.setNavigation(domainObject)); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Navigate to the object described in the context. | ||||
|                  * @returns {Promise} a promise that is resolved once the | ||||
|                  *          navigation has been updated | ||||
|                  */ | ||||
|                 perform: perform | ||||
|             }; | ||||
|             this.domainObject = context.domainObject; | ||||
|             this.$q = $q; | ||||
|             this.navigationService = navigationService; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Navigate to the object described in the context. | ||||
|          * @returns {Promise} a promise that is resolved once the | ||||
|          *          navigation has been updated | ||||
|          */ | ||||
|         NavigateAction.prototype.perform = function () { | ||||
|             // Set navigation, and wrap like a promise | ||||
|             return this.$q.when( | ||||
|                 this.navigationService.setNavigation(this.domainObject) | ||||
|             ); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Navigate as an action is only applicable when a domain object | ||||
|          * is described in the action context. | ||||
|          * @param {ActionContext} context the context in which the action | ||||
|          *        will be performed | ||||
|          * @returns true if applicable | ||||
|          * @returns {boolean} true if applicable | ||||
|          */ | ||||
|         NavigateAction.appliesTo = function (context) { | ||||
|             return context.domainObject !== undefined; | ||||
| @@ -64,4 +66,4 @@ define( | ||||
|  | ||||
|         return NavigateAction; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -32,68 +32,58 @@ define( | ||||
|         /** | ||||
|          * The navigation service maintains the application's current | ||||
|          * navigation state, and allows listening for changes thereto. | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          */ | ||||
|         function NavigationService() { | ||||
|             var navigated, | ||||
|                 callbacks = []; | ||||
|             this.navigated = undefined; | ||||
|             this.callbacks = []; | ||||
|         } | ||||
|  | ||||
|             // Getter for current navigation | ||||
|             function getNavigation() { | ||||
|                 return navigated; | ||||
|             } | ||||
|         /** | ||||
|          * Get the current navigation state. | ||||
|          * @returns {DomainObject} the object that is navigated-to | ||||
|          */ | ||||
|         NavigationService.prototype.getNavigation = function () { | ||||
|             return this.navigated; | ||||
|         }; | ||||
|  | ||||
|             // Setter for navigation; invokes callbacks | ||||
|             function setNavigation(value) { | ||||
|                 if (navigated !== value) { | ||||
|                     navigated = value; | ||||
|                     callbacks.forEach(function (callback) { | ||||
|                         callback(value); | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Adds a callback | ||||
|             function addListener(callback) { | ||||
|                 callbacks.push(callback); | ||||
|             } | ||||
|  | ||||
|             // Filters out a callback | ||||
|             function removeListener(callback) { | ||||
|                 callbacks = callbacks.filter(function (cb) { | ||||
|                     return cb !== callback; | ||||
|         /** | ||||
|          * Set the current navigation state. This will invoke listeners. | ||||
|          * @param {DomainObject} domainObject the domain object to navigate to | ||||
|          */ | ||||
|         NavigationService.prototype.setNavigation = function (value) { | ||||
|             if (this.navigated !== value) { | ||||
|                 this.navigated = value; | ||||
|                 this.callbacks.forEach(function (callback) { | ||||
|                     callback(value); | ||||
|                 }); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get the current navigation state. | ||||
|                  */ | ||||
|                 getNavigation: getNavigation, | ||||
|                 /** | ||||
|                  * Set the current navigation state. Thiswill invoke listeners. | ||||
|                  * @param {DomainObject} value the domain object to navigate | ||||
|                  *        to | ||||
|                  */ | ||||
|                 setNavigation: setNavigation, | ||||
|                 /** | ||||
|                  * Listen for changes in navigation. The passed callback will | ||||
|                  * be invoked with the new domain object of navigation when | ||||
|                  * this changes. | ||||
|                  * @param {function} callback the callback to invoke when | ||||
|                  *        navigation state changes | ||||
|                  */ | ||||
|                 addListener: addListener, | ||||
|                 /** | ||||
|                  * Stop listening for changes in navigation state. | ||||
|                  * @param {function} callback the callback which should | ||||
|                  *        no longer be invoked when navigation state | ||||
|                  *        changes | ||||
|                  */ | ||||
|                 removeListener: removeListener | ||||
|             }; | ||||
|         } | ||||
|         /** | ||||
|          * Listen for changes in navigation. The passed callback will | ||||
|          * be invoked with the new domain object of navigation when | ||||
|          * this changes. | ||||
|          * @param {function} callback the callback to invoke when | ||||
|          *        navigation state changes | ||||
|          */ | ||||
|         NavigationService.prototype.addListener = function (callback) { | ||||
|             this.callbacks.push(callback); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Stop listening for changes in navigation state. | ||||
|          * @param {function} callback the callback which should | ||||
|          *        no longer be invoked when navigation state | ||||
|          *        changes | ||||
|          */ | ||||
|         NavigationService.prototype.removeListener = function (callback) { | ||||
|             this.callbacks = this.callbacks.filter(function (cb) { | ||||
|                 return cb !== callback; | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         return NavigationService; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -35,36 +35,32 @@ define( | ||||
|         /** | ||||
|          * The fullscreen action toggles between fullscreen display | ||||
|          * and regular in-window display. | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          * @implements {Action} | ||||
|          */ | ||||
|         function FullscreenAction(context) { | ||||
|             return { | ||||
|                 /** | ||||
|                  * Toggle full screen state | ||||
|                  */ | ||||
|                 perform: function () { | ||||
|                     screenfull.toggle(); | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Get metadata about this action, including the | ||||
|                  * applicable glyph to display. | ||||
|                  */ | ||||
|                 getMetadata: function () { | ||||
|                     // We override getMetadata, because the glyph and | ||||
|                     // description need to be determined at run-time | ||||
|                     // based on whether or not we are currently | ||||
|                     // full screen. | ||||
|                     var metadata = Object.create(FullscreenAction); | ||||
|                     metadata.glyph = screenfull.isFullscreen ? "_" : "z"; | ||||
|                     metadata.description = screenfull.isFullscreen ? | ||||
|                             EXIT_FULLSCREEN : ENTER_FULLSCREEN; | ||||
|                     metadata.group = "windowing"; | ||||
|                     metadata.context = context; | ||||
|                     return metadata; | ||||
|                 } | ||||
|             }; | ||||
|             this.context = context; | ||||
|         } | ||||
|  | ||||
|         FullscreenAction.prototype.perform = function () { | ||||
|             screenfull.toggle(); | ||||
|         }; | ||||
|  | ||||
|         FullscreenAction.prototype.getMetadata = function () { | ||||
|             // We override getMetadata, because the glyph and | ||||
|             // description need to be determined at run-time | ||||
|             // based on whether or not we are currently | ||||
|             // full screen. | ||||
|             var metadata = Object.create(FullscreenAction); | ||||
|             metadata.glyph = screenfull.isFullscreen ? "_" : "z"; | ||||
|             metadata.description = screenfull.isFullscreen ? | ||||
|                 EXIT_FULLSCREEN : ENTER_FULLSCREEN; | ||||
|             metadata.group = "windowing"; | ||||
|             metadata.context = this.context; | ||||
|             return metadata; | ||||
|         }; | ||||
|  | ||||
|         return FullscreenAction; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -33,35 +33,29 @@ define( | ||||
|         /** | ||||
|          * The new tab action allows a domain object to be opened | ||||
|          * into a new browser tab. | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          * @implements {Action} | ||||
|          */ | ||||
|         function NewTabAction(urlService, $window, context) { | ||||
|             // Returns the selected domain object | ||||
|             // when using the context menu or the top right button | ||||
|             // based on the context and the existance of the object | ||||
|             // It is set to object an returned | ||||
|             function getSelectedObject() { | ||||
|                 var object; | ||||
|                 if (context.selectedObject) { | ||||
|                     object = context.selectedObject; | ||||
|                 } else { | ||||
|                     object = context.domainObject; | ||||
|                 } | ||||
|                 return object; | ||||
|             } | ||||
|              | ||||
|             return { | ||||
|                 // Performs the open in new tab function | ||||
|                 // By calling the url service, the mode needed | ||||
|                 // (browse) and the domainObject is passed in and | ||||
|                 // the path is returned and opened in a new tab | ||||
|                 perform: function () { | ||||
|                     $window.open(urlService.urlForNewTab("browse", getSelectedObject()), | ||||
|                                 "_blank"); | ||||
|                 } | ||||
|             context = context || {}; | ||||
|  | ||||
|             this.urlService = urlService; | ||||
|             this.open = function () { | ||||
|                 $window.open.apply($window, arguments); | ||||
|             }; | ||||
|  | ||||
|             // Choose the object to be opened into a new tab | ||||
|             this.domainObject = context.selectedObject || context.domainObject; | ||||
|         } | ||||
|  | ||||
|         NewTabAction.prototype.perform = function () { | ||||
|             this.open( | ||||
|                 this.urlService.urlForNewTab("browse", this.domainObject), | ||||
|                 "_blank" | ||||
|             ); | ||||
|         }; | ||||
|  | ||||
|         return NewTabAction; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -29,6 +29,7 @@ define( | ||||
|         /** | ||||
|          * Updates the title of the current window to reflect the name | ||||
|          * of the currently navigated-to domain object. | ||||
|          * @memberof platform/commonUI/browse | ||||
|          * @constructor | ||||
|          */ | ||||
|         function WindowTitler(navigationService, $rootScope, $document) { | ||||
| @@ -49,4 +50,4 @@ define( | ||||
|  | ||||
|         return WindowTitler; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -54,6 +54,7 @@ define( | ||||
|                     "$scope", | ||||
|                     [ "$on", "$watch" ] | ||||
|                 ); | ||||
|                 mockScope.ngModel = {}; | ||||
|                 mockRoute = { current: { params: {} } }; | ||||
|                 mockLocation = jasmine.createSpyObj( | ||||
|                     "$location", | ||||
|   | ||||
| @@ -31,6 +31,7 @@ define( | ||||
|             var mockScope, | ||||
|                 mockLocation, | ||||
|                 mockRoute, | ||||
|                 mockWindow, | ||||
|                 mockUnlisten, | ||||
|                 controller; | ||||
|  | ||||
| @@ -48,7 +49,9 @@ define( | ||||
|                     "$scope", | ||||
|                     [ "$on", "$watch" ] | ||||
|                 ); | ||||
|                 mockScope.ngModel = {}; | ||||
|                 mockRoute = { current: { params: {} } }; | ||||
|                 mockWindow = {}; | ||||
|                 mockLocation = jasmine.createSpyObj( | ||||
|                     "$location", | ||||
|                     [ "path", "search" ] | ||||
| @@ -60,7 +63,8 @@ define( | ||||
|                 controller = new BrowseObjectController( | ||||
|                     mockScope, | ||||
|                     mockLocation, | ||||
|                     mockRoute | ||||
|                     mockRoute, | ||||
|                     mockWindow | ||||
|                 ); | ||||
|             }); | ||||
|  | ||||
| @@ -97,7 +101,23 @@ define( | ||||
|                 expect(mockScope.representation.selected) | ||||
|                     .toEqual(testViews[1]); | ||||
|             }); | ||||
|  | ||||
|              | ||||
|             it("sets ngModel properties on initialization", function () { | ||||
|                 // Left pane open status depends on how the window was opened | ||||
|                 // Case 1: undefined opener | ||||
|                 expect(mockWindow.opener).not.toBeDefined(); | ||||
|                 expect(mockScope.ngModel.leftPane).toBeTruthy(); | ||||
|                  | ||||
|                 // Case 2: defined opener | ||||
|                 mockWindow.opener = {}; | ||||
|                 controller = new BrowseObjectController( | ||||
|                     mockScope, | ||||
|                     mockLocation, | ||||
|                     mockRoute, | ||||
|                     mockWindow | ||||
|                 ); | ||||
|                 expect(mockScope.ngModel.leftPane).toBeFalsy(); | ||||
|             }); | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
|   | ||||
| @@ -38,6 +38,7 @@ define( | ||||
|                 mockMutationCapability, | ||||
|                 mockPersistenceCapability, | ||||
|                 mockCompositionCapability, | ||||
|                 mockContextCapability, | ||||
|                 mockCapabilities, | ||||
|                 creationService; | ||||
|  | ||||
| @@ -87,10 +88,15 @@ define( | ||||
|                     "composition", | ||||
|                     ["invoke"] | ||||
|                 ); | ||||
|                 mockContextCapability = jasmine.createSpyObj( | ||||
|                     "context", | ||||
|                     ["getPath"] | ||||
|                 ); | ||||
|                 mockCapabilities = { | ||||
|                     mutation: mockMutationCapability, | ||||
|                     persistence: mockPersistenceCapability, | ||||
|                     composition: mockCompositionCapability | ||||
|                     composition: mockCompositionCapability, | ||||
|                     context: mockContextCapability | ||||
|                 }; | ||||
|  | ||||
|                 mockPersistenceService.createObject.andReturn( | ||||
| @@ -103,6 +109,7 @@ define( | ||||
|                 mockParentObject.useCapability.andCallFake(function (key, value) { | ||||
|                     return mockCapabilities[key].invoke(value); | ||||
|                 }); | ||||
|                 mockParentObject.getId.andReturn('parentId'); | ||||
|  | ||||
|                 mockPersistenceCapability.persist.andReturn( | ||||
|                     mockPromise(true) | ||||
| @@ -194,7 +201,16 @@ define( | ||||
|                 expect(mockLog.error).toHaveBeenCalled(); | ||||
|             }); | ||||
|  | ||||
|             it("stores location on new domainObjects", function () { | ||||
|                 var model = { name: "my model" }, | ||||
|                     objectPromise = creationService.createObject( | ||||
|                         model, | ||||
|                         mockParentObject | ||||
|                     ); | ||||
|  | ||||
|                 expect(model.location).toBe('parentId'); | ||||
|             }); | ||||
|  | ||||
|         }); | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -22,7 +22,9 @@ | ||||
| /*global define*/ | ||||
|  | ||||
| /** | ||||
|  * Module defining DialogService. Created by vwoeltje on 11/10/14. | ||||
|  * This bundle implements the dialog service, which can be used to | ||||
|  * launch dialogs for user input & notifications. | ||||
|  * @namespace platform/commonUI/dialog | ||||
|  */ | ||||
| define( | ||||
|     [], | ||||
| @@ -32,128 +34,130 @@ define( | ||||
|          * The dialog service is responsible for handling window-modal | ||||
|          * communication with the user, such as displaying forms for user | ||||
|          * input. | ||||
|          * @memberof platform/commonUI/dialog | ||||
|          * @constructor | ||||
|          */ | ||||
|         function DialogService(overlayService, $q, $log) { | ||||
|             var overlay, | ||||
|                 dialogVisible = false; | ||||
|  | ||||
|             // Stop showing whatever overlay is currently active | ||||
|             // (e.g. because the user hit cancel) | ||||
|             function dismiss() { | ||||
|                 if (overlay) { | ||||
|                     overlay.dismiss(); | ||||
|                 } | ||||
|                 dialogVisible = false; | ||||
|             } | ||||
|  | ||||
|             function getDialogResponse(key, model, resultGetter) { | ||||
|                 // We will return this result as a promise, because user | ||||
|                 // input is asynchronous. | ||||
|                 var deferred = $q.defer(), | ||||
|                     overlayModel; | ||||
|  | ||||
|                 // Confirm function; this will be passed in to the | ||||
|                 // overlay-dialog template and associated with a | ||||
|                 // OK button click | ||||
|                 function confirm(value) { | ||||
|                     // Pass along the result | ||||
|                     deferred.resolve(resultGetter ? resultGetter() : value); | ||||
|  | ||||
|                     // Stop showing the dialog | ||||
|                     dismiss(); | ||||
|                 } | ||||
|  | ||||
|                 // Cancel function; this will be passed in to the | ||||
|                 // overlay-dialog template and associated with a | ||||
|                 // Cancel or X button click | ||||
|                 function cancel() { | ||||
|                     deferred.reject(); | ||||
|                     dismiss(); | ||||
|                 } | ||||
|  | ||||
|                 // Add confirm/cancel callbacks | ||||
|                 model.confirm = confirm; | ||||
|                 model.cancel = cancel; | ||||
|  | ||||
|                 if (dialogVisible) { | ||||
|                     // Only one dialog should be shown at a time. | ||||
|                     // The application design should be such that | ||||
|                     // we never even try to do this. | ||||
|                     $log.warn([ | ||||
|                         "Dialog already showing; ", | ||||
|                         "unable to show ", | ||||
|                         model.name | ||||
|                     ].join("")); | ||||
|                     deferred.reject(); | ||||
|                 } else { | ||||
|                     // Add the overlay using the OverlayService, which | ||||
|                     // will handle actual insertion into the DOM | ||||
|                     overlay = overlayService.createOverlay( | ||||
|                         key, | ||||
|                         model | ||||
|                     ); | ||||
|  | ||||
|                     // Track that a dialog is already visible, to | ||||
|                     // avoid spawning multiple dialogs at once. | ||||
|                     dialogVisible = true; | ||||
|                 } | ||||
|  | ||||
|                 return deferred.promise; | ||||
|             } | ||||
|  | ||||
|             function getUserInput(formModel, value) { | ||||
|                 var overlayModel = { | ||||
|                         title: formModel.name, | ||||
|                         message: formModel.message, | ||||
|                         structure: formModel, | ||||
|                         value: value | ||||
|                     }; | ||||
|  | ||||
|                 // Provide result from the model | ||||
|                 function resultGetter() { | ||||
|                     return overlayModel.value; | ||||
|                 } | ||||
|  | ||||
|                 // Show the overlay-dialog | ||||
|                 return getDialogResponse( | ||||
|                     "overlay-dialog", | ||||
|                     overlayModel, | ||||
|                     resultGetter | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             function getUserChoice(dialogModel) { | ||||
|                 // Show the overlay-options dialog | ||||
|                 return getDialogResponse( | ||||
|                     "overlay-options", | ||||
|                     { dialog: dialogModel } | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Request user input via a window-modal dialog. | ||||
|                  * | ||||
|                  * @param {FormModel} formModel a description of the form | ||||
|                  *        to be shown (see platform/forms) | ||||
|                  * @param {object} value the initial state of the form | ||||
|                  * @returns {Promise} a promsie for the form value that the | ||||
|                  *          user has supplied; this may be rejected if | ||||
|                  *          user input cannot be obtained (for instance, | ||||
|                  *          because the user cancelled the dialog) | ||||
|                  */ | ||||
|                 getUserInput: getUserInput, | ||||
|                 /** | ||||
|                  * Request that the user chooses from a set of options, | ||||
|                  * which will be shown as buttons. | ||||
|                  * | ||||
|                  * @param dialogModel a description of the dialog to show | ||||
|                  */ | ||||
|                 getUserChoice: getUserChoice | ||||
|             }; | ||||
|             this.overlayService = overlayService; | ||||
|             this.$q = $q; | ||||
|             this.$log = $log; | ||||
|             this.overlay = undefined; | ||||
|             this.dialogVisible = false; | ||||
|         } | ||||
|  | ||||
|         // Stop showing whatever overlay is currently active | ||||
|         // (e.g. because the user hit cancel) | ||||
|         DialogService.prototype.dismiss = function () { | ||||
|             var overlay = this.overlay; | ||||
|             if (overlay) { | ||||
|                 overlay.dismiss(); | ||||
|             } | ||||
|             this.dialogVisible = false; | ||||
|         }; | ||||
|  | ||||
|         DialogService.prototype.getDialogResponse = function (key, model, resultGetter) { | ||||
|             // We will return this result as a promise, because user | ||||
|             // input is asynchronous. | ||||
|             var deferred = this.$q.defer(), | ||||
|                 self = this; | ||||
|  | ||||
|             // Confirm function; this will be passed in to the | ||||
|             // overlay-dialog template and associated with a | ||||
|             // OK button click | ||||
|             function confirm(value) { | ||||
|                 // Pass along the result | ||||
|                 deferred.resolve(resultGetter ? resultGetter() : value); | ||||
|  | ||||
|                 // Stop showing the dialog | ||||
|                 self.dismiss(); | ||||
|             } | ||||
|  | ||||
|             // Cancel function; this will be passed in to the | ||||
|             // overlay-dialog template and associated with a | ||||
|             // Cancel or X button click | ||||
|             function cancel() { | ||||
|                 deferred.reject(); | ||||
|                 self.dismiss(); | ||||
|             } | ||||
|  | ||||
|             // Add confirm/cancel callbacks | ||||
|             model.confirm = confirm; | ||||
|             model.cancel = cancel; | ||||
|  | ||||
|             if (this.dialogVisible) { | ||||
|                 // Only one dialog should be shown at a time. | ||||
|                 // The application design should be such that | ||||
|                 // we never even try to do this. | ||||
|                 this.$log.warn([ | ||||
|                     "Dialog already showing; ", | ||||
|                     "unable to show ", | ||||
|                     model.name | ||||
|                 ].join("")); | ||||
|                 deferred.reject(); | ||||
|             } else { | ||||
|                 // Add the overlay using the OverlayService, which | ||||
|                 // will handle actual insertion into the DOM | ||||
|                 this.overlay = this.overlayService.createOverlay( | ||||
|                     key, | ||||
|                     model | ||||
|                 ); | ||||
|  | ||||
|                 // Track that a dialog is already visible, to | ||||
|                 // avoid spawning multiple dialogs at once. | ||||
|                 this.dialogVisible = true; | ||||
|             } | ||||
|  | ||||
|             return deferred.promise; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Request user input via a window-modal dialog. | ||||
|          * | ||||
|          * @param {FormModel} formModel a description of the form | ||||
|          *        to be shown (see platform/forms) | ||||
|          * @param {object} value the initial state of the form | ||||
|          * @returns {Promise} a promise for the form value that the | ||||
|          *          user has supplied; this may be rejected if | ||||
|          *          user input cannot be obtained (for instance, | ||||
|          *          because the user cancelled the dialog) | ||||
|          */ | ||||
|         DialogService.prototype.getUserInput = function (formModel, value) { | ||||
|             var overlayModel = { | ||||
|                 title: formModel.name, | ||||
|                 message: formModel.message, | ||||
|                 structure: formModel, | ||||
|                 value: value | ||||
|             }; | ||||
|  | ||||
|             // Provide result from the model | ||||
|             function resultGetter() { | ||||
|                 return overlayModel.value; | ||||
|             } | ||||
|  | ||||
|             // Show the overlay-dialog | ||||
|             return this.getDialogResponse( | ||||
|                 "overlay-dialog", | ||||
|                 overlayModel, | ||||
|                 resultGetter | ||||
|             ); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Request that the user chooses from a set of options, | ||||
|          * which will be shown as buttons. | ||||
|          * | ||||
|          * @param dialogModel a description of the dialog to show | ||||
|          * @return {Promise} a promise for the user's choice | ||||
|          */ | ||||
|         DialogService.prototype.getUserChoice = function (dialogModel) { | ||||
|             // Show the overlay-options dialog | ||||
|             return this.getDialogResponse( | ||||
|                 "overlay-options", | ||||
|                 { dialog: dialogModel } | ||||
|             ); | ||||
|         }; | ||||
|  | ||||
|  | ||||
|         return DialogService; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -43,57 +43,63 @@ define( | ||||
|          * particularly where a multiple-overlay effect is not specifically | ||||
|          * desired). | ||||
|          * | ||||
|          * @memberof platform/commonUI/dialog | ||||
|          * @constructor | ||||
|          */ | ||||
|         function OverlayService($document, $compile, $rootScope) { | ||||
|             function createOverlay(key, overlayModel) { | ||||
|                 // Create a new scope for this overlay | ||||
|                 var scope = $rootScope.$new(), | ||||
|                     element; | ||||
|             this.$compile = $compile; | ||||
|  | ||||
|                 // Stop showing the overlay; additionally, release the scope | ||||
|                 // that it uses. | ||||
|                 function dismiss() { | ||||
|                     scope.$destroy(); | ||||
|                     element.remove(); | ||||
|                 } | ||||
|  | ||||
|                 // If no model is supplied, just fill in a default "cancel" | ||||
|                 overlayModel = overlayModel || { cancel: dismiss }; | ||||
|  | ||||
|                 // Populate the scope; will be passed directly to the template | ||||
|                 scope.overlay = overlayModel; | ||||
|                 scope.key = key; | ||||
|  | ||||
|                 // Create the overlay element and add it to the document's body | ||||
|                 element = $compile(TEMPLATE)(scope); | ||||
|                 $document.find('body').prepend(element); | ||||
|  | ||||
|  | ||||
|  | ||||
|                 return { | ||||
|                     dismiss: dismiss | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Add a new overlay to the document. This will be | ||||
|                  * prepended to the document body; the overlay's | ||||
|                  * template (as pointed to by the `key` argument) is | ||||
|                  * responsible for having a useful z-order, and for | ||||
|                  * blocking user interactions if appropriate. | ||||
|                  * | ||||
|                  * @param {string} key the symbolic key which identifies | ||||
|                  *        the template of the overlay to be shown | ||||
|                  * @param {object} overlayModel the model to pass to the | ||||
|                  *        included overlay template (this will be passed | ||||
|                  *        in via ng-model) | ||||
|                  */ | ||||
|                 createOverlay: createOverlay | ||||
|             // Don't include $document and $rootScope directly; | ||||
|             // avoids https://docs.angularjs.org/error/ng/cpws | ||||
|             this.findBody = function () { | ||||
|                 return $document.find('body'); | ||||
|             }; | ||||
|             this.newScope = function () { | ||||
|                 return $rootScope.$new(); | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Add a new overlay to the document. This will be | ||||
|          * prepended to the document body; the overlay's | ||||
|          * template (as pointed to by the `key` argument) is | ||||
|          * responsible for having a useful z-order, and for | ||||
|          * blocking user interactions if appropriate. | ||||
|          * | ||||
|          * @param {string} key the symbolic key which identifies | ||||
|          *        the template of the overlay to be shown | ||||
|          * @param {object} overlayModel the model to pass to the | ||||
|          *        included overlay template (this will be passed | ||||
|          *        in via ng-model) | ||||
|          */ | ||||
|         OverlayService.prototype.createOverlay = function (key, overlayModel) { | ||||
|             // Create a new scope for this overlay | ||||
|             var scope = this.newScope(), | ||||
|                 element; | ||||
|  | ||||
|             // Stop showing the overlay; additionally, release the scope | ||||
|             // that it uses. | ||||
|             function dismiss() { | ||||
|                 scope.$destroy(); | ||||
|                 element.remove(); | ||||
|             } | ||||
|  | ||||
|             // If no model is supplied, just fill in a default "cancel" | ||||
|             overlayModel = overlayModel || { cancel: dismiss }; | ||||
|  | ||||
|             // Populate the scope; will be passed directly to the template | ||||
|             scope.overlay = overlayModel; | ||||
|             scope.key = key; | ||||
|  | ||||
|             // Create the overlay element and add it to the document's body | ||||
|             element = this.$compile(TEMPLATE)(scope); | ||||
|             this.findBody().prepend(element); | ||||
|  | ||||
|             return { | ||||
|                 dismiss: dismiss | ||||
|             }; | ||||
|         }; | ||||
|  | ||||
|         return OverlayService; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -59,7 +59,7 @@ | ||||
|                 "glyph": "Z", | ||||
|                 "name": "Remove", | ||||
|                 "description": "Remove this object from its containing object.", | ||||
|                 "depends": [ "$q" ] | ||||
|                 "depends": [ "$q", "navigationService" ] | ||||
|             }, | ||||
|             { | ||||
|                 "key": "save", | ||||
|   | ||||
| @@ -21,49 +21,71 @@ | ||||
| --> | ||||
| <mct-representation key="'topbar-edit'" | ||||
|                     mct-object="domainObject" | ||||
|                     ng-model="representation"> | ||||
|                     ng-model="representation" | ||||
|                     ng-click="ngModel.inspectionObjects = [domainObject]"> | ||||
| </mct-representation> | ||||
| <div class="holder edit-area abs"> | ||||
|     <mct-split-pane class='contents abs' anchor='right'> | ||||
|         <div class='split-pane-component pane left edit-main'> | ||||
|             <mct-toolbar name="mctToolbar" | ||||
|                          structure="toolbar.structure" | ||||
|                          ng-model="toolbar.state"> | ||||
|             </mct-toolbar> | ||||
|             <div class='holder abs object-holder work-area'> | ||||
|                 <mct-representation key="representation.selected.key" | ||||
|                                     toolbar="toolbar" | ||||
|                                     mct-object="representation.selected.key && domainObject"> | ||||
|                 </mct-representation> | ||||
|             </div> | ||||
|         </div> | ||||
|         <mct-splitter></mct-splitter> | ||||
|         <div | ||||
|             class='split-pane-component pane right edit-objects menus-to-left' | ||||
|             ng-controller='EditPanesController as editPanes' | ||||
|             > | ||||
|             <mct-split-pane class='contents abs' anchor='bottom'> | ||||
|                 <div | ||||
|                     class="abs pane top accordion" | ||||
|                     ng-controller="ToggleController as toggle" | ||||
|                     > | ||||
|                     <mct-container key="accordion" label="Library"> | ||||
|                         <mct-representation key="'tree'" | ||||
|                                             mct-object="editPanes.getRoot()"> | ||||
|     <mct-split-pane class='contents abs' | ||||
|                     anchor='right'> | ||||
|         <div class='split-pane-component secondary-split pane left'> | ||||
|             <mct-split-pane class='contents abs' anchor='right'> | ||||
|                 <div class='split-pane-component pane left edit-main'> | ||||
|                     <mct-toolbar name="mctToolbar" | ||||
|                                  structure="toolbar.structure" | ||||
|                                  ng-model="toolbar.state"> | ||||
|                     </mct-toolbar> | ||||
|                     <div class='holder abs object-holder work-area'> | ||||
|                         <mct-representation key="representation.selected.key" | ||||
|                                             toolbar="toolbar" | ||||
|                                             mct-object="representation.selected.key && domainObject" | ||||
|                                             ng-model="ngModel"> | ||||
|                         </mct-representation> | ||||
|                     </mct-container> | ||||
|                     </div> | ||||
|                 </div> | ||||
|                 <mct-splitter></mct-splitter> | ||||
|                 <div | ||||
|                     class="abs pane bottom accordion" | ||||
|                     ng-controller="ToggleController as toggle" | ||||
|                     class='split-pane-component pane right edit-objects menus-to-left' | ||||
|                     ng-controller='EditPanesController as editPanes' | ||||
|                     > | ||||
|                     <mct-container key="accordion" label="Elements"> | ||||
|                         <mct-representation key="'edit-elements'" mct-object="domainObject"> | ||||
|                         </mct-representation> | ||||
|                     </mct-container> | ||||
|                     <mct-split-pane class='contents abs' anchor='bottom'> | ||||
|                         <div | ||||
|                             class="abs pane top accordion" | ||||
|                             ng-controller="ToggleController as toggle" | ||||
|                             > | ||||
|                             <mct-container key="accordion" label="Library"> | ||||
|                                 <mct-representation key="'tree'" | ||||
|                                                     mct-object="editPanes.getRoot()" | ||||
|                                                     ng-model="ngModel"> | ||||
|                                 </mct-representation> | ||||
|                             </mct-container> | ||||
|                         </div> | ||||
|                         <mct-splitter></mct-splitter> | ||||
|                         <div | ||||
|                             class="abs pane bottom accordion" | ||||
|                             ng-controller="ToggleController as toggle" | ||||
|                             > | ||||
|                             <mct-container key="accordion" label="Elements"> | ||||
|                                 <mct-representation key="'edit-elements'" | ||||
|                                                     mct-object="domainObject" | ||||
|                                                     ng-model="ngModel"> | ||||
|                                 </mct-representation> | ||||
|                             </mct-container> | ||||
|                         </div> | ||||
|                     </mct-split-pane> | ||||
|                 </div> | ||||
|             </mct-split-pane> | ||||
|         </div> | ||||
|          | ||||
|         <mct-splitter></mct-splitter> | ||||
|          | ||||
|         <div class='split-pane-component object-inspector pane right' | ||||
|              ng-class='{inactive: !paneModel.rightPane}'> | ||||
|             <div class='holder inspector-holder abs'> | ||||
|                 <mct-representation key="'object-inspector'" | ||||
|                                     mct-object="editPanes.getRoot()" | ||||
|                                     ng-model="ngModel"> | ||||
|                 </mct-representation> | ||||
|             </div> | ||||
|         </div> | ||||
|     </mct-split-pane> | ||||
| </div> | ||||
|   | ||||
| @@ -24,7 +24,9 @@ | ||||
|      ng-controller="EditController as editMode" | ||||
|      mct-before-unload="editMode.getUnloadWarning()"> | ||||
|  | ||||
|     <mct-representation key="'edit-object'" mct-object="editMode.navigatedObject()"> | ||||
|     <mct-representation key="'edit-object'" | ||||
|                         mct-object="editMode.navigatedObject()" | ||||
|                         ng-model="editModel"> | ||||
|     </mct-representation> | ||||
|  | ||||
|     <mct-include key="'bottombar'"></mct-include> | ||||
|   | ||||
| @@ -24,7 +24,9 @@ | ||||
|     <ul class="tree"> | ||||
|         <li ng-repeat="containedObject in composition"> | ||||
|             <span class="tree-item"> | ||||
|                 <mct-representation key="'label'" mct-object="containedObject"> | ||||
|                 <mct-representation key="'label'" | ||||
|                                     mct-object="containedObject" | ||||
|                                     ng-click="ngModel.inspectionObjects = [containedObject]"> | ||||
|                 </mct-representation> | ||||
|             </span> | ||||
|         </li> | ||||
|   | ||||
| @@ -29,9 +29,26 @@ define( | ||||
|          * The "Cancel" action; the action triggered by clicking Cancel from | ||||
|          * Edit Mode. Exits the editing user interface and invokes object | ||||
|          * capabilities to persist the changes that have been made. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {Action} | ||||
|          */ | ||||
|         function CancelAction($location, urlService, context) { | ||||
|             var domainObject = context.domainObject; | ||||
|             this.domainObject = context.domainObject; | ||||
|             this.$location = $location; | ||||
|             this.urlService = urlService; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Cancel editing. | ||||
|          * | ||||
|          * @returns {Promise} a promise that will be fulfilled when | ||||
|          *          cancellation has completed | ||||
|          */ | ||||
|         CancelAction.prototype.perform = function () { | ||||
|             var domainObject = this.domainObject, | ||||
|                 $location = this.$location, | ||||
|                 urlService = this.urlService; | ||||
|  | ||||
|             // Look up the object's "editor.completion" capability; | ||||
|             // this is introduced by EditableDomainObject which is | ||||
| @@ -56,25 +73,15 @@ define( | ||||
|                 ))); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Cancel editing. | ||||
|                  * | ||||
|                  * @returns {Promise} a promise that will be fulfilled when | ||||
|                  *          cancellation has completed | ||||
|                  */ | ||||
|                 perform: function () { | ||||
|                     return doCancel(getEditorCapability()) | ||||
|                         .then(returnToBrowse); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|             return doCancel(getEditorCapability()) | ||||
|                 .then(returnToBrowse); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Check if this action is applicable in a given context. | ||||
|          * This will ensure that a domain object is present in the context, | ||||
|          * and that this domain object is in Edit mode. | ||||
|          * @returns true if applicable | ||||
|          * @returns {boolean} true if applicable | ||||
|          */ | ||||
|         CancelAction.appliesTo = function (context) { | ||||
|             var domainObject = (context || {}).domainObject; | ||||
| @@ -84,4 +91,4 @@ define( | ||||
|  | ||||
|         return CancelAction; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -42,7 +42,9 @@ define( | ||||
|          * mode (typically triggered by the Edit button.) This will | ||||
|          * show the user interface for editing (by way of a change in | ||||
|          * route) | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          * @implements {Action} | ||||
|          */ | ||||
|         function EditAction($location, navigationService, $log, context) { | ||||
|             var domainObject = (context || {}).domainObject; | ||||
| @@ -60,17 +62,19 @@ define( | ||||
|                 return NULL_ACTION; | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Enter edit mode. | ||||
|                  */ | ||||
|                 perform: function () { | ||||
|                     navigationService.setNavigation(domainObject); | ||||
|                     $location.path("/edit"); | ||||
|                 } | ||||
|             }; | ||||
|             this.domainObject = domainObject; | ||||
|             this.$location = $location; | ||||
|             this.navigationService = navigationService; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Enter edit mode. | ||||
|          */ | ||||
|         EditAction.prototype.perform = function () { | ||||
|             this.navigationService.setNavigation(this.domainObject); | ||||
|             this.$location.path("/edit"); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Check for applicability; verify that a domain object is present | ||||
|          * for this action to be performed upon. | ||||
| @@ -87,4 +91,4 @@ define( | ||||
|  | ||||
|         return EditAction; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -29,42 +29,43 @@ define( | ||||
|  | ||||
|         /** | ||||
|          * Add one domain object to another's composition. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {Action} | ||||
|          */ | ||||
|         function LinkAction(context) { | ||||
|             var domainObject = (context || {}).domainObject, | ||||
|                 selectedObject = (context || {}).selectedObject, | ||||
|                 selectedId = selectedObject && selectedObject.getId(); | ||||
|             this.domainObject = (context || {}).domainObject; | ||||
|             this.selectedObject = (context || {}).selectedObject; | ||||
|             this.selectedId = this.selectedObject && this.selectedObject.getId(); | ||||
|         } | ||||
|  | ||||
|         LinkAction.prototype.perform = function () { | ||||
|             var self = this; | ||||
|  | ||||
|             // Add this domain object's identifier | ||||
|             function addId(model) { | ||||
|                 if (Array.isArray(model.composition) && | ||||
|                         model.composition.indexOf(selectedId) < 0) { | ||||
|                     model.composition.push(selectedId); | ||||
|                     model.composition.indexOf(self.selectedId) < 0) { | ||||
|                     model.composition.push(self.selectedId); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Persist changes to the domain object | ||||
|             function doPersist() { | ||||
|                 var persistence = domainObject.getCapability('persistence'); | ||||
|                 var persistence = | ||||
|                     self.domainObject.getCapability('persistence'); | ||||
|                 return persistence.persist(); | ||||
|             } | ||||
|  | ||||
|             // Link these objects | ||||
|             function doLink() { | ||||
|                 return domainObject.useCapability("mutation", addId) | ||||
|                 return self.domainObject.useCapability("mutation", addId) | ||||
|                     .then(doPersist); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Perform this action. | ||||
|                  */ | ||||
|                 perform: function () { | ||||
|                     return selectedId && doLink(); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|             return this.selectedId && doLink(); | ||||
|         }; | ||||
|  | ||||
|         return LinkAction; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -32,58 +32,58 @@ define( | ||||
|         'use strict'; | ||||
|  | ||||
|         /** | ||||
|          * Construct an action which will allow an object's metadata to be | ||||
|          * edited. | ||||
|          * Implements the "Edit Properties" action, which prompts the user | ||||
|          * to modify a domain object's properties. | ||||
|          * | ||||
|          * @param {DialogService} dialogService a service which will show the dialog | ||||
|          * @param {DomainObject} object the object to be edited | ||||
|          * @param {ActionContext} context the context in which this action is performed | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {Action} | ||||
|          * @constructor | ||||
|          */ | ||||
|         function PropertiesAction(dialogService, context) { | ||||
|             var object = context.domainObject; | ||||
|             this.domainObject = (context || {}).domainObject; | ||||
|             this.dialogService = dialogService; | ||||
|         } | ||||
|  | ||||
|         PropertiesAction.prototype.perform = function () { | ||||
|             var type = this.domainObject.getCapability('type'), | ||||
|                 domainObject = this.domainObject, | ||||
|                 dialogService = this.dialogService; | ||||
|  | ||||
|             // Persist modifications to this domain object | ||||
|             function doPersist() { | ||||
|                 var persistence = object.getCapability('persistence'); | ||||
|                 var persistence = domainObject.getCapability('persistence'); | ||||
|                 return persistence && persistence.persist(); | ||||
|             } | ||||
|  | ||||
|             // Update the domain object model based on user input | ||||
|             function updateModel(userInput, dialog) { | ||||
|                 return object.useCapability('mutation', function (model) { | ||||
|                 return domainObject.useCapability('mutation', function (model) { | ||||
|                     dialog.updateModel(model, userInput); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             function showDialog(type) { | ||||
|                 // Create a dialog object to generate the form structure, etc. | ||||
|                 var dialog = new PropertiesDialog(type, object.getModel()); | ||||
|                 var dialog = | ||||
|                     new PropertiesDialog(type, domainObject.getModel()); | ||||
|  | ||||
|                 // Show the dialog | ||||
|                 return dialogService.getUserInput( | ||||
|                     dialog.getFormStructure(), | ||||
|                     dialog.getInitialFormValue() | ||||
|                 ).then(function (userInput) { | ||||
|                     // Update the model, if user input was provided | ||||
|                     return userInput && updateModel(userInput, dialog); | ||||
|                 }).then(function (result) { | ||||
|                     return result && doPersist(); | ||||
|                 }); | ||||
|                         // Update the model, if user input was provided | ||||
|                         return userInput && updateModel(userInput, dialog); | ||||
|                     }).then(function (result) { | ||||
|                         return result && doPersist(); | ||||
|                     }); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Perform this action. | ||||
|                  * @return {Promise} a promise which will be | ||||
|                  *         fulfilled when the action has completed. | ||||
|                  */ | ||||
|                 perform: function () { | ||||
|                     var type = object.getCapability('type'); | ||||
|                     return type && showDialog(type); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|             return type && showDialog(type); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Filter this action for applicability against a given context. | ||||
| @@ -106,3 +106,4 @@ define( | ||||
|  | ||||
| ); | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -21,12 +21,6 @@ | ||||
|  *****************************************************************************/ | ||||
| /*global define*/ | ||||
|  | ||||
| /** | ||||
|  * Defines the PropertiesDialog, used by the PropertiesAction to | ||||
|  * populate the form shown in dialog based on the created type. | ||||
|  * | ||||
|  * @module common/actions/properties-dialog | ||||
|  */ | ||||
| define( | ||||
|     function () { | ||||
|         'use strict'; | ||||
| @@ -37,58 +31,60 @@ define( | ||||
|          * @param {TypeImpl} type the type of domain object for which properties | ||||
|          *        will be specified | ||||
|          * @param {DomainObject} the object for which properties will be set | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          * @memberof module:common/actions/properties-dialog | ||||
|          */ | ||||
|         function PropertiesDialog(type, model) { | ||||
|             var properties = type.getProperties(); | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get sections provided by this dialog. | ||||
|                  * @return {FormStructure} the structure of this form | ||||
|                  */ | ||||
|                 getFormStructure: function () { | ||||
|                     return { | ||||
|                         name: "Edit " + model.name, | ||||
|                         sections: [{ | ||||
|                             name: "Properties", | ||||
|                             rows: properties.map(function (property, index) { | ||||
|                                 // Property definition is same as form row definition | ||||
|                                 var row = Object.create(property.getDefinition()); | ||||
|                                 row.key = index; | ||||
|                                 return row; | ||||
|                             }) | ||||
|                         }] | ||||
|                     }; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Get the initial state of the form shown by this dialog | ||||
|                  * (based on the object model) | ||||
|                  * @returns {object} initial state of the form | ||||
|                  */ | ||||
|                 getInitialFormValue: function () { | ||||
|                     // Start with initial values for properties | ||||
|                     // Note that index needs to correlate to row.key | ||||
|                     // from getFormStructure | ||||
|                     return properties.map(function (property) { | ||||
|                         return property.getValue(model); | ||||
|                     }); | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Update a domain object model based on the value of a form. | ||||
|                  */ | ||||
|                 updateModel: function (model, formValue) { | ||||
|                     // Update all properties | ||||
|                     properties.forEach(function (property, index) { | ||||
|                         property.setValue(model, formValue[index]); | ||||
|                     }); | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|  | ||||
|             this.type = type; | ||||
|             this.model = model; | ||||
|             this.properties = type.getProperties(); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get sections provided by this dialog. | ||||
|          * @return {FormStructure} the structure of this form | ||||
|          */ | ||||
|         PropertiesDialog.prototype.getFormStructure = function () { | ||||
|             return { | ||||
|                 name: "Edit " + this.model.name, | ||||
|                 sections: [{ | ||||
|                     name: "Properties", | ||||
|                     rows: this.properties.map(function (property, index) { | ||||
|                         // Property definition is same as form row definition | ||||
|                         var row = Object.create(property.getDefinition()); | ||||
|                         row.key = index; | ||||
|                         return row; | ||||
|                     }) | ||||
|                 }] | ||||
|             }; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Get the initial state of the form shown by this dialog | ||||
|          * (based on the object model) | ||||
|          * @returns {object} initial state of the form | ||||
|          */ | ||||
|         PropertiesDialog.prototype.getInitialFormValue = function () { | ||||
|             var model = this.model; | ||||
|  | ||||
|             // Start with initial values for properties | ||||
|             // Note that index needs to correlate to row.key | ||||
|             // from getFormStructure | ||||
|             return this.properties.map(function (property) { | ||||
|                 return property.getValue(model); | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Update a domain object model based on the value of a form. | ||||
|          */ | ||||
|         PropertiesDialog.prototype.updateModel = function (model, formValue) { | ||||
|             // Update all properties | ||||
|             this.properties.forEach(function (property, index) { | ||||
|                 property.setValue(model, formValue[index]); | ||||
|             }); | ||||
|         }; | ||||
|  | ||||
|         return PropertiesDialog; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -37,22 +37,35 @@ define( | ||||
|          * | ||||
|          * @param {DomainObject} object the object to be removed | ||||
|          * @param {ActionContext} context the context in which this action is performed | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          * @memberof module:editor/actions/remove-action | ||||
|          * @implements {Action} | ||||
|          */ | ||||
|         function RemoveAction($q, context) { | ||||
|             var object = (context || {}).domainObject; | ||||
|         function RemoveAction($q, navigationService, context) { | ||||
|             this.domainObject = (context || {}).domainObject; | ||||
|             this.$q = $q; | ||||
|             this.navigationService = navigationService; | ||||
|         } | ||||
|  | ||||
|             /** | ||||
|         /** | ||||
|          * Perform this action. | ||||
|          * @return {Promise} a promise which will be | ||||
|          *         fulfilled when the action has completed. | ||||
|          */ | ||||
|         RemoveAction.prototype.perform = function () { | ||||
|             var $q = this.$q, | ||||
|                 navigationService = this.navigationService, | ||||
|                 domainObject = this.domainObject; | ||||
|             /* | ||||
|              * Check whether an object ID matches the ID of the object being | ||||
|              * removed (used to filter a parent's composition to handle the | ||||
|              * removal.) | ||||
|              */ | ||||
|             function isNotObject(otherObjectId) { | ||||
|                 return otherObjectId !== object.getId(); | ||||
|                 return otherObjectId !== domainObject.getId(); | ||||
|             } | ||||
|  | ||||
|             /** | ||||
|             /* | ||||
|              * Mutate a parent object such that it no longer contains the object | ||||
|              * which is being removed. | ||||
|              */ | ||||
| @@ -60,7 +73,7 @@ define( | ||||
|                 model.composition = model.composition.filter(isNotObject); | ||||
|             } | ||||
|  | ||||
|             /** | ||||
|             /* | ||||
|              * Invoke persistence on a domain object. This will be called upon | ||||
|              * the removed object's parent (as its composition will have changed.) | ||||
|              */ | ||||
| @@ -68,34 +81,55 @@ define( | ||||
|                 var persistence = domainObject.getCapability('persistence'); | ||||
|                 return persistence && persistence.persist(); | ||||
|             } | ||||
|  | ||||
|             /** | ||||
|              * Remove the object from its parent, as identified by its context | ||||
|              * capability. | ||||
|              * @param {ContextCapability} contextCapability the "context" capability | ||||
|              *        of the domain object being removed. | ||||
|              | ||||
|             /* | ||||
|              * Checks current object and ascendants of current | ||||
|              * object with object being removed, if the current | ||||
|              * object or any in the current object's path is being removed, | ||||
|              * navigate back to parent of removed object. | ||||
|              */ | ||||
|             function removeFromContext(contextCapability) { | ||||
|                 var parent = contextCapability.getParent(); | ||||
|                 $q.when( | ||||
|             function checkObjectNavigation(object, parentObject) { | ||||
|                 // Traverse object starts at current location | ||||
|                 var traverseObject = (navigationService).getNavigation(); | ||||
|                  | ||||
|                 // Stop when object is not defined (above ROOT) | ||||
|                 while (traverseObject) { | ||||
|                      | ||||
|                     // If object currently traversed to is object being removed | ||||
|                     // navigate to parent of current object and then exit loop | ||||
|                     if (traverseObject.getId() === object.getId()) { | ||||
|                         navigationService.setNavigation(parentObject); | ||||
|                         return; | ||||
|                     } | ||||
|                     // Traverses to parent of current object, moving | ||||
|                     // up the ascendant path | ||||
|                     traverseObject = traverseObject.getCapability('context').getParent(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             /* | ||||
|              * Remove the object from its parent, as identified by its context | ||||
|              * capability. Based on object's location and selected object's location | ||||
|              * user may be navigated to existing parent object | ||||
|              */ | ||||
|             function removeFromContext(object) { | ||||
|                 var contextCapability = object.getCapability('context'), | ||||
|                     parent = contextCapability.getParent(); | ||||
|                  | ||||
|                 // If currently within path of removed object(s), | ||||
|                 // navigates to existing object up tree | ||||
|                 checkObjectNavigation(object, parent); | ||||
|                  | ||||
|                 return $q.when( | ||||
|                     parent.useCapability('mutation', doMutate) | ||||
|                 ).then(function () { | ||||
|                     return doPersist(parent); | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Perform this action. | ||||
|                  * @return {module:core/promises.Promise} a promise which will be | ||||
|                  *         fulfilled when the action has completed. | ||||
|                  */ | ||||
|                 perform: function () { | ||||
|                     return $q.when(object.getCapability('context')) | ||||
|                         .then(removeFromContext); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|             return $q.when(domainObject) | ||||
|                 .then(removeFromContext); | ||||
|         }; | ||||
|  | ||||
|         // Object needs to have a parent for Remove to be applicable | ||||
|         RemoveAction.appliesTo = function (context) { | ||||
| @@ -113,4 +147,4 @@ define( | ||||
|  | ||||
|         return RemoveAction; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -30,9 +30,27 @@ define( | ||||
|          * The "Save" action; the action triggered by clicking Save from | ||||
|          * Edit Mode. Exits the editing user interface and invokes object | ||||
|          * capabilities to persist the changes that have been made. | ||||
|          * @constructor | ||||
|          * @implements {Action} | ||||
|          * @memberof platform/commonUI/edit | ||||
|          */ | ||||
|         function SaveAction($location, urlService, context) { | ||||
|             var domainObject = context.domainObject; | ||||
|             this.domainObject = (context || {}).domainObject; | ||||
|             this.$location = $location; | ||||
|             this.urlService = urlService; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Save changes and conclude editing. | ||||
|          * | ||||
|          * @returns {Promise} a promise that will be fulfilled when | ||||
|          *          cancellation has completed | ||||
|          * @memberof platform/commonUI/edit.SaveAction# | ||||
|          */ | ||||
|         SaveAction.prototype.perform = function () { | ||||
|             var domainObject = this.domainObject, | ||||
|                 $location = this.$location, | ||||
|                 urlService = this.urlService; | ||||
|  | ||||
|             // Invoke any save behavior introduced by the editor capability; | ||||
|             // this is introduced by EditableDomainObject which is | ||||
| @@ -51,18 +69,8 @@ define( | ||||
|                 )); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Save changes and conclude editing. | ||||
|                  * | ||||
|                  * @returns {Promise} a promise that will be fulfilled when | ||||
|                  *          cancellation has completed | ||||
|                  */ | ||||
|                 perform: function () { | ||||
|                     return doSave().then(returnToBrowse); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|             return doSave().then(returnToBrowse); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Check if this action is applicable in a given context. | ||||
| @@ -78,4 +86,4 @@ define( | ||||
|  | ||||
|         return SaveAction; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -35,6 +35,9 @@ define( | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {CompositionCapability} | ||||
|          */ | ||||
|         return function EditableCompositionCapability( | ||||
|             contextCapability, | ||||
| @@ -54,4 +57,4 @@ define( | ||||
|             ); | ||||
|         }; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -35,6 +35,9 @@ define( | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {ContextCapability} | ||||
|          */ | ||||
|         return function EditableContextCapability( | ||||
|             contextCapability, | ||||
| @@ -72,4 +75,4 @@ define( | ||||
|             return capability; | ||||
|         }; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -35,6 +35,8 @@ define( | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          */ | ||||
|         return function EditableLookupCapability( | ||||
|             contextCapability, | ||||
| @@ -76,7 +78,7 @@ define( | ||||
|             // Wrap a returned value (see above); if it's a promise, wrap | ||||
|             // the resolved value. | ||||
|             function wrapResult(result) { | ||||
|                 return result.then ? // promise-like | ||||
|                 return (result && result.then) ? // promise-like | ||||
|                         result.then(makeEditable) : | ||||
|                         makeEditable(result); | ||||
|             } | ||||
| @@ -105,8 +107,10 @@ define( | ||||
|  | ||||
|             // Wrap a method of this capability | ||||
|             function wrapMethod(fn) { | ||||
|                 capability[fn] = | ||||
|                     (idempotent ? oneTimeFunction : wrapFunction)(fn); | ||||
|                 if (typeof capability[fn] === 'function') { | ||||
|                     capability[fn] = | ||||
|                         (idempotent ? oneTimeFunction : wrapFunction)(fn); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Wrap all methods; return only editable domain objects. | ||||
| @@ -115,4 +119,4 @@ define( | ||||
|             return capability; | ||||
|         }; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -35,6 +35,9 @@ define( | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {PersistenceCapability} | ||||
|          */ | ||||
|         function EditablePersistenceCapability( | ||||
|             persistenceCapability, | ||||
| @@ -62,4 +65,4 @@ define( | ||||
|  | ||||
|         return EditablePersistenceCapability; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -35,6 +35,9 @@ define( | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {RelationshipCapability} | ||||
|          */ | ||||
|         return function EditableRelationshipCapability( | ||||
|             relationshipCapability, | ||||
| @@ -54,4 +57,4 @@ define( | ||||
|             ); | ||||
|         }; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -39,27 +39,48 @@ define( | ||||
|          * Meant specifically for use by EditableDomainObject and the | ||||
|          * associated cache; the constructor signature is particular | ||||
|          * to a pattern used there and may contain unused arguments. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          */ | ||||
|         return function EditorCapability( | ||||
|         function EditorCapability( | ||||
|             persistenceCapability, | ||||
|             editableObject, | ||||
|             domainObject, | ||||
|             cache | ||||
|         ) { | ||||
|             this.editableObject = editableObject; | ||||
|             this.domainObject = domainObject; | ||||
|             this.cache = cache; | ||||
|         } | ||||
|  | ||||
|             // Simulate Promise.resolve (or $q.when); the former | ||||
|             // causes a delayed reaction from Angular (since it | ||||
|             // does not trigger a digest) and the latter is not | ||||
|             // readily accessible, since we're a few classes | ||||
|             // removed from the layer which gets dependency | ||||
|             // injection. | ||||
|             function resolvePromise(value) { | ||||
|                 return (value && value.then) ? value : { | ||||
|                     then: function (callback) { | ||||
|                         return resolvePromise(callback(value)); | ||||
|                     } | ||||
|                 }; | ||||
|             } | ||||
|         // Simulate Promise.resolve (or $q.when); the former | ||||
|         // causes a delayed reaction from Angular (since it | ||||
|         // does not trigger a digest) and the latter is not | ||||
|         // readily accessible, since we're a few classes | ||||
|         // removed from the layer which gets dependency | ||||
|         // injection. | ||||
|         function resolvePromise(value) { | ||||
|             return (value && value.then) ? value : { | ||||
|                 then: function (callback) { | ||||
|                     return resolvePromise(callback(value)); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Save any changes that have been made to this domain object | ||||
|          * (as well as to others that might have been retrieved and | ||||
|          * modified during the editing session) | ||||
|          * @param {boolean} nonrecursive if true, save only this | ||||
|          *        object (and not other objects with associated changes) | ||||
|          * @returns {Promise} a promise that will be fulfilled after | ||||
|          *          persistence has completed. | ||||
|          * @memberof platform/commonUI/edit.EditorCapability# | ||||
|          */ | ||||
|         EditorCapability.prototype.save = function (nonrecursive) { | ||||
|             var domainObject = this.domainObject, | ||||
|                 editableObject = this.editableObject, | ||||
|                 cache = this.cache; | ||||
|  | ||||
|             // Update the underlying, "real" domain object's model | ||||
|             // with changes made to the copy used for editing. | ||||
| @@ -74,39 +95,32 @@ define( | ||||
|                 return domainObject.getCapability('persistence').persist(); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Save any changes that have been made to this domain object | ||||
|                  * (as well as to others that might have been retrieved and | ||||
|                  * modified during the editing session) | ||||
|                  * @param {boolean} nonrecursive if true, save only this | ||||
|                  *        object (and not other objects with associated changes) | ||||
|                  * @returns {Promise} a promise that will be fulfilled after | ||||
|                  *          persistence has completed. | ||||
|                  */ | ||||
|                 save: function (nonrecursive) { | ||||
|                     return nonrecursive ? | ||||
|                             resolvePromise(doMutate()).then(doPersist) : | ||||
|                             resolvePromise(cache.saveAll()); | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Cancel editing; Discard any changes that have been made to | ||||
|                  * this domain object (as well as to others that might have | ||||
|                  * been retrieved and modified during the editing session) | ||||
|                  * @returns {Promise} a promise that will be fulfilled after | ||||
|                  *          cancellation has completed. | ||||
|                  */ | ||||
|                 cancel: function () { | ||||
|                     return resolvePromise(undefined); | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Check if there are any unsaved changes. | ||||
|                  * @returns {boolean} true if there are unsaved changes | ||||
|                  */ | ||||
|                 dirty: function () { | ||||
|                     return cache.dirty(); | ||||
|                 } | ||||
|             }; | ||||
|             return nonrecursive ? | ||||
|                 resolvePromise(doMutate()).then(doPersist) : | ||||
|                 resolvePromise(cache.saveAll()); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Cancel editing; Discard any changes that have been made to | ||||
|          * this domain object (as well as to others that might have | ||||
|          * been retrieved and modified during the editing session) | ||||
|          * @returns {Promise} a promise that will be fulfilled after | ||||
|          *          cancellation has completed. | ||||
|          * @memberof platform/commonUI/edit.EditorCapability# | ||||
|          */ | ||||
|         EditorCapability.prototype.cancel = function () { | ||||
|             return resolvePromise(undefined); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Check if there are any unsaved changes. | ||||
|          * @returns {boolean} true if there are unsaved changes | ||||
|          * @memberof platform/commonUI/edit.EditorCapability# | ||||
|          */ | ||||
|         EditorCapability.prototype.dirty = function () { | ||||
|             return this.cache.dirty(); | ||||
|         }; | ||||
|  | ||||
|         return EditorCapability; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -33,6 +33,7 @@ define( | ||||
|  | ||||
|         /** | ||||
|          * Controller which supplies action instances for Save/Cancel. | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          */ | ||||
|         function EditActionController($scope) { | ||||
| @@ -51,4 +52,4 @@ define( | ||||
|  | ||||
|         return EditActionController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -22,7 +22,8 @@ | ||||
| /*global define,Promise*/ | ||||
|  | ||||
| /** | ||||
|  * Module defining EditController. Created by vwoeltje on 11/14/14. | ||||
|  * This bundle implements Edit mode. | ||||
|  * @namespace platform/commonUI/edit | ||||
|  */ | ||||
| define( | ||||
|     ["../objects/EditableDomainObject"], | ||||
| @@ -33,15 +34,16 @@ define( | ||||
|          * Controller which is responsible for populating the scope for | ||||
|          * Edit mode; introduces an editable version of the currently | ||||
|          * navigated domain object into the scope. | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          */ | ||||
|         function EditController($scope, $q, navigationService) { | ||||
|             var navigatedObject; | ||||
|             var self = this; | ||||
|  | ||||
|             function setNavigation(domainObject) { | ||||
|                 // Wrap the domain object such that all mutation is | ||||
|                 // confined to edit mode (until Save) | ||||
|                 navigatedObject = | ||||
|                 self.navigatedDomainObject = | ||||
|                     domainObject && new EditableDomainObject(domainObject, $q); | ||||
|             } | ||||
|  | ||||
| @@ -50,33 +52,39 @@ define( | ||||
|             $scope.$on("$destroy", function () { | ||||
|                 navigationService.removeListener(setNavigation); | ||||
|             }); | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get the domain object which is navigated-to. | ||||
|                  * @returns {DomainObject} the domain object that is navigated-to | ||||
|                  */ | ||||
|                 navigatedObject: function () { | ||||
|                     return navigatedObject; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Get the warning to show if the user attempts to navigate | ||||
|                  * away from Edit mode while unsaved changes are present. | ||||
|                  * @returns {string} the warning to show, or undefined if | ||||
|                  *          there are no unsaved changes | ||||
|                  */ | ||||
|                 getUnloadWarning: function () { | ||||
|                     var editorCapability = navigatedObject && | ||||
|                             navigatedObject.getCapability("editor"), | ||||
|                         hasChanges = editorCapability && editorCapability.dirty(); | ||||
|  | ||||
|                     return hasChanges ? | ||||
|                             "Unsaved changes will be lost if you leave this page." : | ||||
|                             undefined; | ||||
|                 } | ||||
|              | ||||
|             // Provide a model for edit mode | ||||
|             $scope.editModel = { | ||||
|                 selectedObject: navigationService.getNavigation() | ||||
|             }; | ||||
|             $scope.editModel.inspectionObjects = [$scope.editModel.selectedObject]; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get the domain object which is navigated-to. | ||||
|          * @returns {DomainObject} the domain object that is navigated-to | ||||
|          */ | ||||
|         EditController.prototype.navigatedObject = function () { | ||||
|             return this.navigatedDomainObject; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Get the warning to show if the user attempts to navigate | ||||
|          * away from Edit mode while unsaved changes are present. | ||||
|          * @returns {string} the warning to show, or undefined if | ||||
|          *          there are no unsaved changes | ||||
|          */ | ||||
|         EditController.prototype.getUnloadWarning = function () { | ||||
|             var navigatedObject = this.navigatedDomainObject, | ||||
|                 editorCapability = navigatedObject && | ||||
|                     navigatedObject.getCapability("editor"), | ||||
|                 hasChanges = editorCapability && editorCapability.dirty(); | ||||
|  | ||||
|             return hasChanges ? | ||||
|                 "Unsaved changes will be lost if you leave this page." : | ||||
|                 undefined; | ||||
|         }; | ||||
|  | ||||
|         return EditController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -28,15 +28,17 @@ define( | ||||
|  | ||||
|         /** | ||||
|          * Supports the Library and Elements panes in Edit mode. | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          */ | ||||
|         function EditPanesController($scope) { | ||||
|             var root; | ||||
|             var self = this; | ||||
|  | ||||
|             // Update root object based on represented object | ||||
|             function updateRoot(domainObject) { | ||||
|                 var context = domainObject && | ||||
|                     domainObject.getCapability('context'), | ||||
|                 var root = self.rootDomainObject, | ||||
|                     context = domainObject && | ||||
|                         domainObject.getCapability('context'), | ||||
|                     newRoot = context && context.getTrueRoot(), | ||||
|                     oldId = root && root.getId(), | ||||
|                     newId = newRoot && newRoot.getId(); | ||||
| @@ -44,25 +46,22 @@ define( | ||||
|                 // Only update if this has actually changed, | ||||
|                 // to avoid excessive refreshing. | ||||
|                 if (oldId !== newId) { | ||||
|                     root = newRoot; | ||||
|                     self.rootDomainObject = newRoot; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Update root when represented object changes | ||||
|             $scope.$watch('domainObject', updateRoot); | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get the root-level domain object, as reported by the | ||||
|                  * represented domain object. | ||||
|                  * @returns {DomainObject} the root object | ||||
|                  */ | ||||
|                 getRoot: function () { | ||||
|                     return root; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|         /** | ||||
|          * Get the root-level domain object, as reported by the | ||||
|          * represented domain object. | ||||
|          * @returns {DomainObject} the root object | ||||
|          */ | ||||
|         EditPanesController.prototype.getRoot = function () { | ||||
|             return this.rootDomainObject; | ||||
|         }; | ||||
|  | ||||
|         return EditPanesController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -31,6 +31,7 @@ define( | ||||
|          * to this attribute will be evaluated during page navigation events | ||||
|          * and, if it returns a truthy value, will be used to populate a | ||||
|          * prompt to the user to confirm this navigation. | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          * @param $window the window | ||||
|          */ | ||||
| @@ -102,4 +103,4 @@ define( | ||||
|         return MCTBeforeUnload; | ||||
|  | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -68,6 +68,9 @@ define( | ||||
|          * which need to behave differently in edit mode, | ||||
|          * and provides a "working copy" of the object's | ||||
|          * model to allow changes to be easily cancelled. | ||||
|          * @constructor | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {DomainObject} | ||||
|          */ | ||||
|         function EditableDomainObject(domainObject, $q) { | ||||
|             // The cache will hold all domain objects reached from | ||||
| @@ -92,10 +95,10 @@ define( | ||||
|                             this, | ||||
|                             delegateArguments | ||||
|                         ), | ||||
|                         factory = capabilityFactories[name]; | ||||
|                         Factory = capabilityFactories[name]; | ||||
|  | ||||
|                     return (factory && capability) ? | ||||
|                             factory(capability, editableObject, domainObject, cache) : | ||||
|                     return (Factory && capability) ? | ||||
|                             new Factory(capability, editableObject, domainObject, cache) : | ||||
|                             capability; | ||||
|                 }; | ||||
|  | ||||
| @@ -109,4 +112,4 @@ define( | ||||
|  | ||||
|         return EditableDomainObject; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -22,7 +22,7 @@ | ||||
| /*global define*/ | ||||
|  | ||||
|  | ||||
| /** | ||||
| /* | ||||
|  * An editable domain object cache stores domain objects that have been | ||||
|  * made editable, in a group that can be saved all-at-once. This supports | ||||
|  * Edit mode, which is launched for a specific object but may contain | ||||
| @@ -32,8 +32,6 @@ | ||||
|  * to ensure that changes made while in edit mode do not propagate up | ||||
|  * to the objects used in browse mode (or to persistence) until the user | ||||
|  * initiates a Save. | ||||
|  * | ||||
|  * @module editor/object/editable-domain-object-cache | ||||
|  */ | ||||
| define( | ||||
|     ["./EditableModelCache"], | ||||
| @@ -46,107 +44,118 @@ define( | ||||
|          * of objects retrieved via composition or context capabilities as | ||||
|          * editable domain objects. | ||||
|          * | ||||
|          * @param {Constructor<EditableDomainObject>} EditableDomainObject a | ||||
|          * @param {Constructor<DomainObject>} EditableDomainObject a | ||||
|          *        constructor function which takes a regular domain object as | ||||
|          *        an argument, and returns an editable domain object as its | ||||
|          *        result. | ||||
|          * @param $q Angular's $q, for promise handling | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          * @memberof module:editor/object/editable-domain-object-cache | ||||
|          */ | ||||
|         function EditableDomainObjectCache(EditableDomainObject, $q) { | ||||
|             var cache = new EditableModelCache(), | ||||
|                 dirty = {}, | ||||
|                 root; | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Wrap this domain object in an editable form, or pull such | ||||
|                  * an object from the cache if one already exists. | ||||
|                  * | ||||
|                  * @param {DomainObject} domainObject the regular domain object | ||||
|                  * @returns {DomainObject} the domain object in an editable form | ||||
|                  */ | ||||
|                 getEditableObject: function (domainObject) { | ||||
|                     var type = domainObject.getCapability('type'); | ||||
|  | ||||
|                     // Track the top-level domain object; this will have | ||||
|                     // some special behavior for its context capability. | ||||
|                     root = root || domainObject; | ||||
|  | ||||
|                     // Avoid double-wrapping (WTD-1017) | ||||
|                     if (domainObject.hasCapability('editor')) { | ||||
|                         return domainObject; | ||||
|                     } | ||||
|  | ||||
|                     // Don't bother wrapping non-editable objects | ||||
|                     if (!type || !type.hasFeature('creation')) { | ||||
|                         return domainObject; | ||||
|                     } | ||||
|  | ||||
|                     // Provide an editable form of the object | ||||
|                     return new EditableDomainObject( | ||||
|                         domainObject, | ||||
|                         cache.getCachedModel(domainObject) | ||||
|                     ); | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Check if a domain object is (effectively) the top-level | ||||
|                  * object in this editable subgraph. | ||||
|                  * @returns {boolean} true if it is the root | ||||
|                  */ | ||||
|                 isRoot: function (domainObject) { | ||||
|                     return domainObject === root; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Mark an editable domain object (presumably already cached) | ||||
|                  * as having received modifications during editing; it should be | ||||
|                  * included in the bulk save invoked when editing completes. | ||||
|                  * | ||||
|                  * @param {DomainObject} domainObject the domain object | ||||
|                  */ | ||||
|                 markDirty: function (domainObject) { | ||||
|                     dirty[domainObject.getId()] = domainObject; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Mark an object (presumably already cached) as having had its | ||||
|                  * changes saved (and thus no longer needing to be subject to a | ||||
|                  * save operation.) | ||||
|                  * | ||||
|                  * @param {DomainObject} domainObject the domain object | ||||
|                  */ | ||||
|                 markClean: function (domainObject) { | ||||
|                     delete dirty[domainObject.getId()]; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Initiate a save on all objects that have been cached. | ||||
|                  */ | ||||
|                 saveAll: function () { | ||||
|                     // Get a list of all dirty objects | ||||
|                     var objects = Object.keys(dirty).map(function (k) { | ||||
|                         return dirty[k]; | ||||
|                     }); | ||||
|  | ||||
|                     // Clear dirty set, since we're about to save. | ||||
|                     dirty = {}; | ||||
|  | ||||
|                     // Most save logic is handled by the "editor.completion" | ||||
|                     // capability, so that is delegated here. | ||||
|                     return $q.all(objects.map(function (object) { | ||||
|                         // Save; pass a nonrecursive flag to avoid looping | ||||
|                         return object.getCapability('editor').save(true); | ||||
|                     })); | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Check if any objects have been marked dirty in this cache. | ||||
|                  * @returns {boolean} true if objects are dirty | ||||
|                  */ | ||||
|                 dirty: function () { | ||||
|                     return Object.keys(dirty).length > 0; | ||||
|                 } | ||||
|             }; | ||||
|             this.cache = new EditableModelCache(); | ||||
|             this.dirtyObjects = {}; | ||||
|             this.root = undefined; | ||||
|             this.$q = $q; | ||||
|             this.EditableDomainObject = EditableDomainObject; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Wrap this domain object in an editable form, or pull such | ||||
|          * an object from the cache if one already exists. | ||||
|          * | ||||
|          * @param {DomainObject} domainObject the regular domain object | ||||
|          * @returns {DomainObject} the domain object in an editable form | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.getEditableObject = function (domainObject) { | ||||
|             var type = domainObject.getCapability('type'), | ||||
|                 EditableDomainObject = this.EditableDomainObject; | ||||
|  | ||||
|             // Track the top-level domain object; this will have | ||||
|             // some special behavior for its context capability. | ||||
|             this.root = this.root || domainObject; | ||||
|  | ||||
|             // Avoid double-wrapping (WTD-1017) | ||||
|             if (domainObject.hasCapability('editor')) { | ||||
|                 return domainObject; | ||||
|             } | ||||
|  | ||||
|             // Don't bother wrapping non-editable objects | ||||
|             if (!type || !type.hasFeature('creation')) { | ||||
|                 return domainObject; | ||||
|             } | ||||
|  | ||||
|             // Provide an editable form of the object | ||||
|             return new EditableDomainObject( | ||||
|                 domainObject, | ||||
|                 this.cache.getCachedModel(domainObject) | ||||
|             ); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Check if a domain object is (effectively) the top-level | ||||
|          * object in this editable subgraph. | ||||
|          * @returns {boolean} true if it is the root | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.isRoot = function (domainObject) { | ||||
|             return domainObject === this.root; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Mark an editable domain object (presumably already cached) | ||||
|          * as having received modifications during editing; it should be | ||||
|          * included in the bulk save invoked when editing completes. | ||||
|          * | ||||
|          * @param {DomainObject} domainObject the domain object | ||||
|          * @memberof platform/commonUI/edit.EditableDomainObjectCache# | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.markDirty = function (domainObject) { | ||||
|             this.dirtyObjects[domainObject.getId()] = domainObject; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Mark an object (presumably already cached) as having had its | ||||
|          * changes saved (and thus no longer needing to be subject to a | ||||
|          * save operation.) | ||||
|          * | ||||
|          * @param {DomainObject} domainObject the domain object | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.markClean = function (domainObject) { | ||||
|             delete this.dirtyObjects[domainObject.getId()]; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Initiate a save on all objects that have been cached. | ||||
|          * @return {Promise} A promise which will resolve when all objects are | ||||
|          *         persisted. | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.saveAll = function () { | ||||
|             // Get a list of all dirty objects | ||||
|             var dirty = this.dirtyObjects, | ||||
|                 objects = Object.keys(dirty).map(function (k) { | ||||
|                     return dirty[k]; | ||||
|                 }); | ||||
|  | ||||
|             // Clear dirty set, since we're about to save. | ||||
|             this.dirtyObjects = {}; | ||||
|  | ||||
|             // Most save logic is handled by the "editor.completion" | ||||
|             // capability, so that is delegated here. | ||||
|             return this.$q.all(objects.map(function (object) { | ||||
|                 // Save; pass a nonrecursive flag to avoid looping | ||||
|                 return object.getCapability('editor').save(true); | ||||
|             })); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Check if any objects have been marked dirty in this cache. | ||||
|          * @returns {boolean} true if objects are dirty | ||||
|          */ | ||||
|         EditableDomainObjectCache.prototype.dirty = function () { | ||||
|             return Object.keys(this.dirtyObjects).length > 0; | ||||
|         }; | ||||
|  | ||||
|         return EditableDomainObjectCache; | ||||
|     } | ||||
| ); | ||||
|  | ||||
|   | ||||
| @@ -31,33 +31,32 @@ define( | ||||
|          * made editable, to support a group that can be saved all-at-once. | ||||
|          * This is useful in Edit mode, which is launched for a specific | ||||
|          * object but may contain changes across many objects. | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          */ | ||||
|         function EditableModelCache() { | ||||
|             var cache = {}; | ||||
|  | ||||
|             // Deep-copy a model. Models are JSONifiable, so this can be | ||||
|             // done by stringification then destringification | ||||
|             function clone(model) { | ||||
|                 return JSON.parse(JSON.stringify(model)); | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get this domain object's model from the cache (or | ||||
|                  * place it in the cache if it isn't in the cache yet) | ||||
|                  * @returns a clone of the domain object's model | ||||
|                  */ | ||||
|                 getCachedModel: function (domainObject) { | ||||
|                     var id = domainObject.getId(); | ||||
|  | ||||
|                     return (cache[id] = | ||||
|                         cache[id] || clone(domainObject.getModel())); | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|             this.cache = {}; | ||||
|         } | ||||
|  | ||||
|         // Deep-copy a model. Models are JSONifiable, so this can be | ||||
|         // done by stringification then destringification | ||||
|         function clone(model) { | ||||
|             return JSON.parse(JSON.stringify(model)); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get this domain object's model from the cache (or | ||||
|          * place it in the cache if it isn't in the cache yet) | ||||
|          * @returns a clone of the domain object's model | ||||
|          */ | ||||
|         EditableModelCache.prototype.getCachedModel = function (domainObject) { | ||||
|             var id = domainObject.getId(), | ||||
|                 cache = this.cache; | ||||
|  | ||||
|             return (cache[id] = | ||||
|                 cache[id] || clone(domainObject.getModel())); | ||||
|         }; | ||||
|  | ||||
|         return EditableModelCache; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -30,53 +30,47 @@ define( | ||||
|          * Policy controlling when the `edit` and/or `properties` actions | ||||
|          * can appear as applicable actions of the `view-control` category | ||||
|          * (shown as buttons in the top-right of browse mode.) | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          * @implements {Policy.<Action, ActionContext>} | ||||
|          */ | ||||
|         function EditActionPolicy() { | ||||
|             // Get a count of views which are not flagged as non-editable. | ||||
|             function countEditableViews(context) { | ||||
|                 var domainObject = (context || {}).domainObject, | ||||
|                     views = domainObject && domainObject.useCapability('view'), | ||||
|                     count = 0; | ||||
|         } | ||||
|  | ||||
|                 // A view is editable unless explicitly flagged as not | ||||
|                 (views || []).forEach(function (view) { | ||||
|                     count += (view.editable !== false) ? 1 : 0; | ||||
|                 }); | ||||
|         // Get a count of views which are not flagged as non-editable. | ||||
|         function countEditableViews(context) { | ||||
|             var domainObject = (context || {}).domainObject, | ||||
|                 views = domainObject && domainObject.useCapability('view'), | ||||
|                 count = 0; | ||||
|  | ||||
|                 return count; | ||||
|             // A view is editable unless explicitly flagged as not | ||||
|             (views || []).forEach(function (view) { | ||||
|                 count += (view.editable !== false) ? 1 : 0; | ||||
|             }); | ||||
|  | ||||
|             return count; | ||||
|         } | ||||
|  | ||||
|         EditActionPolicy.prototype.allow = function (action, context) { | ||||
|             var key = action.getMetadata().key, | ||||
|                 category = (context || {}).category; | ||||
|  | ||||
|             // Only worry about actions in the view-control category | ||||
|             if (category === 'view-control') { | ||||
|                 // Restrict 'edit' to cases where there are editable | ||||
|                 // views (similarly, restrict 'properties' to when | ||||
|                 // the converse is true) | ||||
|                 if (key === 'edit') { | ||||
|                     return countEditableViews(context) > 0; | ||||
|                 } else if (key === 'properties') { | ||||
|                     return countEditableViews(context) < 1; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Check whether or not a given action is allowed by this | ||||
|                  * policy. | ||||
|                  * @param {Action} action the action | ||||
|                  * @param context the context | ||||
|                  * @returns {boolean} true if not disallowed | ||||
|                  */ | ||||
|                 allow: function (action, context) { | ||||
|                     var key = action.getMetadata().key, | ||||
|                         category = (context || {}).category; | ||||
|  | ||||
|                     // Only worry about actions in the view-control category | ||||
|                     if (category === 'view-control') { | ||||
|                         // Restrict 'edit' to cases where there are editable | ||||
|                         // views (similarly, restrict 'properties' to when | ||||
|                         // the converse is true) | ||||
|                         if (key === 'edit') { | ||||
|                             return countEditableViews(context) > 0; | ||||
|                         } else if (key === 'properties') { | ||||
|                             return countEditableViews(context) < 1; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     // Like all policies, allow by default. | ||||
|                     return true; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|             // Like all policies, allow by default. | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
|         return EditActionPolicy; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -28,30 +28,24 @@ define( | ||||
|  | ||||
|         /** | ||||
|          * Policy controlling which views should be visible in Edit mode. | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          * @implements {Policy.<View, DomainObject>} | ||||
|          */ | ||||
|         function EditableViewPolicy() { | ||||
|             return { | ||||
|                 /** | ||||
|                  * Check whether or not a given action is allowed by this | ||||
|                  * policy. | ||||
|                  * @param {Action} action the action | ||||
|                  * @param domainObject the domain object which will be viewed | ||||
|                  * @returns {boolean} true if not disallowed | ||||
|                  */ | ||||
|                 allow: function (view, domainObject) { | ||||
|                     // If a view is flagged as non-editable, only allow it | ||||
|                     // while we're not in Edit mode. | ||||
|                     if ((view || {}).editable === false) { | ||||
|                         return !domainObject.hasCapability('editor'); | ||||
|                     } | ||||
|  | ||||
|                     // Like all policies, allow by default. | ||||
|                     return true; | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         EditableViewPolicy.prototype.allow = function (view, domainObject) { | ||||
|             // If a view is flagged as non-editable, only allow it | ||||
|             // while we're not in Edit mode. | ||||
|             if ((view || {}).editable === false) { | ||||
|                 return !domainObject.hasCapability('editor'); | ||||
|             } | ||||
|  | ||||
|             // Like all policies, allow by default. | ||||
|             return true; | ||||
|         }; | ||||
|  | ||||
|         return EditableViewPolicy; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -41,14 +41,17 @@ define( | ||||
|          * and may be reused for different domain objects and/or | ||||
|          * representations resulting from changes there. | ||||
|          * | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @implements {Representer} | ||||
|          * @constructor | ||||
|          */ | ||||
|         function EditRepresenter($q, $log, scope) { | ||||
|             var domainObject, | ||||
|                 key; | ||||
|             var self = this; | ||||
|  | ||||
|             // Mutate and persist a new version of a domain object's model. | ||||
|             function doPersist(model) { | ||||
|                 var domainObject = self.domainObject; | ||||
|  | ||||
|                 // First, mutate; then, persist. | ||||
|                 return $q.when(domainObject.useCapability("mutation", function () { | ||||
|                     return model; | ||||
| @@ -64,7 +67,8 @@ define( | ||||
|                 // Look up from scope; these will have been populated by | ||||
|                 // mct-representation. | ||||
|                 var model = scope.model, | ||||
|                     configuration = scope.configuration; | ||||
|                     configuration = scope.configuration, | ||||
|                     domainObject = self.domainObject; | ||||
|  | ||||
|                 // Log the commit message | ||||
|                 $log.debug([ | ||||
| @@ -78,50 +82,33 @@ define( | ||||
|                 if (domainObject && domainObject.hasCapability("persistence")) { | ||||
|                     // Configurations for specific views are stored by | ||||
|                     // key in the "configuration" field of the model. | ||||
|                     if (key && configuration) { | ||||
|                     if (self.key && configuration) { | ||||
|                         model.configuration = model.configuration || {}; | ||||
|                         model.configuration[key] = configuration; | ||||
|                         model.configuration[self.key] = configuration; | ||||
|                     } | ||||
|                     doPersist(model); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Respond to the destruction of the current representation. | ||||
|             function destroy() { | ||||
|                 // Nothing to clean up | ||||
|             } | ||||
|  | ||||
|             // Handle a specific representation of a specific domain object | ||||
|             function represent(representation, representedObject) { | ||||
|                 // Track the key, to know which view configuration to save to. | ||||
|                 key = (representation || {}).key; | ||||
|                 // Track the represented object | ||||
|                 domainObject = representedObject; | ||||
|                 // Ensure existing watches are released | ||||
|                 destroy(); | ||||
|             } | ||||
|  | ||||
|             // Place the "commit" method in the scope | ||||
|             scope.commit = commit; | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Set the current representation in use, and the domain | ||||
|                  * object being represented. | ||||
|                  * | ||||
|                  * @param {RepresentationDefinition} representation the | ||||
|                  *        definition of the representation in use | ||||
|                  * @param {DomainObject} domainObject the domain object | ||||
|                  *        being represented | ||||
|                  */ | ||||
|                 represent: represent, | ||||
|                 /** | ||||
|                  * Release any resources associated with this representer. | ||||
|                  */ | ||||
|                 destroy: destroy | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         // Handle a specific representation of a specific domain object | ||||
|         EditRepresenter.prototype.represent = function represent(representation, representedObject) { | ||||
|             // Track the key, to know which view configuration to save to. | ||||
|             this.key = (representation || {}).key; | ||||
|             // Track the represented object | ||||
|             this.domainObject = representedObject; | ||||
|             // Ensure existing watches are released | ||||
|             this.destroy(); | ||||
|         }; | ||||
|  | ||||
|         // Respond to the destruction of the current representation. | ||||
|         EditRepresenter.prototype.destroy = function destroy() { | ||||
|             // Nothing to clean up | ||||
|         }; | ||||
|  | ||||
|         return EditRepresenter; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -38,125 +38,23 @@ define( | ||||
|          * | ||||
|          * @param structure toolbar structure, as provided by view definition | ||||
|          * @param {Function} commit callback to invoke after changes | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          */ | ||||
|         function EditToolbar(structure, commit) { | ||||
|             var toolbarStructure = Object.create(structure || {}), | ||||
|                 toolbarState, | ||||
|                 selection, | ||||
|                 properties = []; | ||||
|             var self = this; | ||||
|  | ||||
|             // Generate a new key for an item's property | ||||
|             function addKey(property) { | ||||
|                 properties.push(property); | ||||
|                 return properties.length - 1; // Return index of property | ||||
|             } | ||||
|  | ||||
|             // Update value for this property in all elements of the | ||||
|             // selection which have this property. | ||||
|             function updateProperties(property, value) { | ||||
|                 var changed = false; | ||||
|  | ||||
|                 // Update property in a selected element | ||||
|                 function updateProperty(selected) { | ||||
|                     // Ignore selected elements which don't have this property | ||||
|                     if (selected[property] !== undefined) { | ||||
|                         // Check if this is a setter, or just assignable | ||||
|                         if (typeof selected[property] === 'function') { | ||||
|                             changed = | ||||
|                                 changed || (selected[property]() !== value); | ||||
|                             selected[property](value); | ||||
|                         } else { | ||||
|                             changed = | ||||
|                                 changed || (selected[property] !== value); | ||||
|                             selected[property] = value; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 // Update property in all selected elements | ||||
|                 selection.forEach(updateProperty); | ||||
|  | ||||
|                 // Return whether or not anything changed | ||||
|                 return changed; | ||||
|             } | ||||
|  | ||||
|             // Look up the current value associated with a property | ||||
|             // in selection i | ||||
|             function lookupState(property, selected) { | ||||
|                 var value = selected[property]; | ||||
|                 return (typeof value === 'function') ? value() : value; | ||||
|             } | ||||
|  | ||||
|             // Get initial value for a given property | ||||
|             function initializeState(property) { | ||||
|                 var result; | ||||
|                 // Look through all selections for this property; | ||||
|                 // values should all match by the time we perform | ||||
|                 // this lookup anyway. | ||||
|                 selection.forEach(function (selected) { | ||||
|                     result = (selected[property] !== undefined) ? | ||||
|                             lookupState(property, selected) : | ||||
|                             result; | ||||
|                 }); | ||||
|                 return result; | ||||
|             } | ||||
|  | ||||
|             // Check if all elements of the selection which have this | ||||
|             // property have the same value for this property. | ||||
|             function isConsistent(property) { | ||||
|                 var consistent = true, | ||||
|                     observed = false, | ||||
|                     state; | ||||
|  | ||||
|                 // Check if a given element of the selection is consistent | ||||
|                 // with previously-observed elements for this property. | ||||
|                 function checkConsistency(selected) { | ||||
|                     var next; | ||||
|                     // Ignore selections which don't have this property | ||||
|                     if (selected[property] !== undefined) { | ||||
|                         // Look up state of this element in the selection | ||||
|                         next = lookupState(property, selected); | ||||
|                         // Detect inconsistency | ||||
|                         if (observed) { | ||||
|                             consistent = consistent && (next === state); | ||||
|                         } | ||||
|                         // Track state for next iteration | ||||
|                         state = next; | ||||
|                         observed = true; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 // Iterate through selections | ||||
|                 selection.forEach(checkConsistency); | ||||
|  | ||||
|                 return consistent; | ||||
|             } | ||||
|  | ||||
|             // Used to filter out items which are applicable (or not) | ||||
|             // to the current selection. | ||||
|             function isApplicable(item) { | ||||
|                 var property = (item || {}).property, | ||||
|                     method = (item || {}).method, | ||||
|                     exclusive = !!(item || {}).exclusive; | ||||
|  | ||||
|                 // Check if a selected item defines this property | ||||
|                 function hasProperty(selected) { | ||||
|                     return (property && (selected[property] !== undefined)) || | ||||
|                             (method && (typeof selected[method] === 'function')); | ||||
|                 } | ||||
|  | ||||
|                 return selection.map(hasProperty).reduce( | ||||
|                     exclusive ? and : or, | ||||
|                     exclusive | ||||
|                 ) && isConsistent(property); | ||||
|                 self.properties.push(property); | ||||
|                 return self.properties.length - 1; // Return index of property | ||||
|             } | ||||
|  | ||||
|             // Invoke all functions in selections with the given name | ||||
|             function invoke(method, value) { | ||||
|                 if (method) { | ||||
|                     // Make the change in the selection | ||||
|                     selection.forEach(function (selected) { | ||||
|                     self.selection.forEach(function (selected) { | ||||
|                         if (typeof selected[method] === 'function') { | ||||
|                             selected[method](value); | ||||
|                         } | ||||
| @@ -189,73 +87,172 @@ define( | ||||
|                 return converted; | ||||
|             } | ||||
|  | ||||
|             this.toolbarState = []; | ||||
|             this.selection = undefined; | ||||
|             this.properties = []; | ||||
|             this.toolbarStructure = Object.create(structure || {}); | ||||
|             this.toolbarStructure.sections = | ||||
|                 ((structure || {}).sections || []).map(convertSection); | ||||
|         } | ||||
|  | ||||
|         // Check if all elements of the selection which have this | ||||
|         // property have the same value for this property. | ||||
|         EditToolbar.prototype.isConsistent = function (property) { | ||||
|             var self = this, | ||||
|                 consistent = true, | ||||
|                 observed = false, | ||||
|                 state; | ||||
|  | ||||
|             // Check if a given element of the selection is consistent | ||||
|             // with previously-observed elements for this property. | ||||
|             function checkConsistency(selected) { | ||||
|                 var next; | ||||
|                 // Ignore selections which don't have this property | ||||
|                 if (selected[property] !== undefined) { | ||||
|                     // Look up state of this element in the selection | ||||
|                     next = self.lookupState(property, selected); | ||||
|                     // Detect inconsistency | ||||
|                     if (observed) { | ||||
|                         consistent = consistent && (next === state); | ||||
|                     } | ||||
|                     // Track state for next iteration | ||||
|                     state = next; | ||||
|                     observed = true; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Iterate through selections | ||||
|             self.selection.forEach(checkConsistency); | ||||
|  | ||||
|             return consistent; | ||||
|         }; | ||||
|  | ||||
|         // Used to filter out items which are applicable (or not) | ||||
|         // to the current selection. | ||||
|         EditToolbar.prototype.isApplicable = function (item) { | ||||
|             var property = (item || {}).property, | ||||
|                 method = (item || {}).method, | ||||
|                 exclusive = !!(item || {}).exclusive; | ||||
|  | ||||
|             // Check if a selected item defines this property | ||||
|             function hasProperty(selected) { | ||||
|                 return (property && (selected[property] !== undefined)) || | ||||
|                     (method && (typeof selected[method] === 'function')); | ||||
|             } | ||||
|  | ||||
|             return this.selection.map(hasProperty).reduce( | ||||
|                     exclusive ? and : or, | ||||
|                     exclusive | ||||
|                 ) && this.isConsistent(property); | ||||
|         }; | ||||
|  | ||||
|  | ||||
|         // Look up the current value associated with a property | ||||
|         EditToolbar.prototype.lookupState = function (property, selected) { | ||||
|             var value = selected[property]; | ||||
|             return (typeof value === 'function') ? value() : value; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Set the current selection. Visibility of sections | ||||
|          * and items in the toolbar will be updated to match this. | ||||
|          * @param {Array} s the new selection | ||||
|          */ | ||||
|         EditToolbar.prototype.setSelection = function (s) { | ||||
|             var self = this; | ||||
|  | ||||
|             // Show/hide controls in this section per applicability | ||||
|             function refreshSectionApplicability(section) { | ||||
|                 var count = 0; | ||||
|                 // Show/hide each item | ||||
|                 (section.items || []).forEach(function (item) { | ||||
|                     item.hidden = !isApplicable(item); | ||||
|                     item.hidden = !self.isApplicable(item); | ||||
|                     count += item.hidden ? 0 : 1; | ||||
|                 }); | ||||
|                 // Hide this section if there are no applicable items | ||||
|                 section.hidden = !count; | ||||
|             } | ||||
|  | ||||
|             // Show/hide controls if they are applicable | ||||
|             function refreshApplicability() { | ||||
|                 toolbarStructure.sections.forEach(refreshSectionApplicability); | ||||
|             // Get initial value for a given property | ||||
|             function initializeState(property) { | ||||
|                 var result; | ||||
|                 // Look through all selections for this property; | ||||
|                 // values should all match by the time we perform | ||||
|                 // this lookup anyway. | ||||
|                 self.selection.forEach(function (selected) { | ||||
|                     result = (selected[property] !== undefined) ? | ||||
|                         self.lookupState(property, selected) : | ||||
|                         result; | ||||
|                 }); | ||||
|                 return result; | ||||
|             } | ||||
|  | ||||
|             // Refresh toolbar state to match selection | ||||
|             function refreshState() { | ||||
|                 toolbarState = properties.map(initializeState); | ||||
|             } | ||||
|             this.selection = s; | ||||
|             this.toolbarStructure.sections.forEach(refreshSectionApplicability); | ||||
|             this.toolbarState = this.properties.map(initializeState); | ||||
|         }; | ||||
|  | ||||
|             toolbarStructure.sections = | ||||
|                 ((structure || {}).sections || []).map(convertSection); | ||||
|         /** | ||||
|          * Get the structure of the toolbar, as appropriate to | ||||
|          * pass to `mct-toolbar`. | ||||
|          * @returns the toolbar structure | ||||
|          */ | ||||
|         EditToolbar.prototype.getStructure = function () { | ||||
|             return this.toolbarStructure; | ||||
|         }; | ||||
|  | ||||
|             toolbarState = []; | ||||
|         /** | ||||
|          * Get the current state of the toolbar, as appropriate | ||||
|          * to two-way bind to the state handled by `mct-toolbar`. | ||||
|          * @returns {Array} state of the toolbar | ||||
|          */ | ||||
|         EditToolbar.prototype.getState = function () { | ||||
|             return this.toolbarState; | ||||
|         }; | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Set the current selection. Visisbility of sections | ||||
|                  * and items in the toolbar will be updated to match this. | ||||
|                  * @param {Array} s the new selection | ||||
|                  */ | ||||
|                 setSelection: function (s) { | ||||
|                     selection = s; | ||||
|                     refreshApplicability(); | ||||
|                     refreshState(); | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Get the structure of the toolbar, as appropriate to | ||||
|                  * pass to `mct-toolbar`. | ||||
|                  * @returns the toolbar structure | ||||
|                  */ | ||||
|                 getStructure: function () { | ||||
|                     return toolbarStructure; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Get the current state of the toolbar, as appropriate | ||||
|                  * to two-way bind to the state handled by `mct-toolbar`. | ||||
|                  * @returns {Array} state of the toolbar | ||||
|                  */ | ||||
|                 getState: function () { | ||||
|                     return toolbarState; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Update state within the current selection. | ||||
|                  * @param {number} index the index of the corresponding | ||||
|                  *        element in the state array | ||||
|                  * @param value the new value to convey to the selection | ||||
|                  */ | ||||
|                 updateState: function (index, value) { | ||||
|                     return updateProperties(properties[index], value); | ||||
|         /** | ||||
|          * Update state within the current selection. | ||||
|          * @param {number} index the index of the corresponding | ||||
|          *        element in the state array | ||||
|          * @param value the new value to convey to the selection | ||||
|          */ | ||||
|         EditToolbar.prototype.updateState = function (index, value) { | ||||
|             var self = this; | ||||
|  | ||||
|             // Update value for this property in all elements of the | ||||
|             // selection which have this property. | ||||
|             function updateProperties(property, value) { | ||||
|                 var changed = false; | ||||
|  | ||||
|                 // Update property in a selected element | ||||
|                 function updateProperty(selected) { | ||||
|                     // Ignore selected elements which don't have this property | ||||
|                     if (selected[property] !== undefined) { | ||||
|                         // Check if this is a setter, or just assignable | ||||
|                         if (typeof selected[property] === 'function') { | ||||
|                             changed = | ||||
|                                 changed || (selected[property]() !== value); | ||||
|                             selected[property](value); | ||||
|                         } else { | ||||
|                             changed = | ||||
|                                 changed || (selected[property] !== value); | ||||
|                             selected[property] = value; | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|                 // Update property in all selected elements | ||||
|                 self.selection.forEach(updateProperty); | ||||
|  | ||||
|                 // Return whether or not anything changed | ||||
|                 return changed; | ||||
|             } | ||||
|  | ||||
|             return updateProperties(this.properties[index], value); | ||||
|         }; | ||||
|  | ||||
|         return EditToolbar; | ||||
|     } | ||||
| ); | ||||
|  | ||||
|  | ||||
|   | ||||
| @@ -27,17 +27,21 @@ define( | ||||
|         "use strict"; | ||||
|  | ||||
|         // No operation | ||||
|         function noop() {} | ||||
|         var NOOP_REPRESENTER = { | ||||
|             represent: function () {}, | ||||
|             destroy: function () {} | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * The EditToolbarRepresenter populates the toolbar in Edit mode | ||||
|          * based on a view's definition. | ||||
|          * @param {Scope} scope the Angular scope of the representation | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          * @implements {Representer} | ||||
|          */ | ||||
|         function EditToolbarRepresenter(scope, element, attrs) { | ||||
|             var toolbar, | ||||
|                 toolbarObject = {}; | ||||
|             var self = this; | ||||
|  | ||||
|             // Mark changes as ready to persist | ||||
|             function commit(message) { | ||||
| @@ -49,31 +53,33 @@ define( | ||||
|             // Handle changes to the current selection | ||||
|             function updateSelection(selection) { | ||||
|                 // Only update if there is a toolbar to update | ||||
|                 if (toolbar) { | ||||
|                 if (self.toolbar) { | ||||
|                     // Make sure selection is array-like | ||||
|                     selection = Array.isArray(selection) ? | ||||
|                             selection : | ||||
|                             (selection ? [selection] : []); | ||||
|  | ||||
|                     // Update the toolbar's selection | ||||
|                     toolbar.setSelection(selection); | ||||
|                     self.toolbar.setSelection(selection); | ||||
|  | ||||
|                     // ...and expose its structure/state | ||||
|                     toolbarObject.structure = toolbar.getStructure(); | ||||
|                     toolbarObject.state = toolbar.getState(); | ||||
|                     self.toolbarObject.structure = | ||||
|                         self.toolbar.getStructure(); | ||||
|                     self.toolbarObject.state = | ||||
|                         self.toolbar.getState(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Get state (to watch it) | ||||
|             function getState() { | ||||
|                 return toolbarObject.state; | ||||
|                 return self.toolbarObject.state; | ||||
|             } | ||||
|  | ||||
|             // Update selection models to match changed toolbar state | ||||
|             function updateState(state) { | ||||
|                 // Update underlying state based on toolbar changes | ||||
|                 var changed = (state || []).map(function (value, index) { | ||||
|                     return toolbar.updateState(index, value); | ||||
|                     return self.toolbar.updateState(index, value); | ||||
|                 }).reduce(function (a, b) { | ||||
|                     return a || b; | ||||
|                 }, false); | ||||
| @@ -85,66 +91,73 @@ define( | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Initialize toolbar (expose object to parent scope) | ||||
|             function initialize(definition) { | ||||
|                 // If we have been asked to expose toolbar state... | ||||
|                 if (attrs.toolbar) { | ||||
|                     // Initialize toolbar object | ||||
|                     toolbar = new EditToolbar(definition, commit); | ||||
|                     // Ensure toolbar state is exposed | ||||
|                     scope.$parent[attrs.toolbar] = toolbarObject; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Represent a domain object using this definition | ||||
|             function represent(representation) { | ||||
|                 // Get the newest toolbar definition from the view | ||||
|                 var definition = (representation || {}).toolbar || {}; | ||||
|                 // Expose the toolbar object to the parent scope | ||||
|                 initialize(definition); | ||||
|                 // Create a selection scope | ||||
|                 scope.selection = new EditToolbarSelection(); | ||||
|                 // Initialize toolbar to an empty selection | ||||
|                 updateSelection([]); | ||||
|             } | ||||
|  | ||||
|             // Destroy; remove toolbar object from parent scope | ||||
|             function destroy() { | ||||
|             // Avoid attaching scope to this; | ||||
|             // http://errors.angularjs.org/1.2.26/ng/cpws | ||||
|             this.setSelection = function (s) { | ||||
|                 scope.selection = s; | ||||
|             }; | ||||
|             this.clearExposedToolbar = function () { | ||||
|                 // Clear exposed toolbar state (if any) | ||||
|                 if (attrs.toolbar) { | ||||
|                     delete scope.$parent[attrs.toolbar]; | ||||
|                 } | ||||
|             } | ||||
|             }; | ||||
|             this.exposeToolbar = function () { | ||||
|                 scope.$parent[self.attrs.toolbar] = self.toolbarObject; | ||||
|             }; | ||||
|  | ||||
|             this.commit = commit; | ||||
|             this.attrs = attrs; | ||||
|             this.updateSelection = updateSelection; | ||||
|             this.toolbar = undefined; | ||||
|             this.toolbarObject = {}; | ||||
|  | ||||
|             // If this representation exposes a toolbar, set up watches | ||||
|             // to synchronize with it. | ||||
|             if (attrs.toolbar) { | ||||
|             if (attrs && attrs.toolbar) { | ||||
|                 // Detect and handle changes to state from the toolbar | ||||
|                 scope.$watchCollection(getState, updateState); | ||||
|                 // Watch for changes in the current selection state | ||||
|                 scope.$watchCollection("selection.all()", updateSelection); | ||||
|                 // Expose toolbar state under that name | ||||
|                 scope.$parent[attrs.toolbar] = toolbarObject; | ||||
|                 scope.$parent[attrs.toolbar] = this.toolbarObject; | ||||
|             } else { | ||||
|                 // No toolbar declared, so do nothing. | ||||
|                 return NOOP_REPRESENTER; | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Set the current representation in use, and the domain | ||||
|                  * object being represented. | ||||
|                  * | ||||
|                  * @param {RepresentationDefinition} representation the | ||||
|                  *        definition of the representation in use | ||||
|                  * @param {DomainObject} domainObject the domain object | ||||
|                  *        being represented | ||||
|                  */ | ||||
|                 represent: (attrs || {}).toolbar ? represent : noop, | ||||
|                 /** | ||||
|                  * Release any resources associated with this representer. | ||||
|                  */ | ||||
|                 destroy: (attrs || {}).toolbar ? destroy : noop | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         // Represent a domain object using this definition | ||||
|         EditToolbarRepresenter.prototype.represent = function (representation) { | ||||
|             // Get the newest toolbar definition from the view | ||||
|             var definition = (representation || {}).toolbar || {}, | ||||
|                 self = this; | ||||
|  | ||||
|             // Initialize toolbar (expose object to parent scope) | ||||
|             function initialize(definition) { | ||||
|                 // If we have been asked to expose toolbar state... | ||||
|                 if (self.attrs.toolbar) { | ||||
|                     // Initialize toolbar object | ||||
|                     self.toolbar = new EditToolbar(definition, self.commit); | ||||
|                     // Ensure toolbar state is exposed | ||||
|                     self.exposeToolbar(); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Expose the toolbar object to the parent scope | ||||
|             initialize(definition); | ||||
|             // Create a selection scope | ||||
|             this.setSelection(new EditToolbarSelection()); | ||||
|             // Initialize toolbar to an empty selection | ||||
|             this.updateSelection([]); | ||||
|         }; | ||||
|  | ||||
|         // Destroy; remove toolbar object from parent scope | ||||
|         EditToolbarRepresenter.prototype.destroy = function () { | ||||
|             this.clearExposedToolbar(); | ||||
|         }; | ||||
|  | ||||
|         return EditToolbarRepresenter; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -37,110 +37,96 @@ define( | ||||
|          * * The selection, for single selected elements within the | ||||
|          *   view. | ||||
|          * | ||||
|          * @memberof platform/commonUI/edit | ||||
|          * @constructor | ||||
|          */ | ||||
|         function EditToolbarSelection() { | ||||
|             var selection = [ {} ], | ||||
|                 selecting = false, | ||||
|                 selected; | ||||
|             this.selection = [{}]; | ||||
|             this.selecting = false; | ||||
|             this.selectedObj = undefined; | ||||
|         } | ||||
|  | ||||
|             // Remove the currently-selected object | ||||
|             function deselect() { | ||||
|                 // Nothing to do if we don't have a selected object | ||||
|                 if (selecting) { | ||||
|                     // Clear state tracking | ||||
|                     selecting = false; | ||||
|                     selected = undefined; | ||||
|         /** | ||||
|          * Check if an object is currently selected. | ||||
|          * @param {*} obj the object to check for selection | ||||
|          * @returns {boolean} true if selected, otherwise false | ||||
|          */ | ||||
|         EditToolbarSelection.prototype.selected = function (obj) { | ||||
|             return (obj === this.selectedObj) || (obj === this.selection[0]); | ||||
|         }; | ||||
|  | ||||
|                     // Remove the selection | ||||
|                     selection.pop(); | ||||
|  | ||||
|                     return true; | ||||
|                 } | ||||
|         /** | ||||
|          * Select an object. | ||||
|          * @param obj the object to select | ||||
|          * @returns {boolean} true if selection changed | ||||
|          */ | ||||
|         EditToolbarSelection.prototype.select = function (obj) { | ||||
|             // Proxy is always selected | ||||
|             if (obj === this.selection[0]) { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             // Select an object | ||||
|             function select(obj) { | ||||
|                 // Proxy is always selected | ||||
|                 if (obj === selection[0]) { | ||||
|                     return false; | ||||
|                 } | ||||
|             // Clear any existing selection | ||||
|             this.deselect(); | ||||
|  | ||||
|                 // Clear any existing selection | ||||
|                 deselect(); | ||||
|             // Note the current selection state | ||||
|             this.selectedObj = obj; | ||||
|             this.selecting = true; | ||||
|  | ||||
|                 // Note the current selection state | ||||
|                 selected = obj; | ||||
|                 selecting = true; | ||||
|             // Add the selection | ||||
|             this.selection.push(obj); | ||||
|         }; | ||||
|  | ||||
|                 // Add the selection | ||||
|                 selection.push(obj); | ||||
|         /** | ||||
|          * Clear the current selection. | ||||
|          * @returns {boolean} true if selection changed | ||||
|          */ | ||||
|         EditToolbarSelection.prototype.deselect = function () { | ||||
|             // Nothing to do if we don't have a selected object | ||||
|             if (this.selecting) { | ||||
|                 // Clear state tracking | ||||
|                 this.selecting = false; | ||||
|                 this.selectedObj = undefined; | ||||
|  | ||||
|                 // Remove the selection | ||||
|                 this.selection.pop(); | ||||
|  | ||||
|                 return true; | ||||
|             } | ||||
|             return false; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Get the currently-selected object. | ||||
|          * @returns the currently selected object | ||||
|          */ | ||||
|         EditToolbarSelection.prototype.get = function () { | ||||
|             return this.selectedObj; | ||||
|         }; | ||||
|  | ||||
|             // Check if an object is selected | ||||
|             function isSelected(obj) { | ||||
|                 return (obj === selected) || (obj === selection[0]); | ||||
|         /** | ||||
|          * Get/set the view proxy (for toolbar actions taken upon | ||||
|          * the view itself.) | ||||
|          * @param [proxy] the view proxy (if setting) | ||||
|          * @returns the current view proxy | ||||
|          */ | ||||
|         EditToolbarSelection.prototype.proxy = function (p) { | ||||
|             if (arguments.length > 0) { | ||||
|                 this.selection[0] = p; | ||||
|             } | ||||
|             return this.selection[0]; | ||||
|         }; | ||||
|  | ||||
|             // Getter for current selection | ||||
|             function get() { | ||||
|                 return selected; | ||||
|             } | ||||
|  | ||||
|             // Getter/setter for view proxy | ||||
|             function proxy(p) { | ||||
|                 if (arguments.length > 0) { | ||||
|                     selection[0] = p; | ||||
|                 } | ||||
|                 return selection[0]; | ||||
|             } | ||||
|  | ||||
|             // Getter for the full array of selected objects (incl. view proxy) | ||||
|             function all() { | ||||
|                 return selection; | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Check if an object is currently selected. | ||||
|                  * @returns true if selected, otherwise false | ||||
|                  */ | ||||
|                 selected: isSelected, | ||||
|                 /** | ||||
|                  * Select an object. | ||||
|                  * @param obj the object to select | ||||
|                  * @returns {boolean} true if selection changed | ||||
|                  */ | ||||
|                 select: select, | ||||
|                 /** | ||||
|                  * Clear the current selection. | ||||
|                  * @returns {boolean} true if selection changed | ||||
|                  */ | ||||
|                 deselect: deselect, | ||||
|                 /** | ||||
|                  * Get the currently-selected object. | ||||
|                  * @returns the currently selected object | ||||
|                  */ | ||||
|                 get: get, | ||||
|                 /** | ||||
|                  * Get/set the view proxy (for toolbar actions taken upon | ||||
|                  * the view itself.) | ||||
|                  * @param [proxy] the view proxy (if setting) | ||||
|                  * @returns the current view proxy | ||||
|                  */ | ||||
|                 proxy: proxy, | ||||
|                 /** | ||||
|                  * Get an array containing all selections, including the | ||||
|                  * selection proxy. It is generally not advisable to | ||||
|                  * mutate this array directly. | ||||
|                  * @returns {Array} all selections | ||||
|                  */ | ||||
|                 all: all | ||||
|             }; | ||||
|         } | ||||
|         /** | ||||
|          * Get an array containing all selections, including the | ||||
|          * selection proxy. It is generally not advisable to | ||||
|          * mutate this array directly. | ||||
|          * @returns {Array} all selections | ||||
|          */ | ||||
|         EditToolbarSelection.prototype.all = function () { | ||||
|             return this.selection; | ||||
|         }; | ||||
|  | ||||
|         return EditToolbarSelection; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -28,9 +28,16 @@ define( | ||||
|  | ||||
|         describe("The Remove action", function () { | ||||
|             var mockQ, | ||||
|                 mockNavigationService, | ||||
|                 mockDomainObject, | ||||
|                 mockParent, | ||||
|                 mockChildObject, | ||||
|                 mockGrandchildObject, | ||||
|                 mockRootObject, | ||||
|                 mockContext, | ||||
|                 mockChildContext, | ||||
|                 mockGrandchildContext, | ||||
|                 mockRootContext, | ||||
|                 mockMutation, | ||||
|                 mockPersistence, | ||||
|                 mockType, | ||||
| @@ -54,6 +61,18 @@ define( | ||||
|                     "domainObject", | ||||
|                     [ "getId", "getCapability" ] | ||||
|                 ); | ||||
|                 mockChildObject = jasmine.createSpyObj( | ||||
|                     "domainObject", | ||||
|                     [ "getId", "getCapability" ] | ||||
|                 ); | ||||
|                 mockGrandchildObject = jasmine.createSpyObj( | ||||
|                     "domainObject", | ||||
|                     [ "getId", "getCapability" ] | ||||
|                 ); | ||||
|                 mockRootObject = jasmine.createSpyObj( | ||||
|                     "domainObject", | ||||
|                     [ "getId", "getCapability" ] | ||||
|                 ); | ||||
|                 mockQ = { when: mockPromise }; | ||||
|                 mockParent = { | ||||
|                     getModel: function () { | ||||
| @@ -67,28 +86,41 @@ define( | ||||
|                     } | ||||
|                 }; | ||||
|                 mockContext = jasmine.createSpyObj("context", [ "getParent" ]); | ||||
|                 mockChildContext = jasmine.createSpyObj("context", [ "getParent" ]); | ||||
|                 mockGrandchildContext = jasmine.createSpyObj("context", [ "getParent" ]); | ||||
|                 mockRootContext = jasmine.createSpyObj("context", [ "getParent" ]); | ||||
|                 mockMutation = jasmine.createSpyObj("mutation", [ "invoke" ]); | ||||
|                 mockPersistence = jasmine.createSpyObj("persistence", [ "persist" ]); | ||||
|                 mockType = jasmine.createSpyObj("type", [ "hasFeature" ]); | ||||
|  | ||||
|                 mockNavigationService = jasmine.createSpyObj( | ||||
|                     "navigationService", | ||||
|                     [ | ||||
|                         "getNavigation", | ||||
|                         "setNavigation", | ||||
|                         "addListener", | ||||
|                         "removeListener" | ||||
|                     ] | ||||
|                 ); | ||||
|                 mockNavigationService.getNavigation.andReturn(mockDomainObject); | ||||
|                  | ||||
|                  | ||||
|                 mockDomainObject.getId.andReturn("test"); | ||||
|                 mockDomainObject.getCapability.andReturn(mockContext); | ||||
|                 mockContext.getParent.andReturn(mockParent); | ||||
|                 mockType.hasFeature.andReturn(true); | ||||
|  | ||||
|  | ||||
|                 capabilities = { | ||||
|                     mutation: mockMutation, | ||||
|                     persistence: mockPersistence, | ||||
|                     type: mockType | ||||
|                 }; | ||||
|                 model = { | ||||
|                     composition: [ "a", "test", "b", "c" ] | ||||
|                     composition: [ "a", "test", "b" ] | ||||
|                 }; | ||||
|  | ||||
|                 actionContext = { domainObject: mockDomainObject }; | ||||
|  | ||||
|                 action = new RemoveAction(mockQ, actionContext); | ||||
|                 action = new RemoveAction(mockQ, mockNavigationService, actionContext); | ||||
|             }); | ||||
|  | ||||
|             it("only applies to objects with parents", function () { | ||||
| @@ -123,11 +155,64 @@ define( | ||||
|  | ||||
|                 // Should have removed "test" - that was our | ||||
|                 // mock domain object's id. | ||||
|                 expect(result.composition).toEqual(["a", "b", "c"]); | ||||
|                 expect(result.composition).toEqual(["a", "b"]); | ||||
|  | ||||
|                 // Finally, should have persisted | ||||
|                 expect(mockPersistence.persist).toHaveBeenCalled(); | ||||
|             }); | ||||
|              | ||||
|             it("removes parent of object currently navigated to", function () { | ||||
|                 // Navigates to child object | ||||
|                 mockNavigationService.getNavigation.andReturn(mockChildObject); | ||||
|                  | ||||
|                 // Test is id of object being removed | ||||
|                 // Child object has different id | ||||
|                 mockDomainObject.getId.andReturn("test"); | ||||
|                 mockChildObject.getId.andReturn("not test"); | ||||
|                  | ||||
|                 // Sets context for the child and domainObject | ||||
|                 mockDomainObject.getCapability.andReturn(mockContext); | ||||
|                 mockChildObject.getCapability.andReturn(mockChildContext); | ||||
|                  | ||||
|                 // Parents of child and domainObject are set | ||||
|                 mockContext.getParent.andReturn(mockParent); | ||||
|                 mockChildContext.getParent.andReturn(mockDomainObject); | ||||
|                  | ||||
|                 mockType.hasFeature.andReturn(true); | ||||
|                  | ||||
|                 action.perform(); | ||||
|                  | ||||
|                 // Expects navigation to parent of domainObject (removed object) | ||||
|                 expect(mockNavigationService.setNavigation).toHaveBeenCalledWith(mockParent); | ||||
|             }); | ||||
|              | ||||
|             it("checks if removing object not in ascendent path (reaches ROOT)", function () { | ||||
|                 // Navigates to grandchild of ROOT | ||||
|                 mockNavigationService.getNavigation.andReturn(mockGrandchildObject); | ||||
|                  | ||||
|                 // domainObject (grandparent) is set as ROOT, child and grandchild | ||||
|                 // are set objects not being removed | ||||
|                 mockDomainObject.getId.andReturn("test 1"); | ||||
|                 mockRootObject.getId.andReturn("ROOT"); | ||||
|                 mockChildObject.getId.andReturn("not test 2"); | ||||
|                 mockGrandchildObject.getId.andReturn("not test 3"); | ||||
|                  | ||||
|                 // Sets context for the grandchild, child, and domainObject | ||||
|                 mockRootObject.getCapability.andReturn(mockRootContext); | ||||
|                 mockChildObject.getCapability.andReturn(mockChildContext); | ||||
|                 mockGrandchildObject.getCapability.andReturn(mockGrandchildContext); | ||||
|                  | ||||
|                 // Parents of grandchild and child are set | ||||
|                 mockChildContext.getParent.andReturn(mockRootObject); | ||||
|                 mockGrandchildContext.getParent.andReturn(mockChildObject); | ||||
|                  | ||||
|                 mockType.hasFeature.andReturn(true); | ||||
|                  | ||||
|                 action.perform(); | ||||
|                  | ||||
|                 // Expects no navigation to occur | ||||
|                 expect(mockNavigationService.setNavigation).not.toHaveBeenCalled(); | ||||
|             }); | ||||
|  | ||||
|         }); | ||||
|     } | ||||
|   | ||||
| @@ -112,7 +112,9 @@ define( | ||||
|             }); | ||||
|  | ||||
|             it("saves objects that have been marked dirty", function () { | ||||
|                 var objects = ['a', 'b', 'c'].map(TestObject).map(cache.getEditableObject); | ||||
|                 var objects = ['a', 'b', 'c'].map(TestObject).map(function (domainObject) { | ||||
|                     return cache.getEditableObject(domainObject); | ||||
|                 }); | ||||
|  | ||||
|                 cache.markDirty(objects[0]); | ||||
|                 cache.markDirty(objects[2]); | ||||
| @@ -123,7 +125,9 @@ define( | ||||
|             }); | ||||
|  | ||||
|             it("does not save objects that have been marked clean", function () { | ||||
|                 var objects = ['a', 'b', 'c'].map(TestObject).map(cache.getEditableObject); | ||||
|                 var objects = ['a', 'b', 'c'].map(TestObject).map(function (domainObject) { | ||||
|                     return cache.getEditableObject(domainObject); | ||||
|                 }); | ||||
|  | ||||
|                 cache.markDirty(objects[0]); | ||||
|                 cache.markDirty(objects[2]); | ||||
|   | ||||
| @@ -104,6 +104,11 @@ | ||||
|                 "key": "SelectorController", | ||||
|                 "implementation": "controllers/SelectorController.js", | ||||
|                 "depends": [ "objectService", "$scope" ] | ||||
|             }, | ||||
|             { | ||||
|                 "key": "ObjectInspectorController", | ||||
|                 "implementation": "controllers/ObjectInspectorController.js", | ||||
|                 "depends": [ "$scope", "objectService" ] | ||||
|             } | ||||
|         ], | ||||
|         "directives": [ | ||||
| @@ -196,7 +201,7 @@ | ||||
|             { | ||||
|                 "key": "label", | ||||
|                 "templateUrl": "templates/label.html", | ||||
|                 "uses": [ "type" ], | ||||
|                 "uses": [ "type", "location" ], | ||||
|                 "gestures": [ "drag", "menu", "info" ] | ||||
|             }, | ||||
|             { | ||||
| @@ -219,6 +224,10 @@ | ||||
|                 "key": "switcher", | ||||
|                 "templateUrl": "templates/controls/switcher.html", | ||||
|                 "uses": [ "view" ] | ||||
|             }, | ||||
|             { | ||||
|               "key": "object-inspector", | ||||
|               "templateUrl": "templates/object-inspector.html" | ||||
|             } | ||||
|         ], | ||||
|         "controls": [ | ||||
|   | ||||
| @@ -69,6 +69,7 @@ | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| /*********************************************** FORM ELEMENTS */ | ||||
| /* | ||||
| @mixin invokeMenu($baseColor: $colorBodyFg) { | ||||
| 	$c: $baseColor; | ||||
| @@ -182,27 +183,21 @@ | ||||
|       line-height: 14px; | ||||
|       margin-right: 5px; } | ||||
|     /* line 89, ../sass/forms/_elems.scss */ | ||||
|     .form .form-row .controls input[type="text"] { | ||||
|       height: 22px; | ||||
|       line-height: 22px; | ||||
|       margin-top: -4px; | ||||
|       vertical-align: baseline; } | ||||
|     /* line 96, ../sass/forms/_elems.scss */ | ||||
|     .form .form-row .controls .l-med input[type="text"] { | ||||
|       width: 200px; } | ||||
|     /* line 100, ../sass/forms/_elems.scss */ | ||||
|     /* line 93, ../sass/forms/_elems.scss */ | ||||
|     .form .form-row .controls .l-small input[type="text"] { | ||||
|       width: 50px; } | ||||
|     /* line 104, ../sass/forms/_elems.scss */ | ||||
|     /* line 97, ../sass/forms/_elems.scss */ | ||||
|     .form .form-row .controls .l-numeric input[type="text"] { | ||||
|       text-align: right; } | ||||
|     /* line 108, ../sass/forms/_elems.scss */ | ||||
|     /* line 101, ../sass/forms/_elems.scss */ | ||||
|     .form .form-row .controls .select { | ||||
|       margin-right: 5px; } | ||||
|   /* line 113, ../sass/forms/_elems.scss */ | ||||
|   /* line 106, ../sass/forms/_elems.scss */ | ||||
|   .form .form-row .field-hints { | ||||
|     color: #666666; } | ||||
|   /* line 117, ../sass/forms/_elems.scss */ | ||||
|   /* line 110, ../sass/forms/_elems.scss */ | ||||
|   .form .form-row .selector-list { | ||||
|     -moz-border-radius: 2px; | ||||
|     -webkit-border-radius: 2px; | ||||
| @@ -215,7 +210,7 @@ | ||||
|     position: relative; | ||||
|     height: 150px; | ||||
|     overflow: auto; } | ||||
|     /* line 128, ../sass/forms/_elems.scss */ | ||||
|     /* line 121, ../sass/forms/_elems.scss */ | ||||
|     .form .form-row .selector-list .wrapper { | ||||
|       overflow-y: auto; | ||||
|       position: absolute; | ||||
| @@ -224,24 +219,24 @@ | ||||
|       bottom: 5px; | ||||
|       left: 5px; } | ||||
|  | ||||
| /* line 142, ../sass/forms/_elems.scss */ | ||||
| /* line 135, ../sass/forms/_elems.scss */ | ||||
| label.form-control.checkbox input { | ||||
|   margin-right: 5px; | ||||
|   vertical-align: top; } | ||||
|  | ||||
| /* line 148, ../sass/forms/_elems.scss */ | ||||
| /* line 141, ../sass/forms/_elems.scss */ | ||||
| .hint, | ||||
| .s-hint { | ||||
|   font-size: 0.9em; } | ||||
|  | ||||
| /* line 153, ../sass/forms/_elems.scss */ | ||||
| /* line 146, ../sass/forms/_elems.scss */ | ||||
| .l-result { | ||||
|   display: inline-block; | ||||
|   min-width: 32px; | ||||
|   min-height: 32px; | ||||
|   position: relative; | ||||
|   vertical-align: top; } | ||||
|   /* line 160, ../sass/forms/_elems.scss */ | ||||
|   /* line 153, ../sass/forms/_elems.scss */ | ||||
|   .l-result div.s-hint { | ||||
|     -moz-border-radius: 2px; | ||||
|     -webkit-border-radius: 2px; | ||||
| @@ -276,18 +271,17 @@ label.form-control.checkbox input { | ||||
| .edit-main textarea { | ||||
|   -moz-appearance: none; | ||||
|   -webkit-appearance: none; | ||||
|   -moz-border-radius: 2px; | ||||
|   -webkit-border-radius: 2px; | ||||
|   border-radius: 2px; | ||||
|   -moz-border-radius: 3px; | ||||
|   -webkit-border-radius: 3px; | ||||
|   border-radius: 3px; | ||||
|   -moz-box-sizing: border-box; | ||||
|   -webkit-box-sizing: border-box; | ||||
|   box-sizing: border-box; | ||||
|   -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; | ||||
|   -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; | ||||
|   box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; | ||||
|   -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; | ||||
|   -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; | ||||
|   box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; | ||||
|   background: rgba(255, 255, 255, 0.1); | ||||
|   border: none; | ||||
|   border-bottom: 1px solid rgba(255, 255, 255, 0.1); | ||||
|   color: #cccccc; | ||||
|   outline: none; | ||||
|   padding: 5px; | ||||
| @@ -323,18 +317,17 @@ label.form-control.checkbox input { | ||||
| input[type="text"] { | ||||
|   -moz-appearance: none; | ||||
|   -webkit-appearance: none; | ||||
|   -moz-border-radius: 2px; | ||||
|   -webkit-border-radius: 2px; | ||||
|   border-radius: 2px; | ||||
|   -moz-border-radius: 3px; | ||||
|   -webkit-border-radius: 3px; | ||||
|   border-radius: 3px; | ||||
|   -moz-box-sizing: border-box; | ||||
|   -webkit-box-sizing: border-box; | ||||
|   box-sizing: border-box; | ||||
|   -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; | ||||
|   -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; | ||||
|   box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; | ||||
|   -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; | ||||
|   -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; | ||||
|   box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; | ||||
|   background: rgba(255, 255, 255, 0.1); | ||||
|   border: none; | ||||
|   border-bottom: 1px solid rgba(255, 255, 255, 0.1); | ||||
|   color: #cccccc; | ||||
|   outline: none; | ||||
|   padding: 0 3px; } | ||||
| @@ -374,9 +367,9 @@ input[type="text"] { | ||||
|   background-image: -moz-linear-gradient(#525252, #454545); | ||||
|   background-image: -webkit-linear-gradient(#525252, #454545); | ||||
|   background-image: linear-gradient(#525252, #454545); | ||||
|   -moz-border-radius: 2px; | ||||
|   -webkit-border-radius: 2px; | ||||
|   border-radius: 2px; | ||||
|   -moz-border-radius: 3px; | ||||
|   -webkit-border-radius: 3px; | ||||
|   border-radius: 3px; | ||||
|   -moz-box-sizing: border-box; | ||||
|   -webkit-box-sizing: border-box; | ||||
|   box-sizing: border-box; | ||||
| @@ -463,18 +456,17 @@ input[type="text"] { | ||||
| .channel-selector .treeview { | ||||
|   -moz-appearance: none; | ||||
|   -webkit-appearance: none; | ||||
|   -moz-border-radius: 2px; | ||||
|   -webkit-border-radius: 2px; | ||||
|   border-radius: 2px; | ||||
|   -moz-border-radius: 3px; | ||||
|   -webkit-border-radius: 3px; | ||||
|   border-radius: 3px; | ||||
|   -moz-box-sizing: border-box; | ||||
|   -webkit-box-sizing: border-box; | ||||
|   box-sizing: border-box; | ||||
|   -moz-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; | ||||
|   -webkit-box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; | ||||
|   box-shadow: inset rgba(0, 0, 0, 0.5) 0 1px 5px; | ||||
|   -moz-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; | ||||
|   -webkit-box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; | ||||
|   box-shadow: inset rgba(0, 0, 0, 0.65) 0 1px 4px; | ||||
|   background: rgba(255, 255, 255, 0.1); | ||||
|   border: none; | ||||
|   border-bottom: 1px solid rgba(255, 255, 255, 0.1); | ||||
|   color: #cccccc; | ||||
|   outline: none; | ||||
|   padding: 0 3px; | ||||
|   | ||||
| @@ -69,6 +69,7 @@ | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| /*********************************************** FORM ELEMENTS */ | ||||
| /* | ||||
| @mixin invokeMenu($baseColor: $colorBodyFg) { | ||||
| 	$c: $baseColor; | ||||
| @@ -115,9 +116,9 @@ | ||||
|     background-image: -moz-linear-gradient(#5e5e5e, #525252); | ||||
|     background-image: -webkit-linear-gradient(#5e5e5e, #525252); | ||||
|     background-image: linear-gradient(#5e5e5e, #525252); | ||||
|     -moz-border-radius: 2px; | ||||
|     -webkit-border-radius: 2px; | ||||
|     border-radius: 2px; | ||||
|     -moz-border-radius: 3px; | ||||
|     -webkit-border-radius: 3px; | ||||
|     border-radius: 3px; | ||||
|     -moz-box-sizing: border-box; | ||||
|     -webkit-box-sizing: border-box; | ||||
|     box-sizing: border-box; | ||||
| @@ -255,9 +256,9 @@ | ||||
|       background-image: -moz-linear-gradient(#0ac2ff, #00b4f0); | ||||
|       background-image: -webkit-linear-gradient(#0ac2ff, #00b4f0); | ||||
|       background-image: linear-gradient(#0ac2ff, #00b4f0); | ||||
|       -moz-border-radius: 2px; | ||||
|       -webkit-border-radius: 2px; | ||||
|       border-radius: 2px; | ||||
|       -moz-border-radius: 3px; | ||||
|       -webkit-border-radius: 3px; | ||||
|       border-radius: 3px; | ||||
|       -moz-box-sizing: border-box; | ||||
|       -webkit-box-sizing: border-box; | ||||
|       box-sizing: border-box; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -69,6 +69,7 @@ | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| /*********************************************** FORM ELEMENTS */ | ||||
| /* | ||||
| @mixin invokeMenu($baseColor: $colorBodyFg) { | ||||
| 	$c: $baseColor; | ||||
| @@ -103,7 +104,7 @@ | ||||
| ul.tree { | ||||
|   margin: 0; | ||||
|   padding: 0; } | ||||
|   /* line 276, ../sass/_mixins.scss */ | ||||
|   /* line 308, ../sass/_mixins.scss */ | ||||
|   ul.tree li { | ||||
|     list-style-type: none; | ||||
|     margin: 0; | ||||
| @@ -123,8 +124,8 @@ ul.tree { | ||||
|       transition: background-color 0.25s; | ||||
|       display: block; | ||||
|       font-size: 0.8em; | ||||
|       height: 1.4rem; | ||||
|       line-height: 1.4rem; | ||||
|       height: 1.5rem; | ||||
|       line-height: 1.5rem; | ||||
|       margin-bottom: 3px; | ||||
|       position: relative; } | ||||
|       /* line 39, ../sass/tree/_tree.scss */ | ||||
| @@ -249,3 +250,249 @@ ul.tree { | ||||
|   /* line 154, ../sass/tree/_tree.scss */ | ||||
|   ul.tree ul.tree { | ||||
|     margin-left: 15px; } | ||||
|  | ||||
| /***************************************************************************** | ||||
|  * Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT Web is licensed under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0. | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
|  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
|  * License for the specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  * | ||||
|  * Open MCT Web includes source code licensed under additional open source | ||||
|  * licenses. See the Open Source Licenses file (LICENSES.md) included with | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
| /* line 23, ../sass/search/_search.scss */ | ||||
| .abs.search-holder { | ||||
|   height: 25px; | ||||
|   bottom: 0; | ||||
|   z-index: 5; } | ||||
|   /* line 27, ../sass/search/_search.scss */ | ||||
|   .abs.search-holder.active { | ||||
|     height: auto; | ||||
|     bottom: 0; } | ||||
|  | ||||
| /* line 38, ../sass/search/_search.scss */ | ||||
| .search { | ||||
|   display: flex; | ||||
|   flex-direction: column; | ||||
|   height: 100%; } | ||||
|   /* line 49, ../sass/search/_search.scss */ | ||||
|   .search .search-bar { | ||||
|     font-size: 0.8em; | ||||
|     position: relative; | ||||
|     width: 100%; } | ||||
|     /* line 66, ../sass/search/_search.scss */ | ||||
|     .search .search-bar .search-input { | ||||
|       height: 25px; | ||||
|       line-height: 25px; | ||||
|       padding-top: 0; | ||||
|       padding-bottom: 0; } | ||||
|     /* line 73, ../sass/search/_search.scss */ | ||||
|     .search .search-bar .search-icon, | ||||
|     .search .search-bar .clear-icon, | ||||
|     .search .search-bar .menu-icon { | ||||
|       -moz-box-sizing: border-box; | ||||
|       -webkit-box-sizing: border-box; | ||||
|       box-sizing: border-box; | ||||
|       color: #737373; | ||||
|       height: 17px; | ||||
|       width: 17px; | ||||
|       line-height: 17px; | ||||
|       position: absolute; | ||||
|       text-align: center; | ||||
|       top: 4px; } | ||||
|     /* line 86, ../sass/search/_search.scss */ | ||||
|     .search .search-bar .clear-icon, | ||||
|     .search .search-bar .menu-icon { | ||||
|       cursor: pointer; | ||||
|       transition: color .25s; } | ||||
|     /* line 93, ../sass/search/_search.scss */ | ||||
|     .search .search-bar .search-input { | ||||
|       position: relative; | ||||
|       width: 100%; | ||||
|       padding-left: 22px !important; | ||||
|       padding-right: 44px !important; } | ||||
|       /* line 100, ../sass/search/_search.scss */ | ||||
|       .search .search-bar .search-input input { | ||||
|         width: 100%; } | ||||
|     /* line 105, ../sass/search/_search.scss */ | ||||
|     .search .search-bar .search-icon { | ||||
|       color: #737373; | ||||
|       left: 3px; | ||||
|       transition: visibility .15s, opacity .15s, color .2s; | ||||
|       pointer-events: none; } | ||||
|     /* line 125, ../sass/search/_search.scss */ | ||||
|     .search .search-bar .search-input:hover + div.search-icon { | ||||
|       color: #a6a6a6; } | ||||
|     /* line 129, ../sass/search/_search.scss */ | ||||
|     .search .search-bar .clear-icon { | ||||
|       right: 22px; | ||||
|       visibility: hidden; | ||||
|       opacity: 0; | ||||
|       transition: visibility .15s, opacity .15s, color .2s; } | ||||
|       /* line 138, ../sass/search/_search.scss */ | ||||
|       .search .search-bar .clear-icon.content { | ||||
|         visibility: visible; | ||||
|         opacity: 1; } | ||||
|       /* line 143, ../sass/search/_search.scss */ | ||||
|       .search .search-bar .clear-icon:hover { | ||||
|         color: #a6a6a6; } | ||||
|     /* line 148, ../sass/search/_search.scss */ | ||||
|     .search .search-bar .menu-icon { | ||||
|       font-size: 0.8em; | ||||
|       padding-right: 4px; | ||||
|       right: 4px; | ||||
|       text-align: right; } | ||||
|       /* line 154, ../sass/search/_search.scss */ | ||||
|       .search .search-bar .menu-icon:hover { | ||||
|         color: #a6a6a6; } | ||||
|     /* line 159, ../sass/search/_search.scss */ | ||||
|     .search .search-bar .search-menu-holder { | ||||
|       float: right; | ||||
|       left: -20px; | ||||
|       z-index: 1; | ||||
|       transition: visibility .05s, opacity .05s; } | ||||
|       /* line 169, ../sass/search/_search.scss */ | ||||
|       .search .search-bar .search-menu-holder.off { | ||||
|         visibility: hidden; | ||||
|         opacity: 0; } | ||||
|     /* line 176, ../sass/search/_search.scss */ | ||||
|     .search .search-bar .menu-icon:hover + div.search-menu-holder { | ||||
|       visibility: visible; } | ||||
|     /* line 179, ../sass/search/_search.scss */ | ||||
|     .search .search-bar div.search-menu-holder:hover { | ||||
|       visibility: visible; } | ||||
|   /* line 184, ../sass/search/_search.scss */ | ||||
|   .search .active-filter-display { | ||||
|     -moz-border-radius: 2px; | ||||
|     -webkit-border-radius: 2px; | ||||
|     border-radius: 2px; | ||||
|     -moz-box-sizing: border-box; | ||||
|     -webkit-box-sizing: border-box; | ||||
|     box-sizing: border-box; | ||||
|     line-height: 130%; | ||||
|     padding: 5px 0; | ||||
|     padding-left: 1.4625em; | ||||
|     font-size: 0.65em; | ||||
|     margin-top: 3px; } | ||||
|     /* line 199, ../sass/search/_search.scss */ | ||||
|     .search .active-filter-display .clear-filters-icon { | ||||
|       opacity: 0.4; | ||||
|       font-size: 0.8em; | ||||
|       position: absolute; | ||||
|       left: 1px; | ||||
|       cursor: pointer; } | ||||
|     /* line 210, ../sass/search/_search.scss */ | ||||
|     .search .active-filter-display.off { | ||||
|       visibility: hidden; | ||||
|       opacity: 0; | ||||
|       height: 0; | ||||
|       margin: 0; | ||||
|       padding: 0; | ||||
|       border: 0; } | ||||
|   /* line 220, ../sass/search/_search.scss */ | ||||
|   .search .search-scroll { | ||||
|     order: 3; | ||||
|     margin-top: 4px; | ||||
|     overflow-y: auto; | ||||
|     top: auto; | ||||
|     height: auto; | ||||
|     max-height: 100%; | ||||
|     position: relative; } | ||||
|     /* line 235, ../sass/search/_search.scss */ | ||||
|     .search .search-scroll .results .search-result-item { | ||||
|       -moz-transition: background-color 0.25s; | ||||
|       -o-transition: background-color 0.25s; | ||||
|       -webkit-transition: background-color 0.25s; | ||||
|       transition: background-color 0.25s; | ||||
|       margin-bottom: 2px; | ||||
|       border-radius: 2px; | ||||
|       padding-top: 4px; | ||||
|       padding-bottom: 2px; } | ||||
|       /* line 249, ../sass/search/_search.scss */ | ||||
|       .search .search-scroll .results .search-result-item .label { | ||||
|         margin-left: 6px; } | ||||
|         /* line 253, ../sass/search/_search.scss */ | ||||
|         .search .search-scroll .results .search-result-item .label .title-label { | ||||
|           display: inline-block; | ||||
|           position: absolute; | ||||
|           left: 29px; | ||||
|           right: 5px; | ||||
|           font-size: .8em; | ||||
|           line-height: 17px; | ||||
|           width: auto; | ||||
|           overflow: hidden; | ||||
|           text-overflow: ellipsis; | ||||
|           white-space: nowrap; } | ||||
|       /* line 275, ../sass/search/_search.scss */ | ||||
|       .search .search-scroll .results .search-result-item.selected { | ||||
|         background: #005177; | ||||
|         color: #fff; } | ||||
|         /* line 279, ../sass/search/_search.scss */ | ||||
|         .search .search-scroll .results .search-result-item.selected .view-control { | ||||
|           color: #0099cc; } | ||||
|         /* line 282, ../sass/search/_search.scss */ | ||||
|         .search .search-scroll .results .search-result-item.selected .label .type-icon { | ||||
|           color: #fff; } | ||||
|       /* line 287, ../sass/search/_search.scss */ | ||||
|       .search .search-scroll .results .search-result-item .label .type-icon .l-icon-link { | ||||
|         display: none; | ||||
|         text-shadow: black 0 1px 2px; | ||||
|         z-index: 2; | ||||
|         color: #49dedb; | ||||
|         font-size: 8px; | ||||
|         line-height: 8px; | ||||
|         height: 8px; | ||||
|         width: 8px; | ||||
|         margin-left: -25px; } | ||||
|       /* line 299, ../sass/search/_search.scss */ | ||||
|       .search .search-scroll .results .search-result-item:not(.selected):hover { | ||||
|         background: #404040; | ||||
|         color: #cccccc; } | ||||
|         /* line 302, ../sass/search/_search.scss */ | ||||
|         .search .search-scroll .results .search-result-item:not(.selected):hover .context-trigger { | ||||
|           display: block; } | ||||
|         /* line 305, ../sass/search/_search.scss */ | ||||
|         .search .search-scroll .results .search-result-item:not(.selected):hover .icon { | ||||
|           color: #33ccff; } | ||||
|     /* line 313, ../sass/search/_search.scss */ | ||||
|     .search .search-scroll .load-icon { | ||||
|       position: relative; } | ||||
|       /* line 315, ../sass/search/_search.scss */ | ||||
|       .search .search-scroll .load-icon.loading { | ||||
|         pointer-events: none; | ||||
|         margin-left: 6px; } | ||||
|         /* line 319, ../sass/search/_search.scss */ | ||||
|         .search .search-scroll .load-icon.loading .title-label { | ||||
|           font-style: italic; | ||||
|           font-size: .9em; | ||||
|           opacity: 0.5; | ||||
|           margin-left: 26px; | ||||
|           line-height: 24px; } | ||||
|         /* line 329, ../sass/search/_search.scss */ | ||||
|         .search .search-scroll .load-icon.loading .wait-spinner { | ||||
|           margin-left: 6px; } | ||||
|       /* line 334, ../sass/search/_search.scss */ | ||||
|       .search .search-scroll .load-icon:not(.loading) { | ||||
|         cursor: pointer; } | ||||
|     /* line 339, ../sass/search/_search.scss */ | ||||
|     .search .search-scroll .load-more-button { | ||||
|       margin-top: 5px 0; | ||||
|       font-size: 0.8em; | ||||
|       position: relative; | ||||
|       left: 50%; | ||||
|       margin-left: -45px; | ||||
|       text-align: center; | ||||
|       width: 90px; | ||||
|       white-space: nowrap; } | ||||
|   | ||||
| @@ -1,19 +1,67 @@ | ||||
| { | ||||
| 	"metadata": { | ||||
| 		"name": "WTD Symbols v2.", | ||||
| 		"lastOpened": 1435765696898, | ||||
| 		"created": 1435764071891 | ||||
| 		"name": "WTD Symbols v2.2", | ||||
| 		"lastOpened": 1439948744240, | ||||
| 		"created": 1439948734037 | ||||
| 	}, | ||||
| 	"iconSets": [ | ||||
| 		{ | ||||
| 			"selection": [ | ||||
| 				{ | ||||
| 					"order": 82, | ||||
| 					"id": 84, | ||||
| 					"prevSize": 32, | ||||
| 					"code": 58887, | ||||
| 					"name": "icon-x-in-circle", | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 77, | ||||
| 					"id": 83, | ||||
| 					"prevSize": 32, | ||||
| 					"code": 58881, | ||||
| 					"name": "icon-datatable", | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 78, | ||||
| 					"id": 82, | ||||
| 					"prevSize": 32, | ||||
| 					"code": 58882, | ||||
| 					"name": "icon-tabular-scrolling", | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 79, | ||||
| 					"id": 81, | ||||
| 					"prevSize": 32, | ||||
| 					"code": 58884, | ||||
| 					"name": "icon-tabular", | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 80, | ||||
| 					"id": 80, | ||||
| 					"prevSize": 32, | ||||
| 					"code": 58885, | ||||
| 					"name": "icon-calendar", | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 81, | ||||
| 					"id": 78, | ||||
| 					"prevSize": 32, | ||||
| 					"code": 58886, | ||||
| 					"name": "icon-paint-bucket", | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 1, | ||||
| 					"id": 75, | ||||
| 					"prevSize": 32, | ||||
| 					"code": 123, | ||||
| 					"name": "icon-pointer-left", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 3, | ||||
| @@ -21,7 +69,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 125, | ||||
| 					"name": "icon-pointer-right", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 4, | ||||
| @@ -29,7 +77,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 80, | ||||
| 					"name": "icon-person", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 5, | ||||
| @@ -37,7 +85,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 232, | ||||
| 					"name": "icon-chain-links", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 6, | ||||
| @@ -45,7 +93,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 115, | ||||
| 					"name": "icon-database-in-brackets", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 7, | ||||
| @@ -53,7 +101,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 114, | ||||
| 					"name": "icon-refresh", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 8, | ||||
| @@ -61,7 +109,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 108, | ||||
| 					"name": "icon-lock", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 9, | ||||
| @@ -69,7 +117,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 51, | ||||
| 					"name": "icon-box-with-dashed-lines", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 10, | ||||
| @@ -77,7 +125,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 58880, | ||||
| 					"name": "icon-box-with-arrow-cursor", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 11, | ||||
| @@ -85,7 +133,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 65, | ||||
| 					"name": "icon-activity-mode", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 12, | ||||
| @@ -93,7 +141,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 97, | ||||
| 					"name": "icon-activity", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 13, | ||||
| @@ -101,7 +149,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 33, | ||||
| 					"name": "icon-alert-rect", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 14, | ||||
| @@ -109,7 +157,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 58883, | ||||
| 					"name": "icon-alert-triangle", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 15, | ||||
| @@ -117,7 +165,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 238, | ||||
| 					"name": "icon-arrow-double-down", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 16, | ||||
| @@ -125,7 +173,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 235, | ||||
| 					"name": "icon-arrow-double-up", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 2, | ||||
| @@ -133,7 +181,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 118, | ||||
| 					"name": "icon-arrow-down", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 19, | ||||
| @@ -141,7 +189,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 60, | ||||
| 					"name": "icon-arrow-left", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 20, | ||||
| @@ -149,7 +197,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 62, | ||||
| 					"name": "icon-arrow-right", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 21, | ||||
| @@ -157,7 +205,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 236, | ||||
| 					"name": "icon-arrow-tall-down", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 22, | ||||
| @@ -165,7 +213,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 237, | ||||
| 					"name": "icon-arrow-tall-up", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 23, | ||||
| @@ -173,7 +221,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 94, | ||||
| 					"name": "icon-arrow-up", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 24, | ||||
| @@ -181,7 +229,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 73, | ||||
| 					"name": "icon-arrows-out", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 25, | ||||
| @@ -189,7 +237,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 58893, | ||||
| 					"name": "icon-arrows-right-left", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 33, | ||||
| @@ -197,7 +245,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 53, | ||||
| 					"name": "icon-arrows-up-down", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 26, | ||||
| @@ -205,7 +253,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 42, | ||||
| 					"name": "icon-asterisk", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 27, | ||||
| @@ -213,7 +261,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 72, | ||||
| 					"name": "icon-autoflow-tabular", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 28, | ||||
| @@ -221,7 +269,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 224, | ||||
| 					"name": "icon-box-round-corners", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 29, | ||||
| @@ -229,7 +277,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 50, | ||||
| 					"name": "icon-check", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 30, | ||||
| @@ -237,7 +285,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 67, | ||||
| 					"name": "icon-clock", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 31, | ||||
| @@ -245,7 +293,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 46, | ||||
| 					"name": "icon-connectivity", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 32, | ||||
| @@ -253,7 +301,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 100, | ||||
| 					"name": "icon-database-query", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 17, | ||||
| @@ -261,7 +309,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 68, | ||||
| 					"name": "icon-database", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 35, | ||||
| @@ -269,7 +317,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 81, | ||||
| 					"name": "icon-dictionary", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 36, | ||||
| @@ -277,7 +325,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 242, | ||||
| 					"name": "icon-duplicate", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 37, | ||||
| @@ -285,7 +333,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 102, | ||||
| 					"name": "icon-folder-new", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 38, | ||||
| @@ -293,7 +341,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 70, | ||||
| 					"name": "icon-folder", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 39, | ||||
| @@ -301,7 +349,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 95, | ||||
| 					"name": "icon-fullscreen-collapse", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 40, | ||||
| @@ -309,7 +357,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 122, | ||||
| 					"name": "icon-fullscreen-expand", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 41, | ||||
| @@ -317,7 +365,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 71, | ||||
| 					"name": "icon-gear", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 49, | ||||
| @@ -325,7 +373,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 227, | ||||
| 					"name": "icon-image", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 42, | ||||
| @@ -333,7 +381,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 225, | ||||
| 					"name": "icon-layers", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 43, | ||||
| @@ -341,7 +389,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 76, | ||||
| 					"name": "icon-layout", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 44, | ||||
| @@ -349,7 +397,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 226, | ||||
| 					"name": "icon-line-horz", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 75, | ||||
| @@ -357,7 +405,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 244, | ||||
| 					"name": "icon-link", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 46, | ||||
| @@ -365,7 +413,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 88, | ||||
| 					"name": "icon-magnify-in", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 47, | ||||
| @@ -373,7 +421,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 89, | ||||
| 					"name": "icon-magnify-out", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 48, | ||||
| @@ -381,7 +429,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 77, | ||||
| 					"name": "icon-magnify", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 34, | ||||
| @@ -389,7 +437,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 109, | ||||
| 					"name": "icon-menu", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 50, | ||||
| @@ -397,7 +445,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 243, | ||||
| 					"name": "icon-move", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 51, | ||||
| @@ -405,7 +453,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 121, | ||||
| 					"name": "icon-new-window", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 52, | ||||
| @@ -413,7 +461,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 111, | ||||
| 					"name": "icon-object", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 73, | ||||
| @@ -421,7 +469,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 63, | ||||
| 					"name": "icon-object-unknown", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 53, | ||||
| @@ -429,7 +477,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 86, | ||||
| 					"name": "icon-packet", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 54, | ||||
| @@ -437,7 +485,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 234, | ||||
| 					"name": "icon-page", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 55, | ||||
| @@ -445,7 +493,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 241, | ||||
| 					"name": "icon-pause", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 56, | ||||
| @@ -453,7 +501,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 112, | ||||
| 					"name": "icon-pencil", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 65, | ||||
| @@ -461,7 +509,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 79, | ||||
| 					"name": "icon-people", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 57, | ||||
| @@ -469,7 +517,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 239, | ||||
| 					"name": "icon-play", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 58, | ||||
| @@ -477,7 +525,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 233, | ||||
| 					"name": "icon-plot-resource", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 59, | ||||
| @@ -485,7 +533,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 43, | ||||
| 					"name": "icon-plus", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 60, | ||||
| @@ -493,7 +541,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 45, | ||||
| 					"name": "icon-minus", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 61, | ||||
| @@ -501,7 +549,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 54, | ||||
| 					"name": "icon-sine", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 62, | ||||
| @@ -509,7 +557,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 228, | ||||
| 					"name": "icon-T", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 63, | ||||
| @@ -517,7 +565,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 116, | ||||
| 					"name": "icon-telemetry-panel", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 64, | ||||
| @@ -525,7 +573,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 84, | ||||
| 					"name": "icon-telemetry", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 18, | ||||
| @@ -533,7 +581,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 246, | ||||
| 					"name": "icon-thumbs-strip", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 67, | ||||
| @@ -541,7 +589,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 83, | ||||
| 					"name": "icon-timeline", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 68, | ||||
| @@ -549,7 +597,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 245, | ||||
| 					"name": "icon-timer", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 69, | ||||
| @@ -557,7 +605,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 90, | ||||
| 					"name": "icon-trash", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 70, | ||||
| @@ -565,7 +613,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 229, | ||||
| 					"name": "icon-two-parts-both", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 71, | ||||
| @@ -573,7 +621,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 231, | ||||
| 					"name": "icon-two-parts-one-only", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 72, | ||||
| @@ -581,7 +629,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 120, | ||||
| 					"name": "icon-x-heavy", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				}, | ||||
| 				{ | ||||
| 					"order": 66, | ||||
| @@ -589,7 +637,7 @@ | ||||
| 					"prevSize": 32, | ||||
| 					"code": 58946, | ||||
| 					"name": "icon-x", | ||||
| 					"tempChar": "" | ||||
| 					"tempChar": "" | ||||
| 				} | ||||
| 			], | ||||
| 			"id": 2, | ||||
| @@ -604,6 +652,223 @@ | ||||
| 			"height": 1024, | ||||
| 			"prevSize": 32, | ||||
| 			"icons": [ | ||||
| 				{ | ||||
| 					"id": 84, | ||||
| 					"paths": [ | ||||
| 						"M512 0c-282.8 0-512 229.2-512 512s229.2 512 512 512 512-229.2 512-512-229.2-512-512-512zM832 704l-128 128-192-192-192 192-128-128 192-192-192-192 128-128 192 192 192-192 128 128-192 192 192 192z" | ||||
| 					], | ||||
| 					"attrs": [], | ||||
| 					"isMulticolor": false, | ||||
| 					"grid": 0, | ||||
| 					"tags": [ | ||||
| 						"icon-x-in-circle" | ||||
| 					], | ||||
| 					"colorPermutations": { | ||||
| 						"16161751": [] | ||||
| 					} | ||||
| 				}, | ||||
| 				{ | ||||
| 					"id": 83, | ||||
| 					"paths": [ | ||||
| 						"M1024 192c0 106.039-229.23 192-512 192s-512-85.961-512-192c0-106.039 229.23-192 512-192s512 85.961 512 192z", | ||||
| 						"M512 512c-282.8 0-512-86-512-192v512c0 106 229.2 192 512 192s512-86 512-192v-512c0 106-229.2 192-512 192zM896 575v256c-36.6 15.6-79.8 28.8-128 39.4v-256c48.2-10.6 91.4-23.8 128-39.4zM256 614.4v256c-48.2-10.4-91.4-23.8-128-39.4v-256c36.6 15.6 79.8 28.8 128 39.4zM384 890v-256c41 4 83.8 6 128 6s87-2.2 128-6v256c-41 4-83.8 6-128 6s-87-2.2-128-6z" | ||||
| 					], | ||||
| 					"attrs": [ | ||||
| 						{ | ||||
| 							"fill": "rgb(6,161,75)", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "rgb(6,161,75)", | ||||
| 							"opacity": 1 | ||||
| 						} | ||||
| 					], | ||||
| 					"isMulticolor": false, | ||||
| 					"grid": 0, | ||||
| 					"tags": [ | ||||
| 						"icon-datatable" | ||||
| 					], | ||||
| 					"colorPermutations": { | ||||
| 						"16161751": [ | ||||
| 							1, | ||||
| 							1 | ||||
| 						], | ||||
| 						"125525525516161751": [ | ||||
| 							1, | ||||
| 							1 | ||||
| 						] | ||||
| 					} | ||||
| 				}, | ||||
| 				{ | ||||
| 					"id": 82, | ||||
| 					"paths": [ | ||||
| 						"M64 0c-35.2 0-64 28.8-64 64v192h448v-256h-384z", | ||||
| 						"M1024 256v-192c0-35.2-28.8-64-64-64h-384v256h448z", | ||||
| 						"M0 384v192c0 35.2 28.8 64 64 64h384v-256h-448z", | ||||
| 						"M960 640c35.2 0 64-28.8 64-64v-192h-448v256h384z", | ||||
| 						"M512 1024l-256-256h512z" | ||||
| 					], | ||||
| 					"attrs": [ | ||||
| 						{ | ||||
| 							"fill": "rgb(6,161,75)", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "rgb(6,161,75)", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "rgb(6,161,75)", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "rgb(6,161,75)", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "rgb(6,161,75)", | ||||
| 							"opacity": 1 | ||||
| 						} | ||||
| 					], | ||||
| 					"isMulticolor": false, | ||||
| 					"grid": 0, | ||||
| 					"tags": [ | ||||
| 						"icon-tabular-scrolling" | ||||
| 					], | ||||
| 					"colorPermutations": { | ||||
| 						"16161751": [ | ||||
| 							1, | ||||
| 							1, | ||||
| 							1, | ||||
| 							1, | ||||
| 							1 | ||||
| 						], | ||||
| 						"125525525516161751": [ | ||||
| 							1, | ||||
| 							1, | ||||
| 							1, | ||||
| 							1, | ||||
| 							1 | ||||
| 						] | ||||
| 					} | ||||
| 				}, | ||||
| 				{ | ||||
| 					"id": 81, | ||||
| 					"paths": [ | ||||
| 						"M0 64v192h448v-256h-384c-35.2 0-64 28.8-64 64z", | ||||
| 						"M960 0h-384v256h448v-192c0-35.2-28.8-64-64-64z", | ||||
| 						"M576 384h448v256h-448v-256z", | ||||
| 						"M0 384h448v256h-448v-256z", | ||||
| 						"M0 960c0 35.2 28.8 64 64 64h384v-256h-448v192z", | ||||
| 						"M576 1024h384c35.2 0 64-28.8 64-64v-192h-448v256z" | ||||
| 					], | ||||
| 					"attrs": [ | ||||
| 						{ | ||||
| 							"fill": "#000", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "#000", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "#000", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "#000", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "#000", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "#000", | ||||
| 							"opacity": 1 | ||||
| 						} | ||||
| 					], | ||||
| 					"isMulticolor": false, | ||||
| 					"grid": 0, | ||||
| 					"tags": [ | ||||
| 						"icon-tabular" | ||||
| 					], | ||||
| 					"colorPermutations": { | ||||
| 						"16161751": [ | ||||
| 							0, | ||||
| 							0, | ||||
| 							0, | ||||
| 							0, | ||||
| 							0, | ||||
| 							0 | ||||
| 						], | ||||
| 						"125525525516161751": [ | ||||
| 							0, | ||||
| 							0, | ||||
| 							0, | ||||
| 							0, | ||||
| 							0, | ||||
| 							0 | ||||
| 						] | ||||
| 					} | ||||
| 				}, | ||||
| 				{ | ||||
| 					"id": 80, | ||||
| 					"paths": [ | ||||
| 						"M896 0h-768c-70.4 0-128 57.6-128 128v768c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v-768c0-70.4-57.6-128-128-128zM640 448h-256v-192h256v192zM384 512h256v192h-256v-192zM320 704h-256v-192h256v192zM320 256v192h-256v-192h256zM128 960c-17 0-33-6.6-45.2-18.8s-18.8-28.2-18.8-45.2v-128h256v192h-192zM384 960v-192h256v192h-256zM960 896c0 17-6.6 33-18.8 45.2s-28.2 18.8-45.2 18.8h-192v-192h256v128zM960 704h-256v-192h256v192zM960 448h-256v-192h256v192z" | ||||
| 					], | ||||
| 					"attrs": [ | ||||
| 						{ | ||||
| 							"fill": "rgb(6,161,75)", | ||||
| 							"opacity": 1 | ||||
| 						} | ||||
| 					], | ||||
| 					"isMulticolor": false, | ||||
| 					"grid": 0, | ||||
| 					"tags": [ | ||||
| 						"icon-calendar" | ||||
| 					], | ||||
| 					"colorPermutations": { | ||||
| 						"16161751": [ | ||||
| 							1 | ||||
| 						], | ||||
| 						"125525525516161751": [ | ||||
| 							1 | ||||
| 						] | ||||
| 					} | ||||
| 				}, | ||||
| 				{ | ||||
| 					"id": 78, | ||||
| 					"paths": [ | ||||
| 						"M896 640c0 0-130 188-128 256 2 70.6 57.4 128 128 128s126-57.4 128-128c2-68-128-256-128-256z", | ||||
| 						"M449 129l0.2-64.8c0-35.4-28.4-64-63.8-64.2 0 0-0.2 0-0.2 0-35.2 0-63.8 28.6-64 63.8l-0.6 190.8-294 292.6c-50 50-12.4 215.2 112.4 340s290 162.4 340 112.4l417-423.6-447-447zM384 640c-70.6 0-128-57.4-128-128 0-47.4 25.8-89 64.4-111l-0.4 110.8c0 35.4 28.4 64 63.8 64.2 0 0 0.2 0 0.2 0 35.2 0 63.8-28.6 64-63.8l0.4-110.8c38 22.2 63.6 63.4 63.6 110.6 0 70.6-57.4 128-128 128z" | ||||
| 					], | ||||
| 					"attrs": [ | ||||
| 						{ | ||||
| 							"fill": "rgb(6,161,75)", | ||||
| 							"opacity": 1 | ||||
| 						}, | ||||
| 						{ | ||||
| 							"fill": "rgb(6,161,75)", | ||||
| 							"opacity": 1 | ||||
| 						} | ||||
| 					], | ||||
| 					"isMulticolor": false, | ||||
| 					"grid": 0, | ||||
| 					"tags": [ | ||||
| 						"icon-paint-bucket" | ||||
| 					], | ||||
| 					"colorPermutations": { | ||||
| 						"16161751": [ | ||||
| 							1, | ||||
| 							1 | ||||
| 						], | ||||
| 						"125525525516161751": [ | ||||
| 							1, | ||||
| 							1 | ||||
| 						] | ||||
| 					} | ||||
| 				}, | ||||
| 				{ | ||||
| 					"id": 75, | ||||
| 					"paths": [ | ||||
| @@ -1767,7 +2032,24 @@ | ||||
| 					] | ||||
| 				} | ||||
| 			], | ||||
| 			"invisible": false | ||||
| 			"invisible": false, | ||||
| 			"colorThemes": [ | ||||
| 				[ | ||||
| 					[ | ||||
| 						0, | ||||
| 						0, | ||||
| 						0, | ||||
| 						1 | ||||
| 					], | ||||
| 					[ | ||||
| 						6, | ||||
| 						161, | ||||
| 						75, | ||||
| 						1 | ||||
| 					] | ||||
| 				] | ||||
| 			], | ||||
| 			"colorThemeIdx": 0 | ||||
| 		}, | ||||
| 		{ | ||||
| 			"selection": [ | ||||
| @@ -14510,7 +14792,8 @@ | ||||
| 			"selector": "class", | ||||
| 			"classSelector": ".ui-symbol", | ||||
| 			"showMetrics": true, | ||||
| 			"showMetadata": true | ||||
| 			"showMetadata": true, | ||||
| 			"embed": false | ||||
| 		}, | ||||
| 		"imagePref": { | ||||
| 			"prefix": "icon-", | ||||
										
											Binary file not shown.
										
									
								
							| @@ -6,78 +6,85 @@ | ||||
| <font id="wtdsymbols" horiz-adv-x="1024"> | ||||
| <font-face units-per-em="1024" ascent="960" descent="-64" /> | ||||
| <missing-glyph horiz-adv-x="1024" /> | ||||
| <glyph unicode=" " d="" horiz-adv-x="512" /> | ||||
| <glyph unicode="!" d="M832 960h-640c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM640 128c0-35.2-28.8-64-64-64h-128c-35.2 0-64 28.8-64 64v64c0 35.2 28.8 64 64 64h128c35.2 0 64-28.8 64-64v-64zM696.062 768.494l-48.124-384.988c-4.366-34.928-36.738-63.506-71.938-63.506h-128c-35.2 0-67.572 28.578-71.938 63.506l-48.124 384.988c-4.366 34.928 20.862 63.506 56.062 63.506h256c35.2 0 60.428-28.578 56.062-63.506z" /> | ||||
| <glyph unicode="*" d="M1004.166 619.542l-97.522 168.916-330.534-229.414 33.414 400.956h-195.048l33.414-400.956-330.534 229.414-97.522-168.916 363.944-171.542-363.944-171.542 97.522-168.916 330.534 229.414-33.414-400.956h195.048l-33.414 400.956 330.534-229.414 97.522 168.916-363.944 171.542z" /> | ||||
| <glyph unicode="+" d="M960 576h-330v320c0 35.2-28.8 64-64 64h-108c-35.2 0-64-28.8-64-64v-320h-330c-35.2 0-64-28.8-64-64v-128c0-35.2 28.8-64 64-64h330v-320c0-35.2 28.8-64 64-64h108c35.2 0 64 28.8 64 64v320h330c35.2 0 64 28.8 64 64v128c0 35.2-28.8 64-64 64z" /> | ||||
| <glyph unicode="-" d="M960 320c35.2 0 64 28.8 64 64v128c0 35.2-28.8 64-64 64h-896c-35.2 0-64-28.8-64-64v-128c0-35.2 28.8-64 64-64h896z" /> | ||||
| <glyph unicode="." d="M704 384c0-70.4-57.6-128-128-128h-128c-70.4 0-128 57.6-128 128v128c0 70.4 57.6 128 128 128h128c70.4 0 128-57.6 128-128v-128zM1024 448l-192 320v-640zM0 448l192 320v-640z" /> | ||||
| <glyph unicode="2" d="M1024 960l-640-640-384 384v-384l384-384 640 640z" /> | ||||
| <glyph unicode="3" d="M640 704h-256c-70.4 0-128-57.6-128-128v-256c0-70.4 57.6-128 128-128h256c70.4 0 128 57.6 128 128v256c0 70.4-57.6 128-128 128zM0 960h192v-192h-192v192zM256 960h192v-128h-192v128zM576 960h192v-128h-192v128zM256 64h192v-128h-192v128zM576 64h192v-128h-192v128zM0 384h128v-192h-128v192zM0 704h128v-192h-128v192zM896 384h128v-192h-128v192zM896 704h128v-192h-128v192zM832 960h192v-192h-192v192zM0 128h192v-192h-192v192zM832 128h192v-192h-192v192z" /> | ||||
| <glyph unicode="5" d="M512 960l512-448h-1024zM0 384l512-448 512 448z" /> | ||||
| <glyph unicode="6" d="M1022.294 448c-1.746 7.196-3.476 14.452-5.186 21.786-20.036 85.992-53.302 208.976-98 306.538-22.42 48.938-45.298 86.556-69.946 115.006-48.454 55.93-98.176 67.67-131.356 67.67s-82.902-11.74-131.356-67.672c-24.648-28.45-47.528-66.068-69.948-115.006-44.696-97.558-77.962-220.544-98-306.538-21.646-92.898-46.444-175.138-71.71-237.836-16.308-40.46-30.222-66.358-40.6-82.604-10.378 16.246-24.292 42.142-40.6 82.604-23.272 57.75-46.144 132.088-66.524 216.052h-197.362c1.746-7.196 3.476-14.452 5.186-21.786 20.036-85.992 53.302-208.976 98-306.538 22.42-48.938 45.298-86.556 69.946-115.006 48.454-55.932 98.176-67.672 131.356-67.672s82.902 11.74 131.356 67.672c24.648 28.45 47.528 66.068 69.948 115.006 44.696 97.558 77.962 220.544 98 306.538 21.646 92.898 46.444 175.138 71.71 237.836 16.308 40.46 30.222 66.358 40.6 82.604 10.378-16.246 24.292-42.142 40.6-82.604 23.274-57.748 46.146-132.086 66.526-216.050h197.36z" /> | ||||
| <glyph unicode="<" d="M256 448l512-512v1024z" /> | ||||
| <glyph unicode=">" d="M768 448l-512 512v-1024z" /> | ||||
| <glyph unicode="?" d="M510 962l-512-320v-384l512-320 512 320v384l-512 320zM585.4 100.8c-21.2-20.8-46-30.8-76-30.8-31.2 0-56.2 9.8-76.2 29.6-20 20-29.6 44.8-29.6 76.2 0 30.4 10.2 55.2 31 76.2s45.2 31.2 74.8 31.2c29.6 0 54.2-10.4 75.6-32s31.8-46.4 31.8-76c-0.2-29-10.8-54-31.4-74.4zM638.2 413.4c-23.6-11.8-37.4-22-43.4-32.4-3.6-6.2-6-14.8-7.4-26.8v-41h-161.4v44.2c0 40.2 4.4 69.8 13 88 8 17.2 22.6 30.2 44.8 40l34.8 15.4c32 14.2 48.2 35.2 48.2 62.8 0 16-6 30.4-17.2 41.8-11.2 11.2-25.6 17.2-41.6 17.2-24 0-54.4-10-62.8-57.4l-2.2-12.2h-147l1.4 16.2c4 44.6 17 82.4 38.8 112.2 19.6 27 45.6 48.6 77 64.6s64.6 24 98.2 24c60.6 0 110.2-19.4 151.4-59.6 41.2-40 61.2-88 61.2-147.2 0-70.8-28.8-121.4-85.8-149.8z" /> | ||||
| <glyph unicode="A" d="M512 960c-214.866 0-398.786-132.372-474.744-320h90.744c56.86 0 107.938-24.724 143.094-64h240.906l-192 192h256l320-320-320-320h-256l192 192h-240.906c-35.156-39.276-86.234-64-143.094-64h-90.744c75.958-187.628 259.878-320 474.744-320 282.77 0 512 229.23 512 512s-229.23 512-512 512z" /> | ||||
| <glyph unicode="C" d="M512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512 512 229.23 512 512-229.23 512-512 512zM768 384h-256c-35.2 0-64 28.8-64 64v384c0 35.2 28.8 64 64 64s64-28.8 64-64v-320h192c35.2 0 64-28.8 64-64s-28.8-64-64-64z" /> | ||||
| <glyph unicode="D" d="M1024 768c0-106.039-229.23-192-512-192s-512 85.961-512 192c0 106.039 229.23 192 512 192s512-85.961 512-192zM512 448c-282.77 0-512 85.962-512 192v-512c0-106.038 229.23-192 512-192s512 85.962 512 192v512c0-106.038-229.23-192-512-192z" /> | ||||
| <glyph unicode="F" d="M896 768h-320c-16.4 16.4-96.8 96.8-109.2 109.2l-37.4 37.4c-25 25-74.2 45.4-109.4 45.4h-256c-35.2 0-64-28.8-64-64v-384c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v128c0 70.4-57.6 128-128 128zM896 512h-768c-70.4 0-128-57.6-128-128v-320c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v320c0 70.4-57.6 128-128 128z" /> | ||||
| <glyph unicode="G" d="M1024 384v128l-140.976 35.244c-8.784 32.922-21.818 64.106-38.504 92.918l74.774 124.622-90.51 90.51-124.622-74.774c-28.812 16.686-59.996 29.72-92.918 38.504l-35.244 140.976h-128l-35.244-140.976c-32.922-8.784-64.106-21.818-92.918-38.504l-124.622 74.774-90.51-90.51 74.774-124.622c-16.686-28.812-29.72-59.996-38.504-92.918l-140.976-35.244v-128l140.976-35.244c8.784-32.922 21.818-64.106 38.504-92.918l-74.774-124.622 90.51-90.51 124.622 74.774c28.812-16.686 59.996-29.72 92.918-38.504l35.244-140.976h128l35.244 140.976c32.922 8.784 64.106 21.818 92.918 38.504l124.622-74.774 90.51 90.51-74.774 124.622c16.686 28.812 29.72 59.996 38.504 92.918l140.976 35.244zM704 448c0-106.038-85.962-192-192-192s-192 85.962-192 192 85.962 192 192 192 192-85.962 192-192z" /> | ||||
| <glyph unicode="H" d="M192 960c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h64v1024h-64zM384 960h256v-1024h-256v1024zM832 960h-64v-704h256v512c0 105.6-86.4 192-192 192z" /> | ||||
| <glyph unicode="I" d="M0 448l256-256v512zM512 960l-256-256h512zM512-64l256 256h-512zM768 704v-512l256 256z" /> | ||||
| <glyph unicode="L" d="M448 960h-256c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h256v1024zM832 960h-256v-577.664h448v385.664c0 105.6-86.4 192-192 192zM576-64h256c105.6 0 192 86.4 192 192v129.664h-448v-321.664z" /> | ||||
| <glyph unicode="M" d="M1024 64l-201.662 201.662c47.922 72.498 73.662 157.434 73.662 246.338 0 119.666-46.6 232.168-131.216 316.784s-197.118 131.216-316.784 131.216-232.168-46.6-316.784-131.216-131.216-197.118-131.216-316.784 46.6-232.168 131.216-316.784 197.118-131.216 316.784-131.216c88.904 0 173.84 25.74 246.338 73.662l201.662-201.662 128 128zM448 256c-141.16 0-256 114.842-256 256 0 141.16 114.84 256 256 256 141.158 0 256-114.84 256-256 0-141.158-114.842-256-256-256z" /> | ||||
| <glyph unicode="O" d="M704 640h64c70.4 0 128 57.6 128 128v64c0 70.4-57.6 128-128 128h-64c-70.4 0-128-57.6-128-128v-64c0-70.4 57.6-128 128-128zM256 640h64c70.4 0 128 57.6 128 128v64c0 70.4-57.6 128-128 128h-64c-70.4 0-128-57.6-128-128v-64c0-70.4 57.6-128 128-128zM832 576h-192c-34.908 0-67.716-9.448-96-25.904 57.278-33.324 96-95.404 96-166.096v-448h384v448c0 105.6-86.4 192-192 192zM384 576h-192c-105.6 0-192-86.4-192-192v-448h576v448c0 105.6-86.4 192-192 192z" /> | ||||
| <glyph unicode="P" d="M768 704c0-105.6-86.4-192-192-192h-128c-105.6 0-192 86.4-192 192v64c0 105.6 86.4 192 192 192h128c105.6 0 192-86.4 192-192v-64zM64-64v192c0 140.8 115.2 256 256 256h384c140.8 0 256-115.2 256-256v-192z" /> | ||||
| <glyph unicode="Q" d="M832 320c105.6 0 192 86.4 192 192v256c0 105.6-86.4 192-192 192v-320l-128 64-128-64v320h-384c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v192c0-105.6-86.4-192-192-192h-640v192h640z" /> | ||||
| <glyph unicode="S" d="M256 704h384v-128h-384v128zM384 512h384v-128h-384v128zM320 320h384v-128h-384v128zM832 960h-128v-192h127.6c0.2 0 0.2-0.2 0.4-0.4v-639.4c0-0.2-0.2-0.2-0.4-0.4h-127.6v-192h128c105.6 0 192 86.4 192 192v640.2c0 105.6-86.4 192-192 192zM192 128.4v639.2c0 0.2 0.2 0.2 0.4 0.4h127.6v192h-128c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h128v192h-127.6c-0.2 0-0.4 0.2-0.4 0.4z" /> | ||||
| <glyph unicode="T" d="M718.6 384h-127.2c25-93.4 48.4-144.4 63.6-168.6 15.2 24.2 38.6 75.2 63.6 168.6zM794.2 207.2c-15.4-35.8-31.2-63.2-48.2-84-18.4-22.4-49-49.2-91-49.2s-72.6 26.8-91 49.2c-17 20.6-32.6 48.2-48.2 84-23.6 54.8-42.8 120.4-56.6 176.8h-457.2c31.4-252.6 247-448 508-448s476.6 195.4 508 448h-167.2c-14-56.4-33-122-56.6-176.8zM301.4 512h127.2c-25 93.4-48.4 144.4-63.6 168.6-15.2-24.2-38.6-75.2-63.6-168.6zM274 772.8c18.4 22.4 49 49.2 91 49.2s72.6-26.8 91-49.2c17-20.6 32.6-48.2 48.2-84 23.6-54.8 42.8-120.4 56.6-176.8h457.2c-31.4 252.6-246.8 448-508 448s-476.6-195.4-508-448h167.2c14 56.4 33 122 56.6 176.8 15.6 35.8 31.4 63.2 48.2 84z" /> | ||||
| <glyph unicode="V" d="M511.98 960l-511.98-320v-512c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v512l-512.020 320zM512 768l358.4-224-358.4-224-358.4 224 358.4 224z" /> | ||||
| <glyph unicode="X" d="M640 576h-128v128h-128v-128h-128v-128h128v-128h128v128h128zM1024 64l-201.662 201.662c47.922 72.498 73.662 157.434 73.662 246.338 0 119.666-46.6 232.168-131.216 316.784s-197.118 131.216-316.784 131.216c-119.666 0-232.168-46.6-316.784-131.216s-131.216-197.118-131.216-316.784c0-119.666 46.6-232.168 131.216-316.784s197.118-131.216 316.784-131.216c88.904 0 173.84 25.74 246.338 73.662l201.662-201.662 128 128zM448 256c-141.16 0-256 114.842-256 256 0 141.16 114.84 256 256 256 141.158 0 256-114.84 256-256 0-141.158-114.842-256-256-256z" /> | ||||
| <glyph unicode="Y" d="M256 576h384v-128h-384v128zM1024 64l-201.662 201.662c47.922 72.498 73.662 157.434 73.662 246.338 0 119.666-46.6 232.168-131.216 316.784s-197.118 131.216-316.784 131.216c-119.666 0-232.168-46.6-316.784-131.216s-131.216-197.118-131.216-316.784c0-119.666 46.6-232.168 131.216-316.784s197.118-131.216 316.784-131.216c88.904 0 173.84 25.74 246.338 73.662l201.662-201.662 128 128zM448 256c-141.16 0-256 114.842-256 256 0 141.16 114.84 256 256 256 141.158 0 256-114.84 256-256 0-141.158-114.842-256-256-256z" /> | ||||
| <glyph unicode="Z" d="M832 832h-192.36v64c0 35.2-28.8 64-64 64h-128c-35.2 0-64-28.8-64-64v-64h-191.64c-105.6 0-192-72-192-160s0-160 0-160h64v-384c0-105.6 86.4-192 192-192h512c105.6 0 192 86.4 192 192v384h64c0 0 0 72 0 160s-86.4 160-192 160zM320 128h-128v384h128v-384zM576 128h-128v384h128v-384zM832 128h-128v384h128v-384z" /> | ||||
| <glyph unicode="^" d="M512 704l-512-512h1024z" /> | ||||
| <glyph unicode="_" d="M191.656 128c0.118-0.1 0.244-0.224 0.344-0.344v-191.656h192v192c0 105.6-86.4 192-192 192h-192v-192h191.656zM192 768.344c-0.1-0.118-0.224-0.244-0.344-0.344h-191.656v-192h192c105.6 0 192 86.4 192 192v192h-192v-191.656zM832 576h192v192h-191.656c-0.118 0.1-0.244 0.226-0.344 0.344v191.656h-192v-192c0-105.6 86.4-192 192-192zM832 127.656c0.1 0.118 0.224 0.244 0.344 0.344h191.656v192h-192c-105.6 0-192-86.4-192-192v-192h192v191.656z" /> | ||||
| <glyph unicode="a" d="M576 896h-256l320-320h-290.256c-44.264 76.516-126.99 128-221.744 128h-128v-512h128c94.754 0 177.48 51.484 221.744 128h290.256l-320-320h256l448 448-448 448z" /> | ||||
| <glyph unicode="d" d="M683.52 140.714c-50.782-28.456-109.284-44.714-171.52-44.714-194.094 0-352 157.906-352 352s157.906 352 352 352 352-157.906 352-352c0-62.236-16.258-120.738-44.714-171.52l191.692-191.692c8.516 13.89 13.022 28.354 13.022 43.212v640c0 106.038-229.23 192-512 192s-512-85.962-512-192v-640c0-106.038 229.23-192 512-192 126.11 0 241.548 17.108 330.776 45.46l-159.256 159.254zM352 448c0-88.224 71.776-160 160-160s160 71.776 160 160-71.776 160-160 160-160-71.776-160-160z" /> | ||||
| <glyph unicode="f" d="M896 768h-320c-16.4 16.4-96.8 96.8-109.2 109.2l-37.4 37.4c-25 25-74.2 45.4-109.4 45.4h-256c-35.2 0-64-28.8-64-64v-384c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v128c0 70.4-57.6 128-128 128zM896 512h-768c-70.4 0-128-57.6-128-128v-320c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v320c0 70.4-57.6 128-128 128zM704 160h-128v-128h-128v128h-128v128h128v128h128v-128h128v-128z" /> | ||||
| <glyph unicode="l" d="M832 576h-32v96c0 158.8-129.2 288-288 288s-288-129.2-288-288v-96h-32c-70.4 0-128-57.6-128-128v-384c0-70.4 57.6-128 128-128h640c70.4 0 128 57.6 128 128v384c0 70.4-57.6 128-128 128zM416 672c0 53 43 96 96 96s96-43 96-96v-96h-192v96z" /> | ||||
| <glyph unicode="m" d="M0 960h1024v-256h-1024v256zM0 576h1024v-256h-1024v256zM0 192h1024v-256h-1024v256z" /> | ||||
| <glyph unicode="o" d="M512-64l512 320v384l-512.020 320-511.98-320v-384l512-320zM512 768l358.4-224-358.4-224-358.4 224 358.4 224z" /> | ||||
| <glyph unicode="p" d="M922.344 858.32c-38.612 38.596-81.306 69.232-120.304 86.324-68.848 30.25-104.77 9.078-120.194-6.344l-516.228-516.216-3.136-9.152-162.482-476.932 485.998 165.612 6.73 6.806 509.502 509.506c9.882 9.866 21.768 27.77 21.768 56.578 0.002 50.71-38.996 121.148-101.654 183.818zM237.982 104.34l-69.73 69.728 69.25 203.228 18.498 6.704h64v-128h128v-64l-6.846-18.506-203.172-69.154z" /> | ||||
| <glyph unicode="r" d="M1012.8 545.8v391.6l-127.6-127.4c-96.6 96.8-225.2 150-362 150s-265.2-53.2-362-150c-96.8-96.8-150-225.2-150-362s53.2-265.4 150-362c96.8-96.8 225.2-150 362-150s265.4 53.2 362 150l-136.6 136.6c-124.2-124.2-326.4-124.2-450.8 0-124.2 124.2-124.2 326.4 0 450.8 124.2 124.2 326.4 124.2 450.8 0l-127.4-127.4h391.6z" /> | ||||
| <glyph unicode="s" d="M768 608c0-53.019-114.615-96-256-96s-256 42.981-256 96c0 53.019 114.615 96 256 96s256-42.981 256-96zM768 288v256c0-53-114.6-96-256-96s-256 43-256 96v-256c0-53 114.6-96 256-96s256 43 256 96zM832 960h-128v-192h127.6c0.2 0 0.2-0.2 0.4-0.4v-639.4c0-0.2-0.2-0.2-0.4-0.4h-127.6v-192h128c105.6 0 192 86.4 192 192v640.2c0 105.6-86.4 192-192 192zM192 128.4v639.4c0 0.2 0.2 0.2 0.4 0.4h127.6v191.8h-128c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h128v192h-127.6c-0.2 0-0.4 0.2-0.4 0.4z" /> | ||||
| <glyph unicode="t" d="M169.2 512c14 56.4 33 122 56.6 176.8 15.4 35.8 31.2 63.2 48.2 84 18.4 22.4 49 49.2 91 49.2s72.6-26.8 91-49.2c17-20.6 32.6-48.2 48.2-84 23.6-54.8 42.8-120.4 56.6-176.8h461.2v256c0 105.6-86.4 192-192 192h-640c-105.6 0-192-86.4-192-192v-256h171.2zM718.6 384h-127.2c25-93.4 48.4-144.4 63.6-168.6 15.2 24.2 38.6 75.2 63.6 168.6zM301.4 512h127.2c-25 93.4-48.4 144.4-63.6 168.6-15.2-24.2-38.6-75.2-63.6-168.6zM850.8 384c-14-56.4-33-122-56.6-176.8-15.4-35.8-31.2-63.2-48.2-84-18.4-22.4-49-49.2-91-49.2s-72.6 26.8-91 49.2c-17 20.6-32.6 48.2-48.2 84-23.6 54.8-42.8 120.4-56.6 176.8h-461.2v-256c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v256h-171.2z" /> | ||||
| <glyph unicode="v" d="M512 192l512 512h-1024z" /> | ||||
| <glyph unicode="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" /> | ||||
| <glyph unicode="y" d="M448 960v-128h320l-384-384 128-128 384 384v-320h128v576zM576 285.726v-157.382c-0.1-0.118-0.226-0.244-0.344-0.344h-383.312c-0.118 0.1-0.244 0.226-0.344 0.344v383.312c0.1 0.118 0.226 0.244 0.344 0.344h157.382l192 192h-349.726c-105.6 0-192-86.4-192-192v-384c0-105.6 86.4-192 192-192h384c105.6 0 192 86.4 192 192v349.726l-192-192z" /> | ||||
| <glyph unicode="z" d="M192.344 128c-0.118 0.1-0.244 0.224-0.344 0.344v191.656h-192v-192c0-105.6 86.4-192 192-192h192v192h-191.656zM192 767.656c0.1 0.118 0.224 0.244 0.344 0.344h191.656v192h-192c-105.6 0-192-86.4-192-192v-192h192v191.656zM832 960h-192v-192h191.656c0.118-0.1 0.244-0.226 0.344-0.344v-191.656h192v192c0 105.6-86.4 192-192 192zM832 128.344c-0.1-0.118-0.224-0.244-0.344-0.344h-191.656v-192h192c105.6 0 192 86.4 192 192v192h-192v-191.656z" /> | ||||
| <glyph unicode="{" d="M510-64l-256 512 256 512h-256l-256-512 256-512z" horiz-adv-x="512" /> | ||||
| <glyph unicode="}" d="M-2 960l256-512-256-512h256l256 512-256 512z" horiz-adv-x="512" /> | ||||
| <glyph unicode="à" d="M1024 128c0-105.6-86.4-192-192-192h-640c-105.6 0-192 86.4-192 192v640c0 105.6 86.4 192 192 192h640c105.6 0 192-86.4 192-192v-640z" /> | ||||
| <glyph unicode="á" d="M1024 576l-512 384-512-384 512-384zM512 64l-426.666 320-85.334-64 512-384 512 384-85.334 64z" /> | ||||
| <glyph unicode="â" d="M64 384c-35.346 0-64 28.654-64 64s28.654 64 64 64h896c35.346 0 64-28.654 64-64s-28.654-64-64-64h-896z" /> | ||||
| <glyph unicode="ã" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM896 64h-768v768h768v-768zM320 704l-128-128v-448h640v320l-128 128-128-128z" /> | ||||
| <glyph unicode="ä" d="M0 960v-256h128v64h256v-704h-192v-128h640v128h-192v704h256v-64h128v256z" /> | ||||
| <glyph unicode="å" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM128 832h320v-768h-320v768zM896 64h-320v768h320v-768z" /> | ||||
| <glyph unicode="ç" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM896 64h-320v768h320v-768z" /> | ||||
| <glyph unicode="è" d="M958.4 894.4c-43.8 43.8-101 65.6-158.4 65.6s-114.6-21.8-158.4-65.6l-128-128c-74-74-85.4-187-34-273l-12.8-12.8c-35.4 20.8-75 31.4-114.8 31.4-57.4 0-114.6-21.8-158.4-65.6l-128-128c-87.4-87.4-87.4-229.4 0-316.8 43.8-43.8 101-65.6 158.4-65.6s114.6 21.8 158.4 65.6l128 128c74 74 85.4 187 34 273l12.8 12.8c35.2-21 75-31.6 114.6-31.6 57.4 0 114.6 21.8 158.4 65.6l128 128c87.6 87.6 87.6 229.6 0.2 317zM419.8 220.2l-128-128c-18-18.2-42.2-28.2-67.8-28.2s-49.8 10-67.8 28.2c-37.4 37.4-37.4 98.4 0 135.8l128 128c18.2 18.2 42.2 28.2 67.8 28.2 5.6 0 11.2-0.6 16.8-1.4l-55.6-55.6c-10.4-10.4-16.2-24.2-16.2-38.8s5.8-28.6 16.2-38.8c10.4-10.4 24.2-16.2 38.8-16.2s28.6 5.8 38.8 16.2l55.6 55.6c5.4-30.4-3.6-62.2-26.6-85zM867.8 668.2l-128-128c-18-18.2-42.2-28.2-67.8-28.2-5.6 0-11.2 0.6-16.8 1.4l55.6 55.6c10.4 10.4 16.2 24.2 16.2 38.8s-5.8 28.6-16.2 38.8c-10.4 10.4-24.2 16.2-38.8 16.2s-28.6-5.8-38.8-16.2l-55.6-55.6c-5.2 29.8 3.6 61.6 26.6 84.6l128 128c18 18.4 42.2 28.4 67.8 28.4s49.8-10 67.8-28.2c37.6-37.4 37.6-98.2 0-135.6z" /> | ||||
| <glyph unicode="é" d="M255.884 256c0.040 0.034 0.082 0.074 0.116 0.116v127.884c0 70.58 57.42 128 128 128h255.884c0.040 0.034 0.082 0.074 0.116 0.116v127.884c0 70.58 57.42 128 128 128h143.658c-93.832 117.038-237.98 192-399.658 192-282.77 0-512-229.23-512-512 0-67.904 13.25-132.704 37.256-192h218.628zM768.116 640c-0.040-0.034-0.082-0.074-0.116-0.116v-127.884c0-70.58-57.42-128-128-128h-255.884c-0.040-0.034-0.082-0.074-0.116-0.116v-127.884c0-70.58-57.42-128-128-128h-143.658c93.832-117.038 237.98-192 399.658-192 282.77 0 512 229.23 512 512 0 67.904-13.25 132.704-37.256 192h-218.628z" /> | ||||
| <glyph unicode="ê" d="M702 452c-105.6 0-192 86.4-192 192v320h-320c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v320h-320zM766 580h256l-384 384v-256c0-70.4 57.6-128 128-128z" /> | ||||
| <glyph unicode="ë" d="M510 450l512-512h-1024zM510 962l512-512h-1024z" /> | ||||
| <glyph unicode="ì" d="M512-64l-512 1024h1024z" /> | ||||
| <glyph unicode="í" d="M512 960l512-1024h-1024z" /> | ||||
| <glyph unicode="î" d="M510 450l-512 512h1024zM510-62l-512 512h1024z" /> | ||||
| <glyph unicode="ï" d="M1024 448l-1024-512v1024z" /> | ||||
| <glyph unicode="ñ" d="M126 962h256v-1024h-256v1024zM638 962h256v-1024h-256v1024z" /> | ||||
| <glyph unicode="ò" d="M640 704v128c0 70.4-57.6 128-128 128h-384c-70.4 0-128-57.6-128-128v-384c0-70.4 57.6-128 128-128h128v139.6c0 134.8 109.6 244.4 244.4 244.4h139.6zM896 576h-384c-70.4 0-128-57.6-128-128v-384c0-70.4 57.6-128 128-128h384c70.4 0 128 57.6 128 128v384c0 70.4-57.6 128-128 128z" /> | ||||
| <glyph unicode="ó" d="M293.4 448l218.6 218.6 256-256v421.4c0 70.4-57.6 128-128 128h-512c-70.4 0-128-57.6-128-128v-512c0-70.4 57.6-128 128-128h421.4l-256 256zM1024 512h-128v-320l-384 384-128-128 384-384h-320v-128h576z" /> | ||||
| <glyph unicode="ô" d="M1024 448l-512 512v-307.2l-512-204.8v-256h512v-256z" /> | ||||
| <glyph unicode="õ" d="M638 898c0 35.4-28.6 64-64 64h-128c-35.4 0-64-28.6-64-64s28.6-64 64-64h128c35.4 0 64 28.6 64 64zM510 834c-247.4 0-448-200.6-448-448s200.6-448 448-448 448 200.6 448 448-200.6 448-448 448zM510 386h-336c0 185.2 150.8 336 336 336v-336z" /> | ||||
| <glyph unicode="ö" d="M448 578c0-35.2-28.8-64-64-64h-320c-35.2 0-64 28.8-64 64v320c0 35.2 28.8 64 64 64h320c35.2 0 64-28.8 64-64v-320zM1024 578c0-35.2-28.8-64-64-64h-320c-35.2 0-64 28.8-64 64v320c0 35.2 28.8 64 64 64h320c35.2 0 64-28.8 64-64v-320zM448 2c0-35.2-28.8-64-64-64h-320c-35.2 0-64 28.8-64 64v320c0 35.2 28.8 64 64 64h320c35.2 0 64-28.8 64-64v-320zM1024 2c0-35.2-28.8-64-64-64h-320c-35.2 0-64 28.8-64 64v320c0 35.2 28.8 64 64 64h320c35.2 0 64-28.8 64-64v-320z" /> | ||||
| <glyph unicode="" d="M832 447.6c0 0.2 0 0.2 0 0.4v320c0 105.6-86.4 192-192 192h-448c-105.6 0-192-86.4-192-192v-320c0-105.6 86.4-192 192-192h263.6l-197.2 445.6 573.6-254zM766.8 300.2l193.8 20.4-576.6 255.4 255.4-576.6 20.4 193.8 257-257.2 107.2 107.2z" /> | ||||
| <glyph unicode="" d="M998.208 111.136l-422.702 739.728c-34.928 61.124-92.084 61.124-127.012 0l-422.702-739.728c-34.928-61.126-5.906-111.136 64.494-111.136h843.428c70.4 0 99.422 50.010 64.494 111.136zM512 128c-35.2 0-64 28.8-64 64s28.8 64 64 64 64-28.8 64-64c0-35.2-28.8-64-64-64zM627.448 577.242l-38.898-194.486c-6.902-34.516-41.35-62.756-76.55-62.756s-69.648 28.24-76.552 62.758l-38.898 194.486c-6.902 34.516 16.25 62.756 51.45 62.756h128c35.2 0 58.352-28.24 51.448-62.758z" /> | ||||
| <glyph unicode="" d="M1024 448l-448-512v1024zM448 960l-448-512 448-512z" /> | ||||
| <glyph unicode="" 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" /> | ||||
| <glyph unicode=" " horiz-adv-x="512" d="" /> | ||||
| <glyph unicode="!" glyph-name="icon-alert-rect" d="M832 960h-640c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v640c0 105.6-86.4 192-192 192zM640 128c0-35.2-28.8-64-64-64h-128c-35.2 0-64 28.8-64 64v64c0 35.2 28.8 64 64 64h128c35.2 0 64-28.8 64-64v-64zM696.062 768.494l-48.124-384.988c-4.366-34.928-36.738-63.506-71.938-63.506h-128c-35.2 0-67.572 28.578-71.938 63.506l-48.124 384.988c-4.366 34.928 20.862 63.506 56.062 63.506h256c35.2 0 60.428-28.578 56.062-63.506z" /> | ||||
| <glyph unicode="*" glyph-name="icon-asterisk" d="M1004.166 619.542l-97.522 168.916-330.534-229.414 33.414 400.956h-195.048l33.414-400.956-330.534 229.414-97.522-168.916 363.944-171.542-363.944-171.542 97.522-168.916 330.534 229.414-33.414-400.956h195.048l-33.414 400.956 330.534-229.414 97.522 168.916-363.944 171.542z" /> | ||||
| <glyph unicode="+" glyph-name="icon-plus" d="M960 576h-330v320c0 35.2-28.8 64-64 64h-108c-35.2 0-64-28.8-64-64v-320h-330c-35.2 0-64-28.8-64-64v-128c0-35.2 28.8-64 64-64h330v-320c0-35.2 28.8-64 64-64h108c35.2 0 64 28.8 64 64v320h330c35.2 0 64 28.8 64 64v128c0 35.2-28.8 64-64 64z" /> | ||||
| <glyph unicode="-" glyph-name="icon-minus" d="M960 320c35.2 0 64 28.8 64 64v128c0 35.2-28.8 64-64 64h-896c-35.2 0-64-28.8-64-64v-128c0-35.2 28.8-64 64-64h896z" /> | ||||
| <glyph unicode="." glyph-name="icon-connectivity" d="M704 384c0-70.4-57.6-128-128-128h-128c-70.4 0-128 57.6-128 128v128c0 70.4 57.6 128 128 128h128c70.4 0 128-57.6 128-128v-128zM1024 448l-192 320v-640zM0 448l192 320v-640z" /> | ||||
| <glyph unicode="2" glyph-name="icon-check" d="M1024 960l-640-640-384 384v-384l384-384 640 640z" /> | ||||
| <glyph unicode="3" glyph-name="icon-box-with-dashed-lines" d="M640 704h-256c-70.4 0-128-57.6-128-128v-256c0-70.4 57.6-128 128-128h256c70.4 0 128 57.6 128 128v256c0 70.4-57.6 128-128 128zM0 960h192v-192h-192v192zM256 960h192v-128h-192v128zM576 960h192v-128h-192v128zM256 64h192v-128h-192v128zM576 64h192v-128h-192v128zM0 384h128v-192h-128v192zM0 704h128v-192h-128v192zM896 384h128v-192h-128v192zM896 704h128v-192h-128v192zM832 960h192v-192h-192v192zM0 128h192v-192h-192v192zM832 128h192v-192h-192v192z" /> | ||||
| <glyph unicode="5" glyph-name="icon-arrows-up-down" d="M512 960l512-448h-1024zM0 384l512-448 512 448z" /> | ||||
| <glyph unicode="6" glyph-name="icon-sine" d="M1022.294 448c-1.746 7.196-3.476 14.452-5.186 21.786-20.036 85.992-53.302 208.976-98 306.538-22.42 48.938-45.298 86.556-69.946 115.006-48.454 55.93-98.176 67.67-131.356 67.67s-82.902-11.74-131.356-67.672c-24.648-28.45-47.528-66.068-69.948-115.006-44.696-97.558-77.962-220.544-98-306.538-21.646-92.898-46.444-175.138-71.71-237.836-16.308-40.46-30.222-66.358-40.6-82.604-10.378 16.246-24.292 42.142-40.6 82.604-23.272 57.75-46.144 132.088-66.524 216.052h-197.362c1.746-7.196 3.476-14.452 5.186-21.786 20.036-85.992 53.302-208.976 98-306.538 22.42-48.938 45.298-86.556 69.946-115.006 48.454-55.932 98.176-67.672 131.356-67.672s82.902 11.74 131.356 67.672c24.648 28.45 47.528 66.068 69.948 115.006 44.696 97.558 77.962 220.544 98 306.538 21.646 92.898 46.444 175.138 71.71 237.836 16.308 40.46 30.222 66.358 40.6 82.604 10.378-16.246 24.292-42.142 40.6-82.604 23.274-57.748 46.146-132.086 66.526-216.050h197.36z" /> | ||||
| <glyph unicode="<" glyph-name="icon-arrow-left" d="M256 448l512-512v1024z" /> | ||||
| <glyph unicode=">" glyph-name="icon-arrow-right" d="M768 448l-512 512v-1024z" /> | ||||
| <glyph unicode="?" glyph-name="icon-object-unknown" d="M510 962l-512-320v-384l512-320 512 320v384l-512 320zM585.4 100.8c-21.2-20.8-46-30.8-76-30.8-31.2 0-56.2 9.8-76.2 29.6-20 20-29.6 44.8-29.6 76.2 0 30.4 10.2 55.2 31 76.2s45.2 31.2 74.8 31.2c29.6 0 54.2-10.4 75.6-32s31.8-46.4 31.8-76c-0.2-29-10.8-54-31.4-74.4zM638.2 413.4c-23.6-11.8-37.4-22-43.4-32.4-3.6-6.2-6-14.8-7.4-26.8v-41h-161.4v44.2c0 40.2 4.4 69.8 13 88 8 17.2 22.6 30.2 44.8 40l34.8 15.4c32 14.2 48.2 35.2 48.2 62.8 0 16-6 30.4-17.2 41.8-11.2 11.2-25.6 17.2-41.6 17.2-24 0-54.4-10-62.8-57.4l-2.2-12.2h-147l1.4 16.2c4 44.6 17 82.4 38.8 112.2 19.6 27 45.6 48.6 77 64.6s64.6 24 98.2 24c60.6 0 110.2-19.4 151.4-59.6 41.2-40 61.2-88 61.2-147.2 0-70.8-28.8-121.4-85.8-149.8z" /> | ||||
| <glyph unicode="A" glyph-name="icon-activity-mode" d="M512 960c-214.866 0-398.786-132.372-474.744-320h90.744c56.86 0 107.938-24.724 143.094-64h240.906l-192 192h256l320-320-320-320h-256l192 192h-240.906c-35.156-39.276-86.234-64-143.094-64h-90.744c75.958-187.628 259.878-320 474.744-320 282.77 0 512 229.23 512 512s-229.23 512-512 512z" /> | ||||
| <glyph unicode="C" glyph-name="icon-clock" d="M512 960c-282.77 0-512-229.23-512-512s229.23-512 512-512 512 229.23 512 512-229.23 512-512 512zM768 384h-256c-35.2 0-64 28.8-64 64v384c0 35.2 28.8 64 64 64s64-28.8 64-64v-320h192c35.2 0 64-28.8 64-64s-28.8-64-64-64z" /> | ||||
| <glyph unicode="D" glyph-name="icon-database" d="M1024 768c0-106.039-229.23-192-512-192s-512 85.961-512 192c0 106.039 229.23 192 512 192s512-85.961 512-192zM512 448c-282.77 0-512 85.962-512 192v-512c0-106.038 229.23-192 512-192s512 85.962 512 192v512c0-106.038-229.23-192-512-192z" /> | ||||
| <glyph unicode="F" glyph-name="icon-folder" d="M896 768h-320c-16.4 16.4-96.8 96.8-109.2 109.2l-37.4 37.4c-25 25-74.2 45.4-109.4 45.4h-256c-35.2 0-64-28.8-64-64v-384c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v128c0 70.4-57.6 128-128 128zM896 512h-768c-70.4 0-128-57.6-128-128v-320c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v320c0 70.4-57.6 128-128 128z" /> | ||||
| <glyph unicode="G" glyph-name="icon-gear" d="M1024 384v128l-140.976 35.244c-8.784 32.922-21.818 64.106-38.504 92.918l74.774 124.622-90.51 90.51-124.622-74.774c-28.812 16.686-59.996 29.72-92.918 38.504l-35.244 140.976h-128l-35.244-140.976c-32.922-8.784-64.106-21.818-92.918-38.504l-124.622 74.774-90.51-90.51 74.774-124.622c-16.686-28.812-29.72-59.996-38.504-92.918l-140.976-35.244v-128l140.976-35.244c8.784-32.922 21.818-64.106 38.504-92.918l-74.774-124.622 90.51-90.51 124.622 74.774c28.812-16.686 59.996-29.72 92.918-38.504l35.244-140.976h128l35.244 140.976c32.922 8.784 64.106 21.818 92.918 38.504l124.622-74.774 90.51 90.51-74.774 124.622c16.686 28.812 29.72 59.996 38.504 92.918l140.976 35.244zM704 448c0-106.038-85.962-192-192-192s-192 85.962-192 192 85.962 192 192 192 192-85.962 192-192z" /> | ||||
| <glyph unicode="H" glyph-name="icon-autoflow-tabular" d="M192 960c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h64v1024h-64zM384 960h256v-1024h-256v1024zM832 960h-64v-704h256v512c0 105.6-86.4 192-192 192z" /> | ||||
| <glyph unicode="I" glyph-name="icon-arrows-out" d="M0 448l256-256v512zM512 960l-256-256h512zM512-64l256 256h-512zM768 704v-512l256 256z" /> | ||||
| <glyph unicode="L" glyph-name="icon-layout" d="M448 960h-256c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h256v1024zM832 960h-256v-577.664h448v385.664c0 105.6-86.4 192-192 192zM576-64h256c105.6 0 192 86.4 192 192v129.664h-448v-321.664z" /> | ||||
| <glyph unicode="M" glyph-name="icon-magnify" d="M1024 64l-201.662 201.662c47.922 72.498 73.662 157.434 73.662 246.338 0 119.666-46.6 232.168-131.216 316.784s-197.118 131.216-316.784 131.216-232.168-46.6-316.784-131.216-131.216-197.118-131.216-316.784 46.6-232.168 131.216-316.784 197.118-131.216 316.784-131.216c88.904 0 173.84 25.74 246.338 73.662l201.662-201.662 128 128zM448 256c-141.16 0-256 114.842-256 256 0 141.16 114.84 256 256 256 141.158 0 256-114.84 256-256 0-141.158-114.842-256-256-256z" /> | ||||
| <glyph unicode="O" glyph-name="icon-people" d="M704 640h64c70.4 0 128 57.6 128 128v64c0 70.4-57.6 128-128 128h-64c-70.4 0-128-57.6-128-128v-64c0-70.4 57.6-128 128-128zM256 640h64c70.4 0 128 57.6 128 128v64c0 70.4-57.6 128-128 128h-64c-70.4 0-128-57.6-128-128v-64c0-70.4 57.6-128 128-128zM832 576h-192c-34.908 0-67.716-9.448-96-25.904 57.278-33.324 96-95.404 96-166.096v-448h384v448c0 105.6-86.4 192-192 192zM384 576h-192c-105.6 0-192-86.4-192-192v-448h576v448c0 105.6-86.4 192-192 192z" /> | ||||
| <glyph unicode="P" glyph-name="icon-person" d="M768 704c0-105.6-86.4-192-192-192h-128c-105.6 0-192 86.4-192 192v64c0 105.6 86.4 192 192 192h128c105.6 0 192-86.4 192-192v-64zM64-64v192c0 140.8 115.2 256 256 256h384c140.8 0 256-115.2 256-256v-192z" /> | ||||
| <glyph unicode="Q" glyph-name="icon-dictionary" d="M832 320c105.6 0 192 86.4 192 192v256c0 105.6-86.4 192-192 192v-320l-128 64-128-64v320h-384c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v192c0-105.6-86.4-192-192-192h-640v192h640z" /> | ||||
| <glyph unicode="S" glyph-name="icon-timeline" d="M256 704h384v-128h-384v128zM384 512h384v-128h-384v128zM320 320h384v-128h-384v128zM832 960h-128v-192h127.6c0.2 0 0.2-0.2 0.4-0.4v-639.4c0-0.2-0.2-0.2-0.4-0.4h-127.6v-192h128c105.6 0 192 86.4 192 192v640.2c0 105.6-86.4 192-192 192zM192 128.4v639.2c0 0.2 0.2 0.2 0.4 0.4h127.6v192h-128c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h128v192h-127.6c-0.2 0-0.4 0.2-0.4 0.4z" /> | ||||
| <glyph unicode="T" glyph-name="icon-telemetry" d="M718.6 384h-127.2c25-93.4 48.4-144.4 63.6-168.6 15.2 24.2 38.6 75.2 63.6 168.6zM794.2 207.2c-15.4-35.8-31.2-63.2-48.2-84-18.4-22.4-49-49.2-91-49.2s-72.6 26.8-91 49.2c-17 20.6-32.6 48.2-48.2 84-23.6 54.8-42.8 120.4-56.6 176.8h-457.2c31.4-252.6 247-448 508-448s476.6 195.4 508 448h-167.2c-14-56.4-33-122-56.6-176.8zM301.4 512h127.2c-25 93.4-48.4 144.4-63.6 168.6-15.2-24.2-38.6-75.2-63.6-168.6zM274 772.8c18.4 22.4 49 49.2 91 49.2s72.6-26.8 91-49.2c17-20.6 32.6-48.2 48.2-84 23.6-54.8 42.8-120.4 56.6-176.8h457.2c-31.4 252.6-246.8 448-508 448s-476.6-195.4-508-448h167.2c14 56.4 33 122 56.6 176.8 15.6 35.8 31.4 63.2 48.2 84z" /> | ||||
| <glyph unicode="V" glyph-name="icon-packet" d="M511.98 960l-511.98-320v-512c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v512l-512.020 320zM512 768l358.4-224-358.4-224-358.4 224 358.4 224z" /> | ||||
| <glyph unicode="X" glyph-name="icon-magnify-in" d="M640 576h-128v128h-128v-128h-128v-128h128v-128h128v128h128zM1024 64l-201.662 201.662c47.922 72.498 73.662 157.434 73.662 246.338 0 119.666-46.6 232.168-131.216 316.784s-197.118 131.216-316.784 131.216c-119.666 0-232.168-46.6-316.784-131.216s-131.216-197.118-131.216-316.784c0-119.666 46.6-232.168 131.216-316.784s197.118-131.216 316.784-131.216c88.904 0 173.84 25.74 246.338 73.662l201.662-201.662 128 128zM448 256c-141.16 0-256 114.842-256 256 0 141.16 114.84 256 256 256 141.158 0 256-114.84 256-256 0-141.158-114.842-256-256-256z" /> | ||||
| <glyph unicode="Y" glyph-name="icon-magnify-out" d="M256 576h384v-128h-384v128zM1024 64l-201.662 201.662c47.922 72.498 73.662 157.434 73.662 246.338 0 119.666-46.6 232.168-131.216 316.784s-197.118 131.216-316.784 131.216c-119.666 0-232.168-46.6-316.784-131.216s-131.216-197.118-131.216-316.784c0-119.666 46.6-232.168 131.216-316.784s197.118-131.216 316.784-131.216c88.904 0 173.84 25.74 246.338 73.662l201.662-201.662 128 128zM448 256c-141.16 0-256 114.842-256 256 0 141.16 114.84 256 256 256 141.158 0 256-114.84 256-256 0-141.158-114.842-256-256-256z" /> | ||||
| <glyph unicode="Z" glyph-name="icon-trash" d="M832 832h-192.36v64c0 35.2-28.8 64-64 64h-128c-35.2 0-64-28.8-64-64v-64h-191.64c-105.6 0-192-72-192-160s0-160 0-160h64v-384c0-105.6 86.4-192 192-192h512c105.6 0 192 86.4 192 192v384h64c0 0 0 72 0 160s-86.4 160-192 160zM320 128h-128v384h128v-384zM576 128h-128v384h128v-384zM832 128h-128v384h128v-384z" /> | ||||
| <glyph unicode="^" glyph-name="icon-arrow-up" d="M512 704l-512-512h1024z" /> | ||||
| <glyph unicode="_" glyph-name="icon-fullscreen-collapse" d="M191.656 128c0.118-0.1 0.244-0.224 0.344-0.344v-191.656h192v192c0 105.6-86.4 192-192 192h-192v-192h191.656zM192 768.344c-0.1-0.118-0.224-0.244-0.344-0.344h-191.656v-192h192c105.6 0 192 86.4 192 192v192h-192v-191.656zM832 576h192v192h-191.656c-0.118 0.1-0.244 0.226-0.344 0.344v191.656h-192v-192c0-105.6 86.4-192 192-192zM832 127.656c0.1 0.118 0.224 0.244 0.344 0.344h191.656v192h-192c-105.6 0-192-86.4-192-192v-192h192v191.656z" /> | ||||
| <glyph unicode="a" glyph-name="icon-activity" d="M576 896h-256l320-320h-290.256c-44.264 76.516-126.99 128-221.744 128h-128v-512h128c94.754 0 177.48 51.484 221.744 128h290.256l-320-320h256l448 448-448 448z" /> | ||||
| <glyph unicode="d" glyph-name="icon-database-query" d="M683.52 140.714c-50.782-28.456-109.284-44.714-171.52-44.714-194.094 0-352 157.906-352 352s157.906 352 352 352 352-157.906 352-352c0-62.236-16.258-120.738-44.714-171.52l191.692-191.692c8.516 13.89 13.022 28.354 13.022 43.212v640c0 106.038-229.23 192-512 192s-512-85.962-512-192v-640c0-106.038 229.23-192 512-192 126.11 0 241.548 17.108 330.776 45.46l-159.256 159.254zM352 448c0-88.224 71.776-160 160-160s160 71.776 160 160-71.776 160-160 160-160-71.776-160-160z" /> | ||||
| <glyph unicode="f" glyph-name="icon-folder-new" d="M896 768h-320c-16.4 16.4-96.8 96.8-109.2 109.2l-37.4 37.4c-25 25-74.2 45.4-109.4 45.4h-256c-35.2 0-64-28.8-64-64v-384c0 70.4 57.6 128 128 128h768c70.4 0 128-57.6 128-128v128c0 70.4-57.6 128-128 128zM896 512h-768c-70.4 0-128-57.6-128-128v-320c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v320c0 70.4-57.6 128-128 128zM704 160h-128v-128h-128v128h-128v128h128v128h128v-128h128v-128z" /> | ||||
| <glyph unicode="l" glyph-name="icon-lock" d="M832 576h-32v96c0 158.8-129.2 288-288 288s-288-129.2-288-288v-96h-32c-70.4 0-128-57.6-128-128v-384c0-70.4 57.6-128 128-128h640c70.4 0 128 57.6 128 128v384c0 70.4-57.6 128-128 128zM416 672c0 53 43 96 96 96s96-43 96-96v-96h-192v96z" /> | ||||
| <glyph unicode="m" glyph-name="icon-menu" d="M0 960h1024v-256h-1024v256zM0 576h1024v-256h-1024v256zM0 192h1024v-256h-1024v256z" /> | ||||
| <glyph unicode="o" glyph-name="icon-object" d="M512-64l512 320v384l-512.020 320-511.98-320v-384l512-320zM512 768l358.4-224-358.4-224-358.4 224 358.4 224z" /> | ||||
| <glyph unicode="p" glyph-name="icon-pencil" d="M922.344 858.32c-38.612 38.596-81.306 69.232-120.304 86.324-68.848 30.25-104.77 9.078-120.194-6.344l-516.228-516.216-3.136-9.152-162.482-476.932 485.998 165.612 6.73 6.806 509.502 509.506c9.882 9.866 21.768 27.77 21.768 56.578 0.002 50.71-38.996 121.148-101.654 183.818zM237.982 104.34l-69.73 69.728 69.25 203.228 18.498 6.704h64v-128h128v-64l-6.846-18.506-203.172-69.154z" /> | ||||
| <glyph unicode="r" glyph-name="icon-refresh" d="M1012.8 545.8v391.6l-127.6-127.4c-96.6 96.8-225.2 150-362 150s-265.2-53.2-362-150c-96.8-96.8-150-225.2-150-362s53.2-265.4 150-362c96.8-96.8 225.2-150 362-150s265.4 53.2 362 150l-136.6 136.6c-124.2-124.2-326.4-124.2-450.8 0-124.2 124.2-124.2 326.4 0 450.8 124.2 124.2 326.4 124.2 450.8 0l-127.4-127.4h391.6z" /> | ||||
| <glyph unicode="s" glyph-name="icon-database-in-brackets" d="M768 608c0-53.019-114.615-96-256-96s-256 42.981-256 96c0 53.019 114.615 96 256 96s256-42.981 256-96zM768 288v256c0-53-114.6-96-256-96s-256 43-256 96v-256c0-53 114.6-96 256-96s256 43 256 96zM832 960h-128v-192h127.6c0.2 0 0.2-0.2 0.4-0.4v-639.4c0-0.2-0.2-0.2-0.4-0.4h-127.6v-192h128c105.6 0 192 86.4 192 192v640.2c0 105.6-86.4 192-192 192zM192 128.4v639.4c0 0.2 0.2 0.2 0.4 0.4h127.6v191.8h-128c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h128v192h-127.6c-0.2 0-0.4 0.2-0.4 0.4z" /> | ||||
| <glyph unicode="t" glyph-name="icon-telemetry-panel" d="M169.2 512c14 56.4 33 122 56.6 176.8 15.4 35.8 31.2 63.2 48.2 84 18.4 22.4 49 49.2 91 49.2s72.6-26.8 91-49.2c17-20.6 32.6-48.2 48.2-84 23.6-54.8 42.8-120.4 56.6-176.8h461.2v256c0 105.6-86.4 192-192 192h-640c-105.6 0-192-86.4-192-192v-256h171.2zM718.6 384h-127.2c25-93.4 48.4-144.4 63.6-168.6 15.2 24.2 38.6 75.2 63.6 168.6zM301.4 512h127.2c-25 93.4-48.4 144.4-63.6 168.6-15.2-24.2-38.6-75.2-63.6-168.6zM850.8 384c-14-56.4-33-122-56.6-176.8-15.4-35.8-31.2-63.2-48.2-84-18.4-22.4-49-49.2-91-49.2s-72.6 26.8-91 49.2c-17 20.6-32.6 48.2-48.2 84-23.6 54.8-42.8 120.4-56.6 176.8h-461.2v-256c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v256h-171.2z" /> | ||||
| <glyph unicode="v" glyph-name="icon-arrow-down" d="M512 192l512 512h-1024z" /> | ||||
| <glyph unicode="x" glyph-name="icon-x-heavy" 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" /> | ||||
| <glyph unicode="y" glyph-name="icon-new-window" d="M448 960v-128h320l-384-384 128-128 384 384v-320h128v576zM576 285.726v-157.382c-0.1-0.118-0.226-0.244-0.344-0.344h-383.312c-0.118 0.1-0.244 0.226-0.344 0.344v383.312c0.1 0.118 0.226 0.244 0.344 0.344h157.382l192 192h-349.726c-105.6 0-192-86.4-192-192v-384c0-105.6 86.4-192 192-192h384c105.6 0 192 86.4 192 192v349.726l-192-192z" /> | ||||
| <glyph unicode="z" glyph-name="icon-fullscreen-expand" d="M192.344 128c-0.118 0.1-0.244 0.224-0.344 0.344v191.656h-192v-192c0-105.6 86.4-192 192-192h192v192h-191.656zM192 767.656c0.1 0.118 0.224 0.244 0.344 0.344h191.656v192h-192c-105.6 0-192-86.4-192-192v-192h192v191.656zM832 960h-192v-192h191.656c0.118-0.1 0.244-0.226 0.344-0.344v-191.656h192v192c0 105.6-86.4 192-192 192zM832 128.344c-0.1-0.118-0.224-0.244-0.344-0.344h-191.656v-192h192c105.6 0 192 86.4 192 192v192h-192v-191.656z" /> | ||||
| <glyph unicode="{" glyph-name="icon-pointer-left" horiz-adv-x="512" d="M510-64l-256 512 256 512h-256l-256-512 256-512z" /> | ||||
| <glyph unicode="}" glyph-name="icon-pointer-right" horiz-adv-x="512" d="M-2 960l256-512-256-512h256l256 512-256 512z" /> | ||||
| <glyph unicode="à" glyph-name="icon-box-round-corners" d="M1024 128c0-105.6-86.4-192-192-192h-640c-105.6 0-192 86.4-192 192v640c0 105.6 86.4 192 192 192h640c105.6 0 192-86.4 192-192v-640z" /> | ||||
| <glyph unicode="á" glyph-name="icon-layers" d="M1024 576l-512 384-512-384 512-384zM512 64l-426.666 320-85.334-64 512-384 512 384-85.334 64z" /> | ||||
| <glyph unicode="â" glyph-name="icon-line-horz" d="M64 384c-35.346 0-64 28.654-64 64s28.654 64 64 64h896c35.346 0 64-28.654 64-64s-28.654-64-64-64h-896z" /> | ||||
| <glyph unicode="ã" glyph-name="icon-image" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM896 64h-768v768h768v-768zM320 704l-128-128v-448h640v320l-128 128-128-128z" /> | ||||
| <glyph unicode="ä" glyph-name="icon-T" d="M0 960v-256h128v64h256v-704h-192v-128h640v128h-192v704h256v-64h128v256z" /> | ||||
| <glyph unicode="å" glyph-name="icon-two-parts-both" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM128 832h320v-768h-320v768zM896 64h-320v768h320v-768z" /> | ||||
| <glyph unicode="ç" glyph-name="icon-two-parts-one-only" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM896 64h-320v768h320v-768z" /> | ||||
| <glyph unicode="è" glyph-name="icon-chain-links" d="M958.4 894.4c-43.8 43.8-101 65.6-158.4 65.6s-114.6-21.8-158.4-65.6l-128-128c-74-74-85.4-187-34-273l-12.8-12.8c-35.4 20.8-75 31.4-114.8 31.4-57.4 0-114.6-21.8-158.4-65.6l-128-128c-87.4-87.4-87.4-229.4 0-316.8 43.8-43.8 101-65.6 158.4-65.6s114.6 21.8 158.4 65.6l128 128c74 74 85.4 187 34 273l12.8 12.8c35.2-21 75-31.6 114.6-31.6 57.4 0 114.6 21.8 158.4 65.6l128 128c87.6 87.6 87.6 229.6 0.2 317zM419.8 220.2l-128-128c-18-18.2-42.2-28.2-67.8-28.2s-49.8 10-67.8 28.2c-37.4 37.4-37.4 98.4 0 135.8l128 128c18.2 18.2 42.2 28.2 67.8 28.2 5.6 0 11.2-0.6 16.8-1.4l-55.6-55.6c-10.4-10.4-16.2-24.2-16.2-38.8s5.8-28.6 16.2-38.8c10.4-10.4 24.2-16.2 38.8-16.2s28.6 5.8 38.8 16.2l55.6 55.6c5.4-30.4-3.6-62.2-26.6-85zM867.8 668.2l-128-128c-18-18.2-42.2-28.2-67.8-28.2-5.6 0-11.2 0.6-16.8 1.4l55.6 55.6c10.4 10.4 16.2 24.2 16.2 38.8s-5.8 28.6-16.2 38.8c-10.4 10.4-24.2 16.2-38.8 16.2s-28.6-5.8-38.8-16.2l-55.6-55.6c-5.2 29.8 3.6 61.6 26.6 84.6l128 128c18 18.4 42.2 28.4 67.8 28.4s49.8-10 67.8-28.2c37.6-37.4 37.6-98.2 0-135.6z" /> | ||||
| <glyph unicode="é" glyph-name="icon-plot-resource" d="M255.884 256c0.040 0.034 0.082 0.074 0.116 0.116v127.884c0 70.58 57.42 128 128 128h255.884c0.040 0.034 0.082 0.074 0.116 0.116v127.884c0 70.58 57.42 128 128 128h143.658c-93.832 117.038-237.98 192-399.658 192-282.77 0-512-229.23-512-512 0-67.904 13.25-132.704 37.256-192h218.628zM768.116 640c-0.040-0.034-0.082-0.074-0.116-0.116v-127.884c0-70.58-57.42-128-128-128h-255.884c-0.040-0.034-0.082-0.074-0.116-0.116v-127.884c0-70.58-57.42-128-128-128h-143.658c93.832-117.038 237.98-192 399.658-192 282.77 0 512 229.23 512 512 0 67.904-13.25 132.704-37.256 192h-218.628z" /> | ||||
| <glyph unicode="ê" glyph-name="icon-page" d="M702 452c-105.6 0-192 86.4-192 192v320h-320c-105.6 0-192-86.4-192-192v-640c0-105.6 86.4-192 192-192h640c105.6 0 192 86.4 192 192v320h-320zM766 580h256l-384 384v-256c0-70.4 57.6-128 128-128z" /> | ||||
| <glyph unicode="ë" glyph-name="icon-arrow-double-up" d="M510 450l512-512h-1024zM510 962l512-512h-1024z" /> | ||||
| <glyph unicode="ì" glyph-name="icon-arrow-tall-down" d="M512-64l-512 1024h1024z" /> | ||||
| <glyph unicode="í" glyph-name="icon-arrow-tall-up" d="M512 960l512-1024h-1024z" /> | ||||
| <glyph unicode="î" glyph-name="icon-arrow-double-down" d="M510 450l-512 512h1024zM510-62l-512 512h1024z" /> | ||||
| <glyph unicode="ï" glyph-name="icon-play" d="M1024 448l-1024-512v1024z" /> | ||||
| <glyph unicode="ñ" glyph-name="icon-pause" d="M126 962h256v-1024h-256v1024zM638 962h256v-1024h-256v1024z" /> | ||||
| <glyph unicode="ò" glyph-name="icon-duplicate" d="M640 704v128c0 70.4-57.6 128-128 128h-384c-70.4 0-128-57.6-128-128v-384c0-70.4 57.6-128 128-128h128v139.6c0 134.8 109.6 244.4 244.4 244.4h139.6zM896 576h-384c-70.4 0-128-57.6-128-128v-384c0-70.4 57.6-128 128-128h384c70.4 0 128 57.6 128 128v384c0 70.4-57.6 128-128 128z" /> | ||||
| <glyph unicode="ó" glyph-name="icon-move" d="M293.4 448l218.6 218.6 256-256v421.4c0 70.4-57.6 128-128 128h-512c-70.4 0-128-57.6-128-128v-512c0-70.4 57.6-128 128-128h421.4l-256 256zM1024 512h-128v-320l-384 384-128-128 384-384h-320v-128h576z" /> | ||||
| <glyph unicode="ô" glyph-name="icon-link" d="M1024 448l-512 512v-307.2l-512-204.8v-256h512v-256z" /> | ||||
| <glyph unicode="õ" glyph-name="icon-timer" d="M638 898c0 35.4-28.6 64-64 64h-128c-35.4 0-64-28.6-64-64s28.6-64 64-64h128c35.4 0 64 28.6 64 64zM510 834c-247.4 0-448-200.6-448-448s200.6-448 448-448 448 200.6 448 448-200.6 448-448 448zM510 386h-336c0 185.2 150.8 336 336 336v-336z" /> | ||||
| <glyph unicode="ö" glyph-name="icon-thumbs-strip" d="M448 578c0-35.2-28.8-64-64-64h-320c-35.2 0-64 28.8-64 64v320c0 35.2 28.8 64 64 64h320c35.2 0 64-28.8 64-64v-320zM1024 578c0-35.2-28.8-64-64-64h-320c-35.2 0-64 28.8-64 64v320c0 35.2 28.8 64 64 64h320c35.2 0 64-28.8 64-64v-320zM448 2c0-35.2-28.8-64-64-64h-320c-35.2 0-64 28.8-64 64v320c0 35.2 28.8 64 64 64h320c35.2 0 64-28.8 64-64v-320zM1024 2c0-35.2-28.8-64-64-64h-320c-35.2 0-64 28.8-64 64v320c0 35.2 28.8 64 64 64h320c35.2 0 64-28.8 64-64v-320z" /> | ||||
| <glyph unicode="" glyph-name="icon-box-with-arrow-cursor" d="M832 447.6c0 0.2 0 0.2 0 0.4v320c0 105.6-86.4 192-192 192h-448c-105.6 0-192-86.4-192-192v-320c0-105.6 86.4-192 192-192h263.6l-197.2 445.6 573.6-254zM766.8 300.2l193.8 20.4-576.6 255.4 255.4-576.6 20.4 193.8 257-257.2 107.2 107.2z" /> | ||||
| <glyph unicode="" glyph-name="icon-datatable" d="M1024 768c0-106.039-229.23-192-512-192s-512 85.961-512 192c0 106.039 229.23 192 512 192s512-85.961 512-192zM512 448c-282.8 0-512 86-512 192v-512c0-106 229.2-192 512-192s512 86 512 192v512c0-106-229.2-192-512-192zM896 385v-256c-36.6-15.6-79.8-28.8-128-39.4v256c48.2 10.6 91.4 23.8 128 39.4zM256 345.6v-256c-48.2 10.4-91.4 23.8-128 39.4v256c36.6-15.6 79.8-28.8 128-39.4zM384 70v256c41-4 83.8-6 128-6s87 2.2 128 6v-256c-41-4-83.8-6-128-6s-87 2.2-128 6z" /> | ||||
| <glyph unicode="" glyph-name="icon-tabular-scrolling" d="M64 960c-35.2 0-64-28.8-64-64v-192h448v256h-384zM1024 704v192c0 35.2-28.8 64-64 64h-384v-256h448zM0 576v-192c0-35.2 28.8-64 64-64h384v256h-448zM960 320c35.2 0 64 28.8 64 64v192h-448v-256h384zM512-64l-256 256h512z" /> | ||||
| <glyph unicode="" glyph-name="icon-alert-triangle" d="M998.208 111.136l-422.702 739.728c-34.928 61.124-92.084 61.124-127.012 0l-422.702-739.728c-34.928-61.126-5.906-111.136 64.494-111.136h843.428c70.4 0 99.422 50.010 64.494 111.136zM512 128c-35.2 0-64 28.8-64 64s28.8 64 64 64 64-28.8 64-64c0-35.2-28.8-64-64-64zM627.448 577.242l-38.898-194.486c-6.902-34.516-41.35-62.756-76.55-62.756s-69.648 28.24-76.552 62.758l-38.898 194.486c-6.902 34.516 16.25 62.756 51.45 62.756h128c35.2 0 58.352-28.24 51.448-62.758z" /> | ||||
| <glyph unicode="" glyph-name="icon-tabular" d="M0 896v-192h448v256h-384c-35.2 0-64-28.8-64-64zM960 960h-384v-256h448v192c0 35.2-28.8 64-64 64zM576 576h448v-256h-448v256zM0 576h448v-256h-448v256zM0 0c0-35.2 28.8-64 64-64h384v256h-448v-192zM576-64h384c35.2 0 64 28.8 64 64v192h-448v-256z" /> | ||||
| <glyph unicode="" glyph-name="icon-calendar" d="M896 960h-768c-70.4 0-128-57.6-128-128v-768c0-70.4 57.6-128 128-128h768c70.4 0 128 57.6 128 128v768c0 70.4-57.6 128-128 128zM640 512h-256v192h256v-192zM384 448h256v-192h-256v192zM320 256h-256v192h256v-192zM320 704v-192h-256v192h256zM128 0c-17 0-33 6.6-45.2 18.8s-18.8 28.2-18.8 45.2v128h256v-192h-192zM384 0v192h256v-192h-256zM960 64c0-17-6.6-33-18.8-45.2s-28.2-18.8-45.2-18.8h-192v192h256v-128zM960 256h-256v192h256v-192zM960 512h-256v192h256v-192z" /> | ||||
| <glyph unicode="" glyph-name="icon-paint-bucket" d="M896 320c0 0-130-188-128-256 2-70.6 57.4-128 128-128s126 57.4 128 128c2 68-128 256-128 256zM449 831l0.2 64.8c0 35.4-28.4 64-63.8 64.2 0 0-0.2 0-0.2 0-35.2 0-63.8-28.6-64-63.8l-0.6-190.8-294-292.6c-50-50-12.4-215.2 112.4-340s290-162.4 340-112.4l417 423.6-447 447zM384 320c-70.6 0-128 57.4-128 128 0 47.4 25.8 89 64.4 111l-0.4-110.8c0-35.4 28.4-64 63.8-64.2 0 0 0.2 0 0.2 0 35.2 0 63.8 28.6 64 63.8l0.4 110.8c38-22.2 63.6-63.4 63.6-110.6 0-70.6-57.4-128-128-128z" /> | ||||
| <glyph unicode="" glyph-name="icon-x-in-circle-heavy" d="M512 960c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM832 256l-128-128-192 192-192-192-128 128 192 192-192 192 128 128 192-192 192 192 128-128-192-192 192-192z" /> | ||||
| <glyph unicode="" glyph-name="icon-info" d="M512 960c-282.8 0-512-229.2-512-512s229.2-512 512-512 512 229.2 512 512-229.2 512-512 512zM512 832c70.6 0 128-57.4 128-128s-57.4-128-128-128c-70.6 0-128 57.4-128 128s57.4 128 128 128zM704 128h-384v128h128v128h-128v128h320v-256h64v-128z" /> | ||||
| <glyph unicode="" glyph-name="icon-arrows-right-left" d="M1024 448l-448-512v1024zM448 960l-448-512 448-512z" /> | ||||
| <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> | ||||
| Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 27 KiB | 
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							| @@ -29,7 +29,7 @@ $interiorMargin: 5px; | ||||
| $interiorMarginLg: $interiorMargin * 2; | ||||
| $interiorMarginSm: 3px; | ||||
| $basicCr: 2px; | ||||
| $controlCr: 2px; | ||||
| $controlCr: 3px; | ||||
| $smallCr: 2px; | ||||
| $badgeW: 35px; | ||||
|  | ||||
| @@ -84,6 +84,7 @@ $tabularColorBodyBg: darken($colorBodyBg, 10%); | ||||
| $tabularColorBodyFg: lighten($tabularColorBodyBg, 40%); | ||||
| $tabularColorHeaderBg: lighten($colorBodyBg, 10%); | ||||
| $tabularColorHeaderFg: lighten($tabularColorHeaderBg, 40%); | ||||
| $tabularColorHeaderBorder: $colorBodyBg; | ||||
|  | ||||
| /************************** RATIOS */ | ||||
| $ltGamma: 20%; | ||||
| @@ -99,6 +100,7 @@ $ueAppLogoW: 105px; | ||||
| $ueEditToolBarH: 25px; | ||||
| $ueBrowseLeftPaneW: 25%; | ||||
| $ueEditLeftPaneW: 75%; | ||||
| $treeSearchInputBarH: 25px; | ||||
| // Overlay | ||||
| $ovrTopBarH: 60px; | ||||
| $ovrFooterH: 40px; | ||||
| @@ -115,9 +117,9 @@ $colorItemTreeIcon: $colorKey; | ||||
| $colorItemTreeIconHover: lighten($colorItemTreeIcon, 20%); | ||||
| $colorItemTreeVCHover: $colorAlt1; | ||||
| // Tabular | ||||
| $tabularHeaderH: 18px; | ||||
| $tabularHeaderH: 22px; //18px | ||||
| $tabularTdPadLR: $itemPadLR; | ||||
| $tabularTdPadTB: 2px; | ||||
| $tabularTdPadTB: 3px; | ||||
| // Imagery | ||||
| $imageMainControlBarH: 22px; | ||||
| $imageThumbsD: 120px; | ||||
| @@ -141,12 +143,11 @@ $reqSymbolM: $interiorMargin * 2; | ||||
| $reqSymbolFontSize: 0.7em; | ||||
|  | ||||
| /************************** CONTROLS */ | ||||
| $controlCr: $basicCr; | ||||
| $controlDisabledOpacity: 0.3; | ||||
| $formLabelW: 20%; | ||||
| $formInputH: 22px; | ||||
| $formRowCtrlsH: 14px; | ||||
| $menuLineH: 1.4rem; | ||||
| $menuLineH: 1.5rem; | ||||
| $scrollbarTrackSize: 10px; | ||||
| $scrollbarTrackColorBg: rgba(#000, 0.4); | ||||
| $btnStdH: 25px; | ||||
|   | ||||
| @@ -50,6 +50,11 @@ input, textarea { | ||||
| 	font-family: Helvetica, Arial, sans-serif; | ||||
| } | ||||
|  | ||||
| input[type="text"] { | ||||
| 	vertical-align: baseline; | ||||
| 	padding: 3px 5px !important; | ||||
| } | ||||
|  | ||||
| h1, h2, h3 { | ||||
| 	margin: 0; | ||||
| } | ||||
|   | ||||
| @@ -1,3 +1,4 @@ | ||||
| /***************************************************************************** | ||||
| /***************************************************************************** | ||||
|  * Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
| @@ -31,10 +32,10 @@ | ||||
| @import "global"; | ||||
| @import "fonts"; | ||||
| @import "user-environ/layout"; | ||||
| //@import "search/layout"; | ||||
| @import "fixed-position"; | ||||
| @import "about"; | ||||
| @import "text"; | ||||
| @import "badges"; | ||||
| @import "icons"; | ||||
| @import "limits"; | ||||
| @import "data-status"; | ||||
| @@ -49,7 +50,6 @@ | ||||
| @import "edit/editor"; | ||||
| @import "features/imagery"; | ||||
| @import "features/time-display"; | ||||
| @import "forms/mixins"; | ||||
| @import "forms/elems"; | ||||
| @import "forms/validation"; | ||||
| @import "forms/text-input"; | ||||
| @@ -70,5 +70,10 @@ | ||||
| @import "properties"; | ||||
| @import "autoflow"; | ||||
| @import "iframe"; | ||||
| @import "messages"; | ||||
| @import "initialization"; | ||||
| @import "hide-non-functional"; | ||||
| @import "views"; | ||||
| @import "panes/pane"; | ||||
| @import "inspector/inspector"; | ||||
| @import "inspector/plot"; | ||||
|   | ||||
							
								
								
									
										12
									
								
								platform/commonUI/general/res/sass/_messages.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								platform/commonUI/general/res/sass/_messages.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| /* Styles for messages */ | ||||
|  | ||||
| .message { | ||||
| 	&.block { | ||||
| 		@include border-radius($basicCr); | ||||
| 		padding: $interiorMarginLg; | ||||
| 	} | ||||
| 	&.error { | ||||
| 		background-color: rgba($colorAlert,0.3); | ||||
| 		color: lighten($colorAlert, 20%); | ||||
| 	} | ||||
| } | ||||
| @@ -259,6 +259,38 @@ | ||||
| 	@include text-shadow(rgba(black, $sVal) 0 3px 7px); | ||||
| } | ||||
|  | ||||
| /*********************************************** FORM ELEMENTS */ | ||||
| @mixin input-base($bg: $colorBodyBg, $fg: $colorBodyFg) { | ||||
| 	@include appearance(none); | ||||
| 	@include border-radius($controlCr); | ||||
| 	@include box-sizing(border-box); | ||||
| 	@include box-shadow(inset rgba(black, 0.65) 0 1px 4px); | ||||
| 	//	background: lighten($bg, 20%); | ||||
| 	background: rgba(#fff, 0.1); | ||||
| 	border: none; | ||||
| 	//border-bottom: 1px solid rgba(#fff, 0.1); | ||||
| 	color: lighten($fg, 20%); | ||||
| 	outline: none; | ||||
| 	&.error { | ||||
| 		background: rgba(red, 0.5); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @mixin nice-input($bg: $colorBodyBg, $fg: $colorBodyFg) { | ||||
| 	@include input-base($bg, $fg); | ||||
| 	padding: 0 $interiorMarginSm; | ||||
| } | ||||
|  | ||||
| @mixin nice-textarea($bg: $colorBodyBg, $fg: $colorBodyFg) { | ||||
| 	@include input-base($bg, $fg); | ||||
| 	padding: $interiorMargin; | ||||
| } | ||||
|  | ||||
| @mixin subdued-input($bg: $colorBodyBg, $fg: $colorBodyFg) { | ||||
| 	@include nice-input($bg, $fg); | ||||
| 	background: lighten($bg, 3%); | ||||
| 	border-bottom: 1px solid lighten($bg, 10%); | ||||
| } | ||||
|  | ||||
| /* | ||||
| @mixin invokeMenu($baseColor: $colorBodyFg) { | ||||
|   | ||||
							
								
								
									
										21
									
								
								platform/commonUI/general/res/sass/_views.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								platform/commonUI/general/res/sass/_views.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| /* Styles for sub-dividing views generically */ | ||||
|  | ||||
| .l-view-section { | ||||
| 	@include absPosDefault(0); | ||||
| 	font-size: 0.8rem; | ||||
| 	h2 { | ||||
| 		color: #fff; | ||||
| 		margin-bottom: $interiorMargin; | ||||
| 	} | ||||
| 	&.fixed { | ||||
| 		font-size: 0.8em; | ||||
| 	} | ||||
| 	&.scrolling { | ||||
| 		overflow: auto; | ||||
| 	} | ||||
| 	.controls, | ||||
| 	label, | ||||
| 	.inline-block { | ||||
| 		display: inline-block; | ||||
| 	} | ||||
| } | ||||
| @@ -21,15 +21,15 @@ | ||||
|  *****************************************************************************/ | ||||
| /******************************************************** MENUS */ | ||||
| .menu-element { | ||||
|     $bg: lighten($colorBodyBg, 5%); | ||||
| 	$bg: lighten($colorBodyBg, 5%); | ||||
| 	$bgHover: lighten($bg, 20%); | ||||
| 	$iconColor: $colorKey; | ||||
| 	cursor: pointer; | ||||
| 	position: relative; | ||||
| 	.menu { | ||||
| 		@include border-radius($basicCr); | ||||
|         @include containerSubtle($bg); | ||||
|         @include txtShdwSubtle(0.2); | ||||
| 		@include containerSubtle($bg); | ||||
| 		@include txtShdwSubtle(0.2); | ||||
| 		display: block; // set to block via jQuery | ||||
| 		padding: $interiorMarginSm 0; | ||||
| 		position: absolute; | ||||
| @@ -37,11 +37,12 @@ | ||||
| 		ul { | ||||
| 			@include menuUlReset(); | ||||
| 			li { | ||||
|                 @include box-sizing(border-box); | ||||
| 				@include box-sizing(border-box); | ||||
| 				border-top: 1px solid lighten($bg, 20%); | ||||
| 				color: lighten($bg, 60%); | ||||
| 				line-height: $menuLineH; | ||||
| 				padding: $interiorMarginSm $interiorMargin * 2 $interiorMarginSm ($interiorMargin * 2) + $treeTypeIconW; | ||||
| 				position: relative; | ||||
| 				white-space: nowrap; | ||||
| 				&:first-child { | ||||
| 					border: none; | ||||
| @@ -61,7 +62,7 @@ | ||||
| 				//	display: block; | ||||
| 				//} | ||||
| 				.type-icon { | ||||
|                     left: $interiorMargin * 2; | ||||
| 					left: $interiorMargin * 2; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| @@ -77,7 +78,9 @@ | ||||
| 		@include containerSubtle($bg); | ||||
| 		ul li { | ||||
| 			padding-left: 25px; | ||||
| 			a { color: $fg; } | ||||
| 			a { | ||||
| 				color: $fg; | ||||
| 			} | ||||
| 			.icon { | ||||
| 				color: $ic; | ||||
| 			} | ||||
| @@ -90,99 +93,131 @@ | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	.checkbox-menu { | ||||
| 		// Used in search dropdown in tree | ||||
| 		@extend .context-menu; | ||||
| 		ul li { | ||||
| 			padding-left: 50px; | ||||
| 			.checkbox { | ||||
| 				$d: 0.7rem; | ||||
| 				position: absolute; | ||||
| 				left: $interiorMargin; | ||||
| 				top: ($menuLineH - $d) / 1.5; | ||||
| 				em { | ||||
| 					height: $d; | ||||
| 					width: $d; | ||||
| 					&:before { | ||||
| 						font-size: 7px !important;// $d/2; | ||||
| 						height: $d; | ||||
| 						width: $d; | ||||
| 						line-height: $d; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			.type-icon { | ||||
| 				left: 25px; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
|     .super-menu { | ||||
|         $w: 500px; | ||||
|         $h: $w - 20; | ||||
|         $plw: 50%; //$w * 0.5; | ||||
|         $prw: 50%; //$w - $plw; | ||||
| 	    $fg: #fff; //lighten($colorBodyFg, 40%); | ||||
| 	    $bgHover: $colorKey; //$bg; | ||||
| 	    display: block; | ||||
|         width: $w; | ||||
|         height: $h; | ||||
|         .contents { | ||||
| 	        @include absPosDefault($interiorMargin); | ||||
|         } | ||||
|         .pane { | ||||
|             @include box-sizing(border-box); | ||||
|             &.left { | ||||
|                 //@include test(); | ||||
|                 border-right: 1px solid rgba(white, 0.2); | ||||
|                 left: 0; | ||||
|                 padding-right: $interiorMargin; | ||||
|                 right: auto; | ||||
|                 width: $plw; | ||||
|                 overflow-x: hidden; | ||||
|                 overflow-y: auto; | ||||
|                 ul { | ||||
|                     li { | ||||
|                         @include border-radius($controlCr); | ||||
| 	                    padding-left: 30px; | ||||
|                         border-top: none; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             &.right { | ||||
| 	            //@include test(red); | ||||
| 	            left: auto; | ||||
|                 right: 0; | ||||
|                 padding: $interiorMargin * 5; | ||||
|                 width: $prw; | ||||
| 	            .icon { | ||||
| 		            color: $fg; | ||||
| 	            } | ||||
|             } | ||||
|         } | ||||
| 	    .menu-item-description { | ||||
| 		    .desc-area { | ||||
| 			    &.icon { | ||||
| 				    $h: 150px; | ||||
| 				    position: relative; | ||||
| 				    font-size: 8em; | ||||
| 				    left: 0; | ||||
| 				    height: $h; | ||||
| 				    line-height: $h; | ||||
| 				    margin-bottom: $interiorMargin * 5; | ||||
| 				    text-align: center; | ||||
| 			    } | ||||
| 			    &.title { | ||||
| 				    color: $fg; | ||||
| 				    font-size: 1.2em; | ||||
| 				    margin-bottom: 0.5em; | ||||
| 			    } | ||||
| 			    &.description { | ||||
| 				    //color: lighten($bg, 30%); | ||||
| 				    color: $fg; | ||||
| 				    font-size: 0.8em; | ||||
| 				    line-height: 1.5em; | ||||
| 			    } | ||||
| 		    } | ||||
| 	    } | ||||
|     } | ||||
|     .context-menu { | ||||
|         font-size: 0.80rem; | ||||
|     } | ||||
| 	.super-menu { | ||||
| 		$w: 500px; | ||||
| 		$h: $w - 20; | ||||
| 		$plw: 50%; //$w * 0.5; | ||||
| 		$prw: 50%; //$w - $plw; | ||||
| 		$fg: #fff; //lighten($colorBodyFg, 40%); | ||||
| 		$bgHover: $colorKey; //$bg; | ||||
| 		display: block; | ||||
| 		width: $w; | ||||
| 		height: $h; | ||||
| 		.contents { | ||||
| 			@include absPosDefault($interiorMargin); | ||||
| 		} | ||||
| 		.pane { | ||||
| 			@include box-sizing(border-box); | ||||
| 			&.left { | ||||
| 				//@include test(); | ||||
| 				border-right: 1px solid rgba(white, 0.2); | ||||
| 				left: 0; | ||||
| 				padding-right: $interiorMargin; | ||||
| 				right: auto; | ||||
| 				width: $plw; | ||||
| 				overflow-x: hidden; | ||||
| 				overflow-y: auto; | ||||
| 				ul { | ||||
| 					li { | ||||
| 						@include border-radius($controlCr); | ||||
| 						padding-left: 30px; | ||||
| 						border-top: none; | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 			&.right { | ||||
| 				//@include test(red); | ||||
| 				left: auto; | ||||
| 				right: 0; | ||||
| 				padding: $interiorMargin * 5; | ||||
| 				width: $prw; | ||||
| 				.icon { | ||||
| 					color: $fg; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		.menu-item-description { | ||||
| 			.desc-area { | ||||
| 				&.icon { | ||||
| 					$h: 150px; | ||||
| 					position: relative; | ||||
| 					font-size: 8em; | ||||
| 					left: 0; | ||||
| 					height: $h; | ||||
| 					line-height: $h; | ||||
| 					margin-bottom: $interiorMargin * 5; | ||||
| 					text-align: center; | ||||
| 				} | ||||
| 				&.title { | ||||
| 					color: $fg; | ||||
| 					font-size: 1.2em; | ||||
| 					margin-bottom: 0.5em; | ||||
| 				} | ||||
| 				&.description { | ||||
| 					//color: lighten($bg, 30%); | ||||
| 					color: $fg; | ||||
| 					font-size: 0.8em; | ||||
| 					line-height: 1.5em; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	.context-menu { | ||||
| 		font-size: 0.80rem; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .context-menu-holder { | ||||
|     pointer-events: none; | ||||
|     position: absolute; | ||||
|     height: 200px; | ||||
|     width: 170px; | ||||
|     z-index: 70; | ||||
|     .context-menu-wrapper { | ||||
|         position: absolute; | ||||
|         height: 100%; | ||||
|         width: 100%; | ||||
|         .context-menu { | ||||
|         } | ||||
|     } | ||||
|     &.go-left .context-menu { right: 0; } | ||||
|     &.go-up .context-menu { bottom: 0; } | ||||
| 	pointer-events: none; | ||||
| 	position: absolute; | ||||
| 	height: 200px; | ||||
| 	width: 170px; | ||||
| 	z-index: 70; | ||||
| 	.context-menu-wrapper { | ||||
| 		position: absolute; | ||||
| 		height: 100%; | ||||
| 		width: 100%; | ||||
| 		.context-menu { | ||||
| 		} | ||||
| 	} | ||||
| 	&.go-left .context-menu { | ||||
| 		right: 0; | ||||
| 	} | ||||
| 	&.go-up .context-menu { | ||||
| 		bottom: 0; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .btn-bar.right .menu, | ||||
| .menus-to-left .menu { | ||||
|     left: auto; right: 0; width: auto; | ||||
| 	left: auto; | ||||
| 	right: 0; | ||||
| 	width: auto; | ||||
| } | ||||
| @@ -86,13 +86,6 @@ | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			input[type="text"] { | ||||
| 				height: $formInputH; | ||||
| 				line-height: $formInputH; | ||||
| 				margin-top: -4px; | ||||
| 				vertical-align: baseline; | ||||
| 			} | ||||
|  | ||||
| 			.l-med input[type="text"] { | ||||
| 				width: 200px; | ||||
| 			} | ||||
|   | ||||
| @@ -23,11 +23,11 @@ | ||||
| 	@include appearance(none); | ||||
| 	@include border-radius($controlCr); | ||||
| 	@include box-sizing(border-box); | ||||
| 	@include box-shadow(inset rgba(black, 0.5) 0 1px 5px); | ||||
| 	@include box-shadow(inset rgba(black, 0.65) 0 1px 4px); | ||||
| //	background: lighten($bg, 20%); | ||||
| 	background: rgba(#fff, 0.1); | ||||
| 	border: none; | ||||
| 	border-bottom: 1px solid rgba(#fff, 0.1); | ||||
| 	//border-bottom: 1px solid rgba(#fff, 0.1); | ||||
| 	color: lighten($fg, 20%); | ||||
| 	outline: none; | ||||
| 	&.error { | ||||
|   | ||||
| @@ -48,19 +48,15 @@ | ||||
| 			width: 100%; | ||||
| 			tr { | ||||
| 				td { | ||||
| 					//max-width: 150px; | ||||
| 					padding: 2px 0; | ||||
| 					vertical-align: top; | ||||
| 					//white-space: nowrap; | ||||
| 					//overflow: hidden; | ||||
| 					//text-overflow: ellipsis; | ||||
| 					&.label { | ||||
| 						padding-right: $interiorMargin * 2; | ||||
| 						white-space: nowrap; | ||||
| 					} | ||||
| 					&.value { | ||||
| 						white-space: nowrap; | ||||
| 						//width: 90%; | ||||
| 						//word-wrap: break-word; // Doesn't work in <td>? | ||||
| 						word-break: break-all; | ||||
| 					} | ||||
| 					&.align-wrap { | ||||
| 						white-space: normal; | ||||
| @@ -118,7 +114,9 @@ | ||||
| 		z-index: 2; | ||||
| 	} | ||||
| 	&.arw-up .arw.arw-down, | ||||
| 	&.arw-down .arw.arw-up { display: none; } | ||||
| 	&.arw-down .arw.arw-up { | ||||
| 		display: none; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //************************************************* LOOK AND FEEL | ||||
| @@ -131,6 +129,7 @@ | ||||
| 		@include triangle('down', $bubbleArwSize, 1.5, $colorThumbsBubbleBg); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .s-infobubble { | ||||
| 	$emFg: darken($colorInfoBubbleFg, 20%); | ||||
| 	@include border-radius($basicCr); | ||||
| @@ -142,18 +141,31 @@ | ||||
| 		color: $emFg; | ||||
| 		font-weight: bold; | ||||
| 	} | ||||
| 	tr { | ||||
| 		td { | ||||
| 			border-top: 1px solid darken($colorInfoBubbleBg, 10%); | ||||
| 			font-size: 0.9em; | ||||
| 		} | ||||
| 		&:first-child td { | ||||
| 			border-top: none; | ||||
| 	table { | ||||
| 		tr { | ||||
| 			td { | ||||
| 				border: none; | ||||
| 				border-top: 1px solid darken($colorInfoBubbleBg, 10%) !important; | ||||
| 				font-size: 0.9em; | ||||
| 			} | ||||
|  | ||||
| 			&:first-child td { | ||||
| 				border-top: none !important; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 	&:first-child td { | ||||
| 		border-top: none; | ||||
| 	} | ||||
|  | ||||
| 	.label { | ||||
| 		color: lighten($emFg, 30%); | ||||
| 	} | ||||
|  | ||||
| 	.value { | ||||
| 		color: $emFg; | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| .s-thumbsbubble { | ||||
|   | ||||
| @@ -50,6 +50,12 @@ | ||||
| 	margin-top: $d / -1; | ||||
| 	margin-left: $d / -1; | ||||
| 	z-index: 2; | ||||
| 	&.inline { | ||||
| 		display: inline-block !important; | ||||
| 		margin-right: $interiorMargin; | ||||
| 		position: relative !important; | ||||
| 		vertical-align: middle; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| .l-wait-spinner-holder { | ||||
| @@ -80,4 +86,14 @@ | ||||
| 	margin: 0 !important; | ||||
| 	padding: 0 !important; | ||||
| 	top: 2px; left: 0; | ||||
| } | ||||
|  | ||||
| .wait-spinner.sm { | ||||
| 	$d: 13px; | ||||
| 	@include wait-spinner(0.25em, $colorKey); | ||||
| 	height: $d; width: $d; | ||||
| 	margin-left: 0 !important; | ||||
| 	margin-top: 0 !important; | ||||
| 	padding: 0 !important; | ||||
| 	top: 0; left: 0; | ||||
| } | ||||
							
								
								
									
										123
									
								
								platform/commonUI/general/res/sass/inspector/_inspector.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										123
									
								
								platform/commonUI/general/res/sass/inspector/_inspector.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,123 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| // Added by shale on 08/27/2015. Styling for the object inspector.  | ||||
|  | ||||
| .holder.inspector-holder { | ||||
|     overflow-y: auto; | ||||
|     overflow-x: hidden; | ||||
|  | ||||
|     .info-icon { | ||||
|         color: $colorKey; | ||||
|     } | ||||
|  | ||||
|     .number-selected { | ||||
|         font-size: .8em; | ||||
|         padding: 6px; | ||||
|         background-color: lighten($colorBodyBg, 15%); | ||||
|         color: lighten($colorBodyBg, 45%); | ||||
|         border-radius: 4px; | ||||
|         margin-top: 4px; | ||||
|     } | ||||
|  | ||||
|     ul li { | ||||
|         font-size: 0.9em; | ||||
|  | ||||
|         // Add spacing between items | ||||
|         padding: 2px 0px; | ||||
|         margin: 2px 0px; | ||||
|         border-top: solid 1px grey; | ||||
|         &:first-child { | ||||
|             border-top-width: 0px; | ||||
|         } | ||||
|  | ||||
|         // Style the titles | ||||
|         em { | ||||
|             font-weight: bold; | ||||
|             line-height: 1.25em; | ||||
|  | ||||
|             &:after { | ||||
|                 content: '\A'; | ||||
|                 white-space: pre; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Style object labels  | ||||
|         .inspector-location { | ||||
|             display: inline-block; | ||||
|             max-width: 100%; | ||||
|  | ||||
|             .label { | ||||
|                 cursor: pointer; | ||||
|                 display: inline-block; | ||||
|                 white-space: nowrap; | ||||
|  | ||||
|                 // Colors | ||||
|                 transition: background-color 0.2s; | ||||
|                 &:hover { | ||||
|                     background-color: lighten($colorBodyBg, 5%); | ||||
|                 } | ||||
|  | ||||
|                 // Sizing and spacing  | ||||
|                 border-radius: 4px; | ||||
|                 padding: 3px; | ||||
|                 margin: 2px; | ||||
|  | ||||
|                 // Horizontal overflow  | ||||
|                 max-width: 100%; | ||||
|                 text-overflow: ellipsis; | ||||
|                 overflow-x: hidden; | ||||
|  | ||||
|                 .icon.type-icon { | ||||
|                     font-size: 14px; | ||||
|  | ||||
|                     .l-icon-link { | ||||
|                         color: $colorIconLink; | ||||
|  | ||||
|                         font-size: 6px; | ||||
|                         margin-left: -22px; | ||||
|                         margin-right: 9px; | ||||
|  | ||||
|                         @include txtShdwSubtle(1); | ||||
|                         z-index: 2; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Add arrows to indicate tree heirarchy  | ||||
|             &:after { | ||||
|                 content: '>'; | ||||
|                 font-family: symbolsfont; | ||||
|                 font-size: 8px; | ||||
|  | ||||
|                 //margin-left: -6px; | ||||
|                 position: relative; | ||||
|                 top: -8px; | ||||
|                 left: -4px; | ||||
|             } | ||||
|             &:last-child:after { | ||||
|                 content: ''; | ||||
|                 display: inline-block; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										39
									
								
								platform/commonUI/general/res/sass/inspector/_plot.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								platform/commonUI/general/res/sass/inspector/_plot.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| // Added by shale on 08/26/2015. Additional styling for inspection.  | ||||
|  | ||||
| // Make plot legend items clickable  | ||||
| .plot-legend-item { | ||||
|     cursor: pointer; | ||||
|      | ||||
|     &.inspected { | ||||
|         background-color: $colorKeySelectedBg; | ||||
|      | ||||
|         &.s-limit-upr-yellow:before, | ||||
|         &.s-limit-upr-red:before,  | ||||
|         &.s-limit-lwr-yellow:before,  | ||||
|         &.s-limit-lwr-red:before { | ||||
|             color: lighten($colorKeySelectedBg, 20%); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| @@ -24,13 +24,14 @@ | ||||
| 	height: 100%; | ||||
| } | ||||
|  | ||||
| .tabular { | ||||
| .tabular, | ||||
| table { | ||||
| 	@include box-sizing(border-box); | ||||
| 	border-spacing: 0; | ||||
| 	border-collapse: collapse; | ||||
| 	color: #fff; | ||||
| 	display: table; | ||||
| 	font-size: 0.75em; | ||||
| 	font-size: 0.75rem; | ||||
| 	position: relative; | ||||
| 	//height: 100%; MOVED | ||||
| 	width: 100%; | ||||
| @@ -41,19 +42,7 @@ | ||||
| 		//table-layout: fixed; MOVED | ||||
| 	} | ||||
| 	thead, .thead { | ||||
| 		//width: calc(100% - 10px); MOVED | ||||
| 		tr, .tr { | ||||
| 			height: $tabularHeaderH; | ||||
| 		} | ||||
| 		&:before { | ||||
| 			content: ""; | ||||
| 			display: block; | ||||
| 			z-index: 0; | ||||
| 			position: absolute; | ||||
| 			width: 100%; | ||||
| 			height: $tabularHeaderH; | ||||
| 			background: rgba(#fff, 0.15); | ||||
| 		} | ||||
| 		border-bottom: 1px solid $tabularColorHeaderBorder; | ||||
| 	} | ||||
| 	tbody, .tbody { | ||||
| 		//@include absPosDefault(0); MOVED | ||||
| @@ -72,38 +61,49 @@ | ||||
| 		&:first-child .td { | ||||
| 			border-top: none; | ||||
| 		} | ||||
| 		&.group-header { | ||||
| 			td, .td { | ||||
| 				$d: 5%; | ||||
| 				background-color: darken($tabularColorHeaderBg, $d); | ||||
| 				color: darken($tabularColorHeaderFg, $d); | ||||
| 			} | ||||
| 		} | ||||
| 		th, .th, td, .td { | ||||
| 			display: table-cell; | ||||
| 		} | ||||
| 		th, .th { | ||||
| 			border: none; | ||||
| 			border-left: 1px solid $tabularColorBorder; | ||||
| 			background-color: $tabularColorHeaderBg; | ||||
| 			border-left: 1px solid $tabularColorHeaderBorder; | ||||
| 			color: $tabularColorHeaderFg; | ||||
| 			padding: 0 $tabularTdPadLR; | ||||
| 			padding: $tabularTdPadLR $tabularTdPadLR; | ||||
| 			white-space: nowrap; | ||||
| 			vertical-align: middle; // This is crucial to hiding f**king 4px height injected by browser by default | ||||
| 			&:first-child { | ||||
| 				border-left: none; | ||||
| 			} | ||||
| 			&.sort { | ||||
| 				.icon-sorting:before { | ||||
| 					display: inline-block; | ||||
| 				&.sort:after { | ||||
| 					color: $colorIconLink; | ||||
| 					font-family: symbolsfont; | ||||
| 					margin-left: 5px; | ||||
| 					font-size: 8px; | ||||
| 					content: "\ed"; | ||||
| 					display: inline-block; | ||||
| 					margin-left: $interiorMarginSm; | ||||
| 				} | ||||
| 				&.asc .icon-sorting:before { | ||||
| 					content: '0'; | ||||
| 				} | ||||
| 				&.desc .icon-sorting:before { | ||||
| 					content: '1'; | ||||
| 				&.sort.desc:after { | ||||
| 					content: "\ec"; | ||||
| 				} | ||||
| 			} | ||||
| 			&.sortable { | ||||
| 				cursor: pointer; | ||||
| 			} | ||||
| 		} | ||||
| 		td, .td { | ||||
| 			border-top: 1px solid $tabularColorBorder; | ||||
| 			min-width: 110px; | ||||
| 			border-bottom: 1px solid $tabularColorBorder; | ||||
| 			min-width: 20px; | ||||
| 			color: $colorTelemFresh; | ||||
| 			padding: $tabularTdPadTB $tabularTdPadLR; | ||||
| 			word-wrap: break-word; | ||||
| 			vertical-align: top; | ||||
| 			&.numeric { | ||||
| 				text-align: right; | ||||
| @@ -119,9 +119,20 @@ | ||||
| 		} | ||||
| 	} | ||||
| 	&.filterable { | ||||
| 		thead, .thead { | ||||
| 			tr.s-filters, .tr.s-filters { | ||||
| 				th, .th { | ||||
| 					//border-left: none; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		tbody, .tbody { | ||||
| 			top: $tabularHeaderH * 2; | ||||
| 		} | ||||
| 		input[type="text"] { | ||||
| 			@include box-sizing(border-box); | ||||
| 			width: 100%; //50px; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	&.fixed-header { | ||||
| @@ -133,6 +144,15 @@ | ||||
| 		} | ||||
| 		thead, .thead { | ||||
| 			width: calc(100% - 10px); | ||||
| 			&:before { | ||||
| 				content: ""; | ||||
| 				display: block; | ||||
| 				z-index: 0; | ||||
| 				position: absolute; | ||||
| 				width: 100%; | ||||
| 				height: $tabularHeaderH; | ||||
| 				background: rgba(#fff, 0.15); | ||||
| 			} | ||||
| 		} | ||||
| 		tbody, .tbody { | ||||
| 			@include absPosDefault(0); | ||||
|   | ||||
							
								
								
									
										207
									
								
								platform/commonUI/general/res/sass/panes/_pane.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										207
									
								
								platform/commonUI/general/res/sass/panes/_pane.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,207 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| // Added by shale on 08/19/2015. Styling for the collapsible left and right panes.  | ||||
|  | ||||
| $transitionTime: 0.35s; // For the pane open/close | ||||
|  | ||||
|  | ||||
| // Set the left pane (which contains the tree) to have no width to close | ||||
| // (not display:none because we still need to have access to the create button) | ||||
| .pane.left { | ||||
|     &.inactive { | ||||
|         width: 0 !important; | ||||
|         min-width: 0 !important; | ||||
|          | ||||
|         // Undo the tree-holder's right padding when tree closed | ||||
|         .tree-holder { | ||||
|             padding-right: 0; | ||||
|         } | ||||
|          | ||||
|         // Hide the search bar when the pane is closed | ||||
|         .search-holder { | ||||
|             display: none; | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     // When the pane is closed, move and resize the create button | ||||
|     .create-btn.major { | ||||
|         top: 0; | ||||
|         left: 0; | ||||
|         transition: all $transitionTime; | ||||
|  | ||||
|         &.inactivePane { | ||||
|             top: 0; | ||||
|             left: 0; | ||||
|  | ||||
|             position: relative; | ||||
|             padding: 0; | ||||
|  | ||||
|             text-align: center; | ||||
|             font-size: 12px; | ||||
|  | ||||
|             width: 13px; | ||||
|             height: 16px; | ||||
|             line-height: 14px; | ||||
|  | ||||
|             left: -11px; | ||||
|             top: 20px; | ||||
|  | ||||
|             // Remove 'Create' text from the button when in small mode | ||||
|             span { | ||||
|                 display: none; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| // Hide a splitter bar when the corresponding pane is inactive | ||||
| .splitter-bar.splitter { | ||||
|     opacity: 1; | ||||
|     transition: opacity $transitionTime, visibility $transitionTime; | ||||
|      | ||||
|     // Make the splitter bar vertically span to the top | ||||
|     top: 0; | ||||
|      | ||||
|     &.inactive { | ||||
|         visibility: hidden; | ||||
|         opacity: 0; | ||||
|          | ||||
|         &:before { | ||||
|             border-width: 0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
| // Fade the splitter bar in when opening treeview, but immediately fade | ||||
| //   out when closing treeview | ||||
| .splitter-bar.left.splitter { | ||||
|     &.inactive { | ||||
|         transition: opacity 0s, visibility 0s; | ||||
|     } | ||||
| } | ||||
|  | ||||
| // The main view needs to align left when the left pane is moving around | ||||
| .split-pane-component.secondary-split.pane.right { | ||||
|      | ||||
|     // Sliding transition for open/close of left pane | ||||
|     &.leftInactive { | ||||
|         left: 0 !important; | ||||
|     } | ||||
|     &.slide { | ||||
|         transition: left $transitionTime; | ||||
|     } | ||||
|      | ||||
|     .split-pane-component.items.pane { | ||||
|          | ||||
|         // Sliding transition for open/close of right pane | ||||
|         &.rightInactive { | ||||
|             right: 0 !important; | ||||
|         } | ||||
|         &.slide { | ||||
|             transition: right $transitionTime; | ||||
|         } | ||||
|          | ||||
|         // Tab buttons close to the splitter bars | ||||
|         .object-browse-bar { | ||||
|             position: relative; | ||||
|              | ||||
|             .pane-tabs { | ||||
|                 position: relative; | ||||
|                 cursor: pointer; | ||||
|                 font-family: symbolsfont; | ||||
|                  | ||||
|                 background-color: darken($colorBodyFg, 25%); | ||||
|                  | ||||
|                 width: 13px !important; | ||||
|                 height: 16px; | ||||
|                 line-height: 16px; | ||||
|                 font-size: 10px; | ||||
|                 text-align: center; | ||||
|                  | ||||
|                 // Open and closes treeview | ||||
|                 &.left { | ||||
|                     left: -12px; | ||||
|                     top: 3px; | ||||
|  | ||||
|                     border-top-right-radius: 2px; | ||||
|                     border-bottom-right-radius: 2px; | ||||
|  | ||||
|                     // Change button icon depending on state | ||||
|                     &.inactivePane { | ||||
|                         left: -15px; | ||||
|                         &:after { | ||||
|                             content: 'F';//'>'; | ||||
|                         } | ||||
|                     } | ||||
|                     &.activePane:after { | ||||
|                         content: '<'; | ||||
|                     } | ||||
|                 } | ||||
|                  | ||||
|                 // Open and closes object inspector  | ||||
|                 &.right { | ||||
|                     float: right; | ||||
|                     right: -9px; | ||||
|                     top: -13px; | ||||
|  | ||||
|                     border-top-left-radius: 2px; | ||||
|                     border-bottom-left-radius: 2px; | ||||
|                      | ||||
|                     // Change button icon depending on state | ||||
|                     &.inactivePane { | ||||
|                         right: -12px; | ||||
|                         &:after { | ||||
|                             content: '\e608';//'G';//'<'; | ||||
|                         } | ||||
|                     } | ||||
|                     &.activePane:after { | ||||
|                         content: '>'; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|              | ||||
|             // Move domain object title to the right some to make room  | ||||
|             //   for treeview collapser button | ||||
|             .items-select { | ||||
|                 margin-left: 10px; | ||||
|             } | ||||
|             // Similarly move the top button bar for the object inspector | ||||
|             .btn-bar.right { | ||||
|                 margin-right: 10px; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|      | ||||
|     .split-pane-component.object-inspector.pane.right { | ||||
|         min-width: 150px; | ||||
|         opacity: 1; | ||||
|          | ||||
|         transition: opacity $transitionTime/2; | ||||
|         transition-delay: $transitionTime/2; | ||||
|         &.inactive { | ||||
|             min-width: 0 !important; | ||||
|             width: 0 !important; | ||||
|             visibility: hidden; | ||||
|             opacity: 0; | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										31
									
								
								platform/commonUI/general/res/sass/search/_layout.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								platform/commonUI/general/res/sass/search/_layout.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| /***************************************************************************** | ||||
|  * Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  * as represented by the Administrator of the National Aeronautics and Space | ||||
|  * Administration. All rights reserved. | ||||
|  * | ||||
|  * Open MCT Web is licensed under the Apache License, Version 2.0 (the | ||||
|  * "License"); you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0. | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
|  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
|  * License for the specific language governing permissions and limitations | ||||
|  * under the License. | ||||
|  * | ||||
|  * Open MCT Web includes source code licensed under additional open source | ||||
|  * licenses. See the Open Source Licenses file (LICENSES.md) included with | ||||
|  * this source code distribution or the Licensing information page available | ||||
|  * at runtime from the About dialog for additional information. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| // Overrides some styling in user-environ/_layout.scss | ||||
| .pane { | ||||
|     &.treeview.left { | ||||
| 	    .tree-holder { | ||||
|             // Want tree holder to start right below the search bar. | ||||
| 		    top: 60px; | ||||
| 	    } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										350
									
								
								platform/commonUI/general/res/sass/search/_search.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										350
									
								
								platform/commonUI/general/res/sass/search/_search.scss
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,350 @@ | ||||
| /***************************************************************************** | ||||
|  * 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. | ||||
|  *****************************************************************************/ | ||||
|  | ||||
| .abs.search-holder { | ||||
| 	//@include test(#990000); | ||||
| 	height: $treeSearchInputBarH; | ||||
| 	bottom: 0; | ||||
| 	&.active { | ||||
| 		height: auto; | ||||
| 		bottom: 0; | ||||
| 	} | ||||
| 	//top: 23px; | ||||
|  | ||||
| 	// Align with the top of the divider bar, below create button | ||||
| 	//margin-top: 10px; // CH comment out | ||||
| 	z-index:5; | ||||
| } | ||||
|  | ||||
| .search { | ||||
| 	$iconWidth: 20px; | ||||
| 	$leftMargin: 6px; | ||||
| 	$rightPadding: 5px; | ||||
|  | ||||
| 	//padding-right: $rightPadding; | ||||
| 	//@include test(); | ||||
| 	display: flex; //block; | ||||
| 	flex-direction: column; | ||||
| 	height: 100%; | ||||
|  | ||||
| 	.search-bar { | ||||
| 		//$heightAdjust: 4px; | ||||
| 		$textInputHeight: 19px; // This is equal to the default value, 19px | ||||
| 		$iconEdgeM: 4px; | ||||
| 		$iconD: $treeSearchInputBarH - ($iconEdgeM*2); | ||||
| 		font-size: 0.8em; | ||||
|  | ||||
| 		//order: 1; | ||||
|  | ||||
| 		position: relative; | ||||
| 		width: 100%; | ||||
| 		//height: $textInputHeight; | ||||
| 		//margin-top: $heightAdjust; | ||||
| 		.search-input, | ||||
| 		.search-icon { | ||||
| 		} | ||||
| 		 | ||||
| 		.search-input { | ||||
| 			height: $treeSearchInputBarH; | ||||
| 			line-height: $treeSearchInputBarH; | ||||
| 			padding-top: 0; | ||||
| 			padding-bottom: 0; | ||||
| 		} | ||||
| 		 | ||||
| 		.search-icon, | ||||
| 		.clear-icon, | ||||
| 		.menu-icon { | ||||
| 			//@include test(#008800); | ||||
| 			@include box-sizing(border-box); | ||||
| 			color: $colorItemFg; | ||||
| 			height: $iconD; width: $iconD; | ||||
| 			line-height: $iconD; | ||||
| 			position: absolute; | ||||
| 			text-align: center; | ||||
| 			top: $iconEdgeM; | ||||
| 		} | ||||
|  | ||||
| 		.clear-icon, | ||||
| 		.menu-icon { | ||||
| 			cursor: pointer; | ||||
| 			transition: color .25s; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		.search-input { | ||||
| 			position: relative; | ||||
| 			width: 100%; | ||||
| 			padding-left: $iconD + $interiorMargin !important; | ||||
| 			padding-right: ($iconD * 2) + ($interiorMargin * 2) !important; | ||||
|  | ||||
| 			// Make work for mct-control textfield | ||||
| 			input { | ||||
| 				width: 100%; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		.search-icon { | ||||
| 			color: $colorItemFg; | ||||
| 			left: $interiorMarginSm; | ||||
| 			transition: visibility .15s, opacity .15s, color .2s; | ||||
| 			pointer-events: none; | ||||
|  | ||||
| 			&.content { | ||||
| 				// Make icon invisible whenever there is text input | ||||
| 				//visibility: hidden; | ||||
| 				//opacity: 0; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Make icon invisible when the text input is focused | ||||
| 		.search-input:focus + div.search-icon { | ||||
| 			//visibility: hidden; | ||||
| 			//opacity: 0; | ||||
| 		} | ||||
|  | ||||
| 		// Make icon lighten when hovering over search bar | ||||
| 		.search-input:hover + div.search-icon { | ||||
| 			color: lighten($colorItemFg, 20%); | ||||
| 		} | ||||
|  | ||||
| 		.clear-icon { | ||||
| 			right: $iconD + $interiorMargin; | ||||
|  | ||||
| 			// Icon is visible only when there is text input | ||||
| 			visibility: hidden; | ||||
| 			opacity: 0; | ||||
|  | ||||
| 			transition: visibility .15s, opacity .15s, color .2s; | ||||
|  | ||||
| 			&.content { | ||||
| 				visibility: visible; | ||||
| 				opacity: 1; | ||||
| 			} | ||||
|  | ||||
| 			&:hover { | ||||
| 				color: lighten($colorItemFg, 20%); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		.menu-icon { | ||||
| 			font-size: 0.8em; | ||||
| 			padding-right: $iconEdgeM; | ||||
| 			right: $iconEdgeM; | ||||
| 			text-align: right; | ||||
|  | ||||
| 			&:hover { | ||||
| 				color: lighten($colorItemFg, 20%); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		.search-menu-holder { | ||||
| 			float: right; | ||||
| 			//margin-top: $textInputHeight - 2px; | ||||
| 			//left: -50px; | ||||
| 			left: -20px; | ||||
|  | ||||
| 			z-index: 1; | ||||
|  | ||||
| 			transition: visibility .05s, opacity .05s; | ||||
|  | ||||
| 			&.off { | ||||
| 				visibility: hidden; | ||||
| 				opacity: 0; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		// Hovering reveals menu | ||||
| 		.menu-icon:hover + div.search-menu-holder { | ||||
| 			visibility: visible; | ||||
| 		} | ||||
| 		div.search-menu-holder:hover { | ||||
| 			visibility: visible; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	.active-filter-display { | ||||
| 		//order: 2; | ||||
| 		$s: 0.65em; | ||||
| 		$p: $interiorMargin; | ||||
| 		@include border-radius($basicCr); | ||||
| 		@include box-sizing(border-box); | ||||
| 		line-height: 130%; | ||||
| 		padding: $p 0; | ||||
| 		padding-left: $s * 2.25; | ||||
| 		font-size: $s; | ||||
| 		//background-color: rgba(#000, 0.3); | ||||
| 		//border-radius: $basicCr; | ||||
| 		margin-top: $interiorMarginSm; | ||||
|  | ||||
|  | ||||
| 		.clear-filters-icon { | ||||
| 			opacity: 0.4; | ||||
| 			font-size: 0.8em; | ||||
| 			position: absolute; | ||||
| 			left: 1px; | ||||
| 			cursor: pointer; | ||||
| 		} | ||||
|  | ||||
| 		// Transition looks weird when the results list has none | ||||
| 		//transition: visibility .2s, opacity .2s; | ||||
|  | ||||
| 		&.off { | ||||
| 			visibility: hidden; | ||||
| 			opacity: 0; | ||||
| 			height: 0; | ||||
| 			margin: 0; | ||||
| 			padding: 0; | ||||
| 			border: 0; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	.search-scroll { | ||||
| 		order: 3; | ||||
|  | ||||
| 		//padding-right: $rightPadding; | ||||
| 		margin-top: 4px; | ||||
|  | ||||
| 		// Adjustable scrolling size | ||||
| 		overflow-y: auto; | ||||
| 		top: auto; | ||||
| 		height: auto; | ||||
| 		max-height: 100%; | ||||
| 		position: relative; | ||||
|  | ||||
| 		.results { | ||||
|  | ||||
| 			.search-result-item { | ||||
| 				// Include transitions (for the highlights) | ||||
| 				@include single-transition(background-color, 0.25s); | ||||
|  | ||||
| 				// Space the results from each other | ||||
| 				margin-bottom: 2px; | ||||
|  | ||||
| 				// Make the highlights the right color and shape. | ||||
| 				// Attempting to match the style in the tree, but | ||||
| 				//   while having these be compact. | ||||
| 				border-radius: 2px; | ||||
| 				padding-top: 4px; | ||||
| 				padding-bottom: 2px; | ||||
|  | ||||
| 				.label { | ||||
| 					// Give some padding away from the left side | ||||
| 					margin-left: $leftMargin; | ||||
|  | ||||
| 					.title-label { | ||||
| 						display: inline-block; | ||||
| 						position: absolute; | ||||
|  | ||||
| 						// Give some padding away from the left side | ||||
| 						left: $leftMargin + 3px + $iconWidth; | ||||
| 						// and the right side | ||||
| 						right: $rightPadding; | ||||
|  | ||||
| 						// Size and position the text | ||||
| 						font-size: .8em; | ||||
| 						line-height: 17px; | ||||
|  | ||||
| 						// Hide overflow text | ||||
| 						width: auto; | ||||
| 						overflow: hidden; | ||||
| 						text-overflow: ellipsis; | ||||
| 						white-space: nowrap; | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				// Change styling when it's selected | ||||
| 				&.selected { | ||||
| 					$c: #fff; | ||||
| 					background: $colorKeySelectedBg; | ||||
| 					color: $c; | ||||
| 					.view-control { | ||||
| 						color: $colorItemTreeIcon; | ||||
| 					} | ||||
| 					.label .type-icon { | ||||
| 						color: #fff; | ||||
| 					} | ||||
| 				} | ||||
|                  | ||||
|                 .label .type-icon .l-icon-link { | ||||
|                     // Hide links for now. See GitHub issue #84. | ||||
|                     display: none; | ||||
|                      | ||||
|                     @include txtShdwSubtle(1); | ||||
|                     z-index: 2; | ||||
|                     @include ancillaryIcon(8px, $colorIconLink); | ||||
|                     margin-left: -25px; | ||||
|                 } | ||||
|  | ||||
| 				// Change styling when it's being hovered over | ||||
| 				&:not(.selected) { | ||||
| 					&:hover { | ||||
| 						background: lighten($colorBodyBg, 5%); | ||||
| 						color: lighten($colorBodyFg, 20%); | ||||
| 						.context-trigger { | ||||
| 							display: block; | ||||
| 						} | ||||
| 						.icon { | ||||
| 							color: $colorItemTreeIconHover; | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		.load-icon { | ||||
| 			position: relative; | ||||
| 			&.loading { | ||||
| 				pointer-events: none; | ||||
| 				margin-left: $leftMargin; | ||||
|  | ||||
| 				.title-label { | ||||
| 					// Text styling | ||||
| 					font-style: italic; | ||||
| 					font-size: .9em; | ||||
| 					opacity: 0.5; | ||||
|  | ||||
| 					// Text positioning | ||||
| 					margin-left: $iconWidth + $leftMargin; | ||||
| 					line-height: 24px; | ||||
| 				} | ||||
| 				.wait-spinner { | ||||
| 					margin-left: $leftMargin; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			&:not(.loading) { | ||||
| 				cursor: pointer; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		.load-more-button { | ||||
| 			margin-top: $interiorMargin 0; | ||||
| 			font-size: 0.8em; | ||||
| 			position: relative; | ||||
| 			left: 50%; | ||||
| 			margin-left: -45px; | ||||
| 			text-align: center; | ||||
| 			width: 90px; | ||||
| 			white-space: nowrap; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -27,4 +27,5 @@ | ||||
|  | ||||
| @import "constants"; | ||||
| @import "mixins"; | ||||
| @import "tree/tree"; | ||||
| @import "tree/tree"; | ||||
| @import "search/search"; | ||||
| @@ -229,10 +229,12 @@ | ||||
| 			    bottom: $interiorMargin; | ||||
| 		    } | ||||
| 	    } | ||||
| 	    .search-holder { | ||||
| 		    top: $ueTopBarH + $interiorMarginLg; | ||||
| 	    } | ||||
| 	    .tree-holder { | ||||
| 		    overflow: auto; | ||||
| 		    top: $ueTopBarH + $interiorMarginLg; | ||||
|             padding-right: $interiorMargin; | ||||
| 			top: $ueTopBarH + $interiorMarginLg + $treeSearchInputBarH + $interiorMargin; | ||||
| 	    } | ||||
|     } | ||||
|     &.items { | ||||
|   | ||||
| @@ -22,7 +22,13 @@ | ||||
| <span class="label s-label"> | ||||
|     <span class='ui-symbol icon type-icon'> | ||||
|         {{type.getGlyph()}} | ||||
|         <span class='ui-symbol icon alert hidden'>!</span> | ||||
|         <span | ||||
|             class='ui-symbol icon l-icon-link' | ||||
|             ng-show="location.isLink()" | ||||
|             ></span> | ||||
|         <span class='ui-symbol icon l-icon-alert'></span> | ||||
|     </span> | ||||
|     <span class='title-label'> | ||||
|         {{model.name}} | ||||
|     </span> | ||||
|     <span class='title-label'>{{model.name}}</span> | ||||
| </span> | ||||
|   | ||||
| @@ -0,0 +1,64 @@ | ||||
| <!-- | ||||
|  Open MCT Web, Copyright (c) 2014-2015, United States Government | ||||
|  as represented by the Administrator of the National Aeronautics and Space | ||||
|  Administration. All rights reserved. | ||||
|  | ||||
|  Open MCT Web is licensed under the Apache License, Version 2.0 (the | ||||
|  "License"); you may not use this file except in compliance with the License. | ||||
|  You may obtain a copy of the License at | ||||
|  http://www.apache.org/licenses/LICENSE-2.0. | ||||
|  | ||||
|  Unless required by applicable law or agreed to in writing, software | ||||
|  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
|  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
|  License for the specific language governing permissions and limitations | ||||
|  under the License. | ||||
|  | ||||
|  Open MCT Web includes source code licensed under additional open source | ||||
|  licenses. See the Open Source Licenses file (LICENSES.md) included with | ||||
|  this source code distribution or the Licensing information page available | ||||
|  at runtime from the About dialog for additional information. | ||||
| --> | ||||
| <span ng-controller="ObjectInspectorController as controller"> | ||||
|     <span class="ui-symbol info-icon"> | ||||
|          | ||||
|     </span> | ||||
|      | ||||
|     <div class="number-selected" | ||||
|          ng-if="ngModel.inspectionObjects.length > 1"> | ||||
|         {{ngModel.inspectionObjects.length}} items selected | ||||
|     </div> | ||||
|      | ||||
|     <ul> | ||||
|         <li ng-repeat="data in metadata"> | ||||
|             <em>{{ data.name }}</em> | ||||
|             {{ data.value }} | ||||
|         </li> | ||||
|         <li ng-if="contextutalParents.length > 0"> | ||||
|             <em title="The location of this linked object."> | ||||
|                 Contextual Location | ||||
|             </em> | ||||
|             <span class="inspector-location" | ||||
|                   ng-repeat="parent in contextutalParents"> | ||||
|                 <mct-representation key="'label'" | ||||
|                                     mct-object="parent" | ||||
|                                     ng-model="ngModel" | ||||
|                                     ng-click="ngModel.selectedObject = parent"> | ||||
|                 </mct-representation> | ||||
|             </span> | ||||
|         </li> | ||||
|         <li ng-if="primaryParents.length > 0"> | ||||
|             <em title="The location of the object that this was linked from."> | ||||
|                 Primary Location | ||||
|             </em> | ||||
|             <span class="inspector-location" | ||||
|                   ng-repeat="parent in primaryParents"> | ||||
|                 <mct-representation key="'label'" | ||||
|                                     mct-object="parent" | ||||
|                                     ng-model="ngModel" | ||||
|                                     ng-click="ngModel.selectedObject = parent"> | ||||
|                 </mct-representation> | ||||
|             </span> | ||||
|         </li> | ||||
|     </ul> | ||||
| </span> | ||||
| @@ -21,30 +21,26 @@ | ||||
| --> | ||||
| <span ng-controller="ToggleController as toggle"> | ||||
|     <span ng-controller="TreeNodeController as treeNode"> | ||||
|         <span | ||||
| 	        class="tree-item menus-to-left" | ||||
| 	        ng-class="{selected: treeNode.isSelected()}" | ||||
| 	        > | ||||
|         <span class="tree-item menus-to-left" | ||||
|               ng-class="{selected: treeNode.isSelected()}"> | ||||
|             <span | ||||
| 	            class='ui-symbol view-control' | ||||
| 				ng-click="toggle.toggle(); treeNode.trackExpansion()" | ||||
| 				ng-if="model.composition !== undefined" | ||||
| 				> | ||||
|                 class='ui-symbol view-control' | ||||
|                 ng-click="toggle.toggle(); treeNode.trackExpansion()" | ||||
|                 ng-if="model.composition !== undefined" | ||||
|                 > | ||||
|                 {{toggle.isActive() ? "v" : ">"}} | ||||
|             </span> | ||||
|             <mct-representation | ||||
| 				key="'label'" | ||||
| 				mct-object="domainObject" | ||||
| 				ng-model="ngModel" | ||||
| 				ng-click="ngModel.selectedObject = domainObject" | ||||
| 				> | ||||
|             <mct-representation key="'label'" | ||||
|                                 mct-object="domainObject" | ||||
|                                 ng-model="ngModel" | ||||
|                                 ng-click="ngModel.selectedObject = domainObject; ngModel.inspectionObjects = [domainObject]"> | ||||
|             </mct-representation> | ||||
|         </span> | ||||
|         <span | ||||
| 			class="tree-item-subtree" | ||||
| 			ng-show="toggle.isActive()" | ||||
| 			ng-if="model.composition !== undefined" | ||||
| 			> | ||||
|             class="tree-item-subtree" | ||||
|             ng-show="toggle.isActive()" | ||||
|             ng-if="model.composition !== undefined" | ||||
|             > | ||||
|  | ||||
|             <mct-representation key="'subtree'" | ||||
|                                 ng-model="ngModel" | ||||
|   | ||||
| @@ -21,6 +21,11 @@ | ||||
|  *****************************************************************************/ | ||||
| /*global define*/ | ||||
|  | ||||
| /** | ||||
|  * This bundle provides various general-purpose UI elements, including | ||||
|  * platform styling. | ||||
|  * @namespace platform/commonUI/general | ||||
|  */ | ||||
| define( | ||||
|     [], | ||||
|     function () { | ||||
| @@ -29,6 +34,7 @@ define( | ||||
|         /** | ||||
|          * The StyleSheetLoader adds links to style sheets exposed from | ||||
|          * various bundles as extensions of category `stylesheets`. | ||||
|          * @memberof platform/commonUI/general | ||||
|          * @constructor | ||||
|          * @param {object[]} stylesheets stylesheet extension definitions | ||||
|          * @param $document Angular's jqLite-wrapped document element | ||||
| @@ -62,4 +68,4 @@ define( | ||||
|  | ||||
|         return StyleSheetLoader; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -42,6 +42,7 @@ define( | ||||
|          * * `ungrouped`: All actions which did not have a defined | ||||
|          *   group. | ||||
|          * | ||||
|          * @memberof platform/commonUI/general | ||||
|          * @constructor | ||||
|          */ | ||||
|         function ActionGroupController($scope) { | ||||
| @@ -102,4 +103,4 @@ define( | ||||
|  | ||||
|         return ActionGroupController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -29,6 +29,7 @@ define( | ||||
|         /** | ||||
|          * Controller for the bottombar template. Exposes | ||||
|          * available indicators (of extension category "indicators") | ||||
|          * @memberof platform/commonUI/general | ||||
|          * @constructor | ||||
|          */ | ||||
|         function BottomBarController(indicators) { | ||||
| @@ -42,20 +43,19 @@ define( | ||||
|                 }; | ||||
|             } | ||||
|  | ||||
|             indicators = indicators.map(present); | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get all indicators to display. | ||||
|                  * @returns {Indicator[]} all indicators | ||||
|                  *          to display in the bottom bar. | ||||
|                  */ | ||||
|                 getIndicators: function () { | ||||
|                     return indicators; | ||||
|                 } | ||||
|             }; | ||||
|             this.indicators = indicators.map(present); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get all indicators to display. | ||||
|          * @returns {Indicator[]} all indicators | ||||
|          *          to display in the bottom bar. | ||||
|          * @memberof platform/commonUI/general.BottomBarController# | ||||
|          */ | ||||
|         BottomBarController.prototype.getIndicators = function () { | ||||
|             return this.indicators; | ||||
|         }; | ||||
|  | ||||
|         return BottomBarController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -31,71 +31,69 @@ define( | ||||
|          * menus) where clicking elsewhere in the document while the toggle | ||||
|          * is in an active state is intended to dismiss the toggle. | ||||
|          * | ||||
|          * @memberof platform/commonUI/general | ||||
|          * @constructor | ||||
|          * @param $scope the scope in which this controller is active | ||||
|          * @param $document the document element, injected by Angular | ||||
|          */ | ||||
|         function ClickAwayController($scope, $document) { | ||||
|             var state = false, | ||||
|                 clickaway; | ||||
|             var self = this; | ||||
|  | ||||
|             // Track state, but also attach and detach a listener for | ||||
|             // mouseup events on the document. | ||||
|             function deactivate() { | ||||
|                 state = false; | ||||
|                 $document.off("mouseup", clickaway); | ||||
|             } | ||||
|  | ||||
|             function activate() { | ||||
|                 state = true; | ||||
|                 $document.on("mouseup", clickaway); | ||||
|             } | ||||
|  | ||||
|             function changeState() { | ||||
|                 if (state) { | ||||
|                     deactivate(); | ||||
|                 } else { | ||||
|                     activate(); | ||||
|                 } | ||||
|             } | ||||
|             this.state = false; | ||||
|             this.$scope = $scope; | ||||
|             this.$document = $document; | ||||
|  | ||||
|             // Callback used by the document listener. Deactivates; | ||||
|             // note also $scope.$apply is invoked to indicate that | ||||
|             // the state of this controller has changed. | ||||
|             clickaway = function () { | ||||
|                 deactivate(); | ||||
|             this.clickaway = function () { | ||||
|                 self.deactivate(); | ||||
|                 $scope.$apply(); | ||||
|                 return false; | ||||
|             }; | ||||
|  | ||||
|             return { | ||||
|                 /** | ||||
|                  * Get the current state of the toggle. | ||||
|                  * @return {boolean} true if active | ||||
|                  */ | ||||
|                 isActive: function () { | ||||
|                     return state; | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Set a new state for the toggle. | ||||
|                  * @return {boolean} true to activate | ||||
|                  */ | ||||
|                 setState: function (newState) { | ||||
|                     if (state !== newState) { | ||||
|                         changeState(); | ||||
|                     } | ||||
|                 }, | ||||
|                 /** | ||||
|                  * Toggle the current state; activate if it is inactive, | ||||
|                  * deactivate if it is active. | ||||
|                  */ | ||||
|                 toggle: function () { | ||||
|                     changeState(); | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         // Track state, but also attach and detach a listener for | ||||
|         // mouseup events on the document. | ||||
|         ClickAwayController.prototype.deactivate = function () { | ||||
|             this.state = false; | ||||
|             this.$document.off("mouseup", this.clickaway); | ||||
|         }; | ||||
|         ClickAwayController.prototype.activate = function () { | ||||
|             this.state = true; | ||||
|             this.$document.on("mouseup", this.clickaway); | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Get the current state of the toggle. | ||||
|          * @return {boolean} true if active | ||||
|          */ | ||||
|         ClickAwayController.prototype.isActive =function () { | ||||
|             return this.state; | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Set a new state for the toggle. | ||||
|          * @return {boolean} true to activate | ||||
|          */ | ||||
|         ClickAwayController.prototype.setState = function (newState) { | ||||
|             if (this.state !== newState) { | ||||
|                 this.toggle(); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Toggle the current state; activate if it is inactive, | ||||
|          * deactivate if it is active. | ||||
|          */ | ||||
|         ClickAwayController.prototype.toggle = function () { | ||||
|             if (this.state) { | ||||
|                 this.deactivate(); | ||||
|             } else { | ||||
|                 this.activate(); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         return ClickAwayController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -33,6 +33,7 @@ define( | ||||
|          * Controller for the context menu. Maintains an up-to-date | ||||
|          * list of applicable actions (those from category "contextual") | ||||
|          * | ||||
|          * @memberof platform/commonUI/general | ||||
|          * @constructor | ||||
|          */ | ||||
|         function ContextMenuController($scope) { | ||||
| @@ -49,4 +50,4 @@ define( | ||||
|  | ||||
|         return ContextMenuController; | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
| @@ -54,6 +54,7 @@ define( | ||||
|          * parameter it received.) Getter-setter functions are never the | ||||
|          * target of a scope assignment and so avoid this problem. | ||||
|          * | ||||
|          * @memberof platform/commonUI/general | ||||
|          * @constructor | ||||
|          * @param {Scope} $scope the controller's scope | ||||
|          */ | ||||
| @@ -87,4 +88,4 @@ define( | ||||
|         return GetterSetterController; | ||||
|  | ||||
|     } | ||||
| ); | ||||
| ); | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user