Compare commits
	
		
			10 Commits
		
	
	
		
			hex-values
			...
			limits-513
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					c0a93a3619 | ||
| 
						 | 
					e75befafbd | ||
| 
						 | 
					d7d06b59ea | ||
| 
						 | 
					8b4a55a7ec | ||
| 
						 | 
					2519e601d7 | ||
| 
						 | 
					b7b205621b | ||
| 
						 | 
					3d2d932323 | ||
| 
						 | 
					ce28dd2b9f | ||
| 
						 | 
					286a533dad | ||
| 
						 | 
					378a4ca282 | 
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
  "name": "openmct",
 | 
			
		||||
  "version": "2.0.3-SNAPSHOT",
 | 
			
		||||
  "version": "2.0.3",
 | 
			
		||||
  "description": "The Open MCT core platform",
 | 
			
		||||
  "devDependencies": {
 | 
			
		||||
    "@babel/eslint-parser": "7.16.3",
 | 
			
		||||
 
 | 
			
		||||
@@ -241,8 +241,6 @@ define([
 | 
			
		||||
        this.branding = BrandingAPI.default;
 | 
			
		||||
 | 
			
		||||
        // Plugins that are installed by default
 | 
			
		||||
 | 
			
		||||
        this.install(this.plugins.Gauge());
 | 
			
		||||
        this.install(this.plugins.Plot());
 | 
			
		||||
        this.install(this.plugins.Chart());
 | 
			
		||||
        this.install(this.plugins.TelemetryTable.default());
 | 
			
		||||
 
 | 
			
		||||
@@ -22,12 +22,14 @@
 | 
			
		||||
 | 
			
		||||
export default class Transaction {
 | 
			
		||||
    constructor(objectAPI) {
 | 
			
		||||
        this.dirtyObjects = new Set();
 | 
			
		||||
        this.dirtyObjects = {};
 | 
			
		||||
        this.objectAPI = objectAPI;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    add(object) {
 | 
			
		||||
        this.dirtyObjects.add(object);
 | 
			
		||||
        const key = this.objectAPI.makeKeyString(object.identifier);
 | 
			
		||||
 | 
			
		||||
        this.dirtyObjects[key] = object;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    cancel() {
 | 
			
		||||
@@ -37,7 +39,8 @@ export default class Transaction {
 | 
			
		||||
    commit() {
 | 
			
		||||
        const promiseArray = [];
 | 
			
		||||
        const save = this.objectAPI.save.bind(this.objectAPI);
 | 
			
		||||
        this.dirtyObjects.forEach(object => {
 | 
			
		||||
 | 
			
		||||
        Object.values(this.dirtyObjects).forEach(object => {
 | 
			
		||||
            promiseArray.push(this.createDirtyObjectPromise(object, save));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
@@ -48,7 +51,9 @@ export default class Transaction {
 | 
			
		||||
        return new Promise((resolve, reject) => {
 | 
			
		||||
            action(object)
 | 
			
		||||
                .then((success) => {
 | 
			
		||||
                    this.dirtyObjects.delete(object);
 | 
			
		||||
                    const key = this.objectAPI.makeKeyString(object.identifier);
 | 
			
		||||
 | 
			
		||||
                    delete this.dirtyObjects[key];
 | 
			
		||||
                    resolve(success);
 | 
			
		||||
                })
 | 
			
		||||
                .catch(reject);
 | 
			
		||||
@@ -57,7 +62,8 @@ export default class Transaction {
 | 
			
		||||
 | 
			
		||||
    getDirtyObject(identifier) {
 | 
			
		||||
        let dirtyObject;
 | 
			
		||||
        this.dirtyObjects.forEach(object => {
 | 
			
		||||
 | 
			
		||||
        Object.values(this.dirtyObjects).forEach(object => {
 | 
			
		||||
            const areIdsEqual = this.objectAPI.areIdsEqual(object.identifier, identifier);
 | 
			
		||||
            if (areIdsEqual) {
 | 
			
		||||
                dirtyObject = object;
 | 
			
		||||
@@ -67,14 +73,11 @@ export default class Transaction {
 | 
			
		||||
        return dirtyObject;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    start() {
 | 
			
		||||
        this.dirtyObjects = new Set();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    _clear() {
 | 
			
		||||
        const promiseArray = [];
 | 
			
		||||
        const refresh = this.objectAPI.refresh.bind(this.objectAPI);
 | 
			
		||||
        this.dirtyObjects.forEach(object => {
 | 
			
		||||
 | 
			
		||||
        Object.values(this.dirtyObjects).forEach(object => {
 | 
			
		||||
            promiseArray.push(this.createDirtyObjectPromise(object, refresh));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -34,24 +34,24 @@ describe("Transaction Class", () => {
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('has no dirty objects', () => {
 | 
			
		||||
        expect(transaction.dirtyObjects.size).toEqual(0);
 | 
			
		||||
        expect(Object.keys(transaction.dirtyObjects).length).toEqual(0);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('add(), adds object to dirtyObjects', () => {
 | 
			
		||||
        const mockDomainObjects = createMockDomainObjects();
 | 
			
		||||
        transaction.add(mockDomainObjects[0]);
 | 
			
		||||
        expect(transaction.dirtyObjects.size).toEqual(1);
 | 
			
		||||
        expect(Object.keys(transaction.dirtyObjects).length).toEqual(1);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    it('cancel(), clears all dirtyObjects', (done) => {
 | 
			
		||||
        const mockDomainObjects = createMockDomainObjects(3);
 | 
			
		||||
        mockDomainObjects.forEach(transaction.add.bind(transaction));
 | 
			
		||||
 | 
			
		||||
        expect(transaction.dirtyObjects.size).toEqual(3);
 | 
			
		||||
        expect(Object.keys(transaction.dirtyObjects).length).toEqual(3);
 | 
			
		||||
 | 
			
		||||
        transaction.cancel()
 | 
			
		||||
            .then(success => {
 | 
			
		||||
                expect(transaction.dirtyObjects.size).toEqual(0);
 | 
			
		||||
                expect(Object.keys(transaction.dirtyObjects).length).toEqual(0);
 | 
			
		||||
            }).finally(done);
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -59,12 +59,12 @@ describe("Transaction Class", () => {
 | 
			
		||||
        const mockDomainObjects = createMockDomainObjects(3);
 | 
			
		||||
        mockDomainObjects.forEach(transaction.add.bind(transaction));
 | 
			
		||||
 | 
			
		||||
        expect(transaction.dirtyObjects.size).toEqual(3);
 | 
			
		||||
        expect(Object.keys(transaction.dirtyObjects).length).toEqual(3);
 | 
			
		||||
        spyOn(objectAPI, 'save').and.callThrough();
 | 
			
		||||
 | 
			
		||||
        transaction.commit()
 | 
			
		||||
            .then(success => {
 | 
			
		||||
                expect(transaction.dirtyObjects.size).toEqual(0);
 | 
			
		||||
                expect(Object.keys(transaction.dirtyObjects).length).toEqual(0);
 | 
			
		||||
                expect(objectAPI.save.calls.count()).toEqual(3);
 | 
			
		||||
            }).finally(done);
 | 
			
		||||
    });
 | 
			
		||||
@@ -73,7 +73,7 @@ describe("Transaction Class", () => {
 | 
			
		||||
        const mockDomainObjects = createMockDomainObjects();
 | 
			
		||||
        transaction.add(mockDomainObjects[0]);
 | 
			
		||||
 | 
			
		||||
        expect(transaction.dirtyObjects.size).toEqual(1);
 | 
			
		||||
        expect(Object.keys(transaction.dirtyObjects).length).toEqual(1);
 | 
			
		||||
        const dirtyObject = transaction.getDirtyObject(mockDomainObjects[0].identifier);
 | 
			
		||||
 | 
			
		||||
        expect(dirtyObject).toEqual(mockDomainObjects[0]);
 | 
			
		||||
@@ -82,7 +82,7 @@ describe("Transaction Class", () => {
 | 
			
		||||
    it('getDirtyObject(), returns empty dirtyObject for no active transaction', () => {
 | 
			
		||||
        const mockDomainObjects = createMockDomainObjects();
 | 
			
		||||
 | 
			
		||||
        expect(transaction.dirtyObjects.size).toEqual(0);
 | 
			
		||||
        expect(Object.keys(transaction.dirtyObjects).length).toEqual(0);
 | 
			
		||||
        const dirtyObject = transaction.getDirtyObject(mockDomainObjects[0].identifier);
 | 
			
		||||
 | 
			
		||||
        expect(dirtyObject).toEqual(undefined);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,3 @@
 | 
			
		||||
 | 
			
		||||
/*****************************************************************************
 | 
			
		||||
 * Open MCT, Copyright (c) 2014-2022, United States Government
 | 
			
		||||
 * as represented by the Administrator of the National Aeronautics and Space
 | 
			
		||||
@@ -114,14 +113,12 @@ export default {
 | 
			
		||||
        this.metadata = this.openmct.telemetry.getMetadata(this.domainObject);
 | 
			
		||||
        this.formats = this.openmct.telemetry.getFormatMap(this.metadata);
 | 
			
		||||
        this.keyString = this.openmct.objects.makeKeyString(this.domainObject.identifier);
 | 
			
		||||
        this.bounds = this.openmct.time.bounds();
 | 
			
		||||
 | 
			
		||||
        this.limitEvaluator = this.openmct
 | 
			
		||||
            .telemetry
 | 
			
		||||
            .limitEvaluator(this.domainObject);
 | 
			
		||||
 | 
			
		||||
        this.openmct.time.on('timeSystem', this.updateTimeSystem);
 | 
			
		||||
        this.openmct.time.on('bounds', this.updateBounds);
 | 
			
		||||
 | 
			
		||||
        this.timestampKey = this.openmct.time.timeSystem().key;
 | 
			
		||||
 | 
			
		||||
@@ -135,72 +132,39 @@ export default {
 | 
			
		||||
 | 
			
		||||
        this.valueKey = this.valueMetadata ? this.valueMetadata.key : undefined;
 | 
			
		||||
 | 
			
		||||
        this.unsubscribe = this.openmct
 | 
			
		||||
            .telemetry
 | 
			
		||||
            .subscribe(this.domainObject, this.setLatestValues);
 | 
			
		||||
 | 
			
		||||
        this.requestHistory();
 | 
			
		||||
        this.telemetryCollection = this.openmct.telemetry.requestCollection(this.domainObject, {
 | 
			
		||||
            size: 1,
 | 
			
		||||
            strategy: 'latest'
 | 
			
		||||
        });
 | 
			
		||||
        this.telemetryCollection.on('add', this.setLatestValues);
 | 
			
		||||
        this.telemetryCollection.on('clear', this.resetValues);
 | 
			
		||||
        this.telemetryCollection.load();
 | 
			
		||||
 | 
			
		||||
        if (this.hasUnits) {
 | 
			
		||||
            this.setUnit();
 | 
			
		||||
        }
 | 
			
		||||
    },
 | 
			
		||||
    destroyed() {
 | 
			
		||||
        this.unsubscribe();
 | 
			
		||||
        this.openmct.time.off('timeSystem', this.updateTimeSystem);
 | 
			
		||||
        this.openmct.time.off('bounds', this.updateBounds);
 | 
			
		||||
        this.telemetryCollection.off('add', this.setLatestValues);
 | 
			
		||||
        this.telemetryCollection.off('clear', this.resetValues);
 | 
			
		||||
    },
 | 
			
		||||
    methods: {
 | 
			
		||||
        updateView() {
 | 
			
		||||
            if (!this.updatingView) {
 | 
			
		||||
                this.updatingView = true;
 | 
			
		||||
                requestAnimationFrame(() => {
 | 
			
		||||
                    let newTimestamp = this.getParsedTimestamp(this.latestDatum);
 | 
			
		||||
 | 
			
		||||
                    if (this.shouldUpdate(newTimestamp)) {
 | 
			
		||||
                        this.timestamp = newTimestamp;
 | 
			
		||||
                        this.datum = this.latestDatum;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    this.timestamp = this.getParsedTimestamp(this.latestDatum);
 | 
			
		||||
                    this.datum = this.latestDatum;
 | 
			
		||||
                    this.updatingView = false;
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        setLatestValues(datum) {
 | 
			
		||||
            this.latestDatum = datum;
 | 
			
		||||
 | 
			
		||||
        setLatestValues(data) {
 | 
			
		||||
            this.latestDatum = data[data.length - 1];
 | 
			
		||||
            this.updateView();
 | 
			
		||||
        },
 | 
			
		||||
        shouldUpdate(newTimestamp) {
 | 
			
		||||
            return this.inBounds(newTimestamp)
 | 
			
		||||
                && (this.timestamp === undefined || newTimestamp > this.timestamp);
 | 
			
		||||
        },
 | 
			
		||||
        requestHistory() {
 | 
			
		||||
            this.openmct
 | 
			
		||||
                .telemetry
 | 
			
		||||
                .request(this.domainObject, {
 | 
			
		||||
                    start: this.bounds.start,
 | 
			
		||||
                    end: this.bounds.end,
 | 
			
		||||
                    size: 1,
 | 
			
		||||
                    strategy: 'latest'
 | 
			
		||||
                })
 | 
			
		||||
                .then((array) => this.setLatestValues(array[array.length - 1]))
 | 
			
		||||
                .catch((error) => {
 | 
			
		||||
                    console.warn('Error fetching data', error);
 | 
			
		||||
                });
 | 
			
		||||
        },
 | 
			
		||||
        updateBounds(bounds, isTick) {
 | 
			
		||||
            this.bounds = bounds;
 | 
			
		||||
            if (!isTick) {
 | 
			
		||||
                this.resetValues();
 | 
			
		||||
                this.requestHistory();
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        inBounds(timestamp) {
 | 
			
		||||
            return timestamp >= this.bounds.start && timestamp <= this.bounds.end;
 | 
			
		||||
        },
 | 
			
		||||
        updateTimeSystem(timeSystem) {
 | 
			
		||||
            this.resetValues();
 | 
			
		||||
            this.timestampKey = timeSystem.key;
 | 
			
		||||
        },
 | 
			
		||||
        updateViewContext() {
 | 
			
		||||
@@ -241,4 +205,3 @@ export default {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
</script>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,7 @@ describe("The LAD Table", () => {
 | 
			
		||||
 | 
			
		||||
    let openmct;
 | 
			
		||||
    let ladPlugin;
 | 
			
		||||
    let historicalProvider;
 | 
			
		||||
    let parent;
 | 
			
		||||
    let child;
 | 
			
		||||
    let telemetryCount = 3;
 | 
			
		||||
@@ -81,6 +82,13 @@ describe("The LAD Table", () => {
 | 
			
		||||
 | 
			
		||||
        spyOn(openmct.objects, 'get').and.returnValue(Promise.resolve({}));
 | 
			
		||||
 | 
			
		||||
        historicalProvider = {
 | 
			
		||||
            request: () => {
 | 
			
		||||
                return Promise.resolve([]);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
        spyOn(openmct.telemetry, 'findRequestProvider').and.returnValue(historicalProvider);
 | 
			
		||||
 | 
			
		||||
        openmct.time.bounds({
 | 
			
		||||
            start: bounds.start,
 | 
			
		||||
            end: bounds.end
 | 
			
		||||
@@ -147,7 +155,7 @@ describe("The LAD Table", () => {
 | 
			
		||||
        // add another telemetry object as composition in lad table to test multi rows
 | 
			
		||||
        mockObj.ladTable.composition.push(anotherTelemetryObj.identifier);
 | 
			
		||||
 | 
			
		||||
        beforeEach(async () => {
 | 
			
		||||
        beforeEach(async (done) => {
 | 
			
		||||
            let telemetryRequestResolve;
 | 
			
		||||
            let telemetryObjectResolve;
 | 
			
		||||
            let anotherTelemetryObjectResolve;
 | 
			
		||||
@@ -166,11 +174,12 @@ describe("The LAD Table", () => {
 | 
			
		||||
                callBack();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            openmct.telemetry.request.and.callFake(() => {
 | 
			
		||||
            historicalProvider.request = () => {
 | 
			
		||||
                telemetryRequestResolve(mockTelemetry);
 | 
			
		||||
 | 
			
		||||
                return telemetryRequestPromise;
 | 
			
		||||
            });
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            openmct.objects.get.and.callFake((obj) => {
 | 
			
		||||
                if (obj.key === 'telemetry-object') {
 | 
			
		||||
                    telemetryObjectResolve(mockObj.telemetry);
 | 
			
		||||
@@ -195,6 +204,8 @@ describe("The LAD Table", () => {
 | 
			
		||||
 | 
			
		||||
            await Promise.all([telemetryRequestPromise, telemetryObjectPromise, anotherTelemetryObjectPromise]);
 | 
			
		||||
            await Vue.nextTick();
 | 
			
		||||
 | 
			
		||||
            done();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it("should show one row per object in the composition", () => {
 | 
			
		||||
 
 | 
			
		||||
@@ -222,20 +222,18 @@ export default {
 | 
			
		||||
                .then(this.setObject);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.openmct.time.on("bounds", this.refreshData);
 | 
			
		||||
 | 
			
		||||
        this.status = this.openmct.status.get(this.item.identifier);
 | 
			
		||||
        this.removeStatusListener = this.openmct.status.observe(this.item.identifier, this.setStatus);
 | 
			
		||||
    },
 | 
			
		||||
    beforeDestroy() {
 | 
			
		||||
        this.removeSubscription();
 | 
			
		||||
        this.removeStatusListener();
 | 
			
		||||
 | 
			
		||||
        if (this.removeSelectable) {
 | 
			
		||||
            this.removeSelectable();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        this.openmct.time.off("bounds", this.refreshData);
 | 
			
		||||
        this.telemetryCollection.off('add', this.setLatestValues);
 | 
			
		||||
        this.telemetryCollection.off('clear', this.refreshData);
 | 
			
		||||
 | 
			
		||||
        if (this.mutablePromise) {
 | 
			
		||||
            this.mutablePromise.then(() => {
 | 
			
		||||
@@ -253,34 +251,9 @@ export default {
 | 
			
		||||
 | 
			
		||||
            return `At ${timeFormatter.format(this.datum)} ${this.domainObject.name} had a value of ${this.telemetryValue}${unit}`;
 | 
			
		||||
        },
 | 
			
		||||
        requestHistoricalData() {
 | 
			
		||||
            let bounds = this.openmct.time.bounds();
 | 
			
		||||
            let options = {
 | 
			
		||||
                start: bounds.start,
 | 
			
		||||
                end: bounds.end,
 | 
			
		||||
                size: 1,
 | 
			
		||||
                strategy: 'latest'
 | 
			
		||||
            };
 | 
			
		||||
            this.openmct.telemetry.request(this.domainObject, options)
 | 
			
		||||
                .then(data => {
 | 
			
		||||
                    if (data.length > 0) {
 | 
			
		||||
                        this.latestDatum = data[data.length - 1];
 | 
			
		||||
                        this.updateView();
 | 
			
		||||
                    }
 | 
			
		||||
                });
 | 
			
		||||
        },
 | 
			
		||||
        subscribeToObject() {
 | 
			
		||||
            this.subscription = this.openmct.telemetry.subscribe(this.domainObject, function (datum) {
 | 
			
		||||
                const key = this.openmct.time.timeSystem().key;
 | 
			
		||||
                const datumTimeStamp = datum[key];
 | 
			
		||||
                if (this.openmct.time.clock() !== undefined
 | 
			
		||||
                    || (datumTimeStamp
 | 
			
		||||
                        && (this.openmct.time.bounds().end >= datumTimeStamp))
 | 
			
		||||
                ) {
 | 
			
		||||
                    this.latestDatum = datum;
 | 
			
		||||
                    this.updateView();
 | 
			
		||||
                }
 | 
			
		||||
            }.bind(this));
 | 
			
		||||
        setLatestValues(data) {
 | 
			
		||||
            this.latestDatum = data[data.length - 1];
 | 
			
		||||
            this.updateView();
 | 
			
		||||
        },
 | 
			
		||||
        updateView() {
 | 
			
		||||
            if (!this.updatingView) {
 | 
			
		||||
@@ -291,17 +264,10 @@ export default {
 | 
			
		||||
                });
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        removeSubscription() {
 | 
			
		||||
            if (this.subscription) {
 | 
			
		||||
                this.subscription();
 | 
			
		||||
                this.subscription = undefined;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        refreshData(bounds, isTick) {
 | 
			
		||||
            if (!isTick) {
 | 
			
		||||
                this.latestDatum = undefined;
 | 
			
		||||
                this.updateView();
 | 
			
		||||
                this.requestHistoricalData(this.domainObject);
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        setObject(domainObject) {
 | 
			
		||||
@@ -315,8 +281,13 @@ export default {
 | 
			
		||||
            const valueMetadata = this.metadata.value(this.item.value);
 | 
			
		||||
            this.customStringformatter = this.openmct.telemetry.customStringFormatter(valueMetadata, this.item.format);
 | 
			
		||||
 | 
			
		||||
            this.requestHistoricalData();
 | 
			
		||||
            this.subscribeToObject();
 | 
			
		||||
            this.telemetryCollection = this.openmct.telemetry.requestCollection(this.domainObject, {
 | 
			
		||||
                size: 1,
 | 
			
		||||
                strategy: 'latest'
 | 
			
		||||
            });
 | 
			
		||||
            this.telemetryCollection.on('add', this.setLatestValues);
 | 
			
		||||
            this.telemetryCollection.on('clear', this.refreshData);
 | 
			
		||||
            this.telemetryCollection.load();
 | 
			
		||||
 | 
			
		||||
            this.currentObjectPath = this.objectPath.slice();
 | 
			
		||||
            this.currentObjectPath.unshift(this.domainObject);
 | 
			
		||||
 
 | 
			
		||||
@@ -53,6 +53,8 @@ describe('Gauge plugin', () => {
 | 
			
		||||
        openmct = createOpenMct();
 | 
			
		||||
        openmct.on('start', done);
 | 
			
		||||
 | 
			
		||||
        openmct.install(openmct.plugins.Gauge());
 | 
			
		||||
 | 
			
		||||
        openmct.startHeadless();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
@@ -190,28 +192,27 @@ describe('Gauge plugin', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders gauge element', () => {
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.c-gauge');
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.js-gauge-wrapper');
 | 
			
		||||
            expect(gaugeElement.length).toBe(1);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders major elements', () => {
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.c-gauge__wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.c-gauge__range');
 | 
			
		||||
            const curveElement = gaugeHolder.querySelector('.c-gauge__curval');
 | 
			
		||||
            const dialElement = gaugeHolder.querySelector('.c-dial');
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.js-gauge-wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.js-gauge-dial-range');
 | 
			
		||||
            const valueElement = gaugeHolder.querySelector('.js-dial-current-value');
 | 
			
		||||
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && curveElement && dialElement);
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && valueElement);
 | 
			
		||||
 | 
			
		||||
            expect(hasMajorElements).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders correct min max values', () => {
 | 
			
		||||
            expect(gaugeHolder.querySelector('.c-gauge__range').textContent).toEqual(`${minValue} ${maxValue}`);
 | 
			
		||||
            expect(gaugeHolder.querySelector('.js-gauge-dial-range').textContent).toEqual(`${minValue} ${maxValue}`);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders correct current value', (done) => {
 | 
			
		||||
            function WatchUpdateValue() {
 | 
			
		||||
                const textElement = gaugeHolder.querySelector('.c-gauge__curval-text');
 | 
			
		||||
                const textElement = gaugeHolder.querySelector('.js-dial-current-value');
 | 
			
		||||
                expect(Number(textElement.textContent).toFixed(gaugeViewObject.configuration.gaugeController.precision)).toBe(randomValue.toFixed(gaugeViewObject.configuration.gaugeController.precision));
 | 
			
		||||
                done();
 | 
			
		||||
            }
 | 
			
		||||
@@ -326,28 +327,27 @@ describe('Gauge plugin', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders gauge element', () => {
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.c-gauge');
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.js-gauge-wrapper');
 | 
			
		||||
            expect(gaugeElement.length).toBe(1);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders major elements', () => {
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.c-gauge__wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.c-gauge__range');
 | 
			
		||||
            const curveElement = gaugeHolder.querySelector('.c-gauge__curval');
 | 
			
		||||
            const dialElement = gaugeHolder.querySelector('.c-dial');
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.js-gauge-wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.js-gauge-dial-range');
 | 
			
		||||
            const valueElement = gaugeHolder.querySelector('.js-dial-current-value');
 | 
			
		||||
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && curveElement && dialElement);
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && valueElement);
 | 
			
		||||
 | 
			
		||||
            expect(hasMajorElements).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders correct min max values', () => {
 | 
			
		||||
            expect(gaugeHolder.querySelector('.c-gauge__range').textContent).toEqual(`${minValue} ${maxValue}`);
 | 
			
		||||
            expect(gaugeHolder.querySelector('.js-gauge-dial-range').textContent).toEqual(`${minValue} ${maxValue}`);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders correct current value', (done) => {
 | 
			
		||||
            function WatchUpdateValue() {
 | 
			
		||||
                const textElement = gaugeHolder.querySelector('.c-gauge__curval-text');
 | 
			
		||||
                const textElement = gaugeHolder.querySelector('.js-dial-current-value');
 | 
			
		||||
                expect(Number(textElement.textContent).toFixed(gaugeViewObject.configuration.gaugeController.precision)).toBe(randomValue.toFixed(gaugeViewObject.configuration.gaugeController.precision));
 | 
			
		||||
                done();
 | 
			
		||||
            }
 | 
			
		||||
@@ -462,28 +462,27 @@ describe('Gauge plugin', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders gauge element', () => {
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.c-gauge');
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.js-gauge-wrapper');
 | 
			
		||||
            expect(gaugeElement.length).toBe(1);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders major elements', () => {
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.c-gauge__wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.c-gauge__range');
 | 
			
		||||
            const curveElement = gaugeHolder.querySelector('.c-meter');
 | 
			
		||||
            const dialElement = gaugeHolder.querySelector('.c-meter__bg');
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.js-gauge-wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.js-gauge-meter-range');
 | 
			
		||||
            const valueElement = gaugeHolder.querySelector('.js-meter-current-value');
 | 
			
		||||
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && curveElement && dialElement);
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && valueElement);
 | 
			
		||||
 | 
			
		||||
            expect(hasMajorElements).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders correct min max values', () => {
 | 
			
		||||
            expect(gaugeHolder.querySelector('.c-gauge__range').textContent).toEqual(`${maxValue} ${minValue}`);
 | 
			
		||||
            expect(gaugeHolder.querySelector('.js-gauge-meter-range').textContent).toEqual(`${maxValue} ${minValue}`);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders correct current value', (done) => {
 | 
			
		||||
            function WatchUpdateValue() {
 | 
			
		||||
                const textElement = gaugeHolder.querySelector('.c-gauge__curval-text');
 | 
			
		||||
                const textElement = gaugeHolder.querySelector('.js-meter-current-value');
 | 
			
		||||
                expect(Number(textElement.textContent).toFixed(gaugeViewObject.configuration.gaugeController.precision)).toBe(randomValue.toFixed(gaugeViewObject.configuration.gaugeController.precision));
 | 
			
		||||
                done();
 | 
			
		||||
            }
 | 
			
		||||
@@ -560,17 +559,16 @@ describe('Gauge plugin', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders gauge element', () => {
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.c-gauge');
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.js-gauge-wrapper');
 | 
			
		||||
            expect(gaugeElement.length).toBe(1);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders major elements', () => {
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.c-gauge__wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.c-gauge__range');
 | 
			
		||||
            const curveElement = gaugeHolder.querySelector('.c-meter');
 | 
			
		||||
            const dialElement = gaugeHolder.querySelector('.c-meter__bg');
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.js-gauge-wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.js-gauge-meter-range');
 | 
			
		||||
            const valueElement = gaugeHolder.querySelector('.js-meter-current-value');
 | 
			
		||||
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && curveElement && dialElement);
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && valueElement);
 | 
			
		||||
 | 
			
		||||
            expect(hasMajorElements).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
@@ -643,17 +641,16 @@ describe('Gauge plugin', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders gauge element', () => {
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.c-gauge');
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.js-gauge-wrapper');
 | 
			
		||||
            expect(gaugeElement.length).toBe(1);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders major elements', () => {
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.c-gauge__wrapper');
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.js-gauge-wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.c-gauge__range');
 | 
			
		||||
            const curveElement = gaugeHolder.querySelector('.c-meter');
 | 
			
		||||
            const dialElement = gaugeHolder.querySelector('.c-meter__bg');
 | 
			
		||||
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && curveElement && dialElement);
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && curveElement);
 | 
			
		||||
 | 
			
		||||
            expect(hasMajorElements).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
@@ -772,28 +769,27 @@ describe('Gauge plugin', () => {
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders gauge element', () => {
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.c-gauge');
 | 
			
		||||
            const gaugeElement = gaugeHolder.querySelectorAll('.js-gauge-wrapper');
 | 
			
		||||
            expect(gaugeElement.length).toBe(1);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders major elements', () => {
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.c-gauge__wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.c-gauge__range');
 | 
			
		||||
            const curveElement = gaugeHolder.querySelector('.c-gauge__curval');
 | 
			
		||||
            const dialElement = gaugeHolder.querySelector('.c-dial');
 | 
			
		||||
            const wrapperElement = gaugeHolder.querySelector('.js-gauge-wrapper');
 | 
			
		||||
            const rangeElement = gaugeHolder.querySelector('.js-gauge-dial-range');
 | 
			
		||||
            const valueElement = gaugeHolder.querySelector('.js-dial-current-value');
 | 
			
		||||
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && curveElement && dialElement);
 | 
			
		||||
            const hasMajorElements = Boolean(wrapperElement && rangeElement && valueElement);
 | 
			
		||||
 | 
			
		||||
            expect(hasMajorElements).toBe(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders correct min max values', () => {
 | 
			
		||||
            expect(gaugeHolder.querySelector('.c-gauge__range').textContent).toEqual(`${gaugeViewObject.configuration.gaugeController.min} ${gaugeViewObject.configuration.gaugeController.max}`);
 | 
			
		||||
            expect(gaugeHolder.querySelector('.js-gauge-dial-range').textContent).toEqual(`${gaugeViewObject.configuration.gaugeController.min} ${gaugeViewObject.configuration.gaugeController.max}`);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('renders correct current value', (done) => {
 | 
			
		||||
            function WatchUpdateValue() {
 | 
			
		||||
                const textElement = gaugeHolder.querySelector('.c-gauge__curval-text');
 | 
			
		||||
                const textElement = gaugeHolder.querySelector('.js-dial-current-value');
 | 
			
		||||
                expect(Number(textElement.textContent).toFixed(gaugeViewObject.configuration.gaugeController.precision)).toBe(randomValue.toFixed(gaugeViewObject.configuration.gaugeController.precision));
 | 
			
		||||
                done();
 | 
			
		||||
            }
 | 
			
		||||
 
 | 
			
		||||
@@ -32,7 +32,9 @@ export default function GaugeViewProvider(openmct) {
 | 
			
		||||
            return domainObject.type === 'gauge';
 | 
			
		||||
        },
 | 
			
		||||
        canEdit: function (domainObject) {
 | 
			
		||||
            return false;
 | 
			
		||||
            if (domainObject.type === 'gauge') {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
        },
 | 
			
		||||
        view: function (domainObject) {
 | 
			
		||||
            let component;
 | 
			
		||||
 
 | 
			
		||||
@@ -21,168 +21,259 @@
 | 
			
		||||
*****************************************************************************/
 | 
			
		||||
<template>
 | 
			
		||||
<div
 | 
			
		||||
    class="c-gauge"
 | 
			
		||||
    class="c-gauge__wrapper js-gauge-wrapper"
 | 
			
		||||
    :class="`c-gauge--${gaugeType}`"
 | 
			
		||||
>
 | 
			
		||||
    <div class="c-gauge__wrapper">
 | 
			
		||||
        <template v-if="typeDial">
 | 
			
		||||
            <svg
 | 
			
		||||
                class="c-gauge__range"
 | 
			
		||||
                viewBox="0 0 512 512"
 | 
			
		||||
            >
 | 
			
		||||
                <text
 | 
			
		||||
                    v-if="displayMinMax"
 | 
			
		||||
                    font-size="35"
 | 
			
		||||
                    transform="translate(105 455) rotate(-45)"
 | 
			
		||||
                >{{ rangeLow }}</text>
 | 
			
		||||
                <text
 | 
			
		||||
                    v-if="displayMinMax"
 | 
			
		||||
                    font-size="35"
 | 
			
		||||
                    transform="translate(407 455) rotate(45)"
 | 
			
		||||
                    text-anchor="end"
 | 
			
		||||
                >{{ rangeHigh }}</text>
 | 
			
		||||
            </svg>
 | 
			
		||||
    <template v-if="typeDial">
 | 
			
		||||
        <svg
 | 
			
		||||
            width="0"
 | 
			
		||||
            height="0"
 | 
			
		||||
            class="c-dial__clip-paths"
 | 
			
		||||
        >
 | 
			
		||||
            <defs>
 | 
			
		||||
                <clipPath
 | 
			
		||||
                    id="gaugeBgMask"
 | 
			
		||||
                    clipPathUnits="objectBoundingBox"
 | 
			
		||||
                >
 | 
			
		||||
                    <path d="M0.853553 0.853553C0.944036 0.763071 1 0.638071 1 0.5C1 0.223858 0.776142 0 0.5 0C0.223858 0 0 0.223858 0 0.5C0 0.638071 0.0559644 0.763071 0.146447 0.853553L0.285934 0.714066C0.23115 0.659281 0.197266 0.583598 0.197266 0.5C0.197266 0.332804 0.332804 0.197266 0.5 0.197266C0.667196 0.197266 0.802734 0.332804 0.802734 0.5C0.802734 0.583598 0.76885 0.659281 0.714066 0.714066L0.853553 0.853553Z" />
 | 
			
		||||
                </clipPath>
 | 
			
		||||
                <clipPath
 | 
			
		||||
                    id="gaugeValueMask"
 | 
			
		||||
                    clipPathUnits="objectBoundingBox"
 | 
			
		||||
                >
 | 
			
		||||
                    <path d="M0.18926 0.81074C0.109735 0.731215 0.0605469 0.621351 0.0605469 0.5C0.0605469 0.257298 0.257298 0.0605469 0.5 0.0605469C0.742702 0.0605469 0.939453 0.257298 0.939453 0.5C0.939453 0.621351 0.890265 0.731215 0.81074 0.81074L0.714066 0.714066C0.76885 0.659281 0.802734 0.583599 0.802734 0.5C0.802734 0.332804 0.667196 0.197266 0.5 0.197266C0.332804 0.197266 0.197266 0.332804 0.197266 0.5C0.197266 0.583599 0.23115 0.659281 0.285934 0.714066L0.18926 0.81074Z" />
 | 
			
		||||
                </clipPath>
 | 
			
		||||
            </defs>
 | 
			
		||||
        </svg>
 | 
			
		||||
 | 
			
		||||
        <svg
 | 
			
		||||
            class="c-dial__range c-gauge__range js-gauge-dial-range"
 | 
			
		||||
            viewBox="0 0 512 512"
 | 
			
		||||
        >
 | 
			
		||||
            <text
 | 
			
		||||
                v-if="displayMinMax"
 | 
			
		||||
                font-size="35"
 | 
			
		||||
                transform="translate(105 455) rotate(-45)"
 | 
			
		||||
            >{{ rangeLow }}</text>
 | 
			
		||||
            <text
 | 
			
		||||
                v-if="displayMinMax"
 | 
			
		||||
                font-size="35"
 | 
			
		||||
                transform="translate(407 455) rotate(45)"
 | 
			
		||||
                text-anchor="end"
 | 
			
		||||
            >{{ rangeHigh }}</text>
 | 
			
		||||
        </svg>
 | 
			
		||||
 | 
			
		||||
        <svg
 | 
			
		||||
            class="c-dial__current-value-text-wrapper"
 | 
			
		||||
            viewBox="0 0 512 512"
 | 
			
		||||
        >
 | 
			
		||||
            <svg
 | 
			
		||||
                v-if="displayCurVal"
 | 
			
		||||
                class="c-gauge__curval"
 | 
			
		||||
                class="c-dial__current-value-text-sizer"
 | 
			
		||||
                :viewBox="curValViewBox"
 | 
			
		||||
            >
 | 
			
		||||
                <text
 | 
			
		||||
                    class="c-gauge__curval-text"
 | 
			
		||||
                    class="c-dial__current-value-text js-dial-current-value"
 | 
			
		||||
                    lengthAdjust="spacing"
 | 
			
		||||
                    text-anchor="middle"
 | 
			
		||||
                    style="transform: translate(50%, 70%)"
 | 
			
		||||
                >{{ curVal }}</text>
 | 
			
		||||
            </svg>
 | 
			
		||||
        </svg>
 | 
			
		||||
 | 
			
		||||
            <div class="c-dial">
 | 
			
		||||
                <svg
 | 
			
		||||
                    class="c-dial__bg"
 | 
			
		||||
                    viewBox="0 0 512 512"
 | 
			
		||||
                >
 | 
			
		||||
                    <path d="M256,0C114.6,0,0,114.6,0,256S114.6,512,256,512,512,397.4,512,256,397.4,0,256,0Zm0,412A156,156,0,1,1,412,256,155.9,155.9,0,0,1,256,412Z" />
 | 
			
		||||
                </svg>
 | 
			
		||||
        <svg
 | 
			
		||||
            class="c-dial__bg"
 | 
			
		||||
            viewBox="0 0 10 10"
 | 
			
		||||
        >
 | 
			
		||||
 | 
			
		||||
                <svg
 | 
			
		||||
                    v-if="limitHigh && dialHighLimitDeg < 270"
 | 
			
		||||
                    class="c-dial__limit-high"
 | 
			
		||||
                    viewBox="0 0 512 512"
 | 
			
		||||
                    :class="{
 | 
			
		||||
                        'c-high-limit-clip--90': dialHighLimitDeg > 90,
 | 
			
		||||
                        'c-high-limit-clip--180': dialHighLimitDeg >= 180
 | 
			
		||||
                    }"
 | 
			
		||||
                >
 | 
			
		||||
                    <path
 | 
			
		||||
                        d="M100,256A156,156,0,1,1,366.3,366.3L437,437a255.2,255.2,0,0,0,75-181C512,114.6,397.4,0,256,0S0,114.6,0,256A255.2,255.2,0,0,0,75,437l70.7-70.7A155.5,155.5,0,0,1,100,256Z"
 | 
			
		||||
                        :style="`transform: rotate(${dialHighLimitDeg}deg)`"
 | 
			
		||||
                    />
 | 
			
		||||
                </svg>
 | 
			
		||||
            <g
 | 
			
		||||
                v-if="limitLow !== '' && dialLowLimitDeg < getLimitDegree('low', 'max')"
 | 
			
		||||
                class="c-dial__limit-low"
 | 
			
		||||
                :style="`transform: rotate(${dialLowLimitDeg}deg)`"
 | 
			
		||||
            >
 | 
			
		||||
                <rect
 | 
			
		||||
                    v-if="dialLowLimitDeg >= getLimitDegree('low', 'q1')"
 | 
			
		||||
                    class="c-dial__low-limit__low"
 | 
			
		||||
                    x="5"
 | 
			
		||||
                    y="5"
 | 
			
		||||
                    width="5"
 | 
			
		||||
                    height="5"
 | 
			
		||||
                />
 | 
			
		||||
                <rect
 | 
			
		||||
                    v-if="dialLowLimitDeg >= getLimitDegree('low', 'q2')"
 | 
			
		||||
                    class="c-dial__low-limit__mid"
 | 
			
		||||
                    x="5"
 | 
			
		||||
                    y="0"
 | 
			
		||||
                    width="5"
 | 
			
		||||
                    height="5"
 | 
			
		||||
                />
 | 
			
		||||
                <rect
 | 
			
		||||
                    v-if="dialLowLimitDeg >= getLimitDegree('low', 'q3')"
 | 
			
		||||
                    class="c-dial__low-limit__high"
 | 
			
		||||
                    x="0"
 | 
			
		||||
                    y="0"
 | 
			
		||||
                    width="5"
 | 
			
		||||
                    height="5"
 | 
			
		||||
                />
 | 
			
		||||
            </g>
 | 
			
		||||
 | 
			
		||||
                <svg
 | 
			
		||||
                    v-if="limitLow && dialLowLimitDeg < 270"
 | 
			
		||||
                    class="c-dial__limit-low"
 | 
			
		||||
                    viewBox="0 0 512 512"
 | 
			
		||||
                    :class="{
 | 
			
		||||
                        'c-dial-clip--90': dialLowLimitDeg < 90,
 | 
			
		||||
                        'c-dial-clip--180': dialLowLimitDeg >= 90 && dialLowLimitDeg < 180
 | 
			
		||||
                    }"
 | 
			
		||||
                >
 | 
			
		||||
                    <path
 | 
			
		||||
                        d="M256,100c86.2,0,156,69.8,156,156s-69.8,156-156,156c-43.1,0-82.1-17.5-110.3-45.7L75,437 c46.3,46.3,110.3,75,181,75c141.4,0,256-114.6,256-256S397.4,0,256,0C185.3,0,121.3,28.7,75,75l70.7,70.7 C173.9,117.5,212.9,100,256,100z"
 | 
			
		||||
                        :style="`transform: rotate(${dialLowLimitDeg}deg)`"
 | 
			
		||||
                    />
 | 
			
		||||
                </svg>
 | 
			
		||||
            <g
 | 
			
		||||
                v-if="limitHigh !== '' && dialHighLimitDeg < getLimitDegree('high', 'max')"
 | 
			
		||||
                class="c-dial__limit-high"
 | 
			
		||||
                :style="`transform: rotate(${dialHighLimitDeg}deg)`"
 | 
			
		||||
            >
 | 
			
		||||
                <rect
 | 
			
		||||
                    v-if="dialHighLimitDeg <= getLimitDegree('high', 'max')"
 | 
			
		||||
                    class="c-dial__high-limit__low"
 | 
			
		||||
                    x="0"
 | 
			
		||||
                    y="5"
 | 
			
		||||
                    width="5"
 | 
			
		||||
                    height="5"
 | 
			
		||||
                />
 | 
			
		||||
                <rect
 | 
			
		||||
                    v-if="dialHighLimitDeg <= getLimitDegree('high', 'q2')"
 | 
			
		||||
                    class="c-dial__high-limit__mid"
 | 
			
		||||
                    x="0"
 | 
			
		||||
                    y="0"
 | 
			
		||||
                    width="5"
 | 
			
		||||
                    height="5"
 | 
			
		||||
                />
 | 
			
		||||
                <rect
 | 
			
		||||
                    v-if="dialHighLimitDeg <= getLimitDegree('high', 'q3')"
 | 
			
		||||
                    class="c-dial__high-limit__high"
 | 
			
		||||
                    x="5"
 | 
			
		||||
                    y="0"
 | 
			
		||||
                    width="5"
 | 
			
		||||
                    height="5"
 | 
			
		||||
                />
 | 
			
		||||
            </g>
 | 
			
		||||
        </svg>
 | 
			
		||||
 | 
			
		||||
                <svg
 | 
			
		||||
                    class="c-dial__value"
 | 
			
		||||
                    viewBox="0 0 512 512"
 | 
			
		||||
                    :class="{
 | 
			
		||||
                        'c-dial-clip--90': degValue < 90 && typeFilledDial,
 | 
			
		||||
                        'c-dial-clip--180': degValue >= 90 && degValue < 180 && typeFilledDial
 | 
			
		||||
                    }"
 | 
			
		||||
                >
 | 
			
		||||
                    <path
 | 
			
		||||
                        v-if="typeFilledDial && degValue > 0"
 | 
			
		||||
                        d="M256,31A224.3,224.3,0,0,0,98.3,95.5l48.4,49.2a156,156,0,1,1-1,221.6L96.9,415.1A224.4,224.4,0,0,0,256,481c124.3,0,225-100.7,225-225S380.3,31,256,31Z"
 | 
			
		||||
                        :style="`transform: rotate(${degValue}deg)`"
 | 
			
		||||
                    />
 | 
			
		||||
                    <path
 | 
			
		||||
                        v-if="typeNeedleDial && valueInBounds"
 | 
			
		||||
                        d="M256,86c-93.9,0-170,76.1-170,170c0,43.9,16.6,83.9,43.9,114.1l-38.7,38.7c-3.3,3.3-3.3,8.7,0,12s8.7,3.3,12,0 l38.7-38.7C172.1,409.4,212.1,426,256,426c93.9,0,170-76.1,170-170S349.9,86,256,86z M256,411.7c-86,0-155.7-69.7-155.7-155.7 S170,100.3,256,100.3S411.7,170,411.7,256S342,411.7,256,411.7z"
 | 
			
		||||
                        :style="`transform: rotate(${degValue}deg)`"
 | 
			
		||||
                    />
 | 
			
		||||
                </svg>
 | 
			
		||||
        <svg
 | 
			
		||||
            v-if="typeFilledDial"
 | 
			
		||||
            class="c-dial__filled-value-wrapper"
 | 
			
		||||
            viewBox="0 0 10 10"
 | 
			
		||||
        >
 | 
			
		||||
            <g
 | 
			
		||||
                class="c-dial__filled-value"
 | 
			
		||||
                :style="`transform: rotate(${degValueFilledDial}deg)`"
 | 
			
		||||
            >
 | 
			
		||||
                <rect
 | 
			
		||||
                    v-if="degValue >= getLimitDegree('low', 'q1')"
 | 
			
		||||
                    class="c-dial__filled-value__low"
 | 
			
		||||
                    x="5"
 | 
			
		||||
                    y="5"
 | 
			
		||||
                    width="5"
 | 
			
		||||
                    height="5"
 | 
			
		||||
                />
 | 
			
		||||
                <rect
 | 
			
		||||
                    v-if="degValue >= getLimitDegree('low', 'q2')"
 | 
			
		||||
                    class="c-dial__filled-value__mid"
 | 
			
		||||
                    x="5"
 | 
			
		||||
                    y="0"
 | 
			
		||||
                    width="5"
 | 
			
		||||
                    height="5"
 | 
			
		||||
                />
 | 
			
		||||
                <rect
 | 
			
		||||
                    v-if="degValue >= getLimitDegree('low', 'q3')"
 | 
			
		||||
                    class="c-dial__filled-value__high"
 | 
			
		||||
                    x="0"
 | 
			
		||||
                    y="0"
 | 
			
		||||
                    width="5"
 | 
			
		||||
                    height="5"
 | 
			
		||||
                />
 | 
			
		||||
            </g>
 | 
			
		||||
        </svg>
 | 
			
		||||
 | 
			
		||||
        <svg
 | 
			
		||||
            v-if="valueInBounds && typeNeedleDial"
 | 
			
		||||
            class="c-dial__needle-value-wrapper"
 | 
			
		||||
            viewBox="0 0 10 10"
 | 
			
		||||
        >
 | 
			
		||||
            <g
 | 
			
		||||
                class="c-dial__needle-value"
 | 
			
		||||
                :style="`transform: rotate(${degValue}deg)`"
 | 
			
		||||
            >
 | 
			
		||||
                <path d="M4.90234 9.39453L5.09766 9.39453L5.30146 8.20874C6.93993 8.05674 8.22265 6.67817 8.22266 5C8.22266 3.22018 6.77982 1.77734 5 1.77734C3.22018 1.77734 1.77734 3.22018 1.77734 5C1.77734 6.67817 3.06007 8.05674 4.69854 8.20874L4.90234 9.39453Z" />
 | 
			
		||||
            </g>
 | 
			
		||||
        </svg>
 | 
			
		||||
    </template>
 | 
			
		||||
 | 
			
		||||
    <template v-if="typeMeter">
 | 
			
		||||
        <div class="c-meter">
 | 
			
		||||
            <div
 | 
			
		||||
                v-if="displayMinMax"
 | 
			
		||||
                class="c-gauge__range c-meter__range js-gauge-meter-range"
 | 
			
		||||
            >
 | 
			
		||||
                <div class="c-meter__range__high">{{ rangeHigh }}</div>
 | 
			
		||||
                <div class="c-meter__range__low">{{ rangeLow }}</div>
 | 
			
		||||
            </div>
 | 
			
		||||
        </template>
 | 
			
		||||
            <div class="c-meter__bg">
 | 
			
		||||
                <template v-if="typeMeterVertical">
 | 
			
		||||
                    <div
 | 
			
		||||
                        class="c-meter__value"
 | 
			
		||||
                        :style="`transform: translateY(${meterValueToPerc}%)`"
 | 
			
		||||
                    ></div>
 | 
			
		||||
 | 
			
		||||
        <template v-if="typeMeter">
 | 
			
		||||
            <div class="c-meter">
 | 
			
		||||
                <div
 | 
			
		||||
                    v-if="displayMinMax"
 | 
			
		||||
                    class="c-gauge__range c-meter__range"
 | 
			
		||||
                    <div
 | 
			
		||||
                        v-if="limitHigh !== '' && meterHighLimitPerc > 0"
 | 
			
		||||
                        class="c-meter__limit-high"
 | 
			
		||||
                        :style="`height: ${meterHighLimitPerc}%`"
 | 
			
		||||
                    ></div>
 | 
			
		||||
 | 
			
		||||
                    <div
 | 
			
		||||
                        v-if="limitLow !== '' && meterLowLimitPerc > 0"
 | 
			
		||||
                        class="c-meter__limit-low"
 | 
			
		||||
                        :style="`height: ${meterLowLimitPerc}%`"
 | 
			
		||||
                    ></div>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <template v-if="typeMeterHorizontal">
 | 
			
		||||
                    <div
 | 
			
		||||
                        class="c-meter__value"
 | 
			
		||||
                        :style="`transform: translateX(${meterValueToPerc * -1}%)`"
 | 
			
		||||
                    ></div>
 | 
			
		||||
 | 
			
		||||
                    <div
 | 
			
		||||
                        v-if="limitHigh !== '' && meterHighLimitPerc > 0"
 | 
			
		||||
                        class="c-meter__limit-high"
 | 
			
		||||
                        :style="`width: ${meterHighLimitPerc}%`"
 | 
			
		||||
                    ></div>
 | 
			
		||||
 | 
			
		||||
                    <div
 | 
			
		||||
                        v-if="limitLow !== '' && meterLowLimitPerc > 0"
 | 
			
		||||
                        class="c-meter__limit-low"
 | 
			
		||||
                        :style="`width: ${meterLowLimitPerc}%`"
 | 
			
		||||
                    ></div>
 | 
			
		||||
                </template>
 | 
			
		||||
 | 
			
		||||
                <svg
 | 
			
		||||
                    class="c-meter__current-value-text-wrapper"
 | 
			
		||||
                    viewBox="0 0 512 512"
 | 
			
		||||
                >
 | 
			
		||||
                    <div class="c-meter__range__high">{{ rangeHigh }}</div>
 | 
			
		||||
                    <div class="c-meter__range__low">{{ rangeLow }}</div>
 | 
			
		||||
                </div>
 | 
			
		||||
                <div class="c-meter__bg">
 | 
			
		||||
                    <template v-if="typeMeterVertical">
 | 
			
		||||
                        <div
 | 
			
		||||
                            class="c-meter__value"
 | 
			
		||||
                            :style="`transform: translateY(${meterValueToPerc}%)`"
 | 
			
		||||
                        ></div>
 | 
			
		||||
 | 
			
		||||
                        <div
 | 
			
		||||
                            v-if="limitHigh && meterHighLimitPerc > 0"
 | 
			
		||||
                            class="c-meter__limit-high"
 | 
			
		||||
                            :style="`height: ${meterHighLimitPerc}%`"
 | 
			
		||||
                        ></div>
 | 
			
		||||
 | 
			
		||||
                        <div
 | 
			
		||||
                            v-if="limitLow && meterLowLimitPerc > 0"
 | 
			
		||||
                            class="c-meter__limit-low"
 | 
			
		||||
                            :style="`height: ${meterLowLimitPerc}%`"
 | 
			
		||||
                        ></div>
 | 
			
		||||
                    </template>
 | 
			
		||||
 | 
			
		||||
                    <template v-if="typeMeterHorizontal">
 | 
			
		||||
                        <div
 | 
			
		||||
                            class="c-meter__value"
 | 
			
		||||
                            :style="`transform: translateX(${meterValueToPerc * -1}%)`"
 | 
			
		||||
                        ></div>
 | 
			
		||||
 | 
			
		||||
                        <div
 | 
			
		||||
                            v-if="limitHigh && meterHighLimitPerc > 0"
 | 
			
		||||
                            class="c-meter__limit-high"
 | 
			
		||||
                            :style="`width: ${meterHighLimitPerc}%`"
 | 
			
		||||
                        ></div>
 | 
			
		||||
 | 
			
		||||
                        <div
 | 
			
		||||
                            v-if="limitLow && meterLowLimitPerc > 0"
 | 
			
		||||
                            class="c-meter__limit-low"
 | 
			
		||||
                            :style="`width: ${meterLowLimitPerc}%`"
 | 
			
		||||
                        ></div>
 | 
			
		||||
                    </template>
 | 
			
		||||
 | 
			
		||||
                    <svg
 | 
			
		||||
                        v-if="displayCurVal"
 | 
			
		||||
                        class="c-gauge__curval"
 | 
			
		||||
                        class="c-meter__current-value-text-sizer"
 | 
			
		||||
                        :viewBox="curValViewBox"
 | 
			
		||||
                        preserveAspectRatio="xMidYMid meet"
 | 
			
		||||
                    >
 | 
			
		||||
                        <text
 | 
			
		||||
                            class="c-gauge__curval-text"
 | 
			
		||||
                            text-anchor="middle"
 | 
			
		||||
                            class="c-dial__current-value-text js-meter-current-value"
 | 
			
		||||
                            lengthAdjust="spacing"
 | 
			
		||||
                            text-anchor="middle"
 | 
			
		||||
                            style="transform: translate(50%, 70%)"
 | 
			
		||||
                        >{{ curVal }}</text>
 | 
			
		||||
                    </svg>
 | 
			
		||||
                </div>
 | 
			
		||||
                </svg>
 | 
			
		||||
            </div>
 | 
			
		||||
        </template>
 | 
			
		||||
    </div>
 | 
			
		||||
        </div>
 | 
			
		||||
    </template>
 | 
			
		||||
</div>
 | 
			
		||||
</template>
 | 
			
		||||
 | 
			
		||||
<script>
 | 
			
		||||
import { DIAL_VALUE_DEG_OFFSET, getLimitDegree } from '../gauge-limit-util';
 | 
			
		||||
 | 
			
		||||
const LIMIT_PADDING_IN_PERCENT = 10;
 | 
			
		||||
 | 
			
		||||
export default {
 | 
			
		||||
@@ -209,6 +300,13 @@ export default {
 | 
			
		||||
        degValue() {
 | 
			
		||||
            return this.percentToDegrees(this.valToPercent(this.curVal));
 | 
			
		||||
        },
 | 
			
		||||
        degValueFilledDial() {
 | 
			
		||||
            if (this.curVal > this.rangeHigh) {
 | 
			
		||||
                return this.percentToDegrees(100);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return this.percentToDegrees(this.valToPercent(this.curVal));
 | 
			
		||||
        },
 | 
			
		||||
        dialHighLimitDeg() {
 | 
			
		||||
            return this.percentToDegrees(this.valToPercent(this.limitHigh));
 | 
			
		||||
        },
 | 
			
		||||
@@ -299,6 +397,7 @@ export default {
 | 
			
		||||
        this.openmct.time.off('timeSystem', this.setTimeSystem);
 | 
			
		||||
    },
 | 
			
		||||
    methods: {
 | 
			
		||||
        getLimitDegree: getLimitDegree,
 | 
			
		||||
        addTelemetryObjectAndSubscribe(domainObject) {
 | 
			
		||||
            this.telemetryObject = domainObject;
 | 
			
		||||
            this.request();
 | 
			
		||||
@@ -340,7 +439,7 @@ export default {
 | 
			
		||||
            return this.gaugeType.indexOf(str) !== -1;
 | 
			
		||||
        },
 | 
			
		||||
        percentToDegrees(vPercent) {
 | 
			
		||||
            return this.round((vPercent / 100) * 270, 2);
 | 
			
		||||
            return this.round(((vPercent / 100) * 270) + DIAL_VALUE_DEG_OFFSET, 2);
 | 
			
		||||
        },
 | 
			
		||||
        removeFromComposition(telemetryObject = this.telemetryObject) {
 | 
			
		||||
            let composition = this.domainObject.composition.filter(id =>
 | 
			
		||||
@@ -453,7 +552,7 @@ export default {
 | 
			
		||||
        valToPercent(vValue) {
 | 
			
		||||
            // Used by dial
 | 
			
		||||
            if (vValue >= this.rangeHigh && this.typeFilledDial) {
 | 
			
		||||
                // Don't peg at 100% if the gaugeType isn't a filled shape
 | 
			
		||||
                // For filled dial, clip values over the high range to prevent over-rotation
 | 
			
		||||
                return 100;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -27,6 +27,7 @@
 | 
			
		||||
        :class="model.cssClass"
 | 
			
		||||
    >
 | 
			
		||||
        <ToggleSwitch
 | 
			
		||||
            :id="'gaugeToggle'"
 | 
			
		||||
            :checked="isUseTelemetryLimits"
 | 
			
		||||
            label="Use telemetry limits for minimum and maximum ranges"
 | 
			
		||||
            @change="toggleUseTelemetryLimits"
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										39
									
								
								src/plugins/gauge/gauge-limit-util.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/plugins/gauge/gauge-limit-util.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,39 @@
 | 
			
		||||
const GAUGE_LIMITS = {
 | 
			
		||||
    q1: 0,
 | 
			
		||||
    q2: 90,
 | 
			
		||||
    q3: 180,
 | 
			
		||||
    q4: 270
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export const DIAL_VALUE_DEG_OFFSET = 45;
 | 
			
		||||
 | 
			
		||||
// type: low, high
 | 
			
		||||
// quadrant: low, mid, high, max
 | 
			
		||||
export function getLimitDegree(type, quadrant) {
 | 
			
		||||
    if (quadrant === 'max') {
 | 
			
		||||
        return GAUGE_LIMITS.q4 + DIAL_VALUE_DEG_OFFSET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return type === 'low'
 | 
			
		||||
        ? getLowLimitDegree(quadrant)
 | 
			
		||||
        : getHighLimitDegree(quadrant)
 | 
			
		||||
    ;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getLowLimitDegree(quadrant) {
 | 
			
		||||
    return GAUGE_LIMITS[quadrant] + DIAL_VALUE_DEG_OFFSET;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function getHighLimitDegree(quadrant) {
 | 
			
		||||
    if (quadrant === 'q1') {
 | 
			
		||||
        return GAUGE_LIMITS.q4 + DIAL_VALUE_DEG_OFFSET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (quadrant === 'q2') {
 | 
			
		||||
        return GAUGE_LIMITS.q3 + DIAL_VALUE_DEG_OFFSET;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (quadrant === 'q3') {
 | 
			
		||||
        return GAUGE_LIMITS.q2 + DIAL_VALUE_DEG_OFFSET;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,3 @@
 | 
			
		||||
$dialClip: polygon(0 0, 100% 0, 100% 100%, 50% 50%, 0 100%);
 | 
			
		||||
$dialClip90: polygon(0 0, 50% 50%, 0 100%);
 | 
			
		||||
$dialClip180: polygon(0 0, 100% 0, 0 100%);
 | 
			
		||||
$limitHighClip90: polygon(0 0, 100% 0, 100% 100%);
 | 
			
		||||
$limitHighClip180: polygon(100% 0, 100% 100%, 0 100%);
 | 
			
		||||
 | 
			
		||||
.is-object-type-gauge {
 | 
			
		||||
  overflow: hidden;
 | 
			
		||||
}
 | 
			
		||||
@@ -13,10 +7,8 @@ $limitHighClip180: polygon(100% 0, 100% 100%, 0 100%);
 | 
			
		||||
 | 
			
		||||
  &.invalid,
 | 
			
		||||
  &.invalid.req { @include validationState($glyph-icon-x, $colorFormInvalid); }
 | 
			
		||||
 | 
			
		||||
  &.valid,
 | 
			
		||||
  &.valid.req { @include validationState($glyph-icon-check, $colorFormValid); }
 | 
			
		||||
 | 
			
		||||
  &.req { @include validationState($glyph-icon-asterisk, $colorFormRequired); }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@@ -37,92 +29,47 @@ $limitHighClip180: polygon(100% 0, 100% 100%, 0 100%);
 | 
			
		||||
    @include abs();
 | 
			
		||||
    overflow: hidden;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  svg {
 | 
			
		||||
    path {
 | 
			
		||||
      transform-origin: center;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.c-gauge__curval {
 | 
			
		||||
      @include abs();
 | 
			
		||||
      fill: $colorGaugeTextValue;
 | 
			
		||||
      position: absolute;
 | 
			
		||||
      width: 100%;
 | 
			
		||||
      height: 100%;
 | 
			
		||||
      z-index: 2;
 | 
			
		||||
 | 
			
		||||
      .c-gauge__curval-text {
 | 
			
		||||
        font-family: $heroFont;
 | 
			
		||||
        transform: translate(50%, 75%);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &[class*='dial'] {
 | 
			
		||||
    // Square aspect ratio
 | 
			
		||||
    width: 100%;
 | 
			
		||||
    padding-bottom: 100%;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &[class*='meter'] {
 | 
			
		||||
    @include abs();
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/********************************************** DIAL GAUGE */
 | 
			
		||||
.c-dial {
 | 
			
		||||
  // Dial elements
 | 
			
		||||
  @include abs();
 | 
			
		||||
  clip-path: $dialClip;
 | 
			
		||||
svg[class*='c-dial'] {
 | 
			
		||||
  max-height: 100%;
 | 
			
		||||
  max-width: 100%;
 | 
			
		||||
  position: absolute;
 | 
			
		||||
 | 
			
		||||
  svg,
 | 
			
		||||
  &__ticks,
 | 
			
		||||
  &__bg,
 | 
			
		||||
  &[class*='__limit'],
 | 
			
		||||
  &__value {
 | 
			
		||||
    @include abs();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .c-high-limit-clip--90 {
 | 
			
		||||
    clip-path: $limitHighClip90;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  .c-high-limit-clip--180 {
 | 
			
		||||
    clip-path: $limitHighClip180;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__limit-high path { fill: $colorGaugeLimitHigh; }
 | 
			
		||||
  &__limit-low path { fill: $colorGaugeLimitLow; }
 | 
			
		||||
 | 
			
		||||
  &__value,
 | 
			
		||||
  &__limit-low {
 | 
			
		||||
    &.c-dial-clip--90 {
 | 
			
		||||
      clip-path: $dialClip90;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    &.c-dial-clip--180 {
 | 
			
		||||
      clip-path: $dialClip180;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__value {
 | 
			
		||||
    path,
 | 
			
		||||
    polygon {
 | 
			
		||||
      fill: $colorGaugeValue;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__bg {
 | 
			
		||||
    path {
 | 
			
		||||
      fill: $colorGaugeBg;
 | 
			
		||||
    }
 | 
			
		||||
  g {
 | 
			
		||||
    transform-origin: center;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
.c-gauge--dial-needle .c-dial__value {
 | 
			
		||||
  path {
 | 
			
		||||
.c-dial {
 | 
			
		||||
  &__bg {
 | 
			
		||||
    background: $colorGaugeBg;
 | 
			
		||||
    clip-path: url(#gaugeBgMask);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__limit-high rect { fill: $colorGaugeLimitHigh; }
 | 
			
		||||
  &__limit-low rect { fill: $colorGaugeLimitLow; }
 | 
			
		||||
 | 
			
		||||
  &__filled-value-wrapper {
 | 
			
		||||
    clip-path: url(#gaugeValueMask);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__needle-value-wrapper {
 | 
			
		||||
    clip-path: url(#gaugeValueMask);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__filled-value { fill: $colorGaugeValue; }
 | 
			
		||||
 | 
			
		||||
  &__needle-value {
 | 
			
		||||
    fill: $colorGaugeValue;
 | 
			
		||||
    transition: transform $transitionTimeGauge;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__current-value-text {
 | 
			
		||||
    fill: $colorGaugeTextValue;
 | 
			
		||||
    font-family: $heroFont;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/********************************************** METER GAUGE */
 | 
			
		||||
@@ -131,6 +78,13 @@ $limitHighClip180: polygon(100% 0, 100% 100%, 0 100%);
 | 
			
		||||
  @include abs();
 | 
			
		||||
  display: flex;
 | 
			
		||||
 | 
			
		||||
  svg {
 | 
			
		||||
    // current-value-text
 | 
			
		||||
    position: absolute;
 | 
			
		||||
    height: 100%;
 | 
			
		||||
    width: 100%;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  &__range {
 | 
			
		||||
    display: flex;
 | 
			
		||||
    flex: 0 0 auto;
 | 
			
		||||
 
 | 
			
		||||
@@ -143,13 +143,13 @@
 | 
			
		||||
                <!-- spacecraft position fresh -->
 | 
			
		||||
                <div
 | 
			
		||||
                    v-if="relatedTelemetry.hasRelatedTelemetry && isSpacecraftPositionFresh"
 | 
			
		||||
                    class="c-imagery__age icon-check c-imagery--new"
 | 
			
		||||
                    class="c-imagery__age icon-check c-imagery--new no-animation"
 | 
			
		||||
                >POS</div>
 | 
			
		||||
 | 
			
		||||
                <!-- camera position fresh -->
 | 
			
		||||
                <div
 | 
			
		||||
                    v-if="relatedTelemetry.hasRelatedTelemetry && isCameraPositionFresh"
 | 
			
		||||
                    class="c-imagery__age icon-check c-imagery--new"
 | 
			
		||||
                    class="c-imagery__age icon-check c-imagery--new no-animation"
 | 
			
		||||
                >CAM</div>
 | 
			
		||||
            </div>
 | 
			
		||||
            <div class="h-local-controls">
 | 
			
		||||
@@ -331,6 +331,16 @@ export default {
 | 
			
		||||
        },
 | 
			
		||||
        isImageNew() {
 | 
			
		||||
            let cutoff = FIVE_MINUTES;
 | 
			
		||||
            if (this.imageFreshnessOptions) {
 | 
			
		||||
                const { fadeOutDelayTime, fadeOutDurationTime} = this.imageFreshnessOptions;
 | 
			
		||||
                // convert css duration to IS8601 format for parsing
 | 
			
		||||
                const isoFormattedDuration = 'PT' + fadeOutDurationTime.toUpperCase();
 | 
			
		||||
                const isoFormattedDelay = 'PT' + fadeOutDelayTime.toUpperCase();
 | 
			
		||||
                const parsedDuration = moment.duration(isoFormattedDuration).asMilliseconds();
 | 
			
		||||
                const parsedDelay = moment.duration(isoFormattedDelay).asMilliseconds();
 | 
			
		||||
                cutoff = parsedDuration + parsedDelay;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            let age = this.numericDuration;
 | 
			
		||||
 | 
			
		||||
            return age < cutoff && !this.refreshCSS;
 | 
			
		||||
@@ -514,6 +524,8 @@ export default {
 | 
			
		||||
                if (!this.isPaused) {
 | 
			
		||||
                    this.setFocusedImage(imageIndex);
 | 
			
		||||
                    this.scrollToRight();
 | 
			
		||||
                } else {
 | 
			
		||||
                    this.scrollToFocused();
 | 
			
		||||
                }
 | 
			
		||||
            },
 | 
			
		||||
            deep: true
 | 
			
		||||
@@ -977,6 +989,7 @@ export default {
 | 
			
		||||
 | 
			
		||||
            this.setSizedImageDimensions();
 | 
			
		||||
            this.calculateViewHeight();
 | 
			
		||||
            this.scrollToFocused();
 | 
			
		||||
        },
 | 
			
		||||
        setSizedImageDimensions() {
 | 
			
		||||
            this.focusedImageNaturalAspectRatio = this.$refs.focusedImage.naturalWidth / this.$refs.focusedImage.naturalHeight;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,3 +1,5 @@
 | 
			
		||||
@use 'sass:math';
 | 
			
		||||
 | 
			
		||||
@keyframes fade-out {
 | 
			
		||||
    from {
 | 
			
		||||
        background-color: rgba($colorOk, 0.5);
 | 
			
		||||
@@ -138,6 +140,9 @@
 | 
			
		||||
        animation-timing-function: ease-in;
 | 
			
		||||
        animation-iteration-count: 1;
 | 
			
		||||
        animation-fill-mode: forwards;
 | 
			
		||||
        &.no-animation {
 | 
			
		||||
            animation: none;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@@ -211,7 +216,7 @@
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .c-thumb {
 | 
			
		||||
        $w: $imageThumbsD / 2;
 | 
			
		||||
        $w: math.div($imageThumbsD, 2);
 | 
			
		||||
        min-width: $w;
 | 
			
		||||
        width: $w;
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -204,6 +204,8 @@ export default {
 | 
			
		||||
 | 
			
		||||
        updateTicks(forceRegeneration = false) {
 | 
			
		||||
            const range = this.axis.get('displayRange');
 | 
			
		||||
            const logMode = this.axis.get('logMode');
 | 
			
		||||
 | 
			
		||||
            if (!range) {
 | 
			
		||||
                delete this.min;
 | 
			
		||||
                delete this.max;
 | 
			
		||||
@@ -231,7 +233,7 @@ export default {
 | 
			
		||||
                    step: newTicks[1] - newTicks[0]
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                newTicks = getFormattedTicks(newTicks, format);
 | 
			
		||||
                newTicks = getFormattedTicks(newTicks, format, logMode);
 | 
			
		||||
 | 
			
		||||
                this.ticks = newTicks;
 | 
			
		||||
                this.shouldCheckWidth = true;
 | 
			
		||||
 
 | 
			
		||||
@@ -215,6 +215,10 @@ export default class YAxisModel extends Model {
 | 
			
		||||
 | 
			
		||||
            const _range = this.get('displayRange');
 | 
			
		||||
 | 
			
		||||
            if (!_range) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (this.get('logMode')) {
 | 
			
		||||
                _range.min = antisymlog(_range.min, 10);
 | 
			
		||||
                _range.max = antisymlog(_range.max, 10);
 | 
			
		||||
 
 | 
			
		||||
@@ -131,12 +131,17 @@ export function commonSuffix(a, b) {
 | 
			
		||||
    return a.slice(a.length - breakpoint);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function getFormattedTicks(newTicks, format) {
 | 
			
		||||
export function getFormattedTicks(newTicks, format, formatFloat) {
 | 
			
		||||
    newTicks = newTicks
 | 
			
		||||
        .map(function (tickValue) {
 | 
			
		||||
            let formattedValue = format(tickValue);
 | 
			
		||||
            if (formatFloat === true && typeof formattedValue === 'number' && !Number.isInteger(formattedValue)) {
 | 
			
		||||
                formattedValue = parseFloat(formattedValue).toFixed(2);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            return {
 | 
			
		||||
                value: tickValue,
 | 
			
		||||
                text: format(tickValue)
 | 
			
		||||
                text: formattedValue
 | 
			
		||||
            };
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user