Compare commits
	
		
			7 Commits
		
	
	
		
			couchdb-pe
			...
			add-new-gl
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					606e7e5acd | ||
| 
						 | 
					03607bd3fa | ||
| 
						 | 
					05b5b1c765 | ||
| 
						 | 
					fd66c403ad | ||
| 
						 | 
					ffbf0de655 | ||
| 
						 | 
					f89ae0b566 | ||
| 
						 | 
					fc41ecd4f5 | 
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							@@ -37,7 +37,4 @@ protractor/logs
 | 
			
		||||
# npm-debug log
 | 
			
		||||
npm-debug.log
 | 
			
		||||
 | 
			
		||||
# karma reports
 | 
			
		||||
report.*.json
 | 
			
		||||
 | 
			
		||||
package-lock.json
 | 
			
		||||
 
 | 
			
		||||
@@ -28,16 +28,6 @@ define([
 | 
			
		||||
                        domain: 2
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                // Need to enable "LocalTimeSystem" plugin to make use of this
 | 
			
		||||
                // {
 | 
			
		||||
                //     key: "local",
 | 
			
		||||
                //     name: "Time",
 | 
			
		||||
                //     format: "local-format",
 | 
			
		||||
                //     source: "utc",
 | 
			
		||||
                //     hints: {
 | 
			
		||||
                //         domain: 3
 | 
			
		||||
                //     }
 | 
			
		||||
                // },
 | 
			
		||||
                {
 | 
			
		||||
                    key: "sin",
 | 
			
		||||
                    name: "Sine",
 | 
			
		||||
@@ -71,15 +61,6 @@ define([
 | 
			
		||||
                        domain: 1
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    key: "local",
 | 
			
		||||
                    name: "Time",
 | 
			
		||||
                    format: "utc",
 | 
			
		||||
                    source: "utc",
 | 
			
		||||
                    hints: {
 | 
			
		||||
                        domain: 2
 | 
			
		||||
                    }
 | 
			
		||||
                },
 | 
			
		||||
                {
 | 
			
		||||
                    key: "state",
 | 
			
		||||
                    source: "value",
 | 
			
		||||
 
 | 
			
		||||
@@ -43,9 +43,7 @@
 | 
			
		||||
            openmct.legacyRegistry.enable.bind(openmct.legacyRegistry)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        //openmct.install(openmct.plugins.LocalStorage());
 | 
			
		||||
        //Change 'vipersim' to whatever your local db is named
 | 
			
		||||
        openmct.install(openmct.plugins.CouchDB('http://localhost:5984/vipersim'));
 | 
			
		||||
        openmct.install(openmct.plugins.LocalStorage());
 | 
			
		||||
        openmct.install(openmct.plugins.Espresso());
 | 
			
		||||
        openmct.install(openmct.plugins.MyItems());
 | 
			
		||||
        openmct.install(openmct.plugins.Generator());
 | 
			
		||||
@@ -115,10 +113,7 @@
 | 
			
		||||
        openmct.install(openmct.plugins.LADTable());
 | 
			
		||||
        openmct.install(openmct.plugins.Filters(['table', 'telemetry.plot.overlay']));
 | 
			
		||||
        openmct.install(openmct.plugins.ObjectMigration());
 | 
			
		||||
        openmct.install(openmct.plugins.ClearData(
 | 
			
		||||
            ['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked'],
 | 
			
		||||
            {indicator: true}
 | 
			
		||||
        ));
 | 
			
		||||
        openmct.install(openmct.plugins.ClearData(['table', 'telemetry.plot.overlay', 'telemetry.plot.stacked']));
 | 
			
		||||
        openmct.start();
 | 
			
		||||
    </script>
 | 
			
		||||
</html>
 | 
			
		||||
 
 | 
			
		||||
@@ -23,7 +23,7 @@
 | 
			
		||||
/*global module,process*/
 | 
			
		||||
 | 
			
		||||
const devMode = process.env.NODE_ENV !== 'production';
 | 
			
		||||
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'FirefoxHeadless'];
 | 
			
		||||
const browsers = [process.env.NODE_ENV === 'debug' ? 'ChromeDebugging' : 'ChromeHeadless'];
 | 
			
		||||
const coverageEnabled = process.env.COVERAGE === 'true';
 | 
			
		||||
const reporters = ['progress', 'html'];
 | 
			
		||||
 | 
			
		||||
@@ -95,7 +95,6 @@ module.exports = (config) => {
 | 
			
		||||
            stats: 'errors-only',
 | 
			
		||||
            logLevel: 'warn'
 | 
			
		||||
        },
 | 
			
		||||
        singleRun: true,
 | 
			
		||||
        browserNoActivityTimeout: 90000
 | 
			
		||||
        singleRun: true
 | 
			
		||||
    });
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -41,7 +41,6 @@
 | 
			
		||||
    "jsdoc": "^3.3.2",
 | 
			
		||||
    "karma": "^2.0.3",
 | 
			
		||||
    "karma-chrome-launcher": "^2.2.0",
 | 
			
		||||
    "karma-firefox-launcher": "^1.3.0",
 | 
			
		||||
    "karma-cli": "^1.0.1",
 | 
			
		||||
    "karma-coverage": "^1.1.2",
 | 
			
		||||
    "karma-coverage-istanbul-reporter": "^2.1.1",
 | 
			
		||||
@@ -60,7 +59,7 @@
 | 
			
		||||
    "moment-timezone": "0.5.28",
 | 
			
		||||
    "node-bourbon": "^4.2.3",
 | 
			
		||||
    "node-sass": "^4.9.2",
 | 
			
		||||
    "painterro": "^1.0.35",
 | 
			
		||||
    "painterro": "^0.2.65",
 | 
			
		||||
    "printj": "^1.2.1",
 | 
			
		||||
    "raw-loader": "^0.5.1",
 | 
			
		||||
    "request": "^2.69.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -36,6 +36,8 @@ define(
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        EditPersistableObjectsPolicy.prototype.allow = function (action, context) {
 | 
			
		||||
            var identifier;
 | 
			
		||||
            var provider;
 | 
			
		||||
            var domainObject = context.domainObject;
 | 
			
		||||
            var key = action.getMetadata().key;
 | 
			
		||||
            var category = (context || {}).category;
 | 
			
		||||
@@ -44,8 +46,9 @@ define(
 | 
			
		||||
            // is also invoked during the create process which should be allowed,
 | 
			
		||||
            // because it may be saved elsewhere
 | 
			
		||||
            if ((key === 'edit' && category === 'view-control') || key === 'properties') {
 | 
			
		||||
                let newStyleObject = objectUtils.toNewFormat(domainObject, domainObject.getId());
 | 
			
		||||
                return this.openmct.objects.isPersistable(newStyleObject);
 | 
			
		||||
                identifier = objectUtils.parseKeyString(domainObject.getId());
 | 
			
		||||
                provider = this.openmct.objects.getProvider(identifier);
 | 
			
		||||
                return provider.save !== undefined;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return true;
 | 
			
		||||
 
 | 
			
		||||
@@ -43,7 +43,7 @@ define(
 | 
			
		||||
                );
 | 
			
		||||
 | 
			
		||||
                mockObjectAPI = jasmine.createSpyObj('objectAPI', [
 | 
			
		||||
                    'isPersistable'
 | 
			
		||||
                    'getProvider'
 | 
			
		||||
                ]);
 | 
			
		||||
 | 
			
		||||
                mockAPI = {
 | 
			
		||||
@@ -69,31 +69,34 @@ define(
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("Applies to edit action", function () {
 | 
			
		||||
                expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
 | 
			
		||||
                mockObjectAPI.getProvider.and.returnValue({});
 | 
			
		||||
                expect(mockObjectAPI.getProvider).not.toHaveBeenCalled();
 | 
			
		||||
 | 
			
		||||
                policy.allow(mockEditAction, testContext);
 | 
			
		||||
                expect(mockObjectAPI.isPersistable).toHaveBeenCalled();
 | 
			
		||||
                expect(mockObjectAPI.getProvider).toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("Applies to properties action", function () {
 | 
			
		||||
                expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
 | 
			
		||||
                mockObjectAPI.getProvider.and.returnValue({});
 | 
			
		||||
                expect(mockObjectAPI.getProvider).not.toHaveBeenCalled();
 | 
			
		||||
 | 
			
		||||
                policy.allow(mockPropertiesAction, testContext);
 | 
			
		||||
                expect(mockObjectAPI.isPersistable).toHaveBeenCalled();
 | 
			
		||||
                expect(mockObjectAPI.getProvider).toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("does not apply to other actions", function () {
 | 
			
		||||
                expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
 | 
			
		||||
                mockObjectAPI.getProvider.and.returnValue({});
 | 
			
		||||
                expect(mockObjectAPI.getProvider).not.toHaveBeenCalled();
 | 
			
		||||
 | 
			
		||||
                policy.allow(mockOtherAction, testContext);
 | 
			
		||||
                expect(mockObjectAPI.isPersistable).not.toHaveBeenCalled();
 | 
			
		||||
                expect(mockObjectAPI.getProvider).not.toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("Tests object provider for editability", function () {
 | 
			
		||||
                mockObjectAPI.isPersistable.and.returnValue(false);
 | 
			
		||||
                mockObjectAPI.getProvider.and.returnValue({});
 | 
			
		||||
                expect(policy.allow(mockEditAction, testContext)).toBe(false);
 | 
			
		||||
                expect(mockObjectAPI.isPersistable).toHaveBeenCalled();
 | 
			
		||||
                mockObjectAPI.isPersistable.and.returnValue(true);
 | 
			
		||||
                expect(mockObjectAPI.getProvider).toHaveBeenCalled();
 | 
			
		||||
                mockObjectAPI.getProvider.and.returnValue({save: function () {}});
 | 
			
		||||
                expect(policy.allow(mockEditAction, testContext)).toBe(true);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 
 | 
			
		||||
@@ -19,13 +19,7 @@
 | 
			
		||||
 this source code distribution or the Licensing information page available
 | 
			
		||||
 at runtime from the About dialog for additional information.
 | 
			
		||||
-->
 | 
			
		||||
<div class="c-object-label"
 | 
			
		||||
     ng-class="{ 'is-missing': model.status === 'missing' }"
 | 
			
		||||
>
 | 
			
		||||
    <div class="c-object-label__type-icon {{type.getCssClass()}}"
 | 
			
		||||
         ng-class="{ 'l-icon-link':location.isLink() }"
 | 
			
		||||
    >
 | 
			
		||||
        <span class="is-missing__indicator" title="This item is missing"></span>
 | 
			
		||||
    </div>
 | 
			
		||||
<div class="c-object-label">
 | 
			
		||||
    <div class="c-object-label__type-icon {{type.getCssClass()}}" ng-class="{ 'l-icon-link':location.isLink() }"></div>
 | 
			
		||||
    <div class='c-object-label__name'>{{model.name}}</div>
 | 
			
		||||
</div>
 | 
			
		||||
 
 | 
			
		||||
@@ -48,8 +48,9 @@ define(
 | 
			
		||||
            // prevents editing of objects that cannot be persisted, so we can assume that this
 | 
			
		||||
            // is a new object.
 | 
			
		||||
            if (!(parent.hasCapability('editor') && parent.getCapability('editor').isEditContextRoot())) {
 | 
			
		||||
                let newStyleObject = objectUtils.toNewFormat(parent, parent.getId());
 | 
			
		||||
                return this.openmct.objects.isPersistable(newStyleObject);
 | 
			
		||||
                var identifier = objectUtils.parseKeyString(parent.getId());
 | 
			
		||||
                var provider = this.openmct.objects.getProvider(identifier);
 | 
			
		||||
                return provider.save !== undefined;
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        };
 | 
			
		||||
 
 | 
			
		||||
@@ -33,7 +33,7 @@ define(
 | 
			
		||||
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                objectAPI = jasmine.createSpyObj('objectsAPI', [
 | 
			
		||||
                    'isPersistable'
 | 
			
		||||
                    'getProvider'
 | 
			
		||||
                ]);
 | 
			
		||||
 | 
			
		||||
                mockOpenMCT = {
 | 
			
		||||
@@ -51,6 +51,10 @@ define(
 | 
			
		||||
                    'isEditContextRoot'
 | 
			
		||||
                ]);
 | 
			
		||||
                mockParent.getCapability.and.returnValue(mockEditorCapability);
 | 
			
		||||
 | 
			
		||||
                objectAPI.getProvider.and.returnValue({
 | 
			
		||||
                    save: function () {}
 | 
			
		||||
                });
 | 
			
		||||
                persistableCompositionPolicy = new PersistableCompositionPolicy(mockOpenMCT);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
@@ -61,22 +65,19 @@ define(
 | 
			
		||||
 | 
			
		||||
            it("Does not allow composition for objects that are not persistable", function () {
 | 
			
		||||
                mockEditorCapability.isEditContextRoot.and.returnValue(false);
 | 
			
		||||
                objectAPI.isPersistable.and.returnValue(true);
 | 
			
		||||
                expect(persistableCompositionPolicy.allow(mockParent, mockChild)).toBe(true);
 | 
			
		||||
                objectAPI.isPersistable.and.returnValue(false);
 | 
			
		||||
                objectAPI.getProvider.and.returnValue({});
 | 
			
		||||
                expect(persistableCompositionPolicy.allow(mockParent, mockChild)).toBe(false);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("Always allows composition of objects in edit mode to support object creation", function () {
 | 
			
		||||
                mockEditorCapability.isEditContextRoot.and.returnValue(true);
 | 
			
		||||
                objectAPI.isPersistable.and.returnValue(true);
 | 
			
		||||
                expect(persistableCompositionPolicy.allow(mockParent, mockChild)).toBe(true);
 | 
			
		||||
                expect(objectAPI.isPersistable).not.toHaveBeenCalled();
 | 
			
		||||
                expect(objectAPI.getProvider).not.toHaveBeenCalled();
 | 
			
		||||
 | 
			
		||||
                mockEditorCapability.isEditContextRoot.and.returnValue(false);
 | 
			
		||||
                objectAPI.isPersistable.and.returnValue(true);
 | 
			
		||||
                expect(persistableCompositionPolicy.allow(mockParent, mockChild)).toBe(true);
 | 
			
		||||
                expect(objectAPI.isPersistable).toHaveBeenCalled();
 | 
			
		||||
                expect(objectAPI.getProvider).toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        });
 | 
			
		||||
 
 | 
			
		||||
@@ -297,8 +297,7 @@ define([
 | 
			
		||||
                            "persistenceService",
 | 
			
		||||
                            "identifierService",
 | 
			
		||||
                            "notificationService",
 | 
			
		||||
                            "$q",
 | 
			
		||||
                            "openmct"
 | 
			
		||||
                            "$q"
 | 
			
		||||
                        ]
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,8 @@
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define(["objectUtils"],
 | 
			
		||||
    function (objectUtils) {
 | 
			
		||||
define(
 | 
			
		||||
    function () {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * Defines the `persistence` capability, used to trigger the
 | 
			
		||||
@@ -47,7 +47,6 @@ define(["objectUtils"],
 | 
			
		||||
            identifierService,
 | 
			
		||||
            notificationService,
 | 
			
		||||
            $q,
 | 
			
		||||
            openmct,
 | 
			
		||||
            domainObject
 | 
			
		||||
        ) {
 | 
			
		||||
            // Cache modified timestamp
 | 
			
		||||
@@ -59,7 +58,6 @@ define(["objectUtils"],
 | 
			
		||||
            this.persistenceService = persistenceService;
 | 
			
		||||
            this.notificationService = notificationService;
 | 
			
		||||
            this.$q = $q;
 | 
			
		||||
            this.openmct = openmct;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
@@ -68,7 +66,7 @@ define(["objectUtils"],
 | 
			
		||||
         */
 | 
			
		||||
        function rejectIfFalsey(value, $q) {
 | 
			
		||||
            if (!value) {
 | 
			
		||||
                return Promise.reject("Error persisting object");
 | 
			
		||||
                return $q.reject("Error persisting object");
 | 
			
		||||
            } else {
 | 
			
		||||
                return value;
 | 
			
		||||
            }
 | 
			
		||||
@@ -100,7 +98,7 @@ define(["objectUtils"],
 | 
			
		||||
                dismissable: true
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            return Promise.reject(error);
 | 
			
		||||
            return $q.reject(error);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
@@ -112,16 +110,34 @@ define(["objectUtils"],
 | 
			
		||||
         */
 | 
			
		||||
        PersistenceCapability.prototype.persist = function () {
 | 
			
		||||
            var self = this,
 | 
			
		||||
                domainObject = this.domainObject;
 | 
			
		||||
                domainObject = this.domainObject,
 | 
			
		||||
                model = domainObject.getModel(),
 | 
			
		||||
                modified = model.modified,
 | 
			
		||||
                persisted = model.persisted,
 | 
			
		||||
                persistenceService = this.persistenceService,
 | 
			
		||||
                persistenceFn = persisted !== undefined ?
 | 
			
		||||
                    this.persistenceService.updateObject :
 | 
			
		||||
                    this.persistenceService.createObject;
 | 
			
		||||
 | 
			
		||||
            let newStyleObject = objectUtils.toNewFormat(domainObject.getModel(), domainObject.getId());
 | 
			
		||||
            return this.openmct.objects
 | 
			
		||||
                .save(newStyleObject)
 | 
			
		||||
                .then(function (result) {
 | 
			
		||||
                    return rejectIfFalsey(result, self.$q);
 | 
			
		||||
                }).catch(function (error) {
 | 
			
		||||
                    return notifyOnError(error, domainObject, self.notificationService, self.$q);
 | 
			
		||||
                });
 | 
			
		||||
            if (persisted !== undefined && persisted === modified) {
 | 
			
		||||
                return this.$q.when(true);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // Update persistence timestamp...
 | 
			
		||||
            domainObject.useCapability("mutation", function (m) {
 | 
			
		||||
                m.persisted = modified;
 | 
			
		||||
            }, modified);
 | 
			
		||||
 | 
			
		||||
            // ...and persist
 | 
			
		||||
            return persistenceFn.apply(persistenceService, [
 | 
			
		||||
                this.getSpace(),
 | 
			
		||||
                this.getKey(),
 | 
			
		||||
                domainObject.getModel()
 | 
			
		||||
            ]).then(function (result) {
 | 
			
		||||
                return rejectIfFalsey(result, self.$q);
 | 
			
		||||
            }).catch(function (error) {
 | 
			
		||||
                return notifyOnError(error, domainObject, self.notificationService, self.$q);
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,7 @@
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * PersistenceCapabilitySpec. Created by vwoeltje on 11/6/14.
 | 
			
		||||
 */
 | 
			
		||||
@@ -39,8 +40,7 @@ define(
 | 
			
		||||
                model,
 | 
			
		||||
                SPACE = "some space",
 | 
			
		||||
                persistence,
 | 
			
		||||
                mockOpenMCT,
 | 
			
		||||
                mockNewStyleDomainObject;
 | 
			
		||||
                happyPromise;
 | 
			
		||||
 | 
			
		||||
            function asPromise(value, doCatch) {
 | 
			
		||||
                return (value || {}).then ? value : {
 | 
			
		||||
@@ -56,6 +56,7 @@ define(
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            beforeEach(function () {
 | 
			
		||||
                happyPromise = asPromise(true);
 | 
			
		||||
                model = { someKey: "some value", name: "domain object"};
 | 
			
		||||
 | 
			
		||||
                mockPersistenceService = jasmine.createSpyObj(
 | 
			
		||||
@@ -93,23 +94,12 @@ define(
 | 
			
		||||
                    },
 | 
			
		||||
                    useCapability: jasmine.createSpy()
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                mockNewStyleDomainObject = Object.assign({}, model);
 | 
			
		||||
                mockNewStyleDomainObject.identifier = {
 | 
			
		||||
                    namespace: "",
 | 
			
		||||
                    key: id
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                // Simulate mutation capability
 | 
			
		||||
                mockDomainObject.useCapability.and.callFake(function (capability, mutator) {
 | 
			
		||||
                    if (capability === 'mutation') {
 | 
			
		||||
                        model = mutator(model) || model;
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                mockOpenMCT = {};
 | 
			
		||||
                mockOpenMCT.objects = jasmine.createSpyObj('Object API', ['save']);
 | 
			
		||||
 | 
			
		||||
                mockIdentifierService.parse.and.returnValue(mockIdentifier);
 | 
			
		||||
                mockIdentifier.getSpace.and.returnValue(SPACE);
 | 
			
		||||
                mockIdentifier.getKey.and.returnValue(key);
 | 
			
		||||
@@ -120,28 +110,51 @@ define(
 | 
			
		||||
                    mockIdentifierService,
 | 
			
		||||
                    mockNofificationService,
 | 
			
		||||
                    mockQ,
 | 
			
		||||
                    mockOpenMCT,
 | 
			
		||||
                    mockDomainObject
 | 
			
		||||
                );
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            describe("successful persistence", function () {
 | 
			
		||||
                beforeEach(function () {
 | 
			
		||||
                    mockOpenMCT.objects.save.and.returnValue(Promise.resolve(true));
 | 
			
		||||
                    mockPersistenceService.updateObject.and.returnValue(happyPromise);
 | 
			
		||||
                    mockPersistenceService.createObject.and.returnValue(happyPromise);
 | 
			
		||||
                });
 | 
			
		||||
                it("creates unpersisted objects with the persistence service", function () {
 | 
			
		||||
                    // Verify precondition; no call made during constructor
 | 
			
		||||
                    expect(mockOpenMCT.objects.save).not.toHaveBeenCalled();
 | 
			
		||||
                    expect(mockPersistenceService.createObject).not.toHaveBeenCalled();
 | 
			
		||||
 | 
			
		||||
                    persistence.persist();
 | 
			
		||||
 | 
			
		||||
                    expect(mockOpenMCT.objects.save).toHaveBeenCalledWith(mockNewStyleDomainObject);
 | 
			
		||||
                    expect(mockPersistenceService.createObject).toHaveBeenCalledWith(
 | 
			
		||||
                        SPACE,
 | 
			
		||||
                        key,
 | 
			
		||||
                        model
 | 
			
		||||
                    );
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                it("updates previously persisted objects with the persistence service", function () {
 | 
			
		||||
                    // Verify precondition; no call made during constructor
 | 
			
		||||
                    expect(mockPersistenceService.updateObject).not.toHaveBeenCalled();
 | 
			
		||||
 | 
			
		||||
                    model.persisted = 12321;
 | 
			
		||||
                    persistence.persist();
 | 
			
		||||
 | 
			
		||||
                    expect(mockPersistenceService.updateObject).toHaveBeenCalledWith(
 | 
			
		||||
                        SPACE,
 | 
			
		||||
                        key,
 | 
			
		||||
                        model
 | 
			
		||||
                    );
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                it("reports which persistence space an object belongs to", function () {
 | 
			
		||||
                    expect(persistence.getSpace()).toEqual(SPACE);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                it("updates persisted timestamp on persistence", function () {
 | 
			
		||||
                    model.modified = 12321;
 | 
			
		||||
                    persistence.persist();
 | 
			
		||||
                    expect(model.persisted).toEqual(12321);
 | 
			
		||||
                });
 | 
			
		||||
                it("refreshes the domain object model from persistence", function () {
 | 
			
		||||
                    var refreshModel = {someOtherKey: "some other value"};
 | 
			
		||||
                    model.persisted = 1;
 | 
			
		||||
@@ -152,37 +165,30 @@ define(
 | 
			
		||||
 | 
			
		||||
                it("does not trigger error notification on successful" +
 | 
			
		||||
                    " persistence", function () {
 | 
			
		||||
                    let rejected = false;
 | 
			
		||||
                    return persistence.persist()
 | 
			
		||||
                        .catch(() => rejected = true)
 | 
			
		||||
                        .then(() => {
 | 
			
		||||
                            expect(rejected).toBe(false);
 | 
			
		||||
                            expect(mockNofificationService.error).not.toHaveBeenCalled();
 | 
			
		||||
                        });
 | 
			
		||||
                    persistence.persist();
 | 
			
		||||
                    expect(mockQ.reject).not.toHaveBeenCalled();
 | 
			
		||||
                    expect(mockNofificationService.error).not.toHaveBeenCalled();
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            describe("unsuccessful persistence", function () {
 | 
			
		||||
                var sadPromise = {
 | 
			
		||||
                    then: function (callback) {
 | 
			
		||||
                        return asPromise(callback(0), true);
 | 
			
		||||
                    }
 | 
			
		||||
                };
 | 
			
		||||
                beforeEach(function () {
 | 
			
		||||
                    mockOpenMCT.objects.save.and.returnValue(Promise.resolve(false));
 | 
			
		||||
                    mockPersistenceService.createObject.and.returnValue(sadPromise);
 | 
			
		||||
                });
 | 
			
		||||
                it("rejects on falsey persistence result", function () {
 | 
			
		||||
                    let rejected = false;
 | 
			
		||||
                    return persistence.persist()
 | 
			
		||||
                        .catch(() => rejected = true)
 | 
			
		||||
                        .then(() => {
 | 
			
		||||
                            expect(rejected).toBe(true);
 | 
			
		||||
                        });
 | 
			
		||||
                    persistence.persist();
 | 
			
		||||
                    expect(mockQ.reject).toHaveBeenCalled();
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                it("notifies user on persistence failure", function () {
 | 
			
		||||
                    let rejected = false;
 | 
			
		||||
                    return persistence.persist()
 | 
			
		||||
                        .catch(() => rejected = true)
 | 
			
		||||
                        .then(() => {
 | 
			
		||||
                            expect(rejected).toBe(true);
 | 
			
		||||
                            expect(mockNofificationService.error).toHaveBeenCalled();
 | 
			
		||||
                        });
 | 
			
		||||
                    persistence.persist();
 | 
			
		||||
                    expect(mockQ.reject).toHaveBeenCalled();
 | 
			
		||||
                    expect(mockNofificationService.error).toHaveBeenCalled();
 | 
			
		||||
                });
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 
 | 
			
		||||
@@ -35,8 +35,7 @@ define([
 | 
			
		||||
    './services/LegacyObjectAPIInterceptor',
 | 
			
		||||
    './views/installLegacyViews',
 | 
			
		||||
    './policies/LegacyCompositionPolicyAdapter',
 | 
			
		||||
    './actions/LegacyActionAdapter',
 | 
			
		||||
    './services/LegacyPersistenceAdapter'
 | 
			
		||||
    './actions/LegacyActionAdapter'
 | 
			
		||||
], function (
 | 
			
		||||
    ActionDialogDecorator,
 | 
			
		||||
    AdapterCapability,
 | 
			
		||||
@@ -52,8 +51,7 @@ define([
 | 
			
		||||
    LegacyObjectAPIInterceptor,
 | 
			
		||||
    installLegacyViews,
 | 
			
		||||
    legacyCompositionPolicyAdapter,
 | 
			
		||||
    LegacyActionAdapter,
 | 
			
		||||
    LegacyPersistenceAdapter
 | 
			
		||||
    LegacyActionAdapter
 | 
			
		||||
) {
 | 
			
		||||
    return {
 | 
			
		||||
        name: 'src/adapter',
 | 
			
		||||
@@ -116,13 +114,6 @@ define([
 | 
			
		||||
                            "instantiate",
 | 
			
		||||
                            "topic"
 | 
			
		||||
                        ]
 | 
			
		||||
                    },
 | 
			
		||||
                    {
 | 
			
		||||
                        provides: "persistenceService",
 | 
			
		||||
                        type: "provider",
 | 
			
		||||
                        priority: "fallback",
 | 
			
		||||
                        implementation: LegacyPersistenceAdapter.default,
 | 
			
		||||
                        depends: ["openmct"]
 | 
			
		||||
                    }
 | 
			
		||||
                ],
 | 
			
		||||
                policies: [
 | 
			
		||||
 
 | 
			
		||||
@@ -25,11 +25,10 @@ define([
 | 
			
		||||
], function (
 | 
			
		||||
    utils
 | 
			
		||||
) {
 | 
			
		||||
    function ObjectServiceProvider(eventEmitter, objectService, instantiate, topic, $injector) {
 | 
			
		||||
    function ObjectServiceProvider(eventEmitter, objectService, instantiate, topic) {
 | 
			
		||||
        this.eventEmitter = eventEmitter;
 | 
			
		||||
        this.objectService = objectService;
 | 
			
		||||
        this.instantiate = instantiate;
 | 
			
		||||
        this.$injector = $injector;
 | 
			
		||||
 | 
			
		||||
        this.generalTopic = topic('mutation');
 | 
			
		||||
        this.bridgeEventBuses();
 | 
			
		||||
@@ -69,53 +68,16 @@ define([
 | 
			
		||||
        removeGeneralTopicListener = this.generalTopic.listen(handleLegacyMutation);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ObjectServiceProvider.prototype.create = async function (object) {
 | 
			
		||||
        let model = utils.toOldFormat(object);
 | 
			
		||||
    ObjectServiceProvider.prototype.save = function (object) {
 | 
			
		||||
        var key = object.key;
 | 
			
		||||
 | 
			
		||||
        return this.getPersistenceService().createObject(
 | 
			
		||||
            this.getSpace(utils.makeKeyString(object.identifier)),
 | 
			
		||||
            object.identifier.key,
 | 
			
		||||
            model
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
    ObjectServiceProvider.prototype.update = async function (object) {
 | 
			
		||||
        let model = utils.toOldFormat(object);
 | 
			
		||||
 | 
			
		||||
        return this.getPersistenceService().updateObject(
 | 
			
		||||
            this.getSpace(utils.makeKeyString(object.identifier)),
 | 
			
		||||
            object.identifier.key,
 | 
			
		||||
            model
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the space in which this domain object is persisted;
 | 
			
		||||
     * this is useful when, for example, decided which space a
 | 
			
		||||
     * newly-created domain object should be persisted to (by
 | 
			
		||||
     * default, this should be the space of its containing
 | 
			
		||||
     * object.)
 | 
			
		||||
     *
 | 
			
		||||
     * @returns {string} the name of the space which should
 | 
			
		||||
     *          be used to persist this object
 | 
			
		||||
     */
 | 
			
		||||
    ObjectServiceProvider.prototype.getSpace = function (keystring) {
 | 
			
		||||
        return this.getIdentifierService().parse(keystring).getSpace();
 | 
			
		||||
        return object.getCapability('persistence')
 | 
			
		||||
            .persist()
 | 
			
		||||
            .then(function () {
 | 
			
		||||
                return utils.toNewFormat(object, key);
 | 
			
		||||
            });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ObjectServiceProvider.prototype.getIdentifierService = function () {
 | 
			
		||||
        if (this.identifierService === undefined) {
 | 
			
		||||
            this.identifierService = this.$injector.get('identifierService');
 | 
			
		||||
        }
 | 
			
		||||
        return this.identifierService;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ObjectServiceProvider.prototype.getPersistenceService = function () {
 | 
			
		||||
        if (this.persistenceService === undefined) {
 | 
			
		||||
            this.persistenceService = this.$injector.get('persistenceService');
 | 
			
		||||
        }
 | 
			
		||||
        return this.persistenceService;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ObjectServiceProvider.prototype.delete = function (object) {
 | 
			
		||||
        // TODO!
 | 
			
		||||
    };
 | 
			
		||||
@@ -156,8 +118,7 @@ define([
 | 
			
		||||
                eventEmitter,
 | 
			
		||||
                objectService,
 | 
			
		||||
                instantiate,
 | 
			
		||||
                topic,
 | 
			
		||||
                openmct.$injector
 | 
			
		||||
                topic
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,28 +0,0 @@
 | 
			
		||||
import objectUtils from 'objectUtils';
 | 
			
		||||
 | 
			
		||||
function LegacyPersistenceProvider(openmct) {
 | 
			
		||||
    this.openmct = openmct;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LegacyPersistenceProvider.prototype.listObjects = function () {
 | 
			
		||||
    return Promise.resolve([]);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LegacyPersistenceProvider.prototype.listSpaces = function () {
 | 
			
		||||
    return Promise.resolve(Object.keys(this.openmct.objects.providers));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LegacyPersistenceProvider.prototype.updateObject = function (legacyDomainObject) {
 | 
			
		||||
    return this.openmct.objects.save(legacyDomainObject.useCapability('adapter'));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LegacyPersistenceProvider.prototype.updateObject = function (legacyDomainObject) {
 | 
			
		||||
    return this.openmct.objects.save(legacyDomainObject.useCapability('adapter'));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
LegacyPersistenceProvider.prototype.readObject = function (keystring) {
 | 
			
		||||
    let identifier = objectUtils.parseKeyString(keystring);
 | 
			
		||||
    return this.openmct.legacyObject(this.openmct.objects.get(identifier));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export default LegacyPersistenceProvider;
 | 
			
		||||
@@ -101,25 +101,14 @@ define([
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create the given domain object in the corresponding persistence store
 | 
			
		||||
     * Save this domain object in its current state.
 | 
			
		||||
     *
 | 
			
		||||
     * @method create
 | 
			
		||||
     * @method save
 | 
			
		||||
     * @memberof module:openmct.ObjectProvider#
 | 
			
		||||
     * @param {module:openmct.DomainObject} domainObject the domain object to
 | 
			
		||||
     *        create
 | 
			
		||||
     *        save
 | 
			
		||||
     * @returns {Promise} a promise which will resolve when the domain object
 | 
			
		||||
     *          has been created, or be rejected if it cannot be saved
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Update this domain object in its persistence store
 | 
			
		||||
     *
 | 
			
		||||
     * @method update
 | 
			
		||||
     * @memberof module:openmct.ObjectProvider#
 | 
			
		||||
     * @param {module:openmct.DomainObject} domainObject the domain object to
 | 
			
		||||
     *        update
 | 
			
		||||
     * @returns {Promise} a promise which will resolve when the domain object
 | 
			
		||||
     *          has been updated, or be rejected if it cannot be saved
 | 
			
		||||
     *          has been saved, or be rejected if it cannot be saved
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -172,41 +161,8 @@ define([
 | 
			
		||||
        throw new Error('Delete not implemented');
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    ObjectAPI.prototype.isPersistable = function (domainObject) {
 | 
			
		||||
        let provider = this.getProvider(domainObject.identifier);
 | 
			
		||||
        return provider !== undefined &&
 | 
			
		||||
            provider.create !== undefined &&
 | 
			
		||||
            provider.update !== undefined;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Save this domain object in its current state. EXPERIMENTAL
 | 
			
		||||
     *
 | 
			
		||||
     * @private
 | 
			
		||||
     * @memberof module:openmct.ObjectAPI#
 | 
			
		||||
     * @param {module:openmct.DomainObject} domainObject the domain object to
 | 
			
		||||
     *        save
 | 
			
		||||
     * @returns {Promise} a promise which will resolve when the domain object
 | 
			
		||||
     *          has been saved, or be rejected if it cannot be saved
 | 
			
		||||
     */
 | 
			
		||||
    ObjectAPI.prototype.save = function (domainObject) {
 | 
			
		||||
        let provider = this.getProvider(domainObject.identifier);
 | 
			
		||||
        let result;
 | 
			
		||||
 | 
			
		||||
        if (!this.isPersistable(domainObject)) {
 | 
			
		||||
            result = Promise.reject('Object provider does not support saving');
 | 
			
		||||
        } else if (hasAlreadyBeenPersisted(domainObject)) {
 | 
			
		||||
            result = Promise.resolve(true);
 | 
			
		||||
        } else {
 | 
			
		||||
            if (domainObject.persisted === undefined) {
 | 
			
		||||
                this.mutate(domainObject, 'persisted', domainObject.modified);
 | 
			
		||||
                result = provider.create(domainObject);
 | 
			
		||||
            } else {
 | 
			
		||||
                this.mutate(domainObject, 'persisted', domainObject.modified);
 | 
			
		||||
                result = provider.update(domainObject);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    ObjectAPI.prototype.save = function () {
 | 
			
		||||
        throw new Error('Save not implemented');
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -320,9 +276,5 @@ define([
 | 
			
		||||
     * @memberof module:openmct
 | 
			
		||||
     */
 | 
			
		||||
 | 
			
		||||
    function hasAlreadyBeenPersisted(domainObject) {
 | 
			
		||||
        return domainObject.persisted !== undefined &&
 | 
			
		||||
            domainObject.persisted === domainObject.modified;
 | 
			
		||||
    }
 | 
			
		||||
    return ObjectAPI;
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,60 +0,0 @@
 | 
			
		||||
import ObjectAPI from './ObjectAPI.js';
 | 
			
		||||
 | 
			
		||||
describe("The Object API", () => {
 | 
			
		||||
    let objectAPI;
 | 
			
		||||
    let mockDomainObject;
 | 
			
		||||
    const TEST_NAMESPACE = "test-namespace";
 | 
			
		||||
    const FIFTEEN_MINUTES = 15 * 60 * 1000;
 | 
			
		||||
 | 
			
		||||
    beforeEach(() => {
 | 
			
		||||
        objectAPI = new ObjectAPI();
 | 
			
		||||
        mockDomainObject = {
 | 
			
		||||
            identifier: {
 | 
			
		||||
                namespace: TEST_NAMESPACE,
 | 
			
		||||
                key: "test-key"
 | 
			
		||||
            },
 | 
			
		||||
            name: "test object",
 | 
			
		||||
            type: "test-type"
 | 
			
		||||
        };
 | 
			
		||||
    })
 | 
			
		||||
    describe("The save function", () => {
 | 
			
		||||
        it("Rejects if no provider available", () => {
 | 
			
		||||
            let rejected = false;
 | 
			
		||||
            return objectAPI.save(mockDomainObject)
 | 
			
		||||
                .catch(() => rejected = true)
 | 
			
		||||
                .then(() => expect(rejected).toBe(true));
 | 
			
		||||
        });
 | 
			
		||||
        describe("when a provider is available", () => {
 | 
			
		||||
            let mockProvider;
 | 
			
		||||
            beforeEach(() => {
 | 
			
		||||
                mockProvider = jasmine.createSpyObj("mock provider", [
 | 
			
		||||
                    "create",
 | 
			
		||||
                    "update"
 | 
			
		||||
                ]);
 | 
			
		||||
                objectAPI.addProvider(TEST_NAMESPACE, mockProvider);
 | 
			
		||||
            })
 | 
			
		||||
            it("Calls 'create' on provider if object is new", () => {
 | 
			
		||||
                objectAPI.save(mockDomainObject);
 | 
			
		||||
                expect(mockProvider.create).toHaveBeenCalled();
 | 
			
		||||
                expect(mockProvider.update).not.toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
            it("Calls 'update' on provider if object is not new", () => {
 | 
			
		||||
                mockDomainObject.persisted = Date.now() - FIFTEEN_MINUTES;
 | 
			
		||||
                mockDomainObject.modified = Date.now();
 | 
			
		||||
 | 
			
		||||
                objectAPI.save(mockDomainObject);
 | 
			
		||||
                expect(mockProvider.create).not.toHaveBeenCalled();
 | 
			
		||||
                expect(mockProvider.update).toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it("Does not persist if the object is unchanged", () => {
 | 
			
		||||
                mockDomainObject.persisted =
 | 
			
		||||
                    mockDomainObject.modified = Date.now();
 | 
			
		||||
 | 
			
		||||
                objectAPI.save(mockDomainObject);
 | 
			
		||||
                expect(mockProvider.create).not.toHaveBeenCalled();
 | 
			
		||||
                expect(mockProvider.update).not.toHaveBeenCalled();
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    })
 | 
			
		||||
});
 | 
			
		||||
@@ -334,8 +334,8 @@ define([
 | 
			
		||||
            });
 | 
			
		||||
            if (subscriber.callbacks.length === 0) {
 | 
			
		||||
                subscriber.unsubscribe();
 | 
			
		||||
                delete this.subscribeCache[keyString];
 | 
			
		||||
            }
 | 
			
		||||
            delete this.subscribeCache[keyString];
 | 
			
		||||
        }.bind(this);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -156,29 +156,6 @@ define([
 | 
			
		||||
                expect(callbacktwo).not.toHaveBeenCalledWith('anotherValue');
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('only deletes subscription cache when there are no more subscribers', function () {
 | 
			
		||||
                var unsubFunc = jasmine.createSpy('unsubscribe');
 | 
			
		||||
                telemetryProvider.subscribe.and.returnValue(unsubFunc);
 | 
			
		||||
                telemetryProvider.supportsSubscribe.and.returnValue(true);
 | 
			
		||||
                telemetryAPI.addProvider(telemetryProvider);
 | 
			
		||||
 | 
			
		||||
                var callback = jasmine.createSpy('callback');
 | 
			
		||||
                var callbacktwo = jasmine.createSpy('callback two');
 | 
			
		||||
                var callbackThree = jasmine.createSpy('callback three');
 | 
			
		||||
                var unsubscribe = telemetryAPI.subscribe(domainObject, callback);
 | 
			
		||||
                var unsubscribeTwo = telemetryAPI.subscribe(domainObject, callbacktwo);
 | 
			
		||||
 | 
			
		||||
                expect(telemetryProvider.subscribe.calls.count()).toBe(1);
 | 
			
		||||
                unsubscribe();
 | 
			
		||||
                var unsubscribeThree = telemetryAPI.subscribe(domainObject, callbackThree);
 | 
			
		||||
                // Regression test for where subscription cache was deleted on each unsubscribe, resulting in
 | 
			
		||||
                // superfluous additional subscriptions. If the subscription cache is being deleted on each unsubscribe,
 | 
			
		||||
                // then a subsequent subscribe will result in a new subscription at the provider.
 | 
			
		||||
                expect(telemetryProvider.subscribe.calls.count()).toBe(1);
 | 
			
		||||
                unsubscribeTwo();
 | 
			
		||||
                unsubscribeThree();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('does subscribe/unsubscribe', function () {
 | 
			
		||||
                var unsubFunc = jasmine.createSpy('unsubscribe');
 | 
			
		||||
                telemetryProvider.subscribe.and.returnValue(unsubFunc);
 | 
			
		||||
 
 | 
			
		||||
@@ -64,7 +64,7 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    computed: {
 | 
			
		||||
        formattedTimestamp() {
 | 
			
		||||
            return this.timestamp !== undefined ? this.getFormattedTimestamp(this.timestamp) : '---';
 | 
			
		||||
            return this.timestamp !== undefined ? this.formats[this.timestampKey].format(this.timestamp) : '---';
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    mounted() {
 | 
			
		||||
@@ -110,11 +110,11 @@ export default {
 | 
			
		||||
    },
 | 
			
		||||
    methods: {
 | 
			
		||||
        updateValues(datum) {
 | 
			
		||||
            let newTimestamp = this.getParsedTimestamp(datum),
 | 
			
		||||
            let newTimestamp = this.formats[this.timestampKey].parse(datum),
 | 
			
		||||
                limit;
 | 
			
		||||
 | 
			
		||||
            if(this.shouldUpdate(newTimestamp)) {
 | 
			
		||||
                this.timestamp = newTimestamp;
 | 
			
		||||
                this.timestamp = this.formats[this.timestampKey].parse(datum);
 | 
			
		||||
                this.value = this.formats[this.valueKey].format(datum);
 | 
			
		||||
                limit = this.limitEvaluator.evaluate(datum, this.valueMetadata);
 | 
			
		||||
                if (limit) {
 | 
			
		||||
@@ -125,12 +125,9 @@ export default {
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        shouldUpdate(newTimestamp) {
 | 
			
		||||
            let newTimestampInBounds = this.inBounds(newTimestamp),
 | 
			
		||||
                noExistingTimestamp = this.timestamp === undefined,
 | 
			
		||||
                newTimestampIsLatest = newTimestamp > this.timestamp;
 | 
			
		||||
 | 
			
		||||
            return newTimestampInBounds &&
 | 
			
		||||
                (noExistingTimestamp || newTimestampIsLatest);
 | 
			
		||||
            return (this.timestamp === undefined) ||
 | 
			
		||||
                (this.inBounds(newTimestamp) &&
 | 
			
		||||
                newTimestamp > this.timestamp);
 | 
			
		||||
        },
 | 
			
		||||
        requestHistory() {
 | 
			
		||||
            this.openmct
 | 
			
		||||
@@ -149,7 +146,6 @@ export default {
 | 
			
		||||
        updateBounds(bounds, isTick) {
 | 
			
		||||
            this.bounds = bounds;
 | 
			
		||||
            if(!isTick) {
 | 
			
		||||
                this.resetValues();
 | 
			
		||||
                this.requestHistory();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
@@ -157,34 +153,13 @@ export default {
 | 
			
		||||
            return timestamp >= this.bounds.start && timestamp <= this.bounds.end;
 | 
			
		||||
        },
 | 
			
		||||
        updateTimeSystem(timeSystem) {
 | 
			
		||||
            this.resetValues();
 | 
			
		||||
            this.value = '---';
 | 
			
		||||
            this.timestamp = '---';
 | 
			
		||||
            this.valueClass = '';
 | 
			
		||||
            this.timestampKey = timeSystem.key;
 | 
			
		||||
        },
 | 
			
		||||
        showContextMenu(event) {
 | 
			
		||||
            this.openmct.contextMenu._showContextMenuForObjectPath(this.currentObjectPath, event.x, event.y, CONTEXT_MENU_ACTIONS);
 | 
			
		||||
        },
 | 
			
		||||
        resetValues() {
 | 
			
		||||
            this.value = '---';
 | 
			
		||||
            this.timestamp = undefined;
 | 
			
		||||
            this.valueClass = '';
 | 
			
		||||
        },
 | 
			
		||||
        getParsedTimestamp(timestamp) {
 | 
			
		||||
            if(this.timeSystemFormat()) {
 | 
			
		||||
                return this.formats[this.timestampKey].parse(timestamp);
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        getFormattedTimestamp(timestamp) {
 | 
			
		||||
            if(this.timeSystemFormat()) {
 | 
			
		||||
                return this.formats[this.timestampKey].format(timestamp);
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        timeSystemFormat() {
 | 
			
		||||
            if(this.formats[this.timestampKey]) {
 | 
			
		||||
                return true;
 | 
			
		||||
            } else {
 | 
			
		||||
                console.warn(`No formatter for ${this.timestampKey} time system for ${this.domainObject.name}.`);
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -29,28 +29,24 @@ define([
 | 
			
		||||
    ClearDataAction,
 | 
			
		||||
    Vue
 | 
			
		||||
) {
 | 
			
		||||
    return function plugin(appliesToObjects, options = {indicator: true}) {
 | 
			
		||||
        let installIndicator = options.indicator;
 | 
			
		||||
 | 
			
		||||
    return function plugin(appliesToObjects) {
 | 
			
		||||
        appliesToObjects = appliesToObjects || [];
 | 
			
		||||
 | 
			
		||||
        return function install(openmct) {
 | 
			
		||||
            if (installIndicator) {
 | 
			
		||||
                let component = new Vue ({
 | 
			
		||||
                        provide: {
 | 
			
		||||
                            openmct
 | 
			
		||||
                        },
 | 
			
		||||
                        components: {
 | 
			
		||||
                            GlobalClearIndicator: GlobaClearIndicator.default
 | 
			
		||||
                        },
 | 
			
		||||
                        template: '<GlobalClearIndicator></GlobalClearIndicator>'
 | 
			
		||||
                    }),
 | 
			
		||||
                    indicator = {
 | 
			
		||||
                        element: component.$mount().$el
 | 
			
		||||
                    };
 | 
			
		||||
            let component = new Vue ({
 | 
			
		||||
                    provide: {
 | 
			
		||||
                        openmct
 | 
			
		||||
                    },
 | 
			
		||||
                    components: {
 | 
			
		||||
                        GlobalClearIndicator: GlobaClearIndicator.default
 | 
			
		||||
                    },
 | 
			
		||||
                    template: '<GlobalClearIndicator></GlobalClearIndicator>'
 | 
			
		||||
                }),
 | 
			
		||||
                indicator = {
 | 
			
		||||
                    element: component.$mount().$el
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                openmct.indicators.add(indicator);
 | 
			
		||||
            }
 | 
			
		||||
            openmct.indicators.add(indicator);
 | 
			
		||||
 | 
			
		||||
            openmct.contextMenu.registerAction(new ClearDataAction.default(openmct, appliesToObjects));
 | 
			
		||||
        };
 | 
			
		||||
 
 | 
			
		||||
@@ -103,8 +103,6 @@ export default class ConditionManager extends EventEmitter {
 | 
			
		||||
                        criterion.operation = '';
 | 
			
		||||
                        conditionChanged = true;
 | 
			
		||||
                    }
 | 
			
		||||
                } else {
 | 
			
		||||
                    conditionChanged = true;
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
            if (conditionChanged) {
 | 
			
		||||
 
 | 
			
		||||
@@ -46,7 +46,6 @@ export default class StyleRuleManager extends EventEmitter {
 | 
			
		||||
        if (this.isEditing) {
 | 
			
		||||
            if (this.stopProvidingTelemetry) {
 | 
			
		||||
                this.stopProvidingTelemetry();
 | 
			
		||||
                delete this.stopProvidingTelemetry;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.conditionSetIdentifier) {
 | 
			
		||||
                this.applySelectedConditionStyle();
 | 
			
		||||
@@ -67,7 +66,6 @@ export default class StyleRuleManager extends EventEmitter {
 | 
			
		||||
    subscribeToConditionSet() {
 | 
			
		||||
        if (this.stopProvidingTelemetry) {
 | 
			
		||||
            this.stopProvidingTelemetry();
 | 
			
		||||
            delete this.stopProvidingTelemetry;
 | 
			
		||||
        }
 | 
			
		||||
        this.openmct.objects.get(this.conditionSetIdentifier).then((conditionSetDomainObject) => {
 | 
			
		||||
            this.openmct.telemetry.request(conditionSetDomainObject)
 | 
			
		||||
@@ -156,8 +154,8 @@ export default class StyleRuleManager extends EventEmitter {
 | 
			
		||||
        this.applyStaticStyle();
 | 
			
		||||
        if (this.stopProvidingTelemetry) {
 | 
			
		||||
            this.stopProvidingTelemetry();
 | 
			
		||||
            delete this.stopProvidingTelemetry;
 | 
			
		||||
        }
 | 
			
		||||
        delete this.stopProvidingTelemetry;
 | 
			
		||||
        this.conditionSetIdentifier = undefined;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -197,7 +197,6 @@ export default {
 | 
			
		||||
            }
 | 
			
		||||
            if (this.stopProvidingTelemetry) {
 | 
			
		||||
                this.stopProvidingTelemetry();
 | 
			
		||||
                delete this.stopProvidingTelemetry;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        initialize(conditionSetDomainObject) {
 | 
			
		||||
@@ -211,7 +210,6 @@ export default {
 | 
			
		||||
            if (this.isEditing) {
 | 
			
		||||
                if (this.stopProvidingTelemetry) {
 | 
			
		||||
                    this.stopProvidingTelemetry();
 | 
			
		||||
                    delete this.stopProvidingTelemetry;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                this.subscribeToConditionSet();
 | 
			
		||||
@@ -309,7 +307,6 @@ export default {
 | 
			
		||||
            this.persist(domainObjectStyles);
 | 
			
		||||
            if (this.stopProvidingTelemetry) {
 | 
			
		||||
                this.stopProvidingTelemetry();
 | 
			
		||||
                delete this.stopProvidingTelemetry;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        updateDomainObjectItemStyles(newItems) {
 | 
			
		||||
@@ -378,7 +375,6 @@ export default {
 | 
			
		||||
        subscribeToConditionSet() {
 | 
			
		||||
            if (this.stopProvidingTelemetry) {
 | 
			
		||||
                this.stopProvidingTelemetry();
 | 
			
		||||
                delete this.stopProvidingTelemetry;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.conditionSetDomainObject) {
 | 
			
		||||
                this.openmct.telemetry.request(this.conditionSetDomainObject)
 | 
			
		||||
 
 | 
			
		||||
@@ -190,7 +190,6 @@ export default {
 | 
			
		||||
            if (this.isEditing) {
 | 
			
		||||
                if (this.stopProvidingTelemetry) {
 | 
			
		||||
                    this.stopProvidingTelemetry();
 | 
			
		||||
                    delete this.stopProvidingTelemetry;
 | 
			
		||||
                }
 | 
			
		||||
            } else {
 | 
			
		||||
                this.subscribeToConditionSet();
 | 
			
		||||
@@ -326,7 +325,6 @@ export default {
 | 
			
		||||
 | 
			
		||||
            if (this.stopProvidingTelemetry) {
 | 
			
		||||
                this.stopProvidingTelemetry();
 | 
			
		||||
                delete this.stopProvidingTelemetry;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.unObserveObjects) {
 | 
			
		||||
@@ -339,7 +337,6 @@ export default {
 | 
			
		||||
        subscribeToConditionSet() {
 | 
			
		||||
            if (this.stopProvidingTelemetry) {
 | 
			
		||||
                this.stopProvidingTelemetry();
 | 
			
		||||
                delete this.stopProvidingTelemetry;
 | 
			
		||||
            }
 | 
			
		||||
            if (this.conditionSetDomainObject) {
 | 
			
		||||
                this.openmct.telemetry.request(this.conditionSetDomainObject)
 | 
			
		||||
@@ -497,7 +494,6 @@ export default {
 | 
			
		||||
 | 
			
		||||
            if (this.stopProvidingTelemetry) {
 | 
			
		||||
                this.stopProvidingTelemetry();
 | 
			
		||||
                delete this.stopProvidingTelemetry;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        removeConditionalStyles(domainObjectStyles, itemId) {
 | 
			
		||||
 
 | 
			
		||||
@@ -457,43 +457,15 @@ export default {
 | 
			
		||||
            this.objectViewMap = {};
 | 
			
		||||
            this.layoutItems.forEach(this.trackItem);
 | 
			
		||||
        },
 | 
			
		||||
        isItemAlreadyTracked(child) {
 | 
			
		||||
            let found = false,
 | 
			
		||||
                keyString = this.openmct.objects.makeKeyString(child.identifier);
 | 
			
		||||
 | 
			
		||||
            this.layoutItems.forEach(item => {
 | 
			
		||||
                if (item.identifier) {
 | 
			
		||||
                    let itemKeyString = this.openmct.objects.makeKeyString(item.identifier);
 | 
			
		||||
 | 
			
		||||
                    if (itemKeyString === keyString) {
 | 
			
		||||
                        found = true;
 | 
			
		||||
                        return;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            if (found) {
 | 
			
		||||
                return true;
 | 
			
		||||
            } else if (this.isTelemetry(child)) {
 | 
			
		||||
                return this.telemetryViewMap[keyString] && this.objectViewMap[keyString];
 | 
			
		||||
            } else {
 | 
			
		||||
                return this.objectViewMap[keyString];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        addChild(child) {
 | 
			
		||||
            if (this.isItemAlreadyTracked(child)) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let type;
 | 
			
		||||
 | 
			
		||||
            let keyString = this.openmct.objects.makeKeyString(child.identifier);
 | 
			
		||||
            if (this.isTelemetry(child)) {
 | 
			
		||||
                type = 'telemetry-view';
 | 
			
		||||
            } else {
 | 
			
		||||
                type = 'subobject-view';
 | 
			
		||||
                if (!this.telemetryViewMap[keyString] && !this.objectViewMap[keyString]) {
 | 
			
		||||
                    this.addItem('telemetry-view', child);
 | 
			
		||||
                }
 | 
			
		||||
            } else if (!this.objectViewMap[keyString]) {
 | 
			
		||||
                this.addItem('subobject-view', child);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.addItem(type, child);
 | 
			
		||||
        },
 | 
			
		||||
        removeChild(identifier) {
 | 
			
		||||
            let keyString = this.openmct.objects.makeKeyString(identifier);
 | 
			
		||||
@@ -587,17 +559,14 @@ export default {
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        updateTelemetryFormat(item, format) {
 | 
			
		||||
            let index = this.layoutItems.findIndex((layoutItem) => {
 | 
			
		||||
                return layoutItem.id === item.id;
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            let index = this.layoutItems.findIndex(item);
 | 
			
		||||
            item.format = format;
 | 
			
		||||
            this.mutate(`configuration.items[${index}]`, item);
 | 
			
		||||
        },
 | 
			
		||||
        createNewDomainObject(domainObject, composition, viewType, nameExtension, model) {
 | 
			
		||||
            let identifier = {
 | 
			
		||||
                    key: uuid(),
 | 
			
		||||
                    namespace: this.internalDomainObject.identifier.namespace
 | 
			
		||||
                    namespace: domainObject.identifier.namespace
 | 
			
		||||
                },
 | 
			
		||||
                type = this.openmct.types.get(viewType),
 | 
			
		||||
                parentKeyString = this.openmct.objects.makeKeyString(this.internalDomainObject.identifier),
 | 
			
		||||
 
 | 
			
		||||
@@ -31,16 +31,10 @@
 | 
			
		||||
    <div
 | 
			
		||||
        v-if="domainObject"
 | 
			
		||||
        class="c-telemetry-view"
 | 
			
		||||
        :class="{
 | 
			
		||||
            styleClass,
 | 
			
		||||
            'is-missing': domainObject.status === 'missing'
 | 
			
		||||
        }"
 | 
			
		||||
        :class="styleClass"
 | 
			
		||||
        :style="styleObject"
 | 
			
		||||
        @contextmenu.prevent="showContextMenu"
 | 
			
		||||
    >
 | 
			
		||||
        <div class="is-missing__indicator"
 | 
			
		||||
             title="This item is missing"
 | 
			
		||||
        ></div>
 | 
			
		||||
        <div
 | 
			
		||||
            v-if="showLabel"
 | 
			
		||||
            class="c-telemetry-view__label"
 | 
			
		||||
 
 | 
			
		||||
@@ -26,15 +26,4 @@
 | 
			
		||||
        @include abs();
 | 
			
		||||
        border: 1px solid transparent;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @include isMissing($absPos: true);
 | 
			
		||||
 | 
			
		||||
    .is-missing__indicator {
 | 
			
		||||
        top: 0;
 | 
			
		||||
        left: 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.is-missing {
 | 
			
		||||
        border: $borderMissing;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,18 +1,13 @@
 | 
			
		||||
<template>
 | 
			
		||||
<a
 | 
			
		||||
    class="l-grid-view__item c-grid-item"
 | 
			
		||||
    :class="{
 | 
			
		||||
        'is-alias': item.isAlias === true,
 | 
			
		||||
        'is-missing': item.model.status === 'missing',
 | 
			
		||||
        'c-grid-item--unknown': item.type.cssClass === undefined || item.type.cssClass.indexOf('unknown') !== -1
 | 
			
		||||
    }"
 | 
			
		||||
    :class="{ 'is-alias': item.isAlias === true }"
 | 
			
		||||
    :href="objectLink"
 | 
			
		||||
>
 | 
			
		||||
    <div
 | 
			
		||||
        class="c-grid-item__type-icon"
 | 
			
		||||
        :class="(item.type.cssClass != undefined) ? 'bg-' + item.type.cssClass : 'bg-icon-object-unknown'"
 | 
			
		||||
    >
 | 
			
		||||
    </div>
 | 
			
		||||
    ></div>
 | 
			
		||||
    <div class="c-grid-item__details">
 | 
			
		||||
        <!-- Name and metadata -->
 | 
			
		||||
        <div
 | 
			
		||||
@@ -27,9 +22,6 @@
 | 
			
		||||
        </div>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="c-grid-item__controls">
 | 
			
		||||
        <div class="is-missing__indicator"
 | 
			
		||||
             title="This item is missing"
 | 
			
		||||
        ></div>
 | 
			
		||||
        <div
 | 
			
		||||
            class="icon-people"
 | 
			
		||||
            title="Shared"
 | 
			
		||||
 
 | 
			
		||||
@@ -7,19 +7,13 @@
 | 
			
		||||
    <td class="c-list-item__name">
 | 
			
		||||
        <a
 | 
			
		||||
            ref="objectLink"
 | 
			
		||||
            class="c-object-label"
 | 
			
		||||
            :class="{ 'is-missing': item.model.status === 'missing' }"
 | 
			
		||||
            :href="objectLink"
 | 
			
		||||
        >
 | 
			
		||||
            <div
 | 
			
		||||
                class="c-object-label__type-icon c-list-item__type-icon"
 | 
			
		||||
                class="c-list-item__type-icon"
 | 
			
		||||
                :class="item.type.cssClass"
 | 
			
		||||
            >
 | 
			
		||||
                <span class="is-missing__indicator"
 | 
			
		||||
                      title="This item is missing"
 | 
			
		||||
                ></span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="c-object-label__name c-list-item__name">{{ item.model.name }}</div>
 | 
			
		||||
            ></div>
 | 
			
		||||
            <div class="c-list-item__name-value">{{ item.model.name }}</div>
 | 
			
		||||
        </a>
 | 
			
		||||
    </td>
 | 
			
		||||
    <td class="c-list-item__type">
 | 
			
		||||
 
 | 
			
		||||
@@ -38,15 +38,7 @@
 | 
			
		||||
        // Object is an alias to an original.
 | 
			
		||||
        [class*='__type-icon'] {
 | 
			
		||||
            @include isAlias();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.is-missing {
 | 
			
		||||
        @include isMissing();
 | 
			
		||||
 | 
			
		||||
        [class*='__type-icon'],
 | 
			
		||||
        [class*='__details'] {
 | 
			
		||||
            opacity: $opacityMissing;
 | 
			
		||||
            color: $colorIconAliasForKeyFilter;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -93,14 +85,15 @@
 | 
			
		||||
    body.desktop & {
 | 
			
		||||
        $transOutMs: 300ms;
 | 
			
		||||
        flex-flow: column nowrap;
 | 
			
		||||
        transition: $transOutMs ease-in-out;
 | 
			
		||||
        transition: background $transOutMs ease-in-out;
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
            filter: $filterItemHoverFg;
 | 
			
		||||
            background: $colorItemBgHov;
 | 
			
		||||
            transition: $transIn;
 | 
			
		||||
 | 
			
		||||
            .c-grid-item__type-icon {
 | 
			
		||||
                transform: scale(1.1);
 | 
			
		||||
                filter: $colorKeyFilterHov;
 | 
			
		||||
                transform: scale(1);
 | 
			
		||||
                transition: $transInBounce;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
@@ -110,7 +103,7 @@
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &__controls {
 | 
			
		||||
            align-items: baseline;
 | 
			
		||||
            align-items: start;
 | 
			
		||||
            flex: 0 0 auto;
 | 
			
		||||
            order: 1;
 | 
			
		||||
            .c-info-button,
 | 
			
		||||
@@ -122,6 +115,7 @@
 | 
			
		||||
            font-size: floor($gridItemDesk / 3);
 | 
			
		||||
            margin: $interiorMargin 22.5% $interiorMargin * 3 22.5%;
 | 
			
		||||
            order: 2;
 | 
			
		||||
            transform: scale(0.9);
 | 
			
		||||
            transform-origin: center;
 | 
			
		||||
            transition: all $transOutMs ease-in-out;
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -1,17 +1,37 @@
 | 
			
		||||
/******************************* LIST ITEM */
 | 
			
		||||
.c-list-item {
 | 
			
		||||
    &__type-icon {
 | 
			
		||||
        color: $colorItemTreeIcon;
 | 
			
		||||
    &__name a {
 | 
			
		||||
        display: flex;
 | 
			
		||||
 | 
			
		||||
        > * + * { margin-left: $interiorMarginSm; }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__name {
 | 
			
		||||
    &__type-icon {
 | 
			
		||||
        // Have to do it this way instead of using icon-* class, due to need to apply alias to the icon
 | 
			
		||||
        color: $colorKey;
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
        width: 1em;
 | 
			
		||||
        margin-right:$interiorMarginSm;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__name-value {
 | 
			
		||||
        @include ellipsize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.is-alias {
 | 
			
		||||
        // Object is an alias to an original.
 | 
			
		||||
        [class*='__type-icon'] {
 | 
			
		||||
            @include isAlias();
 | 
			
		||||
            &:after {
 | 
			
		||||
                color: $colorIconAlias;
 | 
			
		||||
                content: $glyph-icon-link;
 | 
			
		||||
                font-family: symbolsfont;
 | 
			
		||||
                display: block;
 | 
			
		||||
                position: absolute;
 | 
			
		||||
                text-shadow: rgba(black, 0.5) 0 1px 2px;
 | 
			
		||||
                top: auto; left: -1px; bottom: 1px; right: auto;
 | 
			
		||||
                transform-origin: bottom left;
 | 
			
		||||
                transform: scale(0.65);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -13,8 +13,7 @@
 | 
			
		||||
            cursor: pointer;
 | 
			
		||||
 | 
			
		||||
            &:hover {
 | 
			
		||||
                background: $colorItemTreeHoverBg;
 | 
			
		||||
                filter: $filterHov;
 | 
			
		||||
                background: $colorListItemBgHov;
 | 
			
		||||
                transition: $transIn;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -24,14 +24,14 @@ import uuid from 'uuid';
 | 
			
		||||
 | 
			
		||||
export default class NewFolderAction {
 | 
			
		||||
    constructor(openmct) {
 | 
			
		||||
        this.name = 'Add New Folder';
 | 
			
		||||
        this.name = 'New Folder';
 | 
			
		||||
        this.key = 'newFolder';
 | 
			
		||||
        this.description = 'Create a new folder';
 | 
			
		||||
        this.cssClass = 'icon-folder-new';
 | 
			
		||||
        this.cssClass = 'icon-folder';
 | 
			
		||||
 | 
			
		||||
        this._openmct = openmct;
 | 
			
		||||
        this._dialogForm = {
 | 
			
		||||
            name: "Add New Folder",
 | 
			
		||||
            name: "New Folder Name",
 | 
			
		||||
            sections: [
 | 
			
		||||
                {
 | 
			
		||||
                    rows: [
 | 
			
		||||
@@ -39,9 +39,7 @@ export default class NewFolderAction {
 | 
			
		||||
                            key: "name",
 | 
			
		||||
                            control: "textfield",
 | 
			
		||||
                            name: "Folder Name",
 | 
			
		||||
                            pattern: "\\S+",
 | 
			
		||||
                            required: true,
 | 
			
		||||
                            cssClass: "l-input-lg"
 | 
			
		||||
                            required: false
 | 
			
		||||
                        }
 | 
			
		||||
                    ]
 | 
			
		||||
                }
 | 
			
		||||
@@ -55,7 +53,7 @@ export default class NewFolderAction {
 | 
			
		||||
            dialogService = this._openmct.$injector.get('dialogService'),
 | 
			
		||||
            folderType = this._openmct.types.get('folder');
 | 
			
		||||
 | 
			
		||||
        dialogService.getUserInput(this._dialogForm, {name: 'Unnamed Folder'}).then((userInput) => {
 | 
			
		||||
        dialogService.getUserInput(this._dialogForm, {}).then((userInput) => {
 | 
			
		||||
            let name = userInput.name,
 | 
			
		||||
                identifier = {
 | 
			
		||||
                    key: uuid(),
 | 
			
		||||
 
 | 
			
		||||
@@ -2,16 +2,13 @@
 | 
			
		||||
<div class="c-snapshots-h">
 | 
			
		||||
    <div class="l-browse-bar">
 | 
			
		||||
        <div class="l-browse-bar__start">
 | 
			
		||||
            <div class="l-browse-bar__object-name--w">
 | 
			
		||||
                <div class="l-browse-bar__object-name c-object-label">
 | 
			
		||||
                    <div class="c-object-label__type-icon icon-notebook"></div>
 | 
			
		||||
                    <div class="c-object-label__name">
 | 
			
		||||
                        Notebook Snapshots
 | 
			
		||||
                        <span v-if="snapshots.length"
 | 
			
		||||
                              class="l-browse-bar__object-details"
 | 
			
		||||
                        > {{ snapshots.length }} of {{ getNotebookSnapshotMaxCount() }}
 | 
			
		||||
                        </span>
 | 
			
		||||
                    </div>
 | 
			
		||||
            <div class="l-browse-bar__object-name--w icon-notebook">
 | 
			
		||||
                <div class="l-browse-bar__object-name">
 | 
			
		||||
                    Notebook Snapshots
 | 
			
		||||
                    <span v-if="snapshots.length"
 | 
			
		||||
                          class="l-browse-bar__object-details"
 | 
			
		||||
                    > {{ snapshots.length }} of {{ getNotebookSnapshotMaxCount() }}
 | 
			
		||||
                    </span>
 | 
			
		||||
                </div>
 | 
			
		||||
                <PopupMenu v-if="snapshots.length > 0"
 | 
			
		||||
                           :popup-menu-items="popupMenuItems"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,53 +0,0 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2018, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * A CouchDocument describes domain object model in a format
 | 
			
		||||
 * which is easily read-written to CouchDB. This includes
 | 
			
		||||
 * Couch's _id and _rev fields, as well as a separate
 | 
			
		||||
 * metadata field which contains a subset of information found
 | 
			
		||||
 * in the model itself (to support search optimization with
 | 
			
		||||
 * CouchDB views.)
 | 
			
		||||
 * @memberof platform/persistence/couch
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @param {string} id the id under which to store this mode
 | 
			
		||||
 * @param {object} model the model to store
 | 
			
		||||
 * @param {string} rev the revision to include (or undefined,
 | 
			
		||||
 *        if no revision should be noted for couch)
 | 
			
		||||
 * @param {boolean} whether or not to mark this document as
 | 
			
		||||
 *        deleted (see CouchDB docs for _deleted)
 | 
			
		||||
 */
 | 
			
		||||
export default function CouchDocument(id, model, rev, markDeleted) {
 | 
			
		||||
    return {
 | 
			
		||||
        "_id": id,
 | 
			
		||||
        "_rev": rev,
 | 
			
		||||
        "_deleted": markDeleted,
 | 
			
		||||
        "metadata": {
 | 
			
		||||
            "category": "domain object",
 | 
			
		||||
            "type": model.type,
 | 
			
		||||
            "owner": "admin",
 | 
			
		||||
            "name": model.name,
 | 
			
		||||
            "created": Date.now()
 | 
			
		||||
        },
 | 
			
		||||
        "model": model
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
@@ -1,65 +0,0 @@
 | 
			
		||||
import CouchDocument from "./CouchDocument";
 | 
			
		||||
 | 
			
		||||
const REV = "_rev";
 | 
			
		||||
const ID = "_id";
 | 
			
		||||
 | 
			
		||||
export default class CouchObjectProvider {
 | 
			
		||||
    constructor(openmct, url, namespace) {
 | 
			
		||||
        this.openmct = openmct;
 | 
			
		||||
        this.url = url;
 | 
			
		||||
        this.namespace = namespace;        this.namespace = namespace;        this.namespace = namespace;
 | 
			
		||||
        this.revs = {};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    request(subPath, method, value) {
 | 
			
		||||
        console.log(subPath, method, value);
 | 
			
		||||
        return fetch(this.url + '/' + subPath, {
 | 
			
		||||
            method: method,
 | 
			
		||||
            body: value
 | 
			
		||||
        }).then(response => response.json())
 | 
			
		||||
            .then(function (response) {
 | 
			
		||||
                return response;
 | 
			
		||||
            }, function () {
 | 
			
		||||
                return undefined;
 | 
			
		||||
            });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Check the response to a create/update/delete request;
 | 
			
		||||
    // track the rev if it's valid, otherwise return false to
 | 
			
		||||
    // indicate that the request failed.
 | 
			
		||||
    checkResponse(response) {
 | 
			
		||||
        if (response && response.ok) {
 | 
			
		||||
            this.revs[response.id] = response.rev;
 | 
			
		||||
            return response.ok;
 | 
			
		||||
        } else {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    getModel(response) {
 | 
			
		||||
        if (response && response.model) {
 | 
			
		||||
            let key = response[ID];
 | 
			
		||||
            this.revs[key] = response[REV];
 | 
			
		||||
            let object = response.model;
 | 
			
		||||
            object.identifier = {
 | 
			
		||||
                namespace: this.namespace,
 | 
			
		||||
                key: key
 | 
			
		||||
            };
 | 
			
		||||
            return object;
 | 
			
		||||
        } else {
 | 
			
		||||
            return undefined;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    get(identifier) {
 | 
			
		||||
        return this.request(identifier.key, "GET").then(this.getModel.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    create(model) {
 | 
			
		||||
        return this.request(model.identifier, "PUT", new CouchDocument(model.identifier.key, model)).then(this.checkResponse.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    update(model) {
 | 
			
		||||
        return this.request(model.identifier, "PUT", model).then(this.checkResponse.bind(this));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,8 +0,0 @@
 | 
			
		||||
import CouchObjectProvider from './CouchObjectProvider';
 | 
			
		||||
const NAMESPACE = '';
 | 
			
		||||
 | 
			
		||||
export default function CouchPlugin(config) {
 | 
			
		||||
    return function install(openmct) {
 | 
			
		||||
        openmct.objects.addProvider(NAMESPACE, new CouchObjectProvider(openmct, config, NAMESPACE));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,77 +0,0 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2020, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
import CouchPlugin from './plugin.js';
 | 
			
		||||
import {
 | 
			
		||||
    createOpenMct,
 | 
			
		||||
    resetApplicationState
 | 
			
		||||
} from 'utils/testing';
 | 
			
		||||
 | 
			
		||||
fdescribe("the plugin", () => {
 | 
			
		||||
    let openmct;
 | 
			
		||||
    let element;
 | 
			
		||||
    let child;
 | 
			
		||||
    let provider;
 | 
			
		||||
    let testSpace = "testSpace";
 | 
			
		||||
    let testPath = "/test/db";
 | 
			
		||||
    let mockDomainObject = { identifier: {namespace: '', key: "some-value"} };
 | 
			
		||||
 | 
			
		||||
    beforeEach((done) => {
 | 
			
		||||
        openmct = createOpenMct(false);
 | 
			
		||||
        openmct.install(new CouchPlugin(testSpace, testPath));
 | 
			
		||||
 | 
			
		||||
        element = document.createElement('div');
 | 
			
		||||
        child = document.createElement('div');
 | 
			
		||||
        element.appendChild(child);
 | 
			
		||||
 | 
			
		||||
        openmct.on('start', done);
 | 
			
		||||
        openmct.startHeadless();
 | 
			
		||||
 | 
			
		||||
        provider = openmct.objects.getProvider(mockDomainObject.identifier);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('registers a provider for objects', () => {
 | 
			
		||||
        expect(provider).toBeDefined();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('gets an object', () => {
 | 
			
		||||
        openmct.objects.get(mockDomainObject.identifier).then((result) => {
 | 
			
		||||
            expect(provider.get).toHaveBeenCalled();
 | 
			
		||||
            expect(result).toBeDefined();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('creates an object', () => {
 | 
			
		||||
        openmct.objects.save(mockDomainObject).then((result) => {
 | 
			
		||||
            expect(provider.create).toHaveBeenCalled();
 | 
			
		||||
            expect(result).toBeDefined();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('updates an object', () => {
 | 
			
		||||
        openmct.objects.save(mockDomainObject).then((result) => {
 | 
			
		||||
            openmct.objects.save(mockDomainObject).then((updatedResult) => {
 | 
			
		||||
                expect(provider.update).toHaveBeenCalled();
 | 
			
		||||
                expect(updatedResult).toBeDefined();
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -28,22 +28,17 @@
 | 
			
		||||
            ng-click="legend.set('expanded', !legend.get('expanded'));">
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <div class="c-plot-legend__wrapper"
 | 
			
		||||
            ng-class="{ 'is-cursor-locked':  !!lockHighlightPoint }">
 | 
			
		||||
        <div class="c-plot-legend__wrapper">
 | 
			
		||||
 | 
			
		||||
            <!-- COLLAPSED PLOT LEGEND -->
 | 
			
		||||
            <div class="plot-wrapper-collapsed-legend"
 | 
			
		||||
                 ng-class="{'is-cursor-locked': !!lockHighlightPoint }">
 | 
			
		||||
                <div class="c-state-indicator__alert-cursor-lock icon-cursor-lock" title="Cursor is point locked. Click anywhere in the plot to unlock."></div>
 | 
			
		||||
                 ng-class="{'icon-cursor-lock': !!lockHighlightPoint}">
 | 
			
		||||
                <div class="plot-legend-item"
 | 
			
		||||
                     ng-class="{'is-missing': series.domainObject.status === 'missing'}"
 | 
			
		||||
                     ng-repeat="series in series track by $index"
 | 
			
		||||
                >
 | 
			
		||||
                      ng-repeat="series in series track by $index">
 | 
			
		||||
                    <div class="plot-series-swatch-and-name">
 | 
			
		||||
                        <span class="plot-series-color-swatch "
 | 
			
		||||
                        <span class="plot-series-color-swatch"
 | 
			
		||||
                              ng-style="{ 'background-color': series.get('color').asHexString() }">
 | 
			
		||||
                        </span>
 | 
			
		||||
                        <span class="is-missing__indicator" title="This item is missing"></span>
 | 
			
		||||
                        <span class="plot-series-name">{{ series.get('name') }}</span>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="plot-series-value hover-value-enabled value-to-display-{{ legend.get('valueToShowWhenCollapsed') }} {{ series.closest.mctLimitState.cssClass }}"
 | 
			
		||||
@@ -60,10 +55,7 @@
 | 
			
		||||
            </div>
 | 
			
		||||
 | 
			
		||||
            <!-- EXPANDED PLOT LEGEND -->
 | 
			
		||||
            <div class="plot-wrapper-expanded-legend"
 | 
			
		||||
                 ng-class="{'is-cursor-locked': !!lockHighlightPoint }"
 | 
			
		||||
            >
 | 
			
		||||
                <div class="c-state-indicator__alert-cursor-lock--verbose icon-cursor-lock" title="Click anywhere in the plot to unlock."> Cursor locked to point</div>
 | 
			
		||||
            <div class="plot-wrapper-expanded-legend">
 | 
			
		||||
                <table>
 | 
			
		||||
                    <thead>
 | 
			
		||||
                        <tr>
 | 
			
		||||
@@ -84,15 +76,12 @@
 | 
			
		||||
                            </th>
 | 
			
		||||
                        </tr>
 | 
			
		||||
                    </thead>
 | 
			
		||||
                    <tr ng-repeat="series in series"
 | 
			
		||||
                        class="plot-legend-item"
 | 
			
		||||
                        ng-class="{'is-missing': series.domainObject.status === 'missing'}"
 | 
			
		||||
                    >
 | 
			
		||||
                        <td class="plot-series-swatch-and-name">
 | 
			
		||||
                    <tr ng-repeat="series in series" class="plot-legend-item">
 | 
			
		||||
                        <td class="plot-series-swatch-and-name"
 | 
			
		||||
                            ng-class="{'icon-cursor-lock': !!lockHighlightPoint}">
 | 
			
		||||
                            <span class="plot-series-color-swatch"
 | 
			
		||||
                                  ng-style="{ 'background-color': series.get('color').asHexString() }">
 | 
			
		||||
                            </span>
 | 
			
		||||
                            <span class="is-missing__indicator" title="This item is missing"></span>
 | 
			
		||||
                            <span class="plot-series-name">{{ series.get('name') }}</span>
 | 
			
		||||
                        </td>
 | 
			
		||||
 | 
			
		||||
@@ -145,7 +134,7 @@
 | 
			
		||||
                    {{option.name}}
 | 
			
		||||
                </option>
 | 
			
		||||
            </select>
 | 
			
		||||
 | 
			
		||||
            
 | 
			
		||||
 | 
			
		||||
            <mct-ticks axis="yAxis">
 | 
			
		||||
                <div ng-repeat="tick in ticks track by tick.value"
 | 
			
		||||
 
 | 
			
		||||
@@ -44,7 +44,7 @@
 | 
			
		||||
                </li>
 | 
			
		||||
                <li class="grid-row">
 | 
			
		||||
                    <div class="grid-cell label"
 | 
			
		||||
                         title="The rendering method to join lines for this series.">Line Method</div>
 | 
			
		||||
                         title="The line rendering style for this series.">Line Style</div>
 | 
			
		||||
                    <div class="grid-cell value">{{ {
 | 
			
		||||
                        'none': 'None',
 | 
			
		||||
                        'linear': 'Linear interpolation',
 | 
			
		||||
@@ -56,7 +56,7 @@
 | 
			
		||||
                    <div class="grid-cell label"
 | 
			
		||||
                         title="Whether markers are displayed, and their size.">Markers</div>
 | 
			
		||||
                    <div class="grid-cell value">
 | 
			
		||||
                        {{ series.markerOptionsDisplayText() }}
 | 
			
		||||
                        {{series.get('markers') ? "Enabled: " + series.get('markerSize') + "px" : "Disabled"}}
 | 
			
		||||
                    </div>
 | 
			
		||||
                </li>
 | 
			
		||||
                <li class="grid-row">
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@
 | 
			
		||||
                </li>
 | 
			
		||||
                <li class="grid-row">
 | 
			
		||||
                    <div class="grid-cell label"
 | 
			
		||||
                         title="The rendering method to join lines for this series.">Line Method</div>
 | 
			
		||||
                         title="The line rendering style for this series.">Line Style</div>
 | 
			
		||||
                    <div class="grid-cell value">
 | 
			
		||||
                        <select ng-model="form.interpolate">
 | 
			
		||||
                            <option value="none">None</option>
 | 
			
		||||
@@ -64,27 +64,12 @@
 | 
			
		||||
                <li class="grid-row">
 | 
			
		||||
                    <div class="grid-cell label"
 | 
			
		||||
                         title="Whether markers are displayed.">Markers</div>
 | 
			
		||||
                    <div class="grid-cell value">
 | 
			
		||||
                        <input type="checkbox" ng-model="form.markers"/>
 | 
			
		||||
                        <select
 | 
			
		||||
                            ng-show="form.markers"
 | 
			
		||||
                            ng-model="form.markerShape">
 | 
			
		||||
                            <option
 | 
			
		||||
                                ng-repeat="option in markerShapeOptions"
 | 
			
		||||
                                value="{{ option.value }}"
 | 
			
		||||
                                ng-selected="option.value == form.markerShape"
 | 
			
		||||
                            >
 | 
			
		||||
                                {{ option.name }}
 | 
			
		||||
                            </option>
 | 
			
		||||
                        </select>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="grid-cell value"><input type="checkbox" ng-model="form.markers"/></div>
 | 
			
		||||
                </li>
 | 
			
		||||
                <li class="grid-row">
 | 
			
		||||
                    <div class="grid-cell label"
 | 
			
		||||
                         title="Display markers visually denoting points in alarm.">Alarm Markers</div>
 | 
			
		||||
                    <div class="grid-cell value">
 | 
			
		||||
                        <input type="checkbox" ng-model="form.alarmMarkers"/>
 | 
			
		||||
                    </div>
 | 
			
		||||
                    <div class="grid-cell value"><input type="checkbox" ng-model="form.alarmMarkers"/></div>
 | 
			
		||||
                </li>
 | 
			
		||||
                <li class="grid-row" ng-show="form.markers || form.alarmMarkers">
 | 
			
		||||
                    <div class="grid-cell label"
 | 
			
		||||
 
 | 
			
		||||
@@ -371,8 +371,7 @@ function (
 | 
			
		||||
            chartElement.getBuffer(),
 | 
			
		||||
            chartElement.color().asRGBAArray(),
 | 
			
		||||
            chartElement.count,
 | 
			
		||||
            chartElement.series.get('markerSize'),
 | 
			
		||||
            chartElement.series.get('markerShape')
 | 
			
		||||
            chartElement.series.get('markerSize')
 | 
			
		||||
        );
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -396,10 +395,9 @@ function (
 | 
			
		||||
                this.offset.yVal(highlight.point, highlight.series)
 | 
			
		||||
            ]),
 | 
			
		||||
            color = highlight.series.get('color').asRGBAArray(),
 | 
			
		||||
            pointCount = 1,
 | 
			
		||||
            shape = highlight.series.get('markerShape');
 | 
			
		||||
            pointCount = 1;
 | 
			
		||||
 | 
			
		||||
        this.drawAPI.drawPoints(points, color, pointCount, HIGHLIGHT_SIZE, shape);
 | 
			
		||||
        this.drawAPI.drawPoints(points, color, pointCount, HIGHLIGHT_SIZE);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MCTChartController.prototype.drawRectangles = function () {
 | 
			
		||||
 
 | 
			
		||||
@@ -25,14 +25,12 @@ define([
 | 
			
		||||
    'lodash',
 | 
			
		||||
    '../configuration/Model',
 | 
			
		||||
    '../lib/extend',
 | 
			
		||||
    'EventEmitter',
 | 
			
		||||
    '../draw/MarkerShapes'
 | 
			
		||||
    'EventEmitter'
 | 
			
		||||
], function (
 | 
			
		||||
    _,
 | 
			
		||||
    Model,
 | 
			
		||||
    extend,
 | 
			
		||||
    EventEmitter,
 | 
			
		||||
    MARKER_SHAPES
 | 
			
		||||
    EventEmitter
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -58,7 +56,6 @@ define([
 | 
			
		||||
     *                `linear` (points are connected via straight lines), or
 | 
			
		||||
     *                `stepAfter` (points are connected by steps).
 | 
			
		||||
     * `markers`: boolean, whether or not this series should render with markers.
 | 
			
		||||
     * `markerShape`: string, shape of markers.
 | 
			
		||||
     * `markerSize`: number, size in pixels of markers for this series.
 | 
			
		||||
     * `alarmMarkers`: whether or not to display alarm markers for this series.
 | 
			
		||||
     * `stats`: An object that tracks the min and max y values observed in this
 | 
			
		||||
@@ -104,7 +101,6 @@ define([
 | 
			
		||||
                xKey: options.collection.plot.xAxis.get('key'),
 | 
			
		||||
                yKey: range.key,
 | 
			
		||||
                markers: true,
 | 
			
		||||
                markerShape: 'point',
 | 
			
		||||
                markerSize: 2.0,
 | 
			
		||||
                alarmMarkers: true
 | 
			
		||||
            };
 | 
			
		||||
@@ -414,18 +410,6 @@ define([
 | 
			
		||||
            } else {
 | 
			
		||||
                this.filters = deepCopiedFilters;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        markerOptionsDisplayText: function () {
 | 
			
		||||
            const showMarkers = this.get('markers');
 | 
			
		||||
            if (!showMarkers) {
 | 
			
		||||
                return "Disabled";
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            const markerShapeKey = this.get('markerShape');
 | 
			
		||||
            const markerShape = MARKER_SHAPES[markerShapeKey].label;
 | 
			
		||||
            const markerSize = this.get('markerSize');
 | 
			
		||||
 | 
			
		||||
            return `${markerShape}: ${markerSize}px`;
 | 
			
		||||
        }
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -23,12 +23,10 @@
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    'EventEmitter',
 | 
			
		||||
    '../lib/eventHelpers',
 | 
			
		||||
    './MarkerShapes'
 | 
			
		||||
    '../lib/eventHelpers'
 | 
			
		||||
], function (
 | 
			
		||||
    EventEmitter,
 | 
			
		||||
    eventHelpers,
 | 
			
		||||
    MARKER_SHAPES
 | 
			
		||||
    eventHelpers
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@@ -123,17 +121,18 @@ define([
 | 
			
		||||
        buf,
 | 
			
		||||
        color,
 | 
			
		||||
        points,
 | 
			
		||||
        pointSize,
 | 
			
		||||
        shape
 | 
			
		||||
        pointSize
 | 
			
		||||
    ) {
 | 
			
		||||
        const drawC2DShape = MARKER_SHAPES[shape].drawC2D.bind(this);
 | 
			
		||||
        var i = 0,
 | 
			
		||||
            offset = pointSize / 2;
 | 
			
		||||
 | 
			
		||||
        this.setColor(color);
 | 
			
		||||
 | 
			
		||||
        for (let i = 0; i < points; i++) {
 | 
			
		||||
            drawC2DShape(
 | 
			
		||||
                this.x(buf[i * 2]),
 | 
			
		||||
                this.y(buf[i * 2 + 1]),
 | 
			
		||||
        for (; i < points; i++) {
 | 
			
		||||
            this.c2d.fillRect(
 | 
			
		||||
                this.x(buf[i * 2]) - offset,
 | 
			
		||||
                this.y(buf[i * 2 + 1]) - offset,
 | 
			
		||||
                pointSize,
 | 
			
		||||
                pointSize
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -23,64 +23,30 @@
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    'EventEmitter',
 | 
			
		||||
    '../lib/eventHelpers',
 | 
			
		||||
    './MarkerShapes'
 | 
			
		||||
    '../lib/eventHelpers'
 | 
			
		||||
], function (
 | 
			
		||||
    EventEmitter,
 | 
			
		||||
    eventHelpers,
 | 
			
		||||
    MARKER_SHAPES
 | 
			
		||||
    eventHelpers
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
    // WebGL shader sources (for drawing plain colors)
 | 
			
		||||
    const FRAGMENT_SHADER = `
 | 
			
		||||
        precision mediump float;
 | 
			
		||||
        uniform vec4 uColor;
 | 
			
		||||
        uniform int uMarkerShape;
 | 
			
		||||
        
 | 
			
		||||
        void main(void) {
 | 
			
		||||
            gl_FragColor = uColor;
 | 
			
		||||
 | 
			
		||||
            if (uMarkerShape > 1) {
 | 
			
		||||
                vec2 clipSpacePointCoord = 2.0 * gl_PointCoord - 1.0;
 | 
			
		||||
 | 
			
		||||
                if (uMarkerShape == 2) { // circle
 | 
			
		||||
                    float distance = length(clipSpacePointCoord);
 | 
			
		||||
 | 
			
		||||
                    if (distance > 1.0) {
 | 
			
		||||
                        discard;
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (uMarkerShape == 3) { // diamond
 | 
			
		||||
                    float distance = abs(clipSpacePointCoord.x) + abs(clipSpacePointCoord.y);
 | 
			
		||||
 | 
			
		||||
                    if (distance > 1.0) {
 | 
			
		||||
                        discard;
 | 
			
		||||
                    }
 | 
			
		||||
                } else if (uMarkerShape == 4) { // triangle
 | 
			
		||||
                    float x = clipSpacePointCoord.x;
 | 
			
		||||
                    float y = clipSpacePointCoord.y;
 | 
			
		||||
                    float distance = 2.0 * x - 1.0;
 | 
			
		||||
                    float distance2 = -2.0 * x - 1.0;
 | 
			
		||||
 | 
			
		||||
                    if (distance > y || distance2 > y) {
 | 
			
		||||
                        discard;
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    `;
 | 
			
		||||
 | 
			
		||||
    const VERTEX_SHADER = `
 | 
			
		||||
        attribute vec2 aVertexPosition;
 | 
			
		||||
        uniform vec2 uDimensions;
 | 
			
		||||
        uniform vec2 uOrigin;
 | 
			
		||||
        uniform float uPointSize;
 | 
			
		||||
        
 | 
			
		||||
        void main(void) {
 | 
			
		||||
            gl_Position = vec4(2.0 * ((aVertexPosition - uOrigin) / uDimensions) - vec2(1,1), 0, 1);
 | 
			
		||||
            gl_PointSize = uPointSize;
 | 
			
		||||
        }
 | 
			
		||||
    `;
 | 
			
		||||
    var FRAGMENT_SHADER = [
 | 
			
		||||
            "precision mediump float;",
 | 
			
		||||
            "uniform vec4 uColor;",
 | 
			
		||||
            "void main(void) {",
 | 
			
		||||
            "gl_FragColor = uColor;",
 | 
			
		||||
            "}"
 | 
			
		||||
        ].join('\n'),
 | 
			
		||||
        VERTEX_SHADER = [
 | 
			
		||||
            "attribute vec2 aVertexPosition;",
 | 
			
		||||
            "uniform vec2 uDimensions;",
 | 
			
		||||
            "uniform vec2 uOrigin;",
 | 
			
		||||
            "uniform float uPointSize;",
 | 
			
		||||
            "void main(void) {",
 | 
			
		||||
            "gl_Position = vec4(2.0 * ((aVertexPosition - uOrigin) / uDimensions) - vec2(1,1), 0, 1);",
 | 
			
		||||
            "gl_PointSize = uPointSize;",
 | 
			
		||||
            "}"
 | 
			
		||||
        ].join('\n');
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Create a draw api utilizing WebGL.
 | 
			
		||||
@@ -124,7 +90,6 @@ define([
 | 
			
		||||
        this.vertexShader = this.gl.createShader(this.gl.VERTEX_SHADER);
 | 
			
		||||
        this.gl.shaderSource(this.vertexShader, VERTEX_SHADER);
 | 
			
		||||
        this.gl.compileShader(this.vertexShader);
 | 
			
		||||
 | 
			
		||||
        this.fragmentShader = this.gl.createShader(this.gl.FRAGMENT_SHADER);
 | 
			
		||||
        this.gl.shaderSource(this.fragmentShader, FRAGMENT_SHADER);
 | 
			
		||||
        this.gl.compileShader(this.fragmentShader);
 | 
			
		||||
@@ -140,7 +105,6 @@ define([
 | 
			
		||||
        // shader programs (to pass values into shaders at draw-time)
 | 
			
		||||
        this.aVertexPosition = this.gl.getAttribLocation(this.program, "aVertexPosition");
 | 
			
		||||
        this.uColor = this.gl.getUniformLocation(this.program, "uColor");
 | 
			
		||||
        this.uMarkerShape = this.gl.getUniformLocation(this.program, "uMarkerShape");
 | 
			
		||||
        this.uDimensions = this.gl.getUniformLocation(this.program, "uDimensions");
 | 
			
		||||
        this.uOrigin = this.gl.getUniformLocation(this.program, "uOrigin");
 | 
			
		||||
        this.uPointSize = this.gl.getUniformLocation(this.program, "uPointSize");
 | 
			
		||||
@@ -150,6 +114,9 @@ define([
 | 
			
		||||
        // Create a buffer to holds points which will be drawn
 | 
			
		||||
        this.buffer = this.gl.createBuffer();
 | 
			
		||||
 | 
			
		||||
        // Use a line width of 2.0 for legibility
 | 
			
		||||
        this.gl.lineWidth(2.0);
 | 
			
		||||
 | 
			
		||||
        // Enable blending, for smoothness
 | 
			
		||||
        this.gl.enable(this.gl.BLEND);
 | 
			
		||||
        this.gl.blendFunc(this.gl.SRC_ALPHA, this.gl.ONE_MINUS_SRC_ALPHA);
 | 
			
		||||
@@ -171,18 +138,14 @@ define([
 | 
			
		||||
            ((v - this.origin[1]) / this.dimensions[1]) * this.height;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    DrawWebGL.prototype.doDraw = function (drawType, buf, color, points, shape) {
 | 
			
		||||
    DrawWebGL.prototype.doDraw = function (drawType, buf, color, points) {
 | 
			
		||||
        if (this.isContextLost) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const shapeCode = MARKER_SHAPES[shape] ? MARKER_SHAPES[shape].drawWebGL : 0;
 | 
			
		||||
 | 
			
		||||
        this.gl.bindBuffer(this.gl.ARRAY_BUFFER, this.buffer);
 | 
			
		||||
        this.gl.bufferData(this.gl.ARRAY_BUFFER, buf, this.gl.DYNAMIC_DRAW);
 | 
			
		||||
        this.gl.vertexAttribPointer(this.aVertexPosition, 2, this.gl.FLOAT, false, 0, 0);
 | 
			
		||||
        this.gl.uniform4fv(this.uColor, color);
 | 
			
		||||
        this.gl.uniform1i(this.uMarkerShape, shapeCode)
 | 
			
		||||
        this.gl.drawArrays(drawType, 0, points);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -247,12 +210,12 @@ define([
 | 
			
		||||
     * Draw the buffer as points.
 | 
			
		||||
     *
 | 
			
		||||
     */
 | 
			
		||||
    DrawWebGL.prototype.drawPoints = function (buf, color, points, pointSize, shape) {
 | 
			
		||||
    DrawWebGL.prototype.drawPoints = function (buf, color, points, pointSize) {
 | 
			
		||||
        if (this.isContextLost) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        this.gl.uniform1f(this.uPointSize, pointSize);
 | 
			
		||||
        this.doDraw(this.gl.POINTS, buf, color, points, shape);
 | 
			
		||||
        this.doDraw(this.gl.POINTS, buf, color, points);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 
 | 
			
		||||
@@ -1,90 +0,0 @@
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2020, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
 * Administration. All rights reserved.
 | 
			
		||||
 *
 | 
			
		||||
 * Open MCT 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 includes source code licensed under additional open source
 | 
			
		||||
 * licenses. See the Open Source Licenses file (LICENSES.md) included with
 | 
			
		||||
 * this source code distribution or the Licensing information page available
 | 
			
		||||
 * at runtime from the About dialog for additional information.
 | 
			
		||||
 *****************************************************************************/
 | 
			
		||||
 | 
			
		||||
define([], function () {
 | 
			
		||||
    /**
 | 
			
		||||
     * @label string (required) display name of shape
 | 
			
		||||
     * @drawWebGL integer (unique, required) index provided to WebGL Fragment Shader
 | 
			
		||||
     * @drawC2D function (required) canvas2d draw function
 | 
			
		||||
     */
 | 
			
		||||
    const MARKER_SHAPES = {
 | 
			
		||||
        point: {
 | 
			
		||||
            label: 'Point',
 | 
			
		||||
            drawWebGL: 1,
 | 
			
		||||
            drawC2D: function (x, y, size) {
 | 
			
		||||
                const offset = size / 2;
 | 
			
		||||
 | 
			
		||||
                this.c2d.fillRect(x - offset, y - offset, size, size);
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        circle: {
 | 
			
		||||
            label: 'Circle',
 | 
			
		||||
            drawWebGL: 2,
 | 
			
		||||
            drawC2D: function (x, y, size) {
 | 
			
		||||
                const radius = size / 2;
 | 
			
		||||
 | 
			
		||||
                this.c2d.beginPath();
 | 
			
		||||
                this.c2d.arc(x, y, radius, 0, 2 * Math.PI, false);
 | 
			
		||||
                this.c2d.closePath();
 | 
			
		||||
                this.c2d.fill();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        diamond: {
 | 
			
		||||
            label: 'Diamond',
 | 
			
		||||
            drawWebGL: 3,
 | 
			
		||||
            drawC2D: function (x, y, size) {
 | 
			
		||||
                const offset = size / 2;
 | 
			
		||||
                const top = [x, y + offset];
 | 
			
		||||
                const right = [x + offset, y];
 | 
			
		||||
                const bottom = [x, y - offset];
 | 
			
		||||
                const left = [x - offset, y];
 | 
			
		||||
 | 
			
		||||
                this.c2d.beginPath();
 | 
			
		||||
                this.c2d.moveTo(...top);
 | 
			
		||||
                this.c2d.lineTo(...right);
 | 
			
		||||
                this.c2d.lineTo(...bottom);
 | 
			
		||||
                this.c2d.lineTo(...left);
 | 
			
		||||
                this.c2d.closePath();
 | 
			
		||||
                this.c2d.fill();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        triangle: {
 | 
			
		||||
            label: 'Triangle',
 | 
			
		||||
            drawWebGL: 4,
 | 
			
		||||
            drawC2D: function (x, y, size) {
 | 
			
		||||
                const offset = size / 2;
 | 
			
		||||
                const v1 = [x, y - offset];
 | 
			
		||||
                const v2 = [x - offset, y + offset];
 | 
			
		||||
                const v3 = [x + offset, y + offset];
 | 
			
		||||
 | 
			
		||||
                this.c2d.beginPath();
 | 
			
		||||
                this.c2d.moveTo(...v1);
 | 
			
		||||
                this.c2d.lineTo(...v2);
 | 
			
		||||
                this.c2d.lineTo(...v3);
 | 
			
		||||
                this.c2d.closePath();
 | 
			
		||||
                this.c2d.fill();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return MARKER_SHAPES;
 | 
			
		||||
});
 | 
			
		||||
@@ -22,11 +22,9 @@
 | 
			
		||||
 | 
			
		||||
define([
 | 
			
		||||
    './PlotModelFormController',
 | 
			
		||||
    '../draw/MarkerShapes',
 | 
			
		||||
    'lodash'
 | 
			
		||||
], function (
 | 
			
		||||
    PlotModelFormController,
 | 
			
		||||
    MARKER_SHAPES,
 | 
			
		||||
    _
 | 
			
		||||
) {
 | 
			
		||||
 | 
			
		||||
@@ -95,13 +93,6 @@ define([
 | 
			
		||||
                        value: o.key
 | 
			
		||||
                    };
 | 
			
		||||
                });
 | 
			
		||||
            this.$scope.markerShapeOptions = Object.entries(MARKER_SHAPES)
 | 
			
		||||
                .map(([key, obj]) => {
 | 
			
		||||
                    return {
 | 
			
		||||
                        name: obj.label,
 | 
			
		||||
                        value: key
 | 
			
		||||
                    };
 | 
			
		||||
                });
 | 
			
		||||
        },
 | 
			
		||||
 | 
			
		||||
        fields: [
 | 
			
		||||
@@ -117,10 +108,6 @@ define([
 | 
			
		||||
                modelProp: 'markers',
 | 
			
		||||
                objectPath: dynamicPathForKey('markers')
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                modelProp: 'markerShape',
 | 
			
		||||
                objectPath: dynamicPathForKey('markerShape')
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                modelProp: 'markerSize',
 | 
			
		||||
                coerce: Number,
 | 
			
		||||
 
 | 
			
		||||
@@ -71,6 +71,8 @@ define([
 | 
			
		||||
        this.listenTo(this.$canvas, 'mouseleave', this.untrackMousePosition, this);
 | 
			
		||||
        this.listenTo(this.$canvas, 'mousedown', this.onMouseDown, this);
 | 
			
		||||
        this.listenTo(this.$canvas, 'wheel', this.wheelZoom, this);
 | 
			
		||||
 | 
			
		||||
        this.watchForMarquee();
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MCTPlotController.prototype.initialize = function () {
 | 
			
		||||
@@ -81,6 +83,11 @@ define([
 | 
			
		||||
        this.listenTo(this.$canvas, 'mousedown', this.onMouseDown, this);
 | 
			
		||||
        this.listenTo(this.$canvas, 'wheel', this.wheelZoom, this);
 | 
			
		||||
 | 
			
		||||
        this.watchForMarquee();
 | 
			
		||||
 | 
			
		||||
        this.listenTo(this.$window, 'keydown', this.toggleInteractionMode, this);
 | 
			
		||||
        this.listenTo(this.$window, 'keyup', this.resetInteractionMode, this);
 | 
			
		||||
 | 
			
		||||
        this.$scope.rectangles = [];
 | 
			
		||||
        this.$scope.tickWidth = 0;
 | 
			
		||||
 | 
			
		||||
@@ -236,16 +243,12 @@ define([
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MCTPlotController.prototype.onMouseDown = function ($event) {
 | 
			
		||||
        // do not monitor drag events on browser context click
 | 
			
		||||
        if (event.ctrlKey) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.listenTo(this.$window, 'mouseup', this.onMouseUp, this);
 | 
			
		||||
        this.listenTo(this.$window, 'mousemove', this.trackMousePosition, this);
 | 
			
		||||
        if (event.altKey) {
 | 
			
		||||
        if (this.allowPan) {
 | 
			
		||||
            return this.startPan($event);
 | 
			
		||||
        } else {
 | 
			
		||||
        }
 | 
			
		||||
        if (this.allowMarquee) {
 | 
			
		||||
            return this.startMarquee($event);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
@@ -258,11 +261,11 @@ define([
 | 
			
		||||
            this.$scope.lockHighlightPoint = !this.$scope.lockHighlightPoint;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.pan) {
 | 
			
		||||
        if (this.allowPan) {
 | 
			
		||||
            return this.endPan($event);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (this.marquee) {
 | 
			
		||||
        if (this.allowMarquee) {
 | 
			
		||||
            return this.endMarquee($event);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
@@ -286,9 +289,6 @@ define([
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MCTPlotController.prototype.startMarquee = function ($event) {
 | 
			
		||||
        this.$canvas.removeClass('plot-drag');
 | 
			
		||||
        this.$canvas.addClass('plot-marquee');
 | 
			
		||||
 | 
			
		||||
        this.trackMousePosition($event);
 | 
			
		||||
        if (this.positionOverPlot) {
 | 
			
		||||
            this.freeze();
 | 
			
		||||
@@ -444,9 +444,6 @@ define([
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MCTPlotController.prototype.startPan = function ($event) {
 | 
			
		||||
        this.$canvas.addClass('plot-drag');
 | 
			
		||||
        this.$canvas.removeClass('plot-marquee');
 | 
			
		||||
 | 
			
		||||
        this.trackMousePosition($event);
 | 
			
		||||
        this.freeze();
 | 
			
		||||
        this.pan = {
 | 
			
		||||
@@ -489,6 +486,32 @@ define([
 | 
			
		||||
        this.$scope.$emit('user:viewport:change:end');
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MCTPlotController.prototype.watchForMarquee = function () {
 | 
			
		||||
        this.$canvas.removeClass('plot-drag');
 | 
			
		||||
        this.$canvas.addClass('plot-marquee');
 | 
			
		||||
        this.allowPan = false;
 | 
			
		||||
        this.allowMarquee = true;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MCTPlotController.prototype.watchForPan = function () {
 | 
			
		||||
        this.$canvas.addClass('plot-drag');
 | 
			
		||||
        this.$canvas.removeClass('plot-marquee');
 | 
			
		||||
        this.allowPan = true;
 | 
			
		||||
        this.allowMarquee = false;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MCTPlotController.prototype.toggleInteractionMode = function (event) {
 | 
			
		||||
        if (event.keyCode === 18) { // control key.
 | 
			
		||||
            this.watchForPan();
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MCTPlotController.prototype.resetInteractionMode = function (event) {
 | 
			
		||||
        if (event.keyCode === 18) {
 | 
			
		||||
            this.watchForMarquee();
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    MCTPlotController.prototype.freeze = function () {
 | 
			
		||||
        this.config.yAxis.set('frozen', true);
 | 
			
		||||
        this.config.xAxis.set('frozen', true);
 | 
			
		||||
 
 | 
			
		||||
@@ -54,8 +54,7 @@ define([
 | 
			
		||||
    './themes/snow',
 | 
			
		||||
    './URLTimeSettingsSynchronizer/plugin',
 | 
			
		||||
    './notificationIndicator/plugin',
 | 
			
		||||
    './newFolderAction/plugin',
 | 
			
		||||
    './persistence/couch/plugin'
 | 
			
		||||
    './newFolderAction/plugin'
 | 
			
		||||
], function (
 | 
			
		||||
    _,
 | 
			
		||||
    UTCTimeSystem,
 | 
			
		||||
@@ -90,12 +89,12 @@ define([
 | 
			
		||||
    Snow,
 | 
			
		||||
    URLTimeSettingsSynchronizer,
 | 
			
		||||
    NotificationIndicator,
 | 
			
		||||
    NewFolderAction,
 | 
			
		||||
    CouchDBPlugin
 | 
			
		||||
    NewFolderAction
 | 
			
		||||
) {
 | 
			
		||||
    var bundleMap = {
 | 
			
		||||
        LocalStorage: 'platform/persistence/local',
 | 
			
		||||
        MyItems: 'platform/features/my-items',
 | 
			
		||||
        CouchDB: 'platform/persistence/couch',
 | 
			
		||||
        Elasticsearch: 'platform/persistence/elastic'
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -127,7 +126,27 @@ define([
 | 
			
		||||
 | 
			
		||||
    plugins.Conductor = TimeConductorPlugin.default;
 | 
			
		||||
 | 
			
		||||
    plugins.CouchDB = CouchDBPlugin.default;
 | 
			
		||||
    plugins.CouchDB = function (url) {
 | 
			
		||||
        return function (openmct) {
 | 
			
		||||
            if (url) {
 | 
			
		||||
                var bundleName = "config/couch";
 | 
			
		||||
                openmct.legacyRegistry.register(bundleName, {
 | 
			
		||||
                    "extensions": {
 | 
			
		||||
                        "constants": [
 | 
			
		||||
                            {
 | 
			
		||||
                                "key": "COUCHDB_PATH",
 | 
			
		||||
                                "value": url,
 | 
			
		||||
                                "priority": "mandatory"
 | 
			
		||||
                            }
 | 
			
		||||
                        ]
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
                openmct.legacyRegistry.enable(bundleName);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            openmct.legacyRegistry.enable(bundleMap.CouchDB);
 | 
			
		||||
        };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    plugins.Elasticsearch = function (url) {
 | 
			
		||||
        return function (openmct) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										7
									
								
								src/plugins/tabs/README.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/plugins/tabs/README.md
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,7 @@
 | 
			
		||||
# Espresso Theme
 | 
			
		||||
A light colored theme for the Open MCT user interface.
 | 
			
		||||
 | 
			
		||||
## Installation
 | 
			
		||||
```js
 | 
			
		||||
openmct.install(openmct.plugins.Snow());
 | 
			
		||||
```
 | 
			
		||||
@@ -3,7 +3,7 @@
 | 
			
		||||
    <div
 | 
			
		||||
        class="c-tabs-view__tabs-holder c-tabs"
 | 
			
		||||
        :class="{
 | 
			
		||||
            'is-dragging': isDragging && allowEditing,
 | 
			
		||||
            'is-dragging': isDragging,
 | 
			
		||||
            'is-mouse-over': allowDrop
 | 
			
		||||
        }"
 | 
			
		||||
    >
 | 
			
		||||
@@ -22,24 +22,14 @@
 | 
			
		||||
        <button
 | 
			
		||||
            v-for="(tab,index) in tabsList"
 | 
			
		||||
            :key="index"
 | 
			
		||||
            class="c-tab c-tabs-view__tab"
 | 
			
		||||
            :class="{
 | 
			
		||||
                'is-current': isCurrent(tab)
 | 
			
		||||
            }"
 | 
			
		||||
            class="c-tabs-view__tab c-tab"
 | 
			
		||||
            :class="[
 | 
			
		||||
                {'is-current': isCurrent(tab)},
 | 
			
		||||
                tab.type.definition.cssClass
 | 
			
		||||
            ]"
 | 
			
		||||
            @click="showTab(tab, index)"
 | 
			
		||||
        >
 | 
			
		||||
            <div class="c-object-label"
 | 
			
		||||
                 :class="{'is-missing': tab.domainObject.status === 'missing'}"
 | 
			
		||||
            >
 | 
			
		||||
                <div class="c-object-label__type-icon"
 | 
			
		||||
                     :class="tab.type.definition.cssClass"
 | 
			
		||||
                >
 | 
			
		||||
                    <span class="is-missing__indicator"
 | 
			
		||||
                          title="This item is missing"
 | 
			
		||||
                    ></span>
 | 
			
		||||
                </div>
 | 
			
		||||
                <span class="c-button__label c-object-label__name">{{ tab.domainObject.name }}</span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <span class="c-button__label">{{ tab.domainObject.name }}</span>
 | 
			
		||||
        </button>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div
 | 
			
		||||
@@ -48,6 +38,15 @@
 | 
			
		||||
        class="c-tabs-view__object-holder"
 | 
			
		||||
        :class="{'c-tabs-view__object-holder--hidden': !isCurrent(tab)}"
 | 
			
		||||
    >
 | 
			
		||||
        <div
 | 
			
		||||
            v-if="currentTab"
 | 
			
		||||
            class="c-tabs-view__object-name c-object-label l-browse-bar__object-name--w"
 | 
			
		||||
            :class="currentTab.type.definition.cssClass"
 | 
			
		||||
        >
 | 
			
		||||
            <div class="l-browse-bar__object-name c-object-label__name">
 | 
			
		||||
                {{ currentTab.domainObject.name }}
 | 
			
		||||
            </div>
 | 
			
		||||
        </div>
 | 
			
		||||
        <object-view
 | 
			
		||||
            v-if="internalDomainObject.keep_alive ? currentTab : isCurrent(tab)"
 | 
			
		||||
            class="c-tabs-view__object"
 | 
			
		||||
@@ -59,12 +58,6 @@
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import ObjectView from '../../../ui/components/ObjectView.vue';
 | 
			
		||||
import {
 | 
			
		||||
    getSearchParam,
 | 
			
		||||
    setSearchParam,
 | 
			
		||||
    deleteSearchParam
 | 
			
		||||
} from 'utils/openmctLocation';
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
var unknownObjectType = {
 | 
			
		||||
    definition: {
 | 
			
		||||
@@ -78,45 +71,26 @@ export default {
 | 
			
		||||
    components: {
 | 
			
		||||
        ObjectView
 | 
			
		||||
    },
 | 
			
		||||
    props: {
 | 
			
		||||
        isEditing: {
 | 
			
		||||
            type: Boolean,
 | 
			
		||||
            required: true
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    data: function () {
 | 
			
		||||
        let keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
 | 
			
		||||
 | 
			
		||||
        return {
 | 
			
		||||
            internalDomainObject: this.domainObject,
 | 
			
		||||
            currentTab: {},
 | 
			
		||||
            currentTabIndex: undefined,
 | 
			
		||||
            tabsList: [],
 | 
			
		||||
            setCurrentTab: true,
 | 
			
		||||
            isDragging: false,
 | 
			
		||||
            allowDrop: false,
 | 
			
		||||
            searchTabKey: `tabs.pos.${keyString}`
 | 
			
		||||
            allowDrop: false
 | 
			
		||||
        };
 | 
			
		||||
    },
 | 
			
		||||
    computed: {
 | 
			
		||||
        allowEditing() {
 | 
			
		||||
            return !this.internalDomainObject.locked && this.isEditing;
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    mounted() {
 | 
			
		||||
        if (this.composition) {
 | 
			
		||||
            this.composition.on('add', this.addItem);
 | 
			
		||||
            this.composition.on('remove', this.removeItem);
 | 
			
		||||
            this.composition.on('reorder', this.onReorder);
 | 
			
		||||
            this.composition.load().then(() => {
 | 
			
		||||
                let currentTabIndexFromURL = getSearchParam(this.searchTabKey);
 | 
			
		||||
                let currentTabIndexFromDomainObject = this.internalDomainObject.currentTabIndex;
 | 
			
		||||
                let currentTabIndex = this.domainObject.currentTabIndex;
 | 
			
		||||
 | 
			
		||||
                if (currentTabIndexFromURL !== null) {
 | 
			
		||||
                    this.setCurrentTabByIndex(currentTabIndexFromURL);
 | 
			
		||||
                } else if (currentTabIndexFromDomainObject !== undefined) {
 | 
			
		||||
                    this.setCurrentTabByIndex(currentTabIndexFromDomainObject);
 | 
			
		||||
                    this.storeCurrentTabIndexInURL(currentTabIndexFromDomainObject);
 | 
			
		||||
                if (currentTabIndex !== undefined && this.tabsList.length > currentTabIndex) {
 | 
			
		||||
                    this.currentTab = this.tabsList[currentTabIndex];
 | 
			
		||||
                }
 | 
			
		||||
            });
 | 
			
		||||
        }
 | 
			
		||||
@@ -126,29 +100,20 @@ export default {
 | 
			
		||||
        document.addEventListener('dragstart', this.dragstart);
 | 
			
		||||
        document.addEventListener('dragend', this.dragend);
 | 
			
		||||
    },
 | 
			
		||||
    beforeDestroy() {
 | 
			
		||||
        this.persistCurrentTabIndex(this.currentTabIndex);
 | 
			
		||||
    },
 | 
			
		||||
    destroyed() {
 | 
			
		||||
        this.composition.off('add', this.addItem);
 | 
			
		||||
        this.composition.off('remove', this.removeItem);
 | 
			
		||||
        this.composition.off('reorder', this.onReorder);
 | 
			
		||||
 | 
			
		||||
        this.unsubscribe();
 | 
			
		||||
        this.clearCurrentTabIndexFromURL();
 | 
			
		||||
 | 
			
		||||
        document.removeEventListener('dragstart', this.dragstart);
 | 
			
		||||
        document.removeEventListener('dragend', this.dragend);
 | 
			
		||||
    },
 | 
			
		||||
    methods:{
 | 
			
		||||
        setCurrentTabByIndex(index) {
 | 
			
		||||
            if (this.tabsList[index]) {
 | 
			
		||||
                this.currentTab = this.tabsList[index];
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        showTab(tab, index) {
 | 
			
		||||
            if (index !== undefined) {
 | 
			
		||||
                this.storeCurrentTabIndexInURL(index);
 | 
			
		||||
                this.storeCurrentTabIndex(index);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            this.currentTab = tab;
 | 
			
		||||
@@ -168,10 +133,6 @@ export default {
 | 
			
		||||
                this.setCurrentTab = false;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        reset() {
 | 
			
		||||
            this.currentTab = {};
 | 
			
		||||
            this.setCurrentTab = true;
 | 
			
		||||
        },
 | 
			
		||||
        removeItem(identifier) {
 | 
			
		||||
            let pos = this.tabsList.findIndex(tab =>
 | 
			
		||||
                    tab.domainObject.identifier.namespace === identifier.namespace && tab.domainObject.identifier.key === identifier.key
 | 
			
		||||
@@ -183,10 +144,6 @@ export default {
 | 
			
		||||
            if (this.isCurrent(tabToBeRemoved)) {
 | 
			
		||||
                this.showTab(this.tabsList[this.tabsList.length - 1], this.tabsList.length - 1);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!this.tabsList.length) {
 | 
			
		||||
                this.reset();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        onReorder(reorderPlan) {
 | 
			
		||||
            let oldTabs = this.tabsList.slice();
 | 
			
		||||
@@ -197,7 +154,7 @@ export default {
 | 
			
		||||
        },
 | 
			
		||||
        onDrop(e) {
 | 
			
		||||
            this.setCurrentTab = true;
 | 
			
		||||
            this.storeCurrentTabIndexInURL(this.tabsList.length);
 | 
			
		||||
            this.storeCurrentTabIndex(this.tabsList.length);
 | 
			
		||||
        },
 | 
			
		||||
        dragstart(e) {
 | 
			
		||||
            if (e.dataTransfer.types.includes('openmct/domain-object-path')) {
 | 
			
		||||
@@ -220,19 +177,8 @@ export default {
 | 
			
		||||
        updateInternalDomainObject(domainObject) {
 | 
			
		||||
            this.internalDomainObject = domainObject;
 | 
			
		||||
        },
 | 
			
		||||
        persistCurrentTabIndex(index) {
 | 
			
		||||
        storeCurrentTabIndex(index) {
 | 
			
		||||
            this.openmct.objects.mutate(this.internalDomainObject, 'currentTabIndex', index);
 | 
			
		||||
        },
 | 
			
		||||
        storeCurrentTabIndexInURL(index) {
 | 
			
		||||
            let currentTabIndexInURL = getSearchParam(this.searchTabKey);
 | 
			
		||||
 | 
			
		||||
            if (index !== currentTabIndexInURL) {
 | 
			
		||||
                setSearchParam(this.searchTabKey, index);
 | 
			
		||||
                this.currentTabIndex = index;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        clearCurrentTabIndexFromURL() {
 | 
			
		||||
            deleteSearchParam(this.searchTabKey);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -42,28 +42,20 @@ define([
 | 
			
		||||
                let component;
 | 
			
		||||
 | 
			
		||||
                return {
 | 
			
		||||
                    show: function (element, editMode) {
 | 
			
		||||
                    show: function (element) {
 | 
			
		||||
                        component =  new Vue({
 | 
			
		||||
                            el: element,
 | 
			
		||||
                            components: {
 | 
			
		||||
                                TabsComponent: TabsComponent.default
 | 
			
		||||
                            },
 | 
			
		||||
                            data() {
 | 
			
		||||
                                return {
 | 
			
		||||
                                    isEditing: editMode
 | 
			
		||||
                                };
 | 
			
		||||
                            },
 | 
			
		||||
                            provide: {
 | 
			
		||||
                                openmct,
 | 
			
		||||
                                domainObject,
 | 
			
		||||
                                composition: openmct.composition.get(domainObject)
 | 
			
		||||
                            },
 | 
			
		||||
                            template: '<tabs-component :isEditing="isEditing"></tabs-component>'
 | 
			
		||||
                            template: '<tabs-component></tabs-component>'
 | 
			
		||||
                        });
 | 
			
		||||
                    },
 | 
			
		||||
                    onEditModeChange(editMode) {
 | 
			
		||||
                        component.isEditing = editMode;
 | 
			
		||||
                    },
 | 
			
		||||
                    destroy: function (element) {
 | 
			
		||||
                        component.$destroy();
 | 
			
		||||
                        component = undefined;
 | 
			
		||||
 
 | 
			
		||||
@@ -151,10 +151,6 @@ $browseFrameColor: pullForward($colorBodyBg, 10%);
 | 
			
		||||
$browseFrameBorder: 1px solid $browseFrameColor; // Frames in Disp and Flex Layouts when frame is showing
 | 
			
		||||
$browseSelectableShdwHov: rgba($colorBodyFg, 0.3) 0 0 3px;
 | 
			
		||||
$browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.4);
 | 
			
		||||
$filterItemHoverFg: brightness(1.2) contrast(1.1);
 | 
			
		||||
$filterItemMissing: brightness(0.6) grayscale(1);
 | 
			
		||||
$opacityMissing: 0.5;
 | 
			
		||||
$borderMissing: 1px dashed $colorAlert !important;
 | 
			
		||||
 | 
			
		||||
/************************************************** EDITING */
 | 
			
		||||
$editUIColor: $uiColor; // Base color
 | 
			
		||||
 
 | 
			
		||||
@@ -155,10 +155,6 @@ $browseFrameColor: pullForward($colorBodyBg, 10%);
 | 
			
		||||
$browseFrameBorder: 1px solid $browseFrameColor; // Frames in Disp and Flex Layouts when frame is showing
 | 
			
		||||
$browseSelectableShdwHov: rgba($colorBodyFg, 0.3) 0 0 3px;
 | 
			
		||||
$browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.4);
 | 
			
		||||
$filterItemHoverFg: brightness(1.2) contrast(1.1);
 | 
			
		||||
$filterItemMissing: contrast(0.2);
 | 
			
		||||
$opacityMissing: 0.5;
 | 
			
		||||
$borderMissing: 1px dashed $colorAlert !important;
 | 
			
		||||
 | 
			
		||||
/************************************************** EDITING */
 | 
			
		||||
$editUIColor: $uiColor; // Base color
 | 
			
		||||
 
 | 
			
		||||
@@ -151,10 +151,6 @@ $browseFrameColor: pullForward($colorBodyBg, 10%);
 | 
			
		||||
$browseFrameBorder: 1px solid $browseFrameColor; // Frames in Disp and Flex Layouts when frame is showing
 | 
			
		||||
$browseSelectableShdwHov: rgba($colorBodyFg, 0.3) 0 0 3px;
 | 
			
		||||
$browseSelectedBorder: 1px solid rgba($colorBodyFg, 0.4);
 | 
			
		||||
$filterItemHoverFg: brightness(0.9);
 | 
			
		||||
$filterItemMissing: contrast(0.2);
 | 
			
		||||
$opacityMissing: 0.4;
 | 
			
		||||
$borderMissing: 1px dashed $colorAlert !important;
 | 
			
		||||
 | 
			
		||||
/************************************************** EDITING */
 | 
			
		||||
$editUIColor: $uiColor; // Base color
 | 
			
		||||
 
 | 
			
		||||
@@ -61,7 +61,7 @@ $plotXBarH: 35px;
 | 
			
		||||
$plotLegendH: 20px;
 | 
			
		||||
$plotLegendWidthCollapsed: 20%;
 | 
			
		||||
$plotLegendWidthExpanded: 50%;
 | 
			
		||||
$plotSwatchD: 12px;
 | 
			
		||||
$plotSwatchD: 10px;
 | 
			
		||||
$plotDisplayArea: (0, 0, $plotXBarH, $plotYBarW); // 1: Top, 2: right, 3: bottom, 4: left
 | 
			
		||||
$plotMinH: 95px;
 | 
			
		||||
$controlBarH: 25px;
 | 
			
		||||
 
 | 
			
		||||
@@ -411,17 +411,7 @@ select {
 | 
			
		||||
 | 
			
		||||
.c-tab {
 | 
			
		||||
    // Used in Tab View, generic tabs
 | 
			
		||||
    $notchSize: 7px;
 | 
			
		||||
    $clipPath:
 | 
			
		||||
        polygon(
 | 
			
		||||
            0% 0%,
 | 
			
		||||
            calc(100% - #{$notchSize}) 0%,
 | 
			
		||||
            100% #{$notchSize},
 | 
			
		||||
            100% calc(100% - #{$notchSize}),
 | 
			
		||||
            100% 100%,
 | 
			
		||||
            0% 100%
 | 
			
		||||
        );
 | 
			
		||||
    background: rgba($colorBtnBg, 0.7);
 | 
			
		||||
    background: $colorBtnBg;
 | 
			
		||||
    color: $colorBtnFg;
 | 
			
		||||
    cursor: pointer;
 | 
			
		||||
    display: flex;
 | 
			
		||||
@@ -430,15 +420,21 @@ select {
 | 
			
		||||
    margin: 1px 1px 0 0;
 | 
			
		||||
    padding: $interiorMargin $interiorMarginLg;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
    clip-path: $clipPath;
 | 
			
		||||
    -webkit-clip-path: $clipPath; // Safari
 | 
			
		||||
 | 
			
		||||
    > * + * {
 | 
			
		||||
        margin-left: $interiorMargin;
 | 
			
		||||
    }
 | 
			
		||||
    --notchSize: 7px;
 | 
			
		||||
 | 
			
		||||
    clip-path:
 | 
			
		||||
        polygon(
 | 
			
		||||
            0% 0%,
 | 
			
		||||
            calc(100% - var(--notchSize)) 0%,
 | 
			
		||||
            100% var(--notchSize),
 | 
			
		||||
            100% calc(100% - var(--notchSize)),
 | 
			
		||||
            100% 100%,
 | 
			
		||||
            0% 100%
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    @include hover() {
 | 
			
		||||
        filter: $filterHov;
 | 
			
		||||
        background: $colorBtnBgHov;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.is-current {
 | 
			
		||||
 
 | 
			
		||||
@@ -43,9 +43,7 @@ mct-plot {
 | 
			
		||||
 | 
			
		||||
.c-plot,
 | 
			
		||||
.gl-plot {
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
 | 
			
		||||
        .s-status-taking-snapshot & {
 | 
			
		||||
    .s-status-taking-snapshot & {
 | 
			
		||||
        .c-control-bar {
 | 
			
		||||
            display: none;
 | 
			
		||||
        }
 | 
			
		||||
@@ -53,17 +51,6 @@ mct-plot {
 | 
			
		||||
            display: none;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*********************** MISSING ITEM INDICATORS */
 | 
			
		||||
    .is-missing__indicator {
 | 
			
		||||
        display: none;
 | 
			
		||||
    }
 | 
			
		||||
    .is-missing {
 | 
			
		||||
        @include isMissing();
 | 
			
		||||
        .is-missing__indicator {
 | 
			
		||||
            font-size: 0.8em;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.c-plot {
 | 
			
		||||
@@ -87,7 +74,6 @@ mct-plot {
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex: 1 1 auto;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
        overflow: hidden;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &--stacked {
 | 
			
		||||
@@ -116,15 +102,18 @@ mct-plot {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
.gl-plot {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex: 1 1 auto;
 | 
			
		||||
    position: relative;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    min-height: $plotMinH;
 | 
			
		||||
 | 
			
		||||
    /*********************** AXIS AND DISPLAY AREA */
 | 
			
		||||
    .plot-wrapper-axis-and-display-area {
 | 
			
		||||
        position: relative;
 | 
			
		||||
        flex: 1 1 auto;
 | 
			
		||||
        min-height: $plotMinH;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .gl-plot-wrapper-display-area-and-x-axis {
 | 
			
		||||
@@ -207,6 +196,7 @@ mct-plot {
 | 
			
		||||
            left: 0; top: 0; right: auto; bottom: 0;
 | 
			
		||||
            padding-left: 5px;
 | 
			
		||||
            text-orientation: mixed;
 | 
			
		||||
            //overflow: hidden;
 | 
			
		||||
            writing-mode: vertical-lr;
 | 
			
		||||
            &:before {
 | 
			
		||||
                // Icon denoting configurability
 | 
			
		||||
@@ -378,6 +368,12 @@ mct-plot {
 | 
			
		||||
    z-index: -10;
 | 
			
		||||
 | 
			
		||||
    .l-view-section {
 | 
			
		||||
        //$m: $interiorMargin;
 | 
			
		||||
        //top: $m !important;
 | 
			
		||||
        //right: $m;
 | 
			
		||||
        //bottom: $m;
 | 
			
		||||
        //left: $m;
 | 
			
		||||
 | 
			
		||||
        .s-status-timeconductor-unsynced .holder-plot {
 | 
			
		||||
            .t-object-alert.t-alert-unsynced {
 | 
			
		||||
                display: none;
 | 
			
		||||
@@ -433,18 +429,14 @@ mct-plot {
 | 
			
		||||
/****************** _LEGEND.SCSS */
 | 
			
		||||
.gl-plot-legend,
 | 
			
		||||
.c-plot-legend {
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
 | 
			
		||||
    &__wrapper {
 | 
			
		||||
        // Holds view-control and both collapsed and expanded legends
 | 
			
		||||
        flex: 1 1 auto;
 | 
			
		||||
        height: 100%;
 | 
			
		||||
        overflow: auto;
 | 
			
		||||
        padding: 2px;
 | 
			
		||||
        overflow: auto; // Prevents collapsed legend from forcing scrollbars on higher parent containers
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__view-control {
 | 
			
		||||
        padding-top: 4px;
 | 
			
		||||
        padding-top: 2px;
 | 
			
		||||
        margin-right: $interiorMarginSm;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -489,21 +481,15 @@ mct-plot {
 | 
			
		||||
/***************** GENERAL STYLES, ALL STATES */
 | 
			
		||||
.plot-legend-item {
 | 
			
		||||
    // General styles for legend items, both expanded and collapsed legend states
 | 
			
		||||
    > * + * {
 | 
			
		||||
        margin-left: $interiorMarginSm;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .plot-series-color-swatch {
 | 
			
		||||
        border-radius: 30%; //$smallCr;
 | 
			
		||||
        border-radius: $smallCr;
 | 
			
		||||
        border: 1px solid $colorBodyBg;
 | 
			
		||||
        display: inline-block;
 | 
			
		||||
        flex: 0 0 auto;
 | 
			
		||||
        height: $plotSwatchD;
 | 
			
		||||
        width: $plotSwatchD;
 | 
			
		||||
    }
 | 
			
		||||
    .plot-series-name {
 | 
			
		||||
        display: inline;
 | 
			
		||||
        @include ellipsize();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .plot-series-value {
 | 
			
		||||
@@ -511,16 +497,6 @@ mct-plot {
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.plot-series-swatch-and-name {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex: 0 1 auto;
 | 
			
		||||
    align-items: center;
 | 
			
		||||
 | 
			
		||||
    > * + * {
 | 
			
		||||
        margin-left: $interiorMarginSm;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.plot-wrapper-expanded-legend {
 | 
			
		||||
    flex: 1 1 auto;
 | 
			
		||||
}
 | 
			
		||||
@@ -529,6 +505,9 @@ mct-plot {
 | 
			
		||||
    &.plot-legend-collapsed .plot-wrapper-expanded-legend { display: none; }
 | 
			
		||||
    &.plot-legend-expanded .plot-wrapper-collapsed-legend { display: none; }
 | 
			
		||||
 | 
			
		||||
    &.plot-legend-collapsed .icon-cursor-lock::before { padding-right: 5px; }
 | 
			
		||||
    &.plot-legend-expanded .icon-cursor-lock::before { padding-right: 5px; }
 | 
			
		||||
 | 
			
		||||
    &.plot-legend-top .gl-plot-legend { margin-bottom: $interiorMargin; }
 | 
			
		||||
    &.plot-legend-bottom .gl-plot-legend { margin-top: $interiorMargin; }
 | 
			
		||||
    &.plot-legend-right .gl-plot-legend { margin-left: $interiorMargin; }
 | 
			
		||||
@@ -542,13 +521,19 @@ mct-plot {
 | 
			
		||||
            display: flex;
 | 
			
		||||
            align-items: center;
 | 
			
		||||
            justify-content: stretch;
 | 
			
		||||
 | 
			
		||||
            &:not(:first-child) {
 | 
			
		||||
                margin-left: $interiorMarginLg;
 | 
			
		||||
            }
 | 
			
		||||
            .plot-series-swatch-and-name,
 | 
			
		||||
            .plot-series-value {
 | 
			
		||||
                @include ellipsize();
 | 
			
		||||
                flex: 1 1 auto;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .plot-series-swatch-and-name {
 | 
			
		||||
                margin-right: $interiorMarginSm;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            .plot-series-value {
 | 
			
		||||
                text-align: left;
 | 
			
		||||
            }
 | 
			
		||||
@@ -558,7 +543,7 @@ mct-plot {
 | 
			
		||||
    /***************** GENERAL STYLES, EXPANDED */
 | 
			
		||||
    &.plot-legend-expanded {
 | 
			
		||||
        .gl-plot-legend {
 | 
			
		||||
             max-height: 70%;
 | 
			
		||||
            // max-height: 70%;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .plot-wrapper-expanded-legend {
 | 
			
		||||
@@ -579,11 +564,6 @@ mct-plot {
 | 
			
		||||
                display: flex;
 | 
			
		||||
                flex: 1 1 auto;
 | 
			
		||||
                overflow: hidden;
 | 
			
		||||
 | 
			
		||||
                > .plot-legend-item + .plot-legend-item {
 | 
			
		||||
                    // Space between plot items
 | 
			
		||||
                    margin-left: $interiorMarginLg;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@@ -615,17 +595,12 @@ mct-plot {
 | 
			
		||||
                min-width: 0;
 | 
			
		||||
                flex: 1 1 auto;
 | 
			
		||||
                overflow-y: auto;
 | 
			
		||||
 | 
			
		||||
                > * + * {
 | 
			
		||||
                    // Space between plot items
 | 
			
		||||
                    margin-top: $interiorMarginSm;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            .plot-legend-item {
 | 
			
		||||
                margin-bottom: 1px;
 | 
			
		||||
                margin-left: 0;
 | 
			
		||||
                flex-wrap: nowrap;
 | 
			
		||||
                flex-wrap: wrap;
 | 
			
		||||
                .plot-series-swatch-and-name {
 | 
			
		||||
                    @include ellipsize();
 | 
			
		||||
                    flex: 0 1 auto;
 | 
			
		||||
                    min-width: 20%;
 | 
			
		||||
                }
 | 
			
		||||
@@ -679,24 +654,3 @@ mct-plot {
 | 
			
		||||
        display: inline-block !important;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*********************** CURSOR LOCK INDICATOR */
 | 
			
		||||
[class*='c-state-indicator__alert-cursor-lock'] {
 | 
			
		||||
    display: none;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
[class*='is-cursor-locked'] {
 | 
			
		||||
    background: rgba($colorInfo, 0.1);
 | 
			
		||||
 | 
			
		||||
    [class*='c-state-indicator__alert-cursor-lock'] {
 | 
			
		||||
        @include userSelectNone();
 | 
			
		||||
        color: $colorInfo;
 | 
			
		||||
        display: block;
 | 
			
		||||
        margin-right: $interiorMarginSm;
 | 
			
		||||
 | 
			
		||||
        &[class*='--verbose'] {
 | 
			
		||||
            padding: $interiorMarginSm;
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -117,33 +117,6 @@
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin isMissing($absPos: false) {
 | 
			
		||||
    // Common styles to be applied to tree items, object labels, grid and list item views
 | 
			
		||||
    //opacity: 0.7;
 | 
			
		||||
    //pointer-events: none; // Don't think we can do this, as disables title hover on icon element
 | 
			
		||||
 | 
			
		||||
    .is-missing__indicator {
 | 
			
		||||
        display: none ;
 | 
			
		||||
        text-shadow: $colorBodyBg 0 0 2px;
 | 
			
		||||
        color: $colorAlert;
 | 
			
		||||
        font-family: symbolsfont;
 | 
			
		||||
 | 
			
		||||
        &:before {
 | 
			
		||||
            content: $glyph-icon-alert-triangle;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @if $absPos {
 | 
			
		||||
        .is-missing__indicator {
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            z-index: 3;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.is-missing .is-missing__indicator,
 | 
			
		||||
    .is-missing .is-missing__indicator { display: block !important; }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@mixin bgDiagonalStripes($c: yellow, $a: 0.1, $d: 40px) {
 | 
			
		||||
    background-image: linear-gradient(-45deg,
 | 
			
		||||
        rgba($c, $a) 25%, transparent 25%,
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,8 @@ table {
 | 
			
		||||
    td {
 | 
			
		||||
        vertical-align: top;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    a { color: $colorBtnMajorBg; }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.is-editing {
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@
 | 
			
		||||
@import "../plugins/filters/components/filters-view.scss";
 | 
			
		||||
@import "../plugins/filters/components/global-filters.scss";
 | 
			
		||||
@import "../plugins/flexibleLayout/components/flexible-layout.scss";
 | 
			
		||||
@import "../plugins/folderView/components/grid-item.scss";
 | 
			
		||||
@import "../plugins/folderView/components/grid-view.scss";
 | 
			
		||||
@import "../plugins/folderView/components/list-item.scss";
 | 
			
		||||
@import "../plugins/folderView/components/list-view.scss";
 | 
			
		||||
 
 | 
			
		||||
@@ -24,24 +24,13 @@
 | 
			
		||||
    class="c-so-view has-local-controls"
 | 
			
		||||
    :class="{
 | 
			
		||||
        'c-so-view--no-frame': !hasFrame,
 | 
			
		||||
        'has-complex-content': complexContent,
 | 
			
		||||
        'is-missing': domainObject.status === 'missing'
 | 
			
		||||
        'has-complex-content': complexContent
 | 
			
		||||
    }"
 | 
			
		||||
>
 | 
			
		||||
    <div class="c-so-view__header">
 | 
			
		||||
        <div class="c-object-label"
 | 
			
		||||
             :class="{
 | 
			
		||||
                 classList,
 | 
			
		||||
                 'is-missing': domainObject.status === 'missing'
 | 
			
		||||
             }"
 | 
			
		||||
             :class="[cssClass, classList]"
 | 
			
		||||
        >
 | 
			
		||||
            <div class="c-object-label__type-icon"
 | 
			
		||||
                 :class="cssClass"
 | 
			
		||||
            >
 | 
			
		||||
                <span class="is-missing__indicator"
 | 
			
		||||
                      title="This item is missing"
 | 
			
		||||
                ></span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="c-object-label__name">
 | 
			
		||||
                {{ domainObject && domainObject.name }}
 | 
			
		||||
            </div>
 | 
			
		||||
@@ -57,9 +46,6 @@
 | 
			
		||||
            @click="expand"
 | 
			
		||||
        ></button>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="is-missing__indicator"
 | 
			
		||||
         title="This item is missing"
 | 
			
		||||
    ></div>
 | 
			
		||||
    <object-view
 | 
			
		||||
        ref="objectView"
 | 
			
		||||
        class="c-so-view__object-view"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,10 +1,7 @@
 | 
			
		||||
<template>
 | 
			
		||||
<a
 | 
			
		||||
    class="c-tree__item__label c-object-label"
 | 
			
		||||
    :class="{
 | 
			
		||||
        classList,
 | 
			
		||||
        'is-missing': observedObject.status === 'missing'
 | 
			
		||||
    }"
 | 
			
		||||
    :class="classList"
 | 
			
		||||
    draggable="true"
 | 
			
		||||
    :href="objectLink"
 | 
			
		||||
    @dragstart="dragStart"
 | 
			
		||||
@@ -13,14 +10,8 @@
 | 
			
		||||
    <div
 | 
			
		||||
        class="c-tree__item__type-icon c-object-label__type-icon"
 | 
			
		||||
        :class="typeClass"
 | 
			
		||||
    >
 | 
			
		||||
        <span class="is-missing__indicator"
 | 
			
		||||
              title="This item is missing"
 | 
			
		||||
        ></span>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div class="c-tree__item__name c-object-label__name">
 | 
			
		||||
        {{ observedObject.name }}
 | 
			
		||||
    </div>
 | 
			
		||||
    ></div>
 | 
			
		||||
    <div class="c-tree__item__name c-object-label__name">{{ observedObject.name }}</div>
 | 
			
		||||
</a>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -53,9 +53,7 @@ export default {
 | 
			
		||||
    mounted() {
 | 
			
		||||
        this.currentObject = this.object;
 | 
			
		||||
        this.updateView();
 | 
			
		||||
        this.$el.addEventListener('dragover', this.onDragOver, {
 | 
			
		||||
            capture: true
 | 
			
		||||
        });
 | 
			
		||||
        this.$el.addEventListener('dragover', this.onDragOver);
 | 
			
		||||
        this.$el.addEventListener('drop', this.editIfEditable, {
 | 
			
		||||
            capture: true
 | 
			
		||||
        });
 | 
			
		||||
@@ -271,7 +269,6 @@ export default {
 | 
			
		||||
            if (provider &&
 | 
			
		||||
                provider.canEdit &&
 | 
			
		||||
                provider.canEdit(this.currentObject) &&
 | 
			
		||||
                this.isEditingAllowed() &&
 | 
			
		||||
                !this.openmct.editor.isEditing()) {
 | 
			
		||||
                this.openmct.editor.edit();
 | 
			
		||||
            }
 | 
			
		||||
@@ -304,7 +301,7 @@ export default {
 | 
			
		||||
                objectPath= this.currentObjectPath || this.objectPath,
 | 
			
		||||
                parentObject = objectPath[1];
 | 
			
		||||
 | 
			
		||||
            return [browseObject, parentObject, this.currentObject].every(object => object && !object.locked);
 | 
			
		||||
            return [browseObject, parentObject, this.currentObject].every(object => !object.locked);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -2,10 +2,6 @@
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
 | 
			
		||||
    &.is-missing {
 | 
			
		||||
        border: $borderMissing;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /*************************** HEADER */
 | 
			
		||||
    &__header {
 | 
			
		||||
        flex: 0 0 auto;
 | 
			
		||||
@@ -43,15 +39,6 @@
 | 
			
		||||
        > .c-so-view__local-controls {
 | 
			
		||||
            top: $interiorMarginSm; right: $interiorMarginSm;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &.is-missing {
 | 
			
		||||
            @include isMissing($absPos: true);
 | 
			
		||||
 | 
			
		||||
            .is-missing__indicator {
 | 
			
		||||
                top: $interiorMargin;
 | 
			
		||||
                left: $interiorMargin;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__local-controls {
 | 
			
		||||
@@ -74,9 +61,11 @@
 | 
			
		||||
        height: 0; // Chrome 73 overflow bug fix
 | 
			
		||||
        overflow: auto;
 | 
			
		||||
 | 
			
		||||
        .u-fills-container {
 | 
			
		||||
            // Expand component types that fill a container
 | 
			
		||||
            @include abs();
 | 
			
		||||
        .u-angular-object-view-wrapper {
 | 
			
		||||
            .u-fills-container {
 | 
			
		||||
                // Expand component types that fill a container
 | 
			
		||||
                @include abs();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -89,5 +78,8 @@
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.u-angular-object-view-wrapper {
 | 
			
		||||
    display: contents;
 | 
			
		||||
    flex: 1 1 auto;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -7,33 +7,19 @@
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
    white-space: nowrap;
 | 
			
		||||
 | 
			
		||||
    > * + * { margin-left: $interiorMargin; }
 | 
			
		||||
 | 
			
		||||
    &__name {
 | 
			
		||||
        @include ellipsize();
 | 
			
		||||
        display: inline;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__type-icon {
 | 
			
		||||
    &__type-icon,
 | 
			
		||||
    &:before {
 | 
			
		||||
        // Type icon. Must be an HTML entity to allow inclusion of alias indicator.
 | 
			
		||||
        display: block;
 | 
			
		||||
        flex: 0 0 auto;
 | 
			
		||||
        font-size: 1.1em;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.is-missing {
 | 
			
		||||
        @include isMissing($absPos: true);
 | 
			
		||||
 | 
			
		||||
        [class*='__type-icon']:before,
 | 
			
		||||
        [class*='__type-icon']:after{
 | 
			
		||||
            opacity: $opacityMissing;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        .is-missing__indicator {
 | 
			
		||||
            right: -3px;
 | 
			
		||||
            top: -3px;
 | 
			
		||||
            transform: scale(0.7);
 | 
			
		||||
        }
 | 
			
		||||
        opacity: 0.6;
 | 
			
		||||
        margin-right: $interiorMargin;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -41,8 +27,6 @@
 | 
			
		||||
    border-radius: $controlCr;
 | 
			
		||||
    padding: $interiorMarginSm 1px;
 | 
			
		||||
 | 
			
		||||
    > * + * { margin-left: $interiorMarginSm; }
 | 
			
		||||
 | 
			
		||||
    &__name {
 | 
			
		||||
        display: inline;
 | 
			
		||||
        width: 100%;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,24 +1,16 @@
 | 
			
		||||
<template>
 | 
			
		||||
<div class="c-inspector__header">
 | 
			
		||||
    <div v-if="!multiSelect"
 | 
			
		||||
    <div v-if="!multiSelect && !singleSelectNonObject"
 | 
			
		||||
         class="c-inspector__selected-w c-object-label"
 | 
			
		||||
         :class="{'is-missing': domainObject.status === 'missing' }"
 | 
			
		||||
         :class="typeCssClass"
 | 
			
		||||
    >
 | 
			
		||||
        <div class="c-object-label__type-icon"
 | 
			
		||||
             :class="typeCssClass"
 | 
			
		||||
        >
 | 
			
		||||
            <span class="is-missing__indicator"
 | 
			
		||||
                  title="This item is missing"
 | 
			
		||||
            ></span>
 | 
			
		||||
        </div>
 | 
			
		||||
 | 
			
		||||
        <span v-if="!singleSelectNonObject"
 | 
			
		||||
              class="c-inspector__selected c-object-label__name"
 | 
			
		||||
        >{{ item.name }}</span>
 | 
			
		||||
        <span v-if="singleSelectNonObject"
 | 
			
		||||
              class="c-inspector__selected  c-object-label__name c-inspector__selected--non-domain-object"
 | 
			
		||||
        >Layout Object</span>
 | 
			
		||||
 | 
			
		||||
        <span class="c-inspector__selected c-object-label__name">{{ item.name }}</span>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-if="singleSelectNonObject"
 | 
			
		||||
         class="c-inspector__selected-w  c-object-label"
 | 
			
		||||
         :class="typeCssClass"
 | 
			
		||||
    >
 | 
			
		||||
        <span class="c-inspector__selected  c-object-label__name c-inspector__selected--non-domain-object">Layout Object</span>
 | 
			
		||||
    </div>
 | 
			
		||||
    <div v-if="multiSelect"
 | 
			
		||||
         class="c-inspector__multiple-selected-w"
 | 
			
		||||
 
 | 
			
		||||
@@ -4,7 +4,7 @@
 | 
			
		||||
    flex-direction: column;
 | 
			
		||||
 | 
			
		||||
    > * {
 | 
			
		||||
        // This is on purpose: want extra margin on top object-name element
 | 
			
		||||
        // Thi is on purpose: want extra margin on top object-name element
 | 
			
		||||
        margin-top: $interiorMargin;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -41,8 +41,6 @@
 | 
			
		||||
 | 
			
		||||
    &__content {
 | 
			
		||||
        flex: 1 1 auto;
 | 
			
		||||
        display: flex;
 | 
			
		||||
        flex-direction: column;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &__elements {
 | 
			
		||||
 
 | 
			
		||||
@@ -8,18 +8,8 @@
 | 
			
		||||
        ></button>
 | 
			
		||||
        <div
 | 
			
		||||
            class="l-browse-bar__object-name--w c-object-label"
 | 
			
		||||
            :class="{
 | 
			
		||||
                classList,
 | 
			
		||||
                'is-missing': domainObject.status === 'missing'
 | 
			
		||||
            }"
 | 
			
		||||
            :class="[ type.cssClass, classList ]"
 | 
			
		||||
        >
 | 
			
		||||
            <div class="c-object-label__type-icon"
 | 
			
		||||
                 :class="type.cssClass"
 | 
			
		||||
            >
 | 
			
		||||
                <span class="is-missing__indicator"
 | 
			
		||||
                      title="This item is missing"
 | 
			
		||||
                ></span>
 | 
			
		||||
            </div>
 | 
			
		||||
            <span
 | 
			
		||||
                class="l-browse-bar__object-name c-object-label__name c-input-inline"
 | 
			
		||||
                contenteditable
 | 
			
		||||
 
 | 
			
		||||
@@ -354,9 +354,9 @@
 | 
			
		||||
        @include headerFont(1.4em);
 | 
			
		||||
        min-width: 0;
 | 
			
		||||
 | 
			
		||||
        .is-missing__indicator {
 | 
			
		||||
            right: -5px !important;
 | 
			
		||||
            top: -4px !important;
 | 
			
		||||
        &:before {
 | 
			
		||||
            // Icon
 | 
			
		||||
            margin-right: $interiorMargin;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -52,13 +52,12 @@
 | 
			
		||||
        padding: $interiorMarginSm $interiorMargin;
 | 
			
		||||
        transition: background 150ms ease;
 | 
			
		||||
 | 
			
		||||
        &__type-icon {
 | 
			
		||||
            color: $colorItemTreeIcon;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
            background: $colorItemTreeHoverBg;
 | 
			
		||||
            filter: $filterHov;
 | 
			
		||||
 | 
			
		||||
            [class*="__name"] {
 | 
			
		||||
                color: $colorItemTreeHoverFg;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &.is-navigated-object,
 | 
			
		||||
@@ -82,6 +81,12 @@
 | 
			
		||||
            margin-left: $interiorMarginSm;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &:hover {
 | 
			
		||||
            .c-tree__item__type-icon:before {
 | 
			
		||||
                color: $colorItemTreeIconHover;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &.is-navigated-object,
 | 
			
		||||
        &.is-selected {
 | 
			
		||||
            .c-tree__item__type-icon:before {
 | 
			
		||||
@@ -110,6 +115,10 @@
 | 
			
		||||
            color: $colorItemTreeFg;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &__type-icon {
 | 
			
		||||
            color: $colorItemTreeIcon;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        &.is-alias {
 | 
			
		||||
            // Object is an alias to an original.
 | 
			
		||||
            [class*='__type-icon'] {
 | 
			
		||||
 
 | 
			
		||||
@@ -76,23 +76,16 @@
 | 
			
		||||
[class*='minify-indicators'] {
 | 
			
		||||
    // All styles for minified Indicators should go in here
 | 
			
		||||
    .c-indicator:not(.no-minify) {
 | 
			
		||||
        border: 1px solid transparent; // Hack to make minified sizing work in Safari. Have no idea why this works.
 | 
			
		||||
        overflow: visible;
 | 
			
		||||
        transition: transform;
 | 
			
		||||
 | 
			
		||||
        @include hover() {
 | 
			
		||||
            background: $colorIndicatorBgHov;
 | 
			
		||||
            transition: transform 250ms ease-in 200ms; // Go-away transition
 | 
			
		||||
 | 
			
		||||
            .c-indicator__label {
 | 
			
		||||
                box-shadow: $colorIndicatorMenuBgShdw;
 | 
			
		||||
                transform: scale(1.0);
 | 
			
		||||
                overflow: visible;
 | 
			
		||||
                transition: transform 100ms ease-out 100ms; // Appear transition
 | 
			
		||||
                transition: all 100ms ease-out 100ms;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        .c-indicator__label {
 | 
			
		||||
            transition: transform 250ms ease-in 200ms; // Go-away transition
 | 
			
		||||
            transition: all 250ms ease-in 200ms;
 | 
			
		||||
            background: $colorIndicatorMenuBg;
 | 
			
		||||
            color: $colorIndicatorMenuFg;
 | 
			
		||||
            border-radius: $controlCr;
 | 
			
		||||
@@ -102,7 +95,7 @@
 | 
			
		||||
            position: absolute;
 | 
			
		||||
            transform-origin: 90% 0;
 | 
			
		||||
            transform: scale(0.0);
 | 
			
		||||
            overflow: hidden;
 | 
			
		||||
            overflow: visible;
 | 
			
		||||
            z-index: 50;
 | 
			
		||||
 | 
			
		||||
            &:before {
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user